diff --git a/Makefile b/Makefile index c06f9c29..ad59c028 100644 --- a/Makefile +++ b/Makefile @@ -13,12 +13,11 @@ PORT ?= /dev/ttyUSB2 # 1 external domain for the CGRA EXTERNAL_DOMAINS = 1 -# Use more memory banks -MEMORY_BANKS = 4 - -# Project options are based on the app to be build (default - hello_world) -PROJECT ?= hello_world +PROJECT ?= hello_world +#MEMORY_BANKS ?= 2 # Multiple of 2 +#MEMORY_BANKS_IL ?= 4 # Power of 2 + export HEEP_DIR = hw/vendor/esl_epfl_x_heep/ include $(HEEP_DIR)Makefile.venv @@ -37,8 +36,6 @@ heepsilon-gen: # This is needed to be done after the X-HEEP mcu-gen because the test-bench to be used is the one from heepsilon, not the one from X-HEEP. mcu-gen: heepsilon-gen $(MAKE) -f $(XHEEP_MAKE) EXTERNAL_DOMAINS=${EXTERNAL_DOMAINS} MEMORY_BANKS=${MEMORY_BANKS} $(MAKECMDGOALS) - cd hw/vendor/esl_epfl_x_heep &&\ - $(PYTHON) util/mcu_gen.py --cfg mcu_cfg.hjson --pads_cfg pad_cfg.hjson --outdir ../../../tb/ --memorybanks $(MEMORY_BANKS) --tpl-sv ../../../tb/tb_util.svh.tpl ## Builds (synthesis and implementation) the bitstream for the FPGA version using Vivado ## @param FPGA_BOARD=nexys-a7-100t,pynq-z2 diff --git a/heepsilon.core b/heepsilon.core index a510aeed..b54290ac 100644 --- a/heepsilon.core +++ b/heepsilon.core @@ -97,25 +97,26 @@ filesets: file_type: systemVerilogSource rtl-fpga: + depend: + - openhwgroup.org:systems:core-v-mini-mcu-fpga files: - - hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv - - hw/fpga/sram_wrapper.sv - - hw/fpga_cgra/cgra_sram_wrapper.sv - - hw/fpga_cgra/cgra_clock_gate.sv - - hw/fpga_cgra/xilinx_heepsilon_wrapper.sv - file_type: systemVerilogSource + - hw/fpga_cgra/scripts/generate_sram_general.tcl: { file_type: tclSource } + - hw/fpga_cgra/scripts/generate_sram_emem.tcl: { file_type: tclSource } + - hw/vendor/esl_epfl_x_heep/hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv: { file_type: systemVerilogSource } + - hw/fpga_cgra/cgra_sram_wrapper.sv: { file_type: systemVerilogSource } + - hw/fpga_cgra/cgra_clock_gate.sv: { file_type: systemVerilogSource } + - hw/fpga_cgra/xilinx_heepsilon_wrapper.sv: { file_type: systemVerilogSource } - ip-fpga: + xdc-fpga-pynq-z2: files: - - hw/fpga/scripts/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } - - hw/fpga/scripts/generate_sram.tcl: { file_type: tclSource } - - hw/fpga/prim_xilinx_clk.sv: { file_type: systemVerilogSource } # Here there are the following modules - - hw/fpga/cve2_xilinx_clock_gate.sv: { file_type: systemVerilogSource } - - hw/fpga/pad_cell_input_xilinx.sv: { file_type: systemVerilogSource } - - hw/fpga/pad_cell_output_xilinx.sv: { file_type: systemVerilogSource } - - hw/fpga/pad_cell_inout_xilinx.sv: { file_type: systemVerilogSource } - - hw/fpga/pad_cell_bypass_input_xilinx.sv: { file_type: systemVerilogSource } - - hw/fpga/pad_cell_bypass_output_xilinx.sv: { file_type: systemVerilogSource } + - hw/fpga_cgra/constraints/pynq-z2/pin_assign.xdc + - hw/fpga/constraints/pynq-z2/constraints.xdc + file_type: xdc + + xdc-fpga-zcu104: + files: + - hw/fpga_cgra/constraints/zcu104/pin_assign.xdc + file_type: xdc fpga-arm-emulation: depend: @@ -127,33 +128,71 @@ filesets: - linux_femu/constraints/pin_assign.xdc: {file_type: xdc} - linux_femu/constraints/constraints.xdc: {file_type: xdc} - xdc-fpga-pynq-z2: - files: - - hw/fpga_cgra/constraints/pin_assign.xdc - file_type: xdc - - netlist-fpga: - files: - - build/openhwgroup.org_systems_core-v-mini-mcu_0/nexys-a7-100t-vivado/core_v_mini_mcu_xiling_postsynth.v - file_type: verilogSource - parameters: COREV_PULP: datatype: int paramtype: vlogparam + description: | + Enables COREV_PULP custom RISC-V extension on the CV32E40P core. Admitted values: 1|0. + default: 0 + FPU: + datatype: int + paramtype: vlogparam + description: | + Enables RV32F RISC-V extension on the CV32E40P core. Admitted values: 1|0. default: 0 JTAG_DPI: datatype: int paramtype: vlogparam + description: | + Enables testbench JTAG DIPs. Admitted values: 1|0. default: 0 + X_EXT: + datatype: int + paramtype: vlogparam + description: | + Enables CORE-V-XIF interface for the CV32E40X and CV32E40PX cores. Admitted values: 1|0. + default: 0 + USE_EXTERNAL_DEVICE_EXAMPLE: + datatype: int + paramtype: vlogparam + description: | + Enables testbench modules compilation. Admitted values: 1|0. + default: 1 USE_UPF: datatype: bool paramtype: vlogdefine - default: false + description: | + Enables simulation with UPF with Modelsim/VCS + REMOVE_OBI_FIFO: + datatype: bool + paramtype: vlogdefine + description: | + Remove the FIFO between the BUS and the peripherals subsystems SYNTHESIS: datatype: bool paramtype: vlogdefine default: false + VERILATOR: #used by SV2V + datatype: bool + paramtype: vlogdefine + default: false + SIM_SYSTEMC: + datatype: bool + paramtype: vlogdefine + default: false + FPGA_SYNTHESIS: + datatype: bool + paramtype: vlogdefine + default: false + FPGA_NEXYS: + datatype: bool + paramtype: vlogdefine + default: false + FPGA_ZCU104: + datatype: bool + paramtype: vlogdefine + default: false # Make the parameter known to FuseSoC to enable overrides from the # command line. If not overwritten, use the generic technology library. PRIM_DEFAULT_IMPL: @@ -266,15 +305,43 @@ targets: description: TUL Pynq-Z2 Board filesets_append: - x_heep_system - - files_rtl_generic # Already added by default? - rtl-fpga - - ip-fpga - xdc-fpga-pynq-z2 - ext_bus parameters: - - COREV_PULP=0 + - COREV_PULP + - FPU + - X_EXT - SYNTHESIS=true + - REMOVE_OBI_FIFO + - FPGA_SYNTHESIS=true tools: vivado: part: xc7z020clg400-1 + board_part: tul.com.tw:pynq-z2:part0:1.0 + board_repo_paths: [../../../hw/fpga/board_files/vendor/esl_epfl_pynq_z2_board_files] + toplevel: [xilinx_heepsilon_wrapper] + + zcu104: + <<: *default_target + default_tool: vivado + description: ZCU104 Evaluation Board + filesets_append: + - x_heep_system + - rtl-fpga + - xdc-fpga-zcu104 + - ext_bus + parameters: + - COREV_PULP + - FPU + - X_EXT + - SYNTHESIS=true + - REMOVE_OBI_FIFO + - FPGA_SYNTHESIS=true + - FPGA_ZCU104=true + tools: + vivado: + part: xczu7ev-ffvc1156-2-e + board_part: xilinx.com:zcu104:part0:1.0 + board_repo_paths: [../../../hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files] toplevel: [xilinx_heepsilon_wrapper] \ No newline at end of file diff --git a/hw/fpga b/hw/fpga deleted file mode 120000 index b31c1596..00000000 --- a/hw/fpga +++ /dev/null @@ -1 +0,0 @@ -./vendor/esl_epfl_x_heep/hw/fpga \ No newline at end of file diff --git a/hw/fpga_cgra/cgra_sram_wrapper.sv b/hw/fpga_cgra/cgra_sram_wrapper.sv index 1d924b29..b9b65778 100644 --- a/hw/fpga_cgra/cgra_sram_wrapper.sv +++ b/hw/fpga_cgra/cgra_sram_wrapper.sv @@ -16,25 +16,87 @@ module cgra_sram_wrapper #( input logic [AddrWidth-1:0] addr_i, // request address input logic [ 31:0] wdata_i, // write data input logic [ 3:0] be_i, // write byte enable - input logic set_retentive_i, + input logic set_retentive_ni, // output ports output logic [ 31:0] rdata_o // read data ); - sram_wrapper#( - .NumWords (NumWords), - .DataWidth(DataWidth), - .AddrWidth(AddrWidth) - ) sram_wrapper_i( - .clk_i (clk_i), - .rst_ni (rst_ni), - .req_i (req_i), - .we_i (we_i), - .addr_i (addr_i), - .wdata_i (wdata_i), - .be_i (be_i), - .set_retentive_ni(set_retentive_i), - // output ports - .rdata_o (rdata_o) - ); + + localparam int unsigned NUM_WORDS = NumWords; + + generate + if (NUM_WORDS == 128) begin + xilinx_emem_gen xilinx_sram_i ( + .clka (clk_i), + .ena (req_i), + .wea ({4{req_i & we_i}} & be_i), + .addra(addr_i), + .dina (wdata_i), + // output ports + .douta(rdata_o) + ); + end else if (NUM_WORDS == 512) begin + xilinx_mem_gen_2k xilinx_sram_i ( + .clka (clk_i), + .ena (req_i), + .wea ({4{req_i & we_i}} & be_i), + .addra(addr_i), + .dina (wdata_i), + // output ports + .douta(rdata_o) + ); + end else if (NUM_WORDS == 1024) begin + xilinx_mem_gen_4k xilinx_sram_i ( + .clka (clk_i), + .ena (req_i), + .wea ({4{req_i & we_i}} & be_i), + .addra(addr_i), + .dina (wdata_i), + // output ports + .douta(rdata_o) + ); + end else if (NUM_WORDS == 2048) begin + xilinx_mem_gen_8k xilinx_sram_i ( + .clka (clk_i), + .ena (req_i), + .wea ({4{req_i & we_i}} & be_i), + .addra(addr_i), + .dina (wdata_i), + // output ports + .douta(rdata_o) + ); + end else if (NUM_WORDS == 4096) begin + xilinx_mem_gen_16k xilinx_sram_i ( + .clka (clk_i), + .ena (req_i), + .wea ({4{req_i & we_i}} & be_i), + .addra(addr_i), + .dina (wdata_i), + // output ports + .douta(rdata_o) + ); + end else if (NUM_WORDS == 8192) begin + xilinx_mem_gen_32k xilinx_sram_i ( + .clka (clk_i), + .ena (req_i), + .wea ({4{req_i & we_i}} & be_i), + .addra(addr_i), + .dina (wdata_i), + // output ports + .douta(rdata_o) + ); + end else if (NUM_WORDS == 16384) begin + xilinx_mem_gen_64k xilinx_sram_i ( + .clka (clk_i), + .ena (req_i), + .wea ({4{req_i & we_i}} & be_i), + .addra(addr_i), + .dina (wdata_i), + // output ports + .douta(rdata_o) + ); + end else begin + $error("Bank size not generated for NumWords = %0d.", NumWords); + end + endgenerate endmodule \ No newline at end of file diff --git a/hw/fpga_cgra/constraints/pynq-z2/constraints.xdc b/hw/fpga_cgra/constraints/pynq-z2/constraints.xdc new file mode 100644 index 00000000..38e2f6b3 --- /dev/null +++ b/hw/fpga_cgra/constraints/pynq-z2/constraints.xdc @@ -0,0 +1 @@ +create_clock -add -name sys_clk_pin -period 8.00 -waveform {0 5} [get_ports {clk_i}]; diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/constraints/pin_assign.xdc b/hw/fpga_cgra/constraints/pynq-z2/pin_assign.xdc similarity index 63% rename from hw/vendor/esl_epfl_x_heep/linux_femu/constraints/pin_assign.xdc rename to hw/fpga_cgra/constraints/pynq-z2/pin_assign.xdc index d6be7e83..deb10d68 100644 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/constraints/pin_assign.xdc +++ b/hw/fpga_cgra/constraints/pynq-z2/pin_assign.xdc @@ -2,29 +2,36 @@ # Solderpad Hardware License, Version 2.1, see LICENSE.md for details. # SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -set_property -dict {PACKAGE_PIN H16 IOSTANDARD LVCMOS33} [get_ports clk_in] +set_property -dict {PACKAGE_PIN H16 IOSTANDARD LVCMOS33} [get_ports clk_i] set_property -dict {PACKAGE_PIN L19 IOSTANDARD LVCMOS33} [get_ports rst_i] + set_property -dict {PACKAGE_PIN M14 IOSTANDARD LVCMOS33} [get_ports rst_led] set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports clk_led] set_property -dict {PACKAGE_PIN W9 IOSTANDARD LVCMOS33} [get_ports clk_out] -set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVCMOS33} [get_ports exit_valid_o] -set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports exit_value_o] -set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS33} [get_ports execute_from_flash_i] + set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS33} [get_ports boot_select_i] +set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS33} [get_ports execute_from_flash_i] ## Pmoda ## RPi GPIO 7-0 are shared with pmoda_rpi_gpio_tri_io[7:0] # QSPI +# Q0 / MOSI +# Q1 / MISO +# Q2 / nWP +# Q3 / nHLD -set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports spi_csb_io] -set_property -dict {PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports spi_sck_io] -set_property -dict {PACKAGE_PIN T12 IOSTANDARD LVCMOS33} [get_ports {spi_sd_0_io}] -set_property -dict {PACKAGE_PIN W15 IOSTANDARD LVCMOS33} [get_ports {spi_sd_1_io}] -set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports {spi_sd_2_io}] -set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports {spi_sd_3_io}] ## Pmodb +#set_property -dict {PACKAGE_PIN Y17 IOSTANDARD LVCMOS33} [get_ports {crst}] +set_property -dict {PACKAGE_PIN W16 IOSTANDARD LVCMOS33} [get_ports jtag_tck_i] +set_property -dict {PACKAGE_PIN T11 IOSTANDARD LVCMOS33} [get_ports jtag_tms_i] +set_property -dict {PACKAGE_PIN W19 IOSTANDARD LVCMOS33} [get_ports jtag_trst_ni] +set_property -dict {PACKAGE_PIN Y14 IOSTANDARD LVCMOS33} [get_ports jtag_tdi_i] +set_property -dict {PACKAGE_PIN V12 IOSTANDARD LVCMOS33} [get_ports jtag_tdo_o] + +set_property -dict {PACKAGE_PIN W14 IOSTANDARD LVCMOS33} [get_ports uart_tx_o] +set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports uart_rx_i] set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[0]}] set_property -dict {PACKAGE_PIN Y8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[1]}] @@ -46,28 +53,41 @@ set_property -dict {PACKAGE_PIN A20 IOSTANDARD LVCMOS33} [get_ports {gpio_io[16] set_property -dict {PACKAGE_PIN B19 IOSTANDARD LVCMOS33} [get_ports {gpio_io[17]}] set_property -dict {PACKAGE_PIN B20 IOSTANDARD LVCMOS33} [get_ports {gpio_io[18]}] set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports {gpio_io[19]}] -set_property -dict {PACKAGE_PIN F20 IOSTANDARD LVCMOS33} [get_ports {gpio_io[20]}] -set_property -dict {PACKAGE_PIN F19 IOSTANDARD LVCMOS33} [get_ports {gpio_io[21]}] -set_property -dict {PACKAGE_PIN P16 IOSTANDARD LVCMOS33} [get_ports {gpio_io[22]}] -set_property -dict {PACKAGE_PIN W6 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_io[0]}] -set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_io[1]}] -set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {spi2_sck_io}] +## Tri-color LD5 for TARGET_PYNQ_Z2 +set_property -dict {PACKAGE_PIN M15 IOSTANDARD LVCMOS33} [get_ports {gpio_io[20]}] +set_property -dict {PACKAGE_PIN G14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[21]}] +set_property -dict {PACKAGE_PIN L14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[22]}] + +set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVCMOS33} [get_ports exit_valid_o] +set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports exit_value_o] + +set_property -dict {PACKAGE_PIN U19 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[0]}] +set_property -dict {PACKAGE_PIN Y19 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[1]}] +set_property -dict {PACKAGE_PIN W18 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[2]}] +set_property -dict {PACKAGE_PIN Y16 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[3]}] +set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports spi_flash_csb_o] +set_property -dict {PACKAGE_PIN Y18 IOSTANDARD LVCMOS33} [get_ports spi_flash_sck_o] + +set_property -dict {PACKAGE_PIN T12 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[0]}] +set_property -dict {PACKAGE_PIN W15 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[1]}] +set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[2]}] +set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[3]}] +set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports spi_csb_o] +set_property -dict {PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports spi_sck_o] + set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_0_io}] set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_1_io}] set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_2_io}] set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_3_io}] -#set_property -dict {PACKAGE_PIN W6 IOSTANDARD LVCMOS33} [get_ports {gpio_io[24]}] -#set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {gpio_io[25]}] -#set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {gpio_io[26]}] -#set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports {gpio_io[27]}] -#set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports {gpio_io[28]}] -#set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports {gpio_io[29]}] -#set_property -dict {PACKAGE_PIN V15 IOSTANDARD LVCMOS33} [get_ports {gpio_io[30]}] -#set_property -dict {PACKAGE_PIN D19 IOSTANDARD LVCMOS33} [get_ports {gpio_io[31]}] +set_property -dict {PACKAGE_PIN W6 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_io[0]}] +set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_io[1]}] +set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {spi2_sck_o}] + +set_property -dict {PACKAGE_PIN W13 IOSTANDARD LVCMOS33} [get_ports {i2c_scl_io}] +set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports {i2c_sda_io}] +# Removing this line (but leaving the one in constraints.xdc gives an error and recommends adding exactly this to turn it into a warning) +# Having this line along with the one in constrains.xdc gives an critical warning +# Not having the line in constraints.xdc synthezises SUPER slow (>1h), or at least thats a candidate for that. set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_tck_i_IBUF] -set_property PACKAGE_PIN W13 [get_ports i2c_scl_io] -set_property PACKAGE_PIN T10 [get_ports i2c_sda_io] -set_property IOSTANDARD LVCMOS33 [get_ports i2c_scl_io] -set_property IOSTANDARD LVCMOS33 [get_ports i2c_sda_io] diff --git a/hw/fpga_cgra/constraints/zcu104/pin_assign.xdc b/hw/fpga_cgra/constraints/zcu104/pin_assign.xdc new file mode 100644 index 00000000..48044127 --- /dev/null +++ b/hw/fpga_cgra/constraints/zcu104/pin_assign.xdc @@ -0,0 +1,105 @@ +# Copyright 2022 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +# CLOCK +set_property -dict {PACKAGE_PIN AH18 IOSTANDARD DIFF_SSTL12} [get_ports clk_300mhz_p] +set_property -dict {PACKAGE_PIN AH17 IOSTANDARD DIFF_SSTL12} [get_ports clk_300mhz_n] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_tck_i] + +# RESET +set_property -dict {PACKAGE_PIN M11 IOSTANDARD LVCMOS33} [get_ports rst_i] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets rst_i] + +# LEDS +set_property -dict {PACKAGE_PIN D5 IOSTANDARD LVCMOS33} [get_ports rst_led] +set_property -dict {PACKAGE_PIN D6 IOSTANDARD LVCMOS33} [get_ports clk_led] +set_property -dict {PACKAGE_PIN B1 IOSTANDARD LVCMOS33} [get_ports clk_out] +set_property -dict {PACKAGE_PIN A5 IOSTANDARD LVCMOS33} [get_ports exit_valid_o] +set_property -dict {PACKAGE_PIN B5 IOSTANDARD LVCMOS33} [get_ports exit_value_o] + +# SWITCHES +set_property -dict {PACKAGE_PIN E4 IOSTANDARD LVCMOS33} [get_ports execute_from_flash_i] +set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33} [get_ports boot_select_i] + +# FLASH +# QSPI +# Q0 / MOSI +# Q1 / MISO +# Q2 / nWP +# Q3 / nHLD +set_property -dict {PACKAGE_PIN L10 IOSTANDARD LVCMOS33} [get_ports spi_flash_csb_o] +set_property -dict {PACKAGE_PIN J9 IOSTANDARD LVCMOS33} [get_ports spi_flash_sck_o] +set_property -dict {PACKAGE_PIN M10 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[0]}] +set_property -dict {PACKAGE_PIN K9 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[1]}] +set_property -dict {PACKAGE_PIN M8 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[2]}] +set_property -dict {PACKAGE_PIN K8 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[3]}] + +# UART +set_property -dict {PACKAGE_PIN G8 IOSTANDARD LVCMOS33} [get_ports uart_tx_o] +set_property -dict {PACKAGE_PIN G6 IOSTANDARD LVCMOS33} [get_ports uart_rx_i] + +# JTAG +set_property -dict {PACKAGE_PIN H8 IOSTANDARD LVCMOS33} [get_ports jtag_tdi_i] +set_property -dict {PACKAGE_PIN J6 IOSTANDARD LVCMOS33} [get_ports jtag_tdo_o] +set_property -dict {PACKAGE_PIN G7 IOSTANDARD LVCMOS33} [get_ports jtag_tms_i] +set_property -dict {PACKAGE_PIN H6 IOSTANDARD LVCMOS33} [get_ports jtag_tck_i] +set_property -dict {PACKAGE_PIN M9 IOSTANDARD LVCMOS33} [get_ports jtag_trst_ni] + +# I2C +set_property -dict {PACKAGE_PIN J7 IOSTANDARD LVCMOS33} [get_ports i2c_scl_io] +set_property -dict {PACKAGE_PIN H7 IOSTANDARD LVCMOS33} [get_ports i2c_sda_io] + +## The following pins are sent to the FMC connector, using the LA pins as single-ended. +## The bank only supports up to 1.8 V. + +# SPI SD +set_property -dict {PACKAGE_PIN H19 IOSTANDARD LVCMOS18} [get_ports spi_csb_o] +set_property -dict {PACKAGE_PIN G19 IOSTANDARD LVCMOS18} [get_ports spi_sck_o] +set_property -dict {PACKAGE_PIN L15 IOSTANDARD LVCMOS18} [get_ports {spi_sd_io[0]}] +set_property -dict {PACKAGE_PIN K15 IOSTANDARD LVCMOS18} [get_ports {spi_sd_io[1]}] +set_property -dict {PACKAGE_PIN C13 IOSTANDARD LVCMOS18} [get_ports {spi_sd_io[2]}] +set_property -dict {PACKAGE_PIN C12 IOSTANDARD LVCMOS18} [get_ports {spi_sd_io[3]}] + +# GPIOs +set_property -dict {PACKAGE_PIN D11 IOSTANDARD LVCMOS18} [get_ports {gpio_io[0]}] +set_property -dict {PACKAGE_PIN D10 IOSTANDARD LVCMOS18} [get_ports {gpio_io[1]}] +set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS18} [get_ports {gpio_io[2]}] +set_property -dict {PACKAGE_PIN A7 IOSTANDARD LVCMOS18} [get_ports {gpio_io[3]}] +set_property -dict {PACKAGE_PIN H18 IOSTANDARD LVCMOS18} [get_ports {gpio_io[4]}] +set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS18} [get_ports {gpio_io[5]}] +set_property -dict {PACKAGE_PIN K17 IOSTANDARD LVCMOS18} [get_ports {gpio_io[6]}] +set_property -dict {PACKAGE_PIN J17 IOSTANDARD LVCMOS18} [get_ports {gpio_io[7]}] +set_property -dict {PACKAGE_PIN H16 IOSTANDARD LVCMOS18} [get_ports {gpio_io[8]}] +set_property -dict {PACKAGE_PIN G16 IOSTANDARD LVCMOS18} [get_ports {gpio_io[9]}] +set_property -dict {PACKAGE_PIN G15 IOSTANDARD LVCMOS18} [get_ports {gpio_io[10]}] +set_property -dict {PACKAGE_PIN F15 IOSTANDARD LVCMOS18} [get_ports {gpio_io[11]}] +set_property -dict {PACKAGE_PIN F11 IOSTANDARD LVCMOS18} [get_ports {gpio_io[12]}] +set_property -dict {PACKAGE_PIN E10 IOSTANDARD LVCMOS18} [get_ports {gpio_io[13]}] +set_property -dict {PACKAGE_PIN B11 IOSTANDARD LVCMOS18} [get_ports {gpio_io[14]}] +set_property -dict {PACKAGE_PIN A11 IOSTANDARD LVCMOS18} [get_ports {gpio_io[15]}] +set_property -dict {PACKAGE_PIN B9 IOSTANDARD LVCMOS18} [get_ports {gpio_io[16]}] +set_property -dict {PACKAGE_PIN B8 IOSTANDARD LVCMOS18} [get_ports {gpio_io[17]}] + +# PDM2PCM +# set_property -dict {PACKAGE_PIN K19 IOSTANDARD LVCMOS18} [get_ports pdm2pcm_clk_io] +# set_property -dict {PACKAGE_PIN K18 IOSTANDARD LVCMOS18} [get_ports pdm2pcm_pdm_io] +set_property -dict {PACKAGE_PIN K19 IOSTANDARD LVCMOS18} [get_ports {gpio_io[19]}] +set_property -dict {PACKAGE_PIN K18 IOSTANDARD LVCMOS18} [get_ports {gpio_io[18]}] + +# I2S +# set_property -dict {PACKAGE_PIN E18 IOSTANDARD LVCMOS18} [get_ports i2s_sck_io] +# set_property -dict {PACKAGE_PIN E17 IOSTANDARD LVCMOS18} [get_ports i2s_ws_io] +# set_property -dict {PACKAGE_PIN G18 IOSTANDARD LVCMOS18} [get_ports i2s_sd_io] +set_property -dict {PACKAGE_PIN E18 IOSTANDARD LVCMOS18} [get_ports {gpio_io[20]}] +set_property -dict {PACKAGE_PIN E17 IOSTANDARD LVCMOS18} [get_ports {gpio_io[21]}] +set_property -dict {PACKAGE_PIN G18 IOSTANDARD LVCMOS18} [get_ports {gpio_io[22]}] + +# SPI2 +set_property -dict {PACKAGE_PIN F18 IOSTANDARD LVCMOS18} [get_ports {spi2_csb_io[0]}] +set_property -dict {PACKAGE_PIN D17 IOSTANDARD LVCMOS18} [get_ports {spi2_csb_io[1]}] +set_property -dict {PACKAGE_PIN C17 IOSTANDARD LVCMOS18} [get_ports spi2_sck_o] +set_property -dict {PACKAGE_PIN F12 IOSTANDARD LVCMOS18} [get_ports spi2_sd_0_io] +set_property -dict {PACKAGE_PIN E12 IOSTANDARD LVCMOS18} [get_ports spi2_sd_1_io] +set_property -dict {PACKAGE_PIN H13 IOSTANDARD LVCMOS18} [get_ports spi2_sd_2_io] +set_property -dict {PACKAGE_PIN H12 IOSTANDARD LVCMOS18} [get_ports spi2_sd_3_io] \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/generate_sram.tcl b/hw/fpga_cgra/scripts/generate_sram_emem.tcl similarity index 88% rename from hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/generate_sram.tcl rename to hw/fpga_cgra/scripts/generate_sram_emem.tcl index 7ba6d975..2907ec83 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/generate_sram.tcl +++ b/hw/fpga_cgra/scripts/generate_sram_emem.tcl @@ -1,5 +1,5 @@ -set ipName xilinx_mem_gen_0 +set ipName xilinx_emem_gen create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 -module_name $ipName @@ -7,9 +7,8 @@ set_property -dict [list CONFIG.Enable_32bit_Address {false} \ CONFIG.Use_Byte_Write_Enable {true} \ CONFIG.Byte_Size {8} \ CONFIG.Algorithm {Minimum_Area} \ - CONFIG.Primitive {2kx9} \ CONFIG.Write_Width_A {32} \ - CONFIG.Write_Depth_A {8192} \ + CONFIG.Write_Depth_A {128} \ CONFIG.Read_Width_A {32} \ CONFIG.Enable_A {Use_ENA_Pin} \ CONFIG.Write_Width_B {32} \ diff --git a/hw/fpga_cgra/scripts/generate_sram_general.tcl b/hw/fpga_cgra/scripts/generate_sram_general.tcl new file mode 100644 index 00000000..d134f9ed --- /dev/null +++ b/hw/fpga_cgra/scripts/generate_sram_general.tcl @@ -0,0 +1,150 @@ +set ipName xilinx_mem_gen_2k + +create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 -module_name xilinx_mem_gen_2k + +set_property -dict [list CONFIG.Enable_32bit_Address {false} \ + CONFIG.Use_Byte_Write_Enable {true} \ + CONFIG.Byte_Size {8} \ + CONFIG.Write_Width_A {32} \ + CONFIG.Write_Depth_A {512} \ + CONFIG.Read_Width_A {32} \ + CONFIG.Enable_A {Use_ENA_Pin} \ + CONFIG.Write_Width_B {32} \ + CONFIG.Read_Width_B {32} \ + CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ + CONFIG.Use_RSTA_Pin {false} \ + CONFIG.EN_SAFETY_CKT {false}] [get_ips xilinx_mem_gen_2k] + +#generate_target {instantiation_template} [get_ips $ipName] + +#export_ip_user_files -of_objects [get_ips $ipName] -no_script -sync -force -quiet + +create_ip_run [get_ips xilinx_mem_gen_2k] +launch_run -jobs 8 xilinx_mem_gen_2k_synth_1 + +set ipName xilinx_mem_gen_4k + +create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 -module_name xilinx_mem_gen_4k + +set_property -dict [list CONFIG.Enable_32bit_Address {false} \ + CONFIG.Use_Byte_Write_Enable {true} \ + CONFIG.Byte_Size {8} \ + CONFIG.Write_Width_A {32} \ + CONFIG.Write_Depth_A {1024} \ + CONFIG.Read_Width_A {32} \ + CONFIG.Enable_A {Use_ENA_Pin} \ + CONFIG.Write_Width_B {32} \ + CONFIG.Read_Width_B {32} \ + CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ + CONFIG.Use_RSTA_Pin {false} \ + CONFIG.EN_SAFETY_CKT {false}] [get_ips xilinx_mem_gen_4k] + +#generate_target {instantiation_template} [get_ips $ipName] + +#export_ip_user_files -of_objects [get_ips $ipName] -no_script -sync -force -quiet + +create_ip_run [get_ips xilinx_mem_gen_4k] +launch_run -jobs 8 xilinx_mem_gen_4k_synth_1 + +set ipName xilinx_mem_gen_8k + +create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 -module_name xilinx_mem_gen_8k + +set_property -dict [list CONFIG.Enable_32bit_Address {false} \ + CONFIG.Use_Byte_Write_Enable {true} \ + CONFIG.Byte_Size {8} \ + CONFIG.Write_Width_A {32} \ + CONFIG.Write_Depth_A {2048} \ + CONFIG.Read_Width_A {32} \ + CONFIG.Enable_A {Use_ENA_Pin} \ + CONFIG.Write_Width_B {32} \ + CONFIG.Read_Width_B {32} \ + CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ + CONFIG.Use_RSTA_Pin {false} \ + CONFIG.EN_SAFETY_CKT {false}] [get_ips xilinx_mem_gen_8k] + +#generate_target {instantiation_template} [get_ips $ipName] + +#export_ip_user_files -of_objects [get_ips $ipName] -no_script -sync -force -quiet + +create_ip_run [get_ips xilinx_mem_gen_8k] +launch_run -jobs 8 xilinx_mem_gen_8k_synth_1 + +set ipName xilinx_mem_gen_16k + +create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 -module_name xilinx_mem_gen_16k + +set_property -dict [list CONFIG.Enable_32bit_Address {false} \ + CONFIG.Use_Byte_Write_Enable {true} \ + CONFIG.Byte_Size {8} \ + CONFIG.Write_Width_A {32} \ + CONFIG.Write_Depth_A {4096} \ + CONFIG.Read_Width_A {32} \ + CONFIG.Enable_A {Use_ENA_Pin} \ + CONFIG.Write_Width_B {32} \ + CONFIG.Read_Width_B {32} \ + CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ + CONFIG.Use_RSTA_Pin {false} \ + CONFIG.EN_SAFETY_CKT {false}] [get_ips xilinx_mem_gen_16k] + +#generate_target {instantiation_template} [get_ips $ipName] + +#export_ip_user_files -of_objects [get_ips $ipName] -no_script -sync -force -quiet + +create_ip_run [get_ips xilinx_mem_gen_16k] +launch_run -jobs 8 xilinx_mem_gen_16k_synth_1 + +set ipName xilinx_mem_gen_32k + +create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 -module_name xilinx_mem_gen_32k + +set_property -dict [list CONFIG.Enable_32bit_Address {false} \ + CONFIG.Use_Byte_Write_Enable {true} \ + CONFIG.Byte_Size {8} \ + CONFIG.Write_Width_A {32} \ + CONFIG.Write_Depth_A {8192} \ + CONFIG.Read_Width_A {32} \ + CONFIG.Enable_A {Use_ENA_Pin} \ + CONFIG.Write_Width_B {32} \ + CONFIG.Read_Width_B {32} \ + CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ + CONFIG.Use_RSTA_Pin {false} \ + CONFIG.EN_SAFETY_CKT {false}] [get_ips xilinx_mem_gen_32k] + +#generate_target {instantiation_template} [get_ips $ipName] + +#export_ip_user_files -of_objects [get_ips $ipName] -no_script -sync -force -quiet + +create_ip_run [get_ips xilinx_mem_gen_32k] +launch_run -jobs 8 xilinx_mem_gen_32k_synth_1 + +set ipName xilinx_mem_gen_64k + +create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 -module_name xilinx_mem_gen_64k + +set_property -dict [list CONFIG.Enable_32bit_Address {false} \ + CONFIG.Use_Byte_Write_Enable {true} \ + CONFIG.Byte_Size {8} \ + CONFIG.Write_Width_A {32} \ + CONFIG.Write_Depth_A {16384} \ + CONFIG.Read_Width_A {32} \ + CONFIG.Enable_A {Use_ENA_Pin} \ + CONFIG.Write_Width_B {32} \ + CONFIG.Read_Width_B {32} \ + CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ + CONFIG.Use_RSTA_Pin {false} \ + CONFIG.EN_SAFETY_CKT {false}] [get_ips xilinx_mem_gen_64k] + +#generate_target {instantiation_template} [get_ips $ipName] + +#export_ip_user_files -of_objects [get_ips $ipName] -no_script -sync -force -quiet + +create_ip_run [get_ips xilinx_mem_gen_64k] +launch_run -jobs 8 xilinx_mem_gen_64k_synth_1 + +wait_on_run xilinx_mem_gen_2k_synth_1 +wait_on_run xilinx_mem_gen_4k_synth_1 +wait_on_run xilinx_mem_gen_8k_synth_1 +wait_on_run xilinx_mem_gen_16k_synth_1 +wait_on_run xilinx_mem_gen_32k_synth_1 +wait_on_run xilinx_mem_gen_64k_synth_1 diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/xilinx_generate_clk_wizard.tcl b/hw/fpga_cgra/scripts/pynq-z2/xilinx_generate_clk_wizard.tcl similarity index 86% rename from hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/xilinx_generate_clk_wizard.tcl rename to hw/fpga_cgra/scripts/pynq-z2/xilinx_generate_clk_wizard.tcl index 1c2a41a0..e61c5832 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/xilinx_generate_clk_wizard.tcl +++ b/hw/fpga_cgra/scripts/pynq-z2/xilinx_generate_clk_wizard.tcl @@ -7,9 +7,6 @@ set design_name xilinx_clk_wizard set in_clk_freq_MHz 125 set out_clk_freq_MHz 15 -# Select board -set_property -name "board_part_repo_paths" -value "[file normalize "../../../hw/fpga/board_files/"]" -objects [current_project] -set_property -name "board_part" -value "tul.com.tw:pynq-z2:part0:1.0" -objects [current_project] # Create block design create_bd_design $design_name diff --git a/hw/fpga_cgra/scripts/zcu104/xilinx_generate_clk_wizard.tcl b/hw/fpga_cgra/scripts/zcu104/xilinx_generate_clk_wizard.tcl new file mode 100644 index 00000000..d67e4054 --- /dev/null +++ b/hw/fpga_cgra/scripts/zcu104/xilinx_generate_clk_wizard.tcl @@ -0,0 +1,40 @@ +# Copyright 2022 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# Define design macros + +set design_name xilinx_clk_wizard + +# Create block design +create_bd_design $design_name + +# Create instance and set properties +create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 +set_property -dict [list \ + CONFIG.CLKIN1_JITTER_PS {33.330000000000005} \ + CONFIG.CLKOUT1_JITTER {282.792} \ + CONFIG.CLKOUT1_PHASE_ERROR {207.545} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {15} \ + CONFIG.CLK_IN1_BOARD_INTERFACE {clk_300mhz} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {32.875} \ + CONFIG.MMCM_CLKIN1_PERIOD {3.333} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {65.750} \ + CONFIG.MMCM_DIVCLK_DIVIDE {10} \ + CONFIG.OPTIMIZE_CLOCKING_STRUCTURE_EN {true} \ + CONFIG.PRIM_SOURCE {Differential_clock_capable_pin} \ + CONFIG.USE_LOCKED {false} \ + CONFIG.USE_RESET {true} \ +] [get_bd_cells clk_wiz_0] + +# Create ports +make_bd_pins_external [get_bd_cells clk_wiz_0] +make_bd_intf_pins_external [get_bd_cells clk_wiz_0] + +# Save and close block design +save_bd_design +close_bd_design $design_name + +# Create wrapper +set wrapper_path [ make_wrapper -fileset sources_1 -files [ get_files -norecurse xilinx_clk_wizard.bd ] -top ] +add_files -norecurse -fileset sources_1 $wrapper_path diff --git a/hw/fpga_cgra/xilinx_heepsilon_wrapper.sv b/hw/fpga_cgra/xilinx_heepsilon_wrapper.sv index 18002a2c..08f90b88 100644 --- a/hw/fpga_cgra/xilinx_heepsilon_wrapper.sv +++ b/hw/fpga_cgra/xilinx_heepsilon_wrapper.sv @@ -11,8 +11,13 @@ module xilinx_heepsilon_wrapper parameter ZFINX = 0, parameter CLK_LED_COUNT_LENGTH = 27 ) ( - inout logic clk_i, - inout logic rst_i, +`ifdef FPGA_ZCU104 + inout logic clk_300mhz_n, + inout logic clk_300mhz_p, +`else + inout logic clk_i, +`endif + inout logic rst_i, //visibility signals output logic rst_led, @@ -84,10 +89,18 @@ module xilinx_heepsilon_wrapper // clock output for debugging assign clk_out = clk_gen; +`ifdef FPGA_ZCU104 + xilinx_clk_wizard_wrapper xilinx_clk_wizard_wrapper_i ( + .CLK_IN1_D_0_clk_n(clk_300mhz_n), + .CLK_IN1_D_0_clk_p(clk_300mhz_p), + .clk_out1_0(clk_gen) + ); +`else // FPGA PYNQ-Z2 xilinx_clk_wizard_wrapper xilinx_clk_wizard_wrapper_i ( .clk_125MHz(clk_i), .clk_out1_0(clk_gen) ); +`endif heepsilon_top #( .COREV_PULP (0), diff --git a/hw/rtl/heepsilon_top.sv b/hw/rtl/heepsilon_top.sv index 6ed60463..70366e66 100644 --- a/hw/rtl/heepsilon_top.sv +++ b/hw/rtl/heepsilon_top.sv @@ -126,12 +126,12 @@ module heepsilon_top #( .heep_core_data_resp_o (heep_core_data_resp), .heep_debug_master_req_i (heep_debug_master_req), .heep_debug_master_resp_o (heep_debug_master_resp), - .heep_dma_read_ch0_req_i (heep_dma_read_ch0_req), - .heep_dma_read_ch0_resp_o (heep_dma_read_ch0_resp), - .heep_dma_write_ch0_req_i (heep_dma_write_ch0_req), - .heep_dma_write_ch0_resp_o(heep_dma_write_ch0_resp), - .heep_dma_addr_ch0_req_i (heep_dma_addr_ch0_req), - .heep_dma_addr_ch0_resp_o (heep_dma_addr_ch0_resp), + .heep_dma_read_req_i (heep_dma_read_ch0_req), + .heep_dma_read_resp_o (heep_dma_read_ch0_resp), + .heep_dma_write_req_i (heep_dma_write_ch0_req), + .heep_dma_write_resp_o(heep_dma_write_ch0_resp), + .heep_dma_addr_req_i (heep_dma_addr_ch0_req), + .heep_dma_addr_resp_o (heep_dma_addr_ch0_resp), .ext_master_req_i (ext_master_req), .ext_master_resp_o(ext_master_resp), @@ -245,12 +245,12 @@ module heepsilon_top #( .ext_core_data_resp_i(heep_core_data_resp), .ext_debug_master_req_o(heep_debug_master_req), .ext_debug_master_resp_i(heep_debug_master_resp), - .ext_dma_read_ch0_req_o(heep_dma_read_ch0_req), - .ext_dma_read_ch0_resp_i(heep_dma_read_ch0_resp), - .ext_dma_write_ch0_req_o(heep_dma_write_ch0_req), - .ext_dma_write_ch0_resp_i(heep_dma_write_ch0_resp), - .ext_dma_addr_ch0_req_o(heep_dma_addr_ch0_req), - .ext_dma_addr_ch0_resp_i(heep_dma_addr_ch0_resp), + .ext_dma_read_req_o(heep_dma_read_ch0_req), + .ext_dma_read_resp_i(heep_dma_read_ch0_resp), + .ext_dma_write_req_o(heep_dma_write_ch0_req), + .ext_dma_write_resp_i(heep_dma_write_ch0_resp), + .ext_dma_addr_req_o(heep_dma_addr_ch0_req), + .ext_dma_addr_resp_i(heep_dma_addr_ch0_resp), .external_subsystem_clkgate_en_no(external_subsystem_clkgate_en_n), .ext_peripheral_slave_req_o(ext_periph_slave_req), .ext_peripheral_slave_resp_i(ext_periph_slave_resp), diff --git a/hw/vendor/esl_epfl_cgra/hw/rtl/conf_reg_file.sv b/hw/vendor/esl_epfl_cgra/hw/rtl/conf_reg_file.sv index c84da438..8676325d 100644 --- a/hw/vendor/esl_epfl_cgra/hw/rtl/conf_reg_file.sv +++ b/hw/vendor/esl_epfl_cgra/hw/rtl/conf_reg_file.sv @@ -16,16 +16,6 @@ module conf_reg_file ); logic [RCS_NUM_CREG-1:0][INSTR_WIDTH-1:0] conf_mem; - logic clk_cg, clk_en; - - assign clk_en = we_i && ce_i; - - cgra_clock_gate u_clk_gate ( - .clk_i ( clk_i ), - .test_en_i ( 1'b0 ), - .en_i ( clk_en ), - .clk_o ( clk_cg ) - ); // Read instruction output register always_ff @(posedge clk_i) @@ -38,9 +28,11 @@ module conf_reg_file end // Write instruction to register file - always_ff @(posedge clk_cg) + always_ff @(posedge clk_i) begin - conf_mem[global_pc_i] <= instr_i; + if (we_i & ce_i) begin + conf_mem[global_pc_i] <= instr_i; + end end endmodule diff --git a/hw/vendor/esl_epfl_cgra/hw/rtl/reg_file.sv b/hw/vendor/esl_epfl_cgra/hw/rtl/reg_file.sv index b9c03c0e..b2844bbe 100644 --- a/hw/vendor/esl_epfl_cgra/hw/rtl/reg_file.sv +++ b/hw/vendor/esl_epfl_cgra/hw/rtl/reg_file.sv @@ -20,25 +20,15 @@ module reg_file ); logic [REGFILE_WIDTH-1:0] reg_file_mem [0:REGFILE_DEPTH-1]; - logic clk_cg; - logic clk_en; assign regs_o = reg_file_mem; - assign clk_en = (we_i & ce_i) | rst_i; - - cgra_clock_gate u_clk_gate ( - .clk_i ( clk_i ), - .test_en_i ( 1'b0 ), - .en_i ( clk_en ), - .clk_o ( clk_cg ) - ); - - always_ff @(posedge clk_cg) + always_ff @(posedge clk_i) begin if (rst_i == 1'b1) begin reg_file_mem <= '{default:'0}; - end else begin + end + else if (we_i & ce_i) begin reg_file_mem[wsel_i] <= reg_i; end end diff --git a/hw/vendor/esl_epfl_cgra/util/INSTRUCTIONS_FFT_SPLITOPS.py b/hw/vendor/esl_epfl_cgra/util/INSTRUCTIONS_FFT_SPLITOPS.py new file mode 100644 index 00000000..75586fca --- /dev/null +++ b/hw/vendor/esl_epfl_cgra/util/INSTRUCTIONS_FFT_SPLITOPS.py @@ -0,0 +1,186 @@ +# FFT OUTPUT SPLIT OPS instructions DEPREDECATED + +instructions.append(["NEXT RC"]) + +# RC1_0 +# PROLOGUE +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["DATA", "OUT_D", "LWD", "RF1", "ON", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["DATA", "OUT_D", "LWD", "RF2", "ON", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) + +# ITERATION LOOP +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["DATA", "RF1", "LWI", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RCR", "OUT_D", "FXP_MUL", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["DATA", "RF2", "LWI", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RCR", "OUT_D", "FXP_MUL", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RF1", "CONST", "SADD", "RF1", "ON", "OUT_F", "4"]) +instructions.append(["RF2", "CONST", "SADD", "RF2", "ON", "OUT_F", "4"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) + + +# RC1_1 +# PROLOGUE +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["DATA", "OUT_D", "LWD", "RF1", "ON", "OUT_F", "0"]) +instructions.append(["DATA", "OUT_D", "LWD", "RF2", "ON", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) + +# ITERATION LOOP +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["DATA", "RF1", "LWI", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RF1", "CONST", "SADD", "RF1", "ON", "OUT_F", "4"]) +instructions.append(["DATA", "RF2", "LWI", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RF2", "CONST", "SSUB", "RF2", "ON", "OUT_F", "4"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) + +################################################################################################# +################################################################################################# +################################################################################################# + +instructions.append(["NEXT RC"]) + +# RC2_0 +# PROLOGUE +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) + +# ITERATION LOOP +instructions.append(["DATA", "OUT_D", "IN1", "RF3", "ON", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RF3", "RCT", "FXP_MUL", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RCB", "OUT_D", "IN1", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RCT", "OUT_D", "FXP_MUL", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "EXIT", "RF1", "OFF", "OUT_F", "0"]) + + +# RC2_1 +# PROLOGUE +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) + +# ITERATION LOOP +instructions.append(["DATA", "OUT_D", "IN1", "RF3", "ON", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RF3", "RCT", "FXP_MUL", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RCL", "OUT_D", "FXP_ADD", "RF2", "ON", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RCL", "RCB", "FXP_SUB", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RF2", "OUT_D", "FXP_ADD", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) + +################################################################################################# +################################################################################################# +################################################################################################# + +instructions.append(["NEXT RC"]) + +# RC3_0 +# PROLOGUE +instructions.append(["DATA", "OUT_D", "LWD", "RF1", "ON", "OUT_F", "0"]) +instructions.append(["RF1", "CONST", "SSUB", "RF1", "ON", "OUT_F", "4"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["DATA", "OUT_D", "LWD", "RF2", "ON", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) + +# ITERATION LOOP +instructions.append(["RF1", "CONST", "SADD", "RF1", "ON", "OUT_F", "4"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["DATA", "RF2", "LWI", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RCR", "OUT_D", "FXP_MUL", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RF2", "CONST", "SSUB", "RF2", "ON", "OUT_F", "4"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RCB", "RF1", "SWI", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) + + +# RC3_1 +# PROLOGUE +instructions.append(["DATA", "OUT_D", "LWD", "RF1", "ON", "OUT_F", "0"]) +instructions.append(["RF1", "CONST", "SSUB", "RF1", "ON", "OUT_F", "4"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) + +# ITERATION LOOP +instructions.append(["RF1", "CONST", "SADD", "RF1", "ON", "OUT_F", "4"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["DATA", "OUT_D", "IN1", "RF3", "ON", "OUT_F", "0"]) +instructions.append(["DATA", "OUT_D", "IN1", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RF3", "OUT_D", "FXP_MUL", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RCT", "RF1", "SWI", "RF1", "OFF", "OUT_F", "0"]) + +################################################################################################# +################################################################################################# +################################################################################################# + +instructions.append(["NEXT RC"]) + +# RC4_0 +# PROLOGUE +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["DATA", "OUT_D", "LWD", "RF1", "ON", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) + +# ITERATION LOOP +instructions.append(["DATA", "RF1", "LWI", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RCR", "OUT_D", "FXP_MUL", "RF2", "ON", "OUT_F", "0"]) +instructions.append(["RF1", "CONST", "SADD", "RF1", "ON", "OUT_F", "4"]) +instructions.append(["RF2", "RCB", "FXP_SUB", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RCT", "OUT_D", "FXP_ADD", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RCB", "OUT_D", "FXP_ADD", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) + + +# RC4_1 +# PROLOGUE +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["DATA", "OUT_D", "LWD", "RF1", "ON", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["DATA", "OUT_D", "LWD", "RF2", "ON", "OUT_F", "0"]) +instructions.append(["DATA", "OUT_D", "LWD", "RF3", "ON", "OUT_F", "0"]) + +# ITERATION LOOP +instructions.append(["DATA", "RF1", "LWI", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RF1", "CONST", "SADD", "RF1", "ON", "OUT_F", "4"]) +instructions.append(["DATA", "RF2", "LWI", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RF2", "CONST", "SADD", "RF2", "ON", "OUT_F", "4"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RF4", "CONST", "SADD", "RF4", "ON", "OUT_F", "1"]) +instructions.append(["ZEROS", "OUT_D", "NOP", "RF1", "OFF", "OUT_F", "0"]) +instructions.append(["RF4", "RF3", "BLT", "RF1", "OFF", "OUT_F", "6"]) + + +################################################################################################# +################################################################################################# +################################################################################################# + +kernel_col_needed = "0011" +row_st_add = 58 +n_instructions = 14 diff --git a/hw/vendor/esl_epfl_cgra/util/instructions_max_peak.py b/hw/vendor/esl_epfl_cgra/util/instructions_max_peak.py new file mode 100644 index 00000000..5c236c82 --- /dev/null +++ b/hw/vendor/esl_epfl_cgra/util/instructions_max_peak.py @@ -0,0 +1,87 @@ +# +# MAX_PEAK search instructions DEPREDECATED +# + +ker_col_needed = 1 +ker_num_instr = 11 + +ker_conf_words[ker_next_id] = get_bin(int(pow(2,ker_col_needed))-1,CGRA_N_COL) +\ + get_bin(ker_start_add, CGRA_IMEM_NL_LOG2) +\ + get_bin(ker_num_instr-1, RCS_NUM_CREG_LOG2) + +# Save current start address +start_add = ker_start_add +# Update start address and ID for next kernel +ker_start_add = ker_start_add + ker_num_instr*ker_col_needed +ker_next_id = ker_next_id+1 + +# Used for multi-column kernels +k = ker_num_instr + +################################################################################################# +############################################## RC0 ############################################## +################################################################################################# + +# COLUMN-0 +rcs_instructions[0][start_add+ 0] = rcs_nop_instr +rcs_instructions[0][start_add+ 1] = rcs_nop_instr +rcs_instructions[0][start_add+ 2] = ["SRAM", "-", "LWD", "R1", "-", "-"] +rcs_instructions[0][start_add+ 3] = ["SRAM", "-", "LWD", "R0", "-", "-"] +rcs_instructions[0][start_add+ 4] = rcs_nop_instr +rcs_instructions[0][start_add+ 5] = [ "R2", "R1", "SSUB", "-", "-", "-"] +rcs_instructions[0][start_add+ 6] = [ "R1", "R2", "BSFA", "-", "PREV", "-"] +rcs_instructions[0][start_add+ 7] = [ "R2", "PREV", "BSFA", "R2", "RCB", "-"] +rcs_instructions[0][start_add+ 8] = [ "R0", "-", "INA", "R1", "-", "-"] +rcs_instructions[0][start_add+ 9] = rcs_nop_instr +rcs_instructions[0][start_add+10] = [ "R2", "-", "SWD", "-", "-", "-"] + +################################################################################################# +############################################## RC1 ############################################## +################################################################################################# + +# COLUMN-0 +rcs_instructions[1][start_add+ 0] = rcs_nop_instr +rcs_instructions[1][start_add+ 1] = ["SRAM", "-", "LWD", "R0", "-", "-"] +rcs_instructions[1][start_add+ 2] = [ "-", "IMM", "INB", "R1", "-", "-1"] +rcs_instructions[1][start_add+ 3] = [ "RCT", "-", "INA", "R3", "-", "-"] +rcs_instructions[1][start_add+ 4] = [ "R3", "R0", "SSUB", "-", "-", "-"] +rcs_instructions[1][start_add+ 5] = [ "R1", "R2", "BSFA", "-", "PREV", "-"] +rcs_instructions[1][start_add+ 6] = [ "RCB", "PREV", "SADD", "-", "-", "-"] +rcs_instructions[1][start_add+ 7] = rcs_nop_instr +rcs_instructions[1][start_add+ 8] = [ "R3", "-", "INA", "R0", "-", "-"] +rcs_instructions[1][start_add+ 9] = rcs_nop_instr +rcs_instructions[1][start_add+10] = rcs_nop_instr + +################################################################################################# +############################################## RC2 ############################################## +################################################################################################# + +# COLUMN-0 +rcs_instructions[2][start_add+ 0] = rcs_nop_instr +rcs_instructions[2][start_add+ 1] = rcs_nop_instr +rcs_instructions[2][start_add+ 2] = [ "-", "IMM", "INB", "R1", "-", "-1"] +rcs_instructions[2][start_add+ 3] = ["SRAM", "-", "INA", "-", "-", "-"] +rcs_instructions[2][start_add+ 4] = [ "RCB", "PREV", "SSUB", "-", "-", "-"] +rcs_instructions[2][start_add+ 5] = [ "R1", "R2", "BSFA", "-", "PREV", "-"] +rcs_instructions[2][start_add+ 6] = [ "RCT", "PREV", "SADD", "-", "-", "-"] +rcs_instructions[2][start_add+ 7] = rcs_nop_instr +rcs_instructions[2][start_add+ 8] = rcs_nop_instr +rcs_instructions[2][start_add+ 9] = rcs_nop_instr +rcs_instructions[2][start_add+10] = [ "-", "-", "EXIT", "-", "-", "-"] + +################################################################################################# +############################################## RC3 ############################################## +################################################################################################# + +# COLUMN-0 +rcs_instructions[3][start_add+ 0] = ["SRAM", "-", "LWD", "R3", "-", "-"] +rcs_instructions[3][start_add+ 1] = rcs_nop_instr +rcs_instructions[3][start_add+ 2] = ["SRAM", "-", "INA", "R1", "-", "-"] +rcs_instructions[3][start_add+ 3] = [ "R1", "-", "INA", "-", "-", "-"] +rcs_instructions[3][start_add+ 4] = [ "RCB", "-", "INA", "R1", "-", "-"] +rcs_instructions[3][start_add+ 5] = [ "R0", "IMM", "SADD", "R0", "-", "1"] +rcs_instructions[3][start_add+ 6] = [ "R0", "R2", "BSFA", "-", "RCB", "-"] +rcs_instructions[3][start_add+ 7] = [ "R2", "PREV", "BSFA", "R2", "RCT", "-"] +rcs_instructions[3][start_add+ 8] = [ "R0", "R3", "BLT", "-", "-", "3"] +rcs_instructions[3][start_add+ 9] = [ "R2", "-", "SWD", "-", "-", "-"] +rcs_instructions[3][start_add+10] = rcs_nop_instr diff --git a/hw/vendor/esl_epfl_cgra/util/instructions_min_max_circular.py b/hw/vendor/esl_epfl_cgra/util/instructions_min_max_circular.py new file mode 100644 index 00000000..2669aa8d --- /dev/null +++ b/hw/vendor/esl_epfl_cgra/util/instructions_min_max_circular.py @@ -0,0 +1,83 @@ +# +# MIN_MAX_CIRCULAR search instructions (manual mapping) DEPREDECATED +# + +ker_col_needed = 1 +ker_num_instr = 10 + +ker_conf_words[ker_next_id] = get_bin(int(pow(2,ker_col_needed))-1,CGRA_N_COL) +\ + get_bin(ker_start_add, CGRA_IMEM_NL_LOG2) +\ + get_bin(ker_num_instr-1, RCS_NUM_CREG_LOG2) + +# Save current start address +start_add = ker_start_add +# Update start address and ID for next kernel +ker_start_add = ker_start_add + ker_num_instr*ker_col_needed +ker_next_id = ker_next_id+1 + +# Used for multi-column kernels +k = ker_num_instr + +################################################################################################# +############################################## RC0 ############################################## +################################################################################################# + +# COLUMN-0 +rcs_instructions[0][start_add+ 0] = rcs_nop_instr +rcs_instructions[0][start_add+ 1] = [ "RCB", "IMM", "SLT", "R3", "-", "2"] +rcs_instructions[0][start_add+ 2] = [ "RCB", "IMM", "SLT", "R1", "-", "2"] +rcs_instructions[0][start_add+ 3] = ["SRAM", "-", "LWD", "R0", "-", "-"] +rcs_instructions[0][start_add+ 4] = [ "R0", "R1", "SADD", "-", "-", "-"] +rcs_instructions[0][start_add+ 5] = [ "R1", "IMM", "SADD", "-", "-", "4"] +rcs_instructions[0][start_add+ 6] = [ "R3", "PREV", "LAND", "R1", "-", "-"] +rcs_instructions[0][start_add+ 7] = [ "R0", "R1", "SADD", "-", "-", "-"] +rcs_instructions[0][start_add+ 8] = rcs_nop_instr +rcs_instructions[0][start_add+ 9] = rcs_nop_instr + +################################################################################################# +############################################## RC1 ############################################## +################################################################################################# + +# COLUMN-0 +rcs_instructions[1][start_add+ 0] = ["SRAM", "-", "LWD", "-", "-", "-"] +rcs_instructions[1][start_add+ 1] = ["SRAM", "-", "LWD", "-", "-", "-"] +rcs_instructions[1][start_add+ 2] = ["SRAM", "-", "LWD", "R3", "-", "-"] +rcs_instructions[1][start_add+ 3] = rcs_nop_instr +rcs_instructions[1][start_add+ 4] = rcs_nop_instr +rcs_instructions[1][start_add+ 5] = ["SRAM", "RCT", "LWI", "-", "-", "-"] +rcs_instructions[1][start_add+ 6] = [ "R0", "IMM", "SADD", "R0", "-", "1"] +rcs_instructions[1][start_add+ 7] = [ "R0", "R3", "BLT", "-", "-", "5"] +rcs_instructions[1][start_add+ 8] = rcs_nop_instr +rcs_instructions[1][start_add+ 9] = rcs_nop_instr + +################################################################################################# +############################################## RC2 ############################################## +################################################################################################# + +# COLUMN-0 +rcs_instructions[2][start_add+ 0] = rcs_nop_instr +rcs_instructions[2][start_add+ 1] = rcs_nop_instr +rcs_instructions[2][start_add+ 2] = rcs_nop_instr +rcs_instructions[2][start_add+ 3] = rcs_nop_instr +rcs_instructions[2][start_add+ 4] = rcs_nop_instr +rcs_instructions[2][start_add+ 5] = ["SRAM", "-", "INA", "R1", "-", "-"] +rcs_instructions[2][start_add+ 6] = [ "R0", "R1", "SSUB", "-", "-", "-"] +rcs_instructions[2][start_add+ 7] = [ "R1", "R0", "BSFA", "R0", "PREV", "-"] +rcs_instructions[2][start_add+ 8] = [ "R0", "-", "SWD", "-", "-", "-"] +rcs_instructions[2][start_add+ 9] = [ "-", "-", "EXIT", "-", "-", "-"] + +################################################################################################# +############################################## RC03############################################## +################################################################################################# + +# COLUMN-0 +rcs_instructions[3][start_add+ 0] = rcs_nop_instr +rcs_instructions[3][start_add+ 1] = rcs_nop_instr +rcs_instructions[3][start_add+ 2] = rcs_nop_instr +rcs_instructions[3][start_add+ 3] = rcs_nop_instr +rcs_instructions[3][start_add+ 4] = rcs_nop_instr +rcs_instructions[3][start_add+ 5] = ["SRAM", "-", "INA", "R1", "-", "-"] +rcs_instructions[3][start_add+ 6] = [ "R0", "R1", "SSUB", "-", "-", "-"] +rcs_instructions[3][start_add+ 7] = [ "R0", "R1", "BSFA", "R0", "PREV", "-"] +rcs_instructions[3][start_add+ 8] = rcs_nop_instr +rcs_instructions[3][start_add+ 9] = [ "R0", "-", "SWD", "-", "-", "-"] diff --git a/hw/vendor/esl_epfl_x_heep/.gitignore b/hw/vendor/esl_epfl_x_heep/.gitignore index a9a6e8c0..d369ddf8 100644 --- a/hw/vendor/esl_epfl_x_heep/.gitignore +++ b/hw/vendor/esl_epfl_x_heep/.gitignore @@ -7,19 +7,18 @@ build/ *.dis *.map *.do -.venv/* -util/__pycache__/* +*.jou +*.str +.venv/ +__pycache__/ # ignore apps output file run_verif_rtl_log.txt -#ignore femu generated hw -linux_femu/rtl/linux_femu.sv -.venv/ - # ignore the following hw automatically generated files environment.yml core-v-mini-mcu.upf +core-v-mini-mcu.dc.upf tb/tb_util.svh hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv hw/core-v-mini-mcu/system_bus.sv @@ -36,9 +35,13 @@ hw/system/pad_control/data/pad_control.hjson hw/system/pad_control/rtl/pad_control.sv hw/system/pad_control/rtl/pad_control_reg_pkg.sv hw/system/pad_control/rtl/pad_control_reg_top.sv +hw/fpga/sram_wrapper.sv +hw/fpga/scripts/generate_sram.tcl -# same for the C header file and linker scripts +# same for the C header file and linker scripts and assembly files +sw/device/lib/crt/crt0.S sw/device/lib/runtime/core_v_mini_mcu.h +sw/device/lib/runtime/core_v_mini_mcu_memory.h sw/linker/link.ld sw/linker/link_flash_exec.ld sw/linker/link_flash_load.ld @@ -50,6 +53,9 @@ sw/device/lib/drivers/**/*_structs.h # openroad flow/OpenROAD-flow-scripts +# automatically generated docs +/docs/source/Configuration/generated + # User-dependent configuration files .vscode private/ diff --git a/hw/vendor/esl_epfl_x_heep/Makefile b/hw/vendor/esl_epfl_x_heep/Makefile index fa6e81ef..f65c4640 100644 --- a/hw/vendor/esl_epfl_x_heep/Makefile +++ b/hw/vendor/esl_epfl_x_heep/Makefile @@ -6,10 +6,13 @@ MAKE = make # Get the absolute path mkfile_path := $(shell dirname "$(realpath $(firstword $(MAKEFILE_LIST)))") +$(info $$You are executing from: $(mkfile_path)) # Include the self-documenting tool -FILE=$(mkfile_path)/Makefile -include $(mkfile_path)/util/generate-makefile-help +export FILE_FOR_HELP=$(mkfile_path)/Makefile + +help: + ${mkfile_path}/util/MakefileHelp # Setup to autogenerate python virtual environment VENVDIR?=$(WORKDIR)/.venv @@ -30,12 +33,15 @@ endif # Project options are based on the app to be build (default - hello_world) PROJECT ?= hello_world +LINK_FOLDER ?= $(mkfile_path)/sw/linker + # Linker options are 'on_chip' (default),'flash_load','flash_exec','freertos' LINKER ?= on_chip -# Target options are 'sim' (default) and 'pynq-z2' +# Target options are 'sim' (default) and 'pynq-z2' and 'nexys-a7-100t' TARGET ?= sim -MCU_CFG ?= mcu_cfg.hjson +MCU_CFG_PERIPHERALS ?= mcu_cfg.hjson +X_HEEP_CFG ?= configs/general.hjson PAD_CFG ?= pad_cfg.hjson EXT_PAD_CFG ?= @@ -49,7 +55,7 @@ COMPILER_PREFIX ?= riscv32-unknown- ARCH ?= rv32imc # Path relative from the location of sw/Makefile from which to fetch source files. The directory of that file is the default value. -SOURCE ?= "." +SOURCE ?= $(".") # Simulation engines options are verilator (default) and questasim SIMULATOR ?= verilator @@ -57,6 +63,31 @@ SIMULATOR ?= verilator # Timeout for simulation, default 120 TIMEOUT ?= 120 +# Flash read address for testing, in hexadecimal format 0x0000 +FLASHREAD_ADDR ?= 0x0 +FLASHREAD_FILE ?= $(mkfile_path)/flashcontent.hex +FLASHREAD_BYTES ?= 256 + + +#binary to store in flash memory +FLASHWRITE_FILE ?= $(mkfile_path)/sw/build/main.hex + +#max address in the hex file, used to program the flash +ifeq ($(wildcard $(FLASHWRITE_FILE)),) + MAX_HEX_ADDRESS := 0 + MAX_HEX_ADDRESS_DEC := 0 + BYTES_AFTER_MAX_HEX_ADDRESS := 0 + FLASHWRITE_BYTES := 0 +else + MAX_HEX_ADDRESS := $(shell cat $(FLASHWRITE_FILE) | grep "@" | tail -1 | cut -c2-) + MAX_HEX_ADDRESS_DEC := $(shell printf "%d" 0x$(MAX_HEX_ADDRESS)) + BYTES_AFTER_MAX_HEX_ADDRESS := $(shell tac $(FLASHWRITE_FILE) | awk 'BEGIN {count=0} /@/ {print count; exit} {count++}') + FLASHWRITE_BYTES := $(shell echo $(MAX_HEX_ADDRESS_DEC) + $(BYTES_AFTER_MAX_HEX_ADDRESS)*16 | bc) +endif + +# Export variables to sub-makefiles +export + ## @section Conda conda: environment.yml conda env create -f environment.yml @@ -64,43 +95,41 @@ conda: environment.yml environment.yml: python-requirements.txt util/python-requirements2conda.sh -## @section Linux-Emulation - -## Generates FEMU -linux-femu-gen: mcu-gen - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir linux_femu/rtl/ --tpl-sv linux_femu/rtl/linux_femu.sv.tpl - $(MAKE) verible - ## @section Installation ## Generates mcu files core-v-mini-mcu files and build the design with fusesoc -## @param CPU=[cv32e20(default),cv32e40p,cv32e40x] +## @param CPU=[cv32e20(default),cv32e40p,cv32e40x,cv32e40px] ## @param BUS=[onetoM(default),NtoM] ## @param MEMORY_BANKS=[2(default) to (16 - MEMORY_BANKS_IL)] ## @param MEMORY_BANKS_IL=[0(default),2,4,8] mcu-gen: - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir hw/core-v-mini-mcu/include --cpu $(CPU) --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_domains $(EXTERNAL_DOMAINS) --external_pads $(EXT_PAD_CFG) --pkg-sv hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir hw/core-v-mini-mcu/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/core-v-mini-mcu/system_bus.sv.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir hw/core-v-mini-mcu/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/core-v-mini-mcu/system_xbar.sv.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir hw/core-v-mini-mcu/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/core-v-mini-mcu/memory_subsystem.sv.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir hw/core-v-mini-mcu/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/core-v-mini-mcu/peripheral_subsystem.sv.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir tb/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv tb/tb_util.svh.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir hw/system/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/system/pad_ring.sv.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir hw/core-v-mini-mcu/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir hw/system/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/system/x_heep_system.sv.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir sw/device/lib/runtime --cpu $(CPU) --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_domains $(EXTERNAL_DOMAINS) --header-c sw/device/lib/runtime/core_v_mini_mcu.h.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir sw/linker --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --linker_script sw/linker/link.ld.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir . --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --pkg-sv ./core-v-mini-mcu.upf.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir hw/ip/power_manager/rtl --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_domains $(EXTERNAL_DOMAINS) --pkg-sv hw/ip/power_manager/data/power_manager.sv.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir hw/ip/power_manager/data --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_domains $(EXTERNAL_DOMAINS) --pkg-sv hw/ip/power_manager/data/power_manager.hjson.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/core-v-mini-mcu/include --cpu $(CPU) --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_domains $(EXTERNAL_DOMAINS) --external_pads $(EXT_PAD_CFG) --pkg-sv hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/core-v-mini-mcu/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/core-v-mini-mcu/system_bus.sv.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/core-v-mini-mcu/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/core-v-mini-mcu/system_xbar.sv.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/core-v-mini-mcu/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/core-v-mini-mcu/memory_subsystem.sv.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/core-v-mini-mcu/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/core-v-mini-mcu/peripheral_subsystem.sv.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir tb/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv tb/tb_util.svh.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/system/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/system/pad_ring.sv.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/core-v-mini-mcu/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/system/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/system/x_heep_system.sv.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir sw/device/lib/runtime --cpu $(CPU) --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_domains $(EXTERNAL_DOMAINS) --header-c sw/device/lib/runtime/core_v_mini_mcu.h.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir sw/device/lib/runtime --cpu $(CPU) --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_domains $(EXTERNAL_DOMAINS) --header-c sw/device/lib/runtime/core_v_mini_mcu_memory.h.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir $(LINK_FOLDER) --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --linker_script $(LINK_FOLDER)/link.ld.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir . --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --pkg-sv ./core-v-mini-mcu.upf.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir . --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --pkg-sv ./core-v-mini-mcu.dc.upf.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/ip/power_manager/rtl --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_domains $(EXTERNAL_DOMAINS) --pkg-sv hw/ip/power_manager/data/power_manager.sv.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/ip/power_manager/data --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_domains $(EXTERNAL_DOMAINS) --pkg-sv hw/ip/power_manager/data/power_manager.hjson.tpl bash -c "cd hw/ip/power_manager; source power_manager_gen.sh; cd ../../../" - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir sw/device/lib/drivers/power_manager --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_domains $(EXTERNAL_DOMAINS) --pkg-sv sw/device/lib/drivers/power_manager/data/power_manager.h.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir hw/system/pad_control/data --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_pads $(EXT_PAD_CFG) --pkg-sv hw/system/pad_control/data/pad_control.hjson.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir hw/system/pad_control/rtl --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_pads $(EXT_PAD_CFG) --pkg-sv hw/system/pad_control/rtl/pad_control.sv.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir sw/device/lib/drivers/power_manager --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_domains $(EXTERNAL_DOMAINS) --pkg-sv sw/device/lib/drivers/power_manager/data/power_manager.h.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/system/pad_control/data --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_pads $(EXT_PAD_CFG) --pkg-sv hw/system/pad_control/data/pad_control.hjson.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/system/pad_control/rtl --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --external_pads $(EXT_PAD_CFG) --pkg-sv hw/system/pad_control/rtl/pad_control.sv.tpl bash -c "cd hw/system/pad_control; source pad_control_gen.sh; cd ../../../" - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir sw/linker --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --linker_script sw/linker/link_flash_exec.ld.tpl - $(PYTHON) util/mcu_gen.py --cfg $(MCU_CFG) --pads_cfg $(PAD_CFG) --outdir sw/linker --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --linker_script sw/linker/link_flash_load.ld.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir $(LINK_FOLDER) --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --linker_script $(LINK_FOLDER)/link_flash_exec.ld.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir $(LINK_FOLDER) --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --linker_script $(LINK_FOLDER)/link_flash_load.ld.tpl $(PYTHON) ./util/structs_periph_gen.py + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/fpga/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/fpga/sram_wrapper.sv.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir hw/fpga/scripts/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv hw/fpga/scripts/generate_sram.tcl.tpl + $(PYTHON) util/mcu_gen.py --config $(X_HEEP_CFG) --cfg_peripherals $(MCU_CFG_PERIPHERALS) --pads_cfg $(PAD_CFG) --outdir sw/device/lib/crt/ --bus $(BUS) --memorybanks $(MEMORY_BANKS) --memorybanks_il $(MEMORY_BANKS_IL) --tpl-sv sw/device/lib/crt/crt0.S.tpl $(MAKE) verible ## Display mcu_gen.py help @@ -115,13 +144,21 @@ verible: ## Generates the build folder in sw using CMake to build (compile and linking) ## @param PROJECT= -## @param TARGET=sim(default),pynq-z2 +## @param TARGET=sim(default),systemc,pynq-z2,nexys-a7-100t,zcu104 ## @param LINKER=on_chip(default),flash_load,flash_exec ## @param COMPILER=gcc(default), clang ## @param COMPILER_PREFIX=riscv32-unknown-(default) ## @param ARCH=rv32imc(default), app: clean-app - $(MAKE) -C sw PROJECT=$(PROJECT) TARGET=$(TARGET) LINKER=$(LINKER) COMPILER=$(COMPILER) COMPILER_PREFIX=$(COMPILER_PREFIX) ARCH=$(ARCH) SOURCE=$(SOURCE) + $(MAKE) -C sw PROJECT=$(PROJECT) TARGET=$(TARGET) LINKER=$(LINKER) LINK_FOLDER=$(LINK_FOLDER) COMPILER=$(COMPILER) COMPILER_PREFIX=$(COMPILER_PREFIX) ARCH=$(ARCH) SOURCE=$(SOURCE) \ + || { \ + echo "\033[0;31mHmmm... seems like the compilation failed...\033[0m"; \ + echo "\033[0;31mIf you do not understand why, it is likely that you either:\033[0m"; \ + echo "\033[0;31m a) offended the Leprechaun of Electronics\033[0m"; \ + echo "\033[0;31m b) forgot to run make mcu-gen\033[0m"; \ + echo "\033[0;31mI would start by checking b) if I were you!\033[0m"; \ + exit 1; \ + } ## Just list the different application names available app-list: @@ -134,10 +171,14 @@ app-compile-all: ## @section Simulation -## Verilator simulation +## Verilator simulation with C++ verilator-sim: $(FUSESOC) --cores-root . run --no-export --target=sim --tool=verilator $(FUSESOC_FLAGS) --build openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildsim.log +## Verilator simulation with SystemC +verilator-sim-sc: + $(FUSESOC) --cores-root . run --no-export --target=sim_sc --tool=verilator $(FUSESOC_FLAGS) --build openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildsim.log + ## Questasim simulation questasim-sim: $(FUSESOC) --cores-root . run --no-export --target=sim --tool=modelsim $(FUSESOC_FLAGS) --build openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildsim.log @@ -152,7 +193,7 @@ questasim-sim-opt-upf: questasim-sim $(MAKE) -C build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-modelsim opt-upf ## VCS simulation -## @param CPU=cv32e20(default),cv32e40p,cv32e40x +## @param CPU=cv32e20(default),cv32e40p,cv32e40x,cv32e40px ## @param BUS=onetoM(default),NtoM vcs-sim: $(FUSESOC) --cores-root . run --no-export --target=sim --tool=vcs $(FUSESOC_FLAGS) --build openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildsim.log @@ -161,6 +202,10 @@ vcs-sim: vcs-ams-sim: $(FUSESOC) --cores-root . run --no-export --target=sim --flag "ams_sim" --tool=vcs $(FUSESOC_FLAGS) --build openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildsim.log +## xcelium simulation +xcelium-sim: + $(FUSESOC) --cores-root . run --no-export --target=sim --tool=xcelium $(FUSESOC_FLAGS) --build openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildsim.log + ## Generates the build output for helloworld application ## Uses verilator to simulate the HW model and run the FW ## UART Dumping in uart0.log to show recollected results @@ -175,7 +220,7 @@ run-helloworld: mcu-gen verilator-sim ## Uses verilator to simulate the HW model and run the FW ## UART Dumping in uart0.log to show recollected results run-blinkyfreertos: mcu-gen verilator-sim - $(MAKE) -C sw PROJECT=blinky_freertos TARGET=$(TARGET) LINKER=$(LINKER) COMPILER=$(COMPILER) COMPILER_PREFIX=$(COMPILER_PREFIX) ARCH=$(ARCH); + $(MAKE) -C sw PROJECT=example_freertos_blinky TARGET=$(TARGET) LINKER=$(LINKER) COMPILER=$(COMPILER) COMPILER_PREFIX=$(COMPILER_PREFIX) ARCH=$(ARCH); cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-verilator; \ ./Vtestharness +firmware=../../../sw/build/main.hex; \ cat uart0.log; \ @@ -196,7 +241,7 @@ app-simulate-all: ## @section Vivado ## Builds (synthesis and implementation) the bitstream for the FPGA version using Vivado -## @param FPGA_BOARD=nexys-a7-100t,pynq-z2 +## @param FPGA_BOARD=nexys-a7-100t,pynq-z2,zcu104 ## @param FUSESOC_FLAGS=--flag= vivado-fpga: $(FUSESOC) --cores-root . run --no-export --target=$(FPGA_BOARD) $(FUSESOC_FLAGS) --build openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildvivado.log @@ -204,6 +249,9 @@ vivado-fpga: vivado-fpga-nobuild: $(FUSESOC) --cores-root . run --no-export --target=$(FPGA_BOARD) $(FUSESOC_FLAGS) --setup openhwgroup.org:systems:core-v-mini-mcu ${FUSESOC_PARAM} 2>&1 | tee buildvivado.log +vivado-fpga-pgm: + $(MAKE) -C build/openhwgroup.org_systems_core-v-mini-mcu_0/$(FPGA_BOARD)-vivado pgm + ## @section ASIC ## Note that for this step you need to provide technology-dependent files (e.g., libs, constraints) asic: @@ -220,18 +268,32 @@ openroad-sky130: ## Read the id from the EPFL_Programmer flash flash-readid: - cd sw/vendor/yosyshq_icestorm/iceprog; \ + cd sw/vendor/yosyshq_icestorm/iceprog; make; \ ./iceprog -d i:0x0403:0x6011 -I B -t; ## Loads the obtained binary to the EPFL_Programmer flash flash-prog: - cd sw/vendor/yosyshq_icestorm/iceprog; \ - ./iceprog -d i:0x0403:0x6011 -I B $(mkfile_path)/sw/build/main.hex; + cd sw/vendor/yosyshq_icestorm/iceprog; make; \ + ./iceprog -a $(FLASHWRITE_BYTES) -d i:0x0403:0x6011 -I B $(FLASHWRITE_FILE); + +## Read the EPFL_Programmer flash +flash-read: + cd sw/vendor/yosyshq_icestorm/iceprog; make; \ + ./iceprog -d i:0x0403:0x6011 -I B -o $(shell printf "%d" $(FLASHREAD_ADDR)) -R $(FLASHREAD_BYTES) $(FLASHREAD_FILE); + +## Erase the EPFL_Programmer flash +flash-erase: + cd sw/vendor/yosyshq_icestorm/iceprog; make; \ + ./iceprog -d i:0x0403:0x6011 -I B -b; ## Run openOCD w/ EPFL_Programmer openOCD_epflp: xterm -e openocd -f ./tb/core-v-mini-mcu-pynq-z2-esl-programmer.cfg; +## Run openOCD w/ BSCAN of the Pynq-Z2 board +openOCD_bscan: + xterm -e openocd -f ./tb/core-v-mini-mcu-pynq-z2-bscan.cfg; + ## Start GDB gdb_connect: $(MAKE) -C sw gdb_connect diff --git a/hw/vendor/esl_epfl_x_heep/README.md b/hw/vendor/esl_epfl_x_heep/README.md index 0e0130b7..1a539464 100644 --- a/hw/vendor/esl_epfl_x_heep/README.md +++ b/hw/vendor/esl_epfl_x_heep/README.md @@ -1,3 +1,22 @@ +
+

+ +`X-HEEP` (eXtendable Heterogeneous Energy-Efficient Platform) is a `RISC-V` microcontroller described in `SystemVerilog` +that can be configured to target small and tiny platforms as well as extended to support accelerators. +The cool thing about `X-HEEP` is that we provide a simple customizable MCU, so CPUs, common peripherals, memories, etc. +so that you can extend it with your own accelerator without modifying the MCU, but just instantiating it in your design. +By doing so, you inherit an IP capable of booting RTOS (such as `freeRTOS`) with the whole FW stack, including `HAL` drivers and `SDK`, +and you can focus on building your special HW supported by the microcontroller. + +`X-HEEP` supports simulation with Verilator, Questasim, etc. Morever, FW can be built and linked by using `CMake` either with gcc or with clang. It can be implemented on FPGA, and it supports implementation in Silicon, which is its main (but not only) target. See below for more details. + +The block diagram below shows the `X-HEEP` MCU + +

+ + +> :bookmark_tabs: Please refer to the documentation in [Read the Docs](https://x-heep.readthedocs.io/en/latest/index.html) + # Repository folder structure . @@ -23,538 +42,17 @@ ├── util └── README.md -
-

- -`X-HEEP` (eXtendable Heterogeneous Energy-Efficient Platform) is a `RISC-V` microcontroller described in `SystemVerilog` -that can be configured to target small and tiny platforms as well as extended to support accelerators. -The cool thing about `X-HEEP` is that we provide a simple customizable MCU, so CPUs, common peripherals, memories, etc. -so that you can extend it with your own accelerator without modifying the MCU, but just instantiating it in your design. -By doing so, you inherit an IP capable of booting RTOS (such as `freeRTOS`) with the whole FW stack, including `HAL` drivers and `SDK`, -and you can focus on building your special HW supported by the microcontroller. - -`X-HEEP` supports simulation with Verilator, Questasim, etc. Morever, FW can be built and linked by using `CMake` either with gcc or with clang. It can be implemented on FPGA, and it supports implementation in Silicon, which is its main (but not only) target. See below for more details. - -The block diagram below shows the `X-HEEP` MCU - -

- -# Self-documented Makefile - -Note that under `util` folder, the file `generate-makefile-help` is employed to generate a self-documented helping output. In case of including any other target or command under the main `Makefile`, follow the same general and parameter descriptions as already provided for every target. Check the `help` output by doing `make` or `make help`. Moreover, **note that some of the parameters required for some of the targets are initiated with _default values_** - -# Prerequisite - -## 1. OS requirements - -To use `X-HEEP`, first make sure you have the following apt packages, or install them as: - -```bash -sudo apt install lcov libelf1 libelf-dev libftdi1-2 libftdi1-dev libncurses5 libssl-dev libudev-dev libusb-1.0-0 lsb-release texinfo autoconf cmake flex bison libexpat-dev gawk tree xterm python3-venv python3-dev -``` - -In general, have a look at the [Install required software](https://opentitan.org/guides/getting_started/index.html) section of the OpenTitan documentation. - -It has been tested only on `Ubuntu 20`, and we know it does NOT WORK on `Ubuntu 22`. - -## 2. Python - - -We rely on either (a) `miniconda`, or (b) `virtual environment` enviroment. - -Choose between `2.a` or `2.b` to setup your enviroment. - -### 2.a Miniconda - -Install [Miniconda](https://docs.conda.io/en/latest/miniconda.html#linux-installers) python 3.8 version as described in the link, -and create the Conda enviroment: - -```bash -make conda -``` - -You need to do it only the first time, then just activate the environment everytime you work with `X-HEEP` as - -```bash -conda activate core-v-mini-mcu -``` - - -### 2.b Virtual Environment - -Install the python virtual environment just as: - -```bash -make venv -``` - -You need to do it only the first time, then just activate the environment everytime you work with `X-HEEP` as - -```bash -source .venv/bin/activate -``` - -## 3. Install the RISC-V Compiler: - -``` -git clone --branch 2022.01.17 --recursive https://github.com/riscv/riscv-gnu-toolchain -cd riscv-gnu-toolchain -./configure --prefix=/home/$USER/tools/riscv --with-abi=ilp32 --with-arch=rv32imc --with-cmodel=medlow -make -``` - -Then, set the `RISCV` env variable as: - -``` -export RISCV=/home/$USER/tools/riscv -``` - -Optionally you can also compile with clang/LLVM instead of gcc. For that you must install the clang compiler into the same `RISCV` path. The binaries of gcc and clang do not collide so you can have both residing in the same `RISCV` directory. For this you can set the `-DCMAKE_INSTALL_PREFIX` cmake variable to `$RISCV` when building LLVM. This can be accomplished by doing the following: - -``` -git clone https://github.com/llvm/llvm-project.git -cd llvm-project -git checkout llvmorg-14.0.0 -mkdir build && cd build -cmake -G "Unix Makefiles" -DLLVM_ENABLE_PROJECTS=clang -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$RISCV -DLLVM_TARGETS_TO_BUILD="RISCV" ../llvm -cmake --build . --target install -``` - -## 4. Install Verilator: - -``` -export VERILATOR_VERSION=4.210 - -git clone https://github.com/verilator/verilator.git -cd verilator -git checkout v$VERILATOR_VERSION - -autoconf -./configure --prefix=/home/$USER/tools/verilator/$VERILATOR_VERSION -make -make install -``` -Then, set the `PATH` env variable to as: - -``` -export PATH=/home/$USER/tools/verilator/$VERILATOR_VERSION/bin:$PATH -``` - -In general, have a look at the [Install Verilator](https://opentitan.org/guides/getting_started/setup_verilator.html) section of the OpenTitan documentation. - -If you want to see the vcd waveforms generated by the Verilator simulation, install GTKWAVE: - -``` -sudo apt install libcanberra-gtk-module libcanberra-gtk3-module -sudo apt-get install -y gtkwave -``` - -## Files are formatted with Verible - -We use version v0.0-1824-ga3b5bedf - -See: [Install Verible](https://opentitan.org/guides/getting_started/index.html#step-6a-install-verible-optional) - -To format your RTL code type: - -``` -make verible -``` -## Compilation Flow and Package Manager - -We use [FuseSoC](https://github.com/olofk/fusesoc) for all the tools we use. - -The `fusesoc` commands are inside the Makefile. - -# Adding external IPs - -This repository relies on [Vendor](https://opentitan.org/book/util/doc/vendor.html) to add new IPs. The `vendor.py` script in the [`./util`](./util/) folder implements what is describeb above, while [this](./ExternalDevices.md) file contains additional information on how to connect external devices to the system. +# Reference -# Compiling with Makefile - -You can compile the example applications and the platform using the Makefile. Type 'make help' or 'make' for more information. Moreover, please, check the different 'clean' commands to verify that you are using the corret one. - -## Generate core-v-mini-mcu package - -First, you have to generate the SystemVerilog package and C header file of the core-v-mini-mcu: - -``` -make mcu-gen -``` - -By default, `X-HEEP` deploys the [cv32e20](https://github.com/openhwgroup/cve2) RISC-V CPU. -Other supported CPUs are: the [cv32e40p](https://github.com/openhwgroup/cv32e40p), [cv32e40x](https://github.com/openhwgroup/cv32e40x), and the [cv32e40px](https://github.com/esl-epfl/cv32e40px). -The default bus type of `X-HEEP` is a single-master-at-a-time architecture, (called `onetoM`), but the cross-bar architecture is also supported by setting -the bus to `NtoM`. Also, the user can select the number of 32kB banks addressed in continuous mode and/or the interleaved mode. -By default, `X-HEEP` is generated with 2 continuous banks and 0 interleaved banks. - -Below an example that changes the default configuration: +If you use X-HEEP in your academic work you can cite us: [X-HEEP Paper](https://arxiv.org/abs/2401.05548) ``` -make mcu-gen CPU=cv32e40p BUS=NtoM MEMORY_BANKS=12 MEMORY_BANKS_IL=4 -``` - -The last command generates x-heep with the cv32e40p core, with a parallel bus, and 16 memory banks (12 continuous and 4 interleaved), -each 32KB, for a total memory of 512KB. - -If you are using `X-HEEP` just as a controller for your own system and you do not need any peripheral, you can use the `minimal` configuration file -when generating the MCU as: - -``` -make mcu-gen MCU_CFG=mcu_cfg_minimal.hjson -``` - -The `minimal` configuration is a work-in-progress, thus not all the APPs have been tested. - - -## Compiling Software - -Don't forget to set the `RISCV` env variable to the compiler folder (without the `/bin` included). -To run 'hello world' application, just type 'make app'. - -``` -make app -``` - -To run any other application, please use the following command with appropiate parameters: - -``` -app PROJECT= TARGET=sim(default),pynq-z2 LINKER=on_chip(default),flash_load,flash_exec COMPILER=gcc(default),clang COMPILER_PREFIX=riscv32-unknown-(default) ARCH=rv32imc(default), - -Params: -- PROJECT (ex: , hello_world(default)) -- TARGET (ex: sim(default),pynq-z2) -- LINKER (ex: on_chip(default),flash_load,flash_exec) -- COMPILER (ex: gcc(default),clang) -- COMPILER_PREFIX (ex: riscv32-unknown-(default)) -- ARCH (ex: rv32imc(default),) -``` - -For instance, to run 'hello world' app for the pynq-z2 FPGA targets, just run: - -``` -make app TARGET=pynq-z2 -``` - -Or, if you use the OpenHW Group [GCC](https://www.embecosm.com/resources/tool-chain-downloads/#corev) compiler with CORE_PULP extensions, make sure to point the `RISCV` env variable to the OpenHW Group compiler, then just run: - - -``` -make app COMPILER_PREFIX=riscv32-corev- ARCH=rv32imc_zicsr_zifencei_xcvhwlp1p0_xcvmem1p0_xcvmac1p0_xcvbi1p0_xcvalu1p0_xcvsimd1p0_xcvbitmanip1p0 -``` - -This will create the executable file to be loaded into your target system (ASIC, FPGA, Simulation). -Remember that, `X-HEEP` is using CMake to compile and link. Thus, the generated files after having -compiled and linked are under `sw\build` - -Alternatively, in case you are doing pure FW development and you are used to developing using Integrated Development Evironments (IDEs), please check [the IDE readme](./IDEs.md). - -## FreeROTS based applications - -'X-HEEP' supports 'FreeRTOS' based applications. Please see `sw\applications\blinky_freertos`. - -After that, you can run the command to compile and link the FreeRTOS based application. Please also set 'LINKER' and 'TARGET' parameters if needed. - -``` -make app PROJECT=blinky_freertos -``` - -The main FreeRTOS configuration is allocated under `sw\freertos`, in `FreeRTOSConfig.h`. Please, change this file based on your application requirements. -Moreover, FreeRTOS is being fetch from 'https://github.com/FreeRTOS/FreeRTOS-Kernel.git' by CMake. Specifically, 'V10.5.1' is used. Finally, the fetch repository is located under `sw\build\_deps` after building. - -## Simulating - -This project supports simulation with Verilator, Synopsys VCS, and Siemens Questasim. -It relies on `fusesoc` to handle multiple EDA tools and parameters. -For example, if you want to set the `FPU` and `COREV_PULP` parameters of the `cv32e40p` CPU, -you need to add next to your compilation command `FUSESOC_PARAM="--COREV_PULP=1 --FPU=1"` -Below the different EDA examples commands. - -### Compiling for Verilator - -To simulate your application with Verilator, first compile the HDL: - -``` -make verilator-sim -``` - -then, go to your target system built folder - -``` -cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-verilator -``` - -and type to run your compiled software: - -``` -./Vtestharness +firmware=../../../sw/build/main.hex -``` - -or to execute all these three steps type: - -``` -make run-helloworld -``` - - -### Compiling for VCS - -To simulate your application with VCS, first compile the HDL: - -``` -make vcs-sim -``` - -then, go to your target system built folder - -``` -cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-vcs -``` - -and type to run your compiled software: - -``` -./openhwgroup.org_systems_core-v-mini-mcu_0 +firmware=../../../sw/build/main.hex -``` - -Waveforms can be viewed with Verdi. Make sure you have the env variable `VERDI_HOME` set to your Verdi install folder, then run your compiled software as above, but with the `-gui` flag: - -``` -./openhwgroup.org_systems_core-v-mini-mcu_0 +firmware=../../../sw/build/main.hex -gui -``` - -An Analog / Mixed-Signal simulation of X-HEEP, combining both the RTL system verilog files for the digital part and a SPICE file connected through a `control.init` file for the analog / mixed-signal part, can be ran by typing - -``` -make vcs-ams-sim -``` - -then going to the target system built folder - -``` -cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-vcs -``` - -and running the same executable as for the digital simulation. Note that with Verdi you can view both the digital and the analog waveforms. - -Additional instructions on how to run an analog / mixed-signal simulation of X-HEEP can be found [here](AnalogMixedSignal.md). To try out the simulation, we provide an example SPICE netlist of an simple 1-bit ADC created by us and exported from [xschem](https://xschem.sourceforge.io/stefan/index.html) and which uses the PTM 65nm bulk CMOS model from [https://ptm.asu.edu](https://ptm.asu.edu/). - -### Compiling for Questasim - -To simulate your application with Questasim, first set the env variable `MODEL_TECH` to your Questasim bin folder, then compile the HDL: - -``` -make questasim-sim -``` - -then, go to your target system built folder - -``` -cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-modelsim/ -``` - -and type to run your compiled software: - -``` -make run PLUSARGS="c firmware=../../../sw/build/main.hex" -``` - -You can also use vopt for HDL optimized compilation: - -``` -make questasim-sim-opt -``` - -then go to - -``` -cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim_opt-modelsim/ -``` -and - -``` -make run RUN_OPT=1 PLUSARGS="c firmware=../../../sw/build/main.hex" -``` - -You can also compile with the UPF power domain description as: - -``` -make questasim-sim-opt-upf FUSESOC_PARAM="--USE_UPF" -``` - -and then execute software as: - -``` -make run RUN_OPT=1 RUN_UPF=1 PLUSARGS="c firmware=../../../sw/build/main.hex" -``` - -Questasim version must be >= Questasim 2020.4 - -### UART DPI - -To simulate the UART, we use the LowRISC OpenTitan [UART DPI](https://github.com/lowRISC/opentitan/tree/master/hw/dv/dpi/uartdpi). -Read how to interact with it in the Section "Running Software on a Verilator Simulation with Bazel" [here](https://opentitan.org/guides/getting_started/setup_verilator.html#running-software-on-a-verilator-simulation-with-bazel). -The output of the UART DPI module is printed in the `uart0.log` file in the simulation folder. - -For example, to see the "hello world!" output of the Verilator simulation: - -``` -cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-verilator -./Vtestharness +firmware=../../../sw/build/main.hex -cat uart0.log -``` - -## Automatic testing - -X-HEEP includes two tools to perform automatic tests over your modifications. - -### Github CIs - -Upon push, tests are run on Github runners, these include: -* The generated `.sv` files pushed are equal to those generated in the runner (the code does not depend on the modification of generated files) -* Vendor is up to date (the code does not depend on the modification of vendorized files) -* All applications can be built successfully using both gcc and clang - -All test must be successful before PRs can be merged. - -### Simulation script - -Additionally, a `test_all.sh` script is provided. Apart from compiling all apps with both gcc and clang, it will simulate them and check the result. - -The available parameters are: -* COMPILER: `gcc` (default) or `clang` (can provide more than one) -* SIMULATOR: `verilator` (default), `questasim` or disable simulation with `nosim` (only one, the last provided is used). -* LINKER: `on_chip`(default), `flash_load` or `flash_exec` (can provide more than one) -* TIMEOUT: Integer number of seconds (default 120) - - -#### Usage - -##### Comands -You can use two different commands to compile or simulate all the existing APPs: -``` -make app-compile-all -``` -``` -make app-simulate-all -``` -Note that both commands allow the previous parameters to specify compiling or simulation options. E.g.: -``` -make app-simulate-all LINKER=on_chip SIMULATOR=questasim COMPILER=clang TIMEOUT=150 -``` - -##### Manually -You can also **SOURCE** the script as -```bash -. util/test_all.sh on_chip questasim clang 150 -``` - -*Pay special attention to the first period in the command!* -You will be killing simulations that take too long, if you **EXECUTE** (`./test_all.sh`) this action kills the script. - -For both usages (commands or manual), the order of the arguments is irrelevant. - -> Note: Be sure to commit all your changes before running the script! - -* Applications that fail being built with gcc will not be simulated (skipped). -* Some applications are skipped by default for not being suitable for simulation. -* If a simulation takes too long (>timeout), it is killed. - -* Upon starting, the script will modify the `mcu_cfg.hjson` file to include all peripherals (so the largest number of apps can be run), re-generates the mcu and re-builds the simulation model for the chosen tool. -These changes can be reverted at the end of the execution (default). If changes were not commited, accepting this operation will revert them! - -The success of the script is not required for merging of a PR. - -## Debug - -Follow the [Debug](./Debug.md) guide to debug core-v-mini-mcu. - -Alternatively, in case you are used to developing using Integrated Development Environments (IDEs), please check [the IDE readme](./IDEs.md). - -## Execute From Flash - -Follow the [ExecuteFromFlash](./ExecuteFromFlash.md) guide to exxecute code directly from the FLASH with modelsim, FPGA, or ASIC. - -## Emulation on Xilinx FPGAs - -This project offers two different X-HEEP implementetions on the Xilinx FPGAs, called Standalone-FEMU and Linux-FEMU. - -### Standalone-FEMU (Standalone Fpga EMUlation) - -In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the FPGA, and its input/output are connected to the available headers on the FPGA board. - -Make sure you have the FPGA board files installed in your Vivado. - -For example, for the Xilinx Pynq-Z2 board, use the documentation provided at the following [link](https://pynq.readthedocs.io/en/v2.5/overlay_design_methodology/board_settings.html) to download and install them: - -To build and program the bitstream for your FPGA with vivado, type: - -``` -make vivado-fpga FPGA_BOARD=pynq-z2 -``` - -or add the flag `use_bscane_xilinx` to use the native Xilinx scanchain: - -``` -make vivado-fpga FPGA_BOARD=pynq-z2 FUSESOC_FLAGS=--flag=use_bscane_xilinx -``` - -Only Vivado 2021.2 has been tried. - -To program the bitstream, open Vivado, - -``` -open --> Hardware Manager --> Open Target --> Autoconnect --> Program Device -``` - -and choose the file `openhwgroup.org_systems_core-v-mini-mcu_0.bit` - -To run SW, follow the [Debug](./Debug.md) guide -to load the binaries with the HS2 cable over JTAG, -or follow the [ExecuteFromFlash](./ExecuteFromFlash.md) -guide if you have a FLASH attached to the FPGA. - -Do not forget that the `pynq-z2` board requires you to have the ethernet cable attached to the board while running. - -For example, if you want to run your application using flash_exec, do as follow: - -compile your application, e.g. `make app PROJECT=example_matfadd TARGET=pynq-z2 ARCH=rv32imfc LINKER=flash_exec` - -and then follow the [ExecuteFromFlash](./ExecuteFromFlash.md) to program the flash and set the boot buttons on the FPGA correctly. - -To look at the output of your printf, run in another terminal: - -`picocom -b 9600 -r -l --imap lfcrlf /dev/ttyUSB2` - -Please be sure to use the right `ttyUSB` number (you can discover it with `dmesg --time-format iso | grep FTDI` for example). - - -### Linux-FEMU (Linux Fpga EMUlation) - -In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the FPGA and Linux is run on the ARM-based processing system (PS) side of the same chip. - -Read the [following](./linux_femu/README.md) documentation to have more information about this implementation. - - -# ASIC Implementation - -This project can be implemented using standard cells based ASIC flow. - -## Synthesis with Synopsys Design Compiler - -First, you need to provide technology-dependent implementations of some of the cells which require specific instantiation. - -Then, please provide a set_libs.tcl and set_constraints.tcl scripts to set link and target libraries, and constraints as the clock. - -To generate the `analyze` script for the synthesis scripts with DC, execute: - -``` -make asic -``` - -## OpenRoad support for SkyWater 130nm - -We are working on supporting OpenRoad and SkyWater 130nm PDK, please refer to the -[OpenRoadFlow](./OpenRoadFlow.md) page. This is not ready yet, it has not been tested. - -This relies on a fork of [edalize](https://github.com/davideschiavone/edalize) that contains templates for Design Compiler and OpenRoad. +@misc{machetti2024xheep, + title={X-HEEP: An Open-Source, Configurable and Extendible RISC-V Microcontroller for the Exploration of Ultra-Low-Power Edge Accelerators}, + author={Simone Machetti and Pasquale Davide Schiavone and Thomas Christoph Müller and Miguel Peón-Quirós and David Atienza}, + year={2024}, + eprint={2401.05548}, + archivePrefix={arXiv}, + primaryClass={cs.AR} +} +``` \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/block_diagrams/core_v_mini_mcu.svg b/hw/vendor/esl_epfl_x_heep/block_diagrams/core_v_mini_mcu.svg deleted file mode 100644 index dbdc7cec..00000000 --- a/hw/vendor/esl_epfl_x_heep/block_diagrams/core_v_mini_mcu.svg +++ /dev/null @@ -1,3553 +0,0 @@ - -image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MMMSSSMSSSSSSMSSS_FLASHM_FLASHSSMMMSSSSSSSSSSSSSSSSPOWERMANAGERTIMER 2TIMER 3DMABOOT ROMSOC CTRLSPI HOSTTIMER 0TIMER 1SPISUBSYSTEMUARTGPIO AOFAST INTRCTRLPLICPERIPHERAL SUBSYSTEMAO PERIPHERAL SUBSYSTEMI2CGPIOBUS SUBSYSTEMCPUSUBSYSTEMMEMORY SUBSYSTEMCORE_V_MINI_MCUDEBUGSUBSYSTEMRAM 0INSTRDATASSRAM 1RAM 2RAM 3TCKTMSTDIRAM 4RAM 5RAM 6RAM 7TDOTRSTEXT PERIPHBOOTSELECTEXECUTEFROMFLASHEXTMASTERSCORE INSTRIO[7:0]TXRXSCK_FCS_FSD_FSDCSSCKIO[31:8]SDASCLEXIT VALUEEXIT VALIDMPAD PERIPHMMMMMCORE DATADEBUGDMA READDMA WRITEMDMA ADDR diff --git a/hw/vendor/esl_epfl_x_heep/block_diagrams/x-heep.svg b/hw/vendor/esl_epfl_x_heep/block_diagrams/x-heep.svg deleted file mode 100644 index 93b2ed0d..00000000 --- a/hw/vendor/esl_epfl_x_heep/block_diagrams/x-heep.svg +++ /dev/null @@ -1,2461 +0,0 @@ - -image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CORE_V_MINI_MCUPAD CONTROLX-HEEPPADRINGTXRXSCKCSSDSCK_FEXIT VALIDEXIT VALIDCS_FSD_FIO[29:0]IO[30]IO[31]MSSCLSDATXRXSCK_FCS_FSD_FSCKCSSDIO[29:0]SDASCLBOOTSELECTEXECUTEFROMFLASHEXIT VALUE diff --git a/hw/vendor/esl_epfl_x_heep/configs/ci.hjson b/hw/vendor/esl_epfl_x_heep/configs/ci.hjson new file mode 100644 index 00000000..011fe3e8 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/configs/ci.hjson @@ -0,0 +1,23 @@ +{ + bus_type: "onetoM", + ram_banks: { + code_and_data: { + num: 6 + sizes: 32 + } + } + + linker_sections: + [ + { + name: code + start: 0 + #minimum size for freeRTOS and clang + size: 0x00000E800 + }, + { + name: data + start: 0x00000E800 + } + ] +} \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/configs/example.py b/hw/vendor/esl_epfl_x_heep/configs/example.py new file mode 100644 index 00000000..b9e3faf2 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/configs/example.py @@ -0,0 +1,18 @@ +from x_heep_gen.linker_section import LinkerSection +from x_heep_gen.system import XHeep, BusType + +def config(): + system = XHeep(BusType.NtoM) + system.add_ram_banks([32] * 2) + system.add_ram_banks_il(2, 64, "data_interleaved") + + system.add_linker_section(LinkerSection.by_size("code", 0, 0x00000C800)) + system.add_linker_section(LinkerSection("data", 0x00000C800, None)) + + # Here the system is build, + # The missing gaps are filled, like the missing end address of the data section. + system.build() + if not system.validate(): + raise RuntimeError("there are errors") + + return system diff --git a/hw/vendor/esl_epfl_x_heep/configs/example_interleaved.hjson b/hw/vendor/esl_epfl_x_heep/configs/example_interleaved.hjson new file mode 100644 index 00000000..35d380c6 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/configs/example_interleaved.hjson @@ -0,0 +1,40 @@ +{ + bus_type: "NtoM", + ram_banks: { + code_and_data: { + sizes: 64 + } + more_data: { + type: continuous + num: 2 + sizes: 32 + } + data_interleaved: { + auto_section: auto + // the name is used by example_matadd_interleaved as .xheep_data_interleaved + type: interleaved + num: 4 + size: 16 + } + data_interleaved_2: { + auto_section: auto + type: interleaved + num: 2 + size: 16 + } + } + + linker_sections: + [ + { + name: code + start: 0 + // minimum size for freeRTOS and clang + size: 0x00000E800 + }, + { + name: data + start: 0x00000E800 + } + ] +} \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/configs/general.hjson b/hw/vendor/esl_epfl_x_heep/configs/general.hjson new file mode 100644 index 00000000..ec460f78 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/configs/general.hjson @@ -0,0 +1,24 @@ +{ + ram_address: 0 + bus_type: "onetoM", + ram_banks: { + code_and_data: { + num: 8 + sizes: [32] + } + } + + linker_sections: + [ + { + name: code + start: 0 + #minimum size for freeRTOS and clang + size: 0x00000E800 + }, + { + name: data + start: 0x00000E800 + } + ] +} \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/configs/testall.hjson b/hw/vendor/esl_epfl_x_heep/configs/testall.hjson new file mode 100644 index 00000000..3e4bad9a --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/configs/testall.hjson @@ -0,0 +1,23 @@ +{ + bus_type: "onetoM", + ram_banks: { + code_and_data: { + num: 3 + sizes: 32 + } + } + + linker_sections: + [ + { + name: code + start: 0 + #minimum size for freeRTOS and clang + size: 0x00000E800 + }, + { + name: data + start: 0x00000E800 + } + ] +} \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu-fpga.core b/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu-fpga.core new file mode 100644 index 00000000..38663aea --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu-fpga.core @@ -0,0 +1,72 @@ +CAPI=2: + +# Copyright 2024 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +name: openhwgroup.org:systems:core-v-mini-mcu-fpga +description: CORE-V MINI-MCU FPGA related files. + +filesets: + rtl-fpga: + depend: + - x-heep::packages + files: + - hw/fpga/sram_wrapper.sv + file_type: systemVerilogSource + + ip-fpga: + files: + - hw/fpga/scripts/generate_sram.tcl: { file_type: tclSource } + - hw/fpga/prim_xilinx_clk.sv: { file_type: systemVerilogSource } + - hw/fpga/cv32e40p_xilinx_clock_gate.sv: { file_type: systemVerilogSource } + - hw/fpga/cv32e40x_xilinx_clock_gate.sv: { file_type: systemVerilogSource } + - hw/fpga/cve2_xilinx_clock_gate.sv: { file_type: systemVerilogSource } + - hw/fpga/cv32e40px_xilinx_clock_gate.sv: { file_type: systemVerilogSource } + - hw/fpga/pad_cell_input_xilinx.sv: { file_type: systemVerilogSource } + - hw/fpga/pad_cell_output_xilinx.sv: { file_type: systemVerilogSource } + - hw/fpga/pad_cell_inout_xilinx.sv: { file_type: systemVerilogSource } + - hw/fpga/pad_cell_bypass_input_xilinx.sv: { file_type: systemVerilogSource } + - hw/fpga/pad_cell_bypass_output_xilinx.sv: { file_type: systemVerilogSource } + + ip-fpga-pynq-z2: + files: + - hw/fpga/scripts/pynq-z2/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } + + ip-fpga-nexys: + files: + - hw/fpga/scripts/nexys/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } + + ip-fpga-zcu104: + files: + - hw/fpga/scripts/zcu104/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } + + xdc-fpga-nexys: + files: + - hw/fpga/constraints/nexys/pin_assign.xdc + - hw/fpga/constraints/nexys/constraints.xdc + file_type: xdc + + xdc-fpga-pynq-z2: + files: + - hw/fpga/constraints/pynq-z2/pin_assign.xdc + - hw/fpga/constraints/pynq-z2/constraints.xdc + file_type: xdc + + xdc-fpga-zcu104: + files: + - hw/fpga/constraints/zcu104/pin_assign.xdc + file_type: xdc + + +targets: + default: &default_target + filesets: + - rtl-fpga + - ip-fpga + - target_pynq-z2 ? (ip-fpga-pynq-z2) + - target_pynq-z2 ? (xdc-fpga-pynq-z2) + - target_nexys-a7-100t ? (ip-fpga-nexys) + - target_nexys-a7-100t ? (xdc-fpga-nexys) + - target_zcu104 ? (ip-fpga-zcu104) + - target_zcu104 ? (xdc-fpga-zcu104) diff --git a/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.core b/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.core index 7bebad44..aef1f20e 100644 --- a/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.core +++ b/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.core @@ -13,7 +13,7 @@ filesets: - x-heep::packages - openhwgroup.org:ip:cv32e40p - openhwgroup.org:ip:cv32e40x - - openhwgroup.org:ip:cve2 + - openhwgroup:cve2:cve2_top - esl_epfl:ip:cv32e40px - pulp-platform.org:ip:gpio - pulp-platform.org::common_cells @@ -30,6 +30,7 @@ filesets: - x-heep:obi_spimemio:0.1.0 - x-heep:ip:boot_rom - x-heep:ip:dma + - x-heep:ip:dma_subsystem - x-heep:ip:i2s - x-heep:ip:power_manager - x-heep:ip:fast_intr_ctrl @@ -84,6 +85,7 @@ filesets: - hw/ip/boot_rom/boot_rom.vlt - hw/ip/obi_spimemio/obi_spimemio.vlt - hw/ip/dma/dma.vlt + - hw/ip/dma_subsystem/dma_subsystem.vlt - hw/ip/pdm2pcm/pdm2pcm.vlt - hw/ip_examples/pdm2pcm_dummy/pdm2pcm_dummy.vlt - hw/ip/power_manager/power_manager.vlt @@ -95,36 +97,12 @@ filesets: file_type: vlt rtl-fpga: + depend: + - openhwgroup.org:systems:core-v-mini-mcu-fpga files: - hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv - - hw/fpga/sram_wrapper.sv file_type: systemVerilogSource - ip-fpga: - files: - - hw/fpga/scripts/xilinx_generate_clk_wizard.tcl: { file_type: tclSource } - - hw/fpga/scripts/generate_sram.tcl: { file_type: tclSource } - - hw/fpga/prim_xilinx_clk.sv: { file_type: systemVerilogSource } - - hw/fpga/cv32e40p_xilinx_clock_gate.sv: { file_type: systemVerilogSource } - - hw/fpga/cv32e40x_xilinx_clock_gate.sv: { file_type: systemVerilogSource } - - hw/fpga/cve2_xilinx_clock_gate.sv: { file_type: systemVerilogSource } - - hw/fpga/cv32e40px_xilinx_clock_gate.sv: { file_type: systemVerilogSource } - - hw/fpga/pad_cell_input_xilinx.sv: { file_type: systemVerilogSource } - - hw/fpga/pad_cell_output_xilinx.sv: { file_type: systemVerilogSource } - - hw/fpga/pad_cell_inout_xilinx.sv: { file_type: systemVerilogSource } - - hw/fpga/pad_cell_bypass_input_xilinx.sv: { file_type: systemVerilogSource } - - hw/fpga/pad_cell_bypass_output_xilinx.sv: { file_type: systemVerilogSource } - - fpga-arm-emulation: - depend: - - pulp-platform.org::axi_spi_slave - files: - - linux_femu/scripts/xilinx_generate_processing_system.tcl: {file_type: tclSource} - - linux_femu/rtl/axi_address_hijacker.v: {file_type: verilogSource} - - linux_femu/rtl/linux_femu.sv: {file_type: systemVerilogSource} - - linux_femu/constraints/pin_assign.xdc: {file_type: xdc} - - linux_femu/constraints/constraints.xdc: {file_type: xdc} - ip-asic: depend: - technology::prim_mytech @@ -143,23 +121,6 @@ filesets: files: - hw/asic/sky130/sky130_sram_4kbyte_1rw_32x1024_8_TT_1p8V_25C.lib : { copyto: lib/sky130_sram_4kbyte_1rw_32x1024_8_TT_1p8V_25C.lib } - xdc-fpga-nexys: - files: - - hw/fpga/constraints/nexys/pin_assign.xdc - - hw/fpga/constraints/nexys/constraints.xdc - file_type: xdc - - xdc-fpga-pynq-z2: - files: - - hw/fpga/constraints/pynq-z2/pin_assign.xdc - - hw/fpga/constraints/pynq-z2/constraints.xdc - file_type: xdc - - netlist-fpga: - files: - - build/openhwgroup.org_systems_core-v-mini-mcu_0/nexys-a7-100t-vivado/core_v_mini_mcu_xiling_postsynth.v - file_type: verilogSource - # Scripts for hooks post_build_modelsim_scripts: files: @@ -194,6 +155,8 @@ filesets: tb-verilator: files: + - tb/XHEEP_CmdLineOptions.hh: { is_include_file: true } + - tb/XHEEP_CmdLineOptions.cpp - tb/tb_top.cpp file_type: cppSource @@ -202,6 +165,14 @@ filesets: - tb/tb_top.sv file_type: systemVerilogSource + tb-sc-verilator: + files: + - tb/XHEEP_CmdLineOptions.hh: { is_include_file: true } + - tb/XHEEP_CmdLineOptions.cpp + - tb/tb_sc_top.cpp + file_type: cppSource + + openroad_base_files: files: - flow/OpenROAD-flow-scripts/flow/Makefile : {file_type: Makefile} @@ -262,7 +233,19 @@ parameters: datatype: bool paramtype: vlogdefine default: false - FPGA_NETLIST: + SIM_SYSTEMC: + datatype: bool + paramtype: vlogdefine + default: false + FPGA_SYNTHESIS: + datatype: bool + paramtype: vlogdefine + default: false + FPGA_NEXYS: + datatype: bool + paramtype: vlogdefine + default: false + FPGA_ZCU104: datatype: bool paramtype: vlogdefine default: false @@ -302,6 +285,8 @@ targets: - files_rtl_generic - target_sim ? (rtl-simulation) - target_sim ? (tool_verilator? (files_verilator_waiver)) + - target_sim_sc ? (rtl-simulation) + - target_sim_sc ? (tool_verilator? (files_verilator_waiver)) toplevel: [core_v_mini_mcu] sim: @@ -314,13 +299,17 @@ targets: - tool_modelsim? (pre_patch_modelsim_Makefile) - tool_vcs? (cfile_uartdpi) - tool_vcs? (pre_build_remote_bitbang) + - tool_xcelium? (pre_build_remote_bitbang) + - tool_xcelium? (pre_build_uartdpi) - tool_verilator? (tb-verilator) - tool_modelsim? (tb-sv) - tool_vcs? (tb-sv) + - tool_xcelium? (tb-sv) - "!integrated_heep? (x_heep_system)" toplevel: - tool_modelsim? (tb_top) - tool_vcs? (tb_top) + - tool_xcelium? (tb_top) - tool_verilator? (testharness) hooks: pre_build: @@ -328,6 +317,8 @@ targets: - tool_modelsim? (pre_build_remote_bitbang) - tool_modelsim? (pre_patch_modelsim_Makefile) # this is required by Questa 2020 on - ams_sim? (pre_patch_vcs_ams_Makefile) + - tool_xcelium? (pre_build_uartdpi) + - tool_xcelium? (pre_build_remote_bitbang) parameters: - COREV_PULP - FPU @@ -342,6 +333,7 @@ targets: - -override_timescale 1ns/1ps - -suppress vlog-2583 - -suppress vlog-2577 + - -suppress vlog-2720 - -pedanticerrors - -define MODELSIM vsim_options: @@ -364,6 +356,12 @@ targets: - -LDFLAGS "-pthread -lutil" - +lint=TFIPC-L - -V + xcelium: + xrun_options: + - -vtimescale 1ns/10ps + - -sv_lib ../../../hw/vendor/lowrisc_opentitan/hw/dv/dpi/uartdpi/uartdpi.so + - -sv_lib ../../../hw/vendor/pulp_platform_pulpissimo/rtl/tb/remote_bitbang/librbs.so + - -define XCELIUM verilator: mode: cc verilator_options: @@ -380,23 +378,60 @@ targets: - '-LDFLAGS "-pthread -lutil -lelf"' - "-Wall" + sim_sc: + <<: *default_target + default_tool: modelsim + filesets_append: + - tb-utils + - tool_verilator? (tb-sc-verilator) + - "!integrated_heep? (x_heep_system)" + toplevel: + - tool_verilator? (testharness) + parameters: + - COREV_PULP + - FPU + - JTAG_DPI + - X_EXT + - USE_EXTERNAL_DEVICE_EXAMPLE + - USE_UPF + - REMOVE_OBI_FIFO + - SIM_SYSTEMC=true + tools: + verilator: + mode: sc + verilator_options: + - '--sc' + - '--trace' + - '--trace-structs' + - '--trace-params' + - '--trace-max-array 1024' + - '--x-assign unique' + - '--x-initial unique' + - '--exe tb_sc_top.cpp' + - '-CFLAGS "-std=c++11 -Wall -g -fpermissive"' + - '-LDFLAGS "-pthread -lutil -lelf $(SYSTEMC_LIBDIR)/libsystemc.a"' + - "-Wall" + nexys-a7-100t: <<: *default_target default_tool: vivado description: Digilent Nexys-A7-100T Board filesets_append: + - x_heep_system - rtl-fpga - - ip-fpga - - xdc-fpga-nexys parameters: - COREV_PULP - FPU - X_EXT - SYNTHESIS=true - REMOVE_OBI_FIFO + - FPGA_SYNTHESIS=true + - FPGA_NEXYS=true tools: vivado: part: xc7a100tcsg324-1 + board_part: digilentinc.com:nexys-a7-100t:part0:1.3 + board_repo_paths: [../../../hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files] toplevel: [xilinx_core_v_mini_mcu_wrapper] pynq-z2: @@ -406,40 +441,42 @@ targets: filesets_append: - x_heep_system - rtl-fpga - - ip-fpga - - xdc-fpga-pynq-z2 parameters: - COREV_PULP - FPU - X_EXT - SYNTHESIS=true - REMOVE_OBI_FIFO + - FPGA_SYNTHESIS=true tools: vivado: part: xc7z020clg400-1 + board_part: tul.com.tw:pynq-z2:part0:1.0 + board_repo_paths: [../../../hw/fpga/board_files/vendor/esl_epfl_pynq_z2_board_files] toplevel: [xilinx_core_v_mini_mcu_wrapper] - pynq-z2-arm-emulation: + zcu104: <<: *default_target default_tool: vivado - description: TUL Pynq-Z2 Board + description: ZCU104 Evaluation Board filesets_append: - x_heep_system - rtl-fpga - - ip-fpga - - fpga-arm-emulation parameters: - COREV_PULP - FPU - X_EXT - SYNTHESIS=true - REMOVE_OBI_FIFO + - FPGA_SYNTHESIS=true + - FPGA_ZCU104=true tools: vivado: - part: xc7z020clg400-1 - jobs: 4 - toplevel: [linux_femu] - + part: xczu7ev-ffvc1156-2-e + board_part: xilinx.com:zcu104:part0:1.0 + board_repo_paths: [../../../hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files] + toplevel: [xilinx_core_v_mini_mcu_wrapper] + asic_synthesis: <<: *default_target default_tool: design_compiler diff --git a/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.dc.upf.tpl b/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.dc.upf.tpl new file mode 100644 index 00000000..b08abad8 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.dc.upf.tpl @@ -0,0 +1,159 @@ +upf_version 2.1 + +set_design_top core_v_mini_mcu +set_scope . + + +<%text> +##################### +## POWER DOMAINS ## +##################### +\ + +create_power_domain PD_TOP -include_scope +create_power_domain PD_CPU -elements {cpu_subsystem_i} +create_power_domain PD_PERIP_SUBS -elements {peripheral_subsystem_i} +% for bank in xheep.iter_ram_banks(): +create_power_domain PD_MEM_BANK_${bank.name()} -elements {memory_subsystem_i/ram${bank.name()}_i} +% endfor + + +<%text> +#################### +## POWER STATES ## +#################### +\ + +add_power_state PD_TOP.primary -state TOP_ON <%text>\ + {-supply_expr {power == `{FULL_ON, 1.2} && ground == `{FULL_ON, 0.0}}} + +add_power_state PD_CPU.primary -state CPU_ON <%text>\ + {-supply_expr {power == `{FULL_ON, 1.2} && ground == `{FULL_ON, 0.0}}} + +add_power_state PD_CPU.primary -state CPU_OFF <%text>\ + {-supply_expr {power == `{OFF} && ground == `{FULL_ON, 0.0}}} -simstate CORRUPT + +add_power_state PD_PERIP_SUBS.primary -state PERIP_SUBS_ON <%text>\ + {-supply_expr {power == `{FULL_ON, 1.2} && ground == `{FULL_ON, 0.0}}} + +add_power_state PD_PERIP_SUBS.primary -state PERIP_SUBS_OFF <%text>\ + {-supply_expr {power == `{OFF} && ground == `{FULL_ON, 0.0}}} -simstate CORRUPT + +% for bank in xheep.iter_ram_banks(): +add_power_state PD_MEM_BANK_${bank.name()}.primary -state MEM_BANK_${bank.name()}_ON <%text>\ + {-supply_expr {power == `{FULL_ON, 1.2} && ground == `{FULL_ON, 0.0}}} + +add_power_state PD_MEM_BANK_${bank.name()}.primary -state MEM_BANK_${bank.name()}_OFF <%text>\ + {-supply_expr {power == `{OFF} && ground == `{FULL_ON, 0.0}}} -simstate CORRUPT + +% endfor + +<%text> +################### +## SUPPLY NETS ## +################### +\ + +create_supply_port VDD -direction in +create_supply_port VSS -direction in + +create_supply_net VDD +create_supply_net VSS + +connect_supply_net VDD -ports VDD +connect_supply_net VSS -ports VSS + +create_supply_set PD_TOP.primary -function {power VDD} -function {ground VSS} -update + +create_supply_net VDD_CPU +create_supply_set PD_CPU.primary -function {power VDD_CPU} -function {ground VSS} -update + +create_supply_net VDD_PERIP_SUBS +create_supply_set PD_PERIP_SUBS.primary -function {power VDD_PERIP_SUBS} -function {ground VSS} -update + +% for bank in xheep.iter_ram_banks(): +create_supply_net VDD_MEM_BANK_${bank.name()} +create_supply_set PD_MEM_BANK_${bank.name()}.primary -function {power VDD_MEM_BANK_${bank.name()}} -function {ground VSS} -update + +% endfor + +<%text> +################ +## SWITCHES ## +################ +\ + +create_power_switch switch_PD_CPU <%text>\ + -supply_set PD_TOP.primary <%text>\ + -domain PD_CPU <%text>\ + -input_supply_port {sw_in VDD} <%text>\ + -output_supply_port {sw_out VDD_CPU} <%text>\ + -control_port {sw_ctrl ao_peripheral_subsystem_i/cpu_subsystem_pwr_ctrl_o<%text>\[pwrgate_en_n<%text>\]} <%text>\ + -ack_port {sw_ack ao_peripheral_subsystem_i/cpu_subsystem_pwr_ctrl_i<%text>\[pwrgate_ack_n<%text>\]} <%text>\ + -on_state {on_state sw_in {sw_ctrl}} <%text>\ + -off_state {off_state {!sw_ctrl}} + +create_power_switch switch_PD_PERIP_SUBS <%text>\ + -supply_set PD_TOP.primary <%text>\ + -domain PD_PERIP_SUBS <%text>\ + -input_supply_port {sw_in VDD} <%text>\ + -output_supply_port {sw_out VDD_PERIP_SUBS} <%text>\ + -control_port {sw_ctrl ao_peripheral_subsystem_i/peripheral_subsystem_pwr_ctrl_o<%text>\[pwrgate_en_n<%text>\]} <%text>\ + -ack_port {sw_ack ao_peripheral_subsystem_i/peripheral_subsystem_pwr_ctrl_i<%text>\[pwrgate_ack_n<%text>\]} <%text>\ + -on_state {on_state sw_in {sw_ctrl}} <%text>\ + -off_state {off_state {!sw_ctrl}} + +% for bank in xheep.iter_ram_banks(): +create_power_switch switch_PD_MEM_BANK_${bank.name()} <%text>\ + -supply_set PD_TOP.primary <%text>\ + -domain PD_MEM_BANK_${bank.name()} <%text>\ + -input_supply_port {sw_in VDD} <%text>\ + -output_supply_port {sw_out VDD_MEM_BANK_${bank.name()}} <%text>\ + -control_port {sw_ctrl ao_peripheral_subsystem_i/memory_subsystem_pwr_ctrl_o[${bank.name()}]<%text>\[pwrgate_en_n<%text>\]} <%text>\ + -ack_port {sw_ack ao_peripheral_subsystem_i/memory_subsystem_pwr_ctrl_i[${bank.name()}]<%text>\[pwrgate_ack_n<%text>\]} <%text>\ + -on_state {on_state sw_in {sw_ctrl}} <%text>\ + -off_state {off_state {!sw_ctrl}} + +% endfor + +<%text> +################# +## ISOLATION ## +################# +\ + +set_isolation cpu_iso <%text>\ + -domain PD_CPU <%text>\ + -isolation_power_net VDD <%text>\ + -isolation_ground_net VSS <%text>\ + -isolation_signal ao_peripheral_subsystem_i/cpu_subsystem_pwr_ctrl_o<%text>\[isogate_en_n<%text>\] <%text>\ + -isolation_sense low <%text>\ + -clamp_value 0 <%text>\ + -applies_to outputs <%text>\ + -name_prefix cpu_iso_cell <%text>\ + -location parent + +set_isolation perip_subs_iso <%text>\ + -domain PD_PERIP_SUBS <%text>\ + -isolation_power_net VDD <%text>\ + -isolation_ground_net VSS <%text>\ + -isolation_signal ao_peripheral_subsystem_i/peripheral_subsystem_pwr_ctrl_o<%text>\[isogate_en_n<%text>\] <%text>\ + -isolation_sense low <%text>\ + -clamp_value 0 <%text>\ + -applies_to outputs <%text>\ + -name_prefix cpu_iso_cell <%text>\ + -location parent + +% for bank in xheep.iter_ram_banks(): +set_isolation mem_bank_${bank.name()}_iso <%text>\ + -domain PD_MEM_BANK_${bank.name()} <%text>\ + -isolation_power_net VDD <%text>\ + -isolation_ground_net VSS <%text>\ + -isolation_signal ao_peripheral_subsystem_i/memory_subsystem_pwr_ctrl_o[${bank.name()}]<%text>\[isogate_en_n<%text>\] <%text>\ + -isolation_sense low <%text>\ + -clamp_value 0 <%text>\ + -elements {memory_subsystem_i/ram${bank.name()}_i/rdata_o} <%text>\ + -name_prefix cpu_iso_cell <%text>\ + -location parent + +% endfor diff --git a/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.upf.tpl b/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.upf.tpl index 5d687f9a..d7e0f6f1 100644 --- a/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.upf.tpl +++ b/hw/vendor/esl_epfl_x_heep/core-v-mini-mcu.upf.tpl @@ -13,8 +13,8 @@ set_scope . create_power_domain PD_TOP -include_scope create_power_domain PD_CPU -elements {cpu_subsystem_i} create_power_domain PD_PERIP_SUBS -elements {peripheral_subsystem_i} -% for bank in range(ram_numbanks): -create_power_domain PD_MEM_BANK_${bank} -elements {memory_subsystem_i/gen_sram[${bank}].ram_i} +% for bank in xheep.iter_ram_banks(): +create_power_domain PD_MEM_BANK_${bank.name()} -elements {memory_subsystem_i/ram${bank.name()}_i} % endfor @@ -39,11 +39,11 @@ add_power_state PD_PERIP_SUBS.primary -state PERIP_SUBS_ON <%text>\ add_power_state PD_PERIP_SUBS.primary -state PERIP_SUBS_OFF <%text>\ {-supply_expr {power == `{OFF} && ground == `{FULL_ON, 0.0}}} -simstate CORRUPT -% for bank in range(ram_numbanks): -add_power_state PD_MEM_BANK_${bank}.primary -state MEM_BANK_${bank}_ON <%text>\ +% for bank in xheep.iter_ram_banks(): +add_power_state PD_MEM_BANK_${bank.name()}.primary -state MEM_BANK_${bank.name()}_ON <%text>\ {-supply_expr {power == `{FULL_ON, 1.2} && ground == `{FULL_ON, 0.0}}} -add_power_state PD_MEM_BANK_${bank}.primary -state MEM_BANK_${bank}_OFF <%text>\ +add_power_state PD_MEM_BANK_${bank.name()}.primary -state MEM_BANK_${bank.name()}_OFF <%text>\ {-supply_expr {power == `{OFF} && ground == `{FULL_ON, 0.0}}} -simstate CORRUPT % endfor @@ -71,9 +71,9 @@ create_supply_set PD_CPU.primary -function {power VDD_CPU} -function {ground VSS create_supply_net VDD_PERIP_SUBS create_supply_set PD_PERIP_SUBS.primary -function {power VDD_PERIP_SUBS} -function {ground VSS} -update -% for bank in range(ram_numbanks): -create_supply_net VDD_MEM_BANK_${bank} -create_supply_set PD_MEM_BANK_${bank}.primary -function {power VDD_MEM_BANK_${bank}} -function {ground VSS} -update +% for bank in xheep.iter_ram_banks(): +create_supply_net VDD_MEM_BANK_${bank.name()} +create_supply_set PD_MEM_BANK_${bank.name()}.primary -function {power VDD_MEM_BANK_${bank.name()}} -function {ground VSS} -update % endfor @@ -103,14 +103,14 @@ create_power_switch switch_PD_PERIP_SUBS <%text>\ -on_state {on_state sw_in {sw_ctrl}} <%text>\ -off_state {off_state {!sw_ctrl}} -% for bank in range(ram_numbanks): -create_power_switch switch_PD_MEM_BANK_${bank} <%text>\ +% for bank in xheep.iter_ram_banks(): +create_power_switch switch_PD_MEM_BANK_${bank.name()} <%text>\ -supply_set PD_TOP.primary <%text>\ - -domain PD_MEM_BANK_${bank} <%text>\ + -domain PD_MEM_BANK_${bank.name()} <%text>\ -input_supply_port {sw_in VDD} <%text>\ - -output_supply_port {sw_out VDD_MEM_BANK_${bank}} <%text>\ - -control_port {sw_ctrl memory_subsystem_banks_powergate_switch_no[${bank}]} <%text>\ - -ack_port {sw_ack memory_subsystem_banks_powergate_switch_ack_ni[${bank}]} <%text>\ + -output_supply_port {sw_out VDD_MEM_BANK_${bank.name()}} <%text>\ + -control_port {sw_ctrl memory_subsystem_banks_powergate_switch_n[${bank.name()}]} <%text>\ + -ack_port {sw_ack memory_subsystem_i.ram${bank.name()}_i.pwrgate_ack_no} <%text>\ -on_state {on_state sw_in {sw_ctrl}} <%text>\ -off_state {off_state {!sw_ctrl}} @@ -144,15 +144,15 @@ set_isolation perip_subs_iso <%text>\ -name_prefix cpu_iso_cell <%text>\ -location parent -% for bank in range(ram_numbanks): -set_isolation mem_bank_${bank}_iso <%text>\ - -domain PD_MEM_BANK_${bank} <%text>\ +% for bank in xheep.iter_ram_banks(): +set_isolation mem_bank_${bank.name()}_iso <%text>\ + -domain PD_MEM_BANK_${bank.name()} <%text>\ -isolation_power_net VDD <%text>\ -isolation_ground_net VSS <%text>\ - -isolation_signal memory_subsystem_banks_powergate_iso_n[${bank}] <%text>\ + -isolation_signal memory_subsystem_banks_powergate_iso_n[${bank.name()}] <%text>\ -isolation_sense low <%text>\ -clamp_value 0 <%text>\ - -applies_to outputs <%text>\ + -elements {memory_subsystem_i/ram${bank.name()}_i/rdata_o} <%text>\ -name_prefix cpu_iso_cell <%text>\ -location parent diff --git a/hw/vendor/esl_epfl_x_heep/docs/requirements.txt b/hw/vendor/esl_epfl_x_heep/docs/requirements.txt index cf9a675b..a4cd7e7b 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/requirements.txt +++ b/hw/vendor/esl_epfl_x_heep/docs/requirements.txt @@ -1,2 +1,3 @@ sphinx-rtd-theme -myst-parser \ No newline at end of file +myst-parser +sphinxcontrib-apidoc diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/Configuration/Configuration.rst b/hw/vendor/esl_epfl_x_heep/docs/source/Configuration/Configuration.rst new file mode 100644 index 00000000..c18a4e26 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/docs/source/Configuration/Configuration.rst @@ -0,0 +1,172 @@ +Configuration +============= + +Project Configuration +--------------------- +The project can be configured either by a hjson file or a python script. +The default configurations and examples are located in the `config` directory. + +Hjson Configuration File +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. literalinclude:: ../../../configs/example_interleaved.hjson + :language: js + +Bus Type Configuration +^^^^^^^^^^^^^^^^^^^^^^ +The bus type can either be configured to `NtoM` or `onetoM`. + +Ram Bank Configuration +^^^^^^^^^^^^^^^^^^^^^^ + +The system can be configured with banks of different sizes. The sizes should be a power of two in kiB. +All banks are configured in one continuous address region. + + +To configure interleaved banks the number and the size of the banks have to be provided. +The following restrictions apply: All banks must have the same size and a power of two banks must be configured. + + +For continuous banks the default mode, only the `sizes` filed is required. +It can be either the size in kiB of a single bank, +a dictionary of the same format containing more banks, or a list of multiple entries. +If the `num` field is also provided the configuration in the `sizes` field is repeated `num` times. + +.. code:: js + + ram_banks: { + code: {sizes: 64} // configure just one bank + + data: { + type: continuous // the default, can be omitted + num: 2 + sizes: 32 + } + + alt_data: {sizes: [32, 32]} // the same as data but with a list + + more_complex: { + // This also works recursively so we can easily have different sizes of banks + // and in bigger numbers without listing them all one by one. + sizes: [ + { + num: 4 + sizes: 8 + }, + { + num: 16 + sizes: 4 + }, + ] + } + + } + + +Linker Section Configuration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The linker script sections can be configured in two ways. +Either a section can be matched with a group of ram banks +or it can be manually defined. + +To automatically add a section the entry `auto_section: auto` should be added to the banks. +It will add a section that matches the banks exactly, it can only be used in the non recursive part. +The name of the section is set with the name of the group of banks. + +When manually setting the the linker section the name and the start address have to be provided. +Additionally the end is either provided by it's address or by the size of the section. +If no end is provided the end is inferred by the start of the next linker section. +Or if no section follows, the end address of the last ram bank. + +Both configuration types can be freely combined as long as no section overlap. +All sections will e sorted by the configuration system. + +The first two sections should always be code and data. +The other name can be used in code with a `.xheep_` prefix, like in `example_matadd_interleaved` + +.. code:: c + + int32_t __attribute__((section(".xheep_data_interleaved"))) m_c[16*16]; + +.. code:: js + + { + ram_address: 0 + bus_type: "onetoM", + ram_banks: { + code_and_data: { + num: 2 + sizes: [32] + } + i_am_a_section_name: { + auto_section: auto + sizes: 16 + } + } + + linker_sections: + [ + { + name: code + start: 0 + + // Alternatively the end tag can be used to provide the end. + size: 0x00000C800 + }, + { + name: data + start: 0x00000C800 + // The end of this section will be at the beginning of the next. + // In this example the next section is i_am_a_section_name + } + ] + } + + + + +Python Configuration +~~~~~~~~~~~~~~~~~~~~ + +The same can be done by using a python script + +.. literalinclude:: ../../../configs/example.py + :language: python + + +The script should include a config function that return an :py:class:`x_heep_gen.system.XHeep` instance. +The configuration is simmilar to the hjson one. The order in which sections are added is also the one used in hardware. +The script writer is responsible to call :py:meth:`x_heep_gen.system.XHeep.build` and :py:meth:`x_heep_gen.system.XHeep.validate` and to raise an error in case of failure. +The first does make the system ready to be used and the second does check for errors in the configuration. + + + +Select Configuration File +~~~~~~~~~~~~~~~~~~~~~~~~~ + +To configure the system call + +.. code:: bash + + make mcu-gen X_HEEP_CFG=configs/name_of_file.hjson + + + +Other configurations +~~~~~~~~~~~~~~~~~~~~ + +The pads are configured in `pad_cfg.hjson`. + +One part of the configuration is in `mcu_cfg.hjson`. + +Additionally if a `hjson` file is ussed for configuration the following parameters can be set to the make command to override the configuration: + +- `BUS=NtoM,onetoM` +- `MEMORY_BANKS=integer` +- `MEMORY_BANKS_IL=integer` + +They will replace the configuration used in the configuration file. +When one parameter is not provided the configuration files value is used. +The memory banks configured this way will only be of size 32kiB. +For compatibility reasons `MEMORY_BANKS` does not create linker sections while `MEMORY_BANKS_IL` does create a linker section. + diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/AnalogMixedSignal.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/AnalogMixedSignal.md index 8ba4ed5c..5e2d0bb4 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/AnalogMixedSignal.md +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/AnalogMixedSignal.md @@ -1,4 +1,4 @@ -# integrate Analog / Mixed-Signal simulations +# Integrate Analog / Mixed-Signal simulations ## About @@ -68,7 +68,7 @@ The example AMS peripheral used by simulations of X-HEEP is located in `hw/ip_ex ### The repository's example SPICE files -

+

An example `adc.sp` file can be found in `hw/ip_examples/ams/analog`. This is a 1-bit ADC with a threshold that is configured through the 2-bit wide SEL input: an input of 00, 01, 10 and 11 will provide a threshold of 20%, 40%, 60% and 80% of VDD (1.2V) respectively. The input signal of the ADC is a sine wave with a peak-to-peak amplitude of 1.2V directly placed inside the SPICE netlist. diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/CompileMakefile b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/CompileMakefile deleted file mode 100644 index c0aab16c..00000000 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/CompileMakefile +++ /dev/null @@ -1,334 +0,0 @@ -# compile with Makefile - -You can compile the example applications and the platform using the Makefile. Type 'make help' or 'make' for more information. Moreover, please, check the different 'clean' commands to verify that you are using the corret one. - -## Generate core-v-mini-mcu package - -First, you have to generate the SystemVerilog package and C header file of the core-v-mini-mcu: - -``` -make mcu-gen -``` - -To change the default cpu type (i.e., cv32e20), the default bus type (i.e., onetoM), -the default continuous memory size (i.e., 2 continuous banks) or the default interleaved memory size (i.e., 0 interleaved banks): - -``` -make mcu-gen CPU=cv32e40p BUS=NtoM MEMORY_BANKS=12 MEMORY_BANKS_IL=4 -``` - -The last command generates x-heep with the cv32e40p core, with a parallel bus, and 16 memory banks (12 continuous and 4 interleaved), -each 32KB, for a total memory of 512KB. - -## Compiling Software - -Don't forget to set the `RISCV` env variable to the compiler folder (without the `/bin` included). -To run 'hello world' application, just type 'make app'. - -``` -make app -``` - -To run any other application, please use the following command with appropiate parameters: - -``` -app PROJECT= TARGET=sim(default),pynq-z2 LINKER=on_chip(default),flash_load,flash_exec COMPILER=gcc(default),clang COMPILER_PREFIX=riscv32-unknown-(default) ARCH=rv32imc(default), - -Params: -- PROJECT (ex: , hello_world(default)) -- TARGET (ex: sim(default),pynq-z2) -- LINKER (ex: on_chip(default),flash_load,flash_exec) -- COMPILER (ex: gcc(default),clang) -- COMPILER_PREFIX (ex: riscv32-unknown-(default)) -- ARCH (ex: rv32imc(default),) -``` - -For instance, to run 'hello world' app for the pynq-z2 FPGA targets, just run: - -``` -make app TARGET=pynq-z2 -``` - -Or, if you use the OpenHW Group [GCC](https://www.embecosm.com/resources/tool-chain-downloads/#corev) compiler with CORE_PULP extensions, make sure to point the `RISCV` env variable to the OpenHW Group compiler, then just run: - - -``` -make app COMPILER_PREFIX=riscv32-corev- ARCH=rv32imc_zicsr_zifencei_xcvhwlp1p0_xcvmem1p0_xcvmac1p0_xcvbi1p0_xcvalu1p0_xcvsimd1p0_xcvbitmanip1p0 -``` - -This will create the executable file to be loaded in your target system (ASIC, FPGA, Simulation). -Remember that, `X-HEEP` is using CMake to compile and link. Thus, the generated files after having -compiled and linked are under `sw\build` - -## FreeROTS based applications - -'X-HEEP' supports 'FreeRTOS' based applications. Please see `sw\applications\blinky_freertos`. - -After that, you can run the command to compile and link the FreeRTOS based application. Please also set 'LINKER' and 'TARGET' parameters if needed. - -``` -make app PROJECT=blinky_freertos -``` - -The main FreeRTOS configuration is allocated under `sw\freertos`, in `FreeRTOSConfig.h`. Please, change this file based on your application requirements. -Moreover, FreeRTOS is being fetch from 'https://github.com/FreeRTOS/FreeRTOS-Kernel.git' by CMake. Specifically, 'V10.5.1' is used. Finally, the fetch repository is located under `sw\build\_deps` after building. - -## Simulating - -This project supports simulation with Verilator, Synopsys VCS, and Siemens Questasim. -It relies on `fusesoc` to handle multiple EDA tools and parameters. -For example, if you want to set the `FPU` and `COREV_PULP` parameters of the `cv32e40p` CPU, -you need to add next to your compilation command `FUSESOC_PARAM="--COREV_PULP=1 --FPU=1"` -Below the different EDA examples commands. - -### Compiling for Verilator - -To simulate your application with Verilator, first compile the HDL: - -``` -make verilator-sim -``` - -then, go to your target system built folder - -``` -cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-verilator -``` - -and type to run your compiled software: - -``` -./Vtestharness +firmware=../../../sw/build/main.hex -``` - -or to execute all these three steps type: - -``` -make run-helloworld -``` - - -### Compiling for VCS - -To simulate your application with VCS, first compile the HDL: - -``` -make vcs-sim -``` - -then, go to your target system built folder - -``` -cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-vcs -``` - -and type to run your compiled software: - -``` -./openhwgroup.org_systems_core-v-mini-mcu_0 +firmware=../../../sw/build/main.hex -``` - -Waveforms can be viewed with Verdi. Make sure you have the env variable `VERDI_HOME` set to your Verdi install folder, then run your compiled software as above, but with the `-gui` flag: - -``` -./openhwgroup.org_systems_core-v-mini-mcu_0 +firmware=../../../sw/build/main.hex -gui -``` - -An Analog / Mixed-Signal simulation of X-HEEP, combining both the RTL system verilog files for the digital part and a SPICE file connected through a `control.init` file for the analog / mixed-signal part, can be ran by typing - -``` -make vcs-ams-sim -``` - -then going to the target system built folder - -``` -cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-vcs -``` - -and running the same executable as for the digital simulation. Note that with Verdi you can view both the digital and the analog waveforms. - -Additional instructions on how to run an analog / mixed-signal simulation of X-HEEP can be found [here](AnalogMixedSignal.md). To try out the simulation, we provide an example SPICE netlist of an simple 1-bit ADC created by us and exported from [xschem](https://xschem.sourceforge.io/stefan/index.html) and which uses the PTM 65nm bulk CMOS model from [https://ptm.asu.edu](https://ptm.asu.edu/). - -### Compiling for Questasim - -To simulate your application with Questasim, first set the env variable `MODEL_TECH` to your Questasim bin folder, then compile the HDL: - -``` -make questasim-sim -``` - -then, go to your target system built folder - -``` -cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-modelsim/ -``` - -and type to run your compiled software: - -``` -make run PLUSARGS="c firmware=../../../sw/build/main.hex" -``` - -You can also use vopt for HDL optimized compilation: - -``` -make questasim-sim-opt -``` - -then go to - -``` -cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim_opt-modelsim/ -``` -and - -``` -make run RUN_OPT=1 PLUSARGS="c firmware=../../../sw/build/main.hex" -``` - -You can also compile with the UPF power domain description as: - -``` -make questasim-sim-opt-upf FUSESOC_PARAM="--USE_UPF" -``` - -and then execute software as: - -``` -make run RUN_OPT=1 RUN_UPF=1 PLUSARGS="c firmware=../../../sw/build/main.hex" -``` - -Questasim version must be >= Questasim 2020.4 - -### UART DPI - -To simulate the UART, we use the LowRISC OpenTitan [UART DPI](https://github.com/lowRISC/opentitan/tree/master/hw/dv/dpi/uartdpi). -Read how to interact with it in the Section "Running Software on a Verilator Simulation with Bazel" [here](https://opentitan.org/guides/getting_started/setup_verilator.html#running-software-on-a-verilator-simulation-with-bazel). -The output of the UART DPI module is printed in the `uart0.log` file in the simulation folder. - -For example, to see the "hello world!" output of the Verilator simulation: - -``` -cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-verilator -./Vtestharness +firmware=../../../sw/build/main.hex -cat uart0.log -``` - -## Automatic testing - -X-HEEP includes two tools to perform automatic tests over your modifications. - -### Github CIs - -Upon push, tests are run on Github runners, these include: -* The generated `.sv` files pushed are equal to those generated in the runner (the code does not depend on the modification of generated files) -* Vendor is up to date (the code does not depend on the modification of vendorized files) -* All applications can be built successfully using both gcc and clang - -All test must be successful before PRs can be merged. - -### Simulation script - -Additionally, a `test_all.sh` script is provided. Apart from compiling all apps with both gcc and clang, it will simulate them and check the result. - -The available parameters are: -* COMPILER: `gcc` (default) or `clang` (can provide more than one) -* SIMULATOR: `verilator` (default), `questasim` or disable simulation with `nosim` (only one, the last provided is used). -* LINKER: `on_chip`(default), `flash_load` or `flash_exec` (can provide more than one) -* TIMEOUT: Integer number of seconds (default 120) - - -#### Usage - -##### Comands -You can use two different commands to compile or simulate all the existing APPs: -``` -make app-compile-all -``` -``` -make app-simulate-all -``` -Note that both commands allow the previous parameters to specify compiling or simulation options. E.g.: -``` -make app-simulate-all LINKER=on_chip SIMULATOR=questasim COMPILER=clang TIMEOUT=150 -``` - -##### Manually -You can also **SOURCE** the script as -```bash -. util/test_all.sh on_chip questasim clang 150 -``` - -*Pay special attention to the first period in the command!* -You will be killing simulations that take too long, if you **EXECUTE** (`./test_all.sh`) this action kills the script. - -For both usages (commands or manual), the order of the arguments is irrelevant. - -> Note: Be sure to commit all your changes before running the script! - -* Applications that fail being built with gcc will not be simulated (skipped). -* Some applications are skipped by default for not being suitable for simulation. -* If a simulation takes too long (>timeout), it is killed. - -* Upon starting, the script will modify the `mcu_cfg.hjson` file to include all peripherals (so the largest number of apps can be run), re-generates the mcu and re-builds the simulation model for the chosen tool. -These changes can be reverted at the end of the execution (default). If changes were not commited, accepting this operation will revert them! - -The success of the script is not required for merging of a PR. - -## Debug - -Follow the [Debug](./Debug.md) guide to debug core-v-mini-mcu. - -## Execute From Flash - -Follow the [ExecuteFromFlash](./ExecuteFromFlash.md) guide to exxecute code directly from the FLASH with modelsim, FPGA, or ASIC. - -## Emulation on Xilinx FPGAs - -This project offers two different X-HEEP implementetions on the Xilinx FPGAs, called Standalone-FEMU and Linux-FEMU. - -### Standalone-FEMU (Standalone Fpga EMUlation) - -In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the FPGA, and its input/output are connected to the available headers on the FPGA board. - -Make sure you have the FPGA board files installed in your Vivado. - -For example, for the Xilinx Pynq-Z2 board, use the documentation provided at the following [link](https://pynq.readthedocs.io/en/v2.5/overlay_design_methodology/board_settings.html) to download and install them: - -To build and program the bitstream for your FPGA with vivado, type: - -``` -make vivado-fpga FPGA_BOARD=pynq-z2 -``` - -or add the flag `use_bscane_xilinx` to use the native Xilinx scanchain: - -``` -make vivado-fpga FPGA_BOARD=pynq-z2 FUSESOC_FLAGS=--flag=use_bscane_xilinx -``` - -Only Vivado 2021.2 has been tried. - -To program the bitstream, open Vivado, - -``` -open --> Hardware Manager --> Open Target --> Autoconnect --> Program Device -``` - -and choose the file `openhwgroup.org_systems_core-v-mini-mcu_0.bit` - -To run SW, follow the [Debug](./Debug.md) guide -to load the binaries with the HS2 cable over JTAG, -or follow the [ExecuteFromFlash](./ExecuteFromFlash.md) -guide if you have a FLASH attached to the FPGA. - - -Do not forget that the `pynq-z2` board requires you to have the ethernet cable attached to the board while running. - - -### Linux-FEMU (Linux Fpga EMUlation) - -In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the FPGA and Linux is run on the ARM-based processing system (PS) side of the same chip. - -Read the [following](./linux_femu/README.md) documentation to have more information about this implementation. diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/CompileMakefile.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/CompileMakefile.md new file mode 100644 index 00000000..774f8ae3 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/CompileMakefile.md @@ -0,0 +1,145 @@ +# Compile with Makefile + +You can compile the example applications and the platform using the Makefile. Type 'make help' or 'make' for more information. Moreover, please, check the different 'clean' commands to verify that you are using the corret one. + +## Generate core-v-mini-mcu package + +First, you have to generate the SystemVerilog package and C header file of the core-v-mini-mcu: + +``` +make mcu-gen +``` + +To change the default cpu type (i.e., cv32e20), the default bus type (i.e., onetoM), +the default continuous memory size (i.e., 2 continuous banks) or the default interleaved memory size (i.e., 0 interleaved banks): + +``` +make mcu-gen CPU=cv32e40p BUS=NtoM MEMORY_BANKS=12 MEMORY_BANKS_IL=4 +``` + +The last command generates x-heep with the cv32e40p core, with a parallel bus, and 16 memory banks (12 continuous and 4 interleaved), +each 32KB, for a total memory of 512KB. +This method is limmited to 32KB banks. + +To configure the ram banks with more flexibility, edit `configs/general.hjson` or provided your own one. +Both method work together the first one overrides the second. + +``` +make mcu-gen X_HEEP_CFG=configs/my_config.hjson +``` + +For more information see Configuration section. + +## Compiling Software + +Don't forget to set the `RISCV` env variable to the compiler folder (without the `/bin` included). +To run 'hello world' application, just type 'make app'. + +``` +make app +``` + +To run any other application, please use the following command with appropiate parameters: + +``` +app PROJECT= TARGET=sim(default),pynq-z2 LINKER=on_chip(default),flash_load,flash_exec COMPILER=gcc(default),clang COMPILER_PREFIX=riscv32-unknown-(default) ARCH=rv32imc(default), + +Params: +- PROJECT (ex: , hello_world(default)) +- TARGET (ex: sim(default),pynq-z2) +- LINKER (ex: on_chip(default),flash_load,flash_exec) +- COMPILER (ex: gcc(default),clang) +- COMPILER_PREFIX (ex: riscv32-unknown-(default)) +- ARCH (ex: rv32imc(default),) +``` + +For instance, to run 'hello world' app for the pynq-z2 FPGA targets, just run: + +``` +make app TARGET=pynq-z2 +``` + +Or, if you use the OpenHW Group [GCC](https://www.embecosm.com/resources/tool-chain-downloads/#corev) compiler with CORE_PULP extensions, make sure to point the `RISCV` env variable to the OpenHW Group compiler, then just run: + + +``` +make app COMPILER_PREFIX=riscv32-corev- ARCH=rv32imc_zicsr_zifencei_xcvhwlp_xcvmem_xcvmac_xcvbi_xcvalu_xcvsimd_xcvbitmanip +``` + +This will create the executable file to be loaded in your target system (ASIC, FPGA, Simulation). +Remember that, `X-HEEP` is using CMake to compile and link. Thus, the generated files after having +compiled and linked are under `sw\build` + +## FreeROTS based applications + +'X-HEEP' supports 'FreeRTOS' based applications. Please see `sw\applications\blinky_freertos`. + +After that, you can run the command to compile and link the FreeRTOS based application. Please also set 'LINKER' and 'TARGET' parameters if needed. + +``` +make app PROJECT=blinky_freertos +``` + +The main FreeRTOS configuration is allocated under `sw\freertos`, in `FreeRTOSConfig.h`. Please, change this file based on your application requirements. +Moreover, FreeRTOS is being fetch from 'https://github.com/FreeRTOS/FreeRTOS-Kernel.git' by CMake. Specifically, 'V10.5.1' is used. Finally, the fetch repository is located under `sw\build\_deps` after building. + + +## Automatic testing + +X-HEEP includes two tools to perform automatic tests over your modifications. + +### Github CIs + +Upon push, tests are run on Github runners, these include: +* The generated `.sv` files pushed are equal to those generated in the runner (the code does not depend on the modification of generated files) +* Vendor is up to date (the code does not depend on the modification of vendorized files) +* All applications can be built successfully using both gcc and clang + +All test must be successful before PRs can be merged. + +### Simulation script + +Additionally, a `test_all.sh` script is provided. Apart from compiling all apps with both gcc and clang, it will simulate them and check the result. + +The available parameters are: +* COMPILER: `gcc` (default) or `clang` (can provide more than one) +* SIMULATOR: `verilator` (default), `questasim` or disable simulation with `nosim` (only one, the last provided is used). +* LINKER: `on_chip`(default), `flash_load` or `flash_exec` (can provide more than one) +* TIMEOUT: Integer number of seconds (default 120) + +#### Usage + +##### Comands +You can use two different commands to compile or simulate all the existing APPs: +``` +make app-compile-all +``` +``` +make app-simulate-all +``` +Note that both commands allow the previous parameters to specify compiling or simulation options. E.g.: +``` +make app-simulate-all LINKER=on_chip SIMULATOR=questasim COMPILER=clang TIMEOUT=150 +``` + +##### Manually +You can also **SOURCE** the script as +```bash +. util/test_all.sh on_chip questasim clang 150 +``` + +*Pay special attention to the first period in the command!* +You will be killing simulations that take too long, if you **EXECUTE** (`./test_all.sh`) this action kills the script. + +For both usages (commands or manual), the order of the arguments is irrelevant. + +> Note: Be sure to commit all your changes before running the script! + +* Applications that fail being built with gcc will not be simulated (skipped). +* Some applications are skipped by default for not being suitable for simulation. +* If a simulation takes too long (>timeout), it is killed. + +* Upon starting, the script will modify the `mcu_cfg.hjson` file to include all peripherals (so the largest number of apps can be run), re-generates the mcu and re-builds the simulation model for the chosen tool. +These changes can be reverted at the end of the execution (default). If changes were not commited, accepting this operation will revert them! + +The success of the script is not required for merging of a PR. \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/Debug.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/Debug.md index 4ec743f3..9bcc76fb 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/Debug.md +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/Debug.md @@ -1,11 +1,11 @@ -# debug +# Debug ## Prerequisite 1. Install the required linux tools: ``` -sudo apt install pkg-config libftdi1-2 libusb-1.0-4 +sudo apt install pkg-config libftdi1-2 ``` You need at least gcc>10, so in case you do not have it: @@ -40,9 +40,9 @@ Now we are going to Simulate debugging with core-v-mini-mcu. In this setup, OpenOCD communicates with the remote bitbang server by means of DPIs. The remote bitbang server is simplemented in the folder ./hw/vendor/pulp_platform_pulpissimo/rtl/tb/remote_bitbang and it will be compiled using fusesoc. -### Verilator +### Verilator (C++ only) -To simulate your application with Questasim using the remote_bitbang server, you need to compile you system adding the `JTAG DPI` functions: +To simulate your application with Verilator using the remote_bitbang server, you need to compile you system adding the `JTAG DPI` functions: ``` make verilator-sim FUSESOC_PARAM="--JTAG_DPI=1" @@ -130,24 +130,86 @@ Transfer rate: 67 bytes/sec, 798 bytes/write. `gdb` automatically set the `program counter` to start from `_start`, check with: +Anytime you want to check the `disassemble`, just do: + + ``` -(gdb) i r pc +(gdb) disassemble ``` -It should give you `0x180`. + +and get an output that look like: + +``` +Dump of assembler code for function _start: +=> 0x00000180 <+0>: auipc gp,0xd + 0x00000184 <+4>: addi gp,gp,964 # 0xd544 + 0x00000188 <+8>: auipc sp,0xf + 0x0000018c <+12>: addi sp,sp,-1080 # 0xed50 + 0x00000190 <+16>: lui a0,0x20000 + ... +``` + +``` +(gdb) info reg pc +``` +Gives you the program counter. Now you can play with `gdb` e.g: Ask for the content of register `a0` ``` -(gdb) i r a0 +(gdb) info reg a0 +``` + +or set it to `15` as: + +``` +(gdb) set $a0=15 +``` + +or just run the entire execution with the and then check the `uart0.log` to see the printed hello world string: + +``` +(gdb) continue +``` + +If you want to reset the non-debug modules (as the CPU): + +``` +(gdb) monitor reset halt ``` -or just run the entire execution with the continue command and then check the `uart0.log` to see the printed hello world string: + +Set a breakpoint to a specific instruction address: + +``` +(gdb) b *0x0000019c +Breakpoint 1 at 0x19c: file /x-heep/sw/device/lib/crt/crt0.S, line 38. +``` + +and continue the execution untill the breakpoint as: ``` (gdb) continue ``` +Then check the breakpoint status: + +``` +(gdb) info b +Num Type Disp Enb Address What +1 breakpoint keep y 0x0000019c /x-heep/sw/device/lib/crt/crt0.S:38 + breakpoint already hit 1 time +``` + +and finally delete it: + +``` +(gdb) delete 1 +(gdb) info b +No breakpoints or watchpoints. +``` + You can also run all the gdb steps by running: ``` make gdb_connect MAINFILE= @@ -202,6 +264,16 @@ or with the EPFL Programmer also using this other command (**strongly recommende make openOCD_epflp ``` +or with the BSCAN of the Pynq-Z2 board using this command: +``` +openocd -f ./tb/core-v-mini-mcu-pynq-z2-bscan.cfg +``` + +or with the BSCAN of the Pynq-Z2 board also using this other command (**strongly recommended**): + +``` +make openOCD_bscan +``` If you get this error: diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ExecuteFromFlash.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ExecuteFromFlash.md index 8413a129..ce7b9a9c 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ExecuteFromFlash.md +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ExecuteFromFlash.md @@ -1,4 +1,4 @@ -# execute Code from FLASH +# Execute Code from FLASH ## Boot Procedure diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ExternalDevices.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ExternalDevices.md deleted file mode 100644 index 530b9817..00000000 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ExternalDevices.md +++ /dev/null @@ -1,99 +0,0 @@ -# interface with external devices - -The top module [`core_v_mini_mcu`]((./../../../hw/core-v-mini-mcu/corecore_v_mini_mcu.sv) exposes several external interfaces: - -- `ext_xbar_master`: N ports to connect external masters to the internal system bus. - -- Five external ports to connect internal masters (e.g., CPU instruction and data ports) to external slaves. Every internal master is exposed to the external subsystem: - 1. `ext_core_instr`: CPU instruction interface. - 2. `ext_core_data`: CPU data interface. - 3. `ext_debug_master`: debug interface. - 4. `ext_dma_read_ch0`: DMA read master, channel 0. - 5. `ext_dma_write_ch0`: DMA write master, channel 0. - 6. `ext_dma_addr_ch0`: DMA address (read) master, channel 0. - -- `ext_peripheral_slave`: 1 peripheral slave port connected to the system bus (through the peripheral interface). - -The number of external master ports is set by the [`EXT_XBAR_NMASTER`](./../../../tb/testharness_pkg.sv#L10) parameter from `testharness_pkg`. -Multiple OBI slaves can be connected to the exposed internal masters using an external bus, as demonstrated in [`testharness.sv`](./../../../tb/testharness.sv#L232). - -> NOTE: the internal bus has no master port connected to the external subsystem. Therefore, an external master cannot send a request to an external slave through one of the exposed master ports. All the address decoding must be done by the external bus: the request must be forwarded to one of the `ext_xbar_master` ports only if the target address falls into the space where internal slaves are mapped. This can be achieved using a 1-to-2 crossbar for each external master as done [here](./../../../tb/ext_bus.sv#L131). - -Finally, only one peripheral slave port is available to the external subsystem. - -## External device example - -One example using the external ports is provided where: - -- hw/ip_examples/slow_sram is a memory slave device -- hw/ip_examples/memcopy is a slave peripheral with a master port. It implements a simple memcopy feature (i.e., DMA). -- hw/ip_examples/ams is an example AMS peripheral which can interface with SPICE netlists to run mixed-signal simulations (in this repository, the example analog peripheral is a 1-bit ADC) - - For more information, see [here](AnalogMixedSignal.md) - -## Run the external device example - -To run the external device example, first compile the software example: - -```bash -make app PROJECT=example_external_dma -``` - -By default, the external device example RTL code is disabled. This example is available for the sim and sim_opt targets. - -For example, compile for Verilator with: - -``` -make verilator-sim -``` - -then, go to your target system built folder - -```bash -cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-verilator -``` - -and type to run your compiled software: - -```bash -./Vtestharness +firmware=../../../sw/build/main.hex -``` - -If you don't compile the platform with the correct fusesoc flag, the simulation will hang forever because the external peripheral is disabled and never replies. - -You can display the UART output with: - -```bash -cat uart0.log -``` - -It should print: - -``` ---- MEMCOPY EXAMPLE - external peripheral --- -Init the PLIC...success -Set MEMCOPY interrupt priority to 1...success -Enable MEMCOPY interrupt...Success -Memcopy launched...finished -Complete interrupt...success -MEMCOPY SUCCESS -``` - -## Add an external master/slave or peripheral - -1. Master(s): use the obi_pkg (import obi_pkg::\*;) to create your master_req output port (obi_req_t) and master_resp input port (obi_resp_t). Adjust the EXT_XBAR_NMASTER parameter accordingly. - -2. Slave(s): similar to adding a master but you have a slave_req input port (obi_req_t) and slave_resp output port (obi_resp_t). Remember to connect external masters with external slaves through an external bus. The same bus can be used to connect multiple external slaves to the internal `core_v_mini_mcu` masters. - -3. Peripheral slave(s): use the reg_pkg (import obi_pkg::\*;) to create your slave_periph_req input port (reg_req_t) and slave_resp output port (reg_rsp_t). If multiple peripheral slaves are used, add a decoding stage for addresses dispatching. - -To create and maintain a peripheral unit efficiently, use the `reggen` tool: - -1. Define the registers of your peripheral in a `.hjson` file (read the documentation [here](https://docs.opentitan.org/doc/rm/register_tool/)). - -2. Launch the `regtool.py` script to generate SystemVerilog RTL code and a C header file. - -For example, launching the script [`memcopy_periph_gen.sh`](./../../../hw/ip_examples/memcopy_periph/memcopy_periph_gen.sh) generates 2 SystemVerilog files and one C header file: - -1. `memcopy_periph_reg_top.sv`: the register file module. It can be directly instantiated inside your peripheral RTL code (e.g., [`memcopy_periph.sv`](./../../../hw/ip_examples/memcopy_periph/rtl/memcopy_periph.sv)) and connected to the peripheral device controller(s). -2. `memcopy_periph_reg_pkg.sv`: SystemVerilog package containing the definitions used in the SystemVerilog module above. -3. `memcopy_periph_regs.h`: C/C++ header file defining the address offset of the peripheral configuration registers. Take a look at the C code [here](./../../../sw/applications/example_external_peripheral/memcopy_periph.c) for a usage example. diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/GettingStarted.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/GettingStarted.md index e5b877dd..4b7b6685 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/GettingStarted.md +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/GettingStarted.md @@ -1,6 +1,34 @@ -# get started +# Get started -## 1. OS requirements +## Docker setup + +A docker image containing all the required software dependancies is available on [github-packages](https://github.com/orgs/esl-epfl/packages/container/package/x-heep-toolchain). + +It is only required to install docker and pull the image. + +```bash +docker pull ghcr.io/esl-epfl/x-heep-toolchain:latest +``` + +Assuming that X-HEEP has been cloned to `X-HEEP-DIR=\absolute\path\to\x-HEEP\folder`, it is possible to directly run the docker mounting `X-HEEP-DIR` to the path `\workspace\x-heep` in the docker. + +```bash +docker run -it -v ${X-HEEP-DIR}:/workspace/x-heep ghcr.io/esl-epfl/x-heep-toolchain +``` + +:warning: Take care to indicate the absolute path to the local clone of X-HEEP, otherwise docker will not be able to properly mount the local folder in the container. + +All the command listed in the README can be execute in the docker container, except for: + +- Simulation with Questasim and VCS, synthesis with Design Compiler (licenses are required to use these tools, so they are not installed in the container) + +- OpenRoad flow is not installed in the container, so it is not possible to run the related make commands + +- Synthesis with Vivado could be possible, but currently is untested + +## Manual setup + +### 1. OS requirements To use `X-HEEP`, first make sure you have the following apt packages, or install them as: @@ -10,16 +38,14 @@ sudo apt install lcov libelf1 libelf-dev libftdi1-2 libftdi1-dev libncurses5 lib In general, have a look at the [Install required software](https://opentitan.org/guides/getting_started/index.html) section of the OpenTitan documentation. -It has been tested only on `Ubuntu 20`, and we know it does NOT WORK on `Ubuntu 22`. - -## 2. Python +### 2. Python We rely on either (a) `miniconda`, or (b) `virtual environment` enviroment. Choose between `2.a` or `2.b` to setup your enviroment. -### 2.a Miniconda +#### 2.a Miniconda Install [Miniconda](https://docs.conda.io/en/latest/miniconda.html#linux-installers) python 3.8 version as described in the link, and create the Conda enviroment: @@ -35,7 +61,7 @@ conda activate core-v-mini-mcu ``` -### 2.b Virtual Environment +#### 2.b Virtual Environment Install the python virtual environment just as: @@ -49,7 +75,7 @@ You need to do it only the first time, then just activate the environment everyt source .venv/bin/activate ``` -## 3. Install the RISC-V Compiler: +### 3. Install the RISC-V Compiler: ``` git clone --branch 2022.01.17 --recursive https://github.com/riscv/riscv-gnu-toolchain @@ -75,7 +101,7 @@ cmake -G "Unix Makefiles" -DLLVM_ENABLE_PROJECTS=clang -DCMAKE_BUILD_TYPE=Releas cmake --build . --target install ``` -## 4. Install Verilator: +### 4. Install Verilator: ``` export VERILATOR_VERSION=4.210 @@ -104,18 +130,18 @@ sudo apt install libcanberra-gtk-module libcanberra-gtk3-module sudo apt-get install -y gtkwave ``` -## Files are formatted with Verible +### Files are formatted with Verible We use version v0.0-1824-ga3b5bedf -See: [Install Verible](https://opentitan.org/guides/getting_started/index.html#step-6a-install-verible-optional) +See: [Install Verible](https://opentitan.org/guides/getting_started/index.html#step-7a-install-verible-optional) To format your RTL code type: ``` make verible ``` -## Compilation Flow and Package Manager +### Compilation Flow and Package Manager We use [FuseSoC](https://github.com/olofk/fusesoc) for all the tools we use. diff --git a/hw/vendor/esl_epfl_x_heep/IDEs.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/IDEs.md similarity index 92% rename from hw/vendor/esl_epfl_x_heep/IDEs.md rename to hw/vendor/esl_epfl_x_heep/docs/source/How_to/IDEs.md index e1fce194..ee932dc3 100644 --- a/hw/vendor/esl_epfl_x_heep/IDEs.md +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/IDEs.md @@ -1,14 +1,14 @@ +# Set up an IDE For FW development, `X-HEEP` can be used together with different Integrated Development Environments (IDEs) flavours. Up to now, full support is just provided by [Segger Embedded Studio (SES)](https://www.segger.com/products/development-tools/embedded-studio/editions/risc-v/). This readme guides you through all the needed steps to get SES working and debugging when prototyping `X-HEEP` into the pynq-z2 board. -# Prerequisite -## 1. SES installation. +## SES installation. The platform was only tested under Linux and version 7.32 of the Embedded Studio for RISC-V. Please, go to the Segger [download center](https://www.segger.com/downloads/embedded-studio/) to get that version. It is assumed that you have already installed the RISC-V compiler and openOCD. If the latter is not true, check the main [Readme](https://github.com/esl-epfl/x-heep) please. -# Configuration +## Configuration -After installing SES, you need to indicate to Segger your Toolchain directory (RISC-V Compiler) as well as your openOCD installation folder. Those need to be specified into `xheep.emProject` file. +After installing SES, you need to indicate to Segger your Toolchain directory (RISC-V Compiler) as well as your openOCD installation folder. Those need to be specified into `xheep.emProject` file. For the RISC-V Compiler path, **line 71**: ``` @@ -22,23 +22,23 @@ gdb_server_command_line="/home/< user >/tools/openocd/bin/openocd -f "$(Pro ``` Please, substitute that path to your current path where openOCD was installed. Do not forget to target the `openocd` file inside the `bin` installation folder of openocd. -# Building +## Building Once the paths are set properly, you can open `xheep.emProject` with SES. That will launch SES with one solution already configured, `xheep_ses`, and one project into that solution `helloworld`. Note that this project has already everything configured to run the `helloworld` application of the main repo, i.e. all the source files are linked to the project as well as the `c user include directories` already set up. Moreover, this project is configured to be running (compile, linking, and debug) by using the on-chip linker `sw/linker/link.ld`. If you want to change any of these options, you will need to change the options of the project or the options of the solution. Note that the project is currently set-up to be working on the `Debug_External` configuration. Please, do not move to other configuration when building and/or debugging. Finally, to build the whole project just press `F7` or `Build > Build helloworld`. The output should be like this: -

+

Note that on the right part, you have the memory usage based on the linker we have configured. If you do not see this, you can activate that view in `View > Memory Usage`. -# Debugging +## Debugging -Finally, after building (compile and linking), you can directly start debugging by pressing `F5` or also `Target > Connect GDB Server` and `Debug > Go`. You also have the possibility to activate the terminal to see directly into the SES window the printing characters. +Finally, after building (compile and linking), you can directly start debugging by pressing `F5` or also `Target > Connect GDB Server` and `Debug > Go`. You also have the possibility to activate the terminal to see directly into the SES window the printing characters. The output should be something like this: -

+

Note that when debugging and setting breakpoints, please, go one-by-one (one breakpoint at a time). Several breakpoints support will be supported in the following releases. diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ImplementASIC.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ImplementASIC.md index bacb7050..2ddf20c8 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ImplementASIC.md +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ImplementASIC.md @@ -1,4 +1,4 @@ -# implement on ASIC +# Implement on ASIC This project can be implemented using standard cells based ASIC flow. diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/IntegratePeripheral.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/IntegratePeripheral.md index ae8b3b3f..f39bdbd1 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/IntegratePeripheral.md +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/IntegratePeripheral.md @@ -206,7 +206,7 @@ module #( b. The corresponding package must be imported: -```systemverilog +``` import _reg_pkg::*; ``` diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ProgramFlash.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ProgramFlash.md index 98c09221..efbe78a9 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ProgramFlash.md +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/ProgramFlash.md @@ -1,4 +1,4 @@ -# program the FLASH on the EPFL Programmer +# Program the FLASH on the EPFL Programmer Install the required linux tools: @@ -92,30 +92,28 @@ Generate the C program you want to execute as described in the [ExecuteFromFlash then program the FLASH as: ``` -./iceprog -d i:0x0403:0x6011 -I B ../../../build/main.hex +make flash-prog ``` -You can also program the FLASH by running: +You can read the content of the FLASH as: ``` -make flash-prog MAINFILE= +make flash-read FLASHREAD_ADDR=0x10000 FLASHREAD_BYTES=16; xxd flashcontent.hex ``` -You can read the content of the FLASH as: +In this example, we are reading `16` bytes from the flash address `0x10000`. -``` -./iceprog -d i:0x0403:0x6011 -I B -r flash_content.txt -xxd flash_content.txt > flash_content.dump.txt -``` Now program the FPGA with the x-heep bitstream: ``` -cd build/openhwgroup.org_systems_core-v-mini-mcu_0/pynq-z2-vivado +make vivado-fpga-pgm FPGA_BOARD=pynq-z2 ``` -Remember to set the `boot_sel_i` and `execute_from_flash_i` switches to 1. +Remember to set the `boot_sel_i` and `execute_from_flash_i` switches to `1` if you `execute from flash`, +or just `boot_sel_i` to `1` and `execute_from_flash_i` to `0` if you `load from flash`. + Reset the logic (so the x-heep reset and not the bitstream reset) and enjoy. Additional note: To use the flash directly from X-HEEP, you first need to execute from the PC any iceprog command targeting the Flash. On the exit of any iceprog program, the FTDI pins will be set to high impedance. If this is not performed, the pins from the FTDI won't be on high impedance and the SPI signals cannot be driven from X-HEEP (or any other device). diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/RunOnFPGA.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/RunOnFPGA.md new file mode 100644 index 00000000..79790a91 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/RunOnFPGA.md @@ -0,0 +1,81 @@ +# Run on FPGA + +This project offers two different X-HEEP implementetions on Xilinx FPGAs, called Standalone and FEMU. + +## Standalone + +### Set-up +In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the FPGA, and its input/output are connected to the available headers on the FPGA board. + +Two FPGA boards are supported: the Xilinx Pynq-z2 and Nexys-A7-100t. + +1. Make sure you have the FPGA board files installed in your Vivado. +> For example, for the Pynq-Z2 board, use the documentation provided at the following [link](https://pynq.readthedocs.io/en/v2.5/overlay_design_methodology/board_settings.html) to download and install them. + +2. Make sure you set up the Vivado environments by running + ``` + source /settings64.sh + ``` + > We recommend adding this command to your `.bashrc` + +3. Install the Xilinx cable drivers. +* Follow the [instructions for Linux](https://docs.amd.com/api/khub/documents/6EIhov6ruoilhq8zq7bXBA/content?Ft-Calling-App=ft%2Fturnkey-portal&Ft-Calling-App-Version=4.3.26#G4.262534) +* Restart your PC + +### Running + +To build and program the bitstream for your FPGA with vivado, type: + +``` +make vivado-fpga FPGA_BOARD=pynq-z2 +``` + +or + +``` +make vivado-fpga FPGA_BOARD=nexys-a7-100t +``` + +or add the flag `use_bscane_xilinx` to use the native Xilinx scanchain: + +``` +make vivado-fpga FPGA_BOARD=pynq-z2 FUSESOC_FLAGS=--flag=use_bscane_xilinx +``` + +To program the bitstream, open Vivado, + +``` +open --> Hardware Manager --> Open Target --> Autoconnect --> Program Device +``` + +and choose the file `openhwgroup.org_systems_core-v-mini-mcu_0.bit`. + +Or simply type: + +``` +bash vivado-fpga-pgm FPGA_BOARD=pynq-z2 +``` + +or + +``` +make vivado-fpga-pgm FPGA_BOARD=nexys-a7-100t +``` + +To run SW, follow the [Debug](./Debug.md) guide to load the binaries with the HS2 cable over JTAG, +or follow the [ExecuteFromFlash](./ExecuteFromFlash.md) guide if you have a FLASH attached to the FPGA. + +Do not forget that the `pynq-z2` board requires you to have the ethernet cable attached to the board while running. + +For example, if you want to run your application using flash_exec, do as follow: +compile your application, e.g. `make app PROJECT=example_matfadd TARGET=pynq-z2 ARCH=rv32imfc LINKER=flash_exec` +and then follow the [ExecuteFromFlash](./ExecuteFromFlash.md) to program the flash and set the boot buttons on the FPGA correctly. +To look at the output of your printf, run in another terminal: +`picocom -b 9600 -r -l --imap lfcrlf /dev/ttyUSB2` +Please be sure to use the right `ttyUSB` number (you can discover it with `dmesg --time-format iso | grep FTDI` for example). + +## FPGA EMUlation Platform (FEMU) + +In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the Xilinx Zynq-7020 chip on the Pynq-Z2 board and Linux is run on the ARM-based processing system (PS) side of the same chip. + +NOTE: This platform is not part of this repository, but you can access it with the following link: [FEMU](https://github.com/esl-epfl/x-heep-femu-sdk). diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/Simulate.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/Simulate.md new file mode 100644 index 00000000..6147648c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/Simulate.md @@ -0,0 +1,160 @@ +# Simulate + +This project supports simulation with Verilator, Synopsys VCS, Siemens Questasim and Cadence Xcelium. +It relies on `fusesoc` to handle multiple EDA tools and parameters. +For example, if you want to set the `FPU` and `COREV_PULP` parameters of the `cv32e40p` CPU, +you need to add next to your compilation command `FUSESOC_PARAM="--COREV_PULP=1 --FPU=1"` +Below the different EDA examples commands. + +## Compiling for Verilator + +To simulate your application with Verilator, first compile the HDL: + +``` +make verilator-sim +``` + +then, go to your target system built folder + +``` +cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-verilator +``` + +and type to run your compiled software: + +``` +./Vtestharness +firmware=../../../sw/build/main.hex +``` + +or to execute all these three steps type: + +``` +make run-helloworld +``` + +## Compiling for VCS + +To simulate your application with VCS, first compile the HDL: + +``` +make vcs-sim +``` + +then, go to your target system built folder + +``` +cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-vcs +``` + +and type to run your compiled software: + +``` +./openhwgroup.org_systems_core-v-mini-mcu_0 +firmware=../../../sw/build/main.hex +``` + +Waveforms can be viewed with Verdi. Make sure you have the env variable `VERDI_HOME` set to your Verdi install folder, then run your compiled software as above, but with the `-gui` flag: + +``` +./openhwgroup.org_systems_core-v-mini-mcu_0 +firmware=../../../sw/build/main.hex -gui +``` + +An Analog / Mixed-Signal simulation of X-HEEP, combining both the RTL system verilog files for the digital part and a SPICE file connected through a `control.init` file for the analog / mixed-signal part, can be ran by typing + +``` +make vcs-ams-sim +``` + +then going to the target system built folder + +``` +cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-vcs +``` + +and running the same executable as for the digital simulation. Note that with Verdi you can view both the digital and the analog waveforms. + +Additional instructions on how to run an analog / mixed-signal simulation of X-HEEP can be found [here](./AnalogMixedSignal.md). To try out the simulation, we provide an example SPICE netlist of an simple 1-bit ADC created by us and exported from [xschem](https://xschem.sourceforge.io/stefan/index.html) and which uses the PTM 65nm bulk CMOS model from [https://ptm.asu.edu](https://ptm.asu.edu/). + +## Compiling for Questasim + +To simulate your application with Questasim, first set the env variable `MODEL_TECH` to your Questasim bin folder, then compile the HDL: + +``` +make questasim-sim +``` + +then, go to your target system built folder + +``` +cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-modelsim/ +``` + +and type to run your compiled software: + +``` +make run PLUSARGS="c firmware=../../../sw/build/main.hex" +``` + +You can also use vopt for HDL optimized compilation: + +``` +make questasim-sim-opt +``` + +then go to + +``` +cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim_opt-modelsim/ +``` +and + +``` +make run RUN_OPT=1 PLUSARGS="c firmware=../../../sw/build/main.hex" +``` + +You can also compile with the UPF power domain description as: + +``` +make questasim-sim-opt-upf FUSESOC_PARAM="--USE_UPF" +``` + +and then execute software as: + +``` +make run RUN_OPT=1 RUN_UPF=1 PLUSARGS="c firmware=../../../sw/build/main.hex" +``` + +Questasim version must be >= Questasim 2020.4 + +## Compiling for Xcelium + +To simulate your application with Xcelium, first compile the HDL: + +``` +make xcelium-sim +``` + +then, go to your target system built folder + +``` +cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-xcelium/ +``` + +and type to run your compiled software: + +``` +make run PLUSARGS="c firmware=../../../sw/build/main.hex" +``` + +## UART DPI + +To simulate the UART, we use the LowRISC OpenTitan [UART DPI](https://github.com/lowRISC/opentitan/tree/master/hw/dv/dpi/uartdpi). +Read how to interact with it in the Section "Running Software on a Verilator Simulation with Bazel" [here](https://opentitan.org/guides/getting_started/setup_verilator.html#running-software-on-a-verilator-simulation-with-bazel). +The output of the UART DPI module is printed in the `uart0.log` file in the simulation folder. + +For example, to see the "hello world!" output of the Verilator simulation: + +``` +cd ./build/openhwgroup.org_systems_core-v-mini-mcu_0/sim-verilator +./Vtestharness +firmware=../../../sw/build/main.hex +cat uart0.log +``` \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/SystemC.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/SystemC.md new file mode 100644 index 00000000..1a1aad57 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/SystemC.md @@ -0,0 +1,16 @@ +# SystemC model + +Supporting SystemC model in `X-HEEP` is still a work-in-progress. +However, a simple example is provided in the SystemC testbench available in `tb/tb_sc_top.cpp`. + +When compiling the `X-HEEP` with Verilator using SystemC, the above testbench is used for simulation. +The testbench gets an `X-HEEP` external-memory `obi` master port to communicate with a SystemC memory model. + +Such model is very simple as meant to be an example and is provided in `tb/systemc_tb`. +For those who want to extend the functionality of `X-HEEP` with SystemC, such examples can be used as starting point. + +The SystemC modules leverages `TLM-2.0` as well as baseline SystemC functionalities. + +The `X-HEEP` `obi` port is connected to a `C++` direct-mapped cache who handles `hit` and `miss` with pre-defined latencies. +It uses `TLM-2.0` to communicate with the external SystemC memory on `miss` cache-transactions. +A module in SystemC then communicates with the RTL SystemC model compiled by Verilator to provides read/write data. \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/UpdateDocumentation.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/UpdateDocumentation.md new file mode 100644 index 00000000..c27a8776 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/UpdateDocumentation.md @@ -0,0 +1,27 @@ +# Update the documentation + +All documentation is found in the `/docs` directory. + +1. If you need to create a new entry, add the new document in markdown (`.md` extension) to the corresponding folder. Otherwise, just edit the corresponding file. + +> Make sure the document has one single `# header`, otherwise they will be considered different documents. + +2. If a new folder is added, add it to the `toctree` inside `docs/source/index.rst` (as the `peripherals` folder is) +3. Commit and push + +## Refresh the web documentation + +After each change to the documentation, once the branch is merged into the main branch of X-HEEP, anyone must do the following: + +1. Open a terminal in the `docs` folder and make sure the conda environment is activated. +2. If it is your first time updating the web docs, run: +```bash +pip install -r requirements.txt +``` +3. Run +```bash +make clean html +``` +4. Wait a few minutes and enjoy your brand new documentation in [Read the Docs](https://x-heep.readthedocs.io/en/latest/). + +Thank you for helping keep X-HEEP accurately and extensively documented! diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/eXtendingHEEP.md b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/eXtendingHEEP.md index ad8805b1..41e9bed7 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/How_to/eXtendingHEEP.md +++ b/hw/vendor/esl_epfl_x_heep/docs/source/How_to/eXtendingHEEP.md @@ -2,14 +2,15 @@ `X-HEEP` is meant to be extended with your own custom IPs. `X-HEEP` itself posseses a hardware-software framework capable of working standalone. If you want to extend it, you will need to merge your hardware and software with `X-HEEP`'s. -For this purpose we support the [CORE-V-XIF](https://docs.openhwgroup.org/projects/openhw-group-core-v-xif/en/latest/intro.html) interface with the [cv32e40x](https://github.com/openhwgroup/cv32e40x) RISCV-CPU, and we expose master and slave ports to/from the bus. +For this purpose we support the [CV-X-IF](https://docs.openhwgroup.org/projects/openhw-group-core-v-xif/en/latest/intro.html) interface with the [cv32e40x](https://github.com/openhwgroup/cv32e40x) or [cv32e40px](https://github.com/esl-epfl/cv32e40px) RISCV-CPU, and we expose master and slave ports to/from the bus. -> `X-HEEP` currently uses the revision [`0.9.0`](https://github.com/openhwgroup/cv32e40x/commit/f17028f2369373d9443e4636f2826218e8d54e0f) of OpenHW Groups's `cv32e40x` core to implement the `CORE-V-XIF`. It is recommended to use the same revision in peripheral IPs to prevent conflicts during RTL compilation. +> We recommend using the `cv32e40px` for pairing with your CV-X-IF compliant coprocessor. If you choose to use the `cv32e40x`, `X-HEEP` currently uses the revision [`0.9.0`](https://github.com/openhwgroup/cv32e40x/commit/f17028f2369373d9443e4636f2826218e8d54e0f). It is recommended to use the same revision in peripheral IPs to prevent conflicts during RTL compilation. Here you can find a list of `X-HEEP` based open-source examples. If you want to include your project in this list, please open an issue with a link to your repository. * [CGRA-X-HEEP](https://github.com/esl-epfl/cgra_x_heep): A CGRA loosely coupled with X-HEEP. -* [F-HEEP](https://github.com/davidmallasen/F-HEEP): System integrating [fpu_ss](https://github.com/pulp-platform/fpu_ss) into X-HEEP via the eXtension interface and cv32e40x. +* [F-HEEP](https://github.com/davidmallasen/F-HEEP): System integrating [fpu_ss](https://github.com/pulp-platform/fpu_ss) into X-HEEP via the eXtension interface and cv32e40px. +* [KALIPSO](https://github.com/vlsi-lab/ntt_intt_kyber) and [KRONOS](https://github.com/vlsi-lab/keccak_integration/tree/keccak_xheep): Loosely-coupled, post-quantum cryptography accelerators for NTT/INTT and Keccak hash function integrated into X-HEEP. In addition, the `X-HEEP` testbench has been extended with a `DMA`, dummy `PERIPHERALs` (including the `FLASH`), and a CORE-V-XIF compatible co-processor @@ -97,7 +98,7 @@ To achieve this: * Create a new top-level repository (`BASE`) and vendorize (or add as git submodules) both your `CORE-V-XIF/OBI` compliant coprocessor/accelerator and `X-HEEP`. * Copy the `x-heep/hw/system/x_heep_system.sv` as your new top-level module. Then modify it as needed to include your co-processor and connect it to the `core_v_mini_mcu` with the `XIF`. The `XIF` SystemVerilog interface must be instantiated in the top-level module, where `X-HEEP` and your co-processor are connected. See the `X-HEEP` [testbench](./../../../tb/testharness.sv) as an example. -* Before building software remember to run `make mcu-gen CPU=cv32e40x`. +* Before building software remember to run `make mcu-gen CPU=cv32e40px`. To add this new top-level module to the simulation/synthesis flow you can extend the [FuseSoC](https://fusesoc.readthedocs.io/en/stable/user/index.html) support of `X-HEEP`. @@ -304,7 +305,7 @@ To do so, it MUST include the `external.mk` AFTER all your custom rules.
Example of BASE/Makefile -``` +```Makefile MAKE = make .PHONY: test test: @@ -326,11 +327,68 @@ include $(XHEEP_MAKE) * The `app` rule will perform actions before calling `X-HEEP` Makefile's `app` rule. In this case, the project and where the source files are to be extracted from is being specified. The `SOURCE=.` argument will set `X-HEEP`'s own `sw/` folder as the directory from which to fetch source files. This is an example of building inner sources from an external directory. * The `verilator-sim` rule will override the `X-HEEP` Makefile's one. * Any other target will be passed straight to `X-HEEP`'s Makefile. For example +```sh +make mcu-gen CPU=cv32e40px ``` -make mcu-gen CPU=cv32e40x +
+ + +### Excluding files from compilation +If you have files that need to be excluded from the gcc compilation flow, you can add them to a directory containing the keyword `exclude`, and/or rename the file to include the keyword `exclude`. +In the following example, the files marked with ✅ will be compiled, and the ones marked with ❌ will not. + + BASE + ├── sw + │ ├── applications + │ │ └── your_app + │ │ ├── ✅ main.c + │ │ ├── ✅ your_app.c + │ │ ├── your_app.h + │ │ ├── ❌ my_kernel_exclude.c + │ │ ├── my_kernel.h + │ │ └── exclude_files + │ │ └── ❌ kernel_asm.S + + + +### Makefile help +If you want that the commands `make` or `make help` show the help for your external Makefile, add the following lines before the first `include` directive or target. + +
+ Addition to print the target's help + +```Makefile +# HEEP_DIR might already be defined, you may want to move it to the top +export HEEP_DIR = hw/vendor/esl_epfl_x_heep/ + +# Get the path of this Makefile to pass to the Makefile help generator +MKFILE_PATH = $(shell dirname "$(realpath $(firstword $(MAKEFILE_LIST)))") +export FILE_FOR_HELP = $(MKFILE_PATH)/Makefile + + +## Call the help generator. Calling simply +## $ make +## or +## $ make help +## Will print the help of this project. +## With the parameter WHICH you can select to print +## either the help of X-HEEP (WHICH=xheep) +## or both this project's and X-HEEP's (WHICH=all) +help: +ifndef WHICH + ${HEEP_DIR}/util/MakefileHelp +else ifeq ($(filter $(WHICH),xheep x-heep),) + ${HEEP_DIR}/util/MakefileHelp + $(MAKE) -C $(HEEP_DIR) help +else + $(MAKE) -C $(HEEP_DIR) help +endif ``` +
+> Remeber to add double hashes `##` on any comment you want printed on the help. +> Use `## @section SectionName` to divide the documentation in sections ### Different use cases If you plan to vendorize `X-HEEP` in a different directory than the one proposed, just update in your `BASE/Makefile`: @@ -343,3 +401,10 @@ If you plan to store source files in a different location that the one proposed, make app PROJECT=your_app SOURCE= ``` Consider that inside this `sw` folder the same structure than the one proposed is required. + + +## Inter-process communication using Verilator's DPI + +The following [repository](https://github.com/specs-feup/x-heep) uses X-HEEP and the Verilator simulator to model a CPU-CGRA hybrid system. This architecture simulates the CPU integrated into the X-HEEP system, and an external Java process simulates the accelerator. Both components require a communication channel to exchange instructions and data. Using the existing infrastructure to to interact with an external OS process is not feasible at first sight, given that the X-HEEP ecosystem's pipeline encapsulates most of the simulation build and execution, with all modules supplied directly to Verilator. + +To circumvent this issue, this project uses [Direct Programming Interface (DPI)](https://verilator.org/guide/latest/connecting.html) calls (defined in `hw/ip_examples/cgraitf/cgraitfdpi.c`) to establish a connection and communicate with an external process through a Unix Domain Socket. This behavior mirrors the UART module (used as the skeleton code) that connects and outputs _printf_ information to the pseudo-terminal. These calls are embedded in a mock CGRA peripheral/interface, located in `hw/ip_examples/cgraitf/cgraitf.sv`. The module overrides reads and writes to the specified peripheral address, with the proper socket-based mechanism (_send_ or _recv_). The _simple_accelerator_ module could also be similarly customized to perform the same operations, using X-HEEP's interfaces and memory access protocols. A given user program executed in the CPU (such as `sw/applications/cgra_itf/main.c`) must then select assignments to or from the address to trigger the appropriate action. \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/Peripherals/DMA.md b/hw/vendor/esl_epfl_x_heep/docs/source/Peripherals/DMA.md index e955df91..a3b4d890 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/Peripherals/DMA.md +++ b/hw/vendor/esl_epfl_x_heep/docs/source/Peripherals/DMA.md @@ -1,490 +1,1914 @@ + # DMA + +## Introduction + The **Direct Memory Access (DMA)** peripheral allows data transfers with reduced CPU interaction. + It can perform *transactions* of data between peripherals and memory, or memory-to-memory (as a `memcpy` would). + The CPU is required to configure the transaction, but once launched it is free to go to sleep, process the incoming data or do anything else. +This unit is capable of performing complex tasks that can significantly impact on the performance and power consumption of memory-intense applications. +It can be configured to perform *1D* or *2D* transactions and it can apply **zero padding** and perform **transpositions** on-the-fly, reducing the overhead of matrix operations. + The DMA **Hardware Abstraction Layer (HAL)** facilitates the configuration of transactions from the users application. Furthermore, it adds an additional layer of safety checks to reduce the risk of faulty memory accesses, data override or infinite loops. -## Previous Definitions -The implementation of this software layer introduced some concepts that need to be understood in order to make proper use of the DMA's functionalities . +The DMA **SDK**, on the other hand, offers user-friendly functions for essential *memcpy* and *fill* operations. It does not include the validation capabilities of the HAL nor the 2D and padding features, prioritizing performance at the cost of an increased risk of inconsistencies. + + +
+ +## Structural description + +![DMA subsystem structure](https://github.com/esl-epfl/x-heep/docs/images/dma_structure.png) + +

Figure 1: Structure of the DMA subsystem in X-Heep

+ +#### DMA channels layout + +The DMA subsystem is composed of a parametrized number of control units called **channels**. +Each channel can be configured, by the CPU or by an external controller, to perform a *transaction*, independently of the state of other channels. + +N-channels are connected to a N-to-M bus that exposes M-master ports on the system bus. **Multiple channels** can thus perform multiple transactions in parallel, a feature that enables memory-intense applications to greatly increase their throuhput. + +There are several ways to connect N-channels to the system bus through M-master ports. + +e.g. +Let's consider a DMA subsystem with N = 4 channels and M = 2 master ports. + +There are two possible solutions: +- CH0, CH1 connected to port 0 & CH2, CH3 connected to port 1 +- CH0, CH1, CH2 connected to port 0 & CH3 connected to port 1 + +In order to specify one among these configurations, the user has to set the `num_channels_per_master_port` parameter in `mcu_cfg.hjson`, which defines the _maximum_ channels per master port ratio. + +The first configuration of the previous example has 2 channels per master port, so a channels per master port ratio of 2. +On the other hand, the second solution has a ratio of 3: the first 3 channels are connected to port 0, while the remaining channel is connected to the remaining port 1. + +While the 1st solution is a general purpose, balanced configuration, the 2nd solution might be better suited for applications that need a low latency channel for high priority tasks. + +This mechanism guarantees **maximum flexibility**, enabling the user to adapt the DMA subsystem to its requirements, both in terms of area and performance. +
+ +#### Interrupts + +If enabled, a transaction interrupt is raised every time a DMA transaction is completed. However, due to architectural limitations, there is only a single transaction done signal for the entire DMA subsystem. + +To allow users to identify which channel raised the transaction interrupt, an **interrupt flag register** system has been developed. Here's how it works: when a DMA channel completes its transaction and the interrupt enable register is correctly set, the transaction **IFR** (Interrupt Flag Register) is set. This register is designed to be cleared automatically once read, which is convenient as it eliminates the need for an additional register write. + +The transaction interrupt handler leverages this mechanism to identify the channel that raised the interrupt. As soon as an IFR is read as high, it triggers the actual handler, which can be redefined by the user. An example of this mechanism at work is explained in [Example 7](#7-multichannel-mem2mem-transaction-focus-on-the-irq-handler). + +It is possible that a channel could raise an interrupt while the CPU is processing a previous interrupt from another channel. This is not an issue because the IFR will remain set until the CPU reads its content. However, this situation could introduce additional delay to the execution of the application. + +For this reason, the handler implemented by the user should be as brief as possible. + +#### Data FIFOs configuration + +Each DMA channel uses FIFOs to buffer the data to be read and written, which is crucial for mitigating the combined delays from the system bus and the Always On Peripheral Bus (**AOPB**). + +The **size of the FIFOs is parametric** and is, by default, the same across all channels. + +Some applications can benefit from larger FIFOs because it allows for more values to be buffered in situations where the bus is heavily utilized or the target peripheral, such as the SPI, is too slow. +On the other hand, other applications might not require such large FIFOs, so area can be saved by reducing its size. +A hybrid system, where some channels have large FIFO sizes and others have smaller ones, could benefit both these types of applications. + +It is possible to specify the size of each DMA channel FIFOs in `dma_subsystem.sv`. +These are the steps to follow to take advantage this feature: + +- Uncomment `//'define EN_SET_FIFO_CH_SIZE;` to enable the mechanism +- Adjust the parameters *LARGE_FIFO_CH_SIZE*, *MEDIUM_FIFO_CH_SIZE* and *SMALL_FIFO_CH_SIZE*. They define the size of a large, medium and small FIFOs. +- Modify the parameter `typedef enum {L, M, S} fifo_ch_size_t;` to assign individual sizes to the FIFOs. The number of elements must reflect the number of DMA channels. + +e.g. + +Let's imagine to configure X-Heep to have 4 channels. These are the definitions of the sizes: +- *LARGE_FIFO_CH_SIZE*: 10 +- *MEDIUM_FIFO_CH_SIZE*: 4 +- *SMALL_FIFO_CH_SIZE*: 2 + +Now, let's set the first 2 channels, CH0 and CH1, to the large size, CH2 to small and CH3 to medium. This is the *fifo_ch_size_t* that would result from that configuration: + +
+
typedef enum {L, L, S, M} fifo_ch_size_t;
+
+ +
+ +#### Triggers + +In the case of memory-peripheral operations, it is common for the peripheral to have a reaction time that cannot match the system clock. For example, the SPI trasmits data with a period of circa 30 clock cycles. + +This difference in response times creates the need for a **communication channel** between DMA subsystem and peripheral allowing the DMA operations to be suspended according to the peripheral state. These signals are called __triggers__. + +They can be used both when the peripheral writes data using the DMA and when the DMA reads data from the peripheral. +The DMA can be configured to respond to triggers by enabling the appropriate _slot_ via software, using the DMA HAL. + +
+ +#### Tips for DMA-based accelerator developers + +The DMA subsystem has been developed with specific features to facilitate the creation of custom accelerators that can leverage it to improve memory-intense applications. + +- **Always-On Peripheral Bus** (AOPB): it exposes the register interface of the units in the Always-On subsystem to any Smart Peripheral Controller (SPC). +In the case of the DMA subsystem, this feature allows the developers to configure the DMA subsystem without any CPU action, reducing power consumption while at the same time increasing the performance and effectiveness of the accelerator. +Check out the _im2col SPC_ in the `\ip_examples` folder for a detailed example. +
+ +- **Triggers**: useful to synchronize the data streams to and from the accelerator. +
+ +- **Stop signal**: it can terminate a DMA transaction at any moment. It's particularly useful for accelerators that produce a large quantity of data, but with a variable trasfer size that cannot be known or computed beforehand. +A good example of such an accelerator is a level crossing subsampler, which writes sampled data only when they cross a specific threshold. +
+ +- **VerifHEEP**: this python library has been developed to test computational units and accelerators deployed on X-Heep. +It has been deployed succesfully to verify the _im2col SPC_ as it is expecially useful for data-driven accelerators. +Additional documentation can be found in the **VerifHEEP documentation**, but in brief it includes methods to: + - Generate random inputs and compute the corresponding golden results + - Launch synthesis & simulations on QuestaSim and Verilator + - Compile, program & launch applications on FPGA targets for a tenfold reduction in test and verification times + - Analyze the performance of the tests. +
+ +### Registers description + +This section will describe every register of a DMA channel and their function. +The complete addres of a DMA channel register is the following: + +

DMA_START_ADDRESS + DMA_CH_SIZE * channel + REGISTER_OFFSET

+ +The previous parameters, including the register offsets, can be found at `sw/device/lib/runtime/core_v_mini_mcu.h` and `sw/device/lib/drivers/dma/dma_regs.h` + +
+ +
+
|-------------- 31 : 0 -------------|
+|-------------- PTR_IN -------------|
+
+ +- **SRC_PTR_REG** + - _SW access_: rw + - _Description_: contains the pointer to the source, which could either be data stored in memory or a peripheral. + +
+ +
+
|-------------- 31 : 0 -------------|
+|------------- PTR_OUT -------------|
+
+ +- **DST_PTR_REG** + - _SW access_: rw + - _Description_: contains the pointer to the destination, which could either be data stored in memory or a peripheral. + +
+ +
+
|-------------- 31 : 0 -------------|
+|------------- PTR_ADDR ------------|
+
+ +- **ADDR_PTR_REG** + - _SW access_: rw + - _Description_: Used only with the [address mode](#transaction-modes) . It contains the pointer to the source, which in this case must data stored in memory. + +
+ +
+
|---- 31 : 14 ----|---- 15 : 0 ----|
+|--- Reserved ----|----- SIZE -----|
+
+ +- **SIZE_D1** + - _SW access_: rw + - _Description_: number of elements (not bytes) to be copied by the DMA channel along the first dimension, i.e. using the first counter. As soon as this register is written, the **transaction starts**. + + +
+ +
+
|---- 31 : 14 ----|---- 15 : 0 ----|
+|--- Reserved ----|----- SIZE -----|
+
+ +- **SIZE_D2** + - _SW access_: rw + - _Description_: number of elements (not bytes) to be copied by the DMA channel along the second dimension, i.e. using the second counter. + +
+ +
+
|---- 31 : 2 ----|--- 1 ---|--- 0 ---|
+|--- Reserved ---|- WIN_DN |-- RDY --|
+
+ +- **STATUS** + - _SW access_: ro + - _Description_: this register is used by the DMA to communicate the status of the transaction. READY is 0 when the DMA is busy performing the transaction, 1 otherwise. + +
+ +
+
|---- 31 : 6 ----|---- 5 : 0 ----|
+|--- Reserved ---|----- INC -----|
+
+ +- **SRC_PTR_INC_D1** + - _SW access_: rw + - _Description_: increment in bytes to apply to the source pointer for every copied element. + +
+ +
+
|--- 31 : 23 --|---- 22 : 0 ----|
+|-- Reserved --|------ INC -----|
+
+ +- **SRC_PTR_INC_D2** + - _SW access_: rw + - _Description_: increment in bytes to apply to the source pointer every time a "row" is copied, in order to go to the new line. It's necessary only for 2D transactions. + From an application perspective, this value has to be computed depending on the size of the input matrix and the 2D stride. Check the functional description paragraph for more information or [Example 4](#4-2d-mem2mem-transaction). + +
+ +
+
|---- 31 : 6 ----|---- 5 : 0 ----|
+|--- Reserved ---|----- INC -----|
+
+ +- **DST_PTR_INC_D1** + - _SW access_: rw + - _Description_: increment in bytes to apply to the destination pointer for every copied element. + +
+ +
+
|--- 31 : 23 --|---- 22 : 0 ----|
+|-- Reserved --|------ INC -----|
+
+ +- **DST_PTR_INC_D2** + - _SW access_: rw + - _Description_: increment in bytes to apply to the destination pointer every time a "row" is copied in order to go to the new line. It's necessary only for 2D transactions. + From an application perspective, this value has to be computed depending on the size of the output matrix and the 2D stride. Check the functional description paragraph for more information. + +
+ +
+
|---- 31 : 16 ----|---- 15 : 0 ----|
+|----- TX_TRG ----|---- RX_TRG ----|
+
+ +- **SLOT** + - _SW access_: rw + - _Description_: identifies the triggers for which the DMA channel will stall in writing and/or reading operations. + +
+ +
+
|---- 31 : 2 ----|---- 1 : 0 ----|
+|--- Reserved ---|---- DATA_T ---|
+
+ +- **SRC_DATA_TYPE** + - _SW access_: rw + - _Description_: defines the source data type using this scheme: + - 0: _word_, i.e. 4 bytes + - 1: _half word_, i.e. 2 bytes + - 2 or 3: _byte_ + +
+ +
+
|---- 31 : 2 ----|---- 1 : 0 ----|
+|--- Reserved ---|---- DATA_T ---|
+
+ +- **DST_DATA_TYPE** + - _SW access_: rw + - _Description_: defines the destination data type using this scheme: + - 0: _word_, i.e. 4 bytes + - 1: _half word_, i.e. 2 bytes + - 2 or 3: _byte_ + If wider than the source datatype and sign extension is enabled, the output data will be sign extended + +
+ +
+
|---- 31 : 1 ----|---- 0 : 0 ---|
+|--- Reserved ---|---- SGND ----|
+
+ +- **SIGN_EXT** + - _SW access_: rw + - _Description_: enables the sign extension, which can be performed only if the output datatype is wider than the source datatype + +
+ +
+
|---- 31 : 2 ----|--- 1 : 0 ---|
+|--- Reserved ---|---- MODE ---|
+
+ +- **MODE** + - _SW access_: rw + - _Description_: defines the operation mode of the DMA channel, following this scheme: + - 0: _linear mode_ + - 1: _circular mode_ + - 2: _address mode_ + +
+ +
+
|---- 31 : 1 ----|---- 0 : 0 ----|
+|--- Reserved ---|--- DIM_CFG ---|
+
+ +- **DIM_CONFIG** + - _SW access_: rw + - _Description_: defines the dimensionality of the transaction, i.e. if the transaction is 1D (DMA_DIM = 0) or if it is 2D (DMA_DIM = 1). + +
+ +
+
|---- 31 : 1 ----|--- 0 : 0 ---|
+|--- Reserved ---|---- INV ----|
+
+ +- **DIM_INV** + - _SW access_: rw + - _Description_: enables the transposition of the input source, only with 2D transactions. + +
+ +
+
|---- 31 : 6 ----|--- 5 : 0 ---|
+|--- Reserved ---|---- PAD ----|
+
+ +- **PAD_TOP/BOTTOM/RIGHT/LEFT** + - _SW access_: rw + - _Description_: defines the size of the padding to be applied to the source, in data units. + +
+ +
+
|---- 31 : 13 ---|--- 12 : 0 ---|
+|--- Reserved ---|---- W_SZ ----|
+
+ +- **WINDOW_SIZE** + - _SW access_: rw + - _Description_: defines the size of the window to be copied. + +
+ +
+
|---- 31 : 8 ----|---- 7 : 0 ---|
+|--- Reserved ---|---- W_CNT ---|
+
+ +- **WINDOW_COUNT** + - _SW access_: ro + - _Description_: indicates the number of times the end of the window was reached since the beginning of the transaction. + +
+ +
+
|---- 31 : 2 ----|-- 1 ---|-- 0 ---|
+|--- Reserved ---|- W_DN -|- T_DN -|
+
+ +- **INTERRUPT_EN** + - _SW access_: rw + - _Description_: enables the interrupt for window and/or transaction done. + + +
+ +
+
|---- 31 : 1 ----|--- 0 : 0 ---|
+|--- Reserved ---|--- FLAG ----|
+
+ +- **TRANSACTION_IFR** + - _SW access_: r0 + - _Description_: interrupt flag register for transaction interrupts. It is set to '1' when the transaction interrupts are enabled and the transaction is completed. It is cleared when it's read by the CPU in the IRQ handler. This feature enables the handler to identify which channel raised the interrupt, as explained [here](#interrupts). + +
+ +
+
|---- 31 : 1 ----|--- 0 : 0 ---|
+|--- Reserved ---|--- FLAG ----|
+
+ +- **WINDOW_IFR** + - _SW access_: r0 + - _Description_: interrupt flag register for window interrupts. It is set to '1' when the window interrupts are enabled and the window is done. It is cleared when it's read by the CPU in the IRQ handler. + + +## Functional description + +### Dictionary + +The implementation of the software layer introduced some concepts that need to be understood in order to make proper use of the DMA's functionalities. + + + +#### Transaction + +A transaction is an operation to be performed by the DMA. It implies copying bytes from a source pointer into a destination pointer. +The transaction configuration can be cross-checked before loading it into the DMA registers to avoid potential issues. +The transaction starts only when the size of the *first dimension*, i.e. 1D, of the transaction is written in its corresponding register. The transaction is finished once the DMA has sent all its bytes (which not necessarily means they have been received by the final destination) or when the _external stop signal_ is asserted. + +While a transaction is running, new transactions can be validated, loaded and launched, provided they are not targeting the same DMA channel. -### Transaction -A transaction is an operation to be performed by the DMA. It implies copying bytes from a source pointer into a destination pointer. The transaction configuration can be loaded into the DMA registers once it has been cross-checked and it only starts when the size of the transaction is written in its corresponding register. The transaction is finished once the DMA has sent all its bytes (which not necessarily means they have been received by the final destination). -Transactions cannot be stopped once they were launched. -While a transaction is running, new transactions can be validated, but not launched or loaded into the DMA. Transactions can be re-launched automatically in `circular mode`. -Once the transaction has finished, a status bit is changed (that can be monitored through polling) and a fast interrupt is triggered. -### Source and destination -Sources and destinations are the two pointers that will exchange data. Bytes will be copied from the source and into the destination address. +Once the transaction has finished, a status bit is changed (that can be monitored through polling) and a fast interrupt is triggered. The channel that raised the interrupt is identified and it's passed to the the handler itself, which can be redefined by the user, as shown in [Example 7](#7-multichannel-mem2mem-transaction-focus-on-the-irq-handler) or in `example_dma_multichannel` in the application folder. + + +#### Source and destination + +Sources and destinations are the two pointers that will exchange data. Bytes will be copied from the source and into the destination address. + + +#### Data type -### Data type The DMA allows transactions in chunks of 1, 2 or 4 Bytes (`Byte`, `Half-Word` and `Word` respectively). The size in bytes of the chosen data type is called _data unit_ (usually abbreviated as `du`). + For example, 16 bytes can be 16 data units if the data type is `Byte`, but 8 data units if the data type is `Half Word`. +Source and destination can have different data types and if the destination type is larger than the source type, data can be sign extended. + +#### Sign extension +It can be enabled by setting the bit in the corresponding [register](#registers-description). +If the destination data type is larger than the source type, the source data is sign extended to fill up the size of the destination data type. + + +#### Dimensionality + +The DMA can perform both **1D transactions** and **2D transactions**. +In a 1D transaction, the DMA copies a certain number of elements from the source pointer to the destination pointer using a single increment. +On the other hand, in a 2D transaction the DMA copies data from the source pointer to the destination pointer using two separate increments, which can be interpreted as a 1D and a 2D increment. +In this way, two-dimensional data manipulations, i.e. matrix manipulations, can be performed in a single DMA transaction. + +#### Increment + +In a 1D transaction, setting the increment appropriately can be leveraged to achieve non-contiguous read and/or write operations. + +For example, let's consider an array of 4 word-type elements. +To copy just the first 2 bytes of each word, follow these steps: + +- Set the datatype of the transaction to **half word**. +- Set the source increment to **2 data units**. +- Set the destination increment to **1 data unit**. + +After each reading operation, the DMA will increment the read pointer by 4 bytes (2 data units) and the write pointer by 2 bytes. + +In the case of 2D transactions, a second increment must be set to perform matrix manipulations. +The 2D increment can be interpreted as the number of words that the DMA has to "skip" to move to the next row of the matrix. + +For example, let's examine the extraction of a contiguous 2x2 matrix from a 4x4 matrix. + + | 3 | 5 | 7 | 9 | + | 2 | 4 | 6 | 8 | -> | 3 | 5 | + | 1 | 3 | 5 | 7 | | 2 | 4 | + | 0 | 2 | 4 | 6 | -### Increment -In the case that source and/or destination data are not to be consecutively read/written, a certain increment can be defined. -For instance, if you have an array of 4-bytes-words, but only want to copy the first 2 bytes of each word, you could define the transaction with a data type of half word, an increment of 2 data units in the source, and 1 data unit in the destination. This way, after each read operation the DMA will increment the read pointer in 4 bytes (2 data units), but the write pointer by only 2 bytes. +The total number of elements copied from the source is 4. +In order to achieve this result, these are the setup of the increments: + - For the source: + - 1D increment set to 1 word + - 2D increment set to 3 words + - For the destination: + - 1D increment set to 1 word + - 2D increment set to 1 word -### Alignment -When doing transactions with bytes, the DMA can read/write from any pointer. However, if the data type is larger, words should be aligned so the DMA can perform a read/write operation and affect only the chosen bytes. If a word or half-word's pointer is not a multiple of 4 or 2 (respectively), the pointer is _misaligned_. In some cases the DMA HAL can overcome this problem reducing the data type (which will reflect on an efficiency loss). +Moreover, by exploiting the 2D increment, it is possible to implement a 2D non-continuous read and/or write. -### Environment -An environment is a region of memory that can optionally be defined by the user to let the HAL know that it is allowed to read/write on that region. It is useful to make sure the DMA will not affect reserved memory regions. -Right now, read and write permissions are not supported by environments, meaning that if it is defined, the DMA will be able to read AND write on it. +Detailed formulas for the computation of 2D increments are reported in the example application in the `\example_dma_2d` folder. + +#### Zero padding -### Triggers and Slots -If the source or destination pointer is a peripheral, there are lines connecting the peripheral and the DMA that can be used to control the data flow (they behave as _triggers_). These lines are connected to _slots_ on the DMA and they allow/stop the DMA from reading/writing data. -### Target -A target is either a region of memory or a peripheral to which the DMA will be able to read/write. When targets are pointing to memory, they can be assigned an environment to make sure that they will comply with memory restrictions. -Targets include a pointer (a point in the memory, or the Rx/Tx buffer in case of peripherals), a size to be copied (if its going to be used as a source), a data type and an increment. +The DMA is capable of performing zero padding on the extracted data, both in 1D and 2D transactions, within a single transaction. +This is achieved by setting four padding parameters: + +- **T**op +- **B**ottom +- **L**eft +- **R**ight + +e.g. Let's consider a 2x3 matrix: + + | T | T | T | T | T | + | L | x | x | x | R | + | L | x | x | x | R | + | B | B | B | B | B | + + +It's important to highlight that the padding is performed (conceptually) only *after* the matrix has been extracted. +So the padding parameters refers only to the extracted matrix, not to the entire source matrix. + +Let's revisit the previous 2x2 extraction example, this time adding a left and top padding of 1 element: + + + | 3 | 5 | 7 | 9 | | 0 | 0 | 0 | + | 2 | 4 | 6 | 8 | -> | 0 | 3 | 5 | + | 1 | 3 | 5 | 7 | | 0 | 2 | 4 | + | 0 | 2 | 4 | 6 | + + +#### Alignment + +When performing transactions with bytes, the DMA can read/write from any pointer. However, if the data type is larger, words should be aligned so the DMA can perform a read/write operation and affect only the chosen bytes. +If a word or half-word's pointer is not a multiple of 4 or 2 (respectively), the pointer is _misaligned_. In some cases the DMA HAL can overcome this problem by reducing the data type (which will reflect on an efficiency loss). + + + +#### Environment + +An environment is a user-defined region of memory that informs the HAL of permissible read/write areas. This ensures that the DMA does not interfere with reserved memory regions. + +Read and write permissions are not supported by environments. If an environment is defined, the DMA will have both read and write access to it. + + +#### Target + +A target is either a memory region or a peripheral that the DMA can read from or write to. When targets point to memory, they can be assigned an environment to ensure compliance with memory restrictions. + +Targets include: + +- A pointer (either a memory location or the Rx/Tx buffer for peripherals) +- A size to be copied (if used as a source) +- A data type +- An increment + + + +#### Configuration flags -### Configuration flags During the creation or configuration of environments, targets or transactions, there could be inconsistencies or threatening situations (like writing outside the boundaries of a defined region). To provide the user with information about this potentially harmful situations, configuration flags are set while creating each of these entities. They can be unmasked and checked. + In some cases, when the threat is too risky, a _crucial error_ might be raised and the operation of the configuration is halted. + If senseless configurations are input to functions, assertions may halt the whole program. This is reserved for extreme situations that mean the program was not properly coded (e.g. a slot value is provided and is not among the available ones). -### Transaction modes + + +#### Transaction modes + There are three different transaction modes: -**Single Mode:** The default mode, where the DMA will perform the copy from the source target to the destination, and trigger an interrupt once done. -**Circular mode:** To take full advantage of the speed and transparency of the DMA, a _circular_ mode was implemented. When selected, the DMA will relaunch the exactly same transaction upon finishing. This cycle only stops if by the end of a transaction the _transaction mode_ was changed to _single_. The CPU receives a fast interrupt on every transaction finished. -**Address Mode:** Instead of using the destination pointer and increment to decide where to copy information, an _address list_ must be provided, containing addresses for each data unit being copied. It is only carried out in _single_ mode. -### Windows -In order to process information as it arrives, the application can define a _window size_ (smaller than the _transaction size_. Every time the DMA has finished sending that given amount of information will trigger an interrupt through the PLIC. +**Single Mode:** The default mode, where the DMA channel will perform the copy from the source target to the destination, and trigger an interrupt once done. + +**Circular mode:** It takes full advantage of the speed and transparency of the DMA. When selected, the DMA will relaunch the exact same transaction upon finishing. This cycle only stops if by the end of a transaction the _transaction mode_ was changed to _single_. The CPU receives a fast interrupt on every transaction finished. + +**Address Mode:** Instead of using the destination pointer and increment to decide where to copy information, an _address list_ must be provided, containing addresses for each data unit being copied. It is only carried out in _single_ mode. +In this mode it's possible to perform only 1D transactions. + + + +#### Windows + +In order to process information as it arrives, the application can define a _window size_ (smaller than the _transaction size_). Every time the DMA has finished sending that amount of information, it will trigger an interrupt through the PLIC. + > :warning: If the window size is a multiple of the transaction size, upon finishing the transaction there will be first an interrupt for the whole transaction (through the FIC), and then an interrupt for the window (through the PLIC, which is slower). + + + +#### Checks and Validations -### Checks and Validations The DMA HAL's interface functions perform two types of checks: -* **Sanity checks**: Make sure that each individual value passed as an argument is reasonable and belongs to the proper domain. This errors will raise an _assertion_ and, depending on how assertions are managed in the application, may result in the program crashing. -* **Integrity checks**: Arguments are cross-checked to make sure that they abide by the rules of the DMA. If configurations are incompatible, contradictory, or a risk for the programs integrity, warnings are raised through the _configuration flags_. In some special cases, a _critical error_ can be raised, which blocks the deployment of the configuration into the DMA registers. + +* **Sanity checks**: Make sure that each individual value passed as an argument is reasonable and belongs to the proper domain. This errors will raise an _assertion_ and, depending on how assertions are managed in the application, may result in the program crashing. + +* **Integrity checks**: Arguments are cross-checked to make sure that they abide by the rules of the DMA. If configurations are incompatible, contradictory, or a risk for the programs integrity, warnings are raised through the _configuration flags_. In some special cases, a _critical error_ can be raised, which blocks the deployment of the configuration into the DMA registers. + + > :warning: Integrity checks can be disabled to speed up configuration time. Do this only if you have previously checked the configuration and are sure it will not cause any trouble. + + Checks and validations are performed during the transactions creation, loading and launching. + + A transaction is validated if it went through the creation-checks without raising critical errors. -### End events -The DMA considers a certain amount of bytes to have been transferred once it has sent them. It does not wait for a confirmation from the recipient. When a transaction/window is finished the DMA performs a series of event. These may include: + + +#### End events + +The DMA considers a certain amount of bytes to have been transferred once it has sent them. It does not wait for a confirmation from the recipient, but can be interrupted at any time using the `ext_dma_stop` signal. +When a transaction/window is finished the DMA performs a series of events. These may include: + * Changing its status register. + * Raising a _transaction done_ interrupt. + * Raising a _window done_ interrupt. -The DMA HAL can follow up on these changes or let the application be in charge. For this purpose, three different types of _end events_ are defined: -* **Polling**: The HAL will disable interrupts from the DMA. The application will need to frequently query the status of the DMA to know when a transaction has finished. -* **Interrupt**: Interrupts will be enabled. The _window done interrupt_ is enabled if a window size is provided. -* **Interrupt wait**: The DMA HAL will block the program in a `wfi()` state until the _transaction done interrupt_ is triggered. + +The DMA HAL can follow up on these changes or let the application be in charge of them. For this purpose, three different types of _end events_ are defined: -## Operation -This section will explain the operation of the DMA through the DMA HAL. -There is a DMA instance inside X-HEEP, but others can be connected outside through the bus (see the `example_external_peripheral` application in `sw/aplications/example_external_peripheral/main.c`). As long as the DMA instance is the same and the registers are memory mapped with the same structure, the DMA HAL can be used. +* **Polling**: The HAL will disable interrupts from the DMA. The application will need to frequently query the status of the DMA to know when a transaction has finished. -The DMA HAL adds an extra computational overhead to transactions in order to check the consistency of the transaction configurations. By-passing this layer (and the steps here described) is disadvised. For the efficiency-hungry applications, doing at least one pass with the whole validation process is recommended. The HAL allows to load and launch transactions with minimum overhead afterwards. +* **Interrupt**: Interrupts will be enabled. The _window done interrupt_ is enabled if a window size is provided. -The following explanation makes use of Figure 1. +* **Interrupt wait**: The DMA HAL will block the program in a `wfi()` state until the _transaction done interrupt_ is triggered. -![DMA HAL-HW + addresses](https://github.com/esl-epfl/x-heep/assets/54960111/3092faa5-c72c-4cd9-a4d4-4c87de63d1c7) -

Figure 1: Example operation of the DMA and its HAL

---- +## Software stack: HAL and SDK + +Like every other computational unit in X-Heep, a DMA transaction can be set up and launched using direct register writes. This method achieves minimal overhead and optimal performance, as thoroughly documented in `sw/applications/example_dma_2d` and `sw/applications/example_dma_multichannel`. -The use of the DMA starts with the application creating a set of targets (**a**) . In the figure, the source target is a peripheral connected to an SPI and to the DMA. The address of the reception FIFO (_Rx FIFO_) of this SPI is `0x70` (**b**) . The destination target is a region of memory of address `0x16` (**c**). It is located inside an environment that spans from `0x12` to `0x35`. Any number of environments and targets can be created, and not used. +However, this strategy carries **significant risks**. For instance, the transaction starts immediately after writing to the size register, so the order of register writes must be strictly followed. If the code is compiled with aggressive optimization flags, these write operations might be reordered, potentially compromising the DMA functionality. Additionally, errors in setting the transaction size or increments can lead to memory corruption. -Additionally, in the application the transaction is created. The _operation mode_ and _window size_ are selected. +Given the criticality of DMA operations and the potential for destructive errors, direct register writes should be approached with utmost _caution_. To mitigate these risks and ease the application development, two software stacks have been developed: -The application calls the validation function of the HAL. If the configurations do not raise a critical flag, it then calls the loading function. By doing so, the desired values are written into their corresponding registers (**d**). The only register that is not immediately written is the _transaction size_, as it is the one responsible for launching the transaction when changed from zero to a non-zero value. It is only written once the application calls the launching function (**e**). +- **HAL**: Provides functions for initializing DMA channels, validating and correcting issues within the targets, loading and launching transactions. +
-Note that there could be some changes between the configuration input in the application and the values written in the registers. For example, a _window size_ of 2 refers to _2 data units_ (i.e. 2 half-words, as such is the data type of the source in Figure 1); however, when writing on the register, this is translated to bytes, so 4 is written instead. +- **SDK**: Offers user-friendly functions for basic but essential *memcpy* and *fill* operations. It does not include the validation capabilities of the HAL nor the 2D and padding features, prioritizing performance at the cost of an increased risk of failure. -Once launched, the transaction will execute completely (it cannot be stopped). Upon finishing, it will check the _operation mode_ and _transaction size_ registers. If any of both is non-zero, it will relaunch. Note that the selecting _circular mode_ during the configuration loading does not launch the transaction (despite what step (**f**) might suggest, which is only illustrative). +### DMA HAL +This section will include a brief overview of the functionalities offered by the DMA HAL. For more practical example, please refer to the next chapter, _"Usecases and examples"_. -Once the transaction is launched, the DMA will take care of copying as many data units as were requested from the source target (**g**), and pasting them into the destination target (**h**). The data width of the transaction is determined by the _data type_ of the source target (**i**). However, this might be changed (for a smaller width) in case of misalignment. It is possible to reject changes by the DMA HAL and raise an error in case of misalignments instead. +Let's start with the structures that enable users to define a DMA transaction and its targets, defined in `dma.h`: -The selected slot will query the state of a trigger from the peripheral (**j**). In case the peripheral's FIFO is empty/full (for reception/transmission respectively), the transaction is paused until the trigger enables it again. +> :warning: Remember to declare these structure as **global**, i.e. outside the main() function, or **static** if they need to be local. This is **critical** as it ensures that the fields that are not needed are initialized correctly. -The source and destination increments will determine the amount of steps the pointer should jump after every read and write, respectively. For peripherals it should always be zero (as it should always take the first element of the FIFO). +#### dma_target_t -The DMA will consider a data unit was transferred once it is sent (**k**). It does not wait for an acknowledge by the destination target. +The dma_target_t structure represents a target for a DMA transaction, either as a source or a destination. It encapsulates the parameters required to define a memory region or a peripheral for DMA operations. Furthermore, control parameters can be added to prevent the DMA from reading/writing outside the boundaries of the target. -The _interrupts_ register controls whether the events triggered by the DMA upon finishing a window or a whole transaction should be propagated as interrupts (**l**). +#### dma_trans_t -Every time _window size_ data units have been transferred the window count is incremented and a PLIC interrupt is triggered (if enabled) (**m**). +The dma_trans_t structure defines a DMA transaction, encapsulating all the necessary parameters and configurations required to perform a DMA operation. Each member of the structure is designed to handle specific aspects of the transaction, from source and destination targets to increments, transaction sizes, data types, and operational modes. +
+Let's examine the main functions to be called in order to correctly perform a DMA transaction. -Every time a transaction is finished a FIC interrupt is triggered and the restart condition is evaluated (**f**). +#### dma_init() -If the window size is a multiple of the transaction size, upon finishing the transaction there will be first an interrupt for the whole transaction (through the FIC), and then an interrupt for the window (through the PLIC, which is slower). +*Purpose*: +The dma_init function initializes the DMA subsystem by cresetting transaction structures and clearing DMA registers of each channel. +*Parameters*: +- dma *dma_peri: Pointer to the DMA peripheral. If this pointer is provided, it uses the given DMA peripheral; otherwise (NULL), it uses the integrated DMA peripheral. -The DMA HAL has weak implementations to handle each interrupt. It is up to the application to do something useful with this. the HAL will only forward the interrupt (**n**). +#### dma_validate_transaction() -> :warning: If the window size is too small (i.e. the time the DMA requires to make the copy is smaller than the time required to attend the interrupt handling), data might be lost. The HAL implements a warning in case the transaction-window size ratio is to small. The warning can be re-configured to an appropriate threshold by overriding a weak implementation. The user should do its own testing and choose this threshold accordingly. The same type of issue might be found on circular mode. The user should be sure it can attend an interrupt before the next one occurs. There is no warning from the HAL in this case. +_Purpose_: +The dma_validate_transaction function ensures the configuration of a DMA transaction is correct, checking for potential issues that could prevent the transaction from executing properly. It performs sanity checks, verifies target configurations, and addresses any alignment, increment, padding, trigger, and mode inconsistencies. -The same result from this example could have been achieved by setting the transaction mode to _address_. It requires an array of destination addresses (**p**) that must be provided as the destination target pointer. Instead of copying information to that pointer, the DMA will read from there and copy the information into the addresses stored in each word (**o**). -This use case is very impractical as it doubles the memory usage. It is intended to be used along In-Memory-Computing architectures and algorithms. +_Parameters_: +- dma_trans_t *p_trans: Pointer to the DMA transaction structure that contains the transaction configuration. +- dma_en_realign_t p_enRealign: Flag indicating whether realignment is enabled. +- dma_perf_checks_t p_check: Flag indicating whether integrity checks should be performed. -## Usage -This section will explain a basic usage of the DMA as a `memcpy`, and a slightly more complex situation involving a peripheral connected via an SPI. +_Return Values_: +- dma_config_flags_t: Configuration flags indicating the status of the transaction validation. They provide information about the validity of the transaction and any detected errors or warnings. -### Basic application -This example will provide a simplified code for copying data from one region of memory to another. For a real implementation please refer to the `dma_example` application in `sw/applications/dma_example/main.c`. +#### dma_load_transaction() -The objective of this app would be to copy the content of an array into another. +_Purpose_: +The dma_load_transaction function configures and loads a DMA transaction into a DMA channel. It checks for critical errors defined by the validation function, ensures no other transaction is running, and sets various parameters such as interrupts, pointers, increments, padding, and operation modes by writing in the correct registers. The only register that is not written is the +SIZE_D1 register so it doesn't launch the transaction. ---- +_Parameters_: +- dma_trans_t *p_trans: Pointer to the DMA transaction structure that contains the configuration for the transaction. -Start the application by calling -```C -dma_init( NULL ); -``` +_Return Values_: +- DMA_CONFIG_OK: Indicates that the transaction was successfully loaded. +- DMA_CONFIG_CRITICAL_ERROR: Indicates that the transaction contains a critical error and cannot be loaded. +- DMA_CONFIG_TRANS_OVERRIDE: Indicates that another transaction is currently running and cannot be overridden. + +#### dma_launch() + +_Purpose_: +The dma_launch function initiates a DMA transaction that has been previously configured and loaded into a DMA channel. It ensures the transaction is valid, checks for any ongoing transactions, and then starts the new transaction. If the end event is set to wait for an interrupt, the function will block until the interrupt is received. + +_Parameters_: +- dma_trans_t *p_trans: Pointer to the DMA transaction structure that contains the configuration for the transaction. + +_Return Values_: +- DMA_CONFIG_OK: Indicates that the transaction was successfully launched. +- DMA_CONFIG_CRITICAL_ERROR: Indicates that the transaction could not be launched due to a critical error. +- DMA_CONFIG_TRANS_OVERRIDE: Indicates that another transaction is currently running and cannot be overridden. + +#### fic_irq_dma() -This will reset the DMA registers. The `NULL` parameter tells the HAL that the devices internal DMA is to be used. +_Purpose_: +The *fic_irq_dma* function is called whenever one of the DMA channels raises the fast interrupt line, signaling the FIC (Fast Interrupt Controller) that a transaction has completed. As thoroughly explained in Example 7 of the next section, this function identifies the channel that triggered the interrupt and calls a handler function, *dma_intr_handler_trans_done()*, passing the channel ID. -The most basic implementation requires the creation of **two targets** and a **transaction** relating them both. +This function can be redefined by the user to perform specific actions, provided that the computational load of these tasks is kept to a minimum. -A target will include the information of the source or destination pointer and the characteristics of the expected transaction. +_Parameters_: +- None -Theoretically, there is no required difference between a _source_ and _destination_ target. They will only be differentiated once the transaction is created. Eventually, they could be interchanged from one transaction to the next. In this example they will be given explicit names and will take different arguments for the sake of clarity. +_Return Values_: +- None (void type) + +
+ +#### handler_irq_dma() + +_Purpose_: +The *handler_irq_dma* function is very similar to *fic_irq_dma*, but its called whenever one of the DMA channels triggers a window donw interrupt, i.e. the transaction has copied N elements. Just like the previous one, this function identifies the channel that triggered the interrupt and calls a handler function, *dma_intr_handler_window_done()*, passing the channel ID. + +_Parameters_: +- None + +_Return Values_: +- None (void type) + +
+ +## Usecases and examples + +This section will examine and explain several use cases in detail to provide users with a comprehensive understanding of the DMA subsystem and how to leverage it to enhance their application's performance. + +These examples focus on the use of the DMA HAL and the padding and multichannel capabilities of the DMA. The DMA SDK is straightforward enough to be fully understood through the structural and operational descriptions provided in the previous sections. + +Here is a brief overview of the examples: + +1) Simple mem2mem transaction, i.e., 1D memcpy +2) Simple mem2mem transaction with address mode +3) Sign extension +4) 2D mem2mem transaction, i.e., 2D memcpy +5) Matrix transposition +6) Matrix zero padding +7) Multichannel mem2mem transaction, focusing on the IRQ handler +8) Multichannel flash2mem transaction using the SPI FLASH + +The complete code for these examples can be found in `sw/applications/example_dma`, `sw/applications/example_dma_2d`, `sw/applications/example_dma_multichannel` and `sw/applications/example_dma_sdk`. These applications offer both verification and performance estimation modes, enabling users to verify the DMA and measure the application's execution time. + +The user is strongly incouraged to look at these applications, as well as any other application that employs the DMA, to gain insight in practical examples of the use of this peripheral. Some aspects or specific usecases might in fact not be present in this guide and could be found in the applications. + +> :warning: If you have any relevant questions about the DMA or other topics, feel free to open a _question_ on our GitHub repository page! + +
+ +### 1. Simple mem2mem transaction + +The goal of this example is to develop a function that copies the content of a source array to a destination array. + +Let's start! + +#### Setting targets & transaction structs + +The first step is to define the source and destination target structs, as well as the transaction structs. + +> :warning: Declare the targets and the transaction structs globally to ensure that the fields unused in this example are automatically initialized to zero. +This practice prevents unintentional data corruption or unexpected behavior during the DMA transaction. + +In this example, an array of six 32-bit words is used. +The data type for both the source and destination is specified in the `.type` field of their respective dma_target_t structures. +Since the data is stored in RAM, the trigger, `.trig`, will be the default one, i.e. *DMA_TRIG_MEMORY*. + +In this example, a 4-element array will be extracted from the 6-element source. The size of the transaction, which is the number of elements to be copied, is specified in `.size_d1_du`. + +The transaction mode will be set to single mode, so the `.mode` field will be configured as *DMA_TRANS_MODE_SINGLE*. +Finally, let's set the end event, `.end`, to *DMA_TRANS_END_INTR_WAIT*, to leave the HAL to wait for the interrupt. ```C -static dma_target_t tgt_src = { - .ptr = copy_buffer, - .inc_du = 1, - .size_du = sizeof(copy_buffer), - }; + + int size = 4; + uint32_t src[6] = {0x12345678, 0x76543210, 0xfedcba98, 0x579a6f90, 0x657d5bee, 0x758ee41f}; + uint32_t dst[4]; + + dma_target_t tgt_src = { + .ptr = (uint8_t *) src, + .inc_d1_du = 1, + .type = DMA_DATA_TYPE_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_target_t tgt_dst = { + .ptr = (uint8_t *) dst, + .inc_d1_du = 1, + .type = DMA_DATA_TYPE_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_trans_t trans = { + .src = &tgt_src, + .dst = &tgt_dst, + .size_d1_du = size, + .src_addr = NULL, + .mode = DMA_TRANS_MODE_SINGLE, + .win_du = 0, + .end = DMA_TRANS_END_INTR_WAIT, + }; + ``` -Here, `ptr = copy_buffer` is a `uint32_t` pointer from where the information will be extracted. `inc_du = 1` is telling the DMA that for each word copied, the pointer should be incremented by 1 unit, therefore words will be copied consecutively without gaps. +#### Perform validation, loading and launching -This configuration is implicitly initializing the rest of the target configurations as zero (as of [C99](https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html)). This means that: -* No environment is set. -* Data type is set to _word_ (32-bits). -* The trigger is set to _memory_ (vs. a peripheral). +This second step is also the final one! The only thing left to do is to perform the __validation__ of the transaction, __load__ the parameters, and __launch__ of it. For convenience, let's put these calls inside a dedicated function, called *run_dma_trans()*. -The destination target can also dispense of a size, as the source size will be used. +The *DMA_ENABLE_REALIGN* flag signals the HAL to perform realignment when necessary. Similarly, the *DMA_PERFORMS_CHECKS_INTEGRITY* flag instructs the HAL to perform integrity checks. -```C -static dma_target_t tgt_dst = { - .ptr = copy_buffer, - .inc_du = 1, - }; +The return values of these HAL calls will be stored and returned to check for any potential issues. + +``` C + +dma_config_flags_t run_dma_trans(dma_trans_t *trans) +{ + dma_config_flags_t res; + + res = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + res |= dma_load_transaction(&trans); + res |= dma_launch(&trans); + + return res; +} + ``` -Finally, a transaction is created to relate both targets: +The datatype *dma_config_flags_t* is defined in the HAL header and is provided below for convenience: + +``` C + +typedef enum +{ + DMA_CONFIG_OK = 0x0000, /*!< DMA transfer was successfully + configured. */ + DMA_CONFIG_SRC = 0x0001, /*!< An issue was encountered in the + source arrangement. */ + DMA_CONFIG_DST = 0x0002, /*!< An issue was encountered in the + destination arrangement. */ + DMA_CONFIG_MISALIGN = 0x0004, /*!< An arrangement is misaligned. */ + DMA_CONFIG_OVERLAP = 0x0008, /*!< The increment is smaller than the + data type size. */ + DMA_CONFIG_DISCONTINUOUS = 0x0010, /*!< The increment is larger than the + data type size. */ + DMA_CONFIG_OUTBOUNDS = 0x0020, /*!< The operation goes beyond the + memory boundaries. */ + DMA_CONFIG_INCOMPATIBLE = 0x0040, /*!< Different arguments result in + incompatible requests. */ + DMA_CONFIG_WINDOW_SIZE = 0x0080, /*!< A small window size might result + in loss of syncronism. If the processing of the window takes longer than the + time it takes to the DMA to finish the next window, the application will not + be able to cope. Although "how small is too small" is highly dependent on + the length of the processing, this flag will be raised when the transaction + and window size ratio is smaller than an arbitrarily chosen ratio as a mere + reminder. This value can be overriden buy means of defining a non-weak + implementation of the dma_window_ratio_warning_threshold function. */ + DMA_CONFIG_TRANS_OVERRIDE = 0x0100, /*!< A transaction is running. Its + values cannot be modified, nor can it be re-launched. */ + DMA_CONFIG_CRITICAL_ERROR = 0x0200, /*!< This flag determines the function + will return without the DMA performing any actions. */ +} dma_config_flags_t; -```C -static dma_trans_t trans = { - .src = &tgt_src, - .dst = &tgt_dst, - }; ``` -This will also imply some configurations set to zero: -* Mode is set to singular (only one transaction will be executed). -* There will be no window interrupts. -* The application will have to do polling to know when the transaction has finished. +Now, the function can be called inside the `main` function, and the flags should be checked to ensure the transaction was executed correctly. -The transaction can now be created (some extra configurations are computed from the targets), loaded into the DMA and launched. +``` C -```C -dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); -dma_load_transaction( &trans ); -dma_launch( &trans ); +... + +int main() +{ + dma_init(NULL); + + dma_config_flags_t result = run_dma_trans(); + + if (result != 0) + { + printf("Error! DMA transaction failed with code: %d\n", result); + return 1; + } else { + printf("Success!\n"); + return 0; + } +} ``` +
-When creating the transaction, the two last parameters are allowing the DMA to perform integrity checks and try some fixes (at the expense of efficiency) if misalignments are found. +### 2. Simple mem2mem transaction with address mode -As there will be no interrupts set, the application has to check by itself the status of the transaction. +The goal of this example is to develop a function that copies the content of a source array to a destination array using the address mode. + +Let's start! + +#### Setting targets & transaction structs + +Just like in example 1., the first step is to define the source and destination target structs, as well as the transaction structs. + +This time, the address mode will be used. The DMA channel will use the content of an array as destination pointers, instead of computing them itself. These addresses will be generated in the *main()* as showed later on. ```C -while( ! dma_is_ready() ){} -// The transaction has finished! + + int size = 4; + uint32_t src[6] = {0x12345678, 0x76543210, 0xfedcba98, 0x579a6f90, 0x657d5bee, 0x758ee41f}; + uint32_t dst[size]; + uint32_t addr[6]; + + dma_target_t tgt_src = { + .ptr = (uint8_t *) src, + .inc_d1_du = 1, + .type = DMA_DATA_TYPE_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_target_t tgt_dst = { + .ptr = (uint8_t *) dst, + .inc_d1_du = 1, + .type = DMA_DATA_TYPE_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_target_t tgt_addr = { + .ptr = (uint8_t *) addr, + .inc_d1_du = 1, + .trig = DMA_TRIG_MEMORY, + }; + + dma_trans_t trans = { + .src = &tgt_src, + .dst = &tgt_dst, + .src_addr = &tgt_addr; + .size_d1_du = size, + .src_addr = NULL, + .mode = DMA_TRANS_MODE_ADDR, + .win_du = 0, + .end = DMA_TRANS_END_INTR_WAIT, + }; + ``` +#### Perform validation, loading and launching -### Complete Application -The objective of this example is to show various special cases, precautions and considerations that can be taken. For a real example refer to the `spi_flash_write` application in `sw/applications/spi_flash_write/main.c`. +Once again, only two steps! Time to perform the __validation__ of the transaction, __load__ the parameters, and __launch__ of it. +Let's put these calls inside a dedicated function, called *run_dma_addr_trans()* and launch it in the *main()*. Finally, let's add a simple for loop to print out the result, i.e. the extracted matrix. -This example will copy every other byte from a buffer in RAM to a FLASH connected via an SPI to the DMA. Then, it will copy information from an SPI peripheral continuously into a small buffer. +``` C -This explanation assumes you have read the previous example. +dma_config_flags_t run_dma_addr_trans(dma_trans_t *trans) +{ + dma_config_flags_t res; + + res = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + res |= dma_load_transaction(&trans); + res |= dma_launch(&trans); ---- + return res; +} + +... + +int main() +{ + dma_init(NULL); + + // Data setup for address mode + for (int i = 0; i < 6; i++) + { + addr[i] = &src[i]; + } + + dma_config_flags_t result = run_dma_addr_trans(); + + if (result != 0) + { + printf("Error! DMA transaction failed with code: %d\n", result); + return 1; + } else { + printf("Success!\n"); + return 0; + } +} -Start the application by calling -```C -dma_init( NULL ); ``` +
+ +### 3. Sign extension + +The goal of this example is to develop a function that transforms an array of bytes in an array of words, performing sign extension when necessary. + +Many examples of sign extensions are present in *TEST_SINGLE* in `example_dma`. + +Let's start! + +#### Setting targets & transaction structs + +First step: define the source and destination target structs, as well as the transaction structs. This time, it's important to pay attention to the data types and ensure that the sign extension feature is enabled. -The first source target will be pointing to a `uint16_t` buffer in memory. Data will be copied in chunks of 1 byte. For every half-word (16 bits), the only the second half (second 8 bits) will be copied. ```C -static dma_target_t tgt1= { - .ptr = (uint8_t*)(copy_buffer + 1), - .inc_du = 2, - .size_du = sizeof(copy_buffer), - .type = DMA_DATA_TYPE_BYTE, -}; + + #define SIZE 6 + uint8_t src[SIZE] = {0xe7, 0x32, 0x89, 0x0a, 0x12, 0xfd}; // {-25, 50, -119, 18, -3} + uint32_t dst[SIZE]; + + dma_target_t tgt_src = { + .ptr = (uint8_t *) src, + .inc_d1_du = 1, + .type = DMA_DATA_TYPE_BYTE, + .trig = DMA_TRIG_MEMORY, + }; + + dma_target_t tgt_dst = { + .ptr = (uint8_t *) dst, + .inc_d1_du = 1, + .type = DMA_DATA_TYPE_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_trans_t trans = { + .src = &tgt_src, + .dst = &tgt_dst, + .size_d1_du = size, + .src_addr = NULL, + .mode = DMA_TRANS_MODE_SINGLE, + .win_du = 0, + .sign_ext = 1; // This flag enables sign extension! + .end = DMA_TRANS_END_INTR_WAIT, + }; ``` -To start copying information from the second byte of `copy_buffer`, the source pointer is set to the address of `copy_buffer` plus one byte. -In order to copy one byte and skip another, the data type is set to byte, and the increment is set to two data units (i.e. two bytes). As for every half-word of the buffer a data unit will be copied, the transaction size is the same as the size of the `copy_buffer`. +#### Perform validation, loading and launching +Once again, only two steps! Time to perform the __validation__ of the transaction, __load__ the parameters, and __launch__ of it. +Let's put these calls inside a dedicated function, called *run_dma_signext_trans()* and launch it in the *main()*. Finally, let's add a simple for loop to print out the result. -The second target will point to the address of the SPI FLASH transmission FIFO. On this example, this value was already computed and stored in a constant `ADDRESS_SPI_FLASH_TX_FIFO`. +``` C +dma_config_flags_t run_dma_signext_trans(dma_trans_t *trans) +{ + dma_config_flags_t res; + + res = dma_validate_transaction(trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + res |= dma_load_transaction(trans); + res |= dma_launch(trans); -```C -static uint32_t *spi_flash_fifo_tx = ADDRESS_SPI_FLASH_TX_FIFO; + return res; +} +... -static dma_target_t tgt2= { - .inc_du = 0, - .trig = DMA_TRIG_SLOT_SPI_FLASH_TX, -}; +int main() +{ + dma_init(NULL); + + dma_config_flags_t result = run_dma_signext_trans(&trans); + + if (result != 0) + { + printf("Error! DMA transaction failed with code: %d\n", result); + return 1; + } else { + printf("Success!\n"); + + for (int i=0; i +
SRC_INC_D2 = SIZE_IN_D1 - (SIZE_EXTR_D1 - 1)
+ + +In this case, the source 2D increment will be 3 data units. On the other hand, the destination increment will always be 1 when the destination stride is 1. + +Finally, set the dimensionality flag to 1 to configure it for 2D transactions. ```C -static dma_trans_t trans = { - .src = &tgt1, - .dst = &tgt2, - .end = DMA_TRANS_END_INTR, - }; + + #define SIZE_IN_D1 4 + #define SIZE_IN_D2 4 + #define SIZE_EXTR_D1 2 + #define SIZE_EXTR_D2 2 + #define SRC_INC_D2 = SIZE_IN_D1 - (SIZE_EXTR_D1 - 1) + #define DST_INC_D2 = 1 + + uint16_t src[SIZE_IN_D1*SIZE_IN_D2] = { + 0x1234, 0x7654, 0xfedc, 0xffff, + 0x5912, 0xabcd, 0xcdef, 0xfafa, + 0x579a, 0x657d, 0x758e, 0xabba, + 0xa1a1, 0xc3c3, 0xb2b2, 0xf4f4 + }; + uint16_t dst[SIZE_EXTR_D1*SIZE_EXTR_D2]; + + dma_target_t tgt_src = { + .ptr = (uint8_t *) src, + .inc_d1_du = 1, + .inc_d2_du = SRC_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_target_t tgt_dst = { + .ptr = (uint8_t *) dst, + .inc_d1_du = 1, + .inc_d2_du = DST_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_trans_t trans_2d = { + .src = &tgt_src, + .dst = &tgt_dst, + .src_addr = NULL, + .mode = DMA_TRANS_MODE_SINGLE, + .dim = DMA_DIM_CONF_2D, // This is the dimensionality flag! + .size_d1_du = SIZE_EXTR_D1, + .size_d2_du = SIZE_EXTR_D2, + .mode = DMA_TRANS_MODE_SINGLE, + .win_du = 0, + .end = DMA_TRANS_END_INTR_WAIT, + }; + ``` -To enable interrupts, the end event is set to `DMA_TRANS_END_INTR`. +
+### 5. Matrix transposition -To create the transaction allowing the DMA to perform necessary realignments and integrity checks such arguments are passed to the creation function along with a pointer to the transaction. +The goal of this example is to develop a function that extracts a submatrix from a source matrix, transpose it and copies it to a destination matrix. -```C -dma_config_flags_t res; -res = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); -``` +Let's start! -The result variable `res` contains configuration flags that can be used to check that no errors or warnings were raised. These are codified as bits in the 16-bit `res` variable. -If only one flag was raised, the value of `res` will be equal to it. Otherwise, they can be checked by selecting individual bits, with inequalities, or comparing the result to a bitwise-or of flags. +#### Setting targets & transaction structs -```C -if( res == DMA_CONFIG_OK ) // Everything was ok. -if( res & DMA_CONFIG_CRITICAL_ERROR ) // A critical error was found. It has to be fixed or the transaction will not be loaded. -if( res >= DMA_CONFIG_OVERLAP && res =< DMA_CONFIG_TRANS_OVERRIDE ) // One or more warning flags were raised between those two. -if( res & ( DMA_CONFIG_SRC | DMA_CONFIG_DST) ) // Either one of the flags was raised. -``` +Once again, the first step is to define the source and destination target structs, as well as the transaction structs. -The transaction can then be loaded into the DMA registers by calling the load function -```C -res = dma_load_transaction( &trans ); -``` +Let's use the same formula as in example 2 to extract a 2x2 matrix from a 4x4 source matrix. So in this case too, the source 2D increment will be 3 data units, while the destination increment will be 1. + +To perform the transposition, we simply need to set a specific tag in the transaction struct, *.dim_inv*. -and launched ```C -res = dma_load_transaction( &trans ); + + #define SIZE_IN_D1 4 + #define SIZE_IN_D2 4 + #define SIZE_EXTR_D1 2 + #define SIZE_EXTR_D2 2 + #define SRC_INC_D2 = SIZE_IN_D1 - (SIZE_EXTR_D1 - 1) + #define DST_INC_D2 = 1 + + uint16_t src[SIZE_IN_D1*SIZE_IN_D2] = { + 0x1234, 0x7654, 0xfedc, 0xffff, + 0x5912, 0xabcd, 0xcdef, 0xfafa, + 0x579a, 0x657d, 0x758e, 0xabba, + 0xa1a1, 0xc3c3, 0xb2b2, 0xf4f4 + }; + uint16_t dst[SIZE_EXTR_D1*SIZE_EXTR_D2]; + + dma_target_t tgt_src = { + .ptr = (uint8_t *) src, + .inc_d1_du = 1, + .inc_d2_du = SRC_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_target_t tgt_dst = { + .ptr = (uint8_t *) dst, + .inc_d1_du = 1, + .inc_d2_du = DST_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_trans_t trans_2d = { + .src = &tgt_src, + .dst = &tgt_dst, + .src_addr = NULL, + .size_d1_du = SIZE_EXTR_D1, + .size_d2_du = SIZE_EXTR_D2, + .mode = DMA_TRANS_MODE_SINGLE, + .win_du = 0, + .dim = DMA_DIM_CONF_2D, + .dim_inv = 1; // This is the transposition flag! + .end = DMA_TRANS_END_INTR_WAIT, + }; + ``` -Because the DMA will raise an interrupt as soon as it has sent all of its information, it is recommended to wait for the SPI interrupt. -```C -while( spi_intr_flag == 0 ) +#### Perform validation, loading and launching + +Once again, only two steps! Time to perform the __validation__ of the transaction, __load__ the parameters, and __launch__ of it. +Let's put these calls inside a dedicated function, called *run_dma_2d_transp_trans()* and launch it in the *main()*. Finally, let's add a simple for loop to print out the result, i.e. the extracted matrix. + +``` C + +dma_config_flags_t run_dma_2d_transp_trans(dma_trans_t *trans) { - wait_for_interrupt(); -} -``` + dma_config_flags_t res; + + res = dma_validate_transaction(trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + res |= dma_load_transaction(trans); + res |= dma_launch(trans); -If something is to be done as soon as the DMA finishes (like preparing a new transaction) it can be triggered by the interrupt attention routine: -```C -void dma_intr_handler_trans_done() + return res; +} + +... + +int main() { - // Raise a flag to trigger an action + dma_init(NULL); + + dma_config_flags_t result = run_dma_2d_transp_trans(&trans); + + if (result != 0) + { + printf("Error! 2D DMA transaction failed with code: %d\n", result); + return 1; + } else { + printf("Success!\n"); + + for (int i=0; i -.tg {border-collapse:collapse;border-spacing:0;} -.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px; - overflow:hidden;padding:10px 5px;word-break:normal;} -.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px; - font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;} -.tg .tg-wp8o{border-color:#000000;text-align:center;vertical-align:top} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RAMFLASH
ABCD000B
EFGH000D
IJKL000F
........
- - ---- - - -For the second part of this example, the targets will be modified and their role switched. - -The source of the data will be a peripheral connected to the SPI, which will be continuously sending information in half-word format, in streams of 4096 bytes (2048 half-words). Every 1024 half-words there should be a `MILESTONE-CHARACTER`, if there is not, the data flow should be stopped. + +#### Non-square matrix transposition + +Working with a square matrix is straightforward, but how could the DMA be leveraged to extract a non-square matrix and transpose it on the fly? + +Let's revise the current example. With non-square matrices, the increment changes. The 1D increment will be equal to the stride on d1, which, in this example, is 1. +The 2D increment, on the other hand, is the number of elements along the d2 axis that the source read pointer must "jump" to move to the next column, starting from the header. A special register called *trsp_src_ptr_reg* holds the position of the first element of a given column within the array. Once a column has been copied, this pointer is increased by the 2D increment, which must be equal to the 2D size of the input, multiplied by the 2D input stride. ```C -tgt2.ptr = spi_peripheral_fifo_rx; -tgt2.size_du = 2048; -tgt2.type = DMA_DATA_TYPE_HALF_WORD; -tgt2.trig = DMA_TRIG_SLOT_SPI_RX; + + #define SIZE_IN_D1 4 + #define SIZE_IN_D2 4 + #define SIZE_EXTR_D1 3 + #define SIZE_EXTR_D2 2 + #define SRC_INC_D2 = SIZE_IN_D1 + #define DST_INC_D2 = 1 + + uint16_t src[SIZE_IN_D1*SIZE_IN_D2] = { + 0x1234, 0x7654, 0xfedc, 0xffff, + 0x5912, 0xabcd, 0xcdef, 0xfafa, + 0x579a, 0x657d, 0x758e, 0xabba, + 0xa1a1, 0xc3c3, 0xb2b2, 0xf4f4 + }; + uint16_t dst[SIZE_EXTR_D1*SIZE_EXTR_D2]; + + dma_target_t tgt_src = { + .ptr = (uint8_t *) src, + .inc_d1_du = 1, + .inc_d2_du = SRC_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_target_t tgt_dst = { + .ptr = (uint8_t *) dst, + .inc_d1_du = 1, + .inc_d2_du = DST_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_trans_t trans_2d = { + .src = &tgt_src, + .dst = &tgt_dst, + .src_addr = NULL, + .size_d1_du = SIZE_EXTR_D1, + .size_d2_du = SIZE_EXTR_D2, + .mode = DMA_TRANS_MODE_SINGLE, + .dim = DMA_DIM_CONF_2D, + .win_du = 0, + .dim_inv = 1; // This is the transposition flag! + .end = DMA_TRANS_END_INTR_WAIT, + }; + ``` -The source pointer is set to the reception FIFO of the SPI, and the appropriate slot is chosen. -The increment is kept in zero. +The rest of the code remains unchanged w.r.t. the square matrix example. + +
+ +### 6. Matrix zero padding + +The goal of this example is to develop a function that extracts a submatrix from a source matrix, applies zero padding on it and copies it to a destination matrix. + +Let's start! + +#### Setting targets & transaction structs + +Once again, the first step is to define the source and destination target structs, as well as the transaction structs. -The destination pointer will be given by a function. +Let's use the same formula as in example 2 to extract a 2x2 matrix from a 4x4 source matrix. So in this case too, the source 2D increment will be 3 data units, while the destination increment will be 1. + +As thoroughly explained in [the functional description](#zero-padding), the padding is performed on the fly but is conceptually applied to the extracted matrix, not to the entire input matrix. In this example, a right padding of 1 and a top padding of 2 will be applied. Since the padding modifies the size of the output, the output dimensions will need to be adjusted accordingly. The formula used are the same used in `example_dma_2d`. ```C -tgt1.ptr = (uint8_t*) myApp_getDestination(); + + #define SIZE_IN_D1 4 + #define SIZE_IN_D2 4 + #define SIZE_EXTR_D1 2 + #define SIZE_EXTR_D2 2 + #define TOP_PAD 2 + #define RIGHT_PAD 1 + #define LEFT_PAD 0 + #define RIGHT_PAD 0 + + #define OUT_D1_PAD ( SIZE_EXTR_D1 + LEFT_PAD + RIGHT_PAD ) + #define OUT_D2_PAD ( SIZE_EXTR_D2 + TOP_PAD + BOTTOM_PAD ) + #define OUT_DIM_1D ( OUT_D1_PAD ) + #define OUT_DIM_2D ( OUT_D1_PAD * OUT_D2_PAD ) + + #define SRC_INC_D2 = SIZE_IN_D1 - (SIZE_EXTR_D1 - 1) + #define DST_INC_D2 = 1 + + uint16_t src[SIZE_IN_D1*SIZE_IN_D2] = { + 0x1234, 0x7654, 0xfedc, 0xffff, + 0x5912, 0xabcd, 0xcdef, 0xfafa, + 0x579a, 0x657d, 0x758e, 0xabba, + 0xa1a1, 0xc3c3, 0xb2b2, 0xf4f4 + }; + uint16_t dst[OUT_DIM_1D*OUT_DIM_2D]; + + dma_target_t tgt_src = { + .ptr = (uint8_t *) src, + .inc_d1_du = 1, + .inc_d2_du = SRC_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_target_t tgt_dst = { + .ptr = (uint8_t *) dst, + .inc_d1_du = 1, + .inc_d2_du = DST_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_trans_t trans_2d = { + .src = &tgt_src, + .dst = &tgt_dst, + .src_addr = NULL, + .size_d1_du = SIZE_EXTR_D1, + .size_d2_du = SIZE_EXTR_D2, + .pad_top_du = TOP_PAD, + .pad_bottom_du = BOTTOM_PAD, + .pad_left_du = LEFT_PAD, + .pad_right_du = RIGHT_PAD, + .mode = DMA_TRANS_MODE_SINGLE, + .win_du = 0, + .dim = DMA_DIM_CONF_2D, + .end = DMA_TRANS_END_INTR_WAIT, + }; + ``` -To guarantee that the result of this function will not cause the DMA to write in undesired regions of memory, an environment can be created. -It requires two pointers to the first and last byte where the DMA will be authorized to make any action. -```C -static dma_env_t safe_zone = { - .start = ADDRESS_START_OF_SAFE_ZONE, - .end = ADDRESS_END_OF_SAFE_ZONE, -}; +#### Perform validation, loading and launching + +Once again, only two steps! Time to perform the __validation__ of the transaction, __load__ the parameters, and __launch__ of it. +Let's put these calls inside a dedicated function, called *run_dma_2d_pad_trans()* and launch it in the *main()*. Finally, let's add a simple for loop to print out the result. + +``` C + +dma_config_flags_t run_dma_2d_pad_trans(dma_trans_t *trans) +{ + dma_config_flags_t res; + + res = dma_validate_transaction(trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + res |= dma_load_transaction(trans); + res |= dma_launch(trans); + + return res; +} + +... + +int main() +{ + dma_init(NULL); + + dma_config_flags_t result = run_dma_2d_pad_trans(&trans); + + if (result != 0) + { + printf("Error! 2D DMA transaction failed with code: %d\n", result); + return 1; + } else { + printf("Success!\n"); + + for (int i=0; i :warning: Make sure to configure X-Heep to have at least two DMA channels! + +Let's start! + +#### Setting targets & transaction structs + +Just like in previous examples, the first step is to define the source and destination target structs, as well as the transaction structs. + +Using the same formula as in example 2 to extract a 2x2 matrix from a 4x4 source matrix, the source 2D increment will be 3 data units, while the destination increment will be 1. + +Let's use the DMA CH0 to copy the {0x1234, 0x7654, 0x5912, 0xabcd} 2x2 matrix and the DMA CH1 to copy the {0x758e, 0xabba, 0xb2b2, 0xf4f4} matrix. These channels will copy the extracted matrices to two different destinations, *dst_ch0* and *dst_ch1*. Each transaction struct should have its _.ch_ field set accordingly. + +Finally, let's set the end event to *DMA_TRANS_END_INTR* to handle manually the interrupt event. + ```C -tgt1.env = &safe_zone; -tgt1.inc_du = 1; + + #define SIZE_IN_D1 4 + #define SIZE_IN_D2 4 + #define SIZE_EXTR_D1 2 + #define SIZE_EXTR_D2 2 + #define SRC_INC_D2 = SIZE_IN_D1 - (SIZE_EXTR_D1 - 1) + #define DST_INC_D2 = 1 + + uint16_t src[SIZE_IN_D1*SIZE_IN_D2] = { + 0x1234, 0x7654, 0xfedc, 0xffff, + 0x5912, 0xabcd, 0xcdef, 0xfafa, + 0x579a, 0x657d, 0x758e, 0xabba, + 0xa1a1, 0xc3c3, 0xb2b2, 0xf4f4 + }; + uint16_t dst_ch0[SIZE_EXTR_D1*SIZE_EXTR_D2], dst_ch1[SIZE_EXTR_D1*SIZE_EXTR_D2]; + + dma_target_t tgt_src_ch0 = { + .ptr = (uint8_t *) src, + .inc_d1_du = 1, + .inc_d2_du = SRC_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_target_t tgt_src_ch1 = { + .ptr = (uint8_t *) &src[10], // This is the address of the "0x758e" element + .inc_d1_du = 1, + .inc_d2_du = SRC_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_target_t tgt_dst_ch0 = { + .ptr = (uint8_t *) dst_ch0, + .inc_d1_du = 1, + .inc_d2_du = DST_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_target_t tgt_dst_ch1 = { + .ptr = (uint8_t *) dst_ch1, + .inc_d1_du = 1, + .inc_d2_du = DST_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_trans_t trans_2d_ch0 = { + .src = &tgt_src, + .dst = &tgt_dst_ch0, + .src_addr = NULL, + .mode = DMA_TRANS_MODE_SINGLE, + .dim = DMA_DIM_CONF_2D, + .size_d1_du = SIZE_EXTR_D1, + .size_d2_du = SIZE_EXTR_D2, + .mode = DMA_TRANS_MODE_SINGLE, + .win_du = 0, + .end = DMA_TRANS_END_INTR, + .ch = 0 // This flag specifies the channel used to run the transaction! + }; + + dma_trans_t trans_2d_ch1 = { + .src = &tgt_src, + .dst = &tgt_dst_ch1, + .src_addr = NULL, + .mode = DMA_TRANS_MODE_SINGLE, + .dim = DMA_DIM_CONF_2D, + .size_d1_du = SIZE_EXTR_D1, + .size_d2_du = SIZE_EXTR_D2, + .mode = DMA_TRANS_MODE_SINGLE, + .win_du = 0, + .end = DMA_TRANS_END_INTR, + .ch = 1 // This flag specifies the channel used to run the transaction! + }; + ``` -Size and data type is up to the source, and the rest of the configurations are inherited from the last transaction. +#### IRQ handler + +Due to hardware limitations, there is just a **single fast interrupt** line dedicated to the DMA subsystem. In order to identify which channel raised the interrupt line, the DMA HAL performs a check on the IFR of each channel. +As soon as an IFR is read high, the HAL calls a weak implementation of the interrupt handler, called **dma_intr_handler_trans_done()** and it passed the channel ID. +After the call, the loop continues to look for interrupts in other channels, and then returns. + +There is, however, an **additional level of customization** provided by the HAL. +It's possible to set an index to differentiate between low and high priority channels by setting *DMA_HP_INTR_INDEX* in `dma.h`. In other words, when a channel whose ID is lower or equal to that index raises an interrupt, the *handler_irq_dma()* calls the user-defined IRQ handler and then returns, instead of compleating the loop. +This means that low ID channels, i.e. high priority channels, have a higher probability of being serviced that the rest of the channels. + +However, this feature could cause low priority channels to never be serviced if the high priority interrupts are raised at a faster frequency and the user-defined handler executes long and complex operations. + +There are two solutions to this problem: +- Use the **universal good design practice** of minimizing the tasks to perform in the IRQ handler. +- Set *DMA_NUM_HP_INTR* to limit the number of consecutive IRQ handler calls that high priority channels can make without checking for low priority interrupts. + +This mechanism is reported from `dma.c` here below: -The transaction is conformed as: ```C -window_size_du = 1024; -trans.src = &tgt2; -trans.dst = &tgt1; -trans.mode = DMA_TRANS_MODE_CIRCULAR; -trans.win_du = window_size_du; +void fic_irq_dma(void) +{ + /* + * Find out which channel raised the interrupt and call + * either the weak implementation provided in this module, + * or the non-weak implementation. + */ + + for (int i = 0; i < DMA_CH_NUM; i++) + { + if (dma_subsys_per[i].peri->TRANSACTION_IFR == 1) + { + dma_subsys_per[i].intrFlag = 1; + dma_intr_handler_trans_done(i); + + #ifdef DMA_HP_INTR_INDEX + /* + * If the channel that raised the interrupt is among the high priority channels, + * return to break the loop. + */ + + #ifdef DMA_NUM_HP_INTR + + if (i <= DMA_HP_INTR_INDEX && dma_hp_tr_intr_counter < DMA_NUM_HP_INTR) + { + dma_hp_tr_intr_counter++; + return; + } + else if (i > DMA_HP_INTR_INDEX) + { + dma_hp_tr_intr_counter = 0; + } + + #else + + if (i <= DMA_HP_INTR_INDEX) + { + return; + } + #endif + + #endif + } + } + return; +} ``` -Meaning that the information will start to flow into the target 1 from target 2, and every 1024 half-words transferred the application will get an interrupt to check if the `MILESTONE_SYMBOL` is present. Upon finishing the transaction, it shall start again to refill the buffer as it was set in `CIRCULAR_MODE`. +Everything that has been explained in this paragraph is true for the **window count interrupts** too. -The amount of times the buffer was filled will be updated on every _transaction done_ interrupt. -```C -void dma_intr_handler_trans_done() +In this example, none of these additional functionalities are necessary, as the IRQ handler will be used to simply set a flag. +A detailed explaination of how these mechanisms work was still necessary, since they are very useful in a variety of applications. + +Let's redefine *dma_intr_handler_trans_done()* to set some flags: + +``` C +char intr_ch0_flag = 0; +char intr_ch1_flag = 0; + +/* Strong transaction ISR implementation */ +void dma_intr_handler_trans_done(uint8_t channel) { - transaction_count++; + if (channel == 0){ + intr_ch0_flag = 1; + } else { + intr_ch1_flag = 1; + } + return; } + ``` -The search for the `MILESTONE_SYMBOL` can be done inside the _window done_ interrupt handling. -```C -void dma_intr_handler_window_done() +#### Perform validation, loading and launching + +Once again, only two steps! Time to perform the __validation__ of the transaction, __load__ the parameters, and __launch__ of it. +Let's put these calls inside a dedicated function, called *run_dma_2d_multi_trans()* and launch it in the *main()*. Finally, let's add a simple for loop to print out the result and to check on the interrupt flags. + +Last but not least, **wait for CH1** to finish its transaction and raise the interrupt. Since both transactions has identical size there is no risk of the first one finishing before the other, so it's safe to assume that CH1 will be the last to terminate. + +``` C + +dma_config_flags_t run_dma_2d_multi_trans(dma_trans_t *trans_ch0, dma_trans_t *trans_ch1) { - /* The current window is obtained. The count is zero when no windows have yet been written. When it is set to one, the window zero is ready. */ - window_count = dma_get_window_count() -1; - /* The pointer to the symbol is obtained from the destination pointer + the amount of half-words that have been written. this assumes the symbol is on the first element of each chunk.*/ - address = (uint16_t *)trans.dst->ptr + window_count*window_size_du; - symbol = *address; - if( symbol != MILESTONE_SYMBOL ) - { - /* If the symbol was not the expected one, future transactions should not be carried out.*/ - dma_stop_circular(); - /* The number of the first window with error is saved to analyze it later.*/ - error_window = error_window == 0 ? window_count : error_window; + dma_config_flags_t res; + + res = dma_validate_transaction(trans_ch0, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + res |= dma_validate_transaction(trans_ch1, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + res |= dma_load_transaction(trans_ch0); + res |= dma_load_transaction(trans_ch1); + res |= dma_launch(trans_ch0); + res |= dma_launch(trans_ch1); + + return res; +} + +... + +int main() +{ + dma_init(NULL); + + dma_config_flags_t result = run_dma_2d_multi_trans(&trans); + + // Wait for CH1 to finish + while (!dma_is_ready(1)) + { + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if (dma_is_ready(1) == 0) + { + wait_for_interrupt(); + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + } + + if (result != 0) + { + printf("Error! 2D DMA transaction failed with code: %d\n", result); + return 1; + } else { + printf("Success!\n"); + + printf("Output CH0:\n\r"); + for (int i=0; i + +### 8. Multichannel flash2mem transaction using the SPI FLASH + +The goal of this example is to develop a function that performs: +- A matrix extraction from a source matrix stored in the FLASH +- A matrix extraction from a source matrix stored in the RAM +These operations are performed using CH0 and CH1 in parallel. + +> :warning: This example can be executed only on QuestaSim or FPGA targets with the appropriate compilation flags. +Checkout the SPI documentation or `example_dma_multichannel` for additional information. + +> :warning: Make sure to configure X-Heep to have at least two DMA channels! + +Let's start! + +#### Setting targets & transaction structs + +Just like in previous examples, the first step is to define the source and destination target structs, as well as the transaction structs. This time we only need to set up the CH1 transaction, as for the + +Most of this example is similar to the previous one, but particular care is required for the setup of FLASH stored data. In x-Heep, this is achieved by using the directive: + +

__attribute__((section(".xheep_data_flash_only")))

+ +```C + + #define SIZE_IN_D1 4 + #define SIZE_IN_D2 4 + #define SIZE_EXTR_D1 2 + #define SIZE_EXTR_D2 2 + #define SRC_INC_D2 = SIZE_IN_D1 - (SIZE_EXTR_D1 - 1) + #define DST_INC_D2 = 1 + + uint16_t __attribute__((section(".xheep_data_flash_only"))) src_flash[SIZE_IN_D1*SIZE_IN_D2] = { + 0x1234, 0x7654, 0xfedc, 0xffff, + 0x5912, 0xabcd, 0xcdef, 0xfafa, + 0x579a, 0x657d, 0x758e, 0xabba, + 0xa1a1, 0xc3c3, 0xb2b2, 0xf4f4 + }; + + uint16_t src[SIZE_IN_D1*SIZE_IN_D2] = { + 0x1111, 0x2222, 0x3333, 0xfccf, + 0x4444, 0x5555, 0x6666, 0xfbba, + 0x7777, 0x8888, 0x9999, 0xadda, + 0x1010, 0x1212, 0x4142, 0xfca4 + }; + + uint16_t dst_ch0[SIZE_EXTR_D1*SIZE_EXTR_D2], dst_ch1[SIZE_EXTR_D1*SIZE_EXTR_D2]; + + dma_target_t tgt_src_ch1 = { + .ptr = (uint8_t *) src, + .inc_d1_du = 1, + .inc_d2_du = SRC_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_target_t tgt_dst_ch1 = { + .ptr = (uint8_t *) dst_ch1, + .inc_d1_du = 1, + .inc_d2_du = DST_INC_D2, + .type = DMA_DATA_TYPE_HALF_WORD, + .trig = DMA_TRIG_MEMORY, + }; + + dma_trans_t trans_2d_ch1 = { + .src = &tgt_src, + .dst = &tgt_dst_ch1, + .src_addr = NULL, + .mode = DMA_TRANS_MODE_SINGLE, + .dim = DMA_DIM_CONF_2D, + .size_d1_du = SIZE_EXTR_D1, + .size_d2_du = SIZE_EXTR_D2, + .mode = DMA_TRANS_MODE_SINGLE, + .win_du = 0, + .end = DMA_TRANS_END_INTR, + .ch = 1 // This flag specifies the channel used to run the transaction! + }; + +``` + +#### Set up of the SPI FLASH + +There are just a few step to follow to correctly set up the SPI for the FLASH transaction. + +The first step is the initialization of the *soc_ctrl*, followed by the pick of the correct SPI device, based on the target, and the bridge set up. + +> :warning: Remember to use *flash_load* when compiling the software! + +```C +void SPI_setup(){ + + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + + /* Pick the correct spi device based on simulation type */ + spi_host_t *spi; + + #ifndef USE_SPI_FLASH + spi = spi_host1; + #else + spi = spi_flash; + #endif + + /* Init SPI host and SPI<->Flash bridge parameters */ + if (w25q128jw_init(spi) != FLASH_OK) + { + PRINTF("Error initializing the flash SPI\n\r"); + return EXIT_FAILURE; + } } ``` -> :warning: Interrupt attention routines are advised to be kept as short as possible. This example is merely illustrative. -Once the `dma_stop_circular()` function is called, the DMA will still finish the transaction it is currently executing (which could be a whole transaction if the faulty window was the last one). It is important to save valuable information that might be overridden by the ongoing transaction (like the faulty window number). +#### Perform validation, loading and launching + +Once the SPI has been set up, the next step it's time to perform the __validation__ of the transaction, __load__ the parameters, and __launch__ of it. + +As for the SPI, there is a function defined in `w25q.c` that simplifies the operation: + +

w25q128jw_read_standard_dma(uint32_t addr, void *data, uint32_t length, uint8_t no_wait_init_dma, uint8_t no_sanity_checks)

+ +The flags *no_wait_init_dma* and *no_sanity_checks* are necessary for running the application, as they prevent the DMA from being reset or using a blocking wait for its interrupt. However, the function is quite handy since it takes care of everything else. +Note that the *w25q128jw_read_standard_dma()* uses **CH0**! -## Testing -This section will describe the available example application in X-HEEP using the DMA, and will outline the testing that needs to be performed in order to validate its proper operation. +**Suggestion:** To further understand how to interface the DMA with the SPI, study the functions in `w25q.c` that employ it. +As usual, let's put these calls inside a dedicated function, called *run_dma_2d_spi_trans()* and launch it in the *main()*. Finally, let's add a simple for loop to print out the result and to check on the interrupt flags. -### Available Applications +Last but not least, **wait for CH0** to finish its transaction and raise the interrupt, since the SPI will always be slower than a standard DMA transaction of equal size. -There are 6 applications using the DMA: -* `dma_example`: Tests memory-to-memory transfer, the blocking of transactions while another one is in progress, and window interrupts. -* `example_external_peripheral`: Tests the use of the DMA HAL one a DMA instance external to X-HEEP. Only available for simulation. -* `example_virtual_flash`: Tests the transfer to/from an external flash through the DMA. -* `spi_flash_write`: Tests the transfer to/from the flash. Tests circular mode. Not available on FPGA if linker is `flash-exec`. Should be used with `mcu gen BUS=NtoM CPU=cv32e40p` to test circular mode. -* `spi_host_dma_exampe`: Test the transfer of data through the SPI host. Not available on Verilator. -* `spi_host_dma_power_gate_example`: Test the transfer of data through the SPI host. Not available on Verilator. +``` C + +dma_config_flags_t run_dma_2d_spi_trans(dma_trans_t *trans_ch0, dma_trans_t *trans_ch1) +{ + dma_config_flags_t res; + + res |= dma_validate_transaction(trans_ch1, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + res |= dma_load_transaction(trans_ch1); + res |= dma_launch(trans_ch1); + + return res; +} + +... + +int main() +{ + dma_init(NULL); + + dma_config_flags_t result = run_dma_2d_multi_trans(&trans); + + /* Start the reading process from the SPI, avoiding both sanity checks and waiting for the DMA to finish */ + w25q_error_codes_t status = w25q128jw_read_standard_dma(TEST_DATA_FLASH_PTR, copied_test_data_flash, TEST_DATA_FLASH_SIZE*4, 1, 1); + if (status != FLASH_OK) + { + PRINTF("Error reading from flash\n\r"); + return EXIT_FAILURE; + } + + // Wait for CH1 to finish + while (!dma_is_ready(1)) + { + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if (dma_is_ready(1) == 0) + { + wait_for_interrupt(); + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + } + + if (result != 0) + { + printf("Error! 2D DMA transaction failed with code: %d\n", result); + return 1; + } else { + printf("Success!\n"); + + printf("Output CH0:\n\r"); + for (int i=0; iSYSTEM_FREQUENCY_HZ) + +// Flash paramters +#define FLASH_MAX_FREQ (133*1000*1000) +#define FLASH_CSN_TIMES 0x0F +#define FLASH_POL 0 +#define FLASH_PHA 0 +#define FC_RD 0x03 /* Flash Read Data Command */ + +// SPI transaction parameters +#define SPI_TX 0x02 +#define SPI_RX 0x01 +#define SPI_STD 0x00 + +#define LEN_B = 4096 /* Amount of bytes of data to read from flash */ + +#define ADDRESS = 0x00800000 /* Flash address where to read */ + +int main(int argc, char *argv[]) +{ + // Initialize RX buffer + uint8_t dest_buff[LEN_B] = {0}; + + // Compute frequency of SPI communication based on slave and MCU frequency + uint16_t clk_div = 0; + if (FLASH_MAX_FREQ < SYS_FREQ / 2) { + clk_div = (SYS_FREQ / FLASH_MAX_FREQ - 2) / 2; + if (SYS_FREQ / (2 * clk_div + 2) > FLASH_MAX_FREQ) clk_div++; + } + // Set slave configuration options + spi_flash_peri->CONFIGOPTS0 = (FLASH_CSN_TIMES << SPI_HOST_CONFIGOPTS_0_CSNIDLE_0_OFFSET) | + (FLASH_CSN_TIMES << SPI_HOST_CONFIGOPTS_0_CSNLEAD_0_OFFSET) | + (FLASH_CSN_TIMES << SPI_HOST_CONFIGOPTS_0_CSNTRAIL_0_OFFSET) | + (FLASH_PHA << SPI_HOST_CONFIGOPTS_0_CPHA_0_BIT) | + (FLASH_POL << SPI_HOST_CONFIGOPTS_0_CPOL_0_BIT) | + (clk_div << SPI_HOST_CONFIGOPTS_0_CLKDIV_0_OFFSET); + + // Enable SPI Host device and output + bitfield_write(spi_flash_peri->CONTROL, BIT_MASK_1, SPI_HOST_CONTROL_SPIEN_BIT, true); + bitfield_write(spi_flash_peri->CONTROL, BIT_MASK_1, SPI_HOST_CONTROL_OUTPUT_EN_BIT, true); + + // Set command to send to slave + spi_flash_peri->TXDATA = ((bitfield_byteswap32(ADDRESS & 0x00ffffff)) | FC_RD); + // Set CSID line where slave is connected + spi_flash_peri->CSID = 0; + // Wait for SPI Host to be ready before setting command + while (!bitfield_read(spi_flash_peri->STATUS, BIT_MASK_1, SPI_HOST_STATUS_READY_BIT)); + // Set command + spi_flash_peri->COMMAND = (SPI_TX << SPI_HOST_COMMAND_DIRECTION_OFFSET) | + (SPI_STD << SPI_HOST_COMMAND_SPEED_OFFSET) | + (0x01 << SPI_HOST_COMMAND_CSAAT_BIT) | + (0x03 << SPI_HOST_COMMAND_LEN_OFFSET); + // Wait for SPI Host to be ready before setting command + while (!bitfield_read(spi_flash_peri->STATUS, BIT_MASK_1, SPI_HOST_STATUS_READY_BIT)); + // Set command + spi_flash_peri->COMMAND = (SPI_RX << SPI_HOST_COMMAND_DIRECTION_OFFSET) | + (SPI_STD << SPI_HOST_COMMAND_SPEED_OFFSET) | + (0x00 << SPI_HOST_COMMAND_CSAAT_BIT) | + (LEN_B-1 << SPI_HOST_COMMAND_LEN_OFFSET); + + // Setup RX word counter and set watermark + uint32_t rxcnt = 0; + const uint8_t watermark = 48; + bitfield_write(spi_flash_peri->CONTROL, SPI_HOST_CONTROL_RX_WATERMARK_MASK, + SPI_HOST_CONTROL_RX_WATERMARK_OFFSET, watermark); + + // While the SPI Host is active (i.e. still processing transaction) + while (bitfield_read(spi_flash_peri->STATUS, BIT_MASK_1, SPI_HOST_STATUS_ACTIVE_BIT)) + { + // If there are still more words to be read than watermark, then wait + // for RX watermark to go high + if ((LEN_B/4) - rxcnt > watermark) + while (!bitfield_read(spi_flash_peri->STATUS, BIT_MASK_1, + SPI_HOST_STATUS_RXWM_BIT)) + // Needed because too fast otherwise + asm volatile ("nop"); + // Just read as much as possible (but no more than watermark words) + for (int i = 0; i < watermark; i++) + { + // If there are words in the RX FIFO read them + if (bitfield_read(spi_flash_peri->STATUS, SPI_HOST_STATUS_RXQD_MASK, + SPI_HOST_STATUS_RXQD_OFFSET)) + { + dest_buff[rxcnt] = spi_flash_peri->RXDATA; + rxcnt++; + } + } + } + // Read the remaining words if there are any + while (bitfield_read(spi_flash_peri->STATUS, SPI_HOST_STATUS_RXQD_MASK, + SPI_HOST_STATUS_RXQD_OFFSET)) + { + dest_buff[rxcnt] = spi_flash_peri->RXDATA; + rxcnt++; + } +} +``` + +```{note} +There are practically no sanity checks performed in this example in order to keep it +as simple as possible. In a practical application there should of course be sanity +checks wherever needed. +``` + + +## Performance Analysis + +A performance testing was carried out utilizing the _EPFL Programmer_, which includes +a _W25Q128JW_ flash memory, and the _PYNQ-Z2_ FPGA. The +[SPI Flash Loading Boot Procedure](/How_to/ExecuteFromFlash.html#spi-flash-loading-boot-procedure) +was employed for all tests. + +The test application used the +[Clock Cycle Counter `mcycle(h)`](https://ibex-core.readthedocs.io/en/latest/03_reference/performance_counters.html) +of X-HEEP, recording time via the `CSR_REG_MCYCLE` register. The test tracked the +duration to create and execute a transaction of various command segments with the +SDK, where each transaction involved reading 4KiB from the _W25Q128JW_ flash device. +This read operation was repeated 500 times to obtain an average. + +The exact same procedure was applied to the HAL and the _direct register_ method, +which involves direct manipulation of _SPI Host_ registers without using the HAL or +SDK. The tests were conducted at both _Standard_ SPI and _Quad_ SPI speeds. For +accurate comparison, only essential steps for transaction execution were implemented, +avoiding as many sanity checks as possible to maximize performance. + +Results indicate that at _Standard_ SPI speed, _direct register_ manipulation was +slightly faster than the HAL by approximately 0.8%. At _Quad_ SPI speed, _direct register_ +manipulation showed a significant performance gain, being about 18.6% faster than +the HAL. Comparing the HAL to the SDK, the HAL was about 1% faster at _Quad_ speed +and 0.8% faster at _Standard_ speed. + +Exact numbers are provided in the following tables. + +```{table} +:widths: auto +:align: center + +| | SDK | HAL | Register | +| :------: | :--------: | :--------: | :--------: | +| **Standard** | 4472.00 μs | 4437.40 μs | 4402.07 μs | +| **Quad** | 1970.00 μs | 1951.40 μs | 1588.00 μs | +``` + +To illustrate these numbers rather in percentage of change, the following table +shows the speed gain(-) and the speed loss(+) when changing method for a Quad speed +read. For example, when switching from the _direct register_ method to the SDK, +there is a + +```{math} +\frac{SDK - Register}{Register}\ =\ 24.055\% +``` + +change, which means 24.055% slower. + +```{table} +:widths: auto +:align: center + +| | SDK | HAL | Register | +| :------: | :------: | :------: | :------: | +| **SDK** | 0% | 0.953% | 24.055% | +| **HAL** | -0.944% | 0% | 22.884% | +| **Register** | -19.391% | -18.623% | 0% | +``` \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/Peripherals/Timer.md b/hw/vendor/esl_epfl_x_heep/docs/source/Peripherals/Timer.md new file mode 100644 index 00000000..052faf0d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/docs/source/Peripherals/Timer.md @@ -0,0 +1,107 @@ + +# Timer SDK + +This SDK provides utilities for execution time measurements using HW timers. It includes functions to start, stop, reset, and configure timers, as well as to enable timer interrupts and measure elapsed time. + +## Usage + +The SDK provides a set of functions to interact with the HW Timer for various timing operations. + +### Initialize Timer for Counting Cycles + +This function configures the counter at the running clock frequency to count the number of clock cycles. Call this function before any of the other timer SDK functions. + +```c +void timer_cycles_init(); +``` + +### Start Timer + +Start the HW timer. + +```c +void timer_start(); +``` + +### Get Current Timer Value + +Retrieve the current value of the HW timer without stopping it. + +```c +uint32_t timer_get_cycles(); +``` + +### Complete timer reset + +Completely resets the HW counter, disabling all IRQs, counters, and comparators. +```c +void timer_reset(); +``` + +### Stop and Reset Timer + +Retrieve the current value of the HW timer and stop it. + +```c +uint32_t timer_stop(); +``` + +### Set Timer Threshold + +Set the timer to go off once the counter value reaches the specified threshold. If the timer interrupts and the timer IRQ have been enabled, when the timer reaches that value an interrupt will be called. + +```c +void timer_arm_set(uint32_t threshold); +``` + +### Set Timer Threshold and Start + +Set the timer to go off once the counter value reaches the specified threshold, and start the timer. If the timer interrupts and the timer IRQ have been enabled, when the timer reaches that value an interrupt will be called. + +```c +void timer_arm_start(uint32_t threshold); +``` + +### Enable Timer IRQ + +Enable the timer interrupt request. + +```c +void timer_irq_enable(); +``` + +### Clear Timer IRQ + +Clear the timer interrupt request. + +```c +void timer_irq_clear(); +``` + +### Enable Timer Machine-level Interrupts + +Enable the timer machine-level interrupts for the X-Heep platform. + +```c +void enable_timer_interrupt(); +``` + +### Wait for Microseconds + +Block execution for a specified number of microseconds. This function is not precise for small numbers of microseconds. Enable timer interrupts with `enable_timer_interrupt()` before using this function. + +```c +void timer_wait_us(uint32_t ms); +``` + +### Get Execution Time in Microseconds + +Get the time taken to execute a certain number of cycles, returned as a float representing the time in microseconds. + +```c +float get_time_from_cycles(uint32_t cycles); +``` + +## Example Usage + +An example of utilization of the timer SDK can be found in `sw/applications/example_timer_sdk/main.c`. diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/Verification/VerifHEEP.md b/hw/vendor/esl_epfl_x_heep/docs/source/Verification/VerifHEEP.md new file mode 100644 index 00000000..13ffd94e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/docs/source/Verification/VerifHEEP.md @@ -0,0 +1,186 @@ +# VerifHeep + +## Introduction + +**VerifHeep** is a Python library designed to provide various methods for implementing a verification and testing environment tailored specifically for X-Heep. + +In particular, VerifHeep enables **on FPGA** verification, testing and performance estimation, offering a tenfold speed improvement compared to traditional simulation tools like Verilator or QuestaSim. +This library employs a _software-based_ verification approach, meaning it conducts its tests by compiling a specific software application, running it on the target unit, and analyzing the results. The user is required to develop an application that can test and verify the target unit and display the data in accordance with specific formats. + +This library has been developed with a focus on verifying and characterizing external accelerators, such as the _im2col Smart Peripheral Controller_ (SPC). +In fact, the `scripts/examples` folder contains the verification environment for this very accelerator, `im2col_spc_verification.py`, along with `im2col_spc_plotter.py` to plot the acquired data. +Users are encouraged to refer to this file as a real-world example of how to use the library and can use it as starting point to develop their own verification environment. + +> :warning: Make sure to follow the preliminary steps explained in `im2col_spc_verification.py` in order to test it! + +This guide aims to address any questions that might arise from studying the *im2col_spc* example. It provides a detailed explanation of each method in VerifHeep, along with the parameters required for its proper functioning. + +> :bulb: The FPGA synthesis must be performed with the **Xilinx scan chains** enabled, as these will be used to load the program. +Additionally, the EPFL programmer will be used for serial communication with the board. Without these two lines of communication, it would be impossible to load the program and read the serial stream. + +## Methods description + +#### __init__ + +_Purpose_: +The initialization function is used to create the VerifHeep object. During this process, it's required to indicate the target of the verification and its directory. Furthermore, an optimization flag can be set when synthesis or simulation module building will be performed. + +_Parameters_: +- **target**: Indicated the target of the verification environment, must be one of the following: + - `pynq-z2` + - `questasim` + - `verilator` +- **xheep_dir**: Sets the directory of the X-Heep project, necessary to run scripts. +- **opt_en**: By default set to _false_, this flag indicates whether optimization should be performed when building the simulation model. Available **only** with QuestaSim! + +#### compileModel + +_Purpose_: +This method is used to compile a simulation model for both Verilator and QuestaSim, i.e. run _make mcu-gen_, provided they are properly installed on the host system. + +_Parameters_: +- **mem_banks**: By default set to 6, this flag indicates how many memory banks will be included in the X-Heep model. No interleaved banks are supported. +- **cpu**: By default set to `cv32e40px`, this flags indicates which CPU will be included in the model. +- **bus**: By default set to `1toN`, this flag indicates the bus type. + +#### buildModel + +_Purpose_: +This method is used to either build a simulation model for Verilator or QuestaSim or to synthesize the project with Xilinx Vivado, provided they are properly installed on the host system. + +_Parameters_: +- **mem_banks**: By default set to *6*, this flag indicates how many memory banks will be included. No interleaved banks are supported. +- **cpu**: By default set to `cv32e40px`, this flags indicates which CPU will be included. +- **bus**: By default set to `1toN`, this flag indicates the bus type. + +#### serialBegin + +_Purpose_: +This method is used to set up the serial communication with the _pynq-z2_ FPGA board. + +> :bulb: **Tip:** Checkout which USB port is connected to the _pynq-z2_ by running a simple hello world (no flash load since the scan chains are used). +Set the USB port parameter of the verification environment as a global variable to quickly modify it. Its value might change! + +_Parameters_: +- **port**: Indicates the USB port connected to the EPFL programmer for the pynq-z2. +- **baudrate**: Indicates the connection speed, usually set to 9600. + +_Return value_: +- **Outcome of the connection**, which is _False_ for unsuccessful. + +#### setupDeb + +_Purpose_: +This method is used to set up the GDB debugger. It creates a process on which the debug communication will be run, thus making this function conveniently non-blocking. + +> :warning: This method should obviously be called at the beginning of the verification process, but not only then! Empirical evidence suggests **resetting the debug connection** approximately **every 100 iterations** to ensure reliable operation. + +_Parameters_: +None + +#### stopDeb + +_Purpose_: +This method is used to close the debugger. Useful both at the end of a script or during the cyclical reset of the debug connection, as explained before. + +_Parameters_: +None + +#### genInputDataset + +_Purpose_: +This method is used to generate random data that the application can use to perform verification. It's possible to set the range of the data, the dimension of the array, the datatype and its variable identifier. In addition, it's possible to obtain a single _.h_ file or both a _.c_ and a _.h_ file. + +_Parameters_: +- **dataset_size**: Indicates the size of the input array to be generated. +- **parameters**: This optional argument is a *dictionary* of parameters that might be useful for the application. It has *no impact on the value generation* but it will be written in the *.h* file. +- **row_size**: By default set to *0*, this parameter is used to organize the array in the case of matrix generation. In other words, every *row_size* words, the matrix will have a new line. +- **range_min** / **range_max**: These are used to set the range of the random data. They can be both negative and float, if the datatype supports it. +- **dataset_dir**: Indicates the directory in which the generated file will be saved, including the name of the file itself. +- **dataset_dir_c**: By default *empty*, when set to a directory it forces the method to generate both a _.c_ and a _.h_, the first with the data definition and the second with its declaration. +- **dataset_name**: Indicates the name of the dataset. +- **datatype**: By default set to *uint32_t*, indicates the datatype of the array to be generated. + +#### genGoldenResult + +_Purpose_: +This method is used to generate golden data from an input dataset, enabling applications to verify the functionality of a unit or accelerator. This feature is performed by a user-defined function, passed as a parameter, which processes the input data. + +Similar to input generation, users can specify the data range, array dimensions, data type, and variable identifier. Additionally, the output can be configured to produce either a single _.h_ file or both a _.c_ and a _.h_ file. + +_Parameters_: +- **function**: This function is the one used by the method to generate the golden results. +- **golden_size**: Indicates the size of the output array to be computed. +- **parameters**:This optional argument is a *dictionary* of parameters that might be useful for the application. It has no impact on the golden result computation but it will be written in the *.h* file. +- **row_size**: By default set to *0*, this parameter is used to organize the array in the case of matrix generation. In other words, every *row_size* words, the matrix will have a new line. +- **range_min** / **range_max**: These are used to set the range of the random data. They can be both negative and float, if the datatype supports it. +- **golden_dir**: Indicates the directory in which the generated file will be saved, including the name of the file itself. +- **golden_dir_c**: By default *empty*, when set to a directory it forces the method to generate both a _.c_ and a _.h_, the first with the data definition and the second with its declaration. +- **input_dir**: Indicates the input data used to generate the golden result. +- **golden_name**: Indicates the name of the golden result array. +- **output_datatype**: By default set to *uint32_t*, indicates the datatype of the array to be computed. + +#### modifyFile + +_Purpose_: +This method is simple yet very useful in particular situations. It allows the user to modify a row with a replacement of its choice. It can be used to modify _#define_ that could change the behaviour of the application. + +For example, the im2col SPC verification example makes use of this feature twice. The first time it modifies the format of the output of the application to be adherent to the verification procedure (which by default it is not). +The second time it reduces the verification times, by avoiding to repeat unnecessary tests. + +_Parameters_: +- **file_dir**: Indicates the directory of the file that the user wants to modify. +- **pattern**: Indicates the pattern to look for in the file, using the library **re**. +- **replacement**: Indicates the row that will be put in place instead of the pattern found. + +#### chronoStart/chronoStop + +_Purpose_:This method is used to track the execution time of an iteration and, by extension, to estimate the total execution time of the verification process. + +_Parameters_: +None + +#### chronoExecutionEst + +_Purpose_:This method estimates the total execution time of the verification process, assuming the verification consists of a loop with N iterations. It requires that the `_chronoStart_` method is called at the beginning and the `_chronoStop_` method is called at the end of each iteration. + +_Parameters_: +- **loop_size**: Size of the loop, i.e. number of iterations of the entire verification process. If it's composed of nested loops, the total number of iterations is obtained by multiplying the size of each loop. + +_Return value_: +- **Remaining time**, a _dictionary_: + - _"hours"_ + - _"minutes"_ + - _"seconds"_ + +#### launchTest + +_Purpose_: +This method is crucial in the verification process, as it's in charge of compiling the application, loading it on the FPGA using the scan chains and GDB, waiting for the results and storing then in *self.results*. + +Its important to note that this method expects a **specific output format** from the application, which needs to be strictly respected otherwise the whole verification would be disrupted. +By default, this is the format expected: + +
+
 test_id:cycles:outcome
+  ...
+  & 
+
+ +An application can send N lines composed of: +- **test_id**: the ID of the test being performed. A single application can test multiple aspects or features, so different tests can be performed in a single run. In the **im2col_spc** application, this is exactly what happens: three different tests are perfomed each run. +- **cycles**: the number of cycles needed by the system to perform that specific test. In order to keep track of the execution cycles, a `timer_sdk` has been developed. Please refer to `example_timer_sdk` for a practical implementation. +- **outcome**: the outcome of the verification performed by the application itself. For example, the application might set up the DMA to perform a transaction and then check that the result corresponds to the golden result. + +Each of these fields can be **left blank** or with whatever ASCII character, but the format has to be followed nonetheless. For example, one could be interested only in verify its design, avoiding the performance estimation. In such case, _cycles_ could be always set to _0_. + +At the end of the run, the application **must send the end character** `&`. + +If needed, the format of the data sent by the application can be modified by changing the _pattern_ parameter. + +_Parameters_: +- **example_name**: Name of the example folder in X-Heep sw/application. e.g. For the DMA verification, this field would have been *example_dma*. +- **input_size**: This field will be appended to the data obtained by the simulation, not mandatory but might be useful for data processing. +- **pattern**: By default set to *test_id:cycles:outcome*. It can be changed by the user, with **caution**. +- **en_timeout_term**: By default set to _False_, if enabled it terminates the application in case that the board doesn't reply in time. + diff --git a/hw/vendor/esl_epfl_x_heep/ides/img/build_screenshot.png b/hw/vendor/esl_epfl_x_heep/docs/source/_static/ides/build_screenshot.png similarity index 100% rename from hw/vendor/esl_epfl_x_heep/ides/img/build_screenshot.png rename to hw/vendor/esl_epfl_x_heep/docs/source/_static/ides/build_screenshot.png diff --git a/hw/vendor/esl_epfl_x_heep/ides/img/debug_screenshot.png b/hw/vendor/esl_epfl_x_heep/docs/source/_static/ides/debug_screenshot.png similarity index 100% rename from hw/vendor/esl_epfl_x_heep/ides/img/debug_screenshot.png rename to hw/vendor/esl_epfl_x_heep/docs/source/_static/ides/debug_screenshot.png diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/conf.py b/hw/vendor/esl_epfl_x_heep/docs/source/conf.py index c9f6eaab..44ce6b68 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/conf.py +++ b/hw/vendor/esl_epfl_x_heep/docs/source/conf.py @@ -4,6 +4,10 @@ # # Author: Embedded Systems Laboratory (EPFL) +import os +import sys +sys.path.insert(0, os.path.abspath("../../util")) + project = 'X-HEEP' copyright = '2023, EPFL' author = 'ESL' @@ -17,9 +21,12 @@ 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', 'sphinx.ext.intersphinx', + 'sphinxcontrib.apidoc', 'myst_parser', ] +html_static_path = ['_static'] + source_suffix = ['.rst', '.md'] intersphinx_mapping = { @@ -33,3 +40,7 @@ html_theme = 'sphinx_rtd_theme' epub_show_urls = 'footnote' + +apidoc_module_dir = '../../util/x_heep_gen' +apidoc_output_dir = 'Configuration/generated' +apidoc_separate_modules = True \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/images/dma_structure.png b/hw/vendor/esl_epfl_x_heep/docs/source/images/dma_structure.png new file mode 100644 index 00000000..1000debb Binary files /dev/null and b/hw/vendor/esl_epfl_x_heep/docs/source/images/dma_structure.png differ diff --git a/hw/vendor/esl_epfl_x_heep/block_diagrams/example_adc.svg b/hw/vendor/esl_epfl_x_heep/docs/source/images/example_adc.svg similarity index 100% rename from hw/vendor/esl_epfl_x_heep/block_diagrams/example_adc.svg rename to hw/vendor/esl_epfl_x_heep/docs/source/images/example_adc.svg diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/images/x-heep-outline.png b/hw/vendor/esl_epfl_x_heep/docs/source/images/x-heep-outline.png new file mode 100644 index 00000000..b2aa5446 Binary files /dev/null and b/hw/vendor/esl_epfl_x_heep/docs/source/images/x-heep-outline.png differ diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/images/xheep_diagram.png b/hw/vendor/esl_epfl_x_heep/docs/source/images/xheep_diagram.png new file mode 100644 index 00000000..681962c0 Binary files /dev/null and b/hw/vendor/esl_epfl_x_heep/docs/source/images/xheep_diagram.png differ diff --git a/hw/vendor/esl_epfl_x_heep/docs/source/index.rst b/hw/vendor/esl_epfl_x_heep/docs/source/index.rst index e3968a3f..a0d4c746 100644 --- a/hw/vendor/esl_epfl_x_heep/docs/source/index.rst +++ b/hw/vendor/esl_epfl_x_heep/docs/source/index.rst @@ -1,6 +1,11 @@ X-HEEP ====== +.. image:: images/x-heep-outline.png + :width: 600 + + + ``X-HEEP`` (eXtendable Heterogeneous Energy-Efficient Platform) is a RISC-V microcontroller described in SystemVerilog that can be configured to target small and tiny platforms as well as extended to support accelerators. The cool thing about X-HEEP is that we provide a simple customizable MCU, so CPUs, common peripherals, memories, etc. so that you can extend it with your own accelerator without modifying the MCU, but just instantiating it in your design. By doing so, you inherit an IP capable of booting RTOS (such as FreeRTOS) with the whole FW stack, including HAL drivers and SDK, and you can focus on building your special HW or APP supported by the microcontroller. @@ -23,7 +28,7 @@ The CPU subsystem is based on the `RISC-V lowRISC Ibex 0) begin + /* Assign the bus port to the first input port of the AOPB */ + reg_req_t [AO_SPC_NUM_RND:0] packet_req; + reg_rsp_t [AO_SPC_NUM_RND:0] packet_rsp; + + assign packet_req[0] = peripheral_req; + assign peripheral_rsp = packet_rsp[0]; + + for (genvar i = 0; i < AO_SPC_NUM_RND; i++) begin : gen_spc + assign packet_req[i+1] = spc2ao_req_i[i]; + assign ao2spc_resp_o[i] = packet_rsp[i+1]; + end + + reg_mux #( + .NoPorts(AO_SPC_NUM_RND + 1), + .req_t (reg_pkg::reg_req_t), + .rsp_t (reg_pkg::reg_rsp_t), + .AW (32), + .DW (32) + ) reg_mux_i ( + .clk_i, + .rst_ni, + .in_req_i (packet_req), + .in_rsp_o (packet_rsp), + .out_req_o(perconv2regdemux_req), + .out_rsp_i(regdemux2perconv_resp) + ); + + end else begin + assign perconv2regdemux_req = peripheral_req; + assign peripheral_rsp = regdemux2perconv_resp; + end + endgenerate + + /* Address decoder for the peripheral registers */ addr_decode #( .NoIndices(core_v_mini_mcu_pkg::AO_PERIPHERALS), .NoRules(core_v_mini_mcu_pkg::AO_PERIPHERALS), .addr_t(logic [31:0]), .rule_t(addr_map_rule_pkg::addr_map_rule_t) ) i_addr_decode_soc_regbus_periph_xbar ( - .addr_i(peripheral_req.addr), + .addr_i(perconv2regdemux_req.addr), .addr_map_i(core_v_mini_mcu_pkg::AO_PERIPHERALS_ADDR_RULES), .idx_o(peripheral_select), .dec_valid_o(), @@ -223,6 +281,7 @@ module ao_peripheral_subsystem .default_idx_i('0) ); + /* Register demux */ reg_demux #( .NoPorts(core_v_mini_mcu_pkg::AO_PERIPHERALS), .req_t (reg_pkg::reg_req_t), @@ -231,8 +290,8 @@ module ao_peripheral_subsystem .clk_i, .rst_ni, .in_select_i(peripheral_select), - .in_req_i(peripheral_req), - .in_rsp_o(peripheral_rsp), + .in_req_i(perconv2regdemux_req), + .in_rsp_o(regdemux2perconv_resp), .out_req_o(ao_peripheral_slv_req), .out_rsp_i(ao_peripheral_slv_rsp) ); @@ -252,11 +311,13 @@ module ao_peripheral_subsystem .exit_value_o ); + /* Boot ROM */ boot_rom boot_rom_i ( .reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::BOOTROM_IDX]), .reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::BOOTROM_IDX]) ); + /* SPI subsystem */ spi_subsystem spi_subsystem_i ( .clk_i, .rst_ni, @@ -280,31 +341,7 @@ module ao_peripheral_subsystem .spi_flash_tx_ready_o(spi_flash_tx_ready) ); - spi_host #( - .reg_req_t(reg_pkg::reg_req_t), - .reg_rsp_t(reg_pkg::reg_rsp_t) - ) spi_host_dma_i ( - .clk_i, - .rst_ni, - .reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::SPI_HOST_IDX]), - .reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::SPI_HOST_IDX]), - .alert_rx_i(), - .alert_tx_o(), - .passthrough_i(spi_device_pkg::PASSTHROUGH_REQ_DEFAULT), - .passthrough_o(), - .cio_sck_o(spi_sck_o), - .cio_sck_en_o(spi_sck_en_o), - .cio_csb_o(spi_csb_o), - .cio_csb_en_o(spi_csb_en_o), - .cio_sd_o(spi_sd_o), - .cio_sd_en_o(spi_sd_en_o), - .cio_sd_i(spi_sd_i), - .rx_valid_o(spi_rx_valid), - .tx_ready_o(spi_tx_ready), - .intr_error_o(), - .intr_spi_event_o(spi_intr_event_o) - ); - + /* Power manager */ power_manager #( .reg_req_t(reg_pkg::reg_req_t), .reg_rsp_t(reg_pkg::reg_rsp_t) @@ -316,26 +353,15 @@ module ao_peripheral_subsystem .intr_i, .ext_irq_i(intr_vector_ext_i), .core_sleep_i, - .cpu_subsystem_powergate_switch_no, - .cpu_subsystem_powergate_switch_ack_ni, - .cpu_subsystem_powergate_iso_no, - .cpu_subsystem_rst_no, - .peripheral_subsystem_powergate_switch_no, - .peripheral_subsystem_powergate_switch_ack_ni, - .peripheral_subsystem_powergate_iso_no, - .peripheral_subsystem_rst_no, - .memory_subsystem_banks_powergate_switch_no, - .memory_subsystem_banks_powergate_switch_ack_ni, - .memory_subsystem_banks_powergate_iso_no, - .memory_subsystem_banks_set_retentive_no, - .external_subsystem_powergate_switch_no, - .external_subsystem_powergate_switch_ack_ni, - .external_subsystem_powergate_iso_no, - .external_subsystem_rst_no, - .external_ram_banks_set_retentive_no, - .peripheral_subsystem_clkgate_en_no, - .memory_subsystem_clkgate_en_no, - .external_subsystem_clkgate_en_no + .cpu_subsystem_pwr_ctrl_o, + .peripheral_subsystem_pwr_ctrl_o, + .memory_subsystem_pwr_ctrl_o, + .external_subsystem_pwr_ctrl_o, + .cpu_subsystem_pwr_ctrl_i, + .peripheral_subsystem_pwr_ctrl_i, + .memory_subsystem_pwr_ctrl_i, + .external_subsystem_pwr_ctrl_i, + .dma_subsystem_pwr_ctrl_o(dma_subsystem_pwr_ctrl) ); reg_to_tlul #( @@ -364,39 +390,33 @@ module ao_peripheral_subsystem .intr_timer_expired_1_0_o(rv_timer_1_intr_o) ); - parameter DMA_TRIGGER_SLOT_NUM = 5; - logic [DMA_TRIGGER_SLOT_NUM-1:0] dma_trigger_slots; - assign dma_trigger_slots[0] = spi_rx_valid; - assign dma_trigger_slots[1] = spi_tx_ready; - assign dma_trigger_slots[2] = spi_flash_rx_valid; - assign dma_trigger_slots[3] = spi_flash_tx_ready; - assign dma_trigger_slots[4] = i2s_rx_valid_i; - - dma #( - .reg_req_t (reg_pkg::reg_req_t), - .reg_rsp_t (reg_pkg::reg_rsp_t), - .obi_req_t (obi_pkg::obi_req_t), + dma_subsystem #( + .reg_req_t(reg_pkg::reg_req_t), + .reg_rsp_t(reg_pkg::reg_rsp_t), + .obi_req_t(obi_pkg::obi_req_t), .obi_resp_t(obi_pkg::obi_resp_t), - .SLOT_NUM (DMA_TRIGGER_SLOT_NUM) - ) dma_i ( + .GLOBAL_SLOT_NUM(DMA_GLOBAL_TRIGGER_SLOT_NUM), + .EXT_SLOT_NUM(DMA_EXT_TRIGGER_SLOT_NUM) + ) dma_subsystem_i ( .clk_i, .rst_ni, + .clk_gate_en_ni(dma_clk_gate_en_n), .reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::DMA_IDX]), .reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::DMA_IDX]), - .dma_read_ch0_req_o, - .dma_read_ch0_resp_i, - .dma_write_ch0_req_o, - .dma_write_ch0_resp_i, - .dma_addr_ch0_req_o, - .dma_addr_ch0_resp_i, - .trigger_slot_i(dma_trigger_slots), + .dma_read_req_o, + .dma_read_resp_i, + .dma_write_req_o, + .dma_write_resp_i, + .dma_addr_req_o, + .dma_addr_resp_i, + .global_trigger_slot_i(dma_global_trigger_slots), + .ext_trigger_slot_i(dma_ext_trigger_slots), + .ext_dma_stop_i(ext_dma_stop_i), .dma_done_intr_o(dma_done_intr_o), - .dma_window_intr_o(dma_window_intr_o) + .dma_window_intr_o(dma_window_intr_o), + .dma_done_o(dma_done_o) ); - assign pad_req_o = ao_peripheral_slv_req[core_v_mini_mcu_pkg::PAD_CONTROL_IDX]; - assign ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::PAD_CONTROL_IDX] = pad_resp_i; - fast_intr_ctrl #( .reg_req_t(reg_pkg::reg_req_t), .reg_rsp_t(reg_pkg::reg_rsp_t) @@ -409,6 +429,7 @@ module ao_peripheral_subsystem .fast_intr_o ); + /* GPIO subsystem */ gpio #( .reg_req_t(reg_pkg::reg_req_t), .reg_rsp_t(reg_pkg::reg_rsp_t) @@ -442,6 +463,7 @@ module ao_peripheral_subsystem .reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::UART_IDX]) ); + /* UART */ uart uart_i ( .clk_i, .rst_ni, diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv index 4a1ef2e9..db16c9a3 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv @@ -11,10 +11,14 @@ module core_v_mini_mcu parameter ZFINX = 0, parameter EXT_XBAR_NMASTER = 0, parameter X_EXT = 0, // eXtension interface in cv32e40x + parameter AO_SPC_NUM = 0, + parameter EXT_HARTS = 0, //do not touch these parameters + parameter AO_SPC_NUM_RND = AO_SPC_NUM == 0 ? 1 : AO_SPC_NUM, parameter EXT_XBAR_NMASTER_RND = EXT_XBAR_NMASTER == 0 ? 1 : EXT_XBAR_NMASTER, parameter EXT_DOMAINS_RND = core_v_mini_mcu_pkg::EXTERNAL_DOMAINS == 0 ? 1 : core_v_mini_mcu_pkg::EXTERNAL_DOMAINS, - parameter NEXT_INT_RND = core_v_mini_mcu_pkg::NEXT_INT == 0 ? 1 : core_v_mini_mcu_pkg::NEXT_INT + parameter NEXT_INT_RND = core_v_mini_mcu_pkg::NEXT_INT == 0 ? 1 : core_v_mini_mcu_pkg::NEXT_INT, + parameter EXT_HARTS_RND = EXT_HARTS == 0 ? 1 : EXT_HARTS ) ( input logic rst_ni, @@ -283,48 +287,64 @@ module core_v_mini_mcu input obi_req_t [EXT_XBAR_NMASTER_RND-1:0] ext_xbar_master_req_i, output obi_resp_t [EXT_XBAR_NMASTER_RND-1:0] ext_xbar_master_resp_o, + input reg_req_t [AO_SPC_NUM_RND-1:0] ext_ao_peripheral_slave_req_i, + output reg_rsp_t [AO_SPC_NUM_RND-1:0] ext_ao_peripheral_slave_resp_o, + // External slave ports - output obi_req_t ext_core_instr_req_o, - input obi_resp_t ext_core_instr_resp_i, - output obi_req_t ext_core_data_req_o, - input obi_resp_t ext_core_data_resp_i, - output obi_req_t ext_debug_master_req_o, - input obi_resp_t ext_debug_master_resp_i, - output obi_req_t ext_dma_read_ch0_req_o, - input obi_resp_t ext_dma_read_ch0_resp_i, - output obi_req_t ext_dma_write_ch0_req_o, - input obi_resp_t ext_dma_write_ch0_resp_i, - output obi_req_t ext_dma_addr_ch0_req_o, - input obi_resp_t ext_dma_addr_ch0_resp_i, + output obi_req_t ext_core_instr_req_o, + input obi_resp_t ext_core_instr_resp_i, + output obi_req_t ext_core_data_req_o, + input obi_resp_t ext_core_data_resp_i, + output obi_req_t ext_debug_master_req_o, + input obi_resp_t ext_debug_master_resp_i, + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_read_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_read_resp_i, + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_write_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_write_resp_i, + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_addr_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_addr_resp_i, + + input logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] ext_dma_stop_i, output reg_req_t ext_peripheral_slave_req_o, input reg_rsp_t ext_peripheral_slave_resp_i, + output logic [EXT_HARTS_RND-1:0] ext_debug_req_o, + output logic ext_debug_reset_no, + input logic [NEXT_INT_RND-1:0] intr_vector_ext_i, + //power manager exposed to top level + //signals are unrolled to easy EDA tools output logic cpu_subsystem_powergate_switch_no, input logic cpu_subsystem_powergate_switch_ack_ni, output logic peripheral_subsystem_powergate_switch_no, input logic peripheral_subsystem_powergate_switch_ack_ni, - output logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_no, - input logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_ack_ni, output logic [EXT_DOMAINS_RND-1:0] external_subsystem_powergate_switch_no, input logic [EXT_DOMAINS_RND-1:0] external_subsystem_powergate_switch_ack_ni, output logic [EXT_DOMAINS_RND-1:0] external_subsystem_powergate_iso_no, output logic [EXT_DOMAINS_RND-1:0] external_subsystem_rst_no, + output logic ext_cpu_subsystem_rst_no, output logic [EXT_DOMAINS_RND-1:0] external_ram_banks_set_retentive_no, output logic [EXT_DOMAINS_RND-1:0] external_subsystem_clkgate_en_no, - output logic [31:0] exit_value_o + output logic [31:0] exit_value_o, + + // External SPC interface + input logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] ext_dma_slot_tx_i, + input logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] ext_dma_slot_rx_i, + output logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] dma_done_o ); import core_v_mini_mcu_pkg::*; import cv32e40p_apu_core_pkg::*; + import power_manager_pkg::*; localparam NUM_BYTES = core_v_mini_mcu_pkg::MEM_SIZE; localparam DM_HALTADDRESS = core_v_mini_mcu_pkg::DEBUG_START_ADDRESS + 32'h00000800; //debug rom code (section .text in linker) starts at 0x800 localparam JTAG_IDCODE = 32'h10001c05; + localparam NRHARTS = EXT_HARTS + 1; //external harts + single hart core-v-mini-mcu localparam BOOT_ADDR = core_v_mini_mcu_pkg::BOOTROM_START_ADDRESS; localparam NUM_MHPMCOUNTERS = 1; @@ -342,12 +362,12 @@ module core_v_mini_mcu obi_resp_t core_data_resp; obi_req_t debug_master_req; obi_resp_t debug_master_resp; - obi_req_t dma_read_ch0_req; - obi_resp_t dma_read_ch0_resp; - obi_req_t dma_write_ch0_req; - obi_resp_t dma_write_ch0_resp; - obi_req_t dma_addr_ch0_req; - obi_resp_t dma_addr_ch0_resp; + obi_req_t [0:0] dma_read_req; + obi_resp_t [0:0] dma_read_resp; + obi_req_t [0:0] dma_write_req; + obi_resp_t [0:0] dma_write_resp; + obi_req_t [0:0] dma_addr_req; + obi_resp_t [0:0] dma_addr_resp; // ram signals obi_req_t [core_v_mini_mcu_pkg::NUM_BANKS-1:0] ram_slave_req; @@ -365,7 +385,8 @@ module core_v_mini_mcu // signals to debug unit logic debug_core_req; - + logic debug_reset_n; + logic [NRHARTS-1:0] debug_req; // core logic core_sleep; @@ -387,24 +408,109 @@ module core_v_mini_mcu logic [31:0] intr; logic [14:0] fast_intr; - // Power manager - logic cpu_subsystem_powergate_iso_n; + //Power manager signals + power_manager_out_t cpu_subsystem_pwr_ctrl_out; + power_manager_out_t peripheral_subsystem_pwr_ctrl_out; + power_manager_out_t memory_subsystem_pwr_ctrl_out[core_v_mini_mcu_pkg::NUM_BANKS-1:0]; + power_manager_out_t external_subsystem_pwr_ctrl_out[EXT_DOMAINS_RND-1:0]; + + power_manager_in_t cpu_subsystem_pwr_ctrl_in; + power_manager_in_t peripheral_subsystem_pwr_ctrl_in; + power_manager_in_t memory_subsystem_pwr_ctrl_in[core_v_mini_mcu_pkg::NUM_BANKS-1:0]; + power_manager_in_t external_subsystem_pwr_ctrl_in[EXT_DOMAINS_RND-1:0]; + logic cpu_subsystem_rst_n; - logic peripheral_subsystem_powergate_iso_n; - logic peripheral_subsystem_rst_n; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_iso_n; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_set_retentive_n; + logic cpu_subsystem_powergate_iso_n; - // Clock gating signals + logic peripheral_subsystem_rst_n; + logic peripheral_subsystem_powergate_iso_n; logic peripheral_subsystem_clkgate_en_n; + + logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_n; + logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_ack_n; + logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_set_retentive_n; + logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_iso_n; logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_clkgate_en_n; + //pwrgate exposed outside for UPF sim flow and switch cells + assign cpu_subsystem_powergate_switch_no = cpu_subsystem_pwr_ctrl_out.pwrgate_en_n; + assign cpu_subsystem_pwr_ctrl_in.pwrgate_ack_n = cpu_subsystem_powergate_switch_ack_ni; + //isogate exposed outside for UPF sim flow and switch cells + assign cpu_subsystem_powergate_iso_n = cpu_subsystem_pwr_ctrl_out.isogate_en_n; + assign cpu_subsystem_rst_n = cpu_subsystem_pwr_ctrl_out.rst_n; + + //pwrgate exposed both outside for UPF sim flow + assign peripheral_subsystem_powergate_switch_no = peripheral_subsystem_pwr_ctrl_out.pwrgate_en_n; + assign peripheral_subsystem_pwr_ctrl_in.pwrgate_ack_n = peripheral_subsystem_powergate_switch_ack_ni; + //isogate exposed outside for UPF sim flow and switch cells + assign peripheral_subsystem_powergate_iso_n = peripheral_subsystem_pwr_ctrl_out.isogate_en_n; + assign peripheral_subsystem_rst_n = peripheral_subsystem_pwr_ctrl_out.rst_n; + assign peripheral_subsystem_clkgate_en_n = peripheral_subsystem_pwr_ctrl_out.clkgate_en_n; + + assign memory_subsystem_banks_powergate_switch_n[0] = memory_subsystem_pwr_ctrl_out[0].pwrgate_en_n; + assign memory_subsystem_pwr_ctrl_in[0].pwrgate_ack_n = memory_subsystem_banks_powergate_switch_ack_n[0]; + //isogate exposed outside for UPF sim flow and switch cells + assign memory_subsystem_banks_powergate_iso_n[0] = memory_subsystem_pwr_ctrl_out[0].isogate_en_n; + assign memory_subsystem_banks_set_retentive_n[0] = memory_subsystem_pwr_ctrl_out[0].retentive_en_n; + assign memory_subsystem_clkgate_en_n[0] = memory_subsystem_pwr_ctrl_out[0].clkgate_en_n; + assign memory_subsystem_banks_powergate_switch_n[1] = memory_subsystem_pwr_ctrl_out[1].pwrgate_en_n; + assign memory_subsystem_pwr_ctrl_in[1].pwrgate_ack_n = memory_subsystem_banks_powergate_switch_ack_n[1]; + //isogate exposed outside for UPF sim flow and switch cells + assign memory_subsystem_banks_powergate_iso_n[1] = memory_subsystem_pwr_ctrl_out[1].isogate_en_n; + assign memory_subsystem_banks_set_retentive_n[1] = memory_subsystem_pwr_ctrl_out[1].retentive_en_n; + assign memory_subsystem_clkgate_en_n[1] = memory_subsystem_pwr_ctrl_out[1].clkgate_en_n; + assign memory_subsystem_banks_powergate_switch_n[2] = memory_subsystem_pwr_ctrl_out[2].pwrgate_en_n; + assign memory_subsystem_pwr_ctrl_in[2].pwrgate_ack_n = memory_subsystem_banks_powergate_switch_ack_n[2]; + //isogate exposed outside for UPF sim flow and switch cells + assign memory_subsystem_banks_powergate_iso_n[2] = memory_subsystem_pwr_ctrl_out[2].isogate_en_n; + assign memory_subsystem_banks_set_retentive_n[2] = memory_subsystem_pwr_ctrl_out[2].retentive_en_n; + assign memory_subsystem_clkgate_en_n[2] = memory_subsystem_pwr_ctrl_out[2].clkgate_en_n; + assign memory_subsystem_banks_powergate_switch_n[3] = memory_subsystem_pwr_ctrl_out[3].pwrgate_en_n; + assign memory_subsystem_pwr_ctrl_in[3].pwrgate_ack_n = memory_subsystem_banks_powergate_switch_ack_n[3]; + //isogate exposed outside for UPF sim flow and switch cells + assign memory_subsystem_banks_powergate_iso_n[3] = memory_subsystem_pwr_ctrl_out[3].isogate_en_n; + assign memory_subsystem_banks_set_retentive_n[3] = memory_subsystem_pwr_ctrl_out[3].retentive_en_n; + assign memory_subsystem_clkgate_en_n[3] = memory_subsystem_pwr_ctrl_out[3].clkgate_en_n; + assign memory_subsystem_banks_powergate_switch_n[4] = memory_subsystem_pwr_ctrl_out[4].pwrgate_en_n; + assign memory_subsystem_pwr_ctrl_in[4].pwrgate_ack_n = memory_subsystem_banks_powergate_switch_ack_n[4]; + //isogate exposed outside for UPF sim flow and switch cells + assign memory_subsystem_banks_powergate_iso_n[4] = memory_subsystem_pwr_ctrl_out[4].isogate_en_n; + assign memory_subsystem_banks_set_retentive_n[4] = memory_subsystem_pwr_ctrl_out[4].retentive_en_n; + assign memory_subsystem_clkgate_en_n[4] = memory_subsystem_pwr_ctrl_out[4].clkgate_en_n; + assign memory_subsystem_banks_powergate_switch_n[5] = memory_subsystem_pwr_ctrl_out[5].pwrgate_en_n; + assign memory_subsystem_pwr_ctrl_in[5].pwrgate_ack_n = memory_subsystem_banks_powergate_switch_ack_n[5]; + //isogate exposed outside for UPF sim flow and switch cells + assign memory_subsystem_banks_powergate_iso_n[5] = memory_subsystem_pwr_ctrl_out[5].isogate_en_n; + assign memory_subsystem_banks_set_retentive_n[5] = memory_subsystem_pwr_ctrl_out[5].retentive_en_n; + assign memory_subsystem_clkgate_en_n[5] = memory_subsystem_pwr_ctrl_out[5].clkgate_en_n; + assign memory_subsystem_banks_powergate_switch_n[6] = memory_subsystem_pwr_ctrl_out[6].pwrgate_en_n; + assign memory_subsystem_pwr_ctrl_in[6].pwrgate_ack_n = memory_subsystem_banks_powergate_switch_ack_n[6]; + //isogate exposed outside for UPF sim flow and switch cells + assign memory_subsystem_banks_powergate_iso_n[6] = memory_subsystem_pwr_ctrl_out[6].isogate_en_n; + assign memory_subsystem_banks_set_retentive_n[6] = memory_subsystem_pwr_ctrl_out[6].retentive_en_n; + assign memory_subsystem_clkgate_en_n[6] = memory_subsystem_pwr_ctrl_out[6].clkgate_en_n; + assign memory_subsystem_banks_powergate_switch_n[7] = memory_subsystem_pwr_ctrl_out[7].pwrgate_en_n; + assign memory_subsystem_pwr_ctrl_in[7].pwrgate_ack_n = memory_subsystem_banks_powergate_switch_ack_n[7]; + //isogate exposed outside for UPF sim flow and switch cells + assign memory_subsystem_banks_powergate_iso_n[7] = memory_subsystem_pwr_ctrl_out[7].isogate_en_n; + assign memory_subsystem_banks_set_retentive_n[7] = memory_subsystem_pwr_ctrl_out[7].retentive_en_n; + assign memory_subsystem_clkgate_en_n[7] = memory_subsystem_pwr_ctrl_out[7].clkgate_en_n; + + for (genvar i = 0; i < EXT_DOMAINS_RND; i = i + 1) begin + assign external_subsystem_powergate_switch_no[i] = external_subsystem_pwr_ctrl_out[i].pwrgate_en_n; + assign external_subsystem_powergate_iso_no[i] = external_subsystem_pwr_ctrl_out[i].isogate_en_n; + assign external_subsystem_rst_no[i] = external_subsystem_pwr_ctrl_out[i].rst_n; + assign external_ram_banks_set_retentive_no[i] = external_subsystem_pwr_ctrl_out[i].retentive_en_n; + assign external_subsystem_clkgate_en_no[i] = external_subsystem_pwr_ctrl_out[i].clkgate_en_n; + assign external_subsystem_pwr_ctrl_in[i].pwrgate_ack_n = external_subsystem_powergate_switch_ack_ni[i]; + end + // DMA logic dma_done_intr; logic dma_window_intr; // SPI - logic spi_flash_intr, spi_intr; + logic spi_flash_intr, spi_intr, spi_rx_valid, spi_tx_ready; // GPIO logic [31:8] gpio_in; @@ -456,7 +562,7 @@ module core_v_mini_mcu ) cpu_subsystem_i ( // Clock and Reset .clk_i, - .rst_ni(cpu_subsystem_rst_n), + .rst_ni(cpu_subsystem_rst_n && debug_reset_n), .core_instr_req_o(core_instr_req), .core_instr_resp_i(core_instr_resp), .core_data_req_o(core_data_req), @@ -475,6 +581,7 @@ module core_v_mini_mcu ); debug_subsystem #( + .NRHARTS (NRHARTS), .JTAG_IDCODE(JTAG_IDCODE) ) debug_subsystem_i ( .clk_i, @@ -484,7 +591,8 @@ module core_v_mini_mcu .jtag_trst_ni, .jtag_tdi_i, .jtag_tdo_o, - .debug_core_req_o(debug_core_req), + .debug_core_req_o(debug_req), + .debug_ndmreset_no(debug_reset_n), .debug_slave_req_i(debug_slave_req), .debug_slave_resp_o(debug_slave_resp), .debug_master_req_o(debug_master_req), @@ -496,19 +604,19 @@ module core_v_mini_mcu .EXT_XBAR_NMASTER(EXT_XBAR_NMASTER) ) system_bus_i ( .clk_i, - .rst_ni, + .rst_ni(rst_ni && debug_reset_n), .core_instr_req_i(core_instr_req), .core_instr_resp_o(core_instr_resp), .core_data_req_i(core_data_req), .core_data_resp_o(core_data_resp), .debug_master_req_i(debug_master_req), .debug_master_resp_o(debug_master_resp), - .dma_read_ch0_req_i(dma_read_ch0_req), - .dma_read_ch0_resp_o(dma_read_ch0_resp), - .dma_write_ch0_req_i(dma_write_ch0_req), - .dma_write_ch0_resp_o(dma_write_ch0_resp), - .dma_addr_ch0_req_i(dma_addr_ch0_req), - .dma_addr_ch0_resp_o(dma_addr_ch0_resp), + .dma_read_req_i(dma_read_req), + .dma_read_resp_o(dma_read_resp), + .dma_write_req_i(dma_write_req), + .dma_write_resp_o(dma_write_resp), + .dma_addr_req_i(dma_addr_req), + .dma_addr_resp_o(dma_addr_resp), .ext_xbar_master_req_i(ext_xbar_master_req_i), .ext_xbar_master_resp_o(ext_xbar_master_resp_o), .ram_req_o(ram_slave_req), @@ -527,30 +635,36 @@ module core_v_mini_mcu .ext_core_data_resp_i(ext_core_data_resp_i), .ext_debug_master_req_o(ext_debug_master_req_o), .ext_debug_master_resp_i(ext_debug_master_resp_i), - .ext_dma_read_ch0_req_o(ext_dma_read_ch0_req_o), - .ext_dma_read_ch0_resp_i(ext_dma_read_ch0_resp_i), - .ext_dma_write_ch0_req_o(ext_dma_write_ch0_req_o), - .ext_dma_write_ch0_resp_i(ext_dma_write_ch0_resp_i), - .ext_dma_addr_ch0_req_o(ext_dma_addr_ch0_req_o), - .ext_dma_addr_ch0_resp_i(ext_dma_addr_ch0_resp_i) + .ext_dma_read_req_o(ext_dma_read_req_o), + .ext_dma_read_resp_i(ext_dma_read_resp_i), + .ext_dma_write_req_o(ext_dma_write_req_o), + .ext_dma_write_resp_i(ext_dma_write_resp_i), + .ext_dma_addr_req_o(ext_dma_addr_req_o), + .ext_dma_addr_resp_i(ext_dma_addr_resp_i) ); memory_subsystem #( .NUM_BANKS(core_v_mini_mcu_pkg::NUM_BANKS) ) memory_subsystem_i ( .clk_i, - .rst_ni, + .rst_ni(rst_ni && debug_reset_n), .clk_gate_en_ni(memory_subsystem_clkgate_en_n), .ram_req_i(ram_slave_req), .ram_resp_o(ram_slave_resp), + .pwrgate_ni(memory_subsystem_banks_powergate_switch_n), + .pwrgate_ack_no(memory_subsystem_banks_powergate_switch_ack_n), .set_retentive_ni(memory_subsystem_banks_set_retentive_n) ); - ao_peripheral_subsystem ao_peripheral_subsystem_i ( + ao_peripheral_subsystem #( + .AO_SPC_NUM(AO_SPC_NUM) + ) ao_peripheral_subsystem_i ( .clk_i, - .rst_ni, + .rst_ni(rst_ni && debug_reset_n), .slave_req_i(ao_peripheral_slave_req), .slave_resp_o(ao_peripheral_slave_resp), + .spc2ao_req_i(ext_ao_peripheral_slave_req_i), + .ao2spc_resp_o(ext_ao_peripheral_slave_resp_o), .boot_select_i, .execute_from_flash_i, .exit_valid_o, @@ -566,47 +680,27 @@ module core_v_mini_mcu spi_flash_sd_3_oe_o, spi_flash_sd_2_oe_o, spi_flash_sd_1_oe_o, spi_flash_sd_0_oe_o }), .spi_flash_sd_i({spi_flash_sd_3_i, spi_flash_sd_2_i, spi_flash_sd_1_i, spi_flash_sd_0_i}), - .spi_sck_o, - .spi_sck_en_o(spi_sck_oe_o), - .spi_csb_o({spi_cs_1_o, spi_cs_0_o}), - .spi_csb_en_o({spi_cs_1_oe_o, spi_cs_0_oe_o}), - .spi_sd_o({spi_sd_3_o, spi_sd_2_o, spi_sd_1_o, spi_sd_0_o}), - .spi_sd_en_o({spi_sd_3_oe_o, spi_sd_2_oe_o, spi_sd_1_oe_o, spi_sd_0_oe_o}), - .spi_sd_i({spi_sd_3_i, spi_sd_2_i, spi_sd_1_i, spi_sd_0_i}), .intr_i(intr), .intr_vector_ext_i, .core_sleep_i(core_sleep), - .cpu_subsystem_powergate_switch_no, - .cpu_subsystem_powergate_switch_ack_ni, - .cpu_subsystem_powergate_iso_no(cpu_subsystem_powergate_iso_n), - .cpu_subsystem_rst_no(cpu_subsystem_rst_n), - .peripheral_subsystem_powergate_switch_no, - .peripheral_subsystem_powergate_switch_ack_ni, - .peripheral_subsystem_powergate_iso_no(peripheral_subsystem_powergate_iso_n), - .peripheral_subsystem_rst_no(peripheral_subsystem_rst_n), - .memory_subsystem_banks_powergate_switch_no, - .memory_subsystem_banks_powergate_switch_ack_ni, - .memory_subsystem_banks_powergate_iso_no(memory_subsystem_banks_powergate_iso_n), - .memory_subsystem_banks_set_retentive_no(memory_subsystem_banks_set_retentive_n), - .external_subsystem_powergate_switch_no, - .external_subsystem_powergate_switch_ack_ni, - .external_subsystem_powergate_iso_no, - .external_subsystem_rst_no, - .external_ram_banks_set_retentive_no, - .peripheral_subsystem_clkgate_en_no(peripheral_subsystem_clkgate_en_n), - .memory_subsystem_clkgate_en_no(memory_subsystem_clkgate_en_n), - .external_subsystem_clkgate_en_no, + .cpu_subsystem_pwr_ctrl_o(cpu_subsystem_pwr_ctrl_out), + .peripheral_subsystem_pwr_ctrl_o(peripheral_subsystem_pwr_ctrl_out), + .memory_subsystem_pwr_ctrl_o(memory_subsystem_pwr_ctrl_out), + .external_subsystem_pwr_ctrl_o(external_subsystem_pwr_ctrl_out), + .cpu_subsystem_pwr_ctrl_i(cpu_subsystem_pwr_ctrl_in), + .peripheral_subsystem_pwr_ctrl_i(peripheral_subsystem_pwr_ctrl_in), + .memory_subsystem_pwr_ctrl_i(memory_subsystem_pwr_ctrl_in), + .external_subsystem_pwr_ctrl_i(external_subsystem_pwr_ctrl_in), .rv_timer_0_intr_o(rv_timer_intr[0]), .rv_timer_1_intr_o(rv_timer_intr[1]), - .dma_read_ch0_req_o(dma_read_ch0_req), - .dma_read_ch0_resp_i(dma_read_ch0_resp), - .dma_write_ch0_req_o(dma_write_ch0_req), - .dma_write_ch0_resp_i(dma_write_ch0_resp), - .dma_addr_ch0_req_o(dma_addr_ch0_req), - .dma_addr_ch0_resp_i(dma_addr_ch0_resp), + .dma_read_req_o(dma_read_req), + .dma_read_resp_i(dma_read_resp), + .dma_write_req_o(dma_write_req), + .dma_write_resp_i(dma_write_resp), + .dma_addr_req_o(dma_addr_req), + .dma_addr_resp_i(dma_addr_resp), .dma_done_intr_o(dma_done_intr), .dma_window_intr_o(dma_window_intr), - .spi_intr_event_o(spi_intr), .spi_flash_intr_event_o(spi_flash_intr), .pad_req_o, .pad_resp_i, @@ -626,14 +720,20 @@ module core_v_mini_mcu .uart_intr_rx_break_err_o(uart_intr_rx_break_err), .uart_intr_rx_timeout_o(uart_intr_rx_timeout), .uart_intr_rx_parity_err_o(uart_intr_rx_parity_err), + .spi_rx_valid_i(spi_rx_valid), + .spi_tx_ready_i(spi_tx_ready), .i2s_rx_valid_i(i2s_rx_valid), .ext_peripheral_slave_req_o, - .ext_peripheral_slave_resp_i + .ext_peripheral_slave_resp_i, + .ext_dma_slot_tx_i, + .ext_dma_slot_rx_i, + .ext_dma_stop_i, + .dma_done_o ); peripheral_subsystem peripheral_subsystem_i ( .clk_i, - .rst_ni(peripheral_subsystem_rst_n), + .rst_ni(peripheral_subsystem_rst_n && debug_reset_n), .clk_gate_en_ni(peripheral_subsystem_clkgate_en_n), .slave_req_i(peripheral_slave_req), .slave_resp_o(peripheral_slave_resp), @@ -658,6 +758,16 @@ module core_v_mini_mcu .cio_sda_i(i2c_sda_i), .cio_sda_o(i2c_sda_o), .cio_sda_en_o(i2c_sda_oe_o), + .spi_sck_o, + .spi_sck_en_o(spi_sck_oe_o), + .spi_csb_o({spi_cs_1_o, spi_cs_0_o}), + .spi_csb_en_o({spi_cs_1_oe_o, spi_cs_0_oe_o}), + .spi_sd_o({spi_sd_3_o, spi_sd_2_o, spi_sd_1_o, spi_sd_0_o}), + .spi_sd_en_o({spi_sd_3_oe_o, spi_sd_2_oe_o, spi_sd_1_oe_o, spi_sd_0_oe_o}), + .spi_sd_i({spi_sd_3_i, spi_sd_2_i, spi_sd_1_i, spi_sd_0_i}), + .spi_intr_event_o(spi_intr), + .spi_rx_valid_o(spi_rx_valid), + .spi_tx_ready_o(spi_tx_ready), .spi2_sck_o, .spi2_sck_en_o(spi2_sck_oe_o), .spi2_csb_o({spi2_cs_1_o, spi2_cs_0_o}), @@ -682,104 +792,120 @@ module core_v_mini_mcu .i2s_rx_valid_o(i2s_rx_valid) ); - assign pdm2pcm_pdm_o = 0; - assign pdm2pcm_pdm_oe_o = 0; - - assign gpio_ao_in[0] = gpio_0_i; - assign gpio_0_o = gpio_ao_out[0]; - assign gpio_0_oe_o = gpio_ao_oe[0]; - assign gpio_ao_in[1] = gpio_1_i; - assign gpio_1_o = gpio_ao_out[1]; - assign gpio_1_oe_o = gpio_ao_oe[1]; - assign gpio_ao_in[2] = gpio_2_i; - assign gpio_2_o = gpio_ao_out[2]; - assign gpio_2_oe_o = gpio_ao_oe[2]; - assign gpio_ao_in[3] = gpio_3_i; - assign gpio_3_o = gpio_ao_out[3]; - assign gpio_3_oe_o = gpio_ao_oe[3]; - assign gpio_ao_in[4] = gpio_4_i; - assign gpio_4_o = gpio_ao_out[4]; - assign gpio_4_oe_o = gpio_ao_oe[4]; - assign gpio_ao_in[5] = gpio_5_i; - assign gpio_5_o = gpio_ao_out[5]; - assign gpio_5_oe_o = gpio_ao_oe[5]; - assign gpio_ao_in[6] = gpio_6_i; - assign gpio_6_o = gpio_ao_out[6]; - assign gpio_6_oe_o = gpio_ao_oe[6]; - assign gpio_ao_in[7] = gpio_7_i; - assign gpio_7_o = gpio_ao_out[7]; - assign gpio_7_oe_o = gpio_ao_oe[7]; - assign gpio_in[8] = gpio_8_i; - assign gpio_8_o = gpio_out[8]; - assign gpio_8_oe_o = gpio_oe[8]; - assign gpio_in[9] = gpio_9_i; - assign gpio_9_o = gpio_out[9]; - assign gpio_9_oe_o = gpio_oe[9]; - assign gpio_in[10] = gpio_10_i; - assign gpio_10_o = gpio_out[10]; - assign gpio_10_oe_o = gpio_oe[10]; - assign gpio_in[11] = gpio_11_i; - assign gpio_11_o = gpio_out[11]; - assign gpio_11_oe_o = gpio_oe[11]; - assign gpio_in[12] = gpio_12_i; - assign gpio_12_o = gpio_out[12]; - assign gpio_12_oe_o = gpio_oe[12]; - assign gpio_in[13] = gpio_13_i; - assign gpio_13_o = gpio_out[13]; - assign gpio_13_oe_o = gpio_oe[13]; - assign gpio_in[14] = gpio_14_i; - assign gpio_14_o = gpio_out[14]; - assign gpio_14_oe_o = gpio_oe[14]; - assign gpio_in[15] = gpio_15_i; - assign gpio_15_o = gpio_out[15]; - assign gpio_15_oe_o = gpio_oe[15]; - assign gpio_in[16] = gpio_16_i; - assign gpio_16_o = gpio_out[16]; - assign gpio_16_oe_o = gpio_oe[16]; - assign gpio_in[17] = gpio_17_i; - assign gpio_17_o = gpio_out[17]; - assign gpio_17_oe_o = gpio_oe[17]; - assign gpio_in[18] = gpio_18_i; - assign gpio_18_o = gpio_out[18]; - assign gpio_18_oe_o = gpio_oe[18]; - assign gpio_in[19] = gpio_19_i; - assign gpio_19_o = gpio_out[19]; - assign gpio_19_oe_o = gpio_oe[19]; - assign gpio_in[20] = gpio_20_i; - assign gpio_20_o = gpio_out[20]; - assign gpio_20_oe_o = gpio_oe[20]; - assign gpio_in[21] = gpio_21_i; - assign gpio_21_o = gpio_out[21]; - assign gpio_21_oe_o = gpio_oe[21]; - assign gpio_in[22] = gpio_22_i; - assign gpio_22_o = gpio_out[22]; - assign gpio_22_oe_o = gpio_oe[22]; - assign gpio_in[23] = gpio_23_i; - assign gpio_23_o = gpio_out[23]; - assign gpio_23_oe_o = gpio_oe[23]; - assign gpio_in[24] = gpio_24_i; - assign gpio_24_o = gpio_out[24]; - assign gpio_24_oe_o = gpio_oe[24]; - assign gpio_in[25] = gpio_25_i; - assign gpio_25_o = gpio_out[25]; - assign gpio_25_oe_o = gpio_oe[25]; - assign gpio_in[26] = gpio_26_i; - assign gpio_26_o = gpio_out[26]; - assign gpio_26_oe_o = gpio_oe[26]; - assign gpio_in[27] = gpio_27_i; - assign gpio_27_o = gpio_out[27]; - assign gpio_27_oe_o = gpio_oe[27]; - assign gpio_in[28] = gpio_28_i; - assign gpio_28_o = gpio_out[28]; - assign gpio_28_oe_o = gpio_oe[28]; - assign gpio_in[29] = gpio_29_i; - assign gpio_29_o = gpio_out[29]; - assign gpio_29_oe_o = gpio_oe[29]; - assign gpio_in[30] = gpio_30_i; - assign gpio_30_o = gpio_out[30]; - assign gpio_30_oe_o = gpio_oe[30]; - assign gpio_in[31] = gpio_31_i; - assign gpio_31_o = gpio_out[31]; - assign gpio_31_oe_o = gpio_oe[31]; + // Debug_req assign + if (NRHARTS == 1) begin + assign debug_core_req = debug_req; + assign ext_debug_req_o = 1'b0; + end else begin + always @(*) begin + for (int i = 0; i < NRHARTS; i++) begin + if (i == 0) debug_core_req = debug_req[i]; + else ext_debug_req_o[i-1] = debug_req[i]; + end + end + end + + assign ext_cpu_subsystem_rst_no = cpu_subsystem_rst_n; + assign ext_debug_reset_no = debug_reset_n; + + assign pdm2pcm_pdm_o = 0; + assign pdm2pcm_pdm_oe_o = 0; + + assign gpio_ao_in[0] = gpio_0_i; + assign gpio_0_o = gpio_ao_out[0]; + assign gpio_0_oe_o = gpio_ao_oe[0]; + assign gpio_ao_in[1] = gpio_1_i; + assign gpio_1_o = gpio_ao_out[1]; + assign gpio_1_oe_o = gpio_ao_oe[1]; + assign gpio_ao_in[2] = gpio_2_i; + assign gpio_2_o = gpio_ao_out[2]; + assign gpio_2_oe_o = gpio_ao_oe[2]; + assign gpio_ao_in[3] = gpio_3_i; + assign gpio_3_o = gpio_ao_out[3]; + assign gpio_3_oe_o = gpio_ao_oe[3]; + assign gpio_ao_in[4] = gpio_4_i; + assign gpio_4_o = gpio_ao_out[4]; + assign gpio_4_oe_o = gpio_ao_oe[4]; + assign gpio_ao_in[5] = gpio_5_i; + assign gpio_5_o = gpio_ao_out[5]; + assign gpio_5_oe_o = gpio_ao_oe[5]; + assign gpio_ao_in[6] = gpio_6_i; + assign gpio_6_o = gpio_ao_out[6]; + assign gpio_6_oe_o = gpio_ao_oe[6]; + assign gpio_ao_in[7] = gpio_7_i; + assign gpio_7_o = gpio_ao_out[7]; + assign gpio_7_oe_o = gpio_ao_oe[7]; + assign gpio_in[8] = gpio_8_i; + assign gpio_8_o = gpio_out[8]; + assign gpio_8_oe_o = gpio_oe[8]; + assign gpio_in[9] = gpio_9_i; + assign gpio_9_o = gpio_out[9]; + assign gpio_9_oe_o = gpio_oe[9]; + assign gpio_in[10] = gpio_10_i; + assign gpio_10_o = gpio_out[10]; + assign gpio_10_oe_o = gpio_oe[10]; + assign gpio_in[11] = gpio_11_i; + assign gpio_11_o = gpio_out[11]; + assign gpio_11_oe_o = gpio_oe[11]; + assign gpio_in[12] = gpio_12_i; + assign gpio_12_o = gpio_out[12]; + assign gpio_12_oe_o = gpio_oe[12]; + assign gpio_in[13] = gpio_13_i; + assign gpio_13_o = gpio_out[13]; + assign gpio_13_oe_o = gpio_oe[13]; + assign gpio_in[14] = gpio_14_i; + assign gpio_14_o = gpio_out[14]; + assign gpio_14_oe_o = gpio_oe[14]; + assign gpio_in[15] = gpio_15_i; + assign gpio_15_o = gpio_out[15]; + assign gpio_15_oe_o = gpio_oe[15]; + assign gpio_in[16] = gpio_16_i; + assign gpio_16_o = gpio_out[16]; + assign gpio_16_oe_o = gpio_oe[16]; + assign gpio_in[17] = gpio_17_i; + assign gpio_17_o = gpio_out[17]; + assign gpio_17_oe_o = gpio_oe[17]; + assign gpio_in[18] = gpio_18_i; + assign gpio_18_o = gpio_out[18]; + assign gpio_18_oe_o = gpio_oe[18]; + assign gpio_in[19] = gpio_19_i; + assign gpio_19_o = gpio_out[19]; + assign gpio_19_oe_o = gpio_oe[19]; + assign gpio_in[20] = gpio_20_i; + assign gpio_20_o = gpio_out[20]; + assign gpio_20_oe_o = gpio_oe[20]; + assign gpio_in[21] = gpio_21_i; + assign gpio_21_o = gpio_out[21]; + assign gpio_21_oe_o = gpio_oe[21]; + assign gpio_in[22] = gpio_22_i; + assign gpio_22_o = gpio_out[22]; + assign gpio_22_oe_o = gpio_oe[22]; + assign gpio_in[23] = gpio_23_i; + assign gpio_23_o = gpio_out[23]; + assign gpio_23_oe_o = gpio_oe[23]; + assign gpio_in[24] = gpio_24_i; + assign gpio_24_o = gpio_out[24]; + assign gpio_24_oe_o = gpio_oe[24]; + assign gpio_in[25] = gpio_25_i; + assign gpio_25_o = gpio_out[25]; + assign gpio_25_oe_o = gpio_oe[25]; + assign gpio_in[26] = gpio_26_i; + assign gpio_26_o = gpio_out[26]; + assign gpio_26_oe_o = gpio_oe[26]; + assign gpio_in[27] = gpio_27_i; + assign gpio_27_o = gpio_out[27]; + assign gpio_27_oe_o = gpio_oe[27]; + assign gpio_in[28] = gpio_28_i; + assign gpio_28_o = gpio_out[28]; + assign gpio_28_oe_o = gpio_oe[28]; + assign gpio_in[29] = gpio_29_i; + assign gpio_29_o = gpio_out[29]; + assign gpio_29_oe_o = gpio_oe[29]; + assign gpio_in[30] = gpio_30_i; + assign gpio_30_o = gpio_out[30]; + assign gpio_30_oe_o = gpio_oe[30]; + assign gpio_in[31] = gpio_31_i; + assign gpio_31_o = gpio_out[31]; + assign gpio_31_oe_o = gpio_oe[31]; endmodule // core_v_mini_mcu diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl index b4935df4..aedf2e2c 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl @@ -11,10 +11,14 @@ module core_v_mini_mcu parameter ZFINX = 0, parameter EXT_XBAR_NMASTER = 0, parameter X_EXT = 0, // eXtension interface in cv32e40x + parameter AO_SPC_NUM = 0, + parameter EXT_HARTS = 0, //do not touch these parameters + parameter AO_SPC_NUM_RND = AO_SPC_NUM == 0 ? 1 : AO_SPC_NUM, parameter EXT_XBAR_NMASTER_RND = EXT_XBAR_NMASTER == 0 ? 1 : EXT_XBAR_NMASTER, parameter EXT_DOMAINS_RND = core_v_mini_mcu_pkg::EXTERNAL_DOMAINS == 0 ? 1 : core_v_mini_mcu_pkg::EXTERNAL_DOMAINS, - parameter NEXT_INT_RND = core_v_mini_mcu_pkg::NEXT_INT == 0 ? 1 : core_v_mini_mcu_pkg::NEXT_INT + parameter NEXT_INT_RND = core_v_mini_mcu_pkg::NEXT_INT == 0 ? 1 : core_v_mini_mcu_pkg::NEXT_INT, + parameter EXT_HARTS_RND = EXT_HARTS == 0 ? 1 : EXT_HARTS ) ( input logic rst_ni, @@ -37,6 +41,9 @@ ${pad.core_v_mini_mcu_interface} input obi_req_t [EXT_XBAR_NMASTER_RND-1:0] ext_xbar_master_req_i, output obi_resp_t [EXT_XBAR_NMASTER_RND-1:0] ext_xbar_master_resp_o, + input reg_req_t [AO_SPC_NUM_RND-1:0] ext_ao_peripheral_slave_req_i, + output reg_rsp_t [AO_SPC_NUM_RND-1:0] ext_ao_peripheral_slave_resp_o, + // External slave ports output obi_req_t ext_core_instr_req_o, input obi_resp_t ext_core_instr_resp_i, @@ -44,41 +51,54 @@ ${pad.core_v_mini_mcu_interface} input obi_resp_t ext_core_data_resp_i, output obi_req_t ext_debug_master_req_o, input obi_resp_t ext_debug_master_resp_i, - output obi_req_t ext_dma_read_ch0_req_o, - input obi_resp_t ext_dma_read_ch0_resp_i, - output obi_req_t ext_dma_write_ch0_req_o, - input obi_resp_t ext_dma_write_ch0_resp_i, - output obi_req_t ext_dma_addr_ch0_req_o, - input obi_resp_t ext_dma_addr_ch0_resp_i, + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_read_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_read_resp_i, + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_write_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_write_resp_i, + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_addr_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_addr_resp_i, + + input logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] ext_dma_stop_i, output reg_req_t ext_peripheral_slave_req_o, input reg_rsp_t ext_peripheral_slave_resp_i, + output logic [EXT_HARTS_RND-1:0] ext_debug_req_o, + output logic ext_debug_reset_no, + input logic [NEXT_INT_RND-1:0] intr_vector_ext_i, + //power manager exposed to top level + //signals are unrolled to easy EDA tools output logic cpu_subsystem_powergate_switch_no, input logic cpu_subsystem_powergate_switch_ack_ni, output logic peripheral_subsystem_powergate_switch_no, input logic peripheral_subsystem_powergate_switch_ack_ni, - output logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_no, - input logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_ack_ni, output logic [EXT_DOMAINS_RND-1:0] external_subsystem_powergate_switch_no, input logic [EXT_DOMAINS_RND-1:0] external_subsystem_powergate_switch_ack_ni, output logic [EXT_DOMAINS_RND-1:0] external_subsystem_powergate_iso_no, output logic [EXT_DOMAINS_RND-1:0] external_subsystem_rst_no, + output logic ext_cpu_subsystem_rst_no, output logic [EXT_DOMAINS_RND-1:0] external_ram_banks_set_retentive_no, output logic [EXT_DOMAINS_RND-1:0] external_subsystem_clkgate_en_no, - output logic [31:0] exit_value_o + output logic [31:0] exit_value_o, + + // External SPC interface + input logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] ext_dma_slot_tx_i, + input logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] ext_dma_slot_rx_i, + output logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] dma_done_o ); import core_v_mini_mcu_pkg::*; import cv32e40p_apu_core_pkg::*; + import power_manager_pkg::*; localparam NUM_BYTES = core_v_mini_mcu_pkg::MEM_SIZE; localparam DM_HALTADDRESS = core_v_mini_mcu_pkg::DEBUG_START_ADDRESS + 32'h00000800; //debug rom code (section .text in linker) starts at 0x800 localparam JTAG_IDCODE = 32'h10001c05; + localparam NRHARTS = EXT_HARTS + 1; //external harts + single hart core-v-mini-mcu localparam BOOT_ADDR = core_v_mini_mcu_pkg::BOOTROM_START_ADDRESS; localparam NUM_MHPMCOUNTERS = 1; @@ -96,12 +116,12 @@ ${pad.core_v_mini_mcu_interface} obi_resp_t core_data_resp; obi_req_t debug_master_req; obi_resp_t debug_master_resp; - obi_req_t dma_read_ch0_req; - obi_resp_t dma_read_ch0_resp; - obi_req_t dma_write_ch0_req; - obi_resp_t dma_write_ch0_resp; - obi_req_t dma_addr_ch0_req; - obi_resp_t dma_addr_ch0_resp; + obi_req_t [${int(num_dma_master_ports)-1}:0]dma_read_req; + obi_resp_t [${int(num_dma_master_ports)-1}:0]dma_read_resp; + obi_req_t [${int(num_dma_master_ports)-1}:0]dma_write_req; + obi_resp_t [${int(num_dma_master_ports)-1}:0]dma_write_resp; + obi_req_t [${int(num_dma_master_ports)-1}:0]dma_addr_req; + obi_resp_t [${int(num_dma_master_ports)-1}:0]dma_addr_resp; // ram signals obi_req_t [core_v_mini_mcu_pkg::NUM_BANKS-1:0] ram_slave_req; @@ -119,7 +139,8 @@ ${pad.core_v_mini_mcu_interface} // signals to debug unit logic debug_core_req; - + logic debug_reset_n; + logic [NRHARTS-1:0] debug_req; // core logic core_sleep; @@ -141,24 +162,69 @@ ${pad.core_v_mini_mcu_interface} logic [31:0] intr; logic [14:0] fast_intr; - // Power manager - logic cpu_subsystem_powergate_iso_n; + //Power manager signals + power_manager_out_t cpu_subsystem_pwr_ctrl_out; + power_manager_out_t peripheral_subsystem_pwr_ctrl_out; + power_manager_out_t memory_subsystem_pwr_ctrl_out[core_v_mini_mcu_pkg::NUM_BANKS-1:0]; + power_manager_out_t external_subsystem_pwr_ctrl_out[EXT_DOMAINS_RND-1:0]; + + power_manager_in_t cpu_subsystem_pwr_ctrl_in; + power_manager_in_t peripheral_subsystem_pwr_ctrl_in; + power_manager_in_t memory_subsystem_pwr_ctrl_in[core_v_mini_mcu_pkg::NUM_BANKS-1:0]; + power_manager_in_t external_subsystem_pwr_ctrl_in[EXT_DOMAINS_RND-1:0]; + logic cpu_subsystem_rst_n; - logic peripheral_subsystem_powergate_iso_n; + logic cpu_subsystem_powergate_iso_n; + logic peripheral_subsystem_rst_n; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_iso_n; + logic peripheral_subsystem_powergate_iso_n; + logic peripheral_subsystem_clkgate_en_n; + + logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_n; + logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_ack_n; logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_set_retentive_n; + logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_iso_n; + logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_clkgate_en_n; + + //pwrgate exposed outside for UPF sim flow and switch cells + assign cpu_subsystem_powergate_switch_no = cpu_subsystem_pwr_ctrl_out.pwrgate_en_n; + assign cpu_subsystem_pwr_ctrl_in.pwrgate_ack_n = cpu_subsystem_powergate_switch_ack_ni; + //isogate exposed outside for UPF sim flow and switch cells + assign cpu_subsystem_powergate_iso_n = cpu_subsystem_pwr_ctrl_out.isogate_en_n; + assign cpu_subsystem_rst_n = cpu_subsystem_pwr_ctrl_out.rst_n; + + //pwrgate exposed both outside for UPF sim flow + assign peripheral_subsystem_powergate_switch_no = peripheral_subsystem_pwr_ctrl_out.pwrgate_en_n; + assign peripheral_subsystem_pwr_ctrl_in.pwrgate_ack_n = peripheral_subsystem_powergate_switch_ack_ni; + //isogate exposed outside for UPF sim flow and switch cells + assign peripheral_subsystem_powergate_iso_n = peripheral_subsystem_pwr_ctrl_out.isogate_en_n; + assign peripheral_subsystem_rst_n = peripheral_subsystem_pwr_ctrl_out.rst_n; + assign peripheral_subsystem_clkgate_en_n = peripheral_subsystem_pwr_ctrl_out.clkgate_en_n; + +% for bank in xheep.iter_ram_banks(): + assign memory_subsystem_banks_powergate_switch_n[${bank.name()}] = memory_subsystem_pwr_ctrl_out[${bank.name()}].pwrgate_en_n; + assign memory_subsystem_pwr_ctrl_in[${bank.name()}].pwrgate_ack_n = memory_subsystem_banks_powergate_switch_ack_n[${bank.name()}]; + //isogate exposed outside for UPF sim flow and switch cells + assign memory_subsystem_banks_powergate_iso_n[${bank.name()}] = memory_subsystem_pwr_ctrl_out[${bank.name()}].isogate_en_n; + assign memory_subsystem_banks_set_retentive_n[${bank.name()}] = memory_subsystem_pwr_ctrl_out[${bank.name()}].retentive_en_n; + assign memory_subsystem_clkgate_en_n[${bank.name()}] = memory_subsystem_pwr_ctrl_out[${bank.name()}].clkgate_en_n; +% endfor - // Clock gating signals - logic peripheral_subsystem_clkgate_en_n; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0]memory_subsystem_clkgate_en_n; + for (genvar i = 0; i < EXT_DOMAINS_RND; i = i + 1) begin + assign external_subsystem_powergate_switch_no[i] = external_subsystem_pwr_ctrl_out[i].pwrgate_en_n; + assign external_subsystem_powergate_iso_no[i] = external_subsystem_pwr_ctrl_out[i].isogate_en_n; + assign external_subsystem_rst_no[i] = external_subsystem_pwr_ctrl_out[i].rst_n; + assign external_ram_banks_set_retentive_no[i] = external_subsystem_pwr_ctrl_out[i].retentive_en_n; + assign external_subsystem_clkgate_en_no[i] = external_subsystem_pwr_ctrl_out[i].clkgate_en_n; + assign external_subsystem_pwr_ctrl_in[i].pwrgate_ack_n = external_subsystem_powergate_switch_ack_ni[i]; + end // DMA logic dma_done_intr; logic dma_window_intr; // SPI - logic spi_flash_intr, spi_intr; + logic spi_flash_intr, spi_intr, spi_rx_valid, spi_tx_ready; // GPIO logic [31:8] gpio_in; @@ -210,7 +276,7 @@ ${pad.core_v_mini_mcu_interface} ) cpu_subsystem_i ( // Clock and Reset .clk_i, - .rst_ni(cpu_subsystem_rst_n), + .rst_ni(cpu_subsystem_rst_n && debug_reset_n), .core_instr_req_o(core_instr_req), .core_instr_resp_i(core_instr_resp), .core_data_req_o(core_data_req), @@ -229,6 +295,7 @@ ${pad.core_v_mini_mcu_interface} ); debug_subsystem #( + .NRHARTS (NRHARTS), .JTAG_IDCODE(JTAG_IDCODE) ) debug_subsystem_i ( .clk_i, @@ -238,7 +305,8 @@ ${pad.core_v_mini_mcu_interface} .jtag_trst_ni, .jtag_tdi_i, .jtag_tdo_o, - .debug_core_req_o(debug_core_req), + .debug_core_req_o(debug_req), + .debug_ndmreset_no(debug_reset_n), .debug_slave_req_i(debug_slave_req), .debug_slave_resp_o(debug_slave_resp), .debug_master_req_o(debug_master_req), @@ -250,19 +318,19 @@ ${pad.core_v_mini_mcu_interface} .EXT_XBAR_NMASTER(EXT_XBAR_NMASTER) ) system_bus_i ( .clk_i, - .rst_ni, + .rst_ni(rst_ni && debug_reset_n), .core_instr_req_i(core_instr_req), .core_instr_resp_o(core_instr_resp), .core_data_req_i(core_data_req), .core_data_resp_o(core_data_resp), .debug_master_req_i(debug_master_req), .debug_master_resp_o(debug_master_resp), - .dma_read_ch0_req_i(dma_read_ch0_req), - .dma_read_ch0_resp_o(dma_read_ch0_resp), - .dma_write_ch0_req_i(dma_write_ch0_req), - .dma_write_ch0_resp_o(dma_write_ch0_resp), - .dma_addr_ch0_req_i(dma_addr_ch0_req), - .dma_addr_ch0_resp_o(dma_addr_ch0_resp), + .dma_read_req_i(dma_read_req), + .dma_read_resp_o(dma_read_resp), + .dma_write_req_i(dma_write_req), + .dma_write_resp_o(dma_write_resp), + .dma_addr_req_i(dma_addr_req), + .dma_addr_resp_o(dma_addr_resp), .ext_xbar_master_req_i(ext_xbar_master_req_i), .ext_xbar_master_resp_o(ext_xbar_master_resp_o), .ram_req_o(ram_slave_req), @@ -281,30 +349,36 @@ ${pad.core_v_mini_mcu_interface} .ext_core_data_resp_i(ext_core_data_resp_i), .ext_debug_master_req_o(ext_debug_master_req_o), .ext_debug_master_resp_i(ext_debug_master_resp_i), - .ext_dma_read_ch0_req_o(ext_dma_read_ch0_req_o), - .ext_dma_read_ch0_resp_i(ext_dma_read_ch0_resp_i), - .ext_dma_write_ch0_req_o(ext_dma_write_ch0_req_o), - .ext_dma_write_ch0_resp_i(ext_dma_write_ch0_resp_i), - .ext_dma_addr_ch0_req_o(ext_dma_addr_ch0_req_o), - .ext_dma_addr_ch0_resp_i(ext_dma_addr_ch0_resp_i) + .ext_dma_read_req_o(ext_dma_read_req_o), + .ext_dma_read_resp_i(ext_dma_read_resp_i), + .ext_dma_write_req_o(ext_dma_write_req_o), + .ext_dma_write_resp_i(ext_dma_write_resp_i), + .ext_dma_addr_req_o(ext_dma_addr_req_o), + .ext_dma_addr_resp_i(ext_dma_addr_resp_i) ); memory_subsystem #( .NUM_BANKS(core_v_mini_mcu_pkg::NUM_BANKS) ) memory_subsystem_i ( .clk_i, - .rst_ni, + .rst_ni(rst_ni && debug_reset_n), .clk_gate_en_ni(memory_subsystem_clkgate_en_n), .ram_req_i(ram_slave_req), .ram_resp_o(ram_slave_resp), + .pwrgate_ni(memory_subsystem_banks_powergate_switch_n), + .pwrgate_ack_no(memory_subsystem_banks_powergate_switch_ack_n), .set_retentive_ni(memory_subsystem_banks_set_retentive_n) ); - ao_peripheral_subsystem ao_peripheral_subsystem_i ( + ao_peripheral_subsystem #( + .AO_SPC_NUM(AO_SPC_NUM) + ) ao_peripheral_subsystem_i ( .clk_i, - .rst_ni, + .rst_ni(rst_ni && debug_reset_n), .slave_req_i(ao_peripheral_slave_req), .slave_resp_o(ao_peripheral_slave_resp), + .spc2ao_req_i(ext_ao_peripheral_slave_req_i), + .ao2spc_resp_o(ext_ao_peripheral_slave_resp_o), .boot_select_i, .execute_from_flash_i, .exit_valid_o, @@ -318,47 +392,27 @@ ${pad.core_v_mini_mcu_interface} .spi_flash_sd_o({spi_flash_sd_3_o,spi_flash_sd_2_o, spi_flash_sd_1_o, spi_flash_sd_0_o}), .spi_flash_sd_en_o({spi_flash_sd_3_oe_o,spi_flash_sd_2_oe_o, spi_flash_sd_1_oe_o, spi_flash_sd_0_oe_o}), .spi_flash_sd_i({spi_flash_sd_3_i,spi_flash_sd_2_i, spi_flash_sd_1_i, spi_flash_sd_0_i}), - .spi_sck_o, - .spi_sck_en_o(spi_sck_oe_o), - .spi_csb_o({spi_cs_1_o,spi_cs_0_o}), - .spi_csb_en_o({spi_cs_1_oe_o, spi_cs_0_oe_o}), - .spi_sd_o({spi_sd_3_o,spi_sd_2_o, spi_sd_1_o, spi_sd_0_o}), - .spi_sd_en_o({spi_sd_3_oe_o,spi_sd_2_oe_o, spi_sd_1_oe_o, spi_sd_0_oe_o}), - .spi_sd_i({spi_sd_3_i,spi_sd_2_i, spi_sd_1_i, spi_sd_0_i}), .intr_i(intr), .intr_vector_ext_i, .core_sleep_i(core_sleep), - .cpu_subsystem_powergate_switch_no, - .cpu_subsystem_powergate_switch_ack_ni, - .cpu_subsystem_powergate_iso_no(cpu_subsystem_powergate_iso_n), - .cpu_subsystem_rst_no(cpu_subsystem_rst_n), - .peripheral_subsystem_powergate_switch_no, - .peripheral_subsystem_powergate_switch_ack_ni, - .peripheral_subsystem_powergate_iso_no(peripheral_subsystem_powergate_iso_n), - .peripheral_subsystem_rst_no(peripheral_subsystem_rst_n), - .memory_subsystem_banks_powergate_switch_no, - .memory_subsystem_banks_powergate_switch_ack_ni, - .memory_subsystem_banks_powergate_iso_no(memory_subsystem_banks_powergate_iso_n), - .memory_subsystem_banks_set_retentive_no(memory_subsystem_banks_set_retentive_n), - .external_subsystem_powergate_switch_no, - .external_subsystem_powergate_switch_ack_ni, - .external_subsystem_powergate_iso_no, - .external_subsystem_rst_no, - .external_ram_banks_set_retentive_no, - .peripheral_subsystem_clkgate_en_no(peripheral_subsystem_clkgate_en_n), - .memory_subsystem_clkgate_en_no(memory_subsystem_clkgate_en_n), - .external_subsystem_clkgate_en_no, + .cpu_subsystem_pwr_ctrl_o(cpu_subsystem_pwr_ctrl_out), + .peripheral_subsystem_pwr_ctrl_o(peripheral_subsystem_pwr_ctrl_out), + .memory_subsystem_pwr_ctrl_o(memory_subsystem_pwr_ctrl_out), + .external_subsystem_pwr_ctrl_o(external_subsystem_pwr_ctrl_out), + .cpu_subsystem_pwr_ctrl_i(cpu_subsystem_pwr_ctrl_in), + .peripheral_subsystem_pwr_ctrl_i(peripheral_subsystem_pwr_ctrl_in), + .memory_subsystem_pwr_ctrl_i(memory_subsystem_pwr_ctrl_in), + .external_subsystem_pwr_ctrl_i(external_subsystem_pwr_ctrl_in), .rv_timer_0_intr_o(rv_timer_intr[0]), .rv_timer_1_intr_o(rv_timer_intr[1]), - .dma_read_ch0_req_o(dma_read_ch0_req), - .dma_read_ch0_resp_i(dma_read_ch0_resp), - .dma_write_ch0_req_o(dma_write_ch0_req), - .dma_write_ch0_resp_i(dma_write_ch0_resp), - .dma_addr_ch0_req_o(dma_addr_ch0_req), - .dma_addr_ch0_resp_i(dma_addr_ch0_resp), + .dma_read_req_o(dma_read_req), + .dma_read_resp_i(dma_read_resp), + .dma_write_req_o(dma_write_req), + .dma_write_resp_i(dma_write_resp), + .dma_addr_req_o(dma_addr_req), + .dma_addr_resp_i(dma_addr_resp), .dma_done_intr_o(dma_done_intr), .dma_window_intr_o(dma_window_intr), - .spi_intr_event_o(spi_intr), .spi_flash_intr_event_o(spi_flash_intr), .pad_req_o, .pad_resp_i, @@ -378,14 +432,20 @@ ${pad.core_v_mini_mcu_interface} .uart_intr_rx_break_err_o(uart_intr_rx_break_err), .uart_intr_rx_timeout_o(uart_intr_rx_timeout), .uart_intr_rx_parity_err_o(uart_intr_rx_parity_err), + .spi_rx_valid_i(spi_rx_valid), + .spi_tx_ready_i(spi_tx_ready), .i2s_rx_valid_i(i2s_rx_valid), .ext_peripheral_slave_req_o, - .ext_peripheral_slave_resp_i + .ext_peripheral_slave_resp_i, + .ext_dma_slot_tx_i, + .ext_dma_slot_rx_i, + .ext_dma_stop_i, + .dma_done_o ); peripheral_subsystem peripheral_subsystem_i ( .clk_i, - .rst_ni(peripheral_subsystem_rst_n), + .rst_ni(peripheral_subsystem_rst_n && debug_reset_n), .clk_gate_en_ni(peripheral_subsystem_clkgate_en_n), .slave_req_i(peripheral_slave_req), .slave_resp_o(peripheral_slave_resp), @@ -410,6 +470,16 @@ ${pad.core_v_mini_mcu_interface} .cio_sda_i(i2c_sda_i), .cio_sda_o(i2c_sda_o), .cio_sda_en_o(i2c_sda_oe_o), + .spi_sck_o, + .spi_sck_en_o(spi_sck_oe_o), + .spi_csb_o({spi_cs_1_o,spi_cs_0_o}), + .spi_csb_en_o({spi_cs_1_oe_o, spi_cs_0_oe_o}), + .spi_sd_o({spi_sd_3_o,spi_sd_2_o, spi_sd_1_o, spi_sd_0_o}), + .spi_sd_en_o({spi_sd_3_oe_o,spi_sd_2_oe_o, spi_sd_1_oe_o, spi_sd_0_oe_o}), + .spi_sd_i({spi_sd_3_i,spi_sd_2_i, spi_sd_1_i, spi_sd_0_i}), + .spi_intr_event_o(spi_intr), + .spi_rx_valid_o(spi_rx_valid), + .spi_tx_ready_o(spi_tx_ready), .spi2_sck_o, .spi2_sck_en_o(spi2_sck_oe_o), .spi2_csb_o({spi2_cs_1_o, spi2_cs_0_o}), @@ -434,6 +504,22 @@ ${pad.core_v_mini_mcu_interface} .i2s_rx_valid_o(i2s_rx_valid) ); + // Debug_req assign + if (NRHARTS == 1) begin + assign debug_core_req = debug_req; + assign ext_debug_req_o = 1'b0; + end else begin + always @(*) begin + for (int i = 0; i < NRHARTS; i++) begin + if (i == 0) debug_core_req = debug_req[i]; + else ext_debug_req_o[i-1] = debug_req[i]; + end + end + end + + assign ext_cpu_subsystem_rst_no = cpu_subsystem_rst_n; + assign ext_debug_reset_no = debug_reset_n; + assign pdm2pcm_pdm_o = 0; assign pdm2pcm_pdm_oe_o = 0; diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.vlt b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.vlt index e1493802..11f96091 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.vlt +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/core_v_mini_mcu.vlt @@ -8,6 +8,7 @@ lint_off -rule UNUSED -file "*/core_v_mini_mcu.sv" -match "*" lint_off -rule UNUSED -file "*/cpu_subsystem.sv" -match "Signal is not used: 'apu*'*" lint_off -rule UNDRIVEN -file "*/memory_subsystem.sv" -match "Bits of signal are not driven: 'ram*_resp_o'[32]*" lint_off -rule UNOPTFLAT -file "*/system_xbar.sv" -match "Signal unoptimizable*" +lint_off -rule UNOPTFLAT -file "*/ao_peripheral_subsystem.sv" -match "*" lint_off -rule UNOPTFLAT -file "*/xbar_varlat_one_to_n.sv" -match "Signal unoptimizable: Feedback to clock or circular logic: *" lint_off -rule UNOPTFLAT -file "*/xbar_varlat_n_to_one.sv" -match "Signal unoptimizable: Feedback to clock or circular logic: *" lint_off -rule UNUSED -file "*/reg_to_tlul.sv" -match "Bits of signal are not used: 'tl_i'*" @@ -28,3 +29,4 @@ lint_off -rule LITENDIAN -file "*/x_heep_system.sv" -match "*" lint_off -rule WIDTH -file "*/ao_peripheral_subsystem.sv" -match "Input port connection 'reg_req_i' expects 70 bits on the pin connection, but pin connection's SEL generates 34 bits.*" lint_off -rule UNDRIVEN -file "*ip/power_manager/rtl/power_manager.sv" -match "Signal is not driven: 'external_ram_banks_set_retentive*'" lint_off -rule UNDRIVEN -file "*ip/power_manager/rtl/power_manager.sv" -match "Signal is not driven: 'external_subsystem_clkgate_en*'" +lint_off -rule UNUSED -file "*vendor/pulp_platform_register_interface/src/reg_mux.sv" -match "*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/cpu_subsystem.sv b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/cpu_subsystem.sv index bbb62d75..256723f6 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/cpu_subsystem.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/cpu_subsystem.sv @@ -59,21 +59,16 @@ module cpu_subsystem if (CPU_TYPE == cv32e20) begin : gen_cv32e20 - logic [4:0] rf_raddr_a, rf_raddr_b, rf_waddr_wb; - logic [31:0] rf_rdata_a, rf_rdata_b, rf_wdata_wb; - logic rf_we_wb; - - import ibex_pkg::*; - - ibex_core #( + cve2_top #( .DmHaltAddr(DM_HALTADDRESS), - .DmExceptionAddr(32'h0), - .DbgTriggerEn(1'b1), - .ResetAll(1'b1) + .DmExceptionAddr('0) ) cv32e20_i ( .clk_i (clk_i), .rst_ni(rst_ni), + .test_en_i(1'b0), + .ram_cfg_i('0), + .hart_id_i (32'h0), .boot_addr_i(BOOT_ADDR), @@ -94,79 +89,20 @@ module cpu_subsystem .data_rvalid_i(core_data_resp_i.rvalid), .data_err_i (1'b0), - .dummy_instr_id_o (), - .rf_raddr_a_o (rf_raddr_a), - .rf_raddr_b_o (rf_raddr_b), - .rf_waddr_wb_o (rf_waddr_wb), - .rf_we_wb_o (rf_we_wb), - .rf_wdata_wb_ecc_o(rf_wdata_wb), - .rf_rdata_a_ecc_i (rf_rdata_a), - .rf_rdata_b_ecc_i (rf_rdata_b), - - .ic_tag_req_o (), - .ic_tag_write_o (), - .ic_tag_addr_o (), - .ic_tag_wdata_o (), - .ic_tag_rdata_i (), - .ic_data_req_o (), - .ic_data_write_o (), - .ic_data_addr_o (), - .ic_data_wdata_o (), - .ic_data_rdata_i (), - .ic_scr_key_valid_i(), - .irq_software_i(irq_i[3]), .irq_timer_i (irq_i[7]), .irq_external_i(irq_i[11]), - .irq_fast_i (irq_i[30:16]), - .irq_nm_i (irq_i[31]), - .irq_pending_o (), + .irq_fast_i (irq_i[31:16]), + .irq_nm_i (1'b0), - .debug_req_i(debug_req_i), + .debug_req_i (debug_req_i), .crash_dump_o(), - .double_fault_seen_o(), .fetch_enable_i(fetch_enable), - .alert_minor_o (), - .alert_major_o (), - .icache_inval_o(), - .core_sleep_o - ); - - cv32e40p_register_file #( - .ADDR_WIDTH(6) - ) cv32e20_register_file_i ( - // Clock and Reset - .clk (clk_i), - .rst_n(rst_ni), - - .scan_cg_en_i(1'b0), - - //Read port R1 - .raddr_a_i({1'b0, rf_raddr_a}), - .rdata_a_o(rf_rdata_a), - - //Read port R2 - .raddr_b_i({1'b0, rf_raddr_b}), - .rdata_b_o(rf_rdata_b), - - //Read port R3 - .raddr_c_i('0), - .rdata_c_o(), - // Write port W1 - .waddr_a_i({1'b0, rf_waddr_wb}), - .wdata_a_i(rf_wdata_wb), - .we_a_i(rf_we_wb), - - // Write port W2 - .waddr_b_i('0), - .wdata_b_i('0), - .we_b_i('0) + .core_sleep_o ); - - assign irq_ack_o = '0; assign irq_id_o = '0; diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/debug_subsystem.sv b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/debug_subsystem.sv index 392c12ad..0718c8f1 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/debug_subsystem.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/debug_subsystem.sv @@ -5,6 +5,7 @@ module debug_subsystem import obi_pkg::*; #( + parameter NRHARTS = 1, parameter JTAG_IDCODE = 32'h10001c05 ) ( input logic clk_i, @@ -16,7 +17,8 @@ module debug_subsystem input logic jtag_tdi_i, output logic jtag_tdo_o, - output logic debug_core_req_o, + output logic debug_ndmreset_no, + output logic [NRHARTS-1:0] debug_core_req_o, input obi_req_t debug_slave_req_i, output obi_resp_t debug_slave_resp_o, @@ -27,14 +29,20 @@ module debug_subsystem import dm::*; - localparam dm::hartinfo_t hartinfo = '{ - zero1: '0, - nscratch: 2, // Debug module needs at least two scratch regs - zero0: '0, - dataaccess: 1'b1, // data registers are memory mapped in the debugger - datasize: dm::DataCount, - dataaddr: dm::DataAddr - }; + logic [NRHARTS-1:0] unavailable; + dm::hartinfo_t [NRHARTS-1:0] hartinfo; + + always @(*) begin + for (int i = 0; i < NRHARTS; i++) begin + hartinfo[i].zero1 = '0; + hartinfo[i].nscratch = 2; // Debug module needs at least two scratch regs + hartinfo[i].zero0 = '0; + hartinfo[i].dataaccess = 1'b1; // data registers are memory mapped in the debugger + hartinfo[i].datasize = dm::DataCount; + hartinfo[i].dataaddr = dm::DataAddr; + unavailable[i] = ~(1'b1); + end + end dm::dmi_req_t dmi_req; logic dmi_req_valid; @@ -42,7 +50,9 @@ module debug_subsystem dm::dmi_resp_t dmi_resp; logic dmi_resp_ready; logic dmi_resp_valid; + logic ndmreset; + assign debug_ndmreset_no = ~ndmreset; dmi_jtag #( .IdcodeValue(JTAG_IDCODE) @@ -65,14 +75,16 @@ module debug_subsystem .tdo_oe_o () ); - dm_obi_top dm_obi_top_i ( + dm_obi_top #( + .NrHarts(NRHARTS) + ) dm_obi_top_i ( .clk_i (clk_i), .rst_ni (rst_ni), .testmode_i (1'b0), - .ndmreset_o (), + .ndmreset_o (ndmreset), .dmactive_o (), .debug_req_o (debug_core_req_o), - .unavailable_i(~(1'b01)), + .unavailable_i(unavailable), .hartinfo_i (hartinfo), .slave_req_i (debug_slave_req_i.req), diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/addr_map_rule_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/addr_map_rule_pkg.sv index 4e0a9a27..712164af 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/addr_map_rule_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/addr_map_rule_pkg.sv @@ -10,4 +10,10 @@ package addr_map_rule_pkg; logic [31:0] end_addr; } addr_map_rule_t; + typedef struct packed { + logic [7:0] idx; + logic [7:0] start_addr; + logic [7:0] end_addr; + } addr_map_rule_8bit_t; + endpackage diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl index 660022e1..00ffc025 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl @@ -16,6 +16,7 @@ package core_v_mini_mcu_pkg; import addr_map_rule_pkg::*; + import power_manager_pkg::*; typedef enum logic [1:0] { cv32e40p, @@ -31,30 +32,30 @@ package core_v_mini_mcu_pkg; onetoM } bus_type_e; - localparam bus_type_e BusType = ${bus_type}; + localparam bus_type_e BusType = ${xheep.bus_type().value}; //master idx localparam logic [31:0] CORE_INSTR_IDX = 0; localparam logic [31:0] CORE_DATA_IDX = 1; localparam logic [31:0] DEBUG_MASTER_IDX = 2; - localparam logic [31:0] DMA_READ_CH0_IDX = 3; - localparam logic [31:0] DMA_WRITE_CH0_IDX = 4; - localparam logic [31:0] DMA_ADDR_CH0_IDX = 5; + localparam logic [31:0] DMA_READ_P0_IDX = 3; + localparam logic [31:0] DMA_WRITE_P0_IDX = 4; + localparam logic [31:0] DMA_ADDR_P0_IDX = 5; - localparam SYSTEM_XBAR_NMASTER = 6; + localparam SYSTEM_XBAR_NMASTER = ${3 + int(num_dma_master_ports)*3}; // Internal slave memory map and index // ----------------------------------- //must be power of two - localparam int unsigned MEM_SIZE = 32'h${ram_size_address}; + localparam int unsigned MEM_SIZE = 32'h${f'{xheep.ram_size_address():08X}'}; - localparam SYSTEM_XBAR_NSLAVE = ${int(ram_numbanks) + 5}; + localparam SYSTEM_XBAR_NSLAVE = ${xheep.ram_numbanks() + 5}; localparam int unsigned LOG_SYSTEM_XBAR_NMASTER = SYSTEM_XBAR_NMASTER > 1 ? $clog2(SYSTEM_XBAR_NMASTER) : 32'd1; localparam int unsigned LOG_SYSTEM_XBAR_NSLAVE = SYSTEM_XBAR_NSLAVE > 1 ? $clog2(SYSTEM_XBAR_NSLAVE) : 32'd1; - localparam int unsigned NUM_BANKS = ${ram_numbanks}; - localparam int unsigned NUM_BANKS_IL = ${ram_numbanks_il}; + localparam int unsigned NUM_BANKS = ${xheep.ram_numbanks()}; + localparam int unsigned NUM_BANKS_IL = ${xheep.ram_numbanks_il()}; localparam int unsigned EXTERNAL_DOMAINS = ${external_domains}; localparam logic[31:0] ERROR_START_ADDRESS = 32'hBADACCE5; @@ -62,49 +63,44 @@ package core_v_mini_mcu_pkg; localparam logic[31:0] ERROR_END_ADDRESS = ERROR_START_ADDRESS + ERROR_SIZE; localparam logic[31:0] ERROR_IDX = 32'd0; -% for bank in range(ram_numbanks_cont): - localparam logic [31:0] RAM${bank}_START_ADDRESS = 32'h${'{:08X}'.format(int(ram_start_address) + bank*32*1024)}; - localparam logic [31:0] RAM${bank}_SIZE = 32'h${hex(32*1024)[2:]}; - localparam logic [31:0] RAM${bank}_END_ADDRESS = RAM${bank}_START_ADDRESS + RAM${bank}_SIZE; - localparam logic [31:0] RAM${bank}_IDX = 32'd${bank + 1}; +% for bank in xheep.iter_ram_banks(): + localparam logic [31:0] RAM${bank.name()}_IDX = 32'd${bank.map_idx()}; + localparam logic [31:0] RAM${bank.name()}_SIZE = 32'h${f'{bank.size():08X}'}; + localparam logic [31:0] RAM${bank.name()}_START_ADDRESS = 32'h${f'{bank.start_address():08X}'}; + localparam logic [31:0] RAM${bank.name()}_END_ADDRESS = 32'h${f'{bank.end_address():08X}'}; % endfor -% if ram_numbanks_il != 0: - localparam logic [31:0] RAM${ram_numbanks_cont}_START_ADDRESS = 32'h${'{:08X}'.format(int(ram_start_address) + int(ram_numbanks_cont)*32*1024)}; - localparam logic [31:0] RAM${ram_numbanks_cont}_SIZE = 32'h${hex(int(ram_numbanks_il)*32*1024)[2:]}; - localparam logic [31:0] RAM${ram_numbanks_cont}_END_ADDRESS = RAM${ram_numbanks_cont}_START_ADDRESS + RAM${ram_numbanks_cont}_SIZE; - localparam logic [31:0] RAM${ram_numbanks_cont}_IDX = 32'd${ram_numbanks_cont + 1}; -% for bank in range(ram_numbanks_il - 1): - localparam logic [31:0] RAM${int(ram_numbanks_cont) + bank + 1}_IDX = 32'd${int(ram_numbanks_cont) + bank + 2}; + +% for i, group in enumerate(xheep.iter_il_groups()): + localparam logic [31:0] RAM_IL${i}_START_ADDRESS = 32'h${f'{group.start:08X}'}; + localparam logic [31:0] RAM_IL${i}_SIZE = 32'h${f'{group.size:08X}'}; + localparam logic [31:0] RAM_IL${i}_END_ADDRESS = RAM_IL${i}_START_ADDRESS + RAM_IL${i}_SIZE; + localparam logic [31:0] RAM_IL${i}_IDX = RAM${group.first_name}_IDX; % endfor -% endif localparam logic[31:0] DEBUG_START_ADDRESS = 32'h${debug_start_address}; localparam logic[31:0] DEBUG_SIZE = 32'h${debug_size_address}; localparam logic[31:0] DEBUG_END_ADDRESS = DEBUG_START_ADDRESS + DEBUG_SIZE; - localparam logic[31:0] DEBUG_IDX = 32'd${int(ram_numbanks) + 1}; + localparam logic[31:0] DEBUG_IDX = 32'd${xheep.ram_numbanks() + 1}; localparam logic[31:0] AO_PERIPHERAL_START_ADDRESS = 32'h${ao_peripheral_start_address}; localparam logic[31:0] AO_PERIPHERAL_SIZE = 32'h${ao_peripheral_size_address}; localparam logic[31:0] AO_PERIPHERAL_END_ADDRESS = AO_PERIPHERAL_START_ADDRESS + AO_PERIPHERAL_SIZE; - localparam logic[31:0] AO_PERIPHERAL_IDX = 32'd${int(ram_numbanks) + 2}; + localparam logic[31:0] AO_PERIPHERAL_IDX = 32'd${xheep.ram_numbanks() + 2}; localparam logic[31:0] PERIPHERAL_START_ADDRESS = 32'h${peripheral_start_address}; localparam logic[31:0] PERIPHERAL_SIZE = 32'h${peripheral_size_address}; localparam logic[31:0] PERIPHERAL_END_ADDRESS = PERIPHERAL_START_ADDRESS + PERIPHERAL_SIZE; - localparam logic[31:0] PERIPHERAL_IDX = 32'd${int(ram_numbanks) + 3}; + localparam logic[31:0] PERIPHERAL_IDX = 32'd${xheep.ram_numbanks() + 3}; localparam logic[31:0] FLASH_MEM_START_ADDRESS = 32'h${flash_mem_start_address}; localparam logic[31:0] FLASH_MEM_SIZE = 32'h${flash_mem_size_address}; localparam logic[31:0] FLASH_MEM_END_ADDRESS = FLASH_MEM_START_ADDRESS + FLASH_MEM_SIZE; - localparam logic[31:0] FLASH_MEM_IDX = 32'd${int(ram_numbanks) + 4}; + localparam logic[31:0] FLASH_MEM_IDX = 32'd${xheep.ram_numbanks() + 4}; localparam addr_map_rule_t [SYSTEM_XBAR_NSLAVE-1:0] XBAR_ADDR_RULES = '{ '{ idx: ERROR_IDX, start_addr: ERROR_START_ADDRESS, end_addr: ERROR_END_ADDRESS }, -% for bank in range(ram_numbanks_cont): - '{ idx: RAM${bank}_IDX, start_addr: RAM${bank}_START_ADDRESS, end_addr: RAM${bank}_END_ADDRESS }, -% endfor -% for bank in range(ram_numbanks_il): - '{ idx: RAM${int(ram_numbanks_cont) + bank}_IDX, start_addr: RAM${ram_numbanks_cont}_START_ADDRESS, end_addr: RAM${ram_numbanks_cont}_END_ADDRESS }, +% for bank in xheep.iter_ram_banks(): + '{ idx: RAM${bank.name()}_IDX, start_addr: RAM${bank.name()}_START_ADDRESS, end_addr: RAM${bank.name()}_END_ADDRESS }, % endfor '{ idx: DEBUG_IDX, start_addr: DEBUG_START_ADDRESS, end_addr: DEBUG_END_ADDRESS }, '{ idx: AO_PERIPHERAL_IDX, start_addr: AO_PERIPHERAL_START_ADDRESS, end_addr: AO_PERIPHERAL_END_ADDRESS }, @@ -142,7 +138,15 @@ package core_v_mini_mcu_pkg; // always-on peripherals // --------------------- localparam AO_PERIPHERALS = ${ao_peripherals_count}; - + localparam DMA_CH_NUM = ${dma_ch_count}; + localparam DMA_CH_SIZE = 32'h${dma_ch_size}; + localparam DMA_NUM_MASTER_PORTS = ${num_dma_master_ports}; +% if int(num_dma_master_ports) > 1: + localparam int DMA_XBAR_MASTERS [DMA_NUM_MASTER_PORTS] = '{${dma_xbar_masters_array[::-1]}}; +% else: + localparam int DMA_XBAR_MASTERS [DMA_NUM_MASTER_PORTS] = '{${dma_xbar_masters_array}}; +% endif + % for peripheral, addr in ao_peripherals.items(): localparam logic [31:0] ${peripheral.upper()}_START_ADDRESS = AO_PERIPHERAL_START_ADDRESS + 32'h${addr["offset"]}; localparam logic [31:0] ${peripheral.upper()}_SIZE = 32'h${addr["length"]}; @@ -150,6 +154,7 @@ package core_v_mini_mcu_pkg; localparam logic [31:0] ${peripheral.upper()}_IDX = 32'd${loop.index}; % endfor + localparam addr_map_rule_t [AO_PERIPHERALS-1:0] AO_PERIPHERALS_ADDR_RULES = '{ % for peripheral, addr in ao_peripherals.items(): '{ idx: ${peripheral.upper()}_IDX, start_addr: ${peripheral.upper()}_START_ADDRESS, end_addr: ${peripheral.upper()}_END_ADDRESS }${"," if not loop.last else ""} @@ -158,6 +163,23 @@ package core_v_mini_mcu_pkg; localparam int unsigned AO_PERIPHERALS_PORT_SEL_WIDTH = AO_PERIPHERALS > 1 ? $clog2(AO_PERIPHERALS) : 32'd1; + // Relative DMA channels addresses +% for i in range(int(dma_ch_count)): + localparam logic [7:0] DMA_CH${i}_START_ADDRESS = 8'h${hex(int(ao_peripherals["dma"]["ch_length"], 16)*(i) >> 8)[2:]}; + localparam logic [7:0] DMA_CH${i}_SIZE = 8'h${hex(int(ao_peripherals["dma"]["ch_length"], 16) >> 8)[2:]}; + localparam logic [7:0] DMA_CH${i}_END_ADDRESS = DMA_CH${i}_START_ADDRESS + DMA_CH${i}_SIZE; + localparam logic [7:0] DMA_CH${i}_IDX = 8'd${i}; + +% endfor + + localparam addr_map_rule_8bit_t [DMA_CH_NUM-1:0] DMA_ADDR_RULES = '{ + % for i in range(int(dma_ch_count)): + '{ idx: DMA_CH${i}_IDX, start_addr: DMA_CH${i}_START_ADDRESS, end_addr: DMA_CH${i}_END_ADDRESS }${"," if not loop.last else ""} +% endfor + }; + + localparam int unsigned DMA_CH_PORT_SEL_WIDTH = DMA_CH_NUM > 1 ? $clog2(DMA_CH_NUM) : 32'd1; + ###################################################################### ## Automatically add all peripherals listed ###################################################################### @@ -195,5 +217,11 @@ package core_v_mini_mcu_pkg; localparam int unsigned NUM_PAD_PORT_SEL_WIDTH = NUM_PAD > 1 ? $clog2(NUM_PAD) : 32'd1; + typedef enum logic [1:0] { + TOP, + RIGHT, + BOTTOM, + LEFT + } pad_side_e; endpackage diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/power_manager_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/power_manager_pkg.sv new file mode 100644 index 00000000..613d2c7d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/power_manager_pkg.sv @@ -0,0 +1,17 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +package power_manager_pkg; + + typedef struct packed {logic pwrgate_ack_n;} power_manager_in_t; + + typedef struct packed { + logic clkgate_en_n; + logic pwrgate_en_n; + logic isogate_en_n; + logic retentive_en_n; + logic rst_n; + } power_manager_out_t; + +endpackage diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/x-heep_packages.core b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/x-heep_packages.core index 8a1a838d..6cbf61b0 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/x-heep_packages.core +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/include/x-heep_packages.core @@ -13,6 +13,7 @@ filesets: - addr_map_rule_pkg.sv - obi_pkg.sv - reg_pkg.sv + - power_manager_pkg.sv - core_v_mini_mcu_pkg.sv file_type: systemVerilogSource diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/memory_subsystem.sv.tpl b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/memory_subsystem.sv.tpl index 9e89348c..660b1b6a 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/memory_subsystem.sv.tpl +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/memory_subsystem.sv.tpl @@ -19,33 +19,27 @@ module memory_subsystem input obi_req_t [NUM_BANKS-1:0] ram_req_i, output obi_resp_t [NUM_BANKS-1:0] ram_resp_o, + // power manager signals that goes to the ASIC macros + input logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] pwrgate_ni, + output logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] pwrgate_ack_no, input logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] set_retentive_ni ); - localparam int NumWords = 32 * 1024 / 4; - localparam int AddrWidth = $clog2(32 * 1024); -% if ram_numbanks_il != 0: - localparam int ilAddrWidth = $clog2(${ram_numbanks_il} * 32 * 1024); -% endif - logic [NUM_BANKS-1:0] ram_valid_q; // Clock-gating logic [NUM_BANKS-1:0] clk_cg; -% if ram_numbanks_il != 0: - logic [NUM_BANKS-1:0][AddrWidth-3:0] ram_req_addr; - for (genvar i = 0; i < NUM_BANKS; i++) begin : gen_addr_napot - if (i >= NUM_BANKS - ${ram_numbanks_il}) begin - assign ram_req_addr[i] = { - ram_req_i[i].addr[ilAddrWidth-1:AddrWidth] - - core_v_mini_mcu_pkg::RAM${ram_numbanks_cont}_START_ADDRESS[ilAddrWidth-1:AddrWidth], - ram_req_i[i].addr[AddrWidth-1:${2+log_ram_numbanks_il}] - }; - end else begin - assign ram_req_addr[i] = ram_req_i[i].addr[AddrWidth-1:2]; - end - end -% endif +% for i, bank in enumerate(xheep.iter_ram_banks()): + logic [${bank.size().bit_length()-1 -2}-1:0] ram_req_addr_${i}; +% endfor + +% for i, bank in enumerate(xheep.iter_ram_banks()): +<% + p1 = bank.size().bit_length()-1 + bank.il_level() + p2 = 2 + bank.il_level() +%> + assign ram_req_addr_${i} = ram_req_i[${i}].addr[${p1}-1:${p2}]; +% endfor for (genvar i = 0; i < NUM_BANKS; i++) begin : gen_sram @@ -66,27 +60,26 @@ module memory_subsystem assign ram_resp_o[i].gnt = ram_req_i[i].req; assign ram_resp_o[i].rvalid = ram_valid_q[i]; + end - //Fixed to 8KWords per bank (32KB) - sram_wrapper #( - .NumWords (NumWords), - .DataWidth(32'd32) - ) ram_i ( - .clk_i(clk_cg[i]), - .rst_ni(rst_ni), - .req_i(ram_req_i[i].req), - .we_i(ram_req_i[i].we), -% if ram_numbanks_il == 0: - .addr_i(ram_req_i[i].addr[AddrWidth-1:2]), -% else: - .addr_i(ram_req_addr[i]), -% endif - .wdata_i(ram_req_i[i].wdata), - .be_i(ram_req_i[i].be), - .set_retentive_ni(set_retentive_ni[i]), - .rdata_o(ram_resp_o[i].rdata) - ); +%for i, bank in enumerate(xheep.iter_ram_banks()): + sram_wrapper #( + .NumWords (${bank.size() // 4}), + .DataWidth(32'd32) + ) ram${bank.name()}_i ( + .clk_i(clk_cg[${i}]), + .rst_ni(rst_ni), + .req_i(ram_req_i[${i}].req), + .we_i(ram_req_i[${i}].we), + .addr_i(ram_req_addr_${i}), + .wdata_i(ram_req_i[${i}].wdata), + .be_i(ram_req_i[${i}].be), + .pwrgate_ni(pwrgate_ni[${i}]), + .pwrgate_ack_no(pwrgate_ack_no[${i}]), + .set_retentive_ni(set_retentive_ni[${i}]), + .rdata_o(ram_resp_o[${i}].rdata) + ); - end +%endfor endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/peripheral_subsystem.sv b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/peripheral_subsystem.sv index 5c28e195..4fa663e6 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/peripheral_subsystem.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/peripheral_subsystem.sv @@ -50,6 +50,18 @@ module peripheral_subsystem output logic cio_sda_en_o, // SPI Host + output logic spi_sck_o, + output logic spi_sck_en_o, + output logic [spi_host_reg_pkg::NumCS-1:0] spi_csb_o, + output logic [spi_host_reg_pkg::NumCS-1:0] spi_csb_en_o, + output logic [ 3:0] spi_sd_o, + output logic [ 3:0] spi_sd_en_o, + input logic [ 3:0] spi_sd_i, + output logic spi_intr_event_o, + output logic spi_rx_valid_o, + output logic spi_tx_ready_o, + + // SPI 2 Host output logic spi2_sck_o, output logic spi2_sck_en_o, output logic [spi_host_reg_pkg::NumCS-1:0] spi2_csb_o, @@ -291,6 +303,32 @@ module peripheral_subsystem .msip_o(msip_o) ); + spi_host #( + .reg_req_t(reg_pkg::reg_req_t), + .reg_rsp_t(reg_pkg::reg_rsp_t) + ) spi_host_dma_i ( + .clk_i(clk_cg), + .rst_ni, + .reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::SPI_HOST_IDX]), + .reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::SPI_HOST_IDX]), + .alert_rx_i(), + .alert_tx_o(), + .passthrough_i(spi_device_pkg::PASSTHROUGH_REQ_DEFAULT), + .passthrough_o(), + .cio_sck_o(spi_sck_o), + .cio_sck_en_o(spi_sck_en_o), + .cio_csb_o(spi_csb_o), + .cio_csb_en_o(spi_csb_en_o), + .cio_sd_o(spi_sd_o), + .cio_sd_en_o(spi_sd_en_o), + .cio_sd_i(spi_sd_i), + .rx_valid_o(spi_rx_valid_o), + .tx_ready_o(spi_tx_ready_o), + .intr_error_o(), + .intr_spi_event_o(spi_intr_event_o) + ); + + gpio #( .reg_req_t(reg_pkg::reg_req_t), @@ -414,7 +452,7 @@ module peripheral_subsystem .reg_req_t(reg_pkg::reg_req_t), .reg_rsp_t(reg_pkg::reg_rsp_t) ) i2s_i ( - .clk_i, + .clk_i(clk_cg), .rst_ni, .reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::I2S_IDX]), .reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::I2S_IDX]), diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/peripheral_subsystem.sv.tpl b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/peripheral_subsystem.sv.tpl index 71215d04..4025cd88 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/peripheral_subsystem.sv.tpl +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/peripheral_subsystem.sv.tpl @@ -50,6 +50,18 @@ module peripheral_subsystem output logic cio_sda_en_o, // SPI Host + output logic spi_sck_o, + output logic spi_sck_en_o, + output logic [spi_host_reg_pkg::NumCS-1:0] spi_csb_o, + output logic [spi_host_reg_pkg::NumCS-1:0] spi_csb_en_o, + output logic [ 3:0] spi_sd_o, + output logic [ 3:0] spi_sd_en_o, + input logic [ 3:0] spi_sd_i, + output logic spi_intr_event_o, + output logic spi_rx_valid_o, + output logic spi_tx_ready_o, + + // SPI 2 Host output logic spi2_sck_o, output logic spi2_sck_en_o, output logic [spi_host_reg_pkg::NumCS-1:0] spi2_csb_o, @@ -306,6 +318,49 @@ module peripheral_subsystem % endif % endfor +% for peripheral in peripherals.items(): +% if peripheral[0] in ("spi_host"): +% if peripheral[1]['is_included'] in ("yes"): + spi_host #( + .reg_req_t(reg_pkg::reg_req_t), + .reg_rsp_t(reg_pkg::reg_rsp_t) + ) spi_host_dma_i ( + .clk_i(clk_cg), + .rst_ni, + .reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::SPI_HOST_IDX]), + .reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::SPI_HOST_IDX]), + .alert_rx_i(), + .alert_tx_o(), + .passthrough_i(spi_device_pkg::PASSTHROUGH_REQ_DEFAULT), + .passthrough_o(), + .cio_sck_o(spi_sck_o), + .cio_sck_en_o(spi_sck_en_o), + .cio_csb_o(spi_csb_o), + .cio_csb_en_o(spi_csb_en_o), + .cio_sd_o(spi_sd_o), + .cio_sd_en_o(spi_sd_en_o), + .cio_sd_i(spi_sd_i), + .rx_valid_o(spi_rx_valid_o), + .tx_ready_o(spi_tx_ready_o), + .intr_error_o(), + .intr_spi_event_o(spi_intr_event_o) + ); +% else: + assign peripheral_slv_rsp[core_v_mini_mcu_pkg::SPI_HOST_IDX] = '0; + assign spi_sck_o = '0; + assign spi_sck_en_o = '0; + assign spi_csb_o = '0; + assign spi_csb_en_o = '0; + assign spi_sd_o = '0; + assign spi_sd_en_o = '0; + assign spi_intr_event_o = '0; + assign spi_rx_valid_o = '0; + assign spi_tx_ready_o = '0; +% endif +% endif +% endfor + + % for peripheral in peripherals.items(): % if peripheral[0] in ("gpio"): @@ -491,7 +546,7 @@ module peripheral_subsystem .reg_req_t(reg_pkg::reg_req_t), .reg_rsp_t(reg_pkg::reg_rsp_t) ) pdm2pcm_i ( - .clk_i, + .clk_i(clk_cg), .rst_ni, .reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::PDM2PCM_IDX]), .reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::PDM2PCM_IDX]), @@ -514,7 +569,7 @@ module peripheral_subsystem .reg_req_t(reg_pkg::reg_req_t), .reg_rsp_t(reg_pkg::reg_rsp_t) ) i2s_i ( - .clk_i, + .clk_i(clk_cg), .rst_ni, .reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::I2S_IDX]), .reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::I2S_IDX]), diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/system_bus.sv.tpl b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/system_bus.sv.tpl index b7dbbfdc..221ec067 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/system_bus.sv.tpl +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/system_bus.sv.tpl @@ -37,14 +37,14 @@ module system_bus input obi_req_t debug_master_req_i, output obi_resp_t debug_master_resp_o, - input obi_req_t dma_read_ch0_req_i, - output obi_resp_t dma_read_ch0_resp_o, + input obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] dma_read_req_i, + output obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] dma_read_resp_o, - input obi_req_t dma_write_ch0_req_i, - output obi_resp_t dma_write_ch0_resp_o, + input obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] dma_write_req_i, + output obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] dma_write_resp_o, - input obi_req_t dma_addr_ch0_req_i, - output obi_resp_t dma_addr_ch0_resp_o, + input obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] dma_addr_req_i, + output obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] dma_addr_resp_o, // External master ports input obi_req_t [EXT_XBAR_NMASTER_RND-1:0] ext_xbar_master_req_i, @@ -76,14 +76,14 @@ module system_bus output obi_req_t ext_debug_master_req_o, input obi_resp_t ext_debug_master_resp_i, - output obi_req_t ext_dma_read_ch0_req_o, - input obi_resp_t ext_dma_read_ch0_resp_i, + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_read_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_read_resp_i, - output obi_req_t ext_dma_write_ch0_req_o, - input obi_resp_t ext_dma_write_ch0_resp_i, + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_write_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_write_resp_i, - output obi_req_t ext_dma_addr_ch0_req_o, - input obi_resp_t ext_dma_addr_ch0_resp_i + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_addr_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_addr_resp_i ); import core_v_mini_mcu_pkg::*; @@ -119,9 +119,12 @@ module system_bus assign int_master_req[core_v_mini_mcu_pkg::CORE_INSTR_IDX] = core_instr_req_i; assign int_master_req[core_v_mini_mcu_pkg::CORE_DATA_IDX] = core_data_req_i; assign int_master_req[core_v_mini_mcu_pkg::DEBUG_MASTER_IDX] = debug_master_req_i; - assign int_master_req[core_v_mini_mcu_pkg::DMA_READ_CH0_IDX] = dma_read_ch0_req_i; - assign int_master_req[core_v_mini_mcu_pkg::DMA_WRITE_CH0_IDX] = dma_write_ch0_req_i; - assign int_master_req[core_v_mini_mcu_pkg::DMA_ADDR_CH0_IDX] = dma_addr_ch0_req_i; + + % for i in range(int(num_dma_master_ports)): + assign int_master_req[${3+i*3}] = dma_read_req_i[${i}]; + assign int_master_req[${4+i*3}] = dma_write_req_i[${i}]; + assign int_master_req[${5+i*3}] = dma_addr_req_i[${i}]; + % endfor // Internal + external master requests generate @@ -142,10 +145,13 @@ module system_bus assign core_instr_resp_o = int_master_resp[core_v_mini_mcu_pkg::CORE_INSTR_IDX]; assign core_data_resp_o = int_master_resp[core_v_mini_mcu_pkg::CORE_DATA_IDX]; assign debug_master_resp_o = int_master_resp[core_v_mini_mcu_pkg::DEBUG_MASTER_IDX]; - assign dma_read_ch0_resp_o = int_master_resp[core_v_mini_mcu_pkg::DMA_READ_CH0_IDX]; - assign dma_write_ch0_resp_o = int_master_resp[core_v_mini_mcu_pkg::DMA_WRITE_CH0_IDX]; - assign dma_addr_ch0_resp_o = int_master_resp[core_v_mini_mcu_pkg::DMA_ADDR_CH0_IDX]; + % for i in range(int(num_dma_master_ports)): + assign dma_read_resp_o[${i}] = int_master_resp[${3+i*3}]; + assign dma_write_resp_o[${i}] = int_master_resp[${4+i*3}]; + assign dma_addr_resp_o[${i}] = int_master_resp[${5+i*3}]; + % endfor + // External master responses if (EXT_XBAR_NMASTER == 0) begin assign ext_xbar_master_resp_o = '0; @@ -157,8 +163,8 @@ module system_bus // Internal slave requests assign error_slave_req = int_slave_req[core_v_mini_mcu_pkg::ERROR_IDX]; -% for bank in range(ram_numbanks): - assign ram_req_o[${bank}] = int_slave_req[core_v_mini_mcu_pkg::RAM${bank}_IDX]; +% for bank in xheep.iter_ram_banks(): + assign ram_req_o[${bank.name()}] = int_slave_req[core_v_mini_mcu_pkg::RAM${bank.name()}_IDX]; % endfor assign debug_slave_req_o = int_slave_req[core_v_mini_mcu_pkg::DEBUG_IDX]; assign ao_peripheral_slave_req_o = int_slave_req[core_v_mini_mcu_pkg::AO_PERIPHERAL_IDX]; @@ -169,14 +175,19 @@ module system_bus assign ext_core_instr_req_o = demux_xbar_req[CORE_INSTR_IDX][DEMUX_XBAR_EXT_SLAVE_IDX]; assign ext_core_data_req_o = demux_xbar_req[CORE_DATA_IDX][DEMUX_XBAR_EXT_SLAVE_IDX]; assign ext_debug_master_req_o = demux_xbar_req[DEBUG_MASTER_IDX][DEMUX_XBAR_EXT_SLAVE_IDX]; - assign ext_dma_read_ch0_req_o = demux_xbar_req[DMA_READ_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX]; - assign ext_dma_write_ch0_req_o = demux_xbar_req[DMA_WRITE_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX]; - assign ext_dma_addr_ch0_req_o = demux_xbar_req[DMA_ADDR_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX]; + generate + for (genvar i = 0; i < core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS; i++) begin : gen_ext_dma_master_req_map + assign ext_dma_read_req_o[i] = demux_xbar_req[core_v_mini_mcu_pkg::DMA_READ_P0_IDX+3*i][DEMUX_XBAR_EXT_SLAVE_IDX]; + assign ext_dma_write_req_o[i] = demux_xbar_req[core_v_mini_mcu_pkg::DMA_WRITE_P0_IDX+3*i][DEMUX_XBAR_EXT_SLAVE_IDX]; + assign ext_dma_addr_req_o[i] = demux_xbar_req[core_v_mini_mcu_pkg::DMA_ADDR_P0_IDX+3*i][DEMUX_XBAR_EXT_SLAVE_IDX]; + end + endgenerate + // Internal slave responses assign int_slave_resp[core_v_mini_mcu_pkg::ERROR_IDX] = error_slave_resp; -% for bank in range(ram_numbanks): - assign int_slave_resp[core_v_mini_mcu_pkg::RAM${bank}_IDX] = ram_resp_i[${bank}]; +% for bank in xheep.iter_ram_banks(): + assign int_slave_resp[core_v_mini_mcu_pkg::RAM${bank.name()}_IDX] = ram_resp_i[${bank.name()}]; % endfor assign int_slave_resp[core_v_mini_mcu_pkg::DEBUG_IDX] = debug_slave_resp_i; assign int_slave_resp[core_v_mini_mcu_pkg::AO_PERIPHERAL_IDX] = ao_peripheral_slave_resp_i; @@ -187,10 +198,14 @@ module system_bus assign demux_xbar_resp[CORE_INSTR_IDX][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_core_instr_resp_i; assign demux_xbar_resp[CORE_DATA_IDX][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_core_data_resp_i; assign demux_xbar_resp[DEBUG_MASTER_IDX][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_debug_master_resp_i; - assign demux_xbar_resp[DMA_READ_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_dma_read_ch0_resp_i; - assign demux_xbar_resp[DMA_WRITE_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_dma_write_ch0_resp_i; - assign demux_xbar_resp[DMA_ADDR_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_dma_addr_ch0_resp_i; - + generate + for (genvar i = 0; i < core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS; i++) begin : gen_ext_dma_master_resp_map + assign demux_xbar_resp[core_v_mini_mcu_pkg::DMA_READ_P0_IDX+3*i][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_dma_read_resp_i[i]; + assign demux_xbar_resp[core_v_mini_mcu_pkg::DMA_WRITE_P0_IDX+3*i][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_dma_write_resp_i[i]; + assign demux_xbar_resp[core_v_mini_mcu_pkg::DMA_ADDR_P0_IDX+3*i][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_dma_addr_resp_i[i]; + end + endgenerate + `ifndef SYNTHESIS always_ff @(posedge clk_i, negedge rst_ni) begin : check_out_of_bound if (rst_ni) begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/system_xbar.sv.tpl b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/system_xbar.sv.tpl index 2731cb4e..18cbbe4d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/system_xbar.sv.tpl +++ b/hw/vendor/esl_epfl_x_heep/hw/core-v-mini-mcu/system_xbar.sv.tpl @@ -38,7 +38,7 @@ module system_xbar localparam int unsigned RESP_AGG_DATA_WIDTH = 32; //Address Decoder -% if ram_numbanks_il == 0: +% if not xheep.has_il_ram(): logic [XBAR_NMASTER-1:0][LOG_XBAR_NSLAVE-1:0] port_sel; % else: logic [XBAR_NMASTER-1:0][LOG_XBAR_NSLAVE-1:0] port_sel, pre_port_sel; @@ -75,7 +75,7 @@ module system_xbar ) addr_decode_i ( .addr_i(master_req_i[i].addr), .addr_map_i, -% if ram_numbanks_il == 0: +% if not xheep.has_il_ram(): .idx_o(port_sel[i]), % else: .idx_o(pre_port_sel[i]), @@ -86,21 +86,21 @@ module system_xbar .default_idx_i ); end -% if ram_numbanks_il != 0: +% if xheep.has_il_ram(): localparam ZERO = 32'h0; for (genvar j = 0; j < XBAR_NMASTER; j++) begin : gen_addr_napot always_comb begin - port_sel[j] = 1; - post_master_req_addr[j] = '0; - if (pre_port_sel[j] == NUM_BANKS[LOG_XBAR_NSLAVE-1:0] - (NUM_BANKS_IL[LOG_XBAR_NSLAVE-1:0]-1)) begin - port_sel[j] = NUM_BANKS[LOG_XBAR_NSLAVE-1:0] - (NUM_BANKS_IL[LOG_XBAR_NSLAVE-1:0]-1) + {ZERO[LOG_XBAR_NSLAVE-${1+log_ram_numbanks_il}:0],master_req_i[j].addr[${1+log_ram_numbanks_il}:2]}; - post_master_req_addr[j] = {master_req_i[j].addr[31:${2+log_ram_numbanks_il}], ${2+log_ram_numbanks_il}'h0}; - end else begin - port_sel[j] = pre_port_sel[j]; - post_master_req_addr[j] = master_req_i[j].addr; + port_sel[j] = pre_port_sel[j]; + post_master_req_addr[j] = master_req_i[j].addr; +% for i, group in enumerate(xheep.iter_il_groups()): + + if (pre_port_sel[j] == RAM_IL${i}_IDX[LOG_XBAR_NSLAVE-1:0]) begin + port_sel[j] = RAM_IL${i}_IDX[LOG_XBAR_NSLAVE-1:0] + {ZERO[LOG_XBAR_NSLAVE-${1+group.n.bit_length()}:0],master_req_i[j].addr[${group.n.bit_length()-1 +1}:2]}; + post_master_req_addr[j] = {master_req_i[j].addr[31:${2+group.n.bit_length()-1}], ${2+group.n.bit_length()-1}'h0}; end +% endfor end end % endif @@ -113,7 +113,7 @@ module system_xbar req: master_req_i[i].req, we: master_req_i[i].we, be: master_req_i[i].be, - % if ram_numbanks_il == 0: + % if not xheep.has_il_ram(): addr: master_req_i[i].addr, % else: addr: post_master_req_addr[i], diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.lock.hjson new file mode 100644 index 00000000..3a3e601c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.lock.hjson @@ -0,0 +1,14 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This file is generated by the util/vendor script. Please do not modify it +// manually. + +{ + upstream: + { + url: https://github.com/esl-epfl/nexys-a7-100t_board_files.git + rev: 19e19ad6bd3b5a405d3e0ef98fee94e7e19e3bab + } +} diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.vendor.hjson new file mode 100644 index 00000000..af1e9c40 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys-a7-100t_board_files.vendor.hjson @@ -0,0 +1,17 @@ +// Copyright 2022 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +{ + name: "esl_epfl_nexys_a7_100t_board_files", + target_dir: "esl_epfl_nexys_a7_100t_board_files", + + upstream: { + url: "https://github.com/esl-epfl/nexys-a7-100t_board_files.git", + rev: "19e19ad6bd3b5a405d3e0ef98fee94e7e19e3bab", + }, + + exclude_from_upstream: [ + "README.md" + ] +} diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/board.xml b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/board.xml new file mode 100644 index 00000000..1ce62873 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/board.xml @@ -0,0 +1,1301 @@ + + + + + D.0 + +1.3 +Nexys A7-100T + + + + + Accelerometer control through SPI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DDR2 board interface, it can use MIG IP for connection. + + + + + + 16 DIP Switches + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dual 7 Seg LED Segments + + + + + + + + + + + + + + + + + + + + 16 LEDs + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 Push Buttons + + + + + + + + + + + + + + + + + Quad SPI Flash + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 RGB LEDs + + + + + + + + + + + + + + + + + + 7 Segment Display Anodes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Temperature Sensor connected to I2C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + USB-to-UART Bridge, which allows a connection to a host computer with a USB port + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Accelerometer controlled through SPI + + + 256 MB Onboard DDR Memory + + + + + + + 16 Switches + + + 7 Segment Display Segment Control + + + 16 LEDs + + + Push Buttons 5 to 0 {Down Right Left Up Center} + + + QSPI Flash + + + Onboard Reset Button + + + 2 RGB LEDs + + + 7 Segment Display Anodes + + + 100 MHz Single-Ended System Clock + + + SPI Controlled Temperature Sensor + + + USB-to-UART Bridge, which allows a connection to a host computer with a USB port + + + Pmod Connector JA + + + Pmod Connector JB + + + Pmod Connector JC + + + Pmod Connector JD + + + Pmod Connector JXADC + + + + + + + + + + + + + + + + + + + + + Onboard MicroSD Card Slot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/mig.prj b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/mig.prj new file mode 100644 index 00000000..301f5834 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/mig.prj @@ -0,0 +1,157 @@ + + + + + + + + design_1_mig_7series_0_0 + + 1 + + 1 + + OFF + + 1024 + + ON + + Enabled + + xc7a100t-csg324/-1 + + 4.2 + + Single-Ended + + No Buffer + + ACTIVE LOW + + FALSE + + 1 + + 50 Ohms + + 0 + + + 7a/xc7a50t-csg324 + + + + DDR2_SDRAM/Components/MT47H64M16HR-25E + 3077 + 1.8V + 4:1 + 99.997 + 1 + 1200 + 6.000 + 1 + 1 + 1 + 1 + 16 + 1 + 1 + Disabled + Strict + 4 + FALSE + + 13 + 10 + 3 + 134217728 + BANK_ROW_COLUMN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 + Sequential + 5 + Normal + No + Fast exit + 5 + Enable-Normal + Fullstrength + Enable + 1 + 50ohms + 0 + OCD Exit + Enable + Disable + Enable + AXI + + RD_PRI_REG + 27 + 128 + 4 + 0 + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/part0_pins.xml b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/part0_pins.xml new file mode 100644 index 00000000..43f20b5e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/part0_pins.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/preset.xml b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/preset.xml new file mode 100644 index 00000000..7128ccee --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_nexys_a7_100t_board_files/preset.xml @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.lock.hjson new file mode 100644 index 00000000..a05740cc --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.lock.hjson @@ -0,0 +1,14 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This file is generated by the util/vendor script. Please do not modify it +// manually. + +{ + upstream: + { + url: https://github.com/esl-epfl/zcu104_board_files.git + rev: 53e4affbaeec73809304940be8f5351ae147227a + } +} diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.vendor.hjson new file mode 100644 index 00000000..69028826 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files.vendor.hjson @@ -0,0 +1,16 @@ +// Copyright 2023 David Mallasén Quintana +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +{ + name: "esl_epfl_zcu104_board_files", + target_dir: "esl_epfl_zcu104_board_files", + + upstream: { + url: "https://github.com/esl-epfl/zcu104_board_files.git", + rev: "53e4affbaeec73809304940be8f5351ae147227a", + }, + + exclude_from_upstream: [ + "README.md" + ] +} diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/board.xml b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/board.xml new file mode 100644 index 00000000..2206a918 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/board.xml @@ -0,0 +1,657 @@ + + + + + + ZCU104 Board File Image + + + + + RevA + RevB + RevC + + + 1.0 + + Zynq UltraScale+ ZCU104 Evaluation Board + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FPGA part on the board + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DDR4 board interface, it can use DDR4 controller IP for connection. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4-Position User DIP Switch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SI570 based User programmable differential 300 MHz Clock. Can be used for DDR4 input system clock + + + + + + + PL UART + + + + + + + + PL I2C + + + + + 2GB DDR4 SDRAM memory SODIMM + + + + + + + + CPU Reset Push Button, Active High + + + + DIP Switches 3 to 0 + + + + LEDs, 3 to 0, Active High + + + + Push Buttons, 3 to 0, Active High + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/part0_pins.xml b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/part0_pins.xml new file mode 100644 index 00000000..e5d6301c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/part0_pins.xml @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/preset.xml b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/preset.xml new file mode 100644 index 00000000..b8d89084 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/board_files/vendor/esl_epfl_zcu104_board_files/preset.xml @@ -0,0 +1,446 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/constraints.xdc b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/constraints.xdc index 5a3c1c4b..ed3a6e89 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/constraints.xdc +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/constraints.xdc @@ -1 +1 @@ -set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets x_heep_system_i/pad_ring_i/pad_clk_i/xilinx_iobuf_i/O] +create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clk_i}]; diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/pin_assign.xdc b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/pin_assign.xdc index 53e0eb8f..d3723fef 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/pin_assign.xdc +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/nexys/pin_assign.xdc @@ -1,213 +1,101 @@ -## This file is a general .xdc for the Nexys A7-100T -## To use it in a project: -## - uncomment the lines corresponding to used pins -## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project +# Copyright 2022 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 ## Clock signal -set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { clk_i }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz -#create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {CLK100MHZ}]; +set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports {clk_i}]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz -##Switches -set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { jtag_trst_ni }]; #IO_L24N_T3_RS0_15 Sch=sw[0] -set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { execute_from_flash_i }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1] -set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { boot_select_i }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2] -#set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { SW[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3] -#set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { SW[4] }]; #IO_L12N_T1_MRCC_14 Sch=sw[4] -#set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { SW[5] }]; #IO_L7N_T1_D10_14 Sch=sw[5] -#set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { SW[6] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6] -#set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { SW[7] }]; #IO_L5N_T0_D07_14 Sch=sw[7] -#set_property -dict { PACKAGE_PIN T8 IOSTANDARD LVCMOS18 } [get_ports { SW[8] }]; #IO_L24N_T3_34 Sch=sw[8] -#set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS18 } [get_ports { SW[9] }]; #IO_25_34 Sch=sw[9] -#set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { SW[10] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=sw[10] -#set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { SW[11] }]; #IO_L23P_T3_A03_D19_14 Sch=sw[11] -#set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { SW[12] }]; #IO_L24P_T3_35 Sch=sw[12] -#set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { SW[13] }]; #IO_L20P_T3_A08_D24_14 Sch=sw[13] -#set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { SW[14] }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=sw[14] -#set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { SW[15] }]; #IO_L21P_T3_DQS_14 Sch=sw[15] +set_property -dict {PACKAGE_PIN C12 IOSTANDARD LVCMOS33} [get_ports {rst_i}]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn ## LEDs -set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { rst_led }]; #IO_L18P_T2_A24_15 Sch=led[0] -set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { clk_led }]; #IO_L24P_T3_RS1_15 Sch=led[1] -set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { exit_value_o }]; #IO_L17N_T2_A25_15 Sch=led[2] -set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { exit_valid_o }]; #IO_L8P_T1_D11_14 Sch=led[3] -set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[29] }]; #IO_L7P_T1_D09_14 Sch=led[4] -#set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[30] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5] -#set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[31] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6] -#set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { LED[7] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7] -#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { LED[8] }]; #IO_L16N_T2_A15_D31_14 Sch=led[8] -#set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { LED[9] }]; #IO_L14N_T2_SRCC_14 Sch=led[9] -#set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { LED[10] }]; #IO_L22P_T3_A05_D21_14 Sch=led[10] -#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { LED[11] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=led[11] -#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { LED[12] }]; #IO_L16P_T2_CSI_B_14 Sch=led[12] -#set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { LED[13] }]; #IO_L22N_T3_A04_D20_14 Sch=led[13] -#set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { LED[14] }]; #IO_L20N_T3_A07_D23_14 Sch=led[14] -#set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { LED[15] }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=led[15] - -## RGB LEDs -#set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { LED16_B }]; #IO_L5P_T0_D06_14 Sch=led16_b -#set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { LED16_G }]; #IO_L10P_T1_D14_14 Sch=led16_g -#set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { LED16_R }]; #IO_L11P_T1_SRCC_14 Sch=led16_r -#set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { LED17_B }]; #IO_L15N_T2_DQS_ADV_B_15 Sch=led17_b -#set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { LED17_G }]; #IO_0_14 Sch=led17_g -#set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { LED17_R }]; #IO_L11N_T1_SRCC_14 Sch=led17_r - -##7 segment display -set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[8] }]; #IO_L24N_T3_A00_D16_14 Sch=ca -set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[9] }]; #IO_25_14 Sch=cb -set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[10] }]; #IO_25_15 Sch=cc -set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[11] }]; #IO_L17P_T2_A26_15 Sch=cd -set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[12] }]; #IO_L13P_T2_MRCC_14 Sch=ce -set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[13] }]; #IO_L19P_T3_A10_D26_14 Sch=cf -set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[14] }]; #IO_L4P_T0_D04_14 Sch=cg -set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[15] }]; #IO_L19N_T3_A21_VREF_15 Sch=dp -set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[16] }]; #IO_L23P_T3_FOE_B_15 Sch=an[0] -set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[17] }]; #IO_L23N_T3_FWE_B_15 Sch=an[1] -set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[18] }]; #IO_L24P_T3_A01_D17_14 Sch=an[2] -set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[19] }]; #IO_L19P_T3_A22_15 Sch=an[3] -set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[20] }]; #IO_L8N_T1_D12_14 Sch=an[4] -set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[21] }]; #IO_L14P_T2_SRCC_14 Sch=an[5] -set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[22] }]; #IO_L23P_T3_35 Sch=an[6] -set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[23] }]; #IO_L23N_T3_A02_D18_14 Sch=an[7] - -##CPU Reset Button -set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { rst_i }]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn +set_property -dict {PACKAGE_PIN V11 IOSTANDARD LVCMOS33} [get_ports {rst_led_o}]; +set_property -dict {PACKAGE_PIN J13 IOSTANDARD LVCMOS33} [get_ports {clk_led_o}]; +set_property -dict {PACKAGE_PIN N14 IOSTANDARD LVCMOS33} [get_ports {exit_valid_o}]; +set_property -dict {PACKAGE_PIN R18 IOSTANDARD LVCMOS33} [get_ports {exit_value_o}]; +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_led_o_OBUF] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets rst_led_o_OBUF] -##Buttons -set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[24] }]; #IO_L9P_T1_DQS_14 Sch=btnc -set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[25] }]; #IO_L4N_T0_D05_14 Sch=btnu -set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[26] }]; #IO_L12P_T1_MRCC_14 Sch=btnl -set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[27] }]; #IO_L10N_T1_D15_14 Sch=btnr -set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[28] }]; #IO_L9N_T1_DQS_D13_14 Sch=btnd +##Switches +set_property -dict {PACKAGE_PIN L16 IOSTANDARD LVCMOS33} [get_ports {execute_from_flash_i}]; #Sch=sw[1] +set_property -dict {PACKAGE_PIN M13 IOSTANDARD LVCMOS33} [get_ports {boot_select_i}]; #Sch=sw[2] +##Switches +set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports {jtag_trst_ni}]; #IO_L24N_T3_RS0_15 Sch=sw[0] ##Pmod Headers ##Pmod Header JA -set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[0] }]; #IO_L20N_T3_A19_15 Sch=ja[1] -set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[1] }]; #IO_L21N_T3_DQS_A18_15 Sch=ja[2] -set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[2] }]; #IO_L21P_T3_DQS_15 Sch=ja[3] -set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[3] }]; #IO_L18N_T2_A23_15 Sch=ja[4] -set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[4] }]; #IO_L16N_T2_A27_15 Sch=ja[7] -set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[5] }]; #IO_L16P_T2_A28_15 Sch=ja[8] -set_property -dict { PACKAGE_PIN F18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[6] }]; #IO_L22N_T3_A16_15 Sch=ja[9] -set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[7] }]; #IO_L22P_T3_A17_15 Sch=ja[10] - -##Pmod Header JB -#set_property -dict { PACKAGE_PIN D14 IOSTANDARD LVCMOS33 } [get_ports { JB[1] }]; #IO_L1P_T0_AD0P_15 Sch=jb[1] -#set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports { JB[2] }]; #IO_L14N_T2_SRCC_15 Sch=jb[2] -#set_property -dict { PACKAGE_PIN G16 IOSTANDARD LVCMOS33 } [get_ports { JB[3] }]; #IO_L13N_T2_MRCC_15 Sch=jb[3] -set_property -dict { PACKAGE_PIN H14 IOSTANDARD LVCMOS33 } [get_ports { clk_out }]; #IO_L15P_T2_DQS_15 Sch=jb[4] -set_property -dict { PACKAGE_PIN E16 IOSTANDARD LVCMOS33 } [get_ports { jtag_tms_i }]; #IO_L11N_T1_SRCC_15 Sch=jb[7] -set_property -dict { PACKAGE_PIN F13 IOSTANDARD LVCMOS33 } [get_ports { jtag_tdi_i }]; #IO_L5P_T0_AD9P_15 Sch=jb[8] -set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports { jtag_tdo_o }]; #IO_0_15 Sch=jb[9] -set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { jtag_tck_i }]; #IO_L13P_T2_MRCC_15 Sch=jb[10] +set_property -dict {PACKAGE_PIN C17 IOSTANDARD LVCMOS33} [get_ports {spi_flash_csb_o}]; #IO_L20N_T3_A19_15 Sch=ja[1] +set_property -dict {PACKAGE_PIN D18 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sck_o}]; #IO_L21N_T3_DQS_A18_15 Sch=ja[2] +set_property -dict {PACKAGE_PIN E18 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[0]}]; #IO_L21P_T3_DQS_15 Sch=ja[3] +set_property -dict {PACKAGE_PIN G17 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[1]}]; #IO_L18N_T2_A23_15 Sch=ja[4] +set_property -dict {PACKAGE_PIN D17 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[2]}]; #IO_L16N_T2_A27_15 Sch=ja[7] +set_property -dict {PACKAGE_PIN E17 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[3]}]; #IO_L16P_T2_A28_15 Sch=ja[8] +#set_property -dict {PACKAGE_PIN F18 IOSTANDARD LVCMOS33} [get_ports {gpio_io[6]}]; #IO_L22N_T3_A16_15 Sch=ja[9] +#set_property -dict {PACKAGE_PIN G18 IOSTANDARD LVCMOS33} [get_ports {gpio_io[7]}]; #IO_L22P_T3_A17_15 Sch=ja[10] ##Pmod Header JC -#set_property -dict { PACKAGE_PIN K1 IOSTANDARD LVCMOS33 } [get_ports { JC[1] }]; #IO_L23N_T3_35 Sch=jc[1] -#set_property -dict { PACKAGE_PIN F6 IOSTANDARD LVCMOS33 } [get_ports { JC[2] }]; #IO_L19N_T3_VREF_35 Sch=jc[2] -set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { i2c_scl_io }]; #IO_L22N_T3_35 Sch=jc[3] -set_property -dict { PACKAGE_PIN G6 IOSTANDARD LVCMOS33 } [get_ports { i2c_sda_io }]; #IO_L19P_T3_35 Sch=jc[4] -#set_property -dict { PACKAGE_PIN E7 IOSTANDARD LVCMOS33 } [get_ports { JC[7] }]; #IO_L6P_T0_35 Sch=jc[7] -set_property -dict { PACKAGE_PIN J3 IOSTANDARD LVCMOS33 } [get_ports { spi_csb_o }]; #IO_L22P_T3_35 Sch=jc[8] -#set_property -dict { PACKAGE_PIN J4 IOSTANDARD LVCMOS33 } [get_ports { JC[9] }]; #IO_L21P_T3_DQS_35 Sch=jc[9] -#set_property -dict { PACKAGE_PIN E6 IOSTANDARD LVCMOS33 } [get_ports { JC[10] }]; #IO_L5P_T0_AD13P_35 Sch=jc[10] - -##Pmod Header JD -#set_property -dict { PACKAGE_PIN H4 IOSTANDARD LVCMOS33 } [get_ports { JD[1] }]; #IO_L21N_T3_DQS_35 Sch=jd[1] -#set_property -dict { PACKAGE_PIN H1 IOSTANDARD LVCMOS33 } [get_ports { JD[2] }]; #IO_L17P_T2_35 Sch=jd[2] -#set_property -dict { PACKAGE_PIN G1 IOSTANDARD LVCMOS33 } [get_ports { JD[3] }]; #IO_L17N_T2_35 Sch=jd[3] -#set_property -dict { PACKAGE_PIN G3 IOSTANDARD LVCMOS33 } [get_ports { JD[4] }]; #IO_L20N_T3_35 Sch=jd[4] -#set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { JD[7] }]; #IO_L15P_T2_DQS_35 Sch=jd[7] -#set_property -dict { PACKAGE_PIN G4 IOSTANDARD LVCMOS33 } [get_ports { JD[8] }]; #IO_L20P_T3_35 Sch=jd[8] -#set_property -dict { PACKAGE_PIN G2 IOSTANDARD LVCMOS33 } [get_ports { JD[9] }]; #IO_L15N_T2_DQS_35 Sch=jd[9] -#set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { JD[10] }]; #IO_L13N_T2_MRCC_35 Sch=jd[10] - -##Pmod Header JXADC -#set_property -dict { PACKAGE_PIN A14 IOSTANDARD LVCMOS33 } [get_ports { XA_N[1] }]; #IO_L9N_T1_DQS_AD3N_15 Sch=xa_n[1] -#set_property -dict { PACKAGE_PIN A13 IOSTANDARD LVCMOS33 } [get_ports { XA_P[1] }]; #IO_L9P_T1_DQS_AD3P_15 Sch=xa_p[1] -set_property -dict { PACKAGE_PIN A16 IOSTANDARD LVCMOS33 } [get_ports { spi_sd_io[2] }]; #IO_L8N_T1_AD10N_15 Sch=xa_n[2] -set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVCMOS33 } [get_ports { spi_sd_io[0] }]; #IO_L8P_T1_AD10P_15 Sch=xa_p[2] -#set_property -dict { PACKAGE_PIN B17 IOSTANDARD LVCMOS33 } [get_ports { XA_N[3] }]; #IO_L7N_T1_AD2N_15 Sch=xa_n[3] -set_property -dict { PACKAGE_PIN B16 IOSTANDARD LVCMOS33 } [get_ports { spi_sd_io[1] }]; #IO_L7P_T1_AD2P_15 Sch=xa_p[3] -set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { spi_sd_io[3] }]; #IO_L10N_T1_AD11N_15 Sch=xa_n[4] -set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 } [get_ports { spi_sck_o }]; #IO_L10P_T1_AD11P_15 Sch=xa_p[4] - -##VGA Connector -#set_property -dict { PACKAGE_PIN A3 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[0] }]; #IO_L8N_T1_AD14N_35 Sch=vga_r[0] -#set_property -dict { PACKAGE_PIN B4 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[1] }]; #IO_L7N_T1_AD6N_35 Sch=vga_r[1] -#set_property -dict { PACKAGE_PIN C5 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[2] }]; #IO_L1N_T0_AD4N_35 Sch=vga_r[2] -#set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[3] }]; #IO_L8P_T1_AD14P_35 Sch=vga_r[3] -#set_property -dict { PACKAGE_PIN C6 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[0] }]; #IO_L1P_T0_AD4P_35 Sch=vga_g[0] -#set_property -dict { PACKAGE_PIN A5 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[1] }]; #IO_L3N_T0_DQS_AD5N_35 Sch=vga_g[1] -#set_property -dict { PACKAGE_PIN B6 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[2] }]; #IO_L2N_T0_AD12N_35 Sch=vga_g[2] -#set_property -dict { PACKAGE_PIN A6 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[3] }]; #IO_L3P_T0_DQS_AD5P_35 Sch=vga_g[3] -#set_property -dict { PACKAGE_PIN B7 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[0] }]; #IO_L2P_T0_AD12P_35 Sch=vga_b[0] -#set_property -dict { PACKAGE_PIN C7 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[1] }]; #IO_L4N_T0_35 Sch=vga_b[1] -#set_property -dict { PACKAGE_PIN D7 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[2] }]; #IO_L6N_T0_VREF_35 Sch=vga_b[2] -#set_property -dict { PACKAGE_PIN D8 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[3] }]; #IO_L4P_T0_35 Sch=vga_b[3] -#set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports { VGA_HS }]; #IO_L4P_T0_15 Sch=vga_hs -#set_property -dict { PACKAGE_PIN B12 IOSTANDARD LVCMOS33 } [get_ports { VGA_VS }]; #IO_L3N_T0_DQS_AD1N_15 Sch=vga_vs - -##Micro SD Connector -#set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { SD_RESET }]; #IO_L14P_T2_SRCC_35 Sch=sd_reset -#set_property -dict { PACKAGE_PIN A1 IOSTANDARD LVCMOS33 } [get_ports { SD_CD }]; #IO_L9N_T1_DQS_AD7N_35 Sch=sd_cd -#set_property -dict { PACKAGE_PIN B1 IOSTANDARD LVCMOS33 } [get_ports { SD_SCK }]; #IO_L9P_T1_DQS_AD7P_35 Sch=sd_sck -#set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { SD_CMD }]; #IO_L16N_T2_35 Sch=sd_cmd -#set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { SD_DAT[0] }]; #IO_L16P_T2_35 Sch=sd_dat[0] -#set_property -dict { PACKAGE_PIN E1 IOSTANDARD LVCMOS33 } [get_ports { SD_DAT[1] }]; #IO_L18N_T2_35 Sch=sd_dat[1] -#set_property -dict { PACKAGE_PIN F1 IOSTANDARD LVCMOS33 } [get_ports { SD_DAT[2] }]; #IO_L18P_T2_35 Sch=sd_dat[2] -#set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { SD_DAT[3] }]; #IO_L14N_T2_SRCC_35 Sch=sd_dat[3] - -##Accelerometer -#set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 } [get_ports { ACL_MISO }]; #IO_L11P_T1_SRCC_15 Sch=acl_miso -#set_property -dict { PACKAGE_PIN F14 IOSTANDARD LVCMOS33 } [get_ports { ACL_MOSI }]; #IO_L5N_T0_AD9N_15 Sch=acl_mosi -#set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS33 } [get_ports { ACL_SCLK }]; #IO_L14P_T2_SRCC_15 Sch=acl_sclk -#set_property -dict { PACKAGE_PIN D15 IOSTANDARD LVCMOS33 } [get_ports { ACL_CSN }]; #IO_L12P_T1_MRCC_15 Sch=acl_csn -#set_property -dict { PACKAGE_PIN B13 IOSTANDARD LVCMOS33 } [get_ports { ACL_INT[1] }]; #IO_L2P_T0_AD8P_15 Sch=acl_int[1] -#set_property -dict { PACKAGE_PIN C16 IOSTANDARD LVCMOS33 } [get_ports { ACL_INT[2] }]; #IO_L20P_T3_A20_15 Sch=acl_int[2] - -##Temperature Sensor -#set_property -dict { PACKAGE_PIN C14 IOSTANDARD LVCMOS33 } [get_ports { TMP_SCL }]; #IO_L1N_T0_AD0N_15 Sch=tmp_scl -#set_property -dict { PACKAGE_PIN C15 IOSTANDARD LVCMOS33 } [get_ports { TMP_SDA }]; #IO_L12N_T1_MRCC_15 Sch=tmp_sda -#set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports { TMP_INT }]; #IO_L6N_T0_VREF_15 Sch=tmp_int -#set_property -dict { PACKAGE_PIN B14 IOSTANDARD LVCMOS33 } [get_ports { TMP_CT }]; #IO_L2N_T0_AD8N_15 Sch=tmp_ct - -##Omnidirectional Microphone -#set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports { M_CLK }]; #IO_25_35 Sch=m_clk -#set_property -dict { PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports { M_DATA }]; #IO_L24N_T3_35 Sch=m_data -#set_property -dict { PACKAGE_PIN F5 IOSTANDARD LVCMOS33 } [get_ports { M_LRSEL }]; #IO_0_35 Sch=m_lrsel - -##PWM Audio Amplifier -#set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports { AUD_PWM }]; #IO_L4N_T0_15 Sch=aud_pwm -#set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 } [get_ports { AUD_SD }]; #IO_L6P_T0_15 Sch=aud_sd +set_property -dict {PACKAGE_PIN K1 IOSTANDARD LVCMOS33} [get_ports {spi_csb_o}]; #IO_L23N_T3_35 Sch=jc[1] +set_property -dict {PACKAGE_PIN F6 IOSTANDARD LVCMOS33} [get_ports {spi_sck_o}]; #IO_L19N_T3_VREF_35 Sch=jc[2] +set_property -dict {PACKAGE_PIN J2 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[0]}]; #IO_L22N_T3_35 Sch=jc[3] +set_property -dict {PACKAGE_PIN G6 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[1]}]; #IO_L19P_T3_35 Sch=jc[4] +set_property -dict {PACKAGE_PIN E7 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[2]}]; #IO_L6P_T0_35 Sch=jc[7] +set_property -dict {PACKAGE_PIN J3 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[3]}]; #IO_L22P_T3_35 Sch=jc[8] +#set_property -dict {PACKAGE_PIN J4 IOSTANDARD LVCMOS33} [get_ports {clk_out}]; #IO_L21P_T3_DQS_35 Sch=jc[9] +#set_property -dict {PACKAGE_PIN E6 IOSTANDARD LVCMOS33} [get_ports {JC[10]}]; #IO_L5P_T0_AD13P_35 Sch=jc[10] ##USB-RS232 Interface -set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { uart_rx_i }]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in -set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { uart_tx_o }]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out -#set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { UART_CTS }]; #IO_L12N_T1_MRCC_35 Sch=uart_cts -#set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { UART_RTS }]; #IO_L5N_T0_AD13N_35 Sch=uart_rts - -##USB HID (PS/2) -#set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { PS2_CLK }]; #IO_L13P_T2_MRCC_35 Sch=ps2_clk -#set_property -dict { PACKAGE_PIN B2 IOSTANDARD LVCMOS33 } [get_ports { PS2_DATA }]; #IO_L10N_T1_AD15N_35 Sch=ps2_data - -##SMSC Ethernet PHY -#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { ETH_MDC }]; #IO_L11P_T1_SRCC_16 Sch=eth_mdc -#set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { ETH_MDIO }]; #IO_L14N_T2_SRCC_16 Sch=eth_mdio -#set_property -dict { PACKAGE_PIN B3 IOSTANDARD LVCMOS33 } [get_ports { ETH_RSTN }]; #IO_L10P_T1_AD15P_35 Sch=eth_rstn -#set_property -dict { PACKAGE_PIN D9 IOSTANDARD LVCMOS33 } [get_ports { ETH_CRSDV }]; #IO_L6N_T0_VREF_16 Sch=eth_crsdv -#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { ETH_RXERR }]; #IO_L13N_T2_MRCC_16 Sch=eth_rxerr -#set_property -dict { PACKAGE_PIN C11 IOSTANDARD LVCMOS33 } [get_ports { ETH_RXD[0] }]; #IO_L13P_T2_MRCC_16 Sch=eth_rxd[0] -#set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { ETH_RXD[1] }]; #IO_L19N_T3_VREF_16 Sch=eth_rxd[1] -#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { ETH_TXEN }]; #IO_L11N_T1_SRCC_16 Sch=eth_txen -#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { ETH_TXD[0] }]; #IO_L14P_T2_SRCC_16 Sch=eth_txd[0] -#set_property -dict { PACKAGE_PIN A8 IOSTANDARD LVCMOS33 } [get_ports { ETH_TXD[1] }]; #IO_L12N_T1_MRCC_16 Sch=eth_txd[1] -#set_property -dict { PACKAGE_PIN D5 IOSTANDARD LVCMOS33 } [get_ports { ETH_REFCLK }]; #IO_L11P_T1_SRCC_35 Sch=eth_refclk -#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { ETH_INTN }]; #IO_L12P_T1_MRCC_16 Sch=eth_intn - -##Quad SPI Flash -#set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[0] }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_dq[0] -#set_property -dict { PACKAGE_PIN K18 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[1] }]; #IO_L1N_T0_D01_DIN_14 Sch=qspi_dq[1] -#set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[2] }]; #IO_L2P_T0_D02_14 Sch=qspi_dq[2] -#set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_dq[3] -#set_property -dict { PACKAGE_PIN L13 IOSTANDARD LVCMOS33 } [get_ports { QSPI_CSN }]; #IO_L6P_T0_FCS_B_14 Sch=qspi_csn \ No newline at end of file +set_property -dict {PACKAGE_PIN C4 IOSTANDARD LVCMOS33} [get_ports {uart_rx_i}]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in +set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33} [get_ports {uart_tx_o}]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out + +##Pmod Header JB +#set_property -dict {PACKAGE_PIN D14 IOSTANDARD LVCMOS33} [get_ports {JB[1]}]; #IO_L1P_T0_AD0P_15 Sch=jb[1] +#set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports {JB[2]}]; #IO_L14N_T2_SRCC_15 Sch=jb[2] +#set_property -dict {PACKAGE_PIN G16 IOSTANDARD LVCMOS33} [get_ports {uart_tx_o}]; #IO_L13N_T2_MRCC_15 Sch=jb[3] +#set_property -dict {PACKAGE_PIN H14 IOSTANDARD LVCMOS33} [get_ports {uart_rx_i}]; #IO_L15P_T2_DQS_15 Sch=jb[4] +set_property -dict {PACKAGE_PIN E16 IOSTANDARD LVCMOS33} [get_ports {jtag_tms_i}]; #IO_L11N_T1_SRCC_15 Sch=jb[7] +set_property -dict {PACKAGE_PIN F13 IOSTANDARD LVCMOS33} [get_ports {jtag_tdi_i}]; #IO_L5P_T0_AD9P_15 Sch=jb[8] +set_property -dict {PACKAGE_PIN G13 IOSTANDARD LVCMOS33} [get_ports {jtag_tdo_o}]; #IO_0_15 Sch=jb[9] +set_property -dict {PACKAGE_PIN H16 IOSTANDARD LVCMOS33} [get_ports {jtag_tck_i}]; #IO_L13P_T2_MRCC_15 Sch=jb[10] + +## LEDs +set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[1]}]; +set_property -dict {PACKAGE_PIN U17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[2]}]; +set_property -dict {PACKAGE_PIN U16 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[3]}]; +set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports {i2c_scl_io}]; +set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports {i2c_sda_io}]; +set_property -dict {PACKAGE_PIN U14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[5]}]; +set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports {gpio_io[6]}]; +set_property -dict {PACKAGE_PIN V15 IOSTANDARD LVCMOS33} [get_ports {gpio_io[7]}]; +set_property -dict {PACKAGE_PIN V14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[8]}]; +set_property -dict {PACKAGE_PIN V12 IOSTANDARD LVCMOS33} [get_ports {gpio_io[9]}]; +set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS33} [get_ports {gpio_io[10]}]; + +##Buttons +set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports {gpio_io[0]}]; #IO_L9P_T1_DQS_14 Sch=btnc +set_property -dict {PACKAGE_PIN M18 IOSTANDARD LVCMOS33} [get_ports {gpio_io[1]}]; #IO_L4N_T0_D05_14 Sch=btnu +set_property -dict {PACKAGE_PIN P17 IOSTANDARD LVCMOS33} [get_ports {gpio_io[2]}]; #IO_L12P_T1_MRCC_14 Sch=btnl +set_property -dict {PACKAGE_PIN M17 IOSTANDARD LVCMOS33} [get_ports {gpio_io[3]}]; #IO_L10N_T1_D15_14 Sch=btnr +set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports {gpio_io[4]}]; #IO_L9N_T1_DQS_D13_14 Sch=btnd + +##7 segment display +set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports { gpio_io[11] }]; +set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33} [get_ports { gpio_io[12] }]; +set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33} [get_ports { gpio_io[13] }]; +set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33} [get_ports { gpio_io[14] }]; +set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports { pdm2pcm_clk_io }]; +set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33} [get_ports { pdm2pcm_pdm_io }]; +set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33} [get_ports { i2s_sck_io }]; +set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports { i2s_ws_io }]; +set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33} [get_ports { i2s_sd_io }]; +set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[15] }]; #IO_L23P_T3_FOE_B_15 Sch=an[0] +set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[16] }]; #IO_L23N_T3_FWE_B_15 Sch=an[1] +set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { gpio_io[17] }]; #IO_L24P_T3_A01_D17_14 Sch=an[2] +set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { spi2_csb_o[0] }]; #IO_L19P_T3_A22_15 Sch=an[3] +set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { spi2_csb_o[1] }]; #IO_L8N_T1_D12_14 Sch=an[4] +set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { spi2_sck_o }]; #IO_L14P_T2_SRCC_14 Sch=an[5] +set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { spi2_sd_io[0] }]; #IO_L23P_T3_35 Sch=an[6] + + +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_tck_i_IBUF] + diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/constraints.xdc b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/constraints.xdc index 5a3c1c4b..38e2f6b3 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/constraints.xdc +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/constraints.xdc @@ -1 +1 @@ -set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets x_heep_system_i/pad_ring_i/pad_clk_i/xilinx_iobuf_i/O] +create_clock -add -name sys_clk_pin -period 8.00 -waveform {0 5} [get_ports {clk_i}]; diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/pin_assign.xdc b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/pin_assign.xdc index 116323f2..9f8f7ded 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/pin_assign.xdc +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/pynq-z2/pin_assign.xdc @@ -2,84 +2,97 @@ # Solderpad Hardware License, Version 2.1, see LICENSE.md for details. # SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# Clock signal set_property -dict {PACKAGE_PIN H16 IOSTANDARD LVCMOS33} [get_ports clk_i] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_tck_i_IBUF] + set_property -dict {PACKAGE_PIN L19 IOSTANDARD LVCMOS33} [get_ports rst_i] -set_property -dict {PACKAGE_PIN M14 IOSTANDARD LVCMOS33} [get_ports rst_led] -set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports clk_led] -set_property -dict {PACKAGE_PIN W9 IOSTANDARD LVCMOS33} [get_ports clk_out] + +# LEDs +set_property -dict {PACKAGE_PIN M14 IOSTANDARD LVCMOS33} [get_ports rst_led_o] +set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports clk_led_o] set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVCMOS33} [get_ports exit_valid_o] set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports exit_value_o] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets rst_led_OBUF] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_out_OBUF] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_led_OBUF] + +# Switches set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS33} [get_ports execute_from_flash_i] set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS33} [get_ports boot_select_i] -## Pmoda -## RPi GPIO 7-0 are shared with pmoda_rpi_gpio_tri_io[7:0] - +# FLASH # QSPI # Q0 / MOSI # Q1 / MISO # Q2 / nWP # Q3 / nHLD +set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports spi_flash_csb_o] ; # Pmoda[4] +set_property -dict {PACKAGE_PIN Y18 IOSTANDARD LVCMOS33} [get_ports spi_flash_sck_o] ; # Pmoda[0] +set_property -dict {PACKAGE_PIN U19 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[0]}] ; # Pmoda[5] +set_property -dict {PACKAGE_PIN Y19 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[1]}] ; # Pmoda[1] +set_property -dict {PACKAGE_PIN W18 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[2]}] ; # Pmoda[6] +set_property -dict {PACKAGE_PIN Y16 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[3]}] ; # Pmoda[2] -set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports spi_flash_csb_o] -set_property -dict {PACKAGE_PIN Y18 IOSTANDARD LVCMOS33} [get_ports spi_flash_sck_o] -set_property -dict {PACKAGE_PIN U19 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[0]}] -set_property -dict {PACKAGE_PIN Y19 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[1]}] -set_property -dict {PACKAGE_PIN W18 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[2]}] -set_property -dict {PACKAGE_PIN Y16 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[3]}] -#set_property -dict {PACKAGE_PIN Y17 IOSTANDARD LVCMOS33} [get_ports {crst}] -set_property -dict {PACKAGE_PIN W19 IOSTANDARD LVCMOS33} [get_ports jtag_trst_ni] +# UART +set_property -dict {PACKAGE_PIN W14 IOSTANDARD LVCMOS33} [get_ports uart_tx_o] ; # Pmodb[0] +set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports uart_rx_i] ; # Pmodb[4] -set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports spi_csb_o] -set_property -dict {PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports spi_sck_o] -set_property -dict {PACKAGE_PIN T12 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[0]}] -set_property -dict {PACKAGE_PIN W15 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[1]}] -set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[2]}] -set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[3]}] +# JTAG +set_property -dict {PACKAGE_PIN Y14 IOSTANDARD LVCMOS33} [get_ports jtag_tdi_i] ; # Pmob[1] +set_property -dict {PACKAGE_PIN V12 IOSTANDARD LVCMOS33} [get_ports jtag_tdo_o] ; # Pmodb[6] +set_property -dict {PACKAGE_PIN T11 IOSTANDARD LVCMOS33} [get_ports jtag_tms_i] ; # Pmodb[2] +set_property -dict {PACKAGE_PIN W16 IOSTANDARD LVCMOS33} [get_ports jtag_tck_i] ; # Pmodb[5] +set_property -dict {PACKAGE_PIN W19 IOSTANDARD LVCMOS33} [get_ports jtag_trst_ni] ; # Pmoda[7] -## Pmodb -set_property -dict {PACKAGE_PIN W14 IOSTANDARD LVCMOS33} [get_ports uart_tx_o] -set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports uart_rx_i] -set_property -dict {PACKAGE_PIN Y14 IOSTANDARD LVCMOS33} [get_ports jtag_tdi_i] -set_property -dict {PACKAGE_PIN V12 IOSTANDARD LVCMOS33} [get_ports jtag_tdo_o] -set_property -dict {PACKAGE_PIN T11 IOSTANDARD LVCMOS33} [get_ports jtag_tms_i] -set_property -dict {PACKAGE_PIN W16 IOSTANDARD LVCMOS33} [get_ports jtag_tck_i] +# I2C +set_property -dict {PACKAGE_PIN W13 IOSTANDARD LVCMOS33} [get_ports {i2c_scl_io}] ; # Pmodb[7] +set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports {i2c_sda_io}] ; # Pmodb[3] -set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[0]}] -set_property -dict {PACKAGE_PIN Y8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[1]}] -set_property -dict {PACKAGE_PIN W8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[2]}] -set_property -dict {PACKAGE_PIN Y7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[3]}] -set_property -dict {PACKAGE_PIN Y6 IOSTANDARD LVCMOS33} [get_ports {gpio_io[4]}] -set_property -dict {PACKAGE_PIN U12 IOSTANDARD LVCMOS33} [get_ports {gpio_io[5]}] -set_property -dict {PACKAGE_PIN W10 IOSTANDARD LVCMOS33} [get_ports {gpio_io[6]}] -set_property -dict {PACKAGE_PIN V10 IOSTANDARD LVCMOS33} [get_ports {gpio_io[7]}] -set_property -dict {PACKAGE_PIN V8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[8]}] -set_property -dict {PACKAGE_PIN U8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[9]}] -set_property -dict {PACKAGE_PIN V7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[10]}] -set_property -dict {PACKAGE_PIN U7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[11]}] -set_property -dict {PACKAGE_PIN V6 IOSTANDARD LVCMOS33} [get_ports {gpio_io[12]}] -set_property -dict {PACKAGE_PIN U13 IOSTANDARD LVCMOS33} [get_ports {gpio_io[13]}] -set_property -dict {PACKAGE_PIN V13 IOSTANDARD LVCMOS33} [get_ports {gpio_io[14]}] -set_property -dict {PACKAGE_PIN Y9 IOSTANDARD LVCMOS33} [get_ports {pdm2pcm_clk_io}] -set_property -dict {PACKAGE_PIN A20 IOSTANDARD LVCMOS33} [get_ports {pdm2pcm_pdm_io}] -set_property -dict {PACKAGE_PIN B19 IOSTANDARD LVCMOS33} [get_ports {i2s_sck_io}] -set_property -dict {PACKAGE_PIN B20 IOSTANDARD LVCMOS33} [get_ports {i2s_ws_io}] -set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports {i2s_sd_io}] +# SPI SD +set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports spi_csb_o] ; # arduino_direct_spi_ss_io +set_property -dict {PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports spi_sck_o] ; # arduino_direct_spi_sck_io +set_property -dict {PACKAGE_PIN T12 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[0]}] ; # arduino_direct_spi_io0_io +set_property -dict {PACKAGE_PIN W15 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[1]}] ; # arduino_direct_spi_io1_io +set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[2]}] ; # arduino_gpio_tri_io[12] +set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports {spi_sd_io[3]}] ; # arduino_gpio_tri_io[13] -## Tri-color LD5 for TARGET_PYNQ_Z2 -set_property -dict {PACKAGE_PIN M15 IOSTANDARD LVCMOS33} [get_ports {gpio_io[15]}] -set_property -dict {PACKAGE_PIN G14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[16]}] -set_property -dict {PACKAGE_PIN L14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[17]}] +# GPIOs +set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[0]}] ; # arduino_gpio_tri_io[0] +set_property -dict {PACKAGE_PIN Y8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[1]}] ; # rpi_gpio_tri_io[11] +set_property -dict {PACKAGE_PIN W8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[2]}] ; # rpi_gpio_tri_io[5] +set_property -dict {PACKAGE_PIN Y7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[3]}] ; # rpi_gpio_tri_io[16] +set_property -dict {PACKAGE_PIN Y6 IOSTANDARD LVCMOS33} [get_ports {gpio_io[4]}] ; # rpi_gpio_tri_io[7] +set_property -dict {PACKAGE_PIN U12 IOSTANDARD LVCMOS33} [get_ports {gpio_io[5]}] ; # arduino_gpio_tri_io[1] +set_property -dict {PACKAGE_PIN W10 IOSTANDARD LVCMOS33} [get_ports {gpio_io[6]}] ; # rpi_gpio_tri_io[3] +set_property -dict {PACKAGE_PIN V10 IOSTANDARD LVCMOS33} [get_ports {gpio_io[7]}] ; # rpi_gpio_tri_io[1] +set_property -dict {PACKAGE_PIN V8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[8]}] ; # rpi_gpio_tri_io[2] +set_property -dict {PACKAGE_PIN U8 IOSTANDARD LVCMOS33} [get_ports {gpio_io[9]}] ; # rpi_gpio_tri_io[14] +set_property -dict {PACKAGE_PIN V7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[10]}] ; # rpi_gpio_tri_io[19] +set_property -dict {PACKAGE_PIN U7 IOSTANDARD LVCMOS33} [get_ports {gpio_io[11]}] ; # rpi_gpio_tri_io[9] +set_property -dict {PACKAGE_PIN V6 IOSTANDARD LVCMOS33} [get_ports {gpio_io[12]}] ; # rpi_gpio_tri_io[6] +set_property -dict {PACKAGE_PIN U13 IOSTANDARD LVCMOS33} [get_ports {gpio_io[13]}] ; # arduino_gpio_tri_io[2] +set_property -dict {PACKAGE_PIN V13 IOSTANDARD LVCMOS33} [get_ports {gpio_io[14]}] ; # arduino_gpio_tri_io[3] -set_property -dict {PACKAGE_PIN W6 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_o[0]}] -set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_o[1]}] -set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {spi2_sck_o}] -set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_0_io}] -set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_1_io}] -set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_2_io}] -set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_3_io}] -set_property -dict {PACKAGE_PIN W13 IOSTANDARD LVCMOS33} [get_ports {i2c_scl_io}] -set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports {i2c_sda_io}] +# PDM2PCM +set_property -dict {PACKAGE_PIN Y9 IOSTANDARD LVCMOS33} [get_ports {pdm2pcm_clk_io}] ; # rpi_gpio_tri_io[13] +set_property -dict {PACKAGE_PIN A20 IOSTANDARD LVCMOS33} [get_ports {pdm2pcm_pdm_io}] ; # rpi_gpio_tri_io[12] -set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_tck_i_IBUF] +# I2S +set_property -dict {PACKAGE_PIN B19 IOSTANDARD LVCMOS33} [get_ports {i2s_sck_io}] ; # rpi_gpio_tri_io[8] +set_property -dict {PACKAGE_PIN B20 IOSTANDARD LVCMOS33} [get_ports {i2s_ws_io}] ; # rpi_gpio_tri_io[4] +set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports {i2s_sd_io}] ; # arduino_direct_iic_scl_io + +# SPI2 +set_property -dict {PACKAGE_PIN W6 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_o[0]}] ; # rpi_gpio_tri_io[15] +set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports {spi2_csb_o[1]}] ; # arduino_gpio_tri_io[5] +set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {spi2_sck_o}] ; # rpi_gpio_tri_io[10] +set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[0]}] ; # arduino__gpio_tri_io[8] +set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[1]}] ; # arduino_gpio_tri_io[9] +set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[2]}] ; # arduino_gpio_tri_io[10] +set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports {spi2_sd_io[3]}] ; # arduino_gpio_tri_io[11] +# Tri-color LEDs for TARGET_PYNQ_Z2 +set_property -dict {PACKAGE_PIN M15 IOSTANDARD LVCMOS33} [get_ports {gpio_io[15]}] ; # rgbleds_6bits_tri_o[5] +set_property -dict {PACKAGE_PIN G14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[16]}] ; # rgbled_6bits_tri_o[3] +set_property -dict {PACKAGE_PIN L14 IOSTANDARD LVCMOS33} [get_ports {gpio_io[17]}] ; # rgbleds_6bits_tri_o[4] diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/zcu104/pin_assign.xdc b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/zcu104/pin_assign.xdc new file mode 100644 index 00000000..4b523cdf --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/constraints/zcu104/pin_assign.xdc @@ -0,0 +1,99 @@ +# Copyright 2022 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +# CLOCK +set_property -dict {PACKAGE_PIN AH18 IOSTANDARD DIFF_SSTL12} [get_ports clk_300mhz_p] +set_property -dict {PACKAGE_PIN AH17 IOSTANDARD DIFF_SSTL12} [get_ports clk_300mhz_n] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_tck_i] + +# RESET +set_property -dict {PACKAGE_PIN M11 IOSTANDARD LVCMOS33} [get_ports rst_i] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets rst_i] + +# LEDS +set_property -dict {PACKAGE_PIN D5 IOSTANDARD LVCMOS33} [get_ports rst_led_o] +set_property -dict {PACKAGE_PIN D6 IOSTANDARD LVCMOS33} [get_ports clk_led_o] +set_property -dict {PACKAGE_PIN A5 IOSTANDARD LVCMOS33} [get_ports exit_valid_o] +set_property -dict {PACKAGE_PIN B5 IOSTANDARD LVCMOS33} [get_ports exit_value_o] + +# SWITCHES +set_property -dict {PACKAGE_PIN E4 IOSTANDARD LVCMOS33} [get_ports execute_from_flash_i] +set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33} [get_ports boot_select_i] + +# FLASH +# QSPI +# Q0 / MOSI +# Q1 / MISO +# Q2 / nWP +# Q3 / nHLD +set_property -dict {PACKAGE_PIN L10 IOSTANDARD LVCMOS33} [get_ports spi_flash_csb_o] +set_property -dict {PACKAGE_PIN J9 IOSTANDARD LVCMOS33} [get_ports spi_flash_sck_o] +set_property -dict {PACKAGE_PIN M10 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[0]}] +set_property -dict {PACKAGE_PIN K9 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[1]}] +set_property -dict {PACKAGE_PIN M8 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[2]}] +set_property -dict {PACKAGE_PIN K8 IOSTANDARD LVCMOS33} [get_ports {spi_flash_sd_io[3]}] + +# UART +set_property -dict {PACKAGE_PIN G8 IOSTANDARD LVCMOS33} [get_ports uart_tx_o] +set_property -dict {PACKAGE_PIN G6 IOSTANDARD LVCMOS33} [get_ports uart_rx_i] + +# JTAG +set_property -dict {PACKAGE_PIN H8 IOSTANDARD LVCMOS33} [get_ports jtag_tdi_i] +set_property -dict {PACKAGE_PIN J6 IOSTANDARD LVCMOS33} [get_ports jtag_tdo_o] +set_property -dict {PACKAGE_PIN G7 IOSTANDARD LVCMOS33} [get_ports jtag_tms_i] +set_property -dict {PACKAGE_PIN H6 IOSTANDARD LVCMOS33} [get_ports jtag_tck_i] +set_property -dict {PACKAGE_PIN M9 IOSTANDARD LVCMOS33} [get_ports jtag_trst_ni] + +# I2C +set_property -dict {PACKAGE_PIN J7 IOSTANDARD LVCMOS33} [get_ports i2c_scl_io] +set_property -dict {PACKAGE_PIN H7 IOSTANDARD LVCMOS33} [get_ports i2c_sda_io] + +## The following pins are sent to the FMC connector, using the LA pins as single-ended. +## The bank only supports up to 1.8 V. + +# SPI SD +set_property -dict {PACKAGE_PIN H19 IOSTANDARD LVCMOS18} [get_ports spi_csb_o] +set_property -dict {PACKAGE_PIN G19 IOSTANDARD LVCMOS18} [get_ports spi_sck_o] +set_property -dict {PACKAGE_PIN L15 IOSTANDARD LVCMOS18} [get_ports {spi_sd_io[0]}] +set_property -dict {PACKAGE_PIN K15 IOSTANDARD LVCMOS18} [get_ports {spi_sd_io[1]}] +set_property -dict {PACKAGE_PIN C13 IOSTANDARD LVCMOS18} [get_ports {spi_sd_io[2]}] +set_property -dict {PACKAGE_PIN C12 IOSTANDARD LVCMOS18} [get_ports {spi_sd_io[3]}] + +# GPIOs +set_property -dict {PACKAGE_PIN D11 IOSTANDARD LVCMOS18} [get_ports {gpio_io[0]}] +set_property -dict {PACKAGE_PIN D10 IOSTANDARD LVCMOS18} [get_ports {gpio_io[1]}] +set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS18} [get_ports {gpio_io[2]}] +set_property -dict {PACKAGE_PIN A7 IOSTANDARD LVCMOS18} [get_ports {gpio_io[3]}] +set_property -dict {PACKAGE_PIN H18 IOSTANDARD LVCMOS18} [get_ports {gpio_io[4]}] +set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS18} [get_ports {gpio_io[5]}] +set_property -dict {PACKAGE_PIN K17 IOSTANDARD LVCMOS18} [get_ports {gpio_io[6]}] +set_property -dict {PACKAGE_PIN J17 IOSTANDARD LVCMOS18} [get_ports {gpio_io[7]}] +set_property -dict {PACKAGE_PIN H16 IOSTANDARD LVCMOS18} [get_ports {gpio_io[8]}] +set_property -dict {PACKAGE_PIN G16 IOSTANDARD LVCMOS18} [get_ports {gpio_io[9]}] +set_property -dict {PACKAGE_PIN G15 IOSTANDARD LVCMOS18} [get_ports {gpio_io[10]}] +set_property -dict {PACKAGE_PIN F15 IOSTANDARD LVCMOS18} [get_ports {gpio_io[11]}] +set_property -dict {PACKAGE_PIN F11 IOSTANDARD LVCMOS18} [get_ports {gpio_io[12]}] +set_property -dict {PACKAGE_PIN E10 IOSTANDARD LVCMOS18} [get_ports {gpio_io[13]}] +set_property -dict {PACKAGE_PIN B11 IOSTANDARD LVCMOS18} [get_ports {gpio_io[14]}] +set_property -dict {PACKAGE_PIN A11 IOSTANDARD LVCMOS18} [get_ports {gpio_io[15]}] +set_property -dict {PACKAGE_PIN B9 IOSTANDARD LVCMOS18} [get_ports {gpio_io[16]}] +set_property -dict {PACKAGE_PIN B8 IOSTANDARD LVCMOS18} [get_ports {gpio_io[17]}] + +# PDM2PCM +set_property -dict {PACKAGE_PIN K19 IOSTANDARD LVCMOS18} [get_ports pdm2pcm_clk_io] +set_property -dict {PACKAGE_PIN K18 IOSTANDARD LVCMOS18} [get_ports pdm2pcm_pdm_io] + +# I2S +set_property -dict {PACKAGE_PIN E18 IOSTANDARD LVCMOS18} [get_ports i2s_sck_io] +set_property -dict {PACKAGE_PIN E17 IOSTANDARD LVCMOS18} [get_ports i2s_ws_io] +set_property -dict {PACKAGE_PIN G18 IOSTANDARD LVCMOS18} [get_ports i2s_sd_io] + +# SPI2 +set_property -dict {PACKAGE_PIN F18 IOSTANDARD LVCMOS18} [get_ports {spi2_csb_o[0]}] +set_property -dict {PACKAGE_PIN D17 IOSTANDARD LVCMOS18} [get_ports {spi2_csb_o[1]}] +set_property -dict {PACKAGE_PIN C17 IOSTANDARD LVCMOS18} [get_ports spi2_sck_o] +set_property -dict {PACKAGE_PIN F12 IOSTANDARD LVCMOS18} [get_ports {spi2_sd_io[0]}] +set_property -dict {PACKAGE_PIN E12 IOSTANDARD LVCMOS18} [get_ports {spi2_sd_io[1]}] +set_property -dict {PACKAGE_PIN H13 IOSTANDARD LVCMOS18} [get_ports {spi2_sd_io[2]}] +set_property -dict {PACKAGE_PIN H12 IOSTANDARD LVCMOS18} [get_ports {spi2_sd_io[3]}] diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/pad_cell_inout_xilinx.sv b/hw/vendor/esl_epfl_x_heep/hw/fpga/pad_cell_inout_xilinx.sv index 69ee4e7e..5c68364b 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/pad_cell_inout_xilinx.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/pad_cell_inout_xilinx.sv @@ -3,7 +3,8 @@ // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 module pad_cell_inout #( - parameter PADATTR = 16 + parameter PADATTR = 16, + parameter core_v_mini_mcu_pkg::pad_side_e SIDE = core_v_mini_mcu_pkg::TOP ) ( input logic pad_in_i, input logic pad_oe_i, diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/pad_cell_input_xilinx.sv b/hw/vendor/esl_epfl_x_heep/hw/fpga/pad_cell_input_xilinx.sv index 989aad1c..470a651a 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/pad_cell_input_xilinx.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/pad_cell_input_xilinx.sv @@ -3,7 +3,8 @@ // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 module pad_cell_input #( - parameter PADATTR = 16 + parameter PADATTR = 16, + parameter core_v_mini_mcu_pkg::pad_side_e SIDE = core_v_mini_mcu_pkg::TOP ) ( input logic pad_in_i, input logic pad_oe_i, diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/pad_cell_output_xilinx.sv b/hw/vendor/esl_epfl_x_heep/hw/fpga/pad_cell_output_xilinx.sv index 3620ad1b..43592acd 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/pad_cell_output_xilinx.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/pad_cell_output_xilinx.sv @@ -3,7 +3,8 @@ // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 module pad_cell_output #( - parameter PADATTR = 16 + parameter PADATTR = 16, + parameter core_v_mini_mcu_pkg::pad_side_e SIDE = core_v_mini_mcu_pkg::TOP ) ( input logic pad_in_i, input logic pad_oe_i, diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/prim_xilinx_clk.sv b/hw/vendor/esl_epfl_x_heep/hw/fpga/prim_xilinx_clk.sv index 349920c1..2893d666 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/prim_xilinx_clk.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/prim_xilinx_clk.sv @@ -9,15 +9,12 @@ module xilinx_clk_gating ( output logic clk_o ); - logic clk_en; - - // Use a latch based clock gate instead of BUFGCE. Otherwise we quickly run out of BUFGCTRL cells on the FPGAs. - always_latch begin - if (clk_i == 1'b0) clk_en <= en_i | test_en_i; - end - - assign clk_o = clk_i & clk_en; - + // In Zynq7000, just bypass the clock gating because there are not enough BUFGs that can be + // cascaded with the BUFG of the MMCM. + // In the Zynq UltraScale+, it can be implemented as BUFGCE without trouble, since there + // are > 500 BUFGCEs and the rules for cascading are more relaxed. + // NOTE: This **cannot** be substituted by a latch+and + assign clk_o = clk_i; endmodule @@ -158,3 +155,12 @@ module tc_clk_xor2 ( assign clk_o = clk0_i ^ clk1_i; endmodule + +module tc_clk_inverter ( + input logic clk_i, + output logic clk_o +); + + xilinx_clk_inverter clk_inv_i (.*); + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/generate_sram.tcl.tpl b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/generate_sram.tcl.tpl new file mode 100644 index 00000000..e8e6cbb4 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/generate_sram.tcl.tpl @@ -0,0 +1,50 @@ +% for num_words in xheep.iter_bank_numwords(): + +set ipName xilinx_mem_gen_${num_words} + +create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 -module_name $ipName + +set_property -dict [list CONFIG.Enable_32bit_Address {false} \\ + + CONFIG.Use_Byte_Write_Enable {true} \\ + + CONFIG.Byte_Size {8} \\ + + CONFIG.Algorithm {Minimum_Area} \\ + + CONFIG.Primitive {2kx9} \\ + + CONFIG.Write_Width_A {32} \\ + + CONFIG.Write_Depth_A {${num_words}} \\ + + CONFIG.Read_Width_A {32} \\ + + CONFIG.Enable_A {Use_ENA_Pin} \\ + + CONFIG.Write_Width_B {32} \\ + + CONFIG.Read_Width_B {32} \\ + + CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \\ + + CONFIG.Use_RSTA_Pin {false} \\ + + CONFIG.EN_SAFETY_CKT {false}] [get_ips $ipName] + +#generate_target {instantiation_template} [get_ips $ipName] + +#export_ip_user_files -of_objects [get_ips $ipName] -no_script -sync -force -quiet + +create_ip_run [get_ips $ipName] + +% endfor + +<%ips = "" +for num_words in xheep.iter_bank_numwords(): + ips += f" xilinx_mem_gen_{num_words}_synth_1"%> +launch_runs -jobs 8 ${ips} + +% for num_words in xheep.iter_bank_numwords(): +wait_on_run xilinx_mem_gen_${num_words}_synth_1 +% endfor diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/nexys/xilinx_generate_clk_wizard.tcl b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/nexys/xilinx_generate_clk_wizard.tcl new file mode 100644 index 00000000..69dff9c3 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/nexys/xilinx_generate_clk_wizard.tcl @@ -0,0 +1,43 @@ +# Copyright 2022 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# Define design macros + +set design_name xilinx_clk_wizard +set in_clk_freq_MHz 100 +set out_clk_freq_MHz 15 + + +# Create block design +create_bd_design $design_name + +# Create ports +set clk_100MHz [ create_bd_port -dir I -type clk -freq_hz [ expr $in_clk_freq_MHz * 1000000 ] clk_100MHz ] +set clk_out1_0 [ create_bd_port -dir O -type clk clk_out1_0 ] +set_property -dict [ list CONFIG.FREQ_HZ [ expr $out_clk_freq_MHz * 1000000 ] ] $clk_out1_0 + +# Create instance and set properties +set clk_wiz_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 ] +set_property -dict [ list \ + CONFIG.CLKOUT1_JITTER {333.843} \ + CONFIG.CLKOUT1_PHASE_ERROR {293.793} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {15} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {49.875} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {66.500} \ + CONFIG.PRIM_IN_FREQ $in_clk_freq_MHz \ + CONFIG.USE_LOCKED {false} \ + CONFIG.USE_RESET {false} \ +] $clk_wiz_0 + +# Create port connections +connect_bd_net -net clk_in1_0_1 [ get_bd_ports clk_100MHz ] [ get_bd_pins clk_wiz_0/clk_in1 ] +connect_bd_net -net clk_wiz_0_clk_out1 [ get_bd_ports clk_out1_0 ] [ get_bd_pins clk_wiz_0/clk_out1 ] + +# Save and close block design +save_bd_design +close_bd_design $design_name + +# create wrapper +set wrapper_path [ make_wrapper -fileset sources_1 -files [ get_files -norecurse xilinx_clk_wizard.bd ] -top ] +add_files -norecurse -fileset sources_1 $wrapper_path diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/pynq-z2/xilinx_generate_clk_wizard.tcl b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/pynq-z2/xilinx_generate_clk_wizard.tcl new file mode 100644 index 00000000..e61c5832 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/pynq-z2/xilinx_generate_clk_wizard.tcl @@ -0,0 +1,44 @@ +# Copyright 2022 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# Define design macros + +set design_name xilinx_clk_wizard +set in_clk_freq_MHz 125 +set out_clk_freq_MHz 15 + + +# Create block design +create_bd_design $design_name + +# Create ports +set clk_125MHz [ create_bd_port -dir I -type clk -freq_hz [ expr $in_clk_freq_MHz * 1000000 ] clk_125MHz ] +set clk_out1_0 [ create_bd_port -dir O -type clk clk_out1_0 ] +set_property -dict [ list CONFIG.FREQ_HZ [ expr $out_clk_freq_MHz * 1000000 ] ] $clk_out1_0 + +# Create instance and set properties +set clk_wiz_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 ] +set_property -dict [ list \ + CONFIG.CLKIN1_JITTER_PS {80.0} \ + CONFIG.CLKOUT1_JITTER {172.798} \ + CONFIG.CLKOUT1_PHASE_ERROR {96.948} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {15} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {8.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {8.000} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {50.000} \ + CONFIG.PRIM_IN_FREQ $in_clk_freq_MHz \ + CONFIG.USE_LOCKED {false} \ + CONFIG.USE_RESET {false} \ +] $clk_wiz_0 + +# Create port connections +connect_bd_net -net clk_in1_0_1 [ get_bd_ports clk_125MHz ] [ get_bd_pins clk_wiz_0/clk_in1 ] +connect_bd_net -net clk_wiz_0_clk_out1 [ get_bd_ports clk_out1_0 ] [ get_bd_pins clk_wiz_0/clk_out1 ] + +# Save and close block design +save_bd_design +close_bd_design $design_name + +# create wrapper +set wrapper_path [ make_wrapper -fileset sources_1 -files [ get_files -norecurse xilinx_clk_wizard.bd ] -top ] +add_files -norecurse -fileset sources_1 $wrapper_path diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/zcu104/xilinx_generate_clk_wizard.tcl b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/zcu104/xilinx_generate_clk_wizard.tcl new file mode 100644 index 00000000..d67e4054 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/scripts/zcu104/xilinx_generate_clk_wizard.tcl @@ -0,0 +1,40 @@ +# Copyright 2022 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# Define design macros + +set design_name xilinx_clk_wizard + +# Create block design +create_bd_design $design_name + +# Create instance and set properties +create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 +set_property -dict [list \ + CONFIG.CLKIN1_JITTER_PS {33.330000000000005} \ + CONFIG.CLKOUT1_JITTER {282.792} \ + CONFIG.CLKOUT1_PHASE_ERROR {207.545} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {15} \ + CONFIG.CLK_IN1_BOARD_INTERFACE {clk_300mhz} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {32.875} \ + CONFIG.MMCM_CLKIN1_PERIOD {3.333} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {65.750} \ + CONFIG.MMCM_DIVCLK_DIVIDE {10} \ + CONFIG.OPTIMIZE_CLOCKING_STRUCTURE_EN {true} \ + CONFIG.PRIM_SOURCE {Differential_clock_capable_pin} \ + CONFIG.USE_LOCKED {false} \ + CONFIG.USE_RESET {true} \ +] [get_bd_cells clk_wiz_0] + +# Create ports +make_bd_pins_external [get_bd_cells clk_wiz_0] +make_bd_intf_pins_external [get_bd_cells clk_wiz_0] + +# Save and close block design +save_bd_design +close_bd_design $design_name + +# Create wrapper +set wrapper_path [ make_wrapper -fileset sources_1 -files [ get_files -norecurse xilinx_clk_wizard.bd ] -top ] +add_files -norecurse -fileset sources_1 $wrapper_path diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/sram_wrapper.sv b/hw/vendor/esl_epfl_x_heep/hw/fpga/sram_wrapper.sv.tpl similarity index 66% rename from hw/vendor/esl_epfl_x_heep/hw/fpga/sram_wrapper.sv rename to hw/vendor/esl_epfl_x_heep/hw/fpga/sram_wrapper.sv.tpl index 44fb5687..6d518136 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/sram_wrapper.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/sram_wrapper.sv.tpl @@ -22,19 +22,32 @@ module sram_wrapper #( input logic [AddrWidth-1:0] addr_i, input logic [31:0] wdata_i, input logic [3:0] be_i, - input logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] set_retentive_ni, + // power manager signals that goes to the ASIC macros + input logic pwrgate_ni, + output logic pwrgate_ack_no, + input logic set_retentive_ni, // output ports output logic [31:0] rdata_o ); - xilinx_mem_gen_0 tc_ram_i ( - .clka (clk_i), - .ena (req_i), - .wea ({4{req_i & we_i}} & be_i), - .addra(addr_i), - .dina (wdata_i), - // output ports - .douta(rdata_o) - ); +assign pwrgate_ack_no = pwrgate_ni; +<%el = ""%> +% for num_words in xheep.iter_bank_numwords(): + ${el}if (NumWords == 32'd${num_words}) begin + xilinx_mem_gen_${num_words} tc_ram_i ( + .clka (clk_i), + .ena (req_i), + .wea ({4{req_i & we_i}} & be_i), + .addra(addr_i), + .dina (wdata_i), + // output ports + .douta(rdata_o) + ); + end +<%el = "else "%> +% endfor + else begin + $error("Bank size not generated."); + end endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv b/hw/vendor/esl_epfl_x_heep/hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv index 1324bfb1..343bda8e 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv @@ -13,13 +13,16 @@ module xilinx_core_v_mini_mcu_wrapper parameter CLK_LED_COUNT_LENGTH = 27 ) ( +`ifdef FPGA_ZCU104 + inout logic clk_300mhz_n, + inout logic clk_300mhz_p, +`else inout logic clk_i, +`endif inout logic rst_i, - //visibility signals - output logic rst_led, - output logic clk_led, - output logic clk_out, + output logic rst_led_o, + output logic clk_led_o, inout logic boot_select_i, inout logic execute_from_flash_i, @@ -33,7 +36,7 @@ module xilinx_core_v_mini_mcu_wrapper inout logic uart_rx_i, inout logic uart_tx_o, - inout logic [19:0] gpio_io, + inout logic [17:0] gpio_io, output logic exit_value_o, inout logic exit_valid_o, @@ -46,10 +49,7 @@ module xilinx_core_v_mini_mcu_wrapper inout logic spi_csb_o, inout logic spi_sck_o, - inout logic spi2_sd_0_io, - inout logic spi2_sd_1_io, - inout logic spi2_sd_2_io, - inout logic spi2_sd_3_io, + inout logic [3:0] spi2_sd_io, inout logic [1:0] spi2_csb_o, inout logic spi2_sck_o, @@ -71,13 +71,17 @@ module xilinx_core_v_mini_mcu_wrapper logic [CLK_LED_COUNT_LENGTH - 1:0] clk_count; // low active reset - assign rst_n = !rst_i; +`ifdef FPGA_NEXYS + assign rst_n = rst_i; +`else + assign rst_n = !rst_i; +`endif // reset LED for debugging - assign rst_led = rst_n; + assign rst_led_o = rst_n; // counter to blink an LED - assign clk_led = clk_count[CLK_LED_COUNT_LENGTH-1]; + assign clk_led_o = clk_count[CLK_LED_COUNT_LENGTH-1]; always_ff @(posedge clk_gen or negedge rst_n) begin : clk_count_process if (!rst_n) begin @@ -90,13 +94,23 @@ module xilinx_core_v_mini_mcu_wrapper // eXtension Interface if_xif #() ext_if (); - // clock output for debugging - assign clk_out = clk_gen; - +`ifdef FPGA_ZCU104 + xilinx_clk_wizard_wrapper xilinx_clk_wizard_wrapper_i ( + .CLK_IN1_D_0_clk_n(clk_300mhz_n), + .CLK_IN1_D_0_clk_p(clk_300mhz_p), + .clk_out1_0(clk_gen) + ); +`elsif FPGA_NEXYS + xilinx_clk_wizard_wrapper xilinx_clk_wizard_wrapper_i ( + .clk_100MHz(clk_i), + .clk_out1_0(clk_gen) + ); +`else // FPGA PYNQ-Z2 xilinx_clk_wizard_wrapper xilinx_clk_wizard_wrapper_i ( .clk_125MHz(clk_i), .clk_out1_0(clk_gen) ); +`endif x_heep_system #( .X_EXT(X_EXT), @@ -119,16 +133,18 @@ module xilinx_core_v_mini_mcu_wrapper .ext_core_data_resp_i('0), .ext_debug_master_req_o(), .ext_debug_master_resp_i('0), - .ext_dma_read_ch0_req_o(), - .ext_dma_read_ch0_resp_i('0), - .ext_dma_write_ch0_req_o(), - .ext_dma_write_ch0_resp_i('0), - .ext_dma_addr_ch0_req_o(), - .ext_dma_addr_ch0_resp_i('0), + .ext_dma_read_req_o(), + .ext_dma_read_resp_i('0), + .ext_dma_write_req_o(), + .ext_dma_write_resp_i('0), + .ext_dma_addr_req_o(), + .ext_dma_addr_resp_i('0), .ext_peripheral_slave_req_o(), .ext_peripheral_slave_resp_i('0), + .ext_ao_peripheral_req_i('0), + .ext_ao_peripheral_resp_o(), .external_subsystem_powergate_switch_no(), - .external_subsystem_powergate_switch_ack_ni(), + .external_subsystem_powergate_switch_ack_ni('0), .external_subsystem_powergate_iso_no(), .external_subsystem_rst_no(), .external_ram_banks_set_retentive_no(), @@ -180,10 +196,10 @@ module xilinx_core_v_mini_mcu_wrapper .spi_sck_io(spi_sck_o), .i2c_scl_io, .i2c_sda_io, - .spi2_sd_0_io(spi2_sd_0_io), - .spi2_sd_1_io(spi2_sd_1_io), - .spi2_sd_2_io(spi2_sd_2_io), - .spi2_sd_3_io(spi2_sd_3_io), + .spi2_sd_0_io(spi2_sd_io[0]), + .spi2_sd_1_io(spi2_sd_io[1]), + .spi2_sd_2_io(spi2_sd_io[2]), + .spi2_sd_3_io(spi2_sd_io[3]), .spi2_cs_0_io(spi2_csb_o[0]), .spi2_cs_1_io(spi2_csb_o[1]), .spi2_sck_io(spi2_sck_o), @@ -191,7 +207,9 @@ module xilinx_core_v_mini_mcu_wrapper .pdm2pcm_pdm_io, .i2s_sck_io(i2s_sck_io), .i2s_ws_io(i2s_ws_io), - .i2s_sd_io(i2s_sd_io) + .i2s_sd_io(i2s_sd_io), + .ext_dma_slot_tx_i('0), + .ext_dma_slot_rx_i('0) ); assign exit_value_o = exit_value[0]; diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/README.md b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/README.md index dc07aef1..65b4b051 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/README.md +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/README.md @@ -1,33 +1,5 @@ ## boot_rom -1. If you haven't done it yet, install [Conda](https://phoenixnap.com/kb/how-to-install-anaconda-ubuntu-18-04-or-20-04) as described in the link, -and create the Conda enviroment with python 2.7: - -```bash -conda update conda -conda env create -f environment.yml -``` - -Activate the environment with - -```bash -conda activate boot_rom -``` - -If you are already in the core-v-mini-mcu conda env, deactivate it first: - -```bash -conda deactivate -``` - -2. Install the required Python tools: - -``` -pip install --user -r python-requirements.txt -``` - -3. Generate the boot_rom: - If you modified the `boot_rom.S` file, generate it as: ``` diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.S b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.S index f154eec4..7b0fab66 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.S +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.S @@ -99,7 +99,7 @@ _wait_spi_ready_tx_init: _wait_spi_ready_read_prog: lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) bgez a5, _wait_spi_ready_read_prog - li a3, 1024 # 1KB copy size + li a3, 2048 # 2KB copy size li s1, 0 # dst ptr (ram) // For loop until the 1KB copy from flash to ram is done diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.dump b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.dump index c4a74476..025800d8 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.dump +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.dump @@ -6,14 +6,14 @@ Disassembly of section .text: 00000000 : 0: 200405b7 lui a1,0x20040 - 4: 0005c503 lbu a0,0(a1) # 20040000 <_end+0x2003ff16> + 4: 0005c503 lbu a0,0(a1) # 20040000 <_end+0x2003ff14> 8: c119 beqz a0,e a: 41c8 lw a0,4(a1) c: 9502 jalr a0 0000000e : e: 200005b7 lui a1,0x20000 - 12: 0085c503 lbu a0,8(a1) # 20000008 <_end+0x1fffff1e> + 12: 0085c503 lbu a0,8(a1) # 20000008 <_end+0x1fffff1c> 16: e511 bnez a0,22 <_jump_to_flash> 00000018 <_jump_to_debug_rom>: @@ -31,7 +31,7 @@ Disassembly of section .text: 2c: 4505 li a0,1 2e: c188 sw a0,0(a1) 30: 400005b7 lui a1,0x40000 - 34: 18058593 addi a1,a1,384 # 40000180 <_end+0x40000096> + 34: 18058593 addi a1,a1,384 # 40000180 <_end+0x40000094> 38: 9582 jalr a1 0000003a <_copy_from_flash>: @@ -73,41 +73,42 @@ Disassembly of section .text: 0000008a <_wait_spi_ready_read_prog>: 8a: 49dc lw a5,20(a1) 8c: fe07dfe3 bgez a5,8a <_wait_spi_ready_read_prog> - 90: 40000693 li a3,1024 - 94: 4481 li s1,0 - 96: 10000b13 li s6,256 - 9a: 09000437 lui s0,0x9000 - 9e: 0ff40a93 addi s5,s0,255 # 90000ff <_end+0x9000015> - -000000a2 <_32B_chunk_loop>: - a2: 00db4663 blt s6,a3,ae <_read_32B_chunk> - a6: 08000437 lui s0,0x8000 - aa: 0ff40a93 addi s5,s0,255 # 80000ff <_end+0x8000015> - -000000ae <_read_32B_chunk>: - ae: 0355a223 sw s5,36(a1) # 20020024 <_end+0x2001ff3a> - b2: 0001 nop - -000000b4 <_wait_spi_ready_read_32B_chunk>: - b4: 49dc lw a5,20(a1) - b6: fe07dfe3 bgez a5,b4 <_wait_spi_ready_read_32B_chunk> - ba: 10048b93 addi s7,s1,256 - -000000be <_wait_spi_rxwm_8_words>: - be: 49dc lw a5,20(a1) - c0: 83d1 srli a5,a5,0x14 - c2: 8b85 andi a5,a5,1 - c4: dfed beqz a5,be <_wait_spi_rxwm_8_words> - c6: 02048613 addi a2,s1,32 - -000000ca <_spi_fifo_read_8_words>: - ca: 0285a883 lw a7,40(a1) - ce: 0114a023 sw a7,0(s1) - d2: 0491 addi s1,s1,4 - d4: fec49be3 bne s1,a2,ca <_spi_fifo_read_8_words> - d8: ff7493e3 bne s1,s7,be <_wait_spi_rxwm_8_words> - dc: f0068693 addi a3,a3,-256 - e0: f2e9 bnez a3,a2 <_32B_chunk_loop> - e2: 200005b7 lui a1,0x20000 - e6: 4990 lw a2,16(a1) - e8: 9602 jalr a2 + 90: 6685 lui a3,0x1 + 92: 80068693 addi a3,a3,-2048 # 800 <_end+0x714> + 96: 4481 li s1,0 + 98: 10000b13 li s6,256 + 9c: 09000437 lui s0,0x9000 + a0: 0ff40a93 addi s5,s0,255 # 90000ff <_end+0x9000013> + +000000a4 <_32B_chunk_loop>: + a4: 00db4663 blt s6,a3,b0 <_read_32B_chunk> + a8: 08000437 lui s0,0x8000 + ac: 0ff40a93 addi s5,s0,255 # 80000ff <_end+0x8000013> + +000000b0 <_read_32B_chunk>: + b0: 0355a223 sw s5,36(a1) # 20020024 <_end+0x2001ff38> + b4: 0001 nop + +000000b6 <_wait_spi_ready_read_32B_chunk>: + b6: 49dc lw a5,20(a1) + b8: fe07dfe3 bgez a5,b6 <_wait_spi_ready_read_32B_chunk> + bc: 10048b93 addi s7,s1,256 + +000000c0 <_wait_spi_rxwm_8_words>: + c0: 49dc lw a5,20(a1) + c2: 83d1 srli a5,a5,0x14 + c4: 8b85 andi a5,a5,1 + c6: dfed beqz a5,c0 <_wait_spi_rxwm_8_words> + c8: 02048613 addi a2,s1,32 + +000000cc <_spi_fifo_read_8_words>: + cc: 0285a883 lw a7,40(a1) + d0: 0114a023 sw a7,0(s1) + d4: 0491 addi s1,s1,4 + d6: fec49be3 bne s1,a2,cc <_spi_fifo_read_8_words> + da: ff7493e3 bne s1,s7,c0 <_wait_spi_rxwm_8_words> + de: f0068693 addi a3,a3,-256 + e2: f2e9 bnez a3,a4 <_32B_chunk_loop> + e4: 200005b7 lui a1,0x20000 + e8: 4990 lw a2,16(a1) + ea: 9602 jalr a2 diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.h b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.h index 8f0e3d2b..bbb8198a 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.h +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.h @@ -39,27 +39,27 @@ uint32_t reset_vec[reset_vec_size] = { 0xd1d8070d, 0x49dc0001, 0xfe07dfe3, - 0x40000693, - 0x0b134481, - 0x04371000, - 0x0a930900, - 0x46630ff4, - 0x043700db, - 0x0a930800, - 0xa2230ff4, - 0x00010355, - 0xdfe349dc, - 0x8b93fe07, - 0x49dc1004, - 0x8b8583d1, - 0x8613dfed, - 0xa8830204, - 0xa0230285, - 0x04910114, - 0xfec49be3, - 0xff7493e3, - 0xf0068693, - 0x05b7f2e9, - 0x49902000, - 0x00009602 + 0x86936685, + 0x44818006, + 0x10000b13, + 0x09000437, + 0x0ff40a93, + 0x00db4663, + 0x08000437, + 0x0ff40a93, + 0x0355a223, + 0x49dc0001, + 0xfe07dfe3, + 0x10048b93, + 0x83d149dc, + 0xdfed8b85, + 0x02048613, + 0x0285a883, + 0x0114a023, + 0x9be30491, + 0x93e3fec4, + 0x8693ff74, + 0xf2e9f006, + 0x200005b7, + 0x96024990 }; diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.sv index 07c74e3a..93983a15 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/boot_rom.sv @@ -26,29 +26,29 @@ module boot_rom logic [RomSize-1:0][31:0] mem; assign mem = { - 32'h00009602, - 32'h49902000, - 32'h05b7f2e9, - 32'hf0068693, - 32'hff7493e3, - 32'hfec49be3, - 32'h04910114, - 32'ha0230285, - 32'ha8830204, - 32'h8613dfed, - 32'h8b8583d1, - 32'h49dc1004, - 32'h8b93fe07, - 32'hdfe349dc, - 32'h00010355, - 32'ha2230ff4, - 32'h0a930800, - 32'h043700db, - 32'h46630ff4, - 32'h0a930900, - 32'h04371000, - 32'h0b134481, - 32'h40000693, + 32'h96024990, + 32'h200005b7, + 32'hf2e9f006, + 32'h8693ff74, + 32'h93e3fec4, + 32'h9be30491, + 32'h0114a023, + 32'h0285a883, + 32'h02048613, + 32'hdfed8b85, + 32'h83d149dc, + 32'h10048b93, + 32'hfe07dfe3, + 32'h49dc0001, + 32'h0355a223, + 32'h0ff40a93, + 32'h08000437, + 32'h00db4663, + 32'h0ff40a93, + 32'h09000437, + 32'h10000b13, + 32'h44818006, + 32'h86936685, 32'hfe07dfe3, 32'h49dc0001, 32'hd1d8070d, diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/environment.yml b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/environment.yml deleted file mode 100644 index 260ecf9a..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/environment.yml +++ /dev/null @@ -1,6 +0,0 @@ -name: boot_rom -channels: - - defaults -dependencies: - - python=2.7.18 - diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/gen_rom.py b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/gen_rom.py index b52e22bd..b1a79b57 100755 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/gen_rom.py +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/boot_rom/gen_rom.py @@ -89,9 +89,8 @@ def read_bin(): with open(filename + ".img", 'rb') as f: - rom = binascii.hexlify(f.read()) - rom = map(''.join, zip(rom[::2], rom[1::2])) - + rom = bytes.hex(f.read()) + rom = list(map(''.join, zip(rom[::2], rom[1::2]))) # align to 32 bit align = (int((len(rom) + 3) / 4 )) * 4; diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/data/dma.hjson b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/data/dma.hjson index d37d92f7..4f144c61 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/data/dma.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/data/dma.hjson @@ -33,13 +33,23 @@ { bits: "31:0", name: "PTR_ADDR", desc: "Address data pointer (word aligned) - used only in Address mode" } ] }, - { name: "SIZE", - desc: "Number of bytes to copy - Once a value is written, the copy starts", + { name: "SIZE_D1", + desc: "Number of elements to copy from, defined with respect to the first dimension - Once a value is written, the copy starts", swaccess: "rw", hwaccess: "hro", hwqe: "true", // enable `qe` latched signal of software write pulse + // Dimensioned to 16 bits to allow for 64kB transfers on 1D fields: [ - { bits: "31:0", name: "SIZE", desc: "DMA counter and start" } + { bits: "15:0", name: "SIZE", desc: "DMA counter D1 and start" } + ] + }, + { name: "SIZE_D2", + desc: "Number of elements to copy from, defined with respect to the second dimension", + swaccess: "rw", + hwaccess: "hro", + // Dimensioned to 16 bits to allow for 64kB transfers on 2D + fields: [ + { bits: "15:0", name: "SIZE", desc: "DMA counter D2" } ] }, { name: "STATUS", @@ -50,23 +60,56 @@ hwre: "true", // enable `re` latched signal of software read pulse resval: 1, fields: [ - { bits: "0", name: "READY", desc: "Transaction iss done"}, + { bits: "0", name: "READY", desc: "Transaction is done"}, { bits: "1", name: "WINDOW_DONE", desc: "set if DMA is copying second half"}, ] }, - { name: "PTR_INC", - desc: "Increment number of src/dst pointer every time a word is copied", + { name: "SRC_PTR_INC_D1", + desc: "Increment the D1 source pointer every time a word is copied", swaccess: "rw", hwaccess: "hro", + // Dimensioned to allow a maximum of a 15 element stride for a data_type_word case fields: [ - { bits: "7:0", - name: "SRC_PTR_INC", - desc: "Source pointer increment", + { bits: "5:0", + name: "INC", + desc: "Source pointer d1 increment", resval:4 - }, - { bits: "15:8", - name: "DST_PTR_INC", - desc: "Destination pointer increment", + } + ] + }, + { name: "SRC_PTR_INC_D2", + desc: "Increment the D2 source pointer every time a word is copied", + swaccess: "rw", + hwaccess: "hro", + // Dimensioned to allow a maximum of 15 element stride for a data_type_word + fields: [ + { bits: "22:0", + name: "INC", + desc: "Source pointer d2 increment", + resval:4 + } + ] + }, + { name: "DST_PTR_INC_D1", + desc: "Increment the D1 destination pointer every time a word is copied", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "5:0", + name: "INC", + desc: "Destination pointer d1 increment", + resval:4 + } + ] + }, + { name: "DST_PTR_INC_D2", + desc: "Increment the D2 destination pointer every time a word is copied", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "22:0", + name: "INC", + desc: "Destination pointer d2 increment", resval:4 } ] @@ -74,7 +117,7 @@ { name: "SLOT", desc: '''The DMA will wait for the signal connected to the selected trigger_slots to be high - on the read and write side respectivly''', + on the read and write side respectively''', swaccess: "rw", hwaccess: "hro", resval: 0, @@ -87,8 +130,25 @@ } ] }, - { name: "DATA_TYPE", - desc: '''Width/type of the data to transfer''', + { name: "SRC_DATA_TYPE", + desc: '''Width/type of the source data to transfer''', + swaccess: "rw", + hwaccess: "hro", + resval: 0, + fields: [ + { bits: "1:0", name: "DATA_TYPE", + desc: "Data type", + enum: [ + { value: "0", name: "DMA_32BIT_WORD", desc: "Transfers 32 bits"}, + { value: "1", name: "DMA_16BIT_WORD", desc: "Transfers 16 bits"}, + { value: "2", name: "DMA_8BIT_WORD" , desc: "Transfers 8 bits"}, + { value: "3", name: "DMA_8BIT_WORD_2",desc: "Transfers 8 bits"}, + ] + } + ] + }, + { name: "DST_DATA_TYPE", + desc: '''Width/type of the destination data to transfer''', swaccess: "rw", hwaccess: "hro", resval: 0, @@ -104,10 +164,27 @@ } ] }, + { + name: "SIGN_EXT", + desc: '''Is the data to be sign extended? (Checked only if the dst data type is wider than the src data type)''', + swaccess: "rw", + hwaccess: "hro", + resval: 0, + fields: [ + { bits: "0", name: "SIGNED", + desc: "Extend the sign to the destination data", + enum: [ + { value: "0", name: "NO_EXTEND", desc: "Does not extend the sign"}, + { value: "1", name: "EXTEND", desc: "Extends the sign"}, + ] + } + ] + }, { name: "MODE", desc: '''Set the operational mode of the DMA''', swaccess: "rw", hwaccess: "hro", + resval: 0, fields: [ { bits: "1:0", name: "MODE", desc: "DMA operation mode", @@ -119,24 +196,78 @@ } ] }, + { name: "DIM_CONFIG", + desc: '''Set the dimensionality of the DMA''', + swaccess: "rw", + hwaccess: "hro", + resval: 0, + fields: [ + { bits: "0", name: "DMA_DIM", desc: "DMA transfer dimensionality"} + ] + }, + { name: "DIM_INV", + desc: '''DMA dimensionality inversion selector''', + swaccess: "rw", + hwaccess: "hro", + resval: 0, + fields: [ + { bits: "0", name: "SEL", desc: "DMA dimensionality inversion, used to perform transposition"} + ] + }, + { name: "PAD_TOP", + desc: '''Set the top padding''', + swaccess: "rw", + hwaccess: "hro", + resval: 0, + fields: [ + { bits: "5:0", name: "PAD", desc: "Top margin padding (2D)"} + ] + }, + { name: "PAD_BOTTOM", + desc: '''Set the bottom padding''', + swaccess: "rw", + hwaccess: "hro", + resval: 0, + fields: [ + { bits: "5:0", name: "PAD", desc: "Bottom margin padding (2D)"} + ] + }, + { name: "PAD_RIGHT", + desc: '''Set the right padding''', + swaccess: "rw", + hwaccess: "hro", + resval: 0, + fields: [ + { bits: "5:0", name: "PAD", desc: "Right margin padding (1D/2D)"} + ] + }, + { name: "PAD_LEFT", + desc: '''Set the left padding''', + swaccess: "rw", + hwaccess: "hro", + resval: 0, + fields: [ + { bits: "5:0", name: "PAD", desc: "Left margin padding (1D/2D)"} + ] + }, { name: "WINDOW_SIZE", desc: '''Will trigger a every "WINDOW_SIZE" writes Set to 0 to disable.''', swaccess: "rw", hwaccess: "hro", + resval: 0, fields: [ - { bits: "31:0", name: "WINDOW_SIZE", desc: ""} + { bits: "12:0", name: "WINDOW_SIZE", desc: ""} ] }, { name: "WINDOW_COUNT", desc: '''Number of times the end of the window was reached since the beginning. Reset at start''', swaccess: "ro", - // hwext: "true", hwaccess: "hrw", resval: 0, fields: [ - { bits: "31:0", name: "WINDOW_COUNT", desc: "Number of windows transferred in the transaction" } + { bits: "7:0", name: "WINDOW_COUNT", desc: "Number of windows transferred in the transaction" } ] }, { name: "INTERRUPT_EN", @@ -144,10 +275,33 @@ (Only the interrupt with the lowest id will be triggered)''', swaccess: "rw", hwaccess: "hro", + resval: 0, fields: [ { bits: "0", name: "TRANSACTION_DONE", desc: "Enables transaction done interrupt" } { bits: "1", name: "WINDOW_DONE", desc: "Enables window done interrupt" } ] + }, + { name: "TRANSACTION_IFR", + desc: '''Interrupt Flag Register for transactions''', + swaccess: "ro", + hwaccess: "hrw", + hwext: "true", + hwre: "true", // latched signal of software write pulse + resval: 0, + fields: [ + { bits: "0", name: "FLAG", desc: "Set for transaction done interrupt" } + ] + }, + { name: "WINDOW_IFR", + desc: '''Interrupt Flag Register for windows''', + swaccess: "ro", + hwaccess: "hrw", + hwext: "true", + hwre: "true", // latched signal of software write pulse + resval: 0, + fields: [ + { bits: "0", name: "FLAG", desc: "Set for window done interrupt" } + ] } - ] + ] } diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/dma.core b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/dma.core index 0a06c35d..0bf343e7 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/dma.core +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/dma.core @@ -1,7 +1,7 @@ CAPI=2: name: "x-heep:ip:dma" -description: "core-v-mini-mcu dma peripheral" +description: "core-v-mini-mcu dma channel" # Copyright 2021 OpenHW Group # Solderpad Hardware License, Version 2.1, see LICENSE.md for details. @@ -14,6 +14,10 @@ filesets: files: - rtl/dma_reg_pkg.sv - rtl/dma_reg_top.sv + - rtl/dma_padding_fsm.sv + - rtl/dma_obiread_fsm.sv + - rtl/dma_obiread_addr_fsm.sv + - rtl/dma_obiwrite_fsm.sv - rtl/dma.sv file_type: systemVerilogSource diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/dma.vlt b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/dma.vlt index 1034666a..70cee9b4 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/dma.vlt +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/dma.vlt @@ -7,8 +7,13 @@ lint_off -rule DECLFILENAME -file "*/dma_reg_top.sv" lint_off -rule WIDTH -file "*/rtl/dma_reg_top.sv" -match "Operator ASSIGNW expects *" +lint_off -rule WIDTH -file "*/rtl/dma.sv" -match "Operator ASSIGNW expects *" lint_off -rule UNUSED -file "*/rtl/dma.sv" -match "Signal is not used: 'data_out_rvalid'" lint_off -rule UNUSED -file "*/rtl/dma.sv" -match "Signal is not used: 'data_out_rdata'" +lint_off -rule UNUSED -file "*/rtl/dma_obiread_fsm.sv" -match "Bits of signal are not used: *" +lint_off -rule UNUSED -file "*/rtl/dma_obiwrite_fsm.sv" -match "Bits of signal are not used: *" +lint_off -rule UNUSED -file "*/rtl/dma_obiread_addr_fsm.sv" -match "Bits of signal are not used: *" +lint_off -rule UNUSED -file "*/rtl/dma_padding_fsm.sv" -match "Bits of signal are not used: *" lint_off -rule UNUSED -file "*/rtl/dma.sv" -match "Bits of signal are not used: *" diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma.sv index c4f5e2ea..923b5a1f 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma.sv @@ -1,8 +1,10 @@ -// Copyright 2022 EPFL -// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 - -// DMA assume a read request is not granted before previous request rvalid is asserted +/* + * Copyright 2024 EPFL + * Solderpad Hardware License, Version 2.1, see LICENSE.md for details. + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Info: Direct Memory Access (DMA) channel module. + */ module dma #( parameter int unsigned FIFO_DEPTH = 4, @@ -14,103 +16,134 @@ module dma #( ) ( input logic clk_i, input logic rst_ni, + input logic clk_gate_en_ni, + + input logic ext_dma_stop_i, input reg_req_t reg_req_i, output reg_rsp_t reg_rsp_o, - output obi_req_t dma_read_ch0_req_o, - input obi_resp_t dma_read_ch0_resp_i, + output obi_req_t dma_read_req_o, + input obi_resp_t dma_read_resp_i, - output obi_req_t dma_write_ch0_req_o, - input obi_resp_t dma_write_ch0_resp_i, + output obi_req_t dma_write_req_o, + input obi_resp_t dma_write_resp_i, - output obi_req_t dma_addr_ch0_req_o, - input obi_resp_t dma_addr_ch0_resp_i, + output obi_req_t dma_addr_req_o, + input obi_resp_t dma_addr_resp_i, input logic [SLOT_NUM-1:0] trigger_slot_i, output dma_done_intr_o, - output dma_window_intr_o + output dma_window_intr_o, + + output dma_done_o ); import dma_reg_pkg::*; + + /*_________________________________________________________________________________________________________________________________ */ + + /* Parameter definition */ + localparam int unsigned LastFifoUsage = FIFO_DEPTH - 1; localparam int unsigned Addr_Fifo_Depth = (FIFO_DEPTH > 1) ? $clog2(FIFO_DEPTH) : 1; - dma_reg2hw_t reg2hw; - dma_hw2reg_t hw2reg; - - logic [ 31:0] read_ptr_reg; - logic [ 31:0] addr_ptr_reg; - logic [ 31:0] read_ptr_valid_reg; - logic [ 31:0] write_ptr_reg; - logic [ 31:0] write_address; - logic [ 31:0] dma_cnt; - logic [ 31:0] dma_addr_cnt; - logic [ 2:0] dma_cnt_dec; - logic dma_start; - logic dma_done; - logic dma_window_event; - - logic window_done_q; - - logic [Addr_Fifo_Depth-1:0] fifo_usage; - logic fifo_alm_full; - - logic [Addr_Fifo_Depth-1:0] fifo_addr_usage; - logic fifo_addr_alm_full; - - logic data_in_req; - logic data_in_we; - logic [ 3:0] data_in_be; - logic [ 31:0] data_in_addr; - logic data_in_gnt; - logic data_in_rvalid; - logic [ 31:0] data_in_rdata; - - logic data_addr_in_req; - logic data_addr_in_we; - logic [ 3:0] data_addr_in_be; - logic [ 31:0] data_addr_in_addr; - logic data_addr_in_gnt; - logic data_addr_in_rvalid; - logic [ 31:0] data_addr_in_rdata; - - logic data_out_req; - logic data_out_we; - logic [ 3:0] data_out_be; - logic [ 31:0] data_out_addr; - logic [ 31:0] data_out_wdata; - logic data_out_gnt; - logic data_out_rvalid; - logic [ 31:0] data_out_rdata; - - logic fifo_flush; - logic fifo_full; - logic fifo_empty; - - logic fifo_addr_flush; - logic fifo_addr_full; - logic fifo_addr_empty, fifo_addr_empty_check; - - logic wait_for_rx; - logic wait_for_tx; - - logic [ 1:0] data_type; - - logic [31:0] fifo_input; - logic [31:0] fifo_addr_input; - logic [31:0] fifo_output; - logic [31:0] fifo_addr_output; - - logic [ 3:0] byte_enable_out; - - logic circular_mode; - logic address_mode; - - logic dma_start_pending; - + /*_________________________________________________________________________________________________________________________________ */ + + /* Signals declaration */ + + /* Gated clock */ + logic clk_cg; + + /* Registers */ + dma_reg2hw_t reg2hw; + dma_hw2reg_t hw2reg; + + /* General signals */ + logic dma_padding_fsm_on; + logic padding_fsm_done; + + logic dma_start; + logic dma_done; + logic dma_window_event; + + logic window_done_q; + + logic data_in_req; + logic data_in_we; + logic [3:0] data_in_be; + logic [31:0] data_in_addr; + logic data_in_gnt; + logic data_in_rvalid; + logic [31:0] data_in_rdata; + + logic data_addr_in_req; + logic data_addr_in_we; + logic [3:0] data_addr_in_be; + logic [31:0] data_addr_in_addr; + logic data_addr_in_gnt; + logic data_addr_in_rvalid; + logic [31:0] data_addr_in_rdata; + + logic data_out_req; + logic data_out_we; + logic [3:0] data_out_be; + logic [31:0] data_out_addr; + logic [31:0] data_out_wdata; + logic data_out_gnt; + logic data_out_rvalid; + logic [31:0] data_out_rdata; + + /* Interrupt Flag Register signals */ + logic transaction_ifr; + logic dma_done_intr_n; + logic dma_done_intr; + logic window_ifr; + logic dma_window_intr; + logic dma_window_intr_n; + + /* FIFO signals */ + logic [Addr_Fifo_Depth-1:0] read_fifo_usage; + logic [Addr_Fifo_Depth-1:0] read_addr_fifo_usage; + logic [Addr_Fifo_Depth-1:0] write_fifo_usage; + + logic fifo_flush; + logic read_fifo_full; + logic read_fifo_empty; + logic read_fifo_alm_full; + logic read_fifo_pop; + logic [31:0] read_fifo_input; + logic [31:0] read_fifo_output; + + logic read_addr_fifo_full; + logic read_addr_fifo_empty; + logic read_addr_fifo_alm_full; + logic [31:0] read_addr_fifo_output; + + logic write_fifo_full; + logic write_fifo_empty; + logic write_fifo_alm_full; + logic write_fifo_push; + logic write_fifo_pop; + logic [31:0] write_fifo_input; + logic [31:0] write_fifo_output; + + /* Trigger signals */ + logic wait_for_rx; + logic wait_for_tx; + + /* Datatypes */ + typedef enum logic [1:0] { + DMA_DATA_TYPE_WORD, + DMA_DATA_TYPE_HALF_WORD, + DMA_DATA_TYPE_BYTE, + DMA_DATA_TYPE_BYTE_ + } dma_data_type_t; + + + /* FSM states */ enum { DMA_READY, DMA_STARTING, @@ -118,77 +151,195 @@ module dma #( } dma_state_q, dma_state_d; - logic [Addr_Fifo_Depth-1:0] outstanding_req, outstanding_addr_req; + logic circular_mode; + logic address_mode; - enum logic { - DMA_READ_FSM_IDLE, - DMA_READ_FSM_ON - } - dma_read_fsm_state, dma_read_fsm_n_state, dma_read_addr_fsm_state, dma_read_addr_fsm_n_state; + logic dma_start_pending; - enum logic { - DMA_WRITE_FSM_IDLE, - DMA_WRITE_FSM_ON - } - dma_write_fsm_state, dma_write_fsm_n_state; - - assign dma_read_ch0_req_o.req = data_in_req; - assign dma_read_ch0_req_o.we = data_in_we; - assign dma_read_ch0_req_o.be = data_in_be; - assign dma_read_ch0_req_o.addr = data_in_addr; - assign dma_read_ch0_req_o.wdata = 32'h0; + logic [31:0] window_counter; - assign data_in_gnt = dma_read_ch0_resp_i.gnt; - assign data_in_rvalid = dma_read_ch0_resp_i.rvalid; - assign data_in_rdata = dma_read_ch0_resp_i.rdata; + /*_________________________________________________________________________________________________________________________________ */ - assign dma_addr_ch0_req_o.req = data_addr_in_req; - assign dma_addr_ch0_req_o.we = data_addr_in_we; - assign dma_addr_ch0_req_o.be = data_addr_in_be; - assign dma_addr_ch0_req_o.addr = data_addr_in_addr; - assign dma_addr_ch0_req_o.wdata = 32'h0; + /* Module instantiation */ - assign data_addr_in_gnt = dma_addr_ch0_resp_i.gnt; - assign data_addr_in_rvalid = dma_addr_ch0_resp_i.rvalid; - assign data_addr_in_rdata = dma_addr_ch0_resp_i.rdata; + /* Clock gating cell */ - assign dma_write_ch0_req_o.req = data_out_req; - assign dma_write_ch0_req_o.we = data_out_we; - assign dma_write_ch0_req_o.be = data_out_be; - assign dma_write_ch0_req_o.addr = data_out_addr; - assign dma_write_ch0_req_o.wdata = data_out_wdata; +`ifndef FPGA_SYNTHESIS +`ifndef VERILATOR + tc_clk_gating clk_gating_cell ( + .clk_i, + .en_i(clk_gate_en_ni), + .test_en_i(1'b0), + .clk_o(clk_cg) + ); - assign data_out_gnt = dma_write_ch0_resp_i.gnt; - assign data_out_rvalid = dma_write_ch0_resp_i.rvalid; - assign data_out_rdata = dma_write_ch0_resp_i.rdata; +`else + assign clk_cg = clk_i & clk_gate_en_ni; +`endif - assign dma_done_intr_o = dma_done & reg2hw.interrupt_en.transaction_done.q; - assign dma_window_intr_o = dma_window_event & reg2hw.interrupt_en.window_done.q; +`else + assign clk_cg = clk_i & clk_gate_en_ni; +`endif - logic [31:0] window_counter; + /* Read FIFO */ + fifo_v3 #( + .DEPTH(FIFO_DEPTH), + .FALL_THROUGH(1'b1) + ) dma_read_fifo_i ( + .clk_i(clk_cg), + .rst_ni, + .flush_i(fifo_flush), + .testmode_i(1'b0), + // status flags + .full_o(read_fifo_full), + .empty_o(read_fifo_empty), + .usage_o(read_fifo_usage), + // as long as the queue is not full we can push new data + .data_i(read_fifo_input), + .push_i(data_in_rvalid), + // as long as the queue is not empty we can pop new elements + .data_o(read_fifo_output), + .pop_i(read_fifo_pop) + ); - assign data_type = reg2hw.data_type.q; + /* Read address mode FIFO */ + fifo_v3 #( + .DEPTH(FIFO_DEPTH), + .FALL_THROUGH(1'b1) + ) dma_read_addr_fifo_i ( + .clk_i(clk_cg), + .rst_ni, + .flush_i(fifo_flush), + .testmode_i(1'b0), + // status flags + .full_o(read_addr_fifo_full), + .empty_o(read_addr_fifo_empty), + .usage_o(read_addr_fifo_usage), + // as long as the queue is not full we can push new data + .data_i(data_addr_in_rdata), + .push_i(data_addr_in_rvalid), + // as long as the queue is not empty we can pop new elements + .data_o(read_addr_fifo_output), + .pop_i(write_fifo_pop && address_mode) // not an error! + ); - assign hw2reg.status.ready.d = (dma_state_q == DMA_READY); + /* Write FIFO */ + fifo_v3 #( + .DEPTH(FIFO_DEPTH), + .FALL_THROUGH(1'b1) + ) dma_write_fifo_i ( + .clk_i(clk_cg), + .rst_ni, + .flush_i(fifo_flush), + .testmode_i(1'b0), + // status flags + .full_o(write_fifo_full), + .empty_o(write_fifo_empty), + .usage_o(write_fifo_usage), + // as long as the queue is not full we can push new data + .data_i(write_fifo_input), + .push_i(write_fifo_push), + // as long as the queue is not empty we can pop new elements + .data_o(write_fifo_output), + .pop_i(write_fifo_pop) + ); - assign hw2reg.status.window_done.d = window_done_q; + dma_reg_top #( + .reg_req_t(reg_req_t), + .reg_rsp_t(reg_rsp_t) + ) dma_reg_top_i ( + .clk_i(clk_cg), + .rst_ni, + .reg_req_i, + .reg_rsp_o, + .reg2hw, + .hw2reg, + .devmode_i(1'b1) + ); - assign circular_mode = reg2hw.mode.q == 1; - assign address_mode = reg2hw.mode.q == 2; + /* Read FSM */ + dma_obiread_fsm dma_obiread_fsm_i ( + .clk_i(clk_cg), + .rst_ni, + .reg2hw_i(reg2hw), + .dma_start_i(dma_start), + .dma_done_i(dma_done), + .ext_dma_stop_i, + .read_fifo_full_i(read_fifo_full), + .read_fifo_alm_full_i(read_fifo_alm_full), + .wait_for_rx_i(wait_for_rx), + .data_in_gnt_i(data_in_gnt), + .data_in_rvalid_i(data_in_rvalid), + .data_in_rdata_i(data_in_rdata), + .fifo_input_o(read_fifo_input), + .data_in_req_o(data_in_req), + .data_in_we_o(data_in_we), + .data_in_be_o(data_in_be), + .data_in_addr_o(data_in_addr), + .read_fifo_flush_o(fifo_flush) + ); - assign write_address = address_mode ? fifo_addr_output : write_ptr_reg; + /* Read address FSM */ + dma_obiread_addr_fsm dma_obiread_addr_fsm_i ( + .clk_i(clk_cg), + .rst_ni, + .reg2hw_i(reg2hw), + .dma_start_i(dma_start), + .ext_dma_stop_i, + .read_fifo_addr_full_i(read_addr_fifo_full), + .read_fifo_addr_alm_full_i(read_addr_fifo_alm_full), + .address_mode_i(address_mode), + .data_in_gnt_i(data_addr_in_gnt), + .data_addr_in_req_o(data_addr_in_req), + .data_addr_in_we_o(data_addr_in_we), + .data_addr_in_be_o(data_addr_in_be), + .data_addr_in_addr_o(data_addr_in_addr) + ); - assign wait_for_rx = |(reg2hw.slot.rx_trigger_slot.q[SLOT_NUM-1:0] & (~trigger_slot_i)); - assign wait_for_tx = |(reg2hw.slot.tx_trigger_slot.q[SLOT_NUM-1:0] & (~trigger_slot_i)); + /* DMA padding FSM */ + dma_padding_fsm dma_padding_fsm_i ( + .clk_i(clk_cg), + .rst_ni, + .reg2hw_i(reg2hw), + .dma_padding_fsm_on_i(dma_padding_fsm_on), + .dma_start_i(dma_start), + .read_fifo_empty_i(read_fifo_empty), + .write_fifo_full_i(write_fifo_full), + .write_fifo_alm_full_i(write_fifo_alm_full), + .data_read_i(read_fifo_output), + .padding_fsm_done_o(padding_fsm_done), + .write_fifo_push_o(write_fifo_push), + .read_fifo_pop_o(read_fifo_pop), + .data_write_o(write_fifo_input) + ); - assign fifo_addr_empty_check = fifo_addr_empty && address_mode; + /* Write FSM */ + dma_obiwrite_fsm dma_obiwrite_fsm_i ( + .clk_i(clk_cg), + .rst_ni, + .reg2hw_i(reg2hw), + .dma_start_i(dma_start), + .write_fifo_empty_i(write_fifo_empty), + .read_addr_fifo_empty_i(read_addr_fifo_empty), + .fifo_output_i(write_fifo_output), + .wait_for_tx_i(wait_for_tx), + .address_mode_i(address_mode), + .padding_fsm_done_i(padding_fsm_done), + .fifo_addr_output_i(read_addr_fifo_output), + .data_out_gnt_i(data_out_gnt), + .data_out_req_o(data_out_req), + .data_out_we_o(data_out_we), + .data_out_be_o(data_out_be), + .data_out_addr_o(data_out_addr), + .data_out_wdata_o(data_out_wdata), + .dma_done_o(dma_done) + ); - assign fifo_alm_full = (fifo_usage == LastFifoUsage[Addr_Fifo_Depth-1:0]); - assign fifo_addr_alm_full = (fifo_addr_usage == LastFifoUsage[Addr_Fifo_Depth-1:0]); + /*_________________________________________________________________________________________________________________________________ */ - assign dma_start = (dma_state_q == DMA_STARTING); + /* FSMs instantiation */ // // Main DMA state machine @@ -198,6 +349,7 @@ module dma #( // RUNNING : waiting for transaction finish // when `dma_done` rises either enter ready or restart in circular mode // + always_comb begin dma_state_d = dma_state_q; case (dma_state_q) @@ -218,8 +370,8 @@ module dma #( endcase end - // update state - always_ff @(posedge clk_i, negedge rst_ni) begin + /* Update DMA state */ + always_ff @(posedge clk_cg, negedge rst_ni) begin if (~rst_ni) begin dma_state_q <= DMA_READY; end else begin @@ -227,378 +379,69 @@ module dma #( end end - - // DMA pulse start when dma_start register is written - always_ff @(posedge clk_i or negedge rst_ni) begin : proc_dma_start + /* DMA pulse start when dma_start register is written */ + always_ff @(posedge clk_cg or negedge rst_ni) begin : proc_dma_start if (~rst_ni) begin dma_start_pending <= 1'b0; end else begin if (dma_start == 1'b1) begin dma_start_pending <= 1'b0; - end else if (reg2hw.size.qe & |reg2hw.size.q) begin + end else if ((reg2hw.size_d1.qe & |reg2hw.size_d1.q)) begin dma_start_pending <= 1'b1; end end end - // Store input data pointer and increment everytime read request is granted - always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_in_reg - if (~rst_ni) begin - read_ptr_reg <= '0; - end else begin - if (dma_start == 1'b1) begin - read_ptr_reg <= reg2hw.src_ptr.q; - end else if (data_in_gnt == 1'b1) begin - read_ptr_reg <= read_ptr_reg + {24'h0, reg2hw.ptr_inc.src_ptr_inc.q}; - end - end - end - - // Store address data pointer and increment everytime read request is granted - only in address mode - always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_addr_reg - if (~rst_ni) begin - addr_ptr_reg <= '0; - end else begin - if (dma_start == 1'b1 && address_mode) begin - addr_ptr_reg <= reg2hw.addr_ptr.q; - end else if (data_addr_in_gnt == 1'b1 && address_mode) begin - addr_ptr_reg <= addr_ptr_reg + 32'h4; //always continuos in 32b - end - end - end - - // Only update read_ptr_valid_reg when the data is stored in the fifo - always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_valid_in_reg - if (~rst_ni) begin - read_ptr_valid_reg <= '0; - end else begin - if (dma_start == 1'b1) begin - read_ptr_valid_reg <= reg2hw.src_ptr.q; - end else if (data_in_rvalid == 1'b1) begin - read_ptr_valid_reg <= read_ptr_valid_reg + {24'h0, reg2hw.ptr_inc.src_ptr_inc.q}; - end - end - end - - // Store output data pointer and increment everytime write request is granted - always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_out_reg + /* Transaction IFR update */ + always_ff @(posedge clk_cg, negedge rst_ni) begin : proc_ff_transaction_ifr if (~rst_ni) begin - write_ptr_reg <= '0; - end else begin - if (dma_start == 1'b1) begin - write_ptr_reg <= reg2hw.dst_ptr.q; - end else if (data_out_gnt == 1'b1) begin - write_ptr_reg <= write_ptr_reg + {24'h0, reg2hw.ptr_inc.dst_ptr_inc.q}; + transaction_ifr <= '0; + end else if (reg2hw.interrupt_en.transaction_done.q == 1'b1) begin + // Enter here only if the transaction_done interrupt is enabled + if (dma_done == 1'b1) begin + transaction_ifr <= 1'b1; + end else if (reg2hw.transaction_ifr.re == 1'b1) begin + // If the IFR bit is read, we must clear the transaction_ifr + transaction_ifr <= 1'b0; end end end - // Store dma transfer size and decrement it everytime input data rvalid is asserted - always_ff @(posedge clk_i or negedge rst_ni) begin : proc_dma_cnt_reg + /* Delayed transaction interrupt signals */ + always_ff @(posedge clk_cg, negedge rst_ni) begin : proc_ff_intr if (~rst_ni) begin - dma_cnt <= '0; + dma_done_intr_n <= '0; end else begin - if (dma_start == 1'b1) begin - dma_cnt <= reg2hw.size.q; - end else if (data_in_gnt == 1'b1) begin - dma_cnt <= dma_cnt - {29'h0, dma_cnt_dec}; - end + dma_done_intr_n <= dma_done_intr; end end - // Store dma transfer size for the address port - always_ff @(posedge clk_i or negedge rst_ni) begin : proc_dma_addr_cnt_reg + /* Window IFR update */ + always_ff @(posedge clk_cg, negedge rst_ni) begin : proc_ff_window_ifr if (~rst_ni) begin - dma_addr_cnt <= '0; - end else begin - if (dma_start == 1'b1 && address_mode) begin - dma_addr_cnt <= reg2hw.size.q; - end else if (data_addr_in_gnt == 1'b1 && address_mode) begin - dma_addr_cnt <= dma_addr_cnt - 32'h4; //address always 32b + window_ifr <= '0; + end else if (reg2hw.interrupt_en.window_done.q == 1'b1) begin + // Enter here only if the window_done interrupt is enabled + if (dma_window_event == 1'b1) begin + window_ifr <= 1'b1; + end else if (reg2hw.window_ifr.re == 1'b1) begin + // If the IFR bit is read, we must clear the window_ifr + window_ifr <= 1'b0; end end end - always_comb begin - case (data_type) - 2'b00: dma_cnt_dec = 3'h4; - 2'b01: dma_cnt_dec = 3'h2; - 2'b10, 2'b11: dma_cnt_dec = 3'h1; - endcase - end - - always_comb begin : proc_byte_enable_out - case (data_type) // Data type 00 Word, 01 Half word, 11,10 byte - 2'b00: byte_enable_out = 4'b1111; // Writing a word (32 bits) - - 2'b01: begin // Writing a half-word (16 bits) - case (write_address[1]) - 1'b0: byte_enable_out = 4'b0011; - 1'b1: byte_enable_out = 4'b1100; - endcase - ; // case(write_address[1:0]) - end - - 2'b10, 2'b11: begin // Writing a byte (8 bits) - case (write_address[1:0]) - 2'b00: byte_enable_out = 4'b0001; - 2'b01: byte_enable_out = 4'b0010; - 2'b10: byte_enable_out = 4'b0100; - 2'b11: byte_enable_out = 4'b1000; - endcase - ; // case(write_address[1:0]) - end - endcase - ; // case (data_type) - end - - // Output data shift - always_comb begin : proc_output_data - - data_out_wdata[7:0] = fifo_output[7:0]; - data_out_wdata[15:8] = fifo_output[15:8]; - data_out_wdata[23:16] = fifo_output[23:16]; - data_out_wdata[31:24] = fifo_output[31:24]; - - case (write_address[1:0]) - 2'b00: ; - - 2'b01: data_out_wdata[15:8] = fifo_output[7:0]; - - 2'b10: begin - data_out_wdata[23:16] = fifo_output[7:0]; - data_out_wdata[31:24] = fifo_output[15:8]; - end - - 2'b11: data_out_wdata[31:24] = fifo_output[7:0]; - endcase - end - - assign fifo_addr_input = data_addr_in_rdata; //never misaligned, always 32b - - // Input data shift: shift the input data to be on the LSB of the fifo - always_comb begin : proc_input_data - - fifo_input[7:0] = data_in_rdata[7:0]; - fifo_input[15:8] = data_in_rdata[15:8]; - fifo_input[23:16] = data_in_rdata[23:16]; - fifo_input[31:24] = data_in_rdata[31:24]; - - case (read_ptr_valid_reg[1:0]) - 2'b00: ; - - 2'b01: fifo_input[7:0] = data_in_rdata[15:8]; - - 2'b10: begin - fifo_input[7:0] = data_in_rdata[23:16]; - fifo_input[15:8] = data_in_rdata[31:24]; - end - - 2'b11: fifo_input[7:0] = data_in_rdata[31:24]; - endcase - end - - // FSM state update - always_ff @(posedge clk_i or negedge rst_ni) begin : proc_fsm_state + /* Delayed window interrupt signals */ + always_ff @(posedge clk_cg, negedge rst_ni) begin : proc_ff_window_intr if (~rst_ni) begin - dma_read_fsm_state <= DMA_READ_FSM_IDLE; - dma_write_fsm_state <= DMA_WRITE_FSM_IDLE; - dma_read_addr_fsm_state <= DMA_READ_FSM_IDLE; - outstanding_req <= '0; - outstanding_addr_req <= '0; + dma_window_intr_n <= '0; end else begin - dma_read_fsm_state <= dma_read_fsm_n_state; - dma_write_fsm_state <= dma_write_fsm_n_state; - dma_read_addr_fsm_state <= dma_read_addr_fsm_n_state; - outstanding_req <= outstanding_req + (data_in_req && data_in_gnt) - data_in_rvalid; - - if (address_mode) - outstanding_addr_req <= outstanding_addr_req + (data_addr_in_req && data_addr_in_gnt) - data_addr_in_rvalid; - + dma_window_intr_n <= dma_window_intr; end end - // Read master FSM - always_comb begin : proc_dma_read_fsm_logic - - dma_read_fsm_n_state = DMA_READ_FSM_IDLE; - - data_in_req = '0; - data_in_we = '0; - data_in_be = '0; - data_in_addr = '0; - - fifo_flush = 1'b0; - - unique case (dma_read_fsm_state) - - DMA_READ_FSM_IDLE: begin - // Wait for start signal - if (dma_start == 1'b1) begin - dma_read_fsm_n_state = DMA_READ_FSM_ON; - fifo_flush = 1'b1; - end else begin - dma_read_fsm_n_state = DMA_READ_FSM_IDLE; - end - end - // Read one word - DMA_READ_FSM_ON: begin - // If all input data read exit - if (|dma_cnt == 1'b0) begin - dma_read_fsm_n_state = DMA_READ_FSM_IDLE; - end else begin - dma_read_fsm_n_state = DMA_READ_FSM_ON; - // Wait if fifo is full, almost full (last data), or if the SPI RX does not have valid data (only in SPI mode 1). - if (fifo_full == 1'b0 && fifo_alm_full == 1'b0 && wait_for_rx == 1'b0) begin - data_in_req = 1'b1; - data_in_we = 1'b0; - data_in_be = 4'b1111; // always read all bytes - data_in_addr = read_ptr_reg; - end - end - end - endcase - end - - // Read address master FSM - always_comb begin : proc_dma_addr_read_fsm_logic - - dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE; - - data_addr_in_req = '0; - data_addr_in_we = '0; - data_addr_in_be = '0; - data_addr_in_addr = '0; - fifo_addr_flush = 1'b0; - - unique case (dma_read_addr_fsm_state) - - DMA_READ_FSM_IDLE: begin - // Wait for start signal - if (dma_start == 1'b1 && address_mode) begin - dma_read_addr_fsm_n_state = DMA_READ_FSM_ON; - fifo_addr_flush = 1'b1; - end else begin - dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE; - end - end - // Read one word - DMA_READ_FSM_ON: begin - // If all input data read exit - if (|dma_addr_cnt == 1'b0) begin - dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE; - end else begin - dma_read_addr_fsm_n_state = DMA_READ_FSM_ON; - // Wait if fifo is full, almost full (last data), or if the SPI RX does not have valid data (only in SPI mode 1). - if (fifo_addr_full == 1'b0 && fifo_addr_alm_full == 1'b0) begin - data_addr_in_req = 1'b1; - data_addr_in_we = 1'b0; - data_addr_in_be = 4'b1111; // always read all bytes - data_addr_in_addr = addr_ptr_reg; - end - end - end - endcase - end - - // Write master FSM - always_comb begin : proc_dma_write_fsm_logic - - dma_write_fsm_n_state = DMA_WRITE_FSM_IDLE; - dma_done = 1'b0; - - data_out_req = '0; - data_out_we = '0; - data_out_be = '0; - data_out_addr = '0; - - unique case (dma_write_fsm_state) - - DMA_WRITE_FSM_IDLE: begin - // Wait for start signal - if (dma_start == 1'b1) begin - dma_write_fsm_n_state = DMA_WRITE_FSM_ON; - end else begin - dma_write_fsm_n_state = DMA_WRITE_FSM_IDLE; - end - end - // Read one word - DMA_WRITE_FSM_ON: begin - // If all input data read exit - if (fifo_empty == 1'b1 && dma_read_fsm_state == DMA_READ_FSM_IDLE) begin - dma_done = outstanding_req == '0 && outstanding_addr_req == '0; - dma_write_fsm_n_state = dma_done ? DMA_WRITE_FSM_IDLE : DMA_WRITE_FSM_ON; - end else begin - dma_write_fsm_n_state = DMA_WRITE_FSM_ON; - // Wait if fifo is empty or if the SPI TX is not ready for new data (only in SPI mode 2). - if (fifo_empty == 1'b0 && wait_for_tx == 1'b0 && fifo_addr_empty_check == 1'b0) begin - data_out_req = 1'b1; - data_out_we = 1'b1; - data_out_be = byte_enable_out; - data_out_addr = write_address; - end - end - end - endcase - end - - fifo_v3 #( - .DEPTH(FIFO_DEPTH) - ) dma_fifo_i ( - .clk_i, - .rst_ni, - .flush_i(fifo_flush), - .testmode_i(1'b0), - // status flags - .full_o(fifo_full), - .empty_o(fifo_empty), - .usage_o(fifo_usage), - // as long as the queue is not full we can push new data - .data_i(fifo_input), - .push_i(data_in_rvalid), - // as long as the queue is not empty we can pop new elements - .data_o(fifo_output), - .pop_i(data_out_gnt) - ); - - fifo_v3 #( - .DEPTH(FIFO_DEPTH) - ) dma_addr_fifo_i ( - .clk_i, - .rst_ni, - .flush_i(fifo_addr_flush), - .testmode_i(1'b0), - // status flags - .full_o(fifo_addr_full), - .empty_o(fifo_addr_empty), - .usage_o(fifo_addr_usage), - // as long as the queue is not full we can push new data - .data_i(fifo_addr_input), - .push_i(data_addr_in_rvalid), - // as long as the queue is not empty we can pop new elements - .data_o(fifo_addr_output), - .pop_i(data_out_gnt && address_mode) - ); - - dma_reg_top #( - .reg_req_t(reg_req_t), - .reg_rsp_t(reg_rsp_t) - ) dma_reg_top_i ( - .clk_i, - .rst_ni, - .reg_req_i, - .reg_rsp_o, - .reg2hw, - .hw2reg, - .devmode_i(1'b1) - ); - - // WINDOW EVENT - // Count gnt write transaction and generate event pulse if WINDOW_SIZE is reached - assign dma_window_event = |reg2hw.window_size.q & data_out_gnt & (window_counter + 'h1 >= reg2hw.window_size.q); - - always_ff @(posedge clk_i, negedge rst_ni) begin + always_ff @(posedge clk_cg, negedge rst_ni) begin : proc_dma_window_cnt if (~rst_ni) begin window_counter <= 'h0; end else begin @@ -606,7 +449,7 @@ module dma #( if (dma_start | dma_done) begin window_counter <= 'h0; end else if (data_out_gnt) begin - if (window_counter + 'h1 >= reg2hw.window_size.q) begin + if (window_counter + 'h1 >= {19'h0, reg2hw.window_size.q}) begin window_counter <= 'h0; end else begin window_counter <= window_counter + 'h1; @@ -617,7 +460,7 @@ module dma #( end // Update WINDOW_COUNT register - always_comb begin + always_comb begin : proc_dma_window_cnt_reg hw2reg.window_count.d = reg2hw.window_count.q + 'h1; hw2reg.window_count.de = 1'b0; if (dma_start) begin @@ -631,7 +474,7 @@ module dma #( // update window_done flag // set on dma_window_event // reset on read - always_ff @(posedge clk_i, negedge rst_ni) begin + always_ff @(posedge clk_cg, negedge rst_ni) begin : proc_dma_window_done if (~rst_ni) begin window_done_q <= 1'b0; end else begin @@ -640,5 +483,84 @@ module dma #( end end + always_ff @(posedge clk_cg, negedge rst_ni) begin + if (~rst_ni) begin + dma_padding_fsm_on <= 1'b0; + end else begin + if (dma_start == 1'b1) begin + dma_padding_fsm_on <= 1'b1; + end else if (dma_done == 1'b1) begin + dma_padding_fsm_on <= 1'b0; + end + end + end + + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signal assignments */ + + assign dma_done_o = dma_done; + assign dma_start = (dma_state_q == DMA_STARTING); + + /* OBI signals */ + assign dma_read_req_o.req = data_in_req; + assign dma_read_req_o.we = data_in_we; + assign dma_read_req_o.be = data_in_be; + assign dma_read_req_o.addr = data_in_addr; + assign dma_read_req_o.wdata = 32'h0; + + assign data_in_gnt = dma_read_resp_i.gnt; + assign data_in_rvalid = dma_read_resp_i.rvalid; + assign data_in_rdata = dma_read_resp_i.rdata; + + assign dma_addr_req_o.req = data_addr_in_req; + assign dma_addr_req_o.we = data_addr_in_we; + assign dma_addr_req_o.be = data_addr_in_be; + assign dma_addr_req_o.addr = data_addr_in_addr; + assign dma_addr_req_o.wdata = 32'h0; + + assign data_addr_in_gnt = dma_addr_resp_i.gnt; + assign data_addr_in_rvalid = dma_addr_resp_i.rvalid; + assign data_addr_in_rdata = dma_addr_resp_i.rdata; + + assign dma_write_req_o.req = data_out_req; + assign dma_write_req_o.we = data_out_we; + assign dma_write_req_o.be = data_out_be; + assign dma_write_req_o.addr = data_out_addr; + assign dma_write_req_o.wdata = data_out_wdata; + + assign data_out_gnt = dma_write_resp_i.gnt; + assign data_out_rvalid = dma_write_resp_i.rvalid; + assign data_out_rdata = dma_write_resp_i.rdata; + + /* FIFO signals */ + assign write_fifo_pop = (dma_state_q == DMA_RUNNING) & data_out_gnt; // @TOD0: check if this is correct + + assign dma_done_intr = transaction_ifr; + assign dma_done_intr_o = dma_done_intr_n; + assign dma_window_intr = window_ifr; + assign dma_window_intr_o = dma_window_intr_n; + + assign hw2reg.transaction_ifr.d = transaction_ifr; + assign hw2reg.window_ifr.d = window_ifr; + + assign hw2reg.status.ready.d = (dma_state_q == DMA_READY); + assign hw2reg.status.window_done.d = window_done_q; + + assign circular_mode = reg2hw.mode.q == 1; + assign address_mode = reg2hw.mode.q == 2; + + assign wait_for_rx = |(reg2hw.slot.rx_trigger_slot.q[SLOT_NUM-1:0] & (~trigger_slot_i)); + assign wait_for_tx = |(reg2hw.slot.tx_trigger_slot.q[SLOT_NUM-1:0] & (~trigger_slot_i)); + + assign read_fifo_alm_full = (read_fifo_usage == LastFifoUsage[Addr_Fifo_Depth-1:0]); + assign read_addr_fifo_alm_full = (read_addr_fifo_usage == LastFifoUsage[Addr_Fifo_Depth-1:0]); + assign write_fifo_alm_full = (write_fifo_usage == LastFifoUsage[Addr_Fifo_Depth-1:0]); + + + // WINDOW EVENT + // Count gnt write transaction and generate event pulse if WINDOW_SIZE is reached + assign dma_window_event = |reg2hw.window_size.q & data_out_gnt & (window_counter + 'h1 >= {19'h0, reg2hw.window_size.q}); endmodule : dma diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_obiread_addr_fsm.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_obiread_addr_fsm.sv new file mode 100644 index 00000000..7eb3e635 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_obiread_addr_fsm.sv @@ -0,0 +1,168 @@ +/* + * Copyright 2024 EPFL + * Solderpad Hardware License, Version 2.1, see LICENSE.md for details. + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Author: Tommaso Terzano + * + * + * Info: Reading FSM for DMA channel in address mode, controls the input FIFO. + */ + +module dma_obiread_addr_fsm + import dma_reg_pkg::*; +#( +) ( + input logic clk_i, + input logic rst_ni, + input dma_reg2hw_t reg2hw_i, + input logic dma_start_i, + input logic ext_dma_stop_i, + input logic read_fifo_addr_full_i, + input logic read_fifo_addr_alm_full_i, + input logic address_mode_i, + input logic data_in_gnt_i, + output logic data_addr_in_req_o, + output logic data_addr_in_we_o, + output logic [3:0] data_addr_in_be_o, + output logic [31:0] data_addr_in_addr_o +); + + /*_________________________________________________________________________________________________________________________________ */ + + /* Parameter definition */ + + import dma_reg_pkg::*; + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signals declaration */ + + /* Registers */ + dma_reg2hw_t reg2hw; + + /* Control signals */ + logic dma_start; + logic ext_dma_stop; + + enum logic { + DMA_READ_FSM_IDLE, + DMA_READ_FSM_ON + } + dma_read_addr_fsm_state, dma_read_addr_fsm_n_state; + + logic fifo_addr_full; + logic fifo_addr_alm_full; + + logic data_addr_in_gnt; + logic data_addr_in_req; + logic data_addr_in_we; + logic [3:0] data_addr_in_be; + logic [31:0] data_addr_in_addr; + + logic address_mode; + logic [31:0] addr_ptr_reg; + logic [31:0] dma_addr_cnt; + + /*_________________________________________________________________________________________________________________________________ */ + + /* FSMs instantiation */ + + // Store address data pointer and increment everytime read request is granted - only in address mode + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_addr_reg + if (~rst_ni) begin + addr_ptr_reg <= '0; + end else begin + if (dma_start == 1'b1 && address_mode) begin + addr_ptr_reg <= reg2hw.addr_ptr.q; + end else if (data_addr_in_gnt == 1'b1 && address_mode) begin + addr_ptr_reg <= addr_ptr_reg + 32'h4; //always continuos in 32b + end + end + end + + // Store dma transfer size for the address port + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_dma_addr_cnt_reg + if (~rst_ni) begin + dma_addr_cnt <= '0; + end else begin + if (dma_start == 1'b1 && address_mode) begin + dma_addr_cnt <= {16'h0, reg2hw.size_d1.q}; + end else if (data_addr_in_gnt == 1'b1 && address_mode) begin + dma_addr_cnt <= dma_addr_cnt - 1; //address always 32b + end + end + end + + // FSM state update + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_fsm_state + if (~rst_ni) begin + dma_read_addr_fsm_state <= DMA_READ_FSM_IDLE; + end else begin + dma_read_addr_fsm_state <= dma_read_addr_fsm_n_state; + end + end + + // Read address master FSM + always_comb begin : proc_dma_addr_read_fsm_logic + + dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE; + + data_addr_in_req = '0; + data_addr_in_we = '0; + data_addr_in_be = '0; + data_addr_in_addr = '0; + + + unique case (dma_read_addr_fsm_state) + + DMA_READ_FSM_IDLE: begin + // Wait for start signal + if (dma_start == 1'b1 && address_mode) begin + dma_read_addr_fsm_n_state = DMA_READ_FSM_ON; + end else begin + dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE; + end + end + // Read one word + DMA_READ_FSM_ON: begin + if (ext_dma_stop == 1'b0) begin + // If all input data read exit + if (|dma_addr_cnt == 1'b0) begin + dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE; + end else begin + dma_read_addr_fsm_n_state = DMA_READ_FSM_ON; + // Wait if fifo is full, almost full (last data), or if the SPI RX does not have valid data (only in SPI mode 1). + if (fifo_addr_full == 1'b0 && fifo_addr_alm_full == 1'b0) begin + data_addr_in_req = 1'b1; + data_addr_in_we = 1'b0; + data_addr_in_be = 4'b1111; // always read all bytes + data_addr_in_addr = addr_ptr_reg; + end + end + end else begin + dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE; + end + end + endcase + end + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signal assignments */ + + /* Renaming */ + assign address_mode = address_mode_i; + assign reg2hw = reg2hw_i; + assign data_addr_in_gnt = data_in_gnt_i; + assign fifo_addr_full = read_fifo_addr_full_i; + assign fifo_addr_alm_full = read_fifo_addr_alm_full_i; + assign dma_start = dma_start_i; + assign ext_dma_stop = ext_dma_stop_i; + assign data_addr_in_be_o = data_addr_in_be; + assign data_addr_in_addr_o = data_addr_in_addr; + assign data_addr_in_req_o = data_addr_in_req; + assign data_addr_in_we_o = data_addr_in_we; + + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_obiread_fsm.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_obiread_fsm.sv new file mode 100644 index 00000000..15103796 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_obiread_fsm.sv @@ -0,0 +1,313 @@ +/* + * Copyright 2024 EPFL + * Solderpad Hardware License, Version 2.1, see LICENSE.md for details. + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Author: Tommaso Terzano + * + * + * Info: Reading FSM for DMA channel, controls the input FIFO. + */ + +module dma_obiread_fsm + import dma_reg_pkg::*; +#( +) ( + input logic clk_i, + input logic rst_ni, + input dma_reg2hw_t reg2hw_i, + input logic dma_start_i, + input logic dma_done_i, + input logic ext_dma_stop_i, + input logic read_fifo_full_i, + input logic read_fifo_alm_full_i, + input logic wait_for_rx_i, + input logic data_in_gnt_i, + input logic data_in_rvalid_i, + input logic [31:0] data_in_rdata_i, + + output logic [31:0] fifo_input_o, + output logic data_in_req_o, + output logic data_in_we_o, + output logic [3:0] data_in_be_o, + output logic [31:0] data_in_addr_o, + output logic read_fifo_flush_o +); + + /*_________________________________________________________________________________________________________________________________ */ + + /* Parameter definition */ + + import dma_reg_pkg::*; + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signals declaration */ + + /* Registers */ + dma_reg2hw_t reg2hw; + + enum logic { + DMA_READ_FSM_IDLE, + DMA_READ_FSM_ON + } + dma_read_fsm_state, dma_read_fsm_n_state; + + logic data_in_gnt; + logic fifo_full; + logic fifo_alm_full; + logic fifo_flush; + logic dma_start; + logic ext_dma_stop; + logic read_ptr_update_sel; + logic dma_conf_1d; + logic dma_conf_2d; + logic data_in_rvalid; + + logic wait_for_rx; + + logic [16:0] dma_src_cnt_d1; + logic [16:0] dma_src_cnt_d2; + + logic [31:0] trsp_src_ptr_reg; + logic [31:0] read_ptr_reg; + + logic data_in_req; + logic data_in_we; + logic [3:0] data_in_be; + logic [31:0] data_in_addr; + logic [31:0] data_in_rdata; + + logic [31:0] read_ptr_valid_reg; + logic [31:0] dma_src_d1_inc; + logic [31:0] dma_src_d2_inc; + + /* FIFO signals */ + logic [31:0] fifo_input; + + /*_________________________________________________________________________________________________________________________________ */ + + /* FSMs instantiation */ + + /* Sign extension of the increments */ + always_comb begin + dma_src_d1_inc = {{26{reg2hw.src_ptr_inc_d1.q[5]}}, reg2hw.src_ptr_inc_d1.q}; + dma_src_d2_inc = {{9{reg2hw.src_ptr_inc_d2.q[22]}}, reg2hw.src_ptr_inc_d2.q}; + end + + /* Counters for the reading fsm */ + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_dma_src_cnt_reg + if (~rst_ni) begin + dma_src_cnt_d1 <= '0; + dma_src_cnt_d2 <= '0; + end else begin + if (dma_start == 1'b1) begin + dma_src_cnt_d1 <= {1'h0, reg2hw.size_d1.q}; + dma_src_cnt_d2 <= {1'h0, reg2hw.size_d2.q}; + end else if (dma_done_i == 1'b1) begin + dma_src_cnt_d1 <= '0; + dma_src_cnt_d2 <= '0; + end else if (data_in_gnt == 1'b1) begin + if (dma_conf_1d == 1'b1) begin + // 1D case + dma_src_cnt_d1 <= dma_src_cnt_d1 - 1; + end else if (dma_conf_2d == 1'b1) begin + // 2D case + if (dma_src_cnt_d1 == 1) begin + // In this case, the d1 is finished, so we need to decrement the d2 size and reset the d2 size + dma_src_cnt_d2 <= dma_src_cnt_d2 - 1; + dma_src_cnt_d1 <= {1'h0, reg2hw.size_d1.q}; + end else begin + // In this case, the d1 isn't finished, so we need to decrement the d1 size + dma_src_cnt_d1 <= dma_src_cnt_d1 - 1; + end + end + end + end + end + + /* + * Store input data pointer in source_ptr_reg and increment it every time read request is granted, + * if the d1 has finished reading and the read pointer update is set to 1'b1 + */ + + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_src_ptr_reg + if (~rst_ni) begin + trsp_src_ptr_reg <= '0; + end else begin + if (dma_start == 1'b1) begin + trsp_src_ptr_reg <= reg2hw.src_ptr.q + dma_src_d1_inc; + end else if (data_in_gnt == 1'b1 && dma_conf_2d == 1'b1 && read_ptr_update_sel == 1'b1 && + (dma_src_cnt_d1 == 1 && |dma_src_cnt_d2 == 1'b1)) begin + trsp_src_ptr_reg <= trsp_src_ptr_reg + dma_src_d1_inc; + end + end + end + + /* Store input data pointer and increment everytime read request is granted */ + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_in_reg + if (~rst_ni) begin + read_ptr_reg <= '0; + end else begin + if (dma_start == 1'b1) begin + read_ptr_reg <= reg2hw.src_ptr.q; + end else if (data_in_gnt == 1'b1) begin + if (dma_conf_1d == 1'b1) begin + /* Increase the pointer by the amount written in ptr_inc */ + read_ptr_reg <= read_ptr_reg + dma_src_d1_inc; + end else if (dma_conf_2d == 1'b1) begin + if (read_ptr_update_sel == 1'b0) begin + if (dma_src_cnt_d1 == 1 && |dma_src_cnt_d2 == 1'b1) begin + /* In this case, the d1 is almost finished, so we need to increment the pointer by sizeof(d1)*data_unit */ + read_ptr_reg <= read_ptr_reg + dma_src_d2_inc; + end else begin + read_ptr_reg <= read_ptr_reg + dma_src_d1_inc; /* Increment of the d1 increment (stride) */ + end + end else begin + /* In this case, perform the transposition */ + if (dma_src_cnt_d1 == 1 && |dma_src_cnt_d2 == 1'b1) begin + /* In this case, the d1 is almost finished, so we need to increment the pointer by sizeof(d1)*data_unit */ + read_ptr_reg <= trsp_src_ptr_reg; + end else begin + read_ptr_reg <= read_ptr_reg + dma_src_d2_inc; /* Increment of the d2 increment (stride) */ + end + end + end + end + end + end + + // FSM state update + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_fsm_state + if (~rst_ni) begin + dma_read_fsm_state <= DMA_READ_FSM_IDLE; + end else begin + dma_read_fsm_state <= dma_read_fsm_n_state; + end + end + + // Read master FSM + always_comb begin : proc_dma_read_fsm_logic + + dma_read_fsm_n_state = DMA_READ_FSM_IDLE; + + data_in_req = '0; + data_in_we = '0; + data_in_be = '0; + data_in_addr = '0; + + fifo_flush = 1'b0; + + unique case (dma_read_fsm_state) + + DMA_READ_FSM_IDLE: begin + // Wait for start signal + if (dma_start == 1'b1) begin + dma_read_fsm_n_state = DMA_READ_FSM_ON; + end else begin + dma_read_fsm_n_state = DMA_READ_FSM_IDLE; + end + end + // Read one word + DMA_READ_FSM_ON: begin + // If all input data read exit + if (ext_dma_stop == 1'b0) begin + if (dma_conf_1d == 1'b1) begin + // 1D DMA case + if (|dma_src_cnt_d1 == 1'b0) begin + dma_read_fsm_n_state = DMA_READ_FSM_IDLE; + end else begin + dma_read_fsm_n_state = DMA_READ_FSM_ON; + // Wait if fifo is full, almost full (last data), or if the SPI RX does not have valid data (only in SPI mode 1). + if (fifo_full == 1'b0 && fifo_alm_full == 1'b0 && wait_for_rx == 1'b0) begin + data_in_req = 1'b1; + data_in_we = 1'b0; + data_in_be = 4'b1111; // always read all bytes + data_in_addr = read_ptr_reg; + end + end + end else if (dma_conf_2d == 1'b1) begin + // 2D DMA case: exit only if both 1d and 2d counters are at 0 + if (dma_src_cnt_d1 == {1'h0, reg2hw.size_d1.q} && |dma_src_cnt_d2 == 1'b0) begin + dma_read_fsm_n_state = DMA_READ_FSM_IDLE; + end else begin + // The read operation is the same in both cases + dma_read_fsm_n_state = DMA_READ_FSM_ON; + // Wait if fifo is full, almost full (last data), or if the SPI RX does not have valid data (only in SPI mode 1). + if (fifo_full == 1'b0 && fifo_alm_full == 1'b0 && wait_for_rx == 1'b0) begin + data_in_req = 1'b1; + data_in_we = 1'b0; + data_in_be = 4'b1111; // always read all bytes + data_in_addr = read_ptr_reg; + end + end + end + end else begin + dma_read_fsm_n_state = DMA_READ_FSM_IDLE; + end + end + endcase + end + + // Only update read_ptr_valid_reg when the data is stored in the fifo. + // Since every input grant is followed by a rvalid, the read_ptr_valid_reg is a mere sample of the read_ptr_reg + // synched with the rvalid signal. + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_valid_in_reg + if (~rst_ni) begin + read_ptr_valid_reg <= '0; + end else begin + if (dma_start == 1'b1) begin + read_ptr_valid_reg <= reg2hw.src_ptr.q; + end else if (data_in_rvalid == 1'b1) begin + read_ptr_valid_reg <= read_ptr_reg; + end + end + end + + // Input data shift: shift the input data to be on the LSB of the fifo + always_comb begin : proc_input_data + + fifo_input[7:0] = data_in_rdata[7:0]; + fifo_input[15:8] = data_in_rdata[15:8]; + fifo_input[23:16] = data_in_rdata[23:16]; + fifo_input[31:24] = data_in_rdata[31:24]; + + case (read_ptr_valid_reg[1:0]) + 2'b00: ; + 2'b01: fifo_input[7:0] = data_in_rdata[15:8]; + + 2'b10: begin + fifo_input[7:0] = data_in_rdata[23:16]; + fifo_input[15:8] = data_in_rdata[31:24]; + end + + 2'b11: fifo_input[7:0] = data_in_rdata[31:24]; + endcase + end + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signal assignments */ + + /* Renaming */ + assign reg2hw = reg2hw_i; + assign data_in_gnt = data_in_gnt_i; + assign fifo_full = read_fifo_full_i; + assign fifo_alm_full = read_fifo_alm_full_i; + assign dma_start = dma_start_i; + assign ext_dma_stop = ext_dma_stop_i; + assign read_ptr_update_sel = reg2hw.dim_inv.q; + assign dma_conf_1d = reg2hw.dim_config.q == 0; + assign dma_conf_2d = reg2hw.dim_config.q == 1; + assign data_in_be_o = data_in_be; + assign data_in_addr_o = data_in_addr; + assign data_in_req_o = data_in_req; + assign data_in_we_o = data_in_we; + assign read_fifo_flush_o = fifo_flush; + assign wait_for_rx = wait_for_rx_i; + assign data_in_rvalid = data_in_rvalid_i; + assign data_in_rdata = data_in_rdata_i; + assign fifo_input_o = fifo_input; + + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_obiwrite_fsm.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_obiwrite_fsm.sv new file mode 100644 index 00000000..5b83c400 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_obiwrite_fsm.sv @@ -0,0 +1,358 @@ +/* + * Copyright 2024 EPFL + * Solderpad Hardware License, Version 2.1, see LICENSE.md for details. + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Author: Tommaso Terzano + * + * + * Info: Writing FSM for DMA channel, process data coming out of the output FIFO. Performs the sign extension if needed. + */ + +module dma_obiwrite_fsm + import dma_reg_pkg::*; +#( +) ( + input logic clk_i, + input logic rst_ni, + input dma_reg2hw_t reg2hw_i, + input logic dma_start_i, + input logic write_fifo_empty_i, + input logic read_addr_fifo_empty_i, + input logic [31:0] fifo_output_i, + input logic wait_for_tx_i, + input logic address_mode_i, + input logic padding_fsm_done_i, + input logic data_out_gnt_i, + input logic [31:0] fifo_addr_output_i, + + output logic data_out_req_o, + output logic data_out_we_o, + output logic [3:0] data_out_be_o, + output logic [31:0] data_out_addr_o, + output logic [31:0] data_out_wdata_o, + output logic dma_done_o +); + + /*_________________________________________________________________________________________________________________________________ */ + + /* Parameter definition */ + + import dma_reg_pkg::*; + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signals declaration */ + + /* Registers */ + dma_reg2hw_t reg2hw; + + logic dma_conf_1d; + logic dma_conf_2d; + logic dma_done; + logic address_mode; + logic dma_start; + + enum logic { + DMA_WRITE_FSM_IDLE, + DMA_WRITE_FSM_ON + } + dma_write_fsm_state, dma_write_fsm_n_state; + + typedef enum logic [1:0] { + DMA_DATA_TYPE_WORD, + DMA_DATA_TYPE_HALF_WORD, + DMA_DATA_TYPE_BYTE, + DMA_DATA_TYPE_BYTE_ + } dma_data_type_t; + + dma_data_type_t dst_data_type; + dma_data_type_t src_data_type; + + logic data_out_req; + logic data_out_we; + logic data_out_gnt; + logic [3:0] data_out_be; + logic [31:0] data_out_addr; + logic [31:0] data_out_wdata; + logic [31:0] write_address; + logic [31:0] write_ptr_reg; + logic [3:0] byte_enable_out; + + logic [31:0] dma_dst_d1_inc; + logic [31:0] dma_dst_d2_inc; + logic [16:0] dma_dst_cnt_d1; + + logic wait_for_tx; + + /* Sign extension signals */ + logic sign_extend; + + /* FIFO signals */ + logic write_fifo_empty; + logic read_addr_fifo_empty; + logic [31:0] fifo_output; + + /*_________________________________________________________________________________________________________________________________ */ + + /* FSMs instantiation */ + + /* Sign extension of the increments */ + always_comb begin + dma_dst_d1_inc = {{26{reg2hw.dst_ptr_inc_d1.q[5]}}, reg2hw.dst_ptr_inc_d1.q}; + dma_dst_d2_inc = {{9{reg2hw.dst_ptr_inc_d2.q[22]}}, reg2hw.dst_ptr_inc_d2.q}; + end + + /* Counters for the reading fsm */ + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_dma_dst_cnt_reg + if (~rst_ni) begin + dma_dst_cnt_d1 <= '0; + end else begin + if (dma_start == 1'b1) begin + dma_dst_cnt_d1 <= {1'h0, reg2hw.size_d1.q} + {11'h0, reg2hw.pad_left.q} + {11'h0, reg2hw.pad_right.q}; + end else if (dma_done == 1'b1) begin + dma_dst_cnt_d1 <= '0; + end else if (data_out_gnt == 1'b1) begin + if (dma_conf_1d == 1'b1) begin + // 1D case + dma_dst_cnt_d1 <= dma_dst_cnt_d1 - 1; + end else if (dma_conf_2d == 1'b1) begin + // 2D case + if (dma_dst_cnt_d1 == 1) begin + // In this case, the d1 is finished, so we need to reset the d2 size + dma_dst_cnt_d1 <= {1'h0, reg2hw.size_d1.q} + {11'h0, reg2hw.pad_left.q} + {11'h0, reg2hw.pad_right.q}; + end else begin + // In this case, the d1 isn't finished, so we need to decrement the d1 size + dma_dst_cnt_d1 <= dma_dst_cnt_d1 - 1; + end + end + end + end + end + + /* Determine the byte enable depending on the datatype */ + always_comb begin : proc_byte_enable_out + case (dst_data_type) // Data type 00 Word, 01 Half word, 11,10 byte + DMA_DATA_TYPE_WORD: byte_enable_out = 4'b1111; // Writing a word (32 bits) + + DMA_DATA_TYPE_HALF_WORD: begin // Writing a half-word (16 bits) + case (write_ptr_reg[1]) + 1'b0: byte_enable_out = 4'b0011; + 1'b1: byte_enable_out = 4'b1100; + endcase + ; // case(write_ptr_reg[1:0]) + end + + DMA_DATA_TYPE_BYTE, DMA_DATA_TYPE_BYTE_: begin // Writing a byte (8 bits) + case (write_ptr_reg[1:0]) + 2'b00: byte_enable_out = 4'b0001; + 2'b01: byte_enable_out = 4'b0010; + 2'b10: byte_enable_out = 4'b0100; + 2'b11: byte_enable_out = 4'b1000; + endcase + ; // case(write_ptr_reg[1:0]) + end + endcase + ; // case (dst_data_type) + end + + /* Store output data pointer and increment everytime write request is granted */ + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_out_reg + if (~rst_ni) begin + write_ptr_reg <= '0; + end else begin + if (dma_start == 1'b1) begin + write_ptr_reg <= reg2hw.dst_ptr.q; + end else if (data_out_gnt == 1'b1) begin + if (dma_conf_1d == 1'b1) begin + write_ptr_reg <= write_ptr_reg + dma_dst_d1_inc; + end else if (dma_conf_2d == 1'b1) begin + if (dma_dst_cnt_d1 == 1) begin + // In this case, the d1 is finished, so we need to increment the pointer by sizeof(d1)*data_unit*strides + write_ptr_reg <= write_ptr_reg + dma_dst_d2_inc; + end else begin + write_ptr_reg <= write_ptr_reg + dma_dst_d1_inc; // Increment just of one du, since we need to increase the 1d + end + end + end + end + end + + /* FSM state update */ + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_fsm_state + if (~rst_ni) begin + dma_write_fsm_state <= DMA_WRITE_FSM_IDLE; + end else begin + dma_write_fsm_state <= dma_write_fsm_n_state; + end + end + + /* Write master FSM */ + always_comb begin : proc_dma_write_fsm_logic + + dma_write_fsm_n_state = DMA_WRITE_FSM_IDLE; + dma_done = 1'b0; + + data_out_req = '0; + data_out_we = '0; + data_out_be = '0; + data_out_addr = '0; + + unique case (dma_write_fsm_state) + + DMA_WRITE_FSM_IDLE: begin + // Wait for start signal + if (dma_start == 1'b1) begin + dma_write_fsm_n_state = DMA_WRITE_FSM_ON; + end else begin + dma_write_fsm_n_state = DMA_WRITE_FSM_IDLE; + end + end + // Read one word + DMA_WRITE_FSM_ON: begin + // If all input data read exit + if (padding_fsm_done_i == 1'b1 && write_fifo_empty == 1'b1) begin + dma_done = (write_fifo_empty == 1'b1); + // If all input data has been processed and written, exit, otherwise finish storing the data + dma_write_fsm_n_state = dma_done ? DMA_WRITE_FSM_IDLE : DMA_WRITE_FSM_ON; + end else begin + dma_write_fsm_n_state = DMA_WRITE_FSM_ON; + // Wait if write fifo is empty or if the SPI TX is not ready for new data (only in SPI mode 2). + if (write_fifo_empty == 1'b0 && wait_for_tx == 1'b0 && (read_addr_fifo_empty && address_mode) == 1'b0) begin + data_out_req = 1'b1; + data_out_we = 1'b1; + data_out_be = byte_enable_out; + data_out_addr = write_address; + end + end + end + endcase + end + + /* Perform the data shift */ + always_comb begin : proc_output_data + + data_out_wdata[7:0] = fifo_output[7:0]; + data_out_wdata[15:8] = fifo_output[15:8]; + data_out_wdata[23:16] = fifo_output[23:16]; + data_out_wdata[31:24] = fifo_output[31:24]; + + case (write_ptr_reg[1:0]) + 2'b00: begin + if (sign_extend) begin + case ({ + src_data_type, dst_data_type + }) + {DMA_DATA_TYPE_WORD, DMA_DATA_TYPE_WORD} : ; + { + DMA_DATA_TYPE_HALF_WORD, DMA_DATA_TYPE_WORD + } : + data_out_wdata[31:16] = {16{fifo_output[15]}}; + { + DMA_DATA_TYPE_BYTE, DMA_DATA_TYPE_WORD + }, { + DMA_DATA_TYPE_BYTE_, DMA_DATA_TYPE_WORD + } : + data_out_wdata[31:8] = {24{fifo_output[7]}}; + {DMA_DATA_TYPE_HALF_WORD, DMA_DATA_TYPE_HALF_WORD} : ; + { + DMA_DATA_TYPE_BYTE, DMA_DATA_TYPE_HALF_WORD + }, { + DMA_DATA_TYPE_BYTE_, DMA_DATA_TYPE_HALF_WORD + } : + data_out_wdata[15:8] = {8{fifo_output[7]}}; + default: ; + endcase + end else begin + case ({ + src_data_type, dst_data_type + }) + {DMA_DATA_TYPE_WORD, DMA_DATA_TYPE_WORD} : ; + {DMA_DATA_TYPE_HALF_WORD, DMA_DATA_TYPE_WORD} : data_out_wdata[31:16] = 16'b0; + { + DMA_DATA_TYPE_BYTE, DMA_DATA_TYPE_WORD + }, { + DMA_DATA_TYPE_BYTE_, DMA_DATA_TYPE_WORD + } : + data_out_wdata[31:8] = 24'b0; + {DMA_DATA_TYPE_HALF_WORD, DMA_DATA_TYPE_HALF_WORD} : ; + { + DMA_DATA_TYPE_BYTE, DMA_DATA_TYPE_HALF_WORD + }, { + DMA_DATA_TYPE_BYTE_, DMA_DATA_TYPE_HALF_WORD + } : + data_out_wdata[15:8] = 8'b0; + default: ; + endcase + end + end + 2'b01: data_out_wdata[15:8] = fifo_output[7:0]; // Writing a byte, no need for sign extension + 2'b10: begin // Writing a half-word or a byte + data_out_wdata[23:16] = fifo_output[7:0]; + data_out_wdata[31:24] = fifo_output[15:8]; + + if (sign_extend) begin + case ({ + src_data_type, dst_data_type + }) + {DMA_DATA_TYPE_HALF_WORD, DMA_DATA_TYPE_HALF_WORD} : ; + { + DMA_DATA_TYPE_BYTE, DMA_DATA_TYPE_HALF_WORD + }, { + DMA_DATA_TYPE_BYTE_, DMA_DATA_TYPE_HALF_WORD + } : + data_out_wdata[31:24] = {8{fifo_output[7]}}; + default: ; + endcase + end else begin + case ({ + src_data_type, dst_data_type + }) + {DMA_DATA_TYPE_HALF_WORD, DMA_DATA_TYPE_HALF_WORD} : ; + { + DMA_DATA_TYPE_BYTE, DMA_DATA_TYPE_HALF_WORD + }, { + DMA_DATA_TYPE_BYTE_, DMA_DATA_TYPE_HALF_WORD + } : + data_out_wdata[31:24] = 8'b0; + default: ; + endcase + end + end + 2'b11: + data_out_wdata[31:24] = fifo_output[7:0]; // Writing a byte, no need for sign extension + endcase + end + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signal assignments */ + + /* Renaming */ + assign dma_start = dma_start_i; + assign reg2hw = reg2hw_i; + assign data_out_gnt = data_out_gnt_i; + assign dma_done_o = dma_done; + assign dst_data_type = dma_data_type_t'(reg2hw.dst_data_type.q); + assign src_data_type = dma_data_type_t'(reg2hw.src_data_type.q); + assign data_out_wdata_o = data_out_wdata; + assign write_fifo_empty = write_fifo_empty_i; + assign fifo_output = fifo_output_i; + assign wait_for_tx = wait_for_tx_i; + assign data_out_be_o = data_out_be; + assign data_out_addr_o = data_out_addr; + assign data_out_req_o = data_out_req; + assign data_out_we_o = data_out_we; + assign read_addr_fifo_empty = read_addr_fifo_empty_i; + assign address_mode = address_mode_i; + assign dma_conf_1d = reg2hw.dim_config.q == 0; + assign dma_conf_2d = reg2hw.dim_config.q == 1; + + /* Write address */ + assign write_address = address_mode ? fifo_addr_output_i : write_ptr_reg; + + /* Sign extension */ + assign sign_extend = reg2hw.sign_ext.q & ( (src_data_type[1] & ~dst_data_type[1]) | ((src_data_type[1] == dst_data_type[1]) & (src_data_type[0] & ~dst_data_type[0]))); + + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_padding_fsm.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_padding_fsm.sv new file mode 100644 index 00000000..d16c0bf3 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_padding_fsm.sv @@ -0,0 +1,339 @@ +/* + * Copyright 2024 EPFL + * Solderpad Hardware License, Version 2.1, see LICENSE.md for details. + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Author: Tommaso Terzano + * + * + * Info: Padding FSM for DMA channel. + */ + +module dma_padding_fsm + import dma_reg_pkg::*; +#( +) ( + input logic clk_i, + input logic rst_ni, + input dma_reg2hw_t reg2hw_i, + input logic dma_padding_fsm_on_i, + input logic dma_start_i, + input logic read_fifo_empty_i, + input logic write_fifo_full_i, + input logic write_fifo_alm_full_i, + input logic [31:0] data_read_i, + + output logic padding_fsm_done_o, + output logic write_fifo_push_o, + output logic read_fifo_pop_o, + output logic [31:0] data_write_o +); + + /*_________________________________________________________________________________________________________________________________ */ + + /* Parameter definition */ + + import dma_reg_pkg::*; + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signals declaration */ + + /* Registers */ + dma_reg2hw_t reg2hw; + + /* General signals */ + logic read_fifo_en; + logic write_fifo_en; + logic pad_on; + logic read_fifo_empty; + logic write_fifo_full; + logic write_fifo_alm_full; + logic dma_start; + logic [16:0] dma_cnt_d1; + logic [16:0] dma_cnt_d2; + logic dma_conf_1d; + logic dma_conf_2d; + + /* Padding FSM states */ + enum { + PAD_IDLE, + TOP_PAD_EXEC, + LEFT_PAD_EXEC, + RIGHT_PAD_EXEC, + BOTTOM_PAD_EXEC, + TOP_PAD_DONE, + LEFT_PAD_DONE, + RIGHT_PAD_DONE, + BOTTOM_PAD_DONE + } + pad_state_q, pad_state_d; + + /* Padding FSM conditions */ + logic idle_to_left_ex; + logic idle_to_top_ex; + logic idle_to_right_ex; + logic idle_to_bottom_ex; + logic top_ex_to_top_dn; + logic top_ex_to_left_ex; + logic top_dn_to_right_ex; + logic top_dn_to_bottom_ex; + logic top_dn_to_idle; + logic left_ex_to_left_dn; + logic left_dn_to_left_ex; + logic left_dn_to_right_ex; + logic left_dn_to_bottom_ex; + logic left_dn_to_idle; + logic right_ex_to_right_dn; + logic right_ex_to_left_ex; + logic right_dn_to_right_ex; + logic right_dn_to_idle; + logic right_ex_to_idle; + logic right_ex_to_bottom_ex; + logic bottom_ex_to_idle; + + /*_________________________________________________________________________________________________________________________________ */ + + /* Module instantiation */ + + /*_________________________________________________________________________________________________________________________________ */ + + /* FSMs instantiation */ + + /* Padding FSM state update */ + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_pad_state + if (~rst_ni) begin + pad_state_q <= PAD_IDLE; + end else begin + /* Advance in the FSM only if the write FIFO is available */ + if (write_fifo_en == 1'b1 && dma_padding_fsm_on_i == 1'b1 && padding_fsm_done_o == 1'b0) begin + pad_state_q <= pad_state_d; + end + end + end + + /* Padding FSM logic */ + always_comb begin : proc_pad_fsm_logic + pad_state_d = pad_state_q; + + unique case (pad_state_q) + PAD_IDLE: begin + /* If the padding is done, stay idle */ + if (padding_fsm_done_o == 1'b1) begin + pad_state_d = PAD_IDLE; + end else begin + if (idle_to_top_ex) begin + pad_state_d = TOP_PAD_EXEC; + end else if (idle_to_left_ex) begin + pad_state_d = LEFT_PAD_EXEC; + end else if (idle_to_right_ex) begin + pad_state_d = RIGHT_PAD_EXEC; + end else if (idle_to_bottom_ex) begin + pad_state_d = BOTTOM_PAD_EXEC; + end + end + end + + TOP_PAD_EXEC: begin + if (top_ex_to_left_ex) begin + pad_state_d = LEFT_PAD_EXEC; + end else if (top_ex_to_top_dn) begin + pad_state_d = TOP_PAD_DONE; + end + end + TOP_PAD_DONE: begin + if (top_dn_to_right_ex) begin + pad_state_d = RIGHT_PAD_EXEC; + end else if (top_dn_to_bottom_ex) begin + pad_state_d = BOTTOM_PAD_EXEC; + end else if (top_dn_to_idle) begin + pad_state_d = PAD_IDLE; + end + end + LEFT_PAD_EXEC: begin + if (left_ex_to_left_dn) begin + pad_state_d = LEFT_PAD_DONE; + end + end + LEFT_PAD_DONE: begin + if (left_dn_to_right_ex) begin + pad_state_d = RIGHT_PAD_EXEC; + end else if (left_dn_to_bottom_ex) begin + pad_state_d = BOTTOM_PAD_EXEC; + end else if (left_dn_to_left_ex) begin + pad_state_d = LEFT_PAD_EXEC; + end else if (left_dn_to_idle) begin + pad_state_d = PAD_IDLE; + end + end + RIGHT_PAD_EXEC: begin + if (right_ex_to_right_dn) begin + pad_state_d = RIGHT_PAD_DONE; + end else if (right_ex_to_left_ex) begin + pad_state_d = LEFT_PAD_EXEC; + end else if (right_ex_to_bottom_ex) begin + pad_state_d = BOTTOM_PAD_EXEC; + end else if (right_ex_to_idle) begin + pad_state_d = PAD_IDLE; + end + end + RIGHT_PAD_DONE: begin + if (right_dn_to_idle) begin + pad_state_d = PAD_IDLE; + end else if (right_dn_to_right_ex) begin + pad_state_d = RIGHT_PAD_EXEC; + end + end + BOTTOM_PAD_EXEC: begin + if (bottom_ex_to_idle) begin + pad_state_d = PAD_IDLE; + end + end + endcase + end + + /* Data transfer */ + always_comb begin : proc_data_transfer + data_write_o = '0; + write_fifo_push_o = 1'b0; + read_fifo_pop_o = 1'b0; + + if (dma_padding_fsm_on_i == 1'b1 && padding_fsm_done_o == 1'b0) begin + /* + * If we need to pad, there is no need to wait for the read fifo to have some values. + * If we don't have to pad, we need to wait for the read fifo to be not empty. + * In both cases, we need to wait for the write fifo to have some space. + */ + if (pad_on == 1'b1 & write_fifo_en == 1'b1) begin + write_fifo_push_o = 1'b1; + end else if (read_fifo_en == 1'b1 & write_fifo_en == 1'b1) begin + data_write_o = data_read_i; + write_fifo_push_o = 1'b1; + read_fifo_pop_o = 1'b1; + end + end + end + + /* Counters for the padding fsm */ + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_cnt + if (~rst_ni) begin + dma_cnt_d1 <= '0; + dma_cnt_d2 <= '0; + end else begin + if (dma_start == 1'b1) begin + dma_cnt_d1 <= ({1'h0, reg2hw.size_d1.q} + {11'h0, reg2hw.pad_left.q} + {11'h0, reg2hw.pad_right.q}); + dma_cnt_d2 <= {1'h0, reg2hw.size_d2.q} + {11'h0, reg2hw.pad_top.q} + {11'h0, reg2hw.pad_bottom.q}; + end else if (padding_fsm_done_o == 1'b1) begin + dma_cnt_d1 <= '0; + dma_cnt_d2 <= '0; + end else if ((dma_padding_fsm_on_i == 1'b1 && padding_fsm_done_o == 1'b0) & + ((pad_on == 1'b1 & write_fifo_en == 1'b1) || + (read_fifo_en == 1'b1 & write_fifo_en == 1'b1))) begin + if (dma_conf_1d == 1'b1) begin + // 1D case + dma_cnt_d1 <= dma_cnt_d1 - 1; + end else if (dma_conf_2d == 1'b1) begin + // 2D case + if (dma_cnt_d1 == 1) begin + // In this case, the d1 is finished, so we need to decrement the d2 size and reset the d2 size + dma_cnt_d2 <= dma_cnt_d2 - 1; + dma_cnt_d1 <= {1'h0, reg2hw.size_d1.q} + {11'h0, reg2hw.pad_left.q} + {11'h0, reg2hw.pad_right.q}; + end else begin + // In this case, the d1 isn't finished, so we need to decrement the d1 size + dma_cnt_d1 <= dma_cnt_d1 - 1; + end + end + end + end + end + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signal assignments */ + + /* Renaming */ + assign read_fifo_empty = read_fifo_empty_i; + assign write_fifo_full = write_fifo_full_i; + assign write_fifo_alm_full = write_fifo_alm_full_i; + assign dma_start = dma_start_i; + assign reg2hw = reg2hw_i; + assign dma_conf_1d = reg2hw.dim_config.q == 0; + assign dma_conf_2d = reg2hw.dim_config.q == 1; + + /* Padding flag */ + assign pad_on = (pad_state_q != PAD_IDLE && pad_state_q != TOP_PAD_DONE && pad_state_q != LEFT_PAD_DONE && pad_state_q != RIGHT_PAD_DONE && pad_state_q != BOTTOM_PAD_DONE); + + /* Read FIFO pop signal */ + assign read_fifo_en = (read_fifo_empty == 1'b0); + + /* Write FIFO push signal */ + assign write_fifo_en = (write_fifo_full == 1'b0 && write_fifo_alm_full == 1'b0); + + /* Padding done signal */ + assign padding_fsm_done_o = ((dma_conf_2d == 1'b1 && |dma_cnt_d2 == 1'b0 && dma_padding_fsm_on_i == 1'b1) + | (dma_conf_1d == 1'b1 && |dma_cnt_d1 == 1'b0 && dma_padding_fsm_on_i == 1'b1)); + + /* Padding FSM conditions assignments */ + assign idle_to_top_ex = {|reg2hw.pad_top.q == 1'b1 && dma_padding_fsm_on_i == 1'b1}; + assign idle_to_left_ex = { + |reg2hw.pad_top.q == 1'b0 && |reg2hw.pad_left.q == 1'b1 && dma_padding_fsm_on_i == 1'b1 + }; + assign idle_to_right_ex = { + write_fifo_push_o == 1'b1 && |reg2hw.pad_top.q == 1'b0 && |reg2hw.pad_left.q == 1'b0 && |reg2hw.pad_right.q == 1'b1 + && dma_cnt_d1 == ({11'h0, reg2hw.pad_right.q} + 1) + }; + assign idle_to_bottom_ex = { + write_fifo_push_o == 1'b1 && |reg2hw.pad_top.q == 1'b0 && |reg2hw.pad_left.q == 1'b0 && |reg2hw.pad_right.q == 1'b0 && |reg2hw.pad_bottom.q == 1'b1 + && dma_cnt_d2 == ({11'h0, reg2hw.pad_bottom.q} + 1) && dma_cnt_d1 == 1 + }; + assign top_ex_to_top_dn = { + write_fifo_push_o == 1'b1 && dma_cnt_d2 == ( {1'h0, reg2hw.size_d2.q} + {11'h0, reg2hw.pad_bottom.q} + 1) && dma_cnt_d1 == 1 && |reg2hw.pad_left.q == 1'b0 + }; + assign top_ex_to_left_ex = { + write_fifo_push_o == 1'b1 && dma_cnt_d2 == ({1'h0, reg2hw.size_d2.q} + {11'h0, reg2hw.pad_bottom.q} + 1) && dma_cnt_d1 == 1 && |reg2hw.pad_left.q == 1'b1 + }; + assign top_dn_to_right_ex = { + write_fifo_push_o == 1'b1 && |reg2hw.pad_left.q == 1'b0 && |reg2hw.pad_right.q == 1'b1 && dma_cnt_d1 == ({11'h0, reg2hw.pad_right.q} + 1) + }; + assign top_dn_to_bottom_ex = { + write_fifo_push_o == 1'b1 && |reg2hw.pad_left.q == 1'b0 && |reg2hw.pad_right.q == 1'b0 && |reg2hw.pad_bottom.q == 1'b1 && dma_cnt_d2 == ({11'h0, reg2hw.pad_bottom.q} + 1) && dma_cnt_d1 == 1 + }; + assign top_dn_to_idle = { + |reg2hw.pad_left.q == 1'b0 && |reg2hw.pad_right.q == 1'b0 && |reg2hw.pad_bottom.q == 1'b0 && dma_cnt_d2 == 1 && dma_cnt_d1 == 1 + }; + assign left_ex_to_left_dn = { + write_fifo_push_o == 1'b1 && dma_cnt_d1 == ({1'h0, reg2hw.size_d1.q} + {11'h0, reg2hw.pad_right.q} + 1) + }; + assign left_dn_to_left_ex = { + write_fifo_push_o == 1'b1 && dma_cnt_d1 == 1 && dma_cnt_d2 != (1'b1 + {11'h0, reg2hw.pad_bottom.q}) && |reg2hw.pad_right.q == 1'b0 + }; + assign left_dn_to_right_ex = { + write_fifo_push_o == 1'b1 && |reg2hw.pad_right.q == 1'b1 && dma_cnt_d1 == ({11'h0, reg2hw.pad_right.q} + 1) + }; + assign left_dn_to_bottom_ex = { + write_fifo_push_o == 1'b1 && |reg2hw.pad_right.q == 1'b0 && |reg2hw.pad_bottom.q == 1'b1 && dma_cnt_d2 == ({11'h0, reg2hw.pad_bottom.q} + 1) && dma_cnt_d1 == 1 + }; + assign left_dn_to_idle = { + |reg2hw.pad_right.q == 1'b0 && |reg2hw.pad_bottom.q == 1'b0 && dma_cnt_d2 == 1 && dma_cnt_d1 == 1 + }; + assign right_ex_to_right_dn = { + write_fifo_push_o == 1'b1 && dma_cnt_d1 == 1 && dma_cnt_d2 != ({11'h0, reg2hw.pad_bottom.q} + 1) && |reg2hw.pad_left.q == 1'b0 + }; + assign right_ex_to_left_ex = { + write_fifo_push_o == 1'b1 && dma_cnt_d1 == 1 && dma_cnt_d2 != ({11'h0, reg2hw.pad_bottom.q} + 1) && |reg2hw.pad_left.q == 1'b1 + }; + assign right_ex_to_bottom_ex = { + write_fifo_push_o == 1'b1 && |reg2hw.pad_bottom.q == 1'b1 && dma_cnt_d2 == ({11'h0, reg2hw.pad_bottom.q} + 1) && dma_cnt_d1 == 1 + }; + assign right_dn_to_right_ex = { + write_fifo_push_o == 1'b1 && dma_cnt_d1 == ({11'h0, reg2hw.pad_right.q} + 1) && |reg2hw.pad_left.q == 1'b0 + }; + assign right_dn_to_idle = {|reg2hw.pad_bottom.q == 1'b0 && dma_cnt_d2 == 1 && dma_cnt_d1 == 1}; + assign bottom_ex_to_idle = {dma_cnt_d1 == 1 && dma_cnt_d2 == 1 && dma_cnt_d1 == 1}; + + assign right_ex_to_idle = {|reg2hw.pad_bottom.q == 1'b0 && dma_cnt_d2 == 1 && dma_cnt_d1 == 1}; + + + + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_reg_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_reg_pkg.sv index e4e31fe2..4e98968c 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_reg_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_reg_pkg.sv @@ -7,7 +7,7 @@ package dma_reg_pkg; // Address widths within the block - parameter int BlockAw = 6; + parameter int BlockAw = 7; //////////////////////////// // Typedefs for registers // @@ -20,9 +20,11 @@ package dma_reg_pkg; typedef struct packed {logic [31:0] q;} dma_reg2hw_addr_ptr_reg_t; typedef struct packed { - logic [31:0] q; + logic [15:0] q; logic qe; - } dma_reg2hw_size_reg_t; + } dma_reg2hw_size_d1_reg_t; + + typedef struct packed {logic [15:0] q;} dma_reg2hw_size_d2_reg_t; typedef struct packed { struct packed { @@ -35,110 +37,205 @@ package dma_reg_pkg; } window_done; } dma_reg2hw_status_reg_t; - typedef struct packed { - struct packed {logic [7:0] q;} src_ptr_inc; - struct packed {logic [7:0] q;} dst_ptr_inc; - } dma_reg2hw_ptr_inc_reg_t; + typedef struct packed {logic [5:0] q;} dma_reg2hw_src_ptr_inc_d1_reg_t; + + typedef struct packed {logic [22:0] q;} dma_reg2hw_src_ptr_inc_d2_reg_t; + + typedef struct packed {logic [5:0] q;} dma_reg2hw_dst_ptr_inc_d1_reg_t; + + typedef struct packed {logic [22:0] q;} dma_reg2hw_dst_ptr_inc_d2_reg_t; typedef struct packed { struct packed {logic [15:0] q;} rx_trigger_slot; struct packed {logic [15:0] q;} tx_trigger_slot; } dma_reg2hw_slot_reg_t; - typedef struct packed {logic [1:0] q;} dma_reg2hw_data_type_reg_t; + typedef struct packed {logic [1:0] q;} dma_reg2hw_src_data_type_reg_t; + + typedef struct packed {logic [1:0] q;} dma_reg2hw_dst_data_type_reg_t; + + typedef struct packed {logic q;} dma_reg2hw_sign_ext_reg_t; typedef struct packed {logic [1:0] q;} dma_reg2hw_mode_reg_t; - typedef struct packed {logic [31:0] q;} dma_reg2hw_window_size_reg_t; + typedef struct packed {logic q;} dma_reg2hw_dim_config_reg_t; + + typedef struct packed {logic q;} dma_reg2hw_dim_inv_reg_t; + + typedef struct packed {logic [5:0] q;} dma_reg2hw_pad_top_reg_t; + + typedef struct packed {logic [5:0] q;} dma_reg2hw_pad_bottom_reg_t; - typedef struct packed {logic [31:0] q;} dma_reg2hw_window_count_reg_t; + typedef struct packed {logic [5:0] q;} dma_reg2hw_pad_right_reg_t; + + typedef struct packed {logic [5:0] q;} dma_reg2hw_pad_left_reg_t; + + typedef struct packed {logic [12:0] q;} dma_reg2hw_window_size_reg_t; + + typedef struct packed {logic [7:0] q;} dma_reg2hw_window_count_reg_t; typedef struct packed { struct packed {logic q;} transaction_done; struct packed {logic q;} window_done; } dma_reg2hw_interrupt_en_reg_t; + typedef struct packed { + logic q; + logic re; + } dma_reg2hw_transaction_ifr_reg_t; + + typedef struct packed { + logic q; + logic re; + } dma_reg2hw_window_ifr_reg_t; + typedef struct packed { struct packed {logic d;} ready; struct packed {logic d;} window_done; } dma_hw2reg_status_reg_t; typedef struct packed { - logic [31:0] d; - logic de; + logic [7:0] d; + logic de; } dma_hw2reg_window_count_reg_t; + typedef struct packed {logic d;} dma_hw2reg_transaction_ifr_reg_t; + + typedef struct packed {logic d;} dma_hw2reg_window_ifr_reg_t; + // Register -> HW type typedef struct packed { - dma_reg2hw_src_ptr_reg_t src_ptr; // [250:219] - dma_reg2hw_dst_ptr_reg_t dst_ptr; // [218:187] - dma_reg2hw_addr_ptr_reg_t addr_ptr; // [186:155] - dma_reg2hw_size_reg_t size; // [154:122] - dma_reg2hw_status_reg_t status; // [121:118] - dma_reg2hw_ptr_inc_reg_t ptr_inc; // [117:102] - dma_reg2hw_slot_reg_t slot; // [101:70] - dma_reg2hw_data_type_reg_t data_type; // [69:68] - dma_reg2hw_mode_reg_t mode; // [67:66] - dma_reg2hw_window_size_reg_t window_size; // [65:34] - dma_reg2hw_window_count_reg_t window_count; // [33:2] - dma_reg2hw_interrupt_en_reg_t interrupt_en; // [1:0] + dma_reg2hw_src_ptr_reg_t src_ptr; // [282:251] + dma_reg2hw_dst_ptr_reg_t dst_ptr; // [250:219] + dma_reg2hw_addr_ptr_reg_t addr_ptr; // [218:187] + dma_reg2hw_size_d1_reg_t size_d1; // [186:170] + dma_reg2hw_size_d2_reg_t size_d2; // [169:154] + dma_reg2hw_status_reg_t status; // [153:150] + dma_reg2hw_src_ptr_inc_d1_reg_t src_ptr_inc_d1; // [149:144] + dma_reg2hw_src_ptr_inc_d2_reg_t src_ptr_inc_d2; // [143:121] + dma_reg2hw_dst_ptr_inc_d1_reg_t dst_ptr_inc_d1; // [120:115] + dma_reg2hw_dst_ptr_inc_d2_reg_t dst_ptr_inc_d2; // [114:92] + dma_reg2hw_slot_reg_t slot; // [91:60] + dma_reg2hw_src_data_type_reg_t src_data_type; // [59:58] + dma_reg2hw_dst_data_type_reg_t dst_data_type; // [57:56] + dma_reg2hw_sign_ext_reg_t sign_ext; // [55:55] + dma_reg2hw_mode_reg_t mode; // [54:53] + dma_reg2hw_dim_config_reg_t dim_config; // [52:52] + dma_reg2hw_dim_inv_reg_t dim_inv; // [51:51] + dma_reg2hw_pad_top_reg_t pad_top; // [50:45] + dma_reg2hw_pad_bottom_reg_t pad_bottom; // [44:39] + dma_reg2hw_pad_right_reg_t pad_right; // [38:33] + dma_reg2hw_pad_left_reg_t pad_left; // [32:27] + dma_reg2hw_window_size_reg_t window_size; // [26:14] + dma_reg2hw_window_count_reg_t window_count; // [13:6] + dma_reg2hw_interrupt_en_reg_t interrupt_en; // [5:4] + dma_reg2hw_transaction_ifr_reg_t transaction_ifr; // [3:2] + dma_reg2hw_window_ifr_reg_t window_ifr; // [1:0] } dma_reg2hw_t; // HW -> register type typedef struct packed { - dma_hw2reg_status_reg_t status; // [34:33] - dma_hw2reg_window_count_reg_t window_count; // [32:0] + dma_hw2reg_status_reg_t status; // [12:11] + dma_hw2reg_window_count_reg_t window_count; // [10:2] + dma_hw2reg_transaction_ifr_reg_t transaction_ifr; // [1:1] + dma_hw2reg_window_ifr_reg_t window_ifr; // [0:0] } dma_hw2reg_t; // Register offsets - parameter logic [BlockAw-1:0] DMA_SRC_PTR_OFFSET = 6'h0; - parameter logic [BlockAw-1:0] DMA_DST_PTR_OFFSET = 6'h4; - parameter logic [BlockAw-1:0] DMA_ADDR_PTR_OFFSET = 6'h8; - parameter logic [BlockAw-1:0] DMA_SIZE_OFFSET = 6'hc; - parameter logic [BlockAw-1:0] DMA_STATUS_OFFSET = 6'h10; - parameter logic [BlockAw-1:0] DMA_PTR_INC_OFFSET = 6'h14; - parameter logic [BlockAw-1:0] DMA_SLOT_OFFSET = 6'h18; - parameter logic [BlockAw-1:0] DMA_DATA_TYPE_OFFSET = 6'h1c; - parameter logic [BlockAw-1:0] DMA_MODE_OFFSET = 6'h20; - parameter logic [BlockAw-1:0] DMA_WINDOW_SIZE_OFFSET = 6'h24; - parameter logic [BlockAw-1:0] DMA_WINDOW_COUNT_OFFSET = 6'h28; - parameter logic [BlockAw-1:0] DMA_INTERRUPT_EN_OFFSET = 6'h2c; + parameter logic [BlockAw-1:0] DMA_SRC_PTR_OFFSET = 7'h0; + parameter logic [BlockAw-1:0] DMA_DST_PTR_OFFSET = 7'h4; + parameter logic [BlockAw-1:0] DMA_ADDR_PTR_OFFSET = 7'h8; + parameter logic [BlockAw-1:0] DMA_SIZE_D1_OFFSET = 7'hc; + parameter logic [BlockAw-1:0] DMA_SIZE_D2_OFFSET = 7'h10; + parameter logic [BlockAw-1:0] DMA_STATUS_OFFSET = 7'h14; + parameter logic [BlockAw-1:0] DMA_SRC_PTR_INC_D1_OFFSET = 7'h18; + parameter logic [BlockAw-1:0] DMA_SRC_PTR_INC_D2_OFFSET = 7'h1c; + parameter logic [BlockAw-1:0] DMA_DST_PTR_INC_D1_OFFSET = 7'h20; + parameter logic [BlockAw-1:0] DMA_DST_PTR_INC_D2_OFFSET = 7'h24; + parameter logic [BlockAw-1:0] DMA_SLOT_OFFSET = 7'h28; + parameter logic [BlockAw-1:0] DMA_SRC_DATA_TYPE_OFFSET = 7'h2c; + parameter logic [BlockAw-1:0] DMA_DST_DATA_TYPE_OFFSET = 7'h30; + parameter logic [BlockAw-1:0] DMA_SIGN_EXT_OFFSET = 7'h34; + parameter logic [BlockAw-1:0] DMA_MODE_OFFSET = 7'h38; + parameter logic [BlockAw-1:0] DMA_DIM_CONFIG_OFFSET = 7'h3c; + parameter logic [BlockAw-1:0] DMA_DIM_INV_OFFSET = 7'h40; + parameter logic [BlockAw-1:0] DMA_PAD_TOP_OFFSET = 7'h44; + parameter logic [BlockAw-1:0] DMA_PAD_BOTTOM_OFFSET = 7'h48; + parameter logic [BlockAw-1:0] DMA_PAD_RIGHT_OFFSET = 7'h4c; + parameter logic [BlockAw-1:0] DMA_PAD_LEFT_OFFSET = 7'h50; + parameter logic [BlockAw-1:0] DMA_WINDOW_SIZE_OFFSET = 7'h54; + parameter logic [BlockAw-1:0] DMA_WINDOW_COUNT_OFFSET = 7'h58; + parameter logic [BlockAw-1:0] DMA_INTERRUPT_EN_OFFSET = 7'h5c; + parameter logic [BlockAw-1:0] DMA_TRANSACTION_IFR_OFFSET = 7'h60; + parameter logic [BlockAw-1:0] DMA_WINDOW_IFR_OFFSET = 7'h64; // Reset values for hwext registers and their fields parameter logic [1:0] DMA_STATUS_RESVAL = 2'h1; parameter logic [0:0] DMA_STATUS_READY_RESVAL = 1'h1; parameter logic [0:0] DMA_STATUS_WINDOW_DONE_RESVAL = 1'h0; + parameter logic [0:0] DMA_TRANSACTION_IFR_RESVAL = 1'h0; + parameter logic [0:0] DMA_TRANSACTION_IFR_FLAG_RESVAL = 1'h0; + parameter logic [0:0] DMA_WINDOW_IFR_RESVAL = 1'h0; + parameter logic [0:0] DMA_WINDOW_IFR_FLAG_RESVAL = 1'h0; // Register index typedef enum int { DMA_SRC_PTR, DMA_DST_PTR, DMA_ADDR_PTR, - DMA_SIZE, + DMA_SIZE_D1, + DMA_SIZE_D2, DMA_STATUS, - DMA_PTR_INC, + DMA_SRC_PTR_INC_D1, + DMA_SRC_PTR_INC_D2, + DMA_DST_PTR_INC_D1, + DMA_DST_PTR_INC_D2, DMA_SLOT, - DMA_DATA_TYPE, + DMA_SRC_DATA_TYPE, + DMA_DST_DATA_TYPE, + DMA_SIGN_EXT, DMA_MODE, + DMA_DIM_CONFIG, + DMA_DIM_INV, + DMA_PAD_TOP, + DMA_PAD_BOTTOM, + DMA_PAD_RIGHT, + DMA_PAD_LEFT, DMA_WINDOW_SIZE, DMA_WINDOW_COUNT, - DMA_INTERRUPT_EN + DMA_INTERRUPT_EN, + DMA_TRANSACTION_IFR, + DMA_WINDOW_IFR } dma_id_e; // Register width information to check illegal writes - parameter logic [3:0] DMA_PERMIT[12] = '{ + parameter logic [3:0] DMA_PERMIT[26] = '{ 4'b1111, // index[ 0] DMA_SRC_PTR 4'b1111, // index[ 1] DMA_DST_PTR 4'b1111, // index[ 2] DMA_ADDR_PTR - 4'b1111, // index[ 3] DMA_SIZE - 4'b0001, // index[ 4] DMA_STATUS - 4'b0011, // index[ 5] DMA_PTR_INC - 4'b1111, // index[ 6] DMA_SLOT - 4'b0001, // index[ 7] DMA_DATA_TYPE - 4'b0001, // index[ 8] DMA_MODE - 4'b1111, // index[ 9] DMA_WINDOW_SIZE - 4'b1111, // index[10] DMA_WINDOW_COUNT - 4'b0001 // index[11] DMA_INTERRUPT_EN + 4'b0011, // index[ 3] DMA_SIZE_D1 + 4'b0011, // index[ 4] DMA_SIZE_D2 + 4'b0001, // index[ 5] DMA_STATUS + 4'b0001, // index[ 6] DMA_SRC_PTR_INC_D1 + 4'b0111, // index[ 7] DMA_SRC_PTR_INC_D2 + 4'b0001, // index[ 8] DMA_DST_PTR_INC_D1 + 4'b0111, // index[ 9] DMA_DST_PTR_INC_D2 + 4'b1111, // index[10] DMA_SLOT + 4'b0001, // index[11] DMA_SRC_DATA_TYPE + 4'b0001, // index[12] DMA_DST_DATA_TYPE + 4'b0001, // index[13] DMA_SIGN_EXT + 4'b0001, // index[14] DMA_MODE + 4'b0001, // index[15] DMA_DIM_CONFIG + 4'b0001, // index[16] DMA_DIM_INV + 4'b0001, // index[17] DMA_PAD_TOP + 4'b0001, // index[18] DMA_PAD_BOTTOM + 4'b0001, // index[19] DMA_PAD_RIGHT + 4'b0001, // index[20] DMA_PAD_LEFT + 4'b0011, // index[21] DMA_WINDOW_SIZE + 4'b0001, // index[22] DMA_WINDOW_COUNT + 4'b0001, // index[23] DMA_INTERRUPT_EN + 4'b0001, // index[24] DMA_TRANSACTION_IFR + 4'b0001 // index[25] DMA_WINDOW_IFR }; endpackage diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_reg_top.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_reg_top.sv index 4a3ff6d0..ea7897c0 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_reg_top.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma/rtl/dma_reg_top.sv @@ -10,7 +10,7 @@ module dma_reg_top #( parameter type reg_req_t = logic, parameter type reg_rsp_t = logic, - parameter int AW = 6 + parameter int AW = 7 ) ( input logic clk_i, input logic rst_ni, @@ -77,41 +77,78 @@ module dma_reg_top #( logic [31:0] addr_ptr_qs; logic [31:0] addr_ptr_wd; logic addr_ptr_we; - logic [31:0] size_qs; - logic [31:0] size_wd; - logic size_we; + logic [15:0] size_d1_qs; + logic [15:0] size_d1_wd; + logic size_d1_we; + logic [15:0] size_d2_qs; + logic [15:0] size_d2_wd; + logic size_d2_we; logic status_ready_qs; logic status_ready_re; logic status_window_done_qs; logic status_window_done_re; - logic [7:0] ptr_inc_src_ptr_inc_qs; - logic [7:0] ptr_inc_src_ptr_inc_wd; - logic ptr_inc_src_ptr_inc_we; - logic [7:0] ptr_inc_dst_ptr_inc_qs; - logic [7:0] ptr_inc_dst_ptr_inc_wd; - logic ptr_inc_dst_ptr_inc_we; + logic [5:0] src_ptr_inc_d1_qs; + logic [5:0] src_ptr_inc_d1_wd; + logic src_ptr_inc_d1_we; + logic [22:0] src_ptr_inc_d2_qs; + logic [22:0] src_ptr_inc_d2_wd; + logic src_ptr_inc_d2_we; + logic [5:0] dst_ptr_inc_d1_qs; + logic [5:0] dst_ptr_inc_d1_wd; + logic dst_ptr_inc_d1_we; + logic [22:0] dst_ptr_inc_d2_qs; + logic [22:0] dst_ptr_inc_d2_wd; + logic dst_ptr_inc_d2_we; logic [15:0] slot_rx_trigger_slot_qs; logic [15:0] slot_rx_trigger_slot_wd; logic slot_rx_trigger_slot_we; logic [15:0] slot_tx_trigger_slot_qs; logic [15:0] slot_tx_trigger_slot_wd; logic slot_tx_trigger_slot_we; - logic [1:0] data_type_qs; - logic [1:0] data_type_wd; - logic data_type_we; + logic [1:0] src_data_type_qs; + logic [1:0] src_data_type_wd; + logic src_data_type_we; + logic [1:0] dst_data_type_qs; + logic [1:0] dst_data_type_wd; + logic dst_data_type_we; + logic sign_ext_qs; + logic sign_ext_wd; + logic sign_ext_we; logic [1:0] mode_qs; logic [1:0] mode_wd; logic mode_we; - logic [31:0] window_size_qs; - logic [31:0] window_size_wd; + logic dim_config_qs; + logic dim_config_wd; + logic dim_config_we; + logic dim_inv_qs; + logic dim_inv_wd; + logic dim_inv_we; + logic [5:0] pad_top_qs; + logic [5:0] pad_top_wd; + logic pad_top_we; + logic [5:0] pad_bottom_qs; + logic [5:0] pad_bottom_wd; + logic pad_bottom_we; + logic [5:0] pad_right_qs; + logic [5:0] pad_right_wd; + logic pad_right_we; + logic [5:0] pad_left_qs; + logic [5:0] pad_left_wd; + logic pad_left_we; + logic [12:0] window_size_qs; + logic [12:0] window_size_wd; logic window_size_we; - logic [31:0] window_count_qs; + logic [7:0] window_count_qs; logic interrupt_en_transaction_done_qs; logic interrupt_en_transaction_done_wd; logic interrupt_en_transaction_done_we; logic interrupt_en_window_done_qs; logic interrupt_en_window_done_wd; logic interrupt_en_window_done_we; + logic transaction_ifr_qs; + logic transaction_ifr_re; + logic window_ifr_qs; + logic window_ifr_re; // Register instances // R[src_ptr]: V(False) @@ -195,30 +232,57 @@ module dma_reg_top #( ); - // R[size]: V(False) + // R[size_d1]: V(False) prim_subreg #( - .DW (32), + .DW (16), .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_size ( + .RESVAL (16'h0) + ) u_size_d1 ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(size_d1_we), + .wd(size_d1_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(reg2hw.size_d1.qe), + .q (reg2hw.size_d1.q), + + // to register interface (read) + .qs(size_d1_qs) + ); + + + // R[size_d2]: V(False) + + prim_subreg #( + .DW (16), + .SWACCESS("RW"), + .RESVAL (16'h0) + ) u_size_d2 ( .clk_i (clk_i), .rst_ni(rst_ni), // from register interface - .we(size_we), - .wd(size_wd), + .we(size_d2_we), + .wd(size_d2_wd), // from internal hardware .de(1'b0), .d ('0), // to internal hardware - .qe(reg2hw.size.qe), - .q (reg2hw.size.q), + .qe(), + .q (reg2hw.size_d2.q), // to register interface (read) - .qs(size_qs) + .qs(size_d2_qs) ); @@ -254,20 +318,19 @@ module dma_reg_top #( ); - // R[ptr_inc]: V(False) + // R[src_ptr_inc_d1]: V(False) - // F[src_ptr_inc]: 7:0 prim_subreg #( - .DW (8), + .DW (6), .SWACCESS("RW"), - .RESVAL (8'h4) - ) u_ptr_inc_src_ptr_inc ( + .RESVAL (6'h4) + ) u_src_ptr_inc_d1 ( .clk_i (clk_i), .rst_ni(rst_ni), // from register interface - .we(ptr_inc_src_ptr_inc_we), - .wd(ptr_inc_src_ptr_inc_wd), + .we(src_ptr_inc_d1_we), + .wd(src_ptr_inc_d1_wd), // from internal hardware .de(1'b0), @@ -275,25 +338,26 @@ module dma_reg_top #( // to internal hardware .qe(), - .q (reg2hw.ptr_inc.src_ptr_inc.q), + .q (reg2hw.src_ptr_inc_d1.q), // to register interface (read) - .qs(ptr_inc_src_ptr_inc_qs) + .qs(src_ptr_inc_d1_qs) ); - // F[dst_ptr_inc]: 15:8 + // R[src_ptr_inc_d2]: V(False) + prim_subreg #( - .DW (8), + .DW (23), .SWACCESS("RW"), - .RESVAL (8'h4) - ) u_ptr_inc_dst_ptr_inc ( + .RESVAL (23'h4) + ) u_src_ptr_inc_d2 ( .clk_i (clk_i), .rst_ni(rst_ni), // from register interface - .we(ptr_inc_dst_ptr_inc_we), - .wd(ptr_inc_dst_ptr_inc_wd), + .we(src_ptr_inc_d2_we), + .wd(src_ptr_inc_d2_wd), // from internal hardware .de(1'b0), @@ -301,10 +365,64 @@ module dma_reg_top #( // to internal hardware .qe(), - .q (reg2hw.ptr_inc.dst_ptr_inc.q), + .q (reg2hw.src_ptr_inc_d2.q), // to register interface (read) - .qs(ptr_inc_dst_ptr_inc_qs) + .qs(src_ptr_inc_d2_qs) + ); + + + // R[dst_ptr_inc_d1]: V(False) + + prim_subreg #( + .DW (6), + .SWACCESS("RW"), + .RESVAL (6'h4) + ) u_dst_ptr_inc_d1 ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(dst_ptr_inc_d1_we), + .wd(dst_ptr_inc_d1_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.dst_ptr_inc_d1.q), + + // to register interface (read) + .qs(dst_ptr_inc_d1_qs) + ); + + + // R[dst_ptr_inc_d2]: V(False) + + prim_subreg #( + .DW (23), + .SWACCESS("RW"), + .RESVAL (23'h4) + ) u_dst_ptr_inc_d2 ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(dst_ptr_inc_d2_we), + .wd(dst_ptr_inc_d2_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.dst_ptr_inc_d2.q), + + // to register interface (read) + .qs(dst_ptr_inc_d2_qs) ); @@ -362,19 +480,73 @@ module dma_reg_top #( ); - // R[data_type]: V(False) + // R[src_data_type]: V(False) + + prim_subreg #( + .DW (2), + .SWACCESS("RW"), + .RESVAL (2'h0) + ) u_src_data_type ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(src_data_type_we), + .wd(src_data_type_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.src_data_type.q), + + // to register interface (read) + .qs(src_data_type_qs) + ); + + + // R[dst_data_type]: V(False) prim_subreg #( .DW (2), .SWACCESS("RW"), .RESVAL (2'h0) - ) u_data_type ( + ) u_dst_data_type ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(dst_data_type_we), + .wd(dst_data_type_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.dst_data_type.q), + + // to register interface (read) + .qs(dst_data_type_qs) + ); + + + // R[sign_ext]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_sign_ext ( .clk_i (clk_i), .rst_ni(rst_ni), // from register interface - .we(data_type_we), - .wd(data_type_wd), + .we(sign_ext_we), + .wd(sign_ext_wd), // from internal hardware .de(1'b0), @@ -382,10 +554,10 @@ module dma_reg_top #( // to internal hardware .qe(), - .q (reg2hw.data_type.q), + .q (reg2hw.sign_ext.q), // to register interface (read) - .qs(data_type_qs) + .qs(sign_ext_qs) ); @@ -416,12 +588,174 @@ module dma_reg_top #( ); + // R[dim_config]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_dim_config ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(dim_config_we), + .wd(dim_config_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.dim_config.q), + + // to register interface (read) + .qs(dim_config_qs) + ); + + + // R[dim_inv]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_dim_inv ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(dim_inv_we), + .wd(dim_inv_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.dim_inv.q), + + // to register interface (read) + .qs(dim_inv_qs) + ); + + + // R[pad_top]: V(False) + + prim_subreg #( + .DW (6), + .SWACCESS("RW"), + .RESVAL (6'h0) + ) u_pad_top ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(pad_top_we), + .wd(pad_top_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.pad_top.q), + + // to register interface (read) + .qs(pad_top_qs) + ); + + + // R[pad_bottom]: V(False) + + prim_subreg #( + .DW (6), + .SWACCESS("RW"), + .RESVAL (6'h0) + ) u_pad_bottom ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(pad_bottom_we), + .wd(pad_bottom_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.pad_bottom.q), + + // to register interface (read) + .qs(pad_bottom_qs) + ); + + + // R[pad_right]: V(False) + + prim_subreg #( + .DW (6), + .SWACCESS("RW"), + .RESVAL (6'h0) + ) u_pad_right ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(pad_right_we), + .wd(pad_right_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.pad_right.q), + + // to register interface (read) + .qs(pad_right_qs) + ); + + + // R[pad_left]: V(False) + + prim_subreg #( + .DW (6), + .SWACCESS("RW"), + .RESVAL (6'h0) + ) u_pad_left ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(pad_left_we), + .wd(pad_left_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.pad_left.q), + + // to register interface (read) + .qs(pad_left_qs) + ); + + // R[window_size]: V(False) prim_subreg #( - .DW (32), + .DW (13), .SWACCESS("RW"), - .RESVAL (32'h0) + .RESVAL (13'h0) ) u_window_size ( .clk_i (clk_i), .rst_ni(rst_ni), @@ -446,9 +780,9 @@ module dma_reg_top #( // R[window_count]: V(False) prim_subreg #( - .DW (32), + .DW (8), .SWACCESS("RO"), - .RESVAL (32'h0) + .RESVAL (8'h0) ) u_window_count ( .clk_i (clk_i), .rst_ni(rst_ni), @@ -523,23 +857,69 @@ module dma_reg_top #( ); + // R[transaction_ifr]: V(True) + + prim_subreg_ext #( + .DW(1) + ) u_transaction_ifr ( + .re (transaction_ifr_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.transaction_ifr.d), + .qre(reg2hw.transaction_ifr.re), + .qe (), + .q (reg2hw.transaction_ifr.q), + .qs (transaction_ifr_qs) + ); + + + // R[window_ifr]: V(True) + + prim_subreg_ext #( + .DW(1) + ) u_window_ifr ( + .re (window_ifr_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.window_ifr.d), + .qre(reg2hw.window_ifr.re), + .qe (), + .q (reg2hw.window_ifr.q), + .qs (window_ifr_qs) + ); + + - logic [11:0] addr_hit; + logic [25:0] addr_hit; always_comb begin addr_hit = '0; addr_hit[0] = (reg_addr == DMA_SRC_PTR_OFFSET); addr_hit[1] = (reg_addr == DMA_DST_PTR_OFFSET); addr_hit[2] = (reg_addr == DMA_ADDR_PTR_OFFSET); - addr_hit[3] = (reg_addr == DMA_SIZE_OFFSET); - addr_hit[4] = (reg_addr == DMA_STATUS_OFFSET); - addr_hit[5] = (reg_addr == DMA_PTR_INC_OFFSET); - addr_hit[6] = (reg_addr == DMA_SLOT_OFFSET); - addr_hit[7] = (reg_addr == DMA_DATA_TYPE_OFFSET); - addr_hit[8] = (reg_addr == DMA_MODE_OFFSET); - addr_hit[9] = (reg_addr == DMA_WINDOW_SIZE_OFFSET); - addr_hit[10] = (reg_addr == DMA_WINDOW_COUNT_OFFSET); - addr_hit[11] = (reg_addr == DMA_INTERRUPT_EN_OFFSET); + addr_hit[3] = (reg_addr == DMA_SIZE_D1_OFFSET); + addr_hit[4] = (reg_addr == DMA_SIZE_D2_OFFSET); + addr_hit[5] = (reg_addr == DMA_STATUS_OFFSET); + addr_hit[6] = (reg_addr == DMA_SRC_PTR_INC_D1_OFFSET); + addr_hit[7] = (reg_addr == DMA_SRC_PTR_INC_D2_OFFSET); + addr_hit[8] = (reg_addr == DMA_DST_PTR_INC_D1_OFFSET); + addr_hit[9] = (reg_addr == DMA_DST_PTR_INC_D2_OFFSET); + addr_hit[10] = (reg_addr == DMA_SLOT_OFFSET); + addr_hit[11] = (reg_addr == DMA_SRC_DATA_TYPE_OFFSET); + addr_hit[12] = (reg_addr == DMA_DST_DATA_TYPE_OFFSET); + addr_hit[13] = (reg_addr == DMA_SIGN_EXT_OFFSET); + addr_hit[14] = (reg_addr == DMA_MODE_OFFSET); + addr_hit[15] = (reg_addr == DMA_DIM_CONFIG_OFFSET); + addr_hit[16] = (reg_addr == DMA_DIM_INV_OFFSET); + addr_hit[17] = (reg_addr == DMA_PAD_TOP_OFFSET); + addr_hit[18] = (reg_addr == DMA_PAD_BOTTOM_OFFSET); + addr_hit[19] = (reg_addr == DMA_PAD_RIGHT_OFFSET); + addr_hit[20] = (reg_addr == DMA_PAD_LEFT_OFFSET); + addr_hit[21] = (reg_addr == DMA_WINDOW_SIZE_OFFSET); + addr_hit[22] = (reg_addr == DMA_WINDOW_COUNT_OFFSET); + addr_hit[23] = (reg_addr == DMA_INTERRUPT_EN_OFFSET); + addr_hit[24] = (reg_addr == DMA_TRANSACTION_IFR_OFFSET); + addr_hit[25] = (reg_addr == DMA_WINDOW_IFR_OFFSET); end assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0; @@ -558,7 +938,21 @@ module dma_reg_top #( (addr_hit[ 8] & (|(DMA_PERMIT[ 8] & ~reg_be))) | (addr_hit[ 9] & (|(DMA_PERMIT[ 9] & ~reg_be))) | (addr_hit[10] & (|(DMA_PERMIT[10] & ~reg_be))) | - (addr_hit[11] & (|(DMA_PERMIT[11] & ~reg_be))))); + (addr_hit[11] & (|(DMA_PERMIT[11] & ~reg_be))) | + (addr_hit[12] & (|(DMA_PERMIT[12] & ~reg_be))) | + (addr_hit[13] & (|(DMA_PERMIT[13] & ~reg_be))) | + (addr_hit[14] & (|(DMA_PERMIT[14] & ~reg_be))) | + (addr_hit[15] & (|(DMA_PERMIT[15] & ~reg_be))) | + (addr_hit[16] & (|(DMA_PERMIT[16] & ~reg_be))) | + (addr_hit[17] & (|(DMA_PERMIT[17] & ~reg_be))) | + (addr_hit[18] & (|(DMA_PERMIT[18] & ~reg_be))) | + (addr_hit[19] & (|(DMA_PERMIT[19] & ~reg_be))) | + (addr_hit[20] & (|(DMA_PERMIT[20] & ~reg_be))) | + (addr_hit[21] & (|(DMA_PERMIT[21] & ~reg_be))) | + (addr_hit[22] & (|(DMA_PERMIT[22] & ~reg_be))) | + (addr_hit[23] & (|(DMA_PERMIT[23] & ~reg_be))) | + (addr_hit[24] & (|(DMA_PERMIT[24] & ~reg_be))) | + (addr_hit[25] & (|(DMA_PERMIT[25] & ~reg_be))))); end assign src_ptr_we = addr_hit[0] & reg_we & !reg_error; @@ -570,40 +964,77 @@ module dma_reg_top #( assign addr_ptr_we = addr_hit[2] & reg_we & !reg_error; assign addr_ptr_wd = reg_wdata[31:0]; - assign size_we = addr_hit[3] & reg_we & !reg_error; - assign size_wd = reg_wdata[31:0]; + assign size_d1_we = addr_hit[3] & reg_we & !reg_error; + assign size_d1_wd = reg_wdata[15:0]; - assign status_ready_re = addr_hit[4] & reg_re & !reg_error; + assign size_d2_we = addr_hit[4] & reg_we & !reg_error; + assign size_d2_wd = reg_wdata[15:0]; - assign status_window_done_re = addr_hit[4] & reg_re & !reg_error; + assign status_ready_re = addr_hit[5] & reg_re & !reg_error; - assign ptr_inc_src_ptr_inc_we = addr_hit[5] & reg_we & !reg_error; - assign ptr_inc_src_ptr_inc_wd = reg_wdata[7:0]; + assign status_window_done_re = addr_hit[5] & reg_re & !reg_error; - assign ptr_inc_dst_ptr_inc_we = addr_hit[5] & reg_we & !reg_error; - assign ptr_inc_dst_ptr_inc_wd = reg_wdata[15:8]; + assign src_ptr_inc_d1_we = addr_hit[6] & reg_we & !reg_error; + assign src_ptr_inc_d1_wd = reg_wdata[5:0]; - assign slot_rx_trigger_slot_we = addr_hit[6] & reg_we & !reg_error; + assign src_ptr_inc_d2_we = addr_hit[7] & reg_we & !reg_error; + assign src_ptr_inc_d2_wd = reg_wdata[22:0]; + + assign dst_ptr_inc_d1_we = addr_hit[8] & reg_we & !reg_error; + assign dst_ptr_inc_d1_wd = reg_wdata[5:0]; + + assign dst_ptr_inc_d2_we = addr_hit[9] & reg_we & !reg_error; + assign dst_ptr_inc_d2_wd = reg_wdata[22:0]; + + assign slot_rx_trigger_slot_we = addr_hit[10] & reg_we & !reg_error; assign slot_rx_trigger_slot_wd = reg_wdata[15:0]; - assign slot_tx_trigger_slot_we = addr_hit[6] & reg_we & !reg_error; + assign slot_tx_trigger_slot_we = addr_hit[10] & reg_we & !reg_error; assign slot_tx_trigger_slot_wd = reg_wdata[31:16]; - assign data_type_we = addr_hit[7] & reg_we & !reg_error; - assign data_type_wd = reg_wdata[1:0]; + assign src_data_type_we = addr_hit[11] & reg_we & !reg_error; + assign src_data_type_wd = reg_wdata[1:0]; + + assign dst_data_type_we = addr_hit[12] & reg_we & !reg_error; + assign dst_data_type_wd = reg_wdata[1:0]; + + assign sign_ext_we = addr_hit[13] & reg_we & !reg_error; + assign sign_ext_wd = reg_wdata[0]; - assign mode_we = addr_hit[8] & reg_we & !reg_error; + assign mode_we = addr_hit[14] & reg_we & !reg_error; assign mode_wd = reg_wdata[1:0]; - assign window_size_we = addr_hit[9] & reg_we & !reg_error; - assign window_size_wd = reg_wdata[31:0]; + assign dim_config_we = addr_hit[15] & reg_we & !reg_error; + assign dim_config_wd = reg_wdata[0]; - assign interrupt_en_transaction_done_we = addr_hit[11] & reg_we & !reg_error; + assign dim_inv_we = addr_hit[16] & reg_we & !reg_error; + assign dim_inv_wd = reg_wdata[0]; + + assign pad_top_we = addr_hit[17] & reg_we & !reg_error; + assign pad_top_wd = reg_wdata[5:0]; + + assign pad_bottom_we = addr_hit[18] & reg_we & !reg_error; + assign pad_bottom_wd = reg_wdata[5:0]; + + assign pad_right_we = addr_hit[19] & reg_we & !reg_error; + assign pad_right_wd = reg_wdata[5:0]; + + assign pad_left_we = addr_hit[20] & reg_we & !reg_error; + assign pad_left_wd = reg_wdata[5:0]; + + assign window_size_we = addr_hit[21] & reg_we & !reg_error; + assign window_size_wd = reg_wdata[12:0]; + + assign interrupt_en_transaction_done_we = addr_hit[23] & reg_we & !reg_error; assign interrupt_en_transaction_done_wd = reg_wdata[0]; - assign interrupt_en_window_done_we = addr_hit[11] & reg_we & !reg_error; + assign interrupt_en_window_done_we = addr_hit[23] & reg_we & !reg_error; assign interrupt_en_window_done_wd = reg_wdata[1]; + assign transaction_ifr_re = addr_hit[24] & reg_re & !reg_error; + + assign window_ifr_re = addr_hit[25] & reg_re & !reg_error; + // Read data return always_comb begin reg_rdata_next = '0; @@ -621,45 +1052,100 @@ module dma_reg_top #( end addr_hit[3]: begin - reg_rdata_next[31:0] = size_qs; + reg_rdata_next[15:0] = size_d1_qs; end addr_hit[4]: begin - reg_rdata_next[0] = status_ready_qs; - reg_rdata_next[1] = status_window_done_qs; + reg_rdata_next[15:0] = size_d2_qs; end addr_hit[5]: begin - reg_rdata_next[7:0] = ptr_inc_src_ptr_inc_qs; - reg_rdata_next[15:8] = ptr_inc_dst_ptr_inc_qs; + reg_rdata_next[0] = status_ready_qs; + reg_rdata_next[1] = status_window_done_qs; end addr_hit[6]: begin - reg_rdata_next[15:0] = slot_rx_trigger_slot_qs; - reg_rdata_next[31:16] = slot_tx_trigger_slot_qs; + reg_rdata_next[5:0] = src_ptr_inc_d1_qs; end addr_hit[7]: begin - reg_rdata_next[1:0] = data_type_qs; + reg_rdata_next[22:0] = src_ptr_inc_d2_qs; end addr_hit[8]: begin - reg_rdata_next[1:0] = mode_qs; + reg_rdata_next[5:0] = dst_ptr_inc_d1_qs; end addr_hit[9]: begin - reg_rdata_next[31:0] = window_size_qs; + reg_rdata_next[22:0] = dst_ptr_inc_d2_qs; end addr_hit[10]: begin - reg_rdata_next[31:0] = window_count_qs; + reg_rdata_next[15:0] = slot_rx_trigger_slot_qs; + reg_rdata_next[31:16] = slot_tx_trigger_slot_qs; end addr_hit[11]: begin + reg_rdata_next[1:0] = src_data_type_qs; + end + + addr_hit[12]: begin + reg_rdata_next[1:0] = dst_data_type_qs; + end + + addr_hit[13]: begin + reg_rdata_next[0] = sign_ext_qs; + end + + addr_hit[14]: begin + reg_rdata_next[1:0] = mode_qs; + end + + addr_hit[15]: begin + reg_rdata_next[0] = dim_config_qs; + end + + addr_hit[16]: begin + reg_rdata_next[0] = dim_inv_qs; + end + + addr_hit[17]: begin + reg_rdata_next[5:0] = pad_top_qs; + end + + addr_hit[18]: begin + reg_rdata_next[5:0] = pad_bottom_qs; + end + + addr_hit[19]: begin + reg_rdata_next[5:0] = pad_right_qs; + end + + addr_hit[20]: begin + reg_rdata_next[5:0] = pad_left_qs; + end + + addr_hit[21]: begin + reg_rdata_next[12:0] = window_size_qs; + end + + addr_hit[22]: begin + reg_rdata_next[7:0] = window_count_qs; + end + + addr_hit[23]: begin reg_rdata_next[0] = interrupt_en_transaction_done_qs; reg_rdata_next[1] = interrupt_en_window_done_qs; end + addr_hit[24]: begin + reg_rdata_next[0] = transaction_ifr_qs; + end + + addr_hit[25]: begin + reg_rdata_next[0] = window_ifr_qs; + end + default: begin reg_rdata_next = '1; end @@ -681,7 +1167,7 @@ module dma_reg_top #( endmodule module dma_reg_top_intf #( - parameter int AW = 6, + parameter int AW = 7, localparam int DW = 32 ) ( input logic clk_i, diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma_subsystem/dma_subsystem.core b/hw/vendor/esl_epfl_x_heep/hw/ip/dma_subsystem/dma_subsystem.core new file mode 100644 index 00000000..d611de9d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma_subsystem/dma_subsystem.core @@ -0,0 +1,22 @@ +CAPI=2: + +name: "x-heep:ip:dma_subsystem" +description: "core-v-mini-mcu dma peripheral" + +# Copyright 2021 OpenHW Group +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +filesets: + files_rtl: + depend: + - pulp-platform.org::common_cells + files: + - rtl/dma_subsystem.sv + - rtl/dma_NtoM_xbar.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_rtl diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma_subsystem/dma_subsystem.vlt b/hw/vendor/esl_epfl_x_heep/hw/ip/dma_subsystem/dma_subsystem.vlt new file mode 100644 index 00000000..a914d355 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma_subsystem/dma_subsystem.vlt @@ -0,0 +1,10 @@ +// Copyright 2022 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +`verilator_config + +lint_off -rule UNUSED -file "*/rtl/dma_subsystem.sv" -match "Signal is not used: 'data_out_rvalid'" +lint_off -rule UNUSED -file "*/rtl/dma_subsystem.sv" -match "Signal is not used: 'data_out_rdata'" + +lint_off -rule UNUSED -file "*/rtl/dma_subsystem.sv" -match "Bits of signal are not used: *" diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma_subsystem/rtl/dma_NtoM_xbar.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/dma_subsystem/rtl/dma_NtoM_xbar.sv new file mode 100644 index 00000000..b1a4f39f --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma_subsystem/rtl/dma_NtoM_xbar.sv @@ -0,0 +1,71 @@ +/* + * Copyright 2024 EPFL + * Solderpad Hardware License, Version 2.1, see LICENSE.md for details. + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Author: Tommaso Terzano + * + * + * Info: Generated N-to-M crossbar. + * This module has been developed to be used in the DMA subsystem, in which it is not possible to use an NtoM crossbar. + * The problem is that each slave port of the DMA xbar is actually a master port of the system bus. The DMA xbar slave ports + * cannot be indexed by the master's request address because they all perform the same function, they all can read/write + * to/from the same memory spaces. + * This module is a workaround to this problem, as it is composed by a number of N-to-1 crossbars, each for a different slave + * (which would be a system bus master port). + * The amount of masters per crossbar is defined by the parameter NUM_MASTERS_PER_XBAR. + * It is thus possible, from an application point of view, to use channels that are guaranteed to have a dedicated master port, + * reducing the need for additional arbitration logic. + */ + +module dma_NtoM_xbar #( + parameter int unsigned XBAR_NMASTER = 4, + parameter int unsigned XBAR_MSLAVE = 2 +) ( + input logic clk_i, + input logic rst_ni, + + // Master ports + input obi_pkg::obi_req_t [XBAR_NMASTER-1:0] master_req_i, + output obi_pkg::obi_resp_t [XBAR_NMASTER-1:0] master_resp_o, + + // slave ports + output obi_pkg::obi_req_t [XBAR_MSLAVE-1:0] slave_req_o, + input obi_pkg::obi_resp_t [XBAR_MSLAVE-1:0] slave_resp_i +); + import obi_pkg::*; + import core_v_mini_mcu_pkg::*; + + /* Generation of the crossbars */ + generate + xbar_varlat_n_to_one #( + .XBAR_NMASTER(core_v_mini_mcu_pkg::DMA_XBAR_MASTERS[0]) + ) xbar_i ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .master_req_i(master_req_i[core_v_mini_mcu_pkg::DMA_XBAR_MASTERS[0]-1:0]), + .master_resp_o(master_resp_o[core_v_mini_mcu_pkg::DMA_XBAR_MASTERS[0]-1:0]), + .slave_req_o(slave_req_o[0]), + .slave_resp_i(slave_resp_i[0]) + ); + + for (genvar i = 1; i < XBAR_MSLAVE; i++) begin : gen_xbar + if (core_v_mini_mcu_pkg::DMA_XBAR_MASTERS[i] == 1) begin + assign slave_req_o[i] = master_req_i[i+core_v_mini_mcu_pkg::DMA_XBAR_MASTERS[0]-1]; + assign master_resp_o[i+core_v_mini_mcu_pkg::DMA_XBAR_MASTERS[0]-1] = slave_resp_i[i]; + end else begin + xbar_varlat_n_to_one #( + .XBAR_NMASTER(core_v_mini_mcu_pkg::DMA_XBAR_MASTERS[i]) + ) xbar_i ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .master_req_i(master_req_i[core_v_mini_mcu_pkg::DMA_XBAR_MASTERS[i] + core_v_mini_mcu_pkg::DMA_XBAR_MASTERS[i-1]-1:core_v_mini_mcu_pkg::DMA_XBAR_MASTERS[i-1]]), + .master_resp_o(master_resp_o[core_v_mini_mcu_pkg::DMA_XBAR_MASTERS[i] + core_v_mini_mcu_pkg::DMA_XBAR_MASTERS[i-1]-1:core_v_mini_mcu_pkg::DMA_XBAR_MASTERS[i-1]]), + .slave_req_o(slave_req_o[i]), + .slave_resp_i(slave_resp_i[i]) + ); + end + end + endgenerate + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/dma_subsystem/rtl/dma_subsystem.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/dma_subsystem/rtl/dma_subsystem.sv new file mode 100644 index 00000000..6ac3df37 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/dma_subsystem/rtl/dma_subsystem.sv @@ -0,0 +1,291 @@ +/* + * Copyright 2024 EPFL + * Solderpad Hardware License, Version 2.1, see LICENSE.md for details. + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Author: Tommaso Terzano + * + * + * Info: DMA subsystem, it instantiates 1 to 8 DMA channels and manages the data transfers. + */ + + +module dma_subsystem #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter type obi_req_t = logic, + parameter type obi_resp_t = logic, + parameter int unsigned GLOBAL_SLOT_NUM = 0, + parameter int unsigned EXT_SLOT_NUM = 0 +) ( + input logic clk_i, + input logic rst_ni, + input logic clk_gate_en_ni [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0], + + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] dma_read_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] dma_read_resp_i, + + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] dma_write_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] dma_write_resp_i, + + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] dma_addr_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] dma_addr_resp_i, + + input logic [GLOBAL_SLOT_NUM-1:0] global_trigger_slot_i, + input logic [EXT_SLOT_NUM-1:0] ext_trigger_slot_i, + + input logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] ext_dma_stop_i, + + output dma_done_intr_o, + output dma_window_intr_o, + + output logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] dma_done_o +); + + /*_________________________________________________________________________________________________________________________________ */ + + /* Imports and parameters */ + + import obi_pkg::*; + import reg_pkg::*; + + /* + * It's possible to define individually the sizes of each DMA channel's FIFOs. + * For example, a FIFO_CH_ARRAY like this {L, M, M, S} means that CH0 will be small, + * CH1 and CH2 will be medium and CH3 will be large. + * + * This is useful in applications that require different bandwidths for different channels. + * To enable this functionality, decomment EN_SET_FIFO_CH_SIZE and set the desired sizes. + */ + + //`define EN_SET_FIFO_CH_SIZE; + + `ifdef EN_SET_FIFO_CH_SIZE + + localparam int unsigned LARGE_FIFO_CH_SIZE = 8; + localparam int unsigned MEDIUM_FIFO_CH_SIZE = 4; + localparam int unsigned SMALL_FIFO_CH_SIZE = 2; + + typedef enum {L, M, S} fifo_ch_size_t; + + localparam fifo_ch_size_t FIFO_CH_ARRAY [core_v_mini_mcu_pkg::DMA_CH_NUM] = '{L, M, M, S}; + + `endif + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signals declaration */ + + /* Masters requests to the bus */ + obi_req_t [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] xbar_write_req; + obi_req_t [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] xbar_read_req; + obi_req_t [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] xbar_address_req; + + /* Masters response from the bus*/ + obi_resp_t [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] xbar_write_resp; + obi_resp_t [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] xbar_read_resp; + obi_resp_t [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] xbar_address_resp; + + /* Interrupt signals */ + logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] dma_trans_done; + logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] dma_window_done; + + /* Register interfaces from register demux to DMAs */ + reg_pkg::reg_req_t [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] submodules_req; + reg_pkg::reg_rsp_t [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] submodules_rsp; + + /*_________________________________________________________________________________________________________________________________ */ + + /* Module instantiation */ + + /* DMA modules */ + generate + for (genvar i = 0; i < core_v_mini_mcu_pkg::DMA_CH_NUM; i++) begin : dma_i_gen + + /* FIFO size assignment */ + localparam int fifo_size = + `ifdef EN_SET_FIFO_CH_SIZE + (FIFO_CH_ARRAY[i] == L) ? LARGE_FIFO_CH_SIZE : + ((FIFO_CH_ARRAY[i] == M) ? MEDIUM_FIFO_CH_SIZE : SMALL_FIFO_CH_SIZE); + `else + 4; + `endif + + dma #( + .reg_req_t (reg_pkg::reg_req_t), + .reg_rsp_t (reg_pkg::reg_rsp_t), + .obi_req_t (obi_pkg::obi_req_t), + .obi_resp_t(obi_pkg::obi_resp_t), + .SLOT_NUM (GLOBAL_SLOT_NUM + 2), + .FIFO_DEPTH (fifo_size) + ) dma_i ( + .clk_i, + .rst_ni, + .clk_gate_en_ni(clk_gate_en_ni[i]), + .ext_dma_stop_i(ext_dma_stop_i[i]), + .reg_req_i(submodules_req[i]), + .reg_rsp_o(submodules_rsp[i]), + .dma_read_req_o(xbar_read_req[i]), + .dma_read_resp_i(xbar_read_resp[i]), + .dma_write_req_o(xbar_write_req[i]), + .dma_write_resp_i(xbar_write_resp[i]), + .dma_addr_req_o(xbar_address_req[i]), + .dma_addr_resp_i(xbar_address_resp[i]), + .trigger_slot_i({ + ext_trigger_slot_i[2*i+1], ext_trigger_slot_i[2*i], global_trigger_slot_i + }), + .dma_done_intr_o(dma_trans_done[i]), + .dma_window_intr_o(dma_window_done[i]), + .dma_done_o(dma_done_o[i]) + ); + end + endgenerate + + + generate + if (core_v_mini_mcu_pkg::DMA_CH_NUM > 1) begin : xbar_varlat_gen + + /* Register interface routing signals */ + logic [core_v_mini_mcu_pkg::DMA_CH_PORT_SEL_WIDTH-1:0] submodules_select; + + if (core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS > 1 && core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS != core_v_mini_mcu_pkg::DMA_CH_NUM) begin : xbar_n_to_m_gen + + /* Read, write & address mode operations xbar*/ + dma_NtoM_xbar #( + .XBAR_NMASTER(core_v_mini_mcu_pkg::DMA_CH_NUM), + .XBAR_MSLAVE(core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS) + ) xbar_read_i ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .master_req_i(xbar_read_req), + .master_resp_o(xbar_read_resp), + .slave_req_o(dma_read_req_o), + .slave_resp_i(dma_read_resp_i) + ); + + dma_NtoM_xbar #( + .XBAR_NMASTER(core_v_mini_mcu_pkg::DMA_CH_NUM), + .XBAR_MSLAVE(core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS) + ) xbar_write_i ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .master_req_i(xbar_write_req), + .master_resp_o(xbar_write_resp), + .slave_req_o(dma_write_req_o), + .slave_resp_i(dma_write_resp_i) + ); + + dma_NtoM_xbar #( + .XBAR_NMASTER(core_v_mini_mcu_pkg::DMA_CH_NUM), + .XBAR_MSLAVE(core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS) + ) xbar_address_i ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .master_req_i(xbar_address_req), + .master_resp_o(xbar_address_resp), + .slave_req_o(dma_addr_req_o), + .slave_resp_i(dma_addr_resp_i) + ); + end else if (core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS > 1 && core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS == core_v_mini_mcu_pkg::DMA_CH_NUM) begin : xbar_n_to_n_gen + for (genvar i = 0 ; i < core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS; i++) begin + assign dma_read_req_o[i] = xbar_read_req[i]; + assign xbar_read_resp[i] = dma_read_resp_i[i]; + assign dma_write_req_o[i] = xbar_write_req[i]; + assign xbar_write_resp[i] = dma_write_resp_i[i]; + assign dma_addr_req_o[i] = xbar_address_req[i]; + assign xbar_address_resp[i] = dma_addr_resp_i[i]; + end + + end else begin : xbar_n_to_1_gen + /* Read, write & address mode operations xbar*/ + xbar_varlat_n_to_one #( + .XBAR_NMASTER(core_v_mini_mcu_pkg::DMA_CH_NUM) + ) xbar_read_i ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .master_req_i (xbar_read_req), + .master_resp_o(xbar_read_resp), + .slave_req_o (dma_read_req_o[0]), + .slave_resp_i (dma_read_resp_i[0]) + ); + + xbar_varlat_n_to_one #( + .XBAR_NMASTER(core_v_mini_mcu_pkg::DMA_CH_NUM) + ) xbar_write_i ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .master_req_i (xbar_write_req), + .master_resp_o(xbar_write_resp), + .slave_req_o (dma_write_req_o[0]), + .slave_resp_i (dma_write_resp_i[0]) + ); + + xbar_varlat_n_to_one #( + .XBAR_NMASTER(core_v_mini_mcu_pkg::DMA_CH_NUM) + ) xbar_address_i ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .master_req_i (xbar_address_req), + .master_resp_o(xbar_address_resp), + .slave_req_o (dma_addr_req_o[0]), + .slave_resp_i (dma_addr_resp_i[0]) + ); + end + + /* Internal address decoder */ + addr_decode #( + .NoIndices(core_v_mini_mcu_pkg::DMA_CH_NUM), + .NoRules(core_v_mini_mcu_pkg::DMA_CH_NUM), + .addr_t(logic [7:0]), + .rule_t(addr_map_rule_pkg::addr_map_rule_8bit_t) + ) addr_dec_i ( + .addr_i(reg_req_i.addr[15:8]), + .addr_map_i(core_v_mini_mcu_pkg::DMA_ADDR_RULES), + .idx_o(submodules_select), + .dec_valid_o(), + .dec_error_o(), + .en_default_idx_i(1'b0), + .default_idx_i('0) + ); + + /* Register demux */ + reg_demux #( + .NoPorts(core_v_mini_mcu_pkg::DMA_CH_NUM), + .req_t (reg_pkg::reg_req_t), + .rsp_t (reg_pkg::reg_rsp_t) + ) reg_demux_i ( + .clk_i, + .rst_ni, + .in_select_i(submodules_select), + .in_req_i(reg_req_i), + .in_rsp_o(reg_rsp_o), + .out_req_o(submodules_req), + .out_rsp_i(submodules_rsp) + ); + + end else begin + + /* Bus ports routing in the case of a single DMA */ + assign dma_read_req_o[0] = xbar_read_req[0]; + assign xbar_read_resp[0] = dma_read_resp_i[0]; + assign dma_write_req_o[0] = xbar_write_req[0]; + assign xbar_write_resp[0] = dma_write_resp_i[0]; + assign dma_addr_req_o[0] = xbar_address_req[0]; + assign xbar_address_resp[0] = dma_addr_resp_i[0]; + assign submodules_req[0] = reg_req_i; + assign reg_rsp_o = submodules_rsp[0]; + end + endgenerate + + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signal assignments */ + + assign dma_done_intr_o = |(dma_trans_done); + assign dma_window_intr_o = |(dma_window_done); + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_core.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_core.sv index fb155575..2195a075 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_core.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_core.sv @@ -7,8 +7,8 @@ // Description: I2s core logic module i2s_core #( - parameter MaxWordWidth, - parameter ClkDividerWidth + parameter MaxWordWidth = 32, + parameter ClkDividerWidth = 8 ) ( input logic clk_i, input logic rst_ni, diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_rx_channel.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_rx_channel.sv index 3c0066a7..52e48f9d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_rx_channel.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_rx_channel.sv @@ -153,7 +153,7 @@ module i2s_rx_channel #( // worst case drop even number of samples always_ff @(posedge sck_i, negedge rst_ni) begin if (~rst_ni) begin - last_data_ws <= ~start_channel_i; + last_data_ws <= 1'b0; end else begin if (~en) begin last_data_ws <= ~start_channel_i; diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_ws_gen.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_ws_gen.sv index ed85b649..a6ebeca2 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_ws_gen.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/i2s/rtl/i2s_ws_gen.sv @@ -10,7 +10,7 @@ // by Antonio Pullini (pullinia@iis.ee.ethz.ch) module i2s_ws_gen #( - parameter MaxWordWidth, + parameter MaxWordWidth = 32, localparam int unsigned CounterWidth = $clog2(MaxWordWidth) ) ( input logic sck_i, diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/pdm2pcm/rtl/fir.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/pdm2pcm/rtl/fir.sv index 6d22d673..ce17a7a6 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/pdm2pcm/rtl/fir.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/pdm2pcm/rtl/fir.sv @@ -48,7 +48,9 @@ module fir #( genvar k; generate for (k = 0; k < TOTCOEFS; k = k + 1) begin : coeffs_mapping - assign coeffs[k] = freecoeffs[int'($floor($sqrt($pow((TOTCOEFS-1)/2.0-k, 2))))]; + // Remove $pow function to avoid errors in Synopsys DC + // assign coeffs[k] = freecoeffs[int'($floor($sqrt($pow((TOTCOEFS-1)/2.0-k, 2))))]; + assign coeffs[k] = freecoeffs[int'($floor($sqrt(((TOTCOEFS-1)/2.0-k)*((TOTCOEFS-1)/2.0-k))))]; end endgenerate diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/pdm2pcm/rtl/halfband.sv b/hw/vendor/esl_epfl_x_heep/hw/ip/pdm2pcm/rtl/halfband.sv index 9d9355c8..a0710c58 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/pdm2pcm/rtl/halfband.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/pdm2pcm/rtl/halfband.sv @@ -63,7 +63,11 @@ module halfband #( genvar k; generate for (k = 0; k < TOTCOEFS; k = k + 1) begin : coeffs_mapping - assign coeffs[k] = lessfreecoeffs[int'($floor($sqrt($pow((TOTCOEFS-1)/2.0-k, 2))))]; + // Remove $pow function to avoid errors in Synopsys DC + // assign coeffs[k] = lessfreecoeffs[int'($floor($sqrt($pow((TOTCOEFS-1)/2.0-k, 2))))]; + assign coeffs[k] = lessfreecoeffs[int'($floor( + $sqrt(((TOTCOEFS-1)/2.0-k)*((TOTCOEFS-1)/2.0-k)) + ))]; end endgenerate diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/data/power_manager.hjson.tpl b/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/data/power_manager.hjson.tpl index fb544a59..6c564b96 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/data/power_manager.hjson.tpl +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/data/power_manager.hjson.tpl @@ -19,12 +19,22 @@ } { name: "RESTORE_ADDRESS", - desc: "Restore xddress value", + desc: "Restore address value", resval: "0x00000000" swaccess: "rw", hwaccess: "hro", fields: [ - { bits: "31:0", name: "RESTORE_XDDRESS", desc: "Restore xddress Reg, used by BOOTROM" } + { bits: "31:0", name: "RESTORE_ADDRESS", desc: "Restore address Reg, used by BOOTROM" } + ] + } + + { name: "GLOBAL_POINTER", + desc: "Global Pointer value", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "GLOBAL_POINTER", desc: "Global Reg, used by power manager HAL" } ] } @@ -213,65 +223,76 @@ ] } +% for channel in range(int(dma_ch_count)): + { name: "DMA_CH${channel}_CLK_GATE", + desc: "Clock-gates the DMA CH${channel}", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", name: "DMA_CH${channel}_CLK_GATE", desc: "Clock-gates the DMA CH${channel}" } + ] + } +% endfor -% for bank in range(ram_numbanks): - { name: "RAM_${bank}_CLK_GATE", - desc: "Clock-gates the RAM_${bank} domain", +% for bank in xheep.iter_ram_banks(): + { name: "RAM_${bank.name()}_CLK_GATE", + desc: "Clock-gates the RAM_${bank.name()} domain", resval: "0x00000000" swaccess: "rw", hwaccess: "hro", fields: [ - { bits: "0", name: "RAM_${bank}_CLK_GATE", desc: "Clock-gates the RAM_${bank} domain" } + { bits: "0", name: "RAM_${bank.name()}_CLK_GATE", desc: "Clock-gates the RAM_${bank.name()} domain" } ] } - { name: "POWER_GATE_RAM_BLOCK_${bank}_ACK", - desc: "Used by the ram ${bank} switch to ack the power manager", + { name: "POWER_GATE_RAM_BLOCK_${bank.name()}_ACK", + desc: "Used by the ram ${bank.name()} switch to ack the power manager", resval: "0x00000000" swaccess: "ro", hwaccess: "hrw", fields: [ - { bits: "0", name: "POWER_GATE_RAM_BLOCK_${bank}_ACK", desc: "Power Gate Ram Block ${bank} Ack Reg" } + { bits: "0", name: "POWER_GATE_RAM_BLOCK_${bank.name()}_ACK", desc: "Power Gate Ram Block ${bank.name()} Ack Reg" } ] } - { name: "RAM_${bank}_SWITCH", - desc: "Switch off the RAM_${bank} domain", + { name: "RAM_${bank.name()}_SWITCH", + desc: "Switch off the RAM_${bank.name()} domain", resval: "0x00000000" swaccess: "rw", hwaccess: "hro", fields: [ - { bits: "0", name: "RAM_${bank}_SWITCH", desc: "Switch off RAM_${bank} domain" } + { bits: "0", name: "RAM_${bank.name()}_SWITCH", desc: "Switch off RAM_${bank.name()} domain" } ] } - { name: "RAM_${bank}_WAIT_ACK_SWITCH_ON", - desc: "Wait for the RAM_${bank} domain switch ack", + { name: "RAM_${bank.name()}_WAIT_ACK_SWITCH_ON", + desc: "Wait for the RAM_${bank.name()} domain switch ack", resval: "0x00000000" swaccess: "rw", hwaccess: "hro", fields: [ - { bits: "0", name: "RAM_${bank}_WAIT_ACK_SWITCH_ON", desc: "Wait RAM_${bank} domain switch ack" } + { bits: "0", name: "RAM_${bank.name()}_WAIT_ACK_SWITCH_ON", desc: "Wait RAM_${bank.name()} domain switch ack" } ] } - { name: "RAM_${bank}_ISO", - desc: "Set on the isolation of the RAM_${bank} domain", + { name: "RAM_${bank.name()}_ISO", + desc: "Set on the isolation of the RAM_${bank.name()} domain", resval: "0x00000000" swaccess: "rw", hwaccess: "hro", fields: [ - { bits: "0", name: "RAM_${bank}_ISO", desc: "Set on isolation of RAM_${bank} domain" } + { bits: "0", name: "RAM_${bank.name()}_ISO", desc: "Set on isolation of RAM_${bank.name()} domain" } ] } - { name: "RAM_${bank}_RETENTIVE", - desc: "Set on retentive mode for the RAM_${bank} domain", + { name: "RAM_${bank.name()}_RETENTIVE", + desc: "Set on retentive mode for the RAM_${bank.name()} domain", resval: "0x00000000" swaccess: "rw", hwaccess: "hro", fields: [ - { bits: "0", name: "RAM_${bank}_RETENTIVE", desc: "Set on retentive mode for RAM_${bank} domain" } + { bits: "0", name: "RAM_${bank.name()}_RETENTIVE", desc: "Set on retentive mode for RAM_${bank.name()} domain" } ] } @@ -368,14 +389,14 @@ ] } -% for bank in range(ram_numbanks): - { name: "MONITOR_POWER_GATE_RAM_BLOCK_${bank}", - desc: "Used to monitor the signals to power gate ram block ${bank}", +% for bank in xheep.iter_ram_banks(): + { name: "MONITOR_POWER_GATE_RAM_BLOCK_${bank.name()}", + desc: "Used to monitor the signals to power gate ram block ${bank.name()}", resval: "0x00000000" swaccess: "ro", hwaccess: "hwo", fields: [ - { bits: "1:0", name: "MONITOR_POWER_GATE_RAM_BLOCK_${bank}", desc: "Monitor Signals Power Gate Ram Block ${bank} Reg" } + { bits: "1:0", name: "MONITOR_POWER_GATE_RAM_BLOCK_${bank.name()}", desc: "Monitor Signals Power Gate Ram Block ${bank.name()} Reg" } ] } diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/data/power_manager.sv.tpl b/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/data/power_manager.sv.tpl index 4b8ba22b..a6abf35d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/data/power_manager.sv.tpl +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/data/power_manager.sv.tpl @@ -4,7 +4,7 @@ `include "common_cells/assertions.svh" -module power_manager #( +module power_manager import power_manager_pkg::*; #( parameter type reg_req_t = logic, parameter type reg_rsp_t = logic, parameter logic SWITCH_IDLE_VALUE = 1'b1, //the value to have Vdd.daughter = Vdd.mother, i.e. on state @@ -44,29 +44,19 @@ module power_manager #( // External interrupts input logic [NEXT_INT_RND-1:0] ext_irq_i, - // Clock gating signals - output logic peripheral_subsystem_clkgate_en_no, - output logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0]memory_subsystem_clkgate_en_no, - output logic [EXT_DOMAINS_RND-1:0]external_subsystem_clkgate_en_no, - - // Power gating signals - output logic cpu_subsystem_powergate_switch_no, - input logic cpu_subsystem_powergate_switch_ack_ni, - output logic cpu_subsystem_powergate_iso_no, - output logic cpu_subsystem_rst_no, - output logic peripheral_subsystem_powergate_switch_no, - input logic peripheral_subsystem_powergate_switch_ack_ni, - output logic peripheral_subsystem_powergate_iso_no, - output logic peripheral_subsystem_rst_no, - output logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_no, - input logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_ack_ni, - output logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_iso_no, - output logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_set_retentive_no, - output logic [EXT_DOMAINS_RND-1:0] external_subsystem_powergate_switch_no, - input logic [EXT_DOMAINS_RND-1:0] external_subsystem_powergate_switch_ack_ni, - output logic [EXT_DOMAINS_RND-1:0] external_subsystem_powergate_iso_no, - output logic [EXT_DOMAINS_RND-1:0] external_subsystem_rst_no, - output logic [EXT_DOMAINS_RND-1:0] external_ram_banks_set_retentive_no + // Power Manager output signals + output power_manager_out_t cpu_subsystem_pwr_ctrl_o, + output power_manager_out_t peripheral_subsystem_pwr_ctrl_o, + output power_manager_out_t memory_subsystem_pwr_ctrl_o[core_v_mini_mcu_pkg::NUM_BANKS-1:0], + output power_manager_out_t external_subsystem_pwr_ctrl_o[EXT_DOMAINS_RND-1:0], + output power_manager_out_t dma_subsystem_pwr_ctrl_o[core_v_mini_mcu_pkg::DMA_CH_NUM-1:0], + + // Power Manager input signals + input power_manager_in_t cpu_subsystem_pwr_ctrl_i, + input power_manager_in_t peripheral_subsystem_pwr_ctrl_i, + input power_manager_in_t memory_subsystem_pwr_ctrl_i[core_v_mini_mcu_pkg::NUM_BANKS-1:0], + input power_manager_in_t external_subsystem_pwr_ctrl_i[EXT_DOMAINS_RND-1:0] + ); import power_manager_reg_pkg::*; @@ -123,37 +113,42 @@ module power_manager #( logic [core_v_mini_mcu_pkg::EXTERNAL_DOMAINS-1:0] external_subsystem_rst_n; % endif - assign cpu_subsystem_powergate_switch_no = cpu_subsystem_powergate_switch_n; - assign cpu_subsystem_powergate_iso_no = cpu_subsystem_powergate_iso_n; - assign cpu_subsystem_rst_no = cpu_subsystem_rst_n; - assign peripheral_subsystem_powergate_switch_no = peripheral_subsystem_powergate_switch_n; - assign peripheral_subsystem_powergate_iso_no = peripheral_subsystem_powergate_iso_n; - assign peripheral_subsystem_rst_no = peripheral_subsystem_rst_n; - assign memory_subsystem_banks_powergate_switch_no = memory_subsystem_banks_powergate_switch_n; - assign memory_subsystem_banks_powergate_iso_no = memory_subsystem_banks_powergate_iso_n; -% if external_domains != 0: - assign external_subsystem_powergate_switch_no = external_subsystem_powergate_switch_n; - assign external_subsystem_powergate_iso_no = external_subsystem_powergate_iso_n; - assign external_subsystem_rst_no = external_subsystem_rst_n; -% else: - assign external_subsystem_powergate_switch_no = '0; - assign external_subsystem_powergate_iso_no = '0; - assign external_subsystem_rst_no = '0; -% endif - - // -------------------------------------------------------------------------------------- - // CLK_GATING - // -------------------------------------------------------------------------------------- - - assign peripheral_subsystem_clkgate_en_no = ~reg2hw.periph_clk_gate.q; + assign cpu_subsystem_pwr_ctrl_o.pwrgate_en_n = cpu_subsystem_powergate_switch_n; + assign cpu_subsystem_pwr_ctrl_o.isogate_en_n = cpu_subsystem_powergate_iso_n; + assign cpu_subsystem_pwr_ctrl_o.rst_n = cpu_subsystem_rst_n; + assign cpu_subsystem_pwr_ctrl_o.clkgate_en_n = 1'b1; //unused, the CPU clk gates itself via WFI + assign cpu_subsystem_pwr_ctrl_o.retentive_en_n = 1'b1; //unused + + assign peripheral_subsystem_pwr_ctrl_o.pwrgate_en_n = peripheral_subsystem_powergate_switch_n; + assign peripheral_subsystem_pwr_ctrl_o.isogate_en_n = peripheral_subsystem_powergate_iso_n; + assign peripheral_subsystem_pwr_ctrl_o.rst_n = peripheral_subsystem_rst_n; + assign peripheral_subsystem_pwr_ctrl_o.retentive_en_n = 1'b1; //unused + assign peripheral_subsystem_pwr_ctrl_o.clkgate_en_n = ~reg2hw.periph_clk_gate.q; + +% for bank in xheep.iter_ram_banks(): + assign memory_subsystem_pwr_ctrl_o[${bank.name()}].pwrgate_en_n = memory_subsystem_banks_powergate_switch_n[${bank.name()}]; + assign memory_subsystem_pwr_ctrl_o[${bank.name()}].isogate_en_n = memory_subsystem_banks_powergate_iso_n[${bank.name()}]; + assign memory_subsystem_pwr_ctrl_o[${bank.name()}].rst_n = 1'b1; + assign memory_subsystem_pwr_ctrl_o[${bank.name()}].clkgate_en_n = ~reg2hw.ram_${bank.name()}_clk_gate.q; +% endfor -% for bank in range(ram_numbanks): - assign memory_subsystem_clkgate_en_no[${bank}] = ~reg2hw.ram_${bank}_clk_gate.q; +% for channel in range(int(dma_ch_count)): + assign dma_subsystem_pwr_ctrl_o[${channel}].clkgate_en_n = ~reg2hw.dma_ch${channel}_clk_gate.q; % endfor +% if external_domains != 0: % for ext in range(external_domains): - assign external_subsystem_clkgate_en_no[${ext}] = ~reg2hw.external_${ext}_clk_gate.q; + assign external_subsystem_pwr_ctrl_o[${ext}].pwrgate_en_n = external_subsystem_powergate_switch_n[${ext}]; + assign external_subsystem_pwr_ctrl_o[${ext}].isogate_en_n = external_subsystem_powergate_iso_n[${ext}]; + assign external_subsystem_pwr_ctrl_o[${ext}].rst_n = external_subsystem_rst_n[${ext}]; + assign external_subsystem_pwr_ctrl_o[${ext}].clkgate_en_n = ~reg2hw.external_${ext}_clk_gate.q; % endfor +% else: + assign external_subsystem_pwr_ctrl_o[0].pwrgate_en_n = 1'b1; + assign external_subsystem_pwr_ctrl_o[0].isogate_en_n = 1'b1; + assign external_subsystem_pwr_ctrl_o[0].rst_n = 1'b1; + assign external_subsystem_pwr_ctrl_o[0].clkgate_en_n = 1'b1; +% endif // -------------------------------------------------------------------------------------- // CPU_SUBSYSTEM DOMAIN @@ -166,7 +161,7 @@ module power_manager #( ) sync_cpu_ack_i ( .clk_i, .rst_ni, - .serial_i(cpu_subsystem_powergate_switch_ack_ni), + .serial_i(cpu_subsystem_pwr_ctrl_i.pwrgate_ack_n), .serial_o(cpu_subsystem_powergate_switch_ack_sync) ); @@ -358,7 +353,7 @@ module power_manager #( ) sync_periph_ack_i ( .clk_i, .rst_ni, - .serial_i(peripheral_subsystem_powergate_switch_ack_ni), + .serial_i(peripheral_subsystem_pwr_ctrl_i.pwrgate_ack_n), .serial_o(peripheral_subsystem_powergate_switch_ack_sync) ); @@ -417,75 +412,75 @@ module power_manager #( .switch_onoff_signal_o(peripheral_subsystem_powergate_iso_n) ); -% for bank in range(ram_numbanks): +% for bank in xheep.iter_ram_banks(): // -------------------------------------------------------------------------------------- - // RAM_${bank} DOMAIN + // RAM_${bank.name()} DOMAIN // -------------------------------------------------------------------------------------- - logic ram_${bank}_subsystem_powergate_switch_ack_sync; + logic ram_${bank.name()}_subsystem_powergate_switch_ack_sync; sync #( .ResetValue(1'b0) - ) sync_ram_${bank}_ack_i ( + ) sync_ram_${bank.name()}_ack_i ( .clk_i, .rst_ni, - .serial_i(memory_subsystem_banks_powergate_switch_ack_ni[${bank}]), - .serial_o(ram_${bank}_subsystem_powergate_switch_ack_sync) + .serial_i(memory_subsystem_pwr_ctrl_i[${bank.name()}].pwrgate_ack_n), + .serial_o(ram_${bank.name()}_subsystem_powergate_switch_ack_sync) ); - assign hw2reg.power_gate_ram_block_${bank}_ack.de = 1'b1; - assign hw2reg.power_gate_ram_block_${bank}_ack.d = ram_${bank}_subsystem_powergate_switch_ack_sync; + assign hw2reg.power_gate_ram_block_${bank.name()}_ack.de = 1'b1; + assign hw2reg.power_gate_ram_block_${bank.name()}_ack.d = ram_${bank.name()}_subsystem_powergate_switch_ack_sync; //if you want to wait for ACK, or just bypass it - logic ram_${bank}_switch_wait_ack; - assign ram_${bank}_switch_wait_ack = reg2hw.ram_${bank}_wait_ack_switch_on.q ? reg2hw.power_gate_ram_block_${bank}_ack.q == SWITCH_IDLE_VALUE : 1'b1; + logic ram_${bank.name()}_switch_wait_ack; + assign ram_${bank.name()}_switch_wait_ack = reg2hw.ram_${bank.name()}_wait_ack_switch_on.q ? reg2hw.power_gate_ram_block_${bank.name()}_ack.q == SWITCH_IDLE_VALUE : 1'b1; power_manager_sequence #( .IDLE_VALUE(SWITCH_IDLE_VALUE), .ONOFF_AT_RESET(SWITCH_VALUE_AT_RESET) - ) power_manager_sequence_ram_${bank}_switch_i ( + ) power_manager_sequence_ram_${bank.name()}_switch_i ( .clk_i, .rst_ni, // trigger to start the sequence - .start_off_sequence_i(reg2hw.ram_${bank}_switch.q), - .start_on_sequence_i (~reg2hw.ram_${bank}_switch.q), + .start_off_sequence_i(reg2hw.ram_${bank.name()}_switch.q), + .start_on_sequence_i (~reg2hw.ram_${bank.name()}_switch.q), .switch_ack_i (1'b1), // switch on and off signal, 1 means on - .switch_onoff_signal_o(memory_subsystem_banks_powergate_switch_n[${bank}]) + .switch_onoff_signal_o(memory_subsystem_banks_powergate_switch_n[${bank.name()}]) ); power_manager_sequence #( .IDLE_VALUE(ISO_IDLE_VALUE), .ONOFF_AT_RESET(ISO_VALUE_AT_RESET) - ) power_manager_sequence_ram_${bank}_iso_i ( + ) power_manager_sequence_ram_${bank.name()}_iso_i ( .clk_i, .rst_ni, // trigger to start the sequence - .start_off_sequence_i(reg2hw.ram_${bank}_iso.q), - .start_on_sequence_i (~reg2hw.ram_${bank}_iso.q), - .switch_ack_i (ram_${bank}_switch_wait_ack), + .start_off_sequence_i(reg2hw.ram_${bank.name()}_iso.q), + .start_on_sequence_i (~reg2hw.ram_${bank.name()}_iso.q), + .switch_ack_i (ram_${bank.name()}_switch_wait_ack), // switch on and off signal, 1 means on - .switch_onoff_signal_o(memory_subsystem_banks_powergate_iso_n[${bank}]) + .switch_onoff_signal_o(memory_subsystem_banks_powergate_iso_n[${bank.name()}]) ); power_manager_sequence #( .IDLE_VALUE(ISO_IDLE_VALUE), .ONOFF_AT_RESET(ISO_VALUE_AT_RESET) - ) power_manager_sequence_ram_${bank}_retentive_i ( + ) power_manager_sequence_ram_${bank.name()}_retentive_i ( .clk_i, .rst_ni, // trigger to start the sequence - .start_off_sequence_i(reg2hw.ram_${bank}_retentive.q), - .start_on_sequence_i (~reg2hw.ram_${bank}_retentive.q), + .start_off_sequence_i(reg2hw.ram_${bank.name()}_retentive.q), + .start_on_sequence_i (~reg2hw.ram_${bank.name()}_retentive.q), .switch_ack_i (1'b1), // switch on and off signal, 1 means on - .switch_onoff_signal_o(memory_subsystem_banks_set_retentive_no[${bank}]) + .switch_onoff_signal_o(memory_subsystem_pwr_ctrl_o[${bank.name()}].retentive_en_n) ); % endfor @@ -501,7 +496,7 @@ module power_manager #( ) sync_external_${ext}_ack_i ( .clk_i, .rst_ni, - .serial_i(external_subsystem_powergate_switch_ack_ni[${ext}]), + .serial_i(external_subsystem_pwr_ctrl_i[${ext}].pwrgate_ack_n), .serial_o(external_${ext}_subsystem_powergate_switch_ack_sync) ); @@ -573,7 +568,7 @@ module power_manager #( .switch_ack_i (1'b1), // switch on and off signal, 1 means on - .switch_onoff_signal_o(external_ram_banks_set_retentive_no[${ext}]) + .switch_onoff_signal_o(external_subsystem_pwr_ctrl_o[${ext}].retentive_en_n) ); % endfor @@ -587,9 +582,9 @@ module power_manager #( assign hw2reg.monitor_power_gate_periph.de = 1'b1; assign hw2reg.monitor_power_gate_periph.d = {peripheral_subsystem_rst_n, peripheral_subsystem_powergate_iso_n, peripheral_subsystem_powergate_switch_n}; -% for bank in range(ram_numbanks): - assign hw2reg.monitor_power_gate_ram_block_${bank}.de = 1'b1; - assign hw2reg.monitor_power_gate_ram_block_${bank}.d = {memory_subsystem_banks_powergate_iso_n[${bank}], memory_subsystem_banks_powergate_switch_n[${bank}]}; +% for bank in xheep.iter_ram_banks(): + assign hw2reg.monitor_power_gate_ram_block_${bank.name()}.de = 1'b1; + assign hw2reg.monitor_power_gate_ram_block_${bank.name()}.d = {memory_subsystem_banks_powergate_iso_n[${bank.name()}], memory_subsystem_banks_powergate_switch_n[${bank.name()}]}; % endfor diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/power_manager.vlt b/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/power_manager.vlt index d0b73948..c9c6f472 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/power_manager.vlt +++ b/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/power_manager.vlt @@ -12,6 +12,6 @@ lint_off -rule LITENDIAN -file "*/power_manager.sv" -match "*" lint_off -rule UNDRIVEN -file "*/power_manager.sv" -match "Signal is not driven: 'external_subsystem_powergate_switch*" lint_off -rule UNDRIVEN -file "*/power_manager.sv" -match "Signal is not driven: 'external_subsystem_powergate_iso*" lint_off -rule UNDRIVEN -file "*/power_manager.sv" -match "Signal is not driven: 'external_subsystem_rst_n*" -lint_off -rule UNUSED -file "*/power_manager.sv" -match "Signal is not used: 'external_subsystem_powergate_switch_ack*" +lint_off -rule UNUSED -file "*/power_manager.sv" -match "Signal is not used: 'external_subsystem_pwr_ctrl_i*" lint_off -rule WIDTH -file "*/power_manager.sv" -match "Operator ASSIGNW expects 16 bits on*" lint_off -rule DECLFILENAME -file "*/power_manager_reg_top.sv" -match "Filename 'power_manager_reg_top' does not match MODULE name: 'power_manager_reg_top_intf'" diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/power_manager_gen.sh b/hw/vendor/esl_epfl_x_heep/hw/ip/power_manager/power_manager_gen.sh old mode 100644 new mode 100755 diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/data/iffifo.hjson b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/data/iffifo.hjson new file mode 100644 index 00000000..919cceaf --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/data/iffifo.hjson @@ -0,0 +1,76 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +{ name: "iffifo" + clock_primary: "clk_i" + bus_interfaces: [ + { protocol: "reg_iface", direction: "device" } + ], + regwidth: 32 + registers: [ + + { name: "FIFO_OUT" + desc: "Data coming from the FIFO (Fifo Output/Software RX)" + swaccess: "ro" + hwaccess: "hrw" # required for RE signal + hwext: "true" # required for RE signal + hwre: "true" # Used to emulate a window behaviour + fields: [ + { bits: "31:0" } + ] + } + + { name: "FIFO_IN" + desc: "Data sent to the FIFO (Fifo Input/Software TX)" + hwaccess: "hro" + swaccess: "rw" # required for QE signal + hwqe: "true" # Used to emulate a window behaviour + fields: [ + { bits: "31:0" } + ] + } + + { name: "STATUS" + desc: "General purpose status register" + swaccess: "ro" + hwaccess: "hwo" + fields: [ + { bits: "0", name: "EMPTY", desc: "Asserted when FIFO empty." } + { bits: "1", name: "AVAILABLE", desc: "Asserted when data is available in FIFO." } + { bits: "2", name: "REACHED", desc: "Asserted when occupied data slots count greater than threshold." } + { bits: "3", name: "FULL", desc: "Asserted when all FIFO slots are occupied." } + ] + } + + { name: "OCCUPANCY" + desc: "Current number of occupied FIFO slots" + swaccess: "ro" + hwaccess: "hwo" + fields: [ + { bits: "31:0" } + ] + } + + { name: "WATERMARK" + desc: "FIFO occupancy at which the STATUS:REACHED bit is asserted" + swaccess: "rw" + hwaccess: "hro" + fields: [ + { bits: "31:0" } + ] + } + + { name: "INTERRUPTS" + desc: "Write any value to assert an interrupt. Write 0 or 1 to disable or enable an interrupt." + swaccess: "rw" + hwaccess: "hro" + hwqe: "true" # Used to catch software writes + fields: [ + { bits: "0", name: "REACHED", desc: "Watermark reached interrupt" } + ] + } + + ] +} + diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.core b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.core new file mode 100644 index 00000000..f0e23463 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.core @@ -0,0 +1,26 @@ +CAPI=2: + +name: "example:ip:iffifo" +description: "core-v-mini-mcu iffifo peripheral" + +# Copyright 2023 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# +# Author: Pierre Guillod , EPFL, STI-SEL +# Date: 18.10.2023 + +filesets: + files_rtl: + depend: + - pulp-platform.org::common_cells + files: + - rtl/iffifo_reg_pkg.sv + - rtl/iffifo_reg_top.sv + - rtl/iffifo.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_rtl diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.vlt b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.vlt new file mode 100644 index 00000000..9820d038 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo.vlt @@ -0,0 +1,15 @@ +// Copyright 2023 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Author: Pierre Guillod , EPFL, STI-SEL +// Date: 18.10.2023 + +`verilator_config + +lint_off -rule DECLFILENAME -file "*/iffifo/rtl/iffifo_reg_top.sv" -match "Filename 'iffifo_reg_top' does not match MODULE name: 'iffifo_reg_top_intf'*" +lint_off -rule WIDTH -file "*/iffifo/rtl/iffifo_reg_top.sv" -match "Operator ASSIGNW expects 3 bits on the Assign RHS, but Assign RHS's SEL generates 32*" +lint_off -rule UNUSED -file "*/iffifo/rtl/iffifo.sv" -match "Bits of signal are not used: 'reg2hw'[0]*" + +lint_off -rule UNUSED -file "*/iffifo/rtl/iffifo_window.sv" -match "Bits of signal are not used: 'rx_win_i'[67:64,31:0]" +lint_off -rule WIDTH -file "*/iffifo/rtl/iffifo_*.sv" -match "Operator ASSIGNW expects*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo_gen.sh b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo_gen.sh new file mode 100755 index 00000000..45cc8f1c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/iffifo_gen.sh @@ -0,0 +1,8 @@ +# Copyright EPFL contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +echo "Generating RTL" +${PYTHON} ../../vendor/pulp_platform_register_interface/vendor/lowrisc_opentitan/util/regtool.py -r -t rtl data/iffifo.hjson +echo "Generating SW" +${PYTHON} ../../vendor/pulp_platform_register_interface/vendor/lowrisc_opentitan/util/regtool.py --cdefines -o ../../../sw/device/lib/drivers/iffifo/iffifo_regs.h data/iffifo.hjson diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo.sv new file mode 100644 index 00000000..35a6b008 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo.sv @@ -0,0 +1,115 @@ +// Copyright 2023 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Author: Pierre Guillod , EPFL, STI-SEL +// Date: 18.10.2023 + +module iffifo #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + localparam int WIDTH = 32, + localparam int DEPTH = 4, + localparam int DEPTHw = $clog2(DEPTH + 1) +) ( + input logic clk_i, + input logic rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + + // DMA slots + output logic iffifo_in_ready_o, + output logic iffifo_out_valid_o, + + // Interrupt lines + output logic iffifo_int_o +); + + import iffifo_reg_pkg::*; + + iffifo_reg2hw_t reg2hw; + iffifo_hw2reg_t hw2reg; + + logic [WIDTH-1:0] fifout; + logic [DEPTHw-1:0] occupancy; + logic empty, full, reached, available; + + assign hw2reg.fifo_out.d = fifout + 1; + + // Status (full/empty/watermark) reporting circuitry + assign empty = (occupancy == 0); + assign available = !empty; + assign hw2reg.status.empty.de = 1; + assign hw2reg.status.empty.d = empty; + assign hw2reg.status.available.de = 1; + assign hw2reg.status.available.d = available; + assign hw2reg.status.full.de = 1; + assign hw2reg.status.full.d = full; + assign hw2reg.status.reached.de = 1; + assign hw2reg.status.reached.d = reached; + assign hw2reg.occupancy.de = 1; + assign hw2reg.occupancy.d = {{32 - DEPTHw{1'b0}}, occupancy}; + assign reached = ({{32 - DEPTHw{1'b0}}, occupancy} >= reg2hw.watermark.q); + + // Interrupts circuitry + always_ff @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + + iffifo_int_o <= 0; + + end else begin + + // Interrupts firing + if (reached & reg2hw.interrupts.q) begin + iffifo_int_o <= 1; + end + + // Interrupts assertion + if (reg2hw.interrupts.qe) begin + iffifo_int_o <= 0; + end + + end + end + + iffifo_reg_top #( + .reg_req_t(reg_req_t), + .reg_rsp_t(reg_rsp_t) + ) iffifo_reg_top_i ( + .clk_i, + .rst_ni, + .reg2hw, + .hw2reg, + .reg_req_i, + .reg_rsp_o, + .devmode_i(1'b0) + ); + + prim_fifo_sync #( + .Width(WIDTH), + .Depth(DEPTH), + .Pass(1'b0), + .OutputZeroIfEmpty(1'b0) + ) iffifo_fifo_i ( + + .clk_i, + .rst_ni, + .clr_i(1'b0), + + // From DMA (output) to FIFO (input, TX) + .wvalid_i(reg2hw.fifo_in.qe), + .wready_o(iffifo_in_ready_o), + .wdata_i (reg2hw.fifo_in.q), + + // From FIFO (output) to DMA (input, RX) + .rvalid_o(iffifo_out_valid_o), + .rready_i(reg2hw.fifo_out.re), + .rdata_o (fifout), + + .full_o (full), + .depth_o(occupancy) + + ); + +endmodule : iffifo + diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_pkg.sv new file mode 100644 index 00000000..e362798d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_pkg.sv @@ -0,0 +1,106 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Package auto-generated by `reggen` containing data structure + +package iffifo_reg_pkg; + + // Address widths within the block + parameter int BlockAw = 5; + + //////////////////////////// + // Typedefs for registers // + //////////////////////////// + + typedef struct packed { + logic [31:0] q; + logic re; + } iffifo_reg2hw_fifo_out_reg_t; + + typedef struct packed { + logic [31:0] q; + logic qe; + } iffifo_reg2hw_fifo_in_reg_t; + + typedef struct packed {logic [31:0] q;} iffifo_reg2hw_watermark_reg_t; + + typedef struct packed { + logic q; + logic qe; + } iffifo_reg2hw_interrupts_reg_t; + + typedef struct packed {logic [31:0] d;} iffifo_hw2reg_fifo_out_reg_t; + + typedef struct packed { + struct packed { + logic d; + logic de; + } empty; + struct packed { + logic d; + logic de; + } available; + struct packed { + logic d; + logic de; + } reached; + struct packed { + logic d; + logic de; + } full; + } iffifo_hw2reg_status_reg_t; + + typedef struct packed { + logic [31:0] d; + logic de; + } iffifo_hw2reg_occupancy_reg_t; + + // Register -> HW type + typedef struct packed { + iffifo_reg2hw_fifo_out_reg_t fifo_out; // [99:67] + iffifo_reg2hw_fifo_in_reg_t fifo_in; // [66:34] + iffifo_reg2hw_watermark_reg_t watermark; // [33:2] + iffifo_reg2hw_interrupts_reg_t interrupts; // [1:0] + } iffifo_reg2hw_t; + + // HW -> register type + typedef struct packed { + iffifo_hw2reg_fifo_out_reg_t fifo_out; // [72:41] + iffifo_hw2reg_status_reg_t status; // [40:33] + iffifo_hw2reg_occupancy_reg_t occupancy; // [32:0] + } iffifo_hw2reg_t; + + // Register offsets + parameter logic [BlockAw-1:0] IFFIFO_FIFO_OUT_OFFSET = 5'h0; + parameter logic [BlockAw-1:0] IFFIFO_FIFO_IN_OFFSET = 5'h4; + parameter logic [BlockAw-1:0] IFFIFO_STATUS_OFFSET = 5'h8; + parameter logic [BlockAw-1:0] IFFIFO_OCCUPANCY_OFFSET = 5'hc; + parameter logic [BlockAw-1:0] IFFIFO_WATERMARK_OFFSET = 5'h10; + parameter logic [BlockAw-1:0] IFFIFO_INTERRUPTS_OFFSET = 5'h14; + + // Reset values for hwext registers and their fields + parameter logic [31:0] IFFIFO_FIFO_OUT_RESVAL = 32'h0; + + // Register index + typedef enum int { + IFFIFO_FIFO_OUT, + IFFIFO_FIFO_IN, + IFFIFO_STATUS, + IFFIFO_OCCUPANCY, + IFFIFO_WATERMARK, + IFFIFO_INTERRUPTS + } iffifo_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] IFFIFO_PERMIT[6] = '{ + 4'b1111, // index[0] IFFIFO_FIFO_OUT + 4'b1111, // index[1] IFFIFO_FIFO_IN + 4'b0001, // index[2] IFFIFO_STATUS + 4'b1111, // index[3] IFFIFO_OCCUPANCY + 4'b1111, // index[4] IFFIFO_WATERMARK + 4'b0001 // index[5] IFFIFO_INTERRUPTS + }; + +endpackage + diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_top.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_top.sv new file mode 100644 index 00000000..cd8d2f56 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/iffifo/rtl/iffifo_reg_top.sv @@ -0,0 +1,451 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Top module auto-generated by `reggen` + + +`include "common_cells/assertions.svh" + +module iffifo_reg_top #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter int AW = 5 +) ( + input logic clk_i, + input logic rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + // To HW + output iffifo_reg_pkg::iffifo_reg2hw_t reg2hw, // Write + input iffifo_reg_pkg::iffifo_hw2reg_t hw2reg, // Read + + + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + + import iffifo_reg_pkg::*; + + localparam int DW = 32; + localparam int DBW = DW / 8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [ AW-1:0] reg_addr; + logic [ DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [ DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + + // Below register interface can be changed + reg_req_t reg_intf_req; + reg_rsp_t reg_intf_rsp; + + + assign reg_intf_req = reg_req_i; + assign reg_rsp_o = reg_intf_rsp; + + + assign reg_we = reg_intf_req.valid & reg_intf_req.write; + assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; + assign reg_addr = reg_intf_req.addr; + assign reg_wdata = reg_intf_req.wdata; + assign reg_be = reg_intf_req.wstrb; + assign reg_intf_rsp.rdata = reg_rdata; + assign reg_intf_rsp.error = reg_error; + assign reg_intf_rsp.ready = 1'b1; + + assign reg_rdata = reg_rdata_next; + assign reg_error = (devmode_i & addrmiss) | wr_err; + + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic [31:0] fifo_out_qs; + logic fifo_out_re; + logic [31:0] fifo_in_qs; + logic [31:0] fifo_in_wd; + logic fifo_in_we; + logic status_empty_qs; + logic status_available_qs; + logic status_reached_qs; + logic status_full_qs; + logic [31:0] occupancy_qs; + logic [31:0] watermark_qs; + logic [31:0] watermark_wd; + logic watermark_we; + logic interrupts_qs; + logic interrupts_wd; + logic interrupts_we; + + // Register instances + // R[fifo_out]: V(True) + + prim_subreg_ext #( + .DW(32) + ) u_fifo_out ( + .re (fifo_out_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.fifo_out.d), + .qre(reg2hw.fifo_out.re), + .qe (), + .q (reg2hw.fifo_out.q), + .qs (fifo_out_qs) + ); + + + // R[fifo_in]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_fifo_in ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(fifo_in_we), + .wd(fifo_in_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(reg2hw.fifo_in.qe), + .q (reg2hw.fifo_in.q), + + // to register interface (read) + .qs(fifo_in_qs) + ); + + + // R[status]: V(False) + + // F[empty]: 0:0 + prim_subreg #( + .DW (1), + .SWACCESS("RO"), + .RESVAL (1'h0) + ) u_status_empty ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .we(1'b0), + .wd('0), + + // from internal hardware + .de(hw2reg.status.empty.de), + .d (hw2reg.status.empty.d), + + // to internal hardware + .qe(), + .q (), + + // to register interface (read) + .qs(status_empty_qs) + ); + + + // F[available]: 1:1 + prim_subreg #( + .DW (1), + .SWACCESS("RO"), + .RESVAL (1'h0) + ) u_status_available ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .we(1'b0), + .wd('0), + + // from internal hardware + .de(hw2reg.status.available.de), + .d (hw2reg.status.available.d), + + // to internal hardware + .qe(), + .q (), + + // to register interface (read) + .qs(status_available_qs) + ); + + + // F[reached]: 2:2 + prim_subreg #( + .DW (1), + .SWACCESS("RO"), + .RESVAL (1'h0) + ) u_status_reached ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .we(1'b0), + .wd('0), + + // from internal hardware + .de(hw2reg.status.reached.de), + .d (hw2reg.status.reached.d), + + // to internal hardware + .qe(), + .q (), + + // to register interface (read) + .qs(status_reached_qs) + ); + + + // F[full]: 3:3 + prim_subreg #( + .DW (1), + .SWACCESS("RO"), + .RESVAL (1'h0) + ) u_status_full ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .we(1'b0), + .wd('0), + + // from internal hardware + .de(hw2reg.status.full.de), + .d (hw2reg.status.full.d), + + // to internal hardware + .qe(), + .q (), + + // to register interface (read) + .qs(status_full_qs) + ); + + + // R[occupancy]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RO"), + .RESVAL (32'h0) + ) u_occupancy ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .we(1'b0), + .wd('0), + + // from internal hardware + .de(hw2reg.occupancy.de), + .d (hw2reg.occupancy.d), + + // to internal hardware + .qe(), + .q (), + + // to register interface (read) + .qs(occupancy_qs) + ); + + + // R[watermark]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_watermark ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(watermark_we), + .wd(watermark_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.watermark.q), + + // to register interface (read) + .qs(watermark_qs) + ); + + + // R[interrupts]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_interrupts ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(interrupts_we), + .wd(interrupts_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(reg2hw.interrupts.qe), + .q (reg2hw.interrupts.q), + + // to register interface (read) + .qs(interrupts_qs) + ); + + + + + logic [5:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[0] = (reg_addr == IFFIFO_FIFO_OUT_OFFSET); + addr_hit[1] = (reg_addr == IFFIFO_FIFO_IN_OFFSET); + addr_hit[2] = (reg_addr == IFFIFO_STATUS_OFFSET); + addr_hit[3] = (reg_addr == IFFIFO_OCCUPANCY_OFFSET); + addr_hit[4] = (reg_addr == IFFIFO_WATERMARK_OFFSET); + addr_hit[5] = (reg_addr == IFFIFO_INTERRUPTS_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[0] & (|(IFFIFO_PERMIT[0] & ~reg_be))) | + (addr_hit[1] & (|(IFFIFO_PERMIT[1] & ~reg_be))) | + (addr_hit[2] & (|(IFFIFO_PERMIT[2] & ~reg_be))) | + (addr_hit[3] & (|(IFFIFO_PERMIT[3] & ~reg_be))) | + (addr_hit[4] & (|(IFFIFO_PERMIT[4] & ~reg_be))) | + (addr_hit[5] & (|(IFFIFO_PERMIT[5] & ~reg_be))))); + end + + assign fifo_out_re = addr_hit[0] & reg_re & !reg_error; + + assign fifo_in_we = addr_hit[1] & reg_we & !reg_error; + assign fifo_in_wd = reg_wdata[31:0]; + + assign watermark_we = addr_hit[4] & reg_we & !reg_error; + assign watermark_wd = reg_wdata[31:0]; + + assign interrupts_we = addr_hit[5] & reg_we & !reg_error; + assign interrupts_wd = reg_wdata[0]; + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[31:0] = fifo_out_qs; + end + + addr_hit[1]: begin + reg_rdata_next[31:0] = fifo_in_qs; + end + + addr_hit[2]: begin + reg_rdata_next[0] = status_empty_qs; + reg_rdata_next[1] = status_available_qs; + reg_rdata_next[2] = status_reached_qs; + reg_rdata_next[3] = status_full_qs; + end + + addr_hit[3]: begin + reg_rdata_next[31:0] = occupancy_qs; + end + + addr_hit[4]: begin + reg_rdata_next[31:0] = watermark_qs; + end + + addr_hit[5]: begin + reg_rdata_next[0] = interrupts_qs; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) + +endmodule + +module iffifo_reg_top_intf #( + parameter int AW = 5, + localparam int DW = 32 +) ( + input logic clk_i, + input logic rst_ni, + REG_BUS.in regbus_slave, + // To HW + output iffifo_reg_pkg::iffifo_reg2hw_t reg2hw, // Write + input iffifo_reg_pkg::iffifo_hw2reg_t hw2reg, // Read + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + localparam int unsigned STRB_WIDTH = DW / 8; + + `include "register_interface/typedef.svh" + `include "register_interface/assign.svh" + + // Define structs for reg_bus + typedef logic [AW-1:0] addr_t; + typedef logic [DW-1:0] data_t; + typedef logic [STRB_WIDTH-1:0] strb_t; + `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) + + reg_bus_req_t s_reg_req; + reg_bus_rsp_t s_reg_rsp; + + // Assign SV interface to structs + `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) + `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) + + + + iffifo_reg_top #( + .reg_req_t(reg_bus_req_t), + .reg_rsp_t(reg_bus_rsp_t), + .AW(AW) + ) i_regs ( + .clk_i, + .rst_ni, + .reg_req_i(s_reg_req), + .reg_rsp_o(s_reg_rsp), + .reg2hw, // Write + .hw2reg, // Read + .devmode_i + ); + +endmodule + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/data/im2col_spc.hjson b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/data/im2col_spc.hjson new file mode 100644 index 00000000..0319c03b --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/data/im2col_spc.hjson @@ -0,0 +1,255 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +{ name: "im2col_spc", + clock_primary: "clk_i", + bus_interfaces: [ + { protocol: "reg_iface", direction: "device" } + ], + regwidth: "32", + registers: [ + { name: "SRC_PTR", + desc: "Input data pointer (word aligned)", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "PTR_IN", desc: "Input data pointer (word aligned)" } + ] + }, + { name: "DST_PTR", + desc: "Output data pointer (word aligned)", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "PTR_OUT", desc: "Output data pointer (word aligned)" } + ] + }, + { name: "IW", + desc: "Image width", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "15:0", name: "SIZE", desc: "Image width" } + ] + }, + { name: "IH", + desc: "Image heigth", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "15:0", name: "SIZE", desc: "Image heigth" } + ] + }, + { name: "FW", + desc: "Filter width", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "7:0", name: "SIZE", desc: "Filter width" } + ] + }, + { name: "FH", + desc: "Filter heigth", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "7:0", name: "SIZE", desc: "Filter heigth" } + ] + }, + { name: "BATCH", + desc: "Batch number", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "7:0", name: "SIZE", desc: "Batch size" } + ] + }, + { name: "NUM_CH", + desc: "Number of channels. When written, the im2col will start executing", + swaccess: "rw", + hwaccess: "hro", + hwqe: "true", + fields: [ + { bits: "7:0", name: "NUM", desc: "Number of channels" } + ] + }, + { name: "CH_COL", + desc: "Number of iterations to perform", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "15:0", name: "NUM", desc: "Number of iterations" } + ] + }, + { name: "N_PATCHES_W", + desc: "Number of patches along W", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "15:0", name: "NUM", desc: "Number of patches" } + ] + }, + { name: "N_PATCHES_H", + desc: "Number of patches along H", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "15:0", name: "NUM", desc: "Number of patches" } + ] + }, + { name: "ADPT_PAD_RIGHT", + desc: "Adapted right padded region", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "7:0", name: "SIZE", desc: "Size of the adapted padded region" } + ] + }, + { name: "ADPT_PAD_BOTTOM", + desc: "Adapted bottom padded region", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "7:0", name: "SIZE", desc: "Size of the adapted padded region" } + ] + }, + { name: "LOG_STRIDES_D1", + desc: "Logarithmic number of strides along D1, set to 1 for no stride", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "3:0", name: "SIZE", desc: "Stride size" } + ] + }, + { name: "LOG_STRIDES_D2", + desc: "Logarithmic number of strides along D2, set to 1 for no stride", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "3:0", name: "SIZE", desc: "Stride size" } + ] + }, + { name: "STATUS", + desc: '''Status bit is set to one when the im2col SPC is ready''', + swaccess: "ro", + hwaccess: "hrw", + hwext: "true", + hwre: "true", // enable `re` latched signal of software read pulse + resval: 1, + fields: [ + { bits: "0", name: "READY", desc: "SPC is done"}, + ] + }, + { name: "SLOT", + desc: '''The DMA will wait for the signal + connected to the selected trigger_slots to be high + on the read and write side respectivly''', + swaccess: "rw", + hwaccess: "hro", + resval: 0, + fields: [ + { bits: "15:0", name: "RX_TRIGGER_SLOT", + desc: "Slot selection mask" + }, + { bits: "31:16", name: "TX_TRIGGER_SLOT", + desc: "Slot selection mask" + } + ] + }, + { name: "DATA_TYPE", + desc: '''Width/type of the data to transfer''', + swaccess: "rw", + hwaccess: "hro", + resval: 0, + fields: [ + { bits: "1:0", name: "DATA_TYPE", + desc: "Data type", + enum: [ + { value: "0", name: "DMA_32BIT_WORD", desc: "Transfers 32 bits"}, + { value: "1", name: "DMA_16BIT_WORD", desc: "Transfers 16 bits"}, + { value: "2", name: "DMA_8BIT_WORD" , desc: "Transfers 8 bits"}, + { value: "3", name: "DMA_8BIT_WORD_2",desc: "Transfers 8 bits"}, + ] + } + ] + }, + { name: "PAD_TOP", + desc: '''Set the top padding''', + swaccess: "rw", + hwaccess: "hro", + hwqe: "true", // enable `qe` latched signal of software write pulse: used to trigger the padding + resval: 0, + fields: [ + { bits: "5:0", name: "PAD", desc: "Top margin padding (2D)"} + ] + }, + { name: "PAD_BOTTOM", + desc: '''Set the bottom padding''', + swaccess: "rw", + hwaccess: "hro", + hwqe: "true", // enable `qe` latched signal of software write pulse: used to trigger the padding + resval: 0, + fields: [ + { bits: "5:0", name: "PAD", desc: "Bottom margin padding (2D)"} + ] + }, + { name: "PAD_RIGHT", + desc: '''Set the right padding''', + swaccess: "rw", + hwaccess: "hro", + hwqe: "true", // enable `qe` latched signal of software write pulse: used to trigger the padding + resval: 0, + fields: [ + { bits: "5:0", name: "PAD", desc: "Right margin padding (1D/2D)"} + ] + }, + { name: "PAD_LEFT", + desc: '''Set the left padding''', + swaccess: "rw", + hwaccess: "hro", + hwqe: "true", // enable `qe` latched signal of software write pulse: used to trigger the padding + resval: 0, + fields: [ + { bits: "5:0", name: "PAD", desc: "Left margin padding (1D/2D)"} + ] + }, + { name: "INTERRUPT_EN", + desc: '''Interrupt Enable Register''', + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", name: "EN", desc: "Enables operation done interrupt" } + ] + }, + { name: "SPC_IFR", + desc: '''Interrupt Flag Register for the SPC operation''', + swaccess: "ro", + hwaccess: "hrw", + hwext: "true", + hwre: "true", // latched signal of software write pulse + resval: 0, + fields: [ + { bits: "0", name: "FLAG", desc: "Set for operation done interrupt" } + ] + }, + { name: "SPC_CH_MASK", + desc: '''Mask that defines which DMA channel the SPC can access''', + swaccess: "rw", + hwaccess: "hro", + resval: 1, + fields: [ + { bits: "31:0", name: "MASK", desc: "Mask of DMA channel" } + ] + }, + { name: "SPC_CH_OFFSET", + desc: '''Offset of the DMA channel the SPC can access''', + swaccess: "rw", + hwaccess: "hro", + resval: 1, + fields: [ + { bits: "31:0", name: "OFF", desc: "Offset of DMA channels" } + ] + } + ] +} diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/im2col_spc.core b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/im2col_spc.core new file mode 100644 index 00000000..e196ccac --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/im2col_spc.core @@ -0,0 +1,28 @@ +CAPI=2: + +name: "example:ip:im2col_spc" +description: "im2col smart peripheral controller" + +# Copyright 2024 OpenHW Group +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +filesets: + files_rtl: + depend: + - pulp-platform.org::common_cells + - x-heep:ip:dma + files: + - rtl/im2col_spc_reg_pkg.sv + - rtl/im2col_spc_reg_top.sv + - rtl/dma_if_pkg.sv + - rtl/pipe_reg.sv + - rtl/im2col_spc_regintfc_controller.sv + - rtl/im2col_spc_param_fsm.sv + - rtl/im2col_spc.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_rtl diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/im2col_spc.vlt b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/im2col_spc.vlt new file mode 100644 index 00000000..1106245e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/im2col_spc.vlt @@ -0,0 +1,16 @@ +// Copyright 2022 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +`verilator_config + +lint_off -rule DECLFILENAME -file "*/im2col_spc_reg_top.sv" + +lint_off -rule WIDTH -file "*/rtl/im2col_spc_reg_top.sv" -match "Operator ASSIGNW expects *" + +lint_off -rule UNUSED -file "*/rtl/im2col_spc.sv" -match "Signal is not used: 'data_out_rvalid'" +lint_off -rule UNUSED -file "*/rtl/im2col_spc.sv" -match "Signal is not used: 'data_out_rdata'" + +lint_off -rule UNUSED -file "*/rtl/im2col_spc.sv" -match "Bits of signal are not used: *" +lint_off -rule UNUSED -file "*/rtl/im2col_spc_param_fsm.sv" -match "Bits of signal are not used: *" +lint_off -rule UNUSED -file "*/rtl/im2col_spc_regintfc_controller.sv" -match "Bits of signal are not used: *" diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/im2col_spc_gen.sh b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/im2col_spc_gen.sh new file mode 100755 index 00000000..c8050ec6 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/im2col_spc_gen.sh @@ -0,0 +1,8 @@ +# Copyright EPFL contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +echo "Generating RTL" +${PYTHON} ../../vendor/pulp_platform_register_interface/vendor/lowrisc_opentitan/util/regtool.py -r -t rtl data/im2col_spc.hjson +echo "Generating SW" +${PYTHON} ../../vendor/pulp_platform_register_interface/vendor/lowrisc_opentitan/util/regtool.py --cdefines -o ../../../sw/device/lib/drivers/im2col_spc/im2col_spc_regs.h data/im2col_spc.hjson diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/dma_if_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/dma_if_pkg.sv new file mode 100644 index 00000000..fd9ceb56 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/dma_if_pkg.sv @@ -0,0 +1,26 @@ +/* + * Copyright 2024 EPFL + * Solderpad Hardware License, Version 2.1, see LICENSE.md for details. + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Author: Tommaso Terzano + * + * + * Info: This module defines the interface structure for the DMA registers. + */ + +package dma_if_pkg; + + typedef struct packed { + logic [31:0] input_ptr; + logic [31:0] output_ptr; + logic [22:0] in_inc_d2; + logic [7:0] n_zeros_top; + logic [7:0] n_zeros_bottom; + logic [7:0] n_zeros_left; + logic [7:0] n_zeros_right; + logic [15:0] size_du_d1; + logic [15:0] size_du_d2; + } dma_if_t; + +endpackage diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc.sv new file mode 100644 index 00000000..be59baa2 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc.sv @@ -0,0 +1,623 @@ +/* + * Copyright 2024 EPFL + * Solderpad Hardware License, Version 2.1, see LICENSE.md for details. + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Author: Tommaso Terzano + * + * + * Info: Im2col accelerator implemented as a Smart Peripheral Controller. + * It accesses the DMA channels to perform the matrix manipulation operation known as + * "image to column" (im2col), which enables efficient CNN inference by transforming + * the input tensor to use the GEMM library. + */ + +module im2col_spc + import obi_pkg::*; + import reg_pkg::*; +#( +) ( + input logic clk_i, + input logic rst_ni, + + input reg_rsp_t aopb2im2col_resp_i, + output reg_req_t im2col2aopb_req_o, + + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + + input logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] dma_done_i, + output logic im2col_spc_done_int_o +); + + import core_v_mini_mcu_pkg::*; + import dma_if_pkg::*; + import im2col_spc_reg_pkg::*; + import dma_reg_pkg::*; + + /*_________________________________________________________________________________________________________________________________ */ + + /* Parameter definition */ + + /* FIFO dimension */ + localparam FIFO_DEPTH = 8; + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signals declaration */ + + /* General status signal */ + enum { + READY, + BUSY + } im2col_status; + + /* Control Unit signals */ + logic im2col_start; + logic im2col_fsms_done; + logic im2col_done; + + /* Interrupt management signals */ + logic im2col_spc_ifr; + + /* DMA FIFO signals */ + logic fifo_flush; + logic fifo_full; + logic fifo_empty; + dma_if_t fifo_input; + logic fifo_push; + dma_if_t fifo_output; + logic fifo_pop; + logic [$clog2(FIFO_DEPTH)-1:0] fifo_usage; + + /* DMA interface unit signals */ + logic im2col_param_done; + logic dma_ch_free; + logic dma_ch_first_write; + logic [31:0] dma_ch_en_mask; + logic [31:0] dma_ch_offset; + logic [31:0] dma_addr; + logic [31:0] dma_wdata; + logic dma_if_loaded; + logic dma_regintfc_start; + logic dma_regintfc_done; + + /* Regtool signals */ + im2col_spc_reg2hw_t reg2hw; + im2col_spc_hw2reg_t hw2reg; + + enum { + READY_IF_CU, + IDLE_IF_CU, + GET_TRANSACTION, + LOAD_TRANSACTION + } + dma_if_cu_q, dma_if_cu_d; + + enum { + IDLE_IF_LOAD, + WRITE_DIMENSIONALITY, + WRITE_SLOTS, + WRITE_SRC_DATATYPE, + WRITE_DST_DATATYPE, + WRITE_TOP_PAD, + WRITE_BOTTOM_PAD, + WRITE_LEFT_PAD, + WRITE_RIGHT_PAD, + WRITE_INPUT_PTR, + WRITE_OUTPUT_PTR, + WRITE_INC_SRC_D1, + WRITE_INC_SRC_D2, + WRITE_INC_DST_D1, + WRITE_INC_DST_D2, + WRITE_SIZE_D2, + WRITE_SIZE_D1, + DONE + } + dma_if_cu_load_q, dma_if_cu_load_d; + + /*_________________________________________________________________________________________________________________________________ */ + + /* Module instantiation */ + + /* Regtool top module */ + im2col_spc_reg_top #( + .reg_req_t(reg_req_t), + .reg_rsp_t(reg_rsp_t) + ) im2col_spc_reg_top_i ( + .clk_i, + .rst_ni, + .reg_req_i, + .reg_rsp_o, + .reg2hw, + .hw2reg, + .devmode_i(1'b1) + ); + + /* DMA FIFO */ + fifo_v3 #( + .DEPTH(FIFO_DEPTH), + .FALL_THROUGH(1'b1), + .dtype(dma_if_t) + ) dma_fifo_i ( + .clk_i, + .rst_ni, + .flush_i(fifo_flush), + .testmode_i(1'b0), + // status flags + .full_o(fifo_full), + .empty_o(fifo_empty), + .usage_o(fifo_usage), + // as long as the queue is not full we can push new data + .data_i(fifo_input), + .push_i(fifo_push), + // as long as the queue is not empty we can pop new elements + .data_o(fifo_output), + .pop_i(fifo_pop) + ); + + /* Parameter FSM */ + im2col_spc_param_fsm im2col_spc_param_fsm_i ( + .clk_i, + .rst_ni, + .reg2hw_i(reg2hw), + .im2col_done_i(im2col_done), + .im2col_start_i(im2col_start), + .fifo_full_i(fifo_full), + .fifo_push_o(fifo_push), + .im2col_param_done_o(im2col_param_done), + .fifo_input_o(fifo_input) + ); + + /* Register interface control FSM */ + im2col_spc_regintfc_controller im2col_spc_regintfc_controller_i ( + .clk_i, + .rst_ni, + .addr_i(dma_addr), + .wdata_i(dma_wdata), + .start_i(dma_regintfc_start), + .aopb_resp_i(aopb2im2col_resp_i), + .aopb_req_o(im2col2aopb_req_o), + .done_o(dma_regintfc_done) + ); + + /*_________________________________________________________________________________________________________________________________ */ + + /* FSMs instantiation */ + + /* General status */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_im2col_status + if (!rst_ni) begin + im2col_status <= READY; + end else begin + if (im2col_done == 1'b1) begin + im2col_status <= READY; + end else if (im2col_start == 1'b1) begin + im2col_status <= BUSY; + end + end + end + + /* DMA interface unit state transition logic */ + always_comb begin : proc_comb_dma_if_fsm + + unique case (dma_if_cu_d) + IDLE_IF_CU: begin + if (fifo_empty == 1'b0 && im2col_fsms_done == 1'b0 && dma_ch_free == 1'b1) begin + dma_if_cu_q = GET_TRANSACTION; + end else begin + dma_if_cu_q = IDLE_IF_CU; + end + end + + GET_TRANSACTION: begin + if (fifo_empty == 1'b0 && dma_ch_free == 1'b1) begin + dma_if_cu_q = LOAD_TRANSACTION; + end else begin + dma_if_cu_q = IDLE_IF_CU; + end + end + + LOAD_TRANSACTION: begin + if (dma_if_loaded == 1'b1) begin + if (im2col_fsms_done == 1'b0 && dma_ch_free == 1'b1) begin + dma_if_cu_q = GET_TRANSACTION; + end else begin + dma_if_cu_q = IDLE_IF_CU; + end + end else begin + dma_if_cu_q = LOAD_TRANSACTION; + end + end + + default: begin + dma_if_cu_q = IDLE_IF_CU; + end + endcase + end + + /* DMA interface unit state transition ff */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_dma_if_fsm + if (!rst_ni) begin + dma_if_cu_d <= IDLE_IF_CU; + end else begin + dma_if_cu_d <= dma_if_cu_q; + end + end + + /* DMA interface unit transaction loading state transition logic */ + always_comb begin : proc_comb_dma_if_trans_load_fsm + unique case (dma_if_cu_load_d) + IDLE_IF_LOAD: begin + if (dma_if_cu_d == GET_TRANSACTION && im2col_fsms_done == 1'b0 && dma_ch_free == 1'b1) begin + if (dma_ch_first_write == 1'b0) begin + dma_if_cu_load_q = WRITE_DIMENSIONALITY; + end else begin + dma_if_cu_load_q = WRITE_TOP_PAD; + end + end else begin + dma_if_cu_load_q = IDLE_IF_LOAD; + end + end + + WRITE_DIMENSIONALITY: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_SLOTS; + end else if (dma_if_cu_d == IDLE_IF_CU) begin + dma_if_cu_load_q = IDLE_IF_LOAD; + end else begin + dma_if_cu_load_q = WRITE_DIMENSIONALITY; + end + end + + WRITE_SLOTS: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_SRC_DATATYPE; + end else if (dma_if_cu_d == IDLE_IF_CU) begin + dma_if_cu_load_q = IDLE_IF_LOAD; + end else begin + dma_if_cu_load_q = WRITE_SLOTS; + end + end + + WRITE_SRC_DATATYPE: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_DST_DATATYPE; + end else begin + dma_if_cu_load_q = WRITE_SRC_DATATYPE; + end + end + + WRITE_DST_DATATYPE: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_TOP_PAD; + end else begin + dma_if_cu_load_q = WRITE_DST_DATATYPE; + end + end + + WRITE_TOP_PAD: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_BOTTOM_PAD; + end else begin + dma_if_cu_load_q = WRITE_TOP_PAD; + end + end + + WRITE_BOTTOM_PAD: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_LEFT_PAD; + end else begin + dma_if_cu_load_q = WRITE_BOTTOM_PAD; + end + end + + WRITE_LEFT_PAD: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_RIGHT_PAD; + end else begin + dma_if_cu_load_q = WRITE_LEFT_PAD; + end + end + + WRITE_RIGHT_PAD: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_INPUT_PTR; + end else begin + dma_if_cu_load_q = WRITE_RIGHT_PAD; + end + end + + WRITE_INPUT_PTR: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_OUTPUT_PTR; + end else begin + dma_if_cu_load_q = WRITE_INPUT_PTR; + end + end + + WRITE_OUTPUT_PTR: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_INC_SRC_D1; + end else begin + dma_if_cu_load_q = WRITE_OUTPUT_PTR; + end + end + + WRITE_INC_SRC_D1: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_INC_SRC_D2; + end else begin + dma_if_cu_load_q = WRITE_INC_SRC_D1; + end + end + + WRITE_INC_SRC_D2: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_INC_DST_D1; + end else begin + dma_if_cu_load_q = WRITE_INC_SRC_D2; + end + end + + WRITE_INC_DST_D1: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_INC_DST_D2; + end else begin + dma_if_cu_load_q = WRITE_INC_DST_D1; + end + end + + WRITE_INC_DST_D2: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_SIZE_D2; + end else begin + dma_if_cu_load_q = WRITE_INC_DST_D2; + end + end + + WRITE_SIZE_D2: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = WRITE_SIZE_D1; + end else begin + dma_if_cu_load_q = WRITE_SIZE_D2; + end + end + + WRITE_SIZE_D1: begin + if (dma_regintfc_done == 1'b1) begin + dma_if_cu_load_q = DONE; + end else begin + dma_if_cu_load_q = WRITE_SIZE_D1; + end + end + + DONE: begin + dma_if_cu_load_q = IDLE_IF_LOAD; + end + + default: begin + dma_if_cu_load_q = IDLE_IF_LOAD; + end + + endcase + end + + always_comb begin : proc_comb_dma_if_trans_load_fsm_regintfc + dma_if_loaded = 1'b0; + dma_regintfc_start = 1'b0; + fifo_pop = 1'b0; + dma_wdata = '0; + dma_addr = '0; + + unique case (dma_if_cu_load_d) + IDLE_IF_LOAD: begin + end + + WRITE_DIMENSIONALITY: begin + dma_wdata = 32'h1; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_DIM_CONFIG_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_SLOTS: begin + dma_wdata = {reg2hw.slot.tx_trigger_slot.q, reg2hw.slot.rx_trigger_slot.q}; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_SLOT_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_SRC_DATATYPE: begin + dma_wdata = {30'h0, reg2hw.data_type.q} & 32'h3; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_SRC_DATA_TYPE_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_DST_DATATYPE: begin + dma_wdata = {30'h0, reg2hw.data_type.q} & 32'h3; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_DST_DATA_TYPE_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_TOP_PAD: begin + dma_wdata = {24'h0, fifo_output.n_zeros_top}; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_PAD_TOP_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_BOTTOM_PAD: begin + dma_wdata = {24'h0, fifo_output.n_zeros_bottom}; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_PAD_BOTTOM_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_LEFT_PAD: begin + dma_wdata = {24'h0, fifo_output.n_zeros_left}; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_PAD_LEFT_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_RIGHT_PAD: begin + dma_wdata = {24'h0, fifo_output.n_zeros_right}; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_PAD_RIGHT_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_INPUT_PTR: begin + dma_wdata = fifo_output.input_ptr; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_SRC_PTR_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_OUTPUT_PTR: begin + dma_wdata = fifo_output.output_ptr; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_DST_PTR_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_INC_SRC_D1: begin + dma_wdata = (1 << {28'h0, reg2hw.log_strides_d1.q}) << (2 - reg2hw.data_type.q) & 32'h3f; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_SRC_PTR_INC_D1_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_INC_SRC_D2: begin + dma_wdata = {9'h0, fifo_output.in_inc_d2} << (2 - reg2hw.data_type.q) & 32'h7fffff; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_SRC_PTR_INC_D2_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_INC_DST_D1: begin + dma_wdata = (4 >> reg2hw.data_type.q) & 32'h3f; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_DST_PTR_INC_D1_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_INC_DST_D2: begin + dma_wdata = (4 >> reg2hw.data_type.q) & 32'h7fffff; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_DST_PTR_INC_D2_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_SIZE_D2: begin + dma_wdata = {16'h0, fifo_output.size_du_d2}; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_SIZE_D2_OFFSET}; + dma_regintfc_start = 1'b1; + end + + WRITE_SIZE_D1: begin + dma_wdata = {16'h0, fifo_output.size_du_d1}; + dma_addr = dma_ch_offset + {25'h0, dma_reg_pkg::DMA_SIZE_D1_OFFSET}; + dma_regintfc_start = 1'b1; + end + + DONE: begin + dma_if_loaded = 1'b1; + fifo_pop = 1'b1; + end + endcase + end + + /* DMA interface unit transaction loading state transition ff */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_dma_if_trans_load_dq + if (!rst_ni) begin + dma_if_cu_load_d <= IDLE_IF_LOAD; + end else begin + dma_if_cu_load_d <= dma_if_cu_load_q; + end + end + + /* Channel tracker */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_control_unit + if (!rst_ni) begin + dma_ch_free <= 1'b1; + dma_ch_first_write <= 1'b0; + end else begin + /* Set the dma_ch_free when im2col starts or when a transaction is finished */ + if (im2col_start == 1'b1) begin + dma_ch_first_write <= 1'b0; + dma_ch_free <= 1'b1; + end + + if (|(dma_ch_en_mask[core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] & dma_done_i) == 1'b1) begin + dma_ch_free <= 1'b1; + end + + /* Clear the ch free flag only if the next state won't be the IDLE state */ + if (dma_if_cu_d == GET_TRANSACTION && dma_if_cu_q != IDLE_IF_CU) begin + dma_ch_first_write <= 1'b1; + dma_ch_free <= 1'b0; + end + end + end + + /* FIFO reset */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_fifo_reset + if (!rst_ni) begin + fifo_flush <= 1'b1; + end else begin + fifo_flush <= 1'b0; + end + end + + /* Transaction IFR update */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_spc_ifr + if (~rst_ni) begin + im2col_spc_ifr <= '0; + end else if (reg2hw.interrupt_en.q == 1'b1) begin + // Enter here only if the im2col_done interrupt is enabled + if (im2col_done == 1'b1) begin + im2col_spc_ifr <= 1'b1; + end else if (reg2hw.spc_ifr.re == 1'b1) begin + // If the IFR bit is read, we must clear the transaction_ifr + im2col_spc_ifr <= 1'b0; + end + end + end + + /* Global fsm done signal update logic */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_spc_done + if (!rst_ni) begin + im2col_fsms_done <= 1'b0; + end else begin + if (im2col_done == 1'b1) begin + im2col_fsms_done <= 1'b0; + end else if (dma_if_cu_load_d == DONE && im2col_param_done == 1'b1 && fifo_usage == 1) begin + im2col_fsms_done <= 1'b1; + end + end + end + + /* Global done signal update logic */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_done + if (!rst_ni) begin + im2col_done <= 1'b0; + end else begin + if (im2col_fsms_done == 1'b1 && dma_ch_free == 1'b1) begin + im2col_done <= 1'b1; + end else begin + im2col_done <= 1'b0; + end + end + end + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signal assignments */ + + /* Start signal assignment */ + assign im2col_start = (reg2hw.num_ch.qe == 1'b1); + + /* Transaction loading process */ + assign hw2reg.status.d = im2col_status == READY; + + /* Interrupt management */ + assign hw2reg.spc_ifr.d = im2col_spc_ifr; + assign im2col_spc_done_int_o = im2col_spc_ifr; + + /* DMA channels mask register */ + assign dma_ch_en_mask = reg2hw.spc_ch_mask.q; + + /* DMA channel offset */ + assign dma_ch_offset = reg2hw.spc_ch_offset.q; + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc_param_fsm.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc_param_fsm.sv new file mode 100644 index 00000000..2bd1d190 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc_param_fsm.sv @@ -0,0 +1,551 @@ +/* + * Copyright 2024 EPFL + * Solderpad Hardware License, Version 2.1, see LICENSE.md for details. + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Author: Tommaso Terzano + * + * + * Info: Parameter FSM of the im2col accelerator. + */ + +module im2col_spc_param_fsm + import im2col_spc_reg_pkg::*; + import dma_if_pkg::*; +( + input logic clk_i, + input logic rst_ni, + input im2col_spc_reg2hw_t reg2hw_i, + input logic im2col_done_i, + input logic fifo_full_i, + input logic im2col_start_i, + output logic fifo_push_o, + output logic im2col_param_done_o, + output dma_if_t fifo_input_o + +); + /*_________________________________________________________________________________________________________________________________ */ + + /* Signals declaration */ + + /* Register interface */ + im2col_spc_reg2hw_t reg2hw; + + /* + * Every "comp" state refers to variable computations that precede the DMA call in the + * loop, while any "param" state refers to the DMA parameters computation that follows the DMA call. + */ + enum { + IDLE, + N_ZEROS_PRECOMP, + ZEROS_COND_EVAL, + N_ZEROS_COMP_1, + N_ZEROS_COMP_2, + N_ZEROS_COMP_3, + OUT_PTR_UPDATE, + IM_OFFSET_UPDATE, + INDEX_COMP_1, + INDEX_COMP_2, + INDEX_COMP_3, + START_DMA_RUN + } + param_state_q, param_state_d; + + /* Parameters computation signals */ + logic [7:0] w_offset; + logic [7:0] h_offset; + logic [7:0] im_c; + logic [7:0] im_row; + logic [7:0] im_col; + logic [7:0] fw_min_w_offset; + logic [7:0] fh_min_h_offset; + logic [7:0] n_zeros_left; + logic [7:0] n_zeros_right; + logic [7:0] n_zeros_top; + logic [7:0] n_zeros_bottom; + logic [15:0] size_transfer_1d; + logic [15:0] size_transfer_2d; + logic [31:0] index; + logic [31:0] h_offset_counter; + logic [31:0] im_c_counter; + logic [15:0] ch_col_counter; + logic [7:0] batch_counter; + logic [31:0] input_data_ptr; + logic [31:0] output_data_ptr; + logic [31:0] source_inc_d2; + logic [31:0] out_data_ptr_inc; + logic left_zero_cond; + logic top_zero_cond; + logic right_zero_cond; + logic bottom_zero_cond; + logic [7:0] n_zeros_left_std; + logic [7:0] n_zeros_top_std; + logic [7:0] n_zeros_right_std; + logic [7:0] n_zeros_bottom_std; + + /* Pipelining control signals */ + logic output_data_ptr_en; + logic im_offset_en; + logic batch_inc_en; + logic batch_rst; + logic zeros_phase1_en; + logic zeros_phase2_en; + logic zeros_rst; + logic output_data_ptr_rst; + logic pipe_rst; + + /* Status signals */ + logic im2col_param_done; + logic im2col_done; + logic im2col_start; + logic fifo_push; + logic fifo_full; + + /* Pipelining signals */ + logic [7:0] n_zeros_left_comp1_n; + logic [7:0] n_zeros_top_comp1_n; + logic [7:0] n_zeros_right_comp1_n; + logic [7:0] n_zeros_bottom_comp1_n; + logic [7:0] n_zeros_left_comp1; + logic [7:0] n_zeros_top_comp1; + logic [7:0] n_zeros_right_comp1; + logic [7:0] n_zeros_bottom_comp1; + logic [31:0] index_comp1_n; + logic [31:0] index_comp2_n; + logic [31:0] index_comp3_n; + logic [31:0] index_comp4_n; + logic [31:0] index_comp1; + logic [31:0] index_comp2; + logic [31:0] index_comp3; + logic [31:0] index_comp4; + + /*_________________________________________________________________________________________________________________________________ */ + + /* FSMs instantiation */ + + /* Parameter computation state transition ff */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_param_state_dq + if (!rst_ni) begin + param_state_d <= IDLE; + end else begin + param_state_d <= param_state_q; + end + end + + /* Parameter computation done signal update */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_param_done + if (!rst_ni) begin + im2col_param_done <= 1'b0; + end else begin + if (im2col_done == 1'b1) begin + im2col_param_done <= 1'b0; + end else if (ch_col_counter == (reg2hw.ch_col.q - 1) && batch_counter == reg2hw.batch.q) begin + im2col_param_done <= 1'b1; + end + end + end + + /* Parameter computation state transition FSM */ + always_comb begin : proc_comb_param_state_fsm + fifo_push = 1'b0; + batch_inc_en = 1'b0; + batch_rst = 1'b0; + output_data_ptr_en = 1'b0; + im_offset_en = 1'b0; + zeros_phase1_en = 1'b0; + zeros_phase2_en = 1'b0; + zeros_rst = 1'b0; + output_data_ptr_rst = 1'b0; + + unique case (param_state_d) + + IDLE: begin + batch_rst = 1'b1; + zeros_rst = 1'b1; + output_data_ptr_rst = 1'b1; + if (im2col_start == 1'b1) begin + param_state_q = N_ZEROS_PRECOMP; + end else begin + param_state_q = IDLE; + end + end + + /* Cycle needed to precompute parts of both the zero condition and the number of zero computations + * and to reduce the datapath for FPGA targets. Every signal is identical to the IDLE state. + * @Tod0: is this really necessary? + */ + N_ZEROS_PRECOMP: begin + batch_rst = 1'b1; + zeros_rst = 1'b1; + output_data_ptr_rst = 1'b1; + param_state_q = ZEROS_COND_EVAL; + end + + ZEROS_COND_EVAL: begin + if (im2col_param_done == 1'b1) begin + param_state_q = IDLE; + end else begin + param_state_q = N_ZEROS_COMP_1; + end + end + + N_ZEROS_COMP_1: begin + zeros_phase1_en = 1'b1; + param_state_q = N_ZEROS_COMP_2; + end + + N_ZEROS_COMP_2: begin + zeros_phase2_en = 1'b1; + param_state_q = N_ZEROS_COMP_3; + end + + N_ZEROS_COMP_3: begin + zeros_phase2_en = 1'b1; + param_state_q = INDEX_COMP_1; + end + + INDEX_COMP_1: begin + param_state_q = INDEX_COMP_2; + end + + INDEX_COMP_2: begin + param_state_q = INDEX_COMP_3; + end + + INDEX_COMP_3: begin + if (fifo_full == 1'b0) begin + param_state_q = START_DMA_RUN; + end else begin + param_state_q = INDEX_COMP_3; + end + end + + OUT_PTR_UPDATE: begin + batch_inc_en = 1'b1; + output_data_ptr_en = 1'b1; + if (batch_counter == reg2hw.batch.q - 1) begin + param_state_q = IM_OFFSET_UPDATE; + end else begin + param_state_q = ZEROS_COND_EVAL; + end + end + + IM_OFFSET_UPDATE: begin + batch_rst = 1'b1; + im_offset_en = 1'b1; + param_state_q = ZEROS_COND_EVAL; + end + + START_DMA_RUN: begin + fifo_push = 1'b1; + param_state_q = OUT_PTR_UPDATE; + end + + default: begin + param_state_q = IDLE; + end + + endcase + end + + /* Number of zeros computation */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_zeros_phase1_comp + if (!rst_ni) begin + fw_min_w_offset <= '0; + fh_min_h_offset <= '0; + end else begin + if (zeros_phase1_en == 1'b1) begin + fw_min_w_offset <= reg2hw.fw.q - 1 - w_offset; + fh_min_h_offset <= reg2hw.fh.q - 1 - h_offset; + end else if (zeros_rst == 1'b1) begin + fw_min_w_offset <= '0; + fh_min_h_offset <= '0; + end + end + end + + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_zeros_phase2_comp + if (!rst_ni) begin + n_zeros_left <= '0; + n_zeros_right <= '0; + n_zeros_top <= '0; + n_zeros_bottom <= '0; + end else begin + if (zeros_phase2_en == 1'b1) begin + /* Left zeros computation */ + if (w_offset >= {2'h0, reg2hw.pad_left.q}) begin + n_zeros_left <= 0; + end else begin + n_zeros_left <= n_zeros_left_std + {7'h0, left_zero_cond}; // Sum a 1 if the condition is true + end + + /* Top zeros computation */ + if (h_offset >= {2'h0, reg2hw.pad_top.q}) begin + n_zeros_top <= 0; + end else begin + n_zeros_top <= n_zeros_top_std + {7'h0, top_zero_cond}; + end + + /* Right zeros computation */ + if (fw_min_w_offset >= {2'h0, reg2hw.pad_right.q} || reg2hw.adpt_pad_right.q == 0) begin + n_zeros_right <= 0; + end else begin + n_zeros_right <= n_zeros_right_std + {7'h0, right_zero_cond}; + end + + /* Bottom zeros computation */ + if (fh_min_h_offset >= {2'h0, reg2hw.pad_bottom.q} || reg2hw.adpt_pad_bottom.q == 0) begin + n_zeros_bottom <= 0; + end else begin + n_zeros_bottom <= n_zeros_bottom_std + {7'h0, bottom_zero_cond}; + end + end else if (zeros_rst == 1'b1) begin + n_zeros_left <= '0; + n_zeros_right <= '0; + n_zeros_top <= '0; + n_zeros_bottom <= '0; + end + end + end + + + /* Batch counter */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_batch_counter + if (!rst_ni) begin + batch_counter <= '0; + end else begin + if (batch_inc_en == 1'b1) begin + batch_counter <= batch_counter + 1; + end else if (batch_rst == 1'b1) begin + batch_counter <= '0; + end + end + end + + /* w_offset counter */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_w_offset_counter + if (!rst_ni) begin + w_offset <= '0; + end else begin + if (im2col_param_done == 1'b1) begin + w_offset <= '0; + end else if (im_offset_en == 1'b1) begin + if (w_offset == reg2hw.fw.q - 1) begin + w_offset <= '0; + end else begin + w_offset <= w_offset + 1; + end + end + end + end + + /* h_offset counter */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_h_offset_counter + if (!rst_ni) begin + h_offset <= '0; + h_offset_counter <= '0; + end else begin + if (im2col_param_done == 1'b1) begin + h_offset <= '0; + h_offset_counter <= '0; + end else if (im_offset_en == 1'b1) begin + if (h_offset_counter == {24'h0, reg2hw.fw.q} - 1) begin + h_offset_counter <= '0; + if (h_offset == reg2hw.fh.q - 1) begin + h_offset <= '0; + end else begin + h_offset <= h_offset + 1; + end + end else begin + h_offset_counter <= h_offset_counter + 1; + end + end + end + end + + /* im_c counter */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_im_c_counter + if (!rst_ni) begin + im_c <= '0; + im_c_counter <= '0; + end else begin + if (im2col_param_done == 1'b1) begin + im_c <= '0; + im_c_counter <= '0; + end else if (im_offset_en == 1'b1) begin + if (im_c_counter == {24'h0, reg2hw.fh.q} * {24'h0, reg2hw.fw.q} - 1) begin + im_c_counter <= '0; + im_c <= im_c + 1; + end else begin + im_c_counter <= im_c_counter + 1; + end + end + end + end + + /* ch_col counter */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_ch_col_counter + if (!rst_ni) begin + ch_col_counter <= '0; + end else begin + if (im2col_param_done == 1'b1) begin + ch_col_counter <= '0; + end else if (im_offset_en == 1'b1) begin + if (ch_col_counter == reg2hw.ch_col.q - 1) begin + ch_col_counter <= '0; + end else begin + ch_col_counter <= ch_col_counter + 1; + end + end + end + end + + /* Output data pointer counter */ + always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_output_data_ptr + if (!rst_ni) begin + output_data_ptr <= reg2hw.dst_ptr.q; + end else begin + if (output_data_ptr_en == 1'b1) begin + output_data_ptr <= output_data_ptr + out_data_ptr_inc; + end else if (output_data_ptr_rst == 1'b1) begin + output_data_ptr <= reg2hw.dst_ptr.q; + end + end + end + + /*_________________________________________________________________________________________________________________________________ */ + + /* Modules instantiation */ + + /* Pipeline modules */ + pipe_reg #( + .WIDTH(8) + ) pipe_reg_left_zeros ( + .clk_i, + .rst_ni (pipe_rst), + .data_in (n_zeros_left_comp1_n), + .data_out(n_zeros_left_comp1) + ); + + pipe_reg #( + .WIDTH(8) + ) pipe_reg_top_zeros ( + .clk_i, + .rst_ni (pipe_rst), + .data_in (n_zeros_top_comp1_n), + .data_out(n_zeros_top_comp1) + ); + + pipe_reg #( + .WIDTH(8) + ) pipe_reg_right_zeros ( + .clk_i, + .rst_ni (pipe_rst), + .data_in (n_zeros_right_comp1_n), + .data_out(n_zeros_right_comp1) + ); + + pipe_reg #( + .WIDTH(8) + ) pipe_reg_bottom_zeros ( + .clk_i, + .rst_ni (pipe_rst), + .data_in (n_zeros_bottom_comp1_n), + .data_out(n_zeros_bottom_comp1) + ); + + pipe_reg #( + .WIDTH(32) + ) pipe_reg_index_comp1 ( + .clk_i, + .rst_ni (pipe_rst), + .data_in (index_comp1_n), + .data_out(index_comp1) + ); + + pipe_reg #( + .WIDTH(32) + ) pipe_reg_index_comp2 ( + .clk_i, + .rst_ni (pipe_rst), + .data_in (index_comp2_n), + .data_out(index_comp2) + ); + + pipe_reg #( + .WIDTH(32) + ) pipe_reg_index_comp3 ( + .clk_i, + .rst_ni (pipe_rst), + .data_in (index_comp3_n), + .data_out(index_comp3) + ); + + pipe_reg #( + .WIDTH(32) + ) pipe_reg_index_comp4 ( + .clk_i, + .rst_ni (pipe_rst), + .data_in (index_comp4_n), + .data_out(index_comp4) + ); + + + /*_________________________________________________________________________________________________________________________________ */ + + /* Signal assignments */ + + assign im_row = h_offset - {2'h0, reg2hw.pad_top.q}; // im_row = h_offset - TOP_PAD; + assign im_col = w_offset - {2'h0, reg2hw.pad_left.q}; // im_col = w_offset - LEFT_PAD; + + assign n_zeros_left_comp1_n = ({2'h0, reg2hw.pad_left.q} - w_offset); + assign n_zeros_left_std = n_zeros_left_comp1 >> {4'h0, reg2hw.log_strides_d1.q}; + + assign n_zeros_top_comp1_n = ({2'h0, reg2hw.pad_top.q} - h_offset); + assign n_zeros_top_std = n_zeros_top_comp1 >> {4'h0, reg2hw.log_strides_d2.q}; + + assign n_zeros_right_comp1_n = (reg2hw.adpt_pad_right.q - fw_min_w_offset); + assign n_zeros_right_std = n_zeros_right_comp1 >> {4'h0, reg2hw.log_strides_d1.q}; + + assign n_zeros_bottom_comp1_n = (reg2hw.adpt_pad_bottom.q - fh_min_h_offset); + assign n_zeros_bottom_std = n_zeros_bottom_comp1 >> {4'h0, reg2hw.log_strides_d2.q}; + + assign size_transfer_1d = reg2hw.n_patches_w.q - {8'h0, n_zeros_left} - {8'h0, n_zeros_right}; + assign size_transfer_2d = reg2hw.n_patches_h.q - {8'h0, n_zeros_top} - {8'h0, n_zeros_bottom}; + + assign index_comp1_n = ({24'h0, batch_counter} * {24'h0, reg2hw.num_ch.q} + {24'h0, im_c}); + assign index_comp2_n = index_comp1 * {16'h0, reg2hw.ih.q}; + assign index_comp3_n = (index_comp2 + ({{24{im_row[7]}}, im_row} + ({24'h0, n_zeros_top} << {4'h0, reg2hw.log_strides_d2.q}))); + assign index_comp4_n = index_comp3 * {16'h0, reg2hw.iw.q} + {{24{im_col[7]}}, im_col}; + assign index = index_comp4 + ({24'h0, n_zeros_left} << {24'h0, reg2hw.log_strides_d1.q}); + + assign source_inc_d2 = (({16'h0, reg2hw.iw.q} << {24'h0, reg2hw.log_strides_d2.q}) - (({16'h0, size_transfer_1d} - 1) << {24'h0, reg2hw.log_strides_d1.q})); + assign input_data_ptr = reg2hw.src_ptr.q + (index << (2 - reg2hw.data_type.q)); + assign out_data_ptr_inc = ({16'h0, reg2hw.n_patches_h.q} * {16'h0, reg2hw.n_patches_w.q}) << (2 - reg2hw.data_type.q); + + assign left_zero_cond = |((n_zeros_left_comp1) & ((1 << {reg2hw.log_strides_d1.q}) - 1)); + assign top_zero_cond = |((n_zeros_top_comp1) & ((1 << {reg2hw.log_strides_d2.q}) - 1)); + assign right_zero_cond = |((n_zeros_right_comp1) & ((1 << {reg2hw.log_strides_d1.q}) - 1)); + assign bottom_zero_cond = |((n_zeros_bottom_comp1) & ((1 << {reg2hw.log_strides_d2.q}) - 1)); + + assign pipe_rst = (rst_ni && param_state_d != IDLE); + + /* Output signals */ + assign im2col_param_done_o = im2col_param_done; + assign reg2hw = reg2hw_i; + assign im2col_done = im2col_done_i; + assign im2col_start = im2col_start_i; + assign fifo_push_o = fifo_push; + assign fifo_full = fifo_full_i; + + assign fifo_input_o.input_ptr = input_data_ptr; + assign fifo_input_o.output_ptr = output_data_ptr; + assign fifo_input_o.in_inc_d2 = source_inc_d2[22:0]; + assign fifo_input_o.n_zeros_top = n_zeros_top; + assign fifo_input_o.n_zeros_bottom = n_zeros_bottom; + assign fifo_input_o.n_zeros_left = n_zeros_left; + assign fifo_input_o.n_zeros_right = n_zeros_right; + assign fifo_input_o.size_du_d1 = size_transfer_1d; + assign fifo_input_o.size_du_d2 = size_transfer_2d; + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc_reg_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc_reg_pkg.sv new file mode 100644 index 00000000..2db852b7 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc_reg_pkg.sv @@ -0,0 +1,227 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Package auto-generated by `reggen` containing data structure + +package im2col_spc_reg_pkg; + + // Address widths within the block + parameter int BlockAw = 7; + + //////////////////////////// + // Typedefs for registers // + //////////////////////////// + + typedef struct packed {logic [31:0] q;} im2col_spc_reg2hw_src_ptr_reg_t; + + typedef struct packed {logic [31:0] q;} im2col_spc_reg2hw_dst_ptr_reg_t; + + typedef struct packed {logic [15:0] q;} im2col_spc_reg2hw_iw_reg_t; + + typedef struct packed {logic [15:0] q;} im2col_spc_reg2hw_ih_reg_t; + + typedef struct packed {logic [7:0] q;} im2col_spc_reg2hw_fw_reg_t; + + typedef struct packed {logic [7:0] q;} im2col_spc_reg2hw_fh_reg_t; + + typedef struct packed {logic [7:0] q;} im2col_spc_reg2hw_batch_reg_t; + + typedef struct packed { + logic [7:0] q; + logic qe; + } im2col_spc_reg2hw_num_ch_reg_t; + + typedef struct packed {logic [15:0] q;} im2col_spc_reg2hw_ch_col_reg_t; + + typedef struct packed {logic [15:0] q;} im2col_spc_reg2hw_n_patches_w_reg_t; + + typedef struct packed {logic [15:0] q;} im2col_spc_reg2hw_n_patches_h_reg_t; + + typedef struct packed {logic [7:0] q;} im2col_spc_reg2hw_adpt_pad_right_reg_t; + + typedef struct packed {logic [7:0] q;} im2col_spc_reg2hw_adpt_pad_bottom_reg_t; + + typedef struct packed {logic [3:0] q;} im2col_spc_reg2hw_log_strides_d1_reg_t; + + typedef struct packed {logic [3:0] q;} im2col_spc_reg2hw_log_strides_d2_reg_t; + + typedef struct packed { + logic q; + logic re; + } im2col_spc_reg2hw_status_reg_t; + + typedef struct packed { + struct packed {logic [15:0] q;} rx_trigger_slot; + struct packed {logic [15:0] q;} tx_trigger_slot; + } im2col_spc_reg2hw_slot_reg_t; + + typedef struct packed {logic [1:0] q;} im2col_spc_reg2hw_data_type_reg_t; + + typedef struct packed { + logic [5:0] q; + logic qe; + } im2col_spc_reg2hw_pad_top_reg_t; + + typedef struct packed { + logic [5:0] q; + logic qe; + } im2col_spc_reg2hw_pad_bottom_reg_t; + + typedef struct packed { + logic [5:0] q; + logic qe; + } im2col_spc_reg2hw_pad_right_reg_t; + + typedef struct packed { + logic [5:0] q; + logic qe; + } im2col_spc_reg2hw_pad_left_reg_t; + + typedef struct packed {logic q;} im2col_spc_reg2hw_interrupt_en_reg_t; + + typedef struct packed { + logic q; + logic re; + } im2col_spc_reg2hw_spc_ifr_reg_t; + + typedef struct packed {logic [31:0] q;} im2col_spc_reg2hw_spc_ch_mask_reg_t; + + typedef struct packed {logic [31:0] q;} im2col_spc_reg2hw_spc_ch_offset_reg_t; + + typedef struct packed {logic d;} im2col_spc_hw2reg_status_reg_t; + + typedef struct packed {logic d;} im2col_spc_hw2reg_spc_ifr_reg_t; + + // Register -> HW type + typedef struct packed { + im2col_spc_reg2hw_src_ptr_reg_t src_ptr; // [331:300] + im2col_spc_reg2hw_dst_ptr_reg_t dst_ptr; // [299:268] + im2col_spc_reg2hw_iw_reg_t iw; // [267:252] + im2col_spc_reg2hw_ih_reg_t ih; // [251:236] + im2col_spc_reg2hw_fw_reg_t fw; // [235:228] + im2col_spc_reg2hw_fh_reg_t fh; // [227:220] + im2col_spc_reg2hw_batch_reg_t batch; // [219:212] + im2col_spc_reg2hw_num_ch_reg_t num_ch; // [211:203] + im2col_spc_reg2hw_ch_col_reg_t ch_col; // [202:187] + im2col_spc_reg2hw_n_patches_w_reg_t n_patches_w; // [186:171] + im2col_spc_reg2hw_n_patches_h_reg_t n_patches_h; // [170:155] + im2col_spc_reg2hw_adpt_pad_right_reg_t adpt_pad_right; // [154:147] + im2col_spc_reg2hw_adpt_pad_bottom_reg_t adpt_pad_bottom; // [146:139] + im2col_spc_reg2hw_log_strides_d1_reg_t log_strides_d1; // [138:135] + im2col_spc_reg2hw_log_strides_d2_reg_t log_strides_d2; // [134:131] + im2col_spc_reg2hw_status_reg_t status; // [130:129] + im2col_spc_reg2hw_slot_reg_t slot; // [128:97] + im2col_spc_reg2hw_data_type_reg_t data_type; // [96:95] + im2col_spc_reg2hw_pad_top_reg_t pad_top; // [94:88] + im2col_spc_reg2hw_pad_bottom_reg_t pad_bottom; // [87:81] + im2col_spc_reg2hw_pad_right_reg_t pad_right; // [80:74] + im2col_spc_reg2hw_pad_left_reg_t pad_left; // [73:67] + im2col_spc_reg2hw_interrupt_en_reg_t interrupt_en; // [66:66] + im2col_spc_reg2hw_spc_ifr_reg_t spc_ifr; // [65:64] + im2col_spc_reg2hw_spc_ch_mask_reg_t spc_ch_mask; // [63:32] + im2col_spc_reg2hw_spc_ch_offset_reg_t spc_ch_offset; // [31:0] + } im2col_spc_reg2hw_t; + + // HW -> register type + typedef struct packed { + im2col_spc_hw2reg_status_reg_t status; // [1:1] + im2col_spc_hw2reg_spc_ifr_reg_t spc_ifr; // [0:0] + } im2col_spc_hw2reg_t; + + // Register offsets + parameter logic [BlockAw-1:0] IM2COL_SPC_SRC_PTR_OFFSET = 7'h0; + parameter logic [BlockAw-1:0] IM2COL_SPC_DST_PTR_OFFSET = 7'h4; + parameter logic [BlockAw-1:0] IM2COL_SPC_IW_OFFSET = 7'h8; + parameter logic [BlockAw-1:0] IM2COL_SPC_IH_OFFSET = 7'hc; + parameter logic [BlockAw-1:0] IM2COL_SPC_FW_OFFSET = 7'h10; + parameter logic [BlockAw-1:0] IM2COL_SPC_FH_OFFSET = 7'h14; + parameter logic [BlockAw-1:0] IM2COL_SPC_BATCH_OFFSET = 7'h18; + parameter logic [BlockAw-1:0] IM2COL_SPC_NUM_CH_OFFSET = 7'h1c; + parameter logic [BlockAw-1:0] IM2COL_SPC_CH_COL_OFFSET = 7'h20; + parameter logic [BlockAw-1:0] IM2COL_SPC_N_PATCHES_W_OFFSET = 7'h24; + parameter logic [BlockAw-1:0] IM2COL_SPC_N_PATCHES_H_OFFSET = 7'h28; + parameter logic [BlockAw-1:0] IM2COL_SPC_ADPT_PAD_RIGHT_OFFSET = 7'h2c; + parameter logic [BlockAw-1:0] IM2COL_SPC_ADPT_PAD_BOTTOM_OFFSET = 7'h30; + parameter logic [BlockAw-1:0] IM2COL_SPC_LOG_STRIDES_D1_OFFSET = 7'h34; + parameter logic [BlockAw-1:0] IM2COL_SPC_LOG_STRIDES_D2_OFFSET = 7'h38; + parameter logic [BlockAw-1:0] IM2COL_SPC_STATUS_OFFSET = 7'h3c; + parameter logic [BlockAw-1:0] IM2COL_SPC_SLOT_OFFSET = 7'h40; + parameter logic [BlockAw-1:0] IM2COL_SPC_DATA_TYPE_OFFSET = 7'h44; + parameter logic [BlockAw-1:0] IM2COL_SPC_PAD_TOP_OFFSET = 7'h48; + parameter logic [BlockAw-1:0] IM2COL_SPC_PAD_BOTTOM_OFFSET = 7'h4c; + parameter logic [BlockAw-1:0] IM2COL_SPC_PAD_RIGHT_OFFSET = 7'h50; + parameter logic [BlockAw-1:0] IM2COL_SPC_PAD_LEFT_OFFSET = 7'h54; + parameter logic [BlockAw-1:0] IM2COL_SPC_INTERRUPT_EN_OFFSET = 7'h58; + parameter logic [BlockAw-1:0] IM2COL_SPC_SPC_IFR_OFFSET = 7'h5c; + parameter logic [BlockAw-1:0] IM2COL_SPC_SPC_CH_MASK_OFFSET = 7'h60; + parameter logic [BlockAw-1:0] IM2COL_SPC_SPC_CH_OFFSET_OFFSET = 7'h64; + + // Reset values for hwext registers and their fields + parameter logic [0:0] IM2COL_SPC_STATUS_RESVAL = 1'h1; + parameter logic [0:0] IM2COL_SPC_STATUS_READY_RESVAL = 1'h1; + parameter logic [0:0] IM2COL_SPC_SPC_IFR_RESVAL = 1'h0; + parameter logic [0:0] IM2COL_SPC_SPC_IFR_FLAG_RESVAL = 1'h0; + + // Register index + typedef enum int { + IM2COL_SPC_SRC_PTR, + IM2COL_SPC_DST_PTR, + IM2COL_SPC_IW, + IM2COL_SPC_IH, + IM2COL_SPC_FW, + IM2COL_SPC_FH, + IM2COL_SPC_BATCH, + IM2COL_SPC_NUM_CH, + IM2COL_SPC_CH_COL, + IM2COL_SPC_N_PATCHES_W, + IM2COL_SPC_N_PATCHES_H, + IM2COL_SPC_ADPT_PAD_RIGHT, + IM2COL_SPC_ADPT_PAD_BOTTOM, + IM2COL_SPC_LOG_STRIDES_D1, + IM2COL_SPC_LOG_STRIDES_D2, + IM2COL_SPC_STATUS, + IM2COL_SPC_SLOT, + IM2COL_SPC_DATA_TYPE, + IM2COL_SPC_PAD_TOP, + IM2COL_SPC_PAD_BOTTOM, + IM2COL_SPC_PAD_RIGHT, + IM2COL_SPC_PAD_LEFT, + IM2COL_SPC_INTERRUPT_EN, + IM2COL_SPC_SPC_IFR, + IM2COL_SPC_SPC_CH_MASK, + IM2COL_SPC_SPC_CH_OFFSET + } im2col_spc_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] IM2COL_SPC_PERMIT[26] = '{ + 4'b1111, // index[ 0] IM2COL_SPC_SRC_PTR + 4'b1111, // index[ 1] IM2COL_SPC_DST_PTR + 4'b0011, // index[ 2] IM2COL_SPC_IW + 4'b0011, // index[ 3] IM2COL_SPC_IH + 4'b0001, // index[ 4] IM2COL_SPC_FW + 4'b0001, // index[ 5] IM2COL_SPC_FH + 4'b0001, // index[ 6] IM2COL_SPC_BATCH + 4'b0001, // index[ 7] IM2COL_SPC_NUM_CH + 4'b0011, // index[ 8] IM2COL_SPC_CH_COL + 4'b0011, // index[ 9] IM2COL_SPC_N_PATCHES_W + 4'b0011, // index[10] IM2COL_SPC_N_PATCHES_H + 4'b0001, // index[11] IM2COL_SPC_ADPT_PAD_RIGHT + 4'b0001, // index[12] IM2COL_SPC_ADPT_PAD_BOTTOM + 4'b0001, // index[13] IM2COL_SPC_LOG_STRIDES_D1 + 4'b0001, // index[14] IM2COL_SPC_LOG_STRIDES_D2 + 4'b0001, // index[15] IM2COL_SPC_STATUS + 4'b1111, // index[16] IM2COL_SPC_SLOT + 4'b0001, // index[17] IM2COL_SPC_DATA_TYPE + 4'b0001, // index[18] IM2COL_SPC_PAD_TOP + 4'b0001, // index[19] IM2COL_SPC_PAD_BOTTOM + 4'b0001, // index[20] IM2COL_SPC_PAD_RIGHT + 4'b0001, // index[21] IM2COL_SPC_PAD_LEFT + 4'b0001, // index[22] IM2COL_SPC_INTERRUPT_EN + 4'b0001, // index[23] IM2COL_SPC_SPC_IFR + 4'b1111, // index[24] IM2COL_SPC_SPC_CH_MASK + 4'b1111 // index[25] IM2COL_SPC_SPC_CH_OFFSET + }; + +endpackage + diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc_reg_top.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc_reg_top.sv new file mode 100644 index 00000000..a364f98c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc_reg_top.sv @@ -0,0 +1,1182 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Top module auto-generated by `reggen` + + +`include "common_cells/assertions.svh" + +module im2col_spc_reg_top #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter int AW = 7 +) ( + input logic clk_i, + input logic rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + // To HW + output im2col_spc_reg_pkg::im2col_spc_reg2hw_t reg2hw, // Write + input im2col_spc_reg_pkg::im2col_spc_hw2reg_t hw2reg, // Read + + + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + + import im2col_spc_reg_pkg::*; + + localparam int DW = 32; + localparam int DBW = DW / 8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [ AW-1:0] reg_addr; + logic [ DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [ DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + + // Below register interface can be changed + reg_req_t reg_intf_req; + reg_rsp_t reg_intf_rsp; + + + assign reg_intf_req = reg_req_i; + assign reg_rsp_o = reg_intf_rsp; + + + assign reg_we = reg_intf_req.valid & reg_intf_req.write; + assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; + assign reg_addr = reg_intf_req.addr; + assign reg_wdata = reg_intf_req.wdata; + assign reg_be = reg_intf_req.wstrb; + assign reg_intf_rsp.rdata = reg_rdata; + assign reg_intf_rsp.error = reg_error; + assign reg_intf_rsp.ready = 1'b1; + + assign reg_rdata = reg_rdata_next; + assign reg_error = (devmode_i & addrmiss) | wr_err; + + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic [31:0] src_ptr_qs; + logic [31:0] src_ptr_wd; + logic src_ptr_we; + logic [31:0] dst_ptr_qs; + logic [31:0] dst_ptr_wd; + logic dst_ptr_we; + logic [15:0] iw_qs; + logic [15:0] iw_wd; + logic iw_we; + logic [15:0] ih_qs; + logic [15:0] ih_wd; + logic ih_we; + logic [7:0] fw_qs; + logic [7:0] fw_wd; + logic fw_we; + logic [7:0] fh_qs; + logic [7:0] fh_wd; + logic fh_we; + logic [7:0] batch_qs; + logic [7:0] batch_wd; + logic batch_we; + logic [7:0] num_ch_qs; + logic [7:0] num_ch_wd; + logic num_ch_we; + logic [15:0] ch_col_qs; + logic [15:0] ch_col_wd; + logic ch_col_we; + logic [15:0] n_patches_w_qs; + logic [15:0] n_patches_w_wd; + logic n_patches_w_we; + logic [15:0] n_patches_h_qs; + logic [15:0] n_patches_h_wd; + logic n_patches_h_we; + logic [7:0] adpt_pad_right_qs; + logic [7:0] adpt_pad_right_wd; + logic adpt_pad_right_we; + logic [7:0] adpt_pad_bottom_qs; + logic [7:0] adpt_pad_bottom_wd; + logic adpt_pad_bottom_we; + logic [3:0] log_strides_d1_qs; + logic [3:0] log_strides_d1_wd; + logic log_strides_d1_we; + logic [3:0] log_strides_d2_qs; + logic [3:0] log_strides_d2_wd; + logic log_strides_d2_we; + logic status_qs; + logic status_re; + logic [15:0] slot_rx_trigger_slot_qs; + logic [15:0] slot_rx_trigger_slot_wd; + logic slot_rx_trigger_slot_we; + logic [15:0] slot_tx_trigger_slot_qs; + logic [15:0] slot_tx_trigger_slot_wd; + logic slot_tx_trigger_slot_we; + logic [1:0] data_type_qs; + logic [1:0] data_type_wd; + logic data_type_we; + logic [5:0] pad_top_qs; + logic [5:0] pad_top_wd; + logic pad_top_we; + logic [5:0] pad_bottom_qs; + logic [5:0] pad_bottom_wd; + logic pad_bottom_we; + logic [5:0] pad_right_qs; + logic [5:0] pad_right_wd; + logic pad_right_we; + logic [5:0] pad_left_qs; + logic [5:0] pad_left_wd; + logic pad_left_we; + logic interrupt_en_qs; + logic interrupt_en_wd; + logic interrupt_en_we; + logic spc_ifr_qs; + logic spc_ifr_re; + logic [31:0] spc_ch_mask_qs; + logic [31:0] spc_ch_mask_wd; + logic spc_ch_mask_we; + logic [31:0] spc_ch_offset_qs; + logic [31:0] spc_ch_offset_wd; + logic spc_ch_offset_we; + + // Register instances + // R[src_ptr]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_src_ptr ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(src_ptr_we), + .wd(src_ptr_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.src_ptr.q), + + // to register interface (read) + .qs(src_ptr_qs) + ); + + + // R[dst_ptr]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_dst_ptr ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(dst_ptr_we), + .wd(dst_ptr_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.dst_ptr.q), + + // to register interface (read) + .qs(dst_ptr_qs) + ); + + + // R[iw]: V(False) + + prim_subreg #( + .DW (16), + .SWACCESS("RW"), + .RESVAL (16'h0) + ) u_iw ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(iw_we), + .wd(iw_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.iw.q), + + // to register interface (read) + .qs(iw_qs) + ); + + + // R[ih]: V(False) + + prim_subreg #( + .DW (16), + .SWACCESS("RW"), + .RESVAL (16'h0) + ) u_ih ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(ih_we), + .wd(ih_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.ih.q), + + // to register interface (read) + .qs(ih_qs) + ); + + + // R[fw]: V(False) + + prim_subreg #( + .DW (8), + .SWACCESS("RW"), + .RESVAL (8'h0) + ) u_fw ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(fw_we), + .wd(fw_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.fw.q), + + // to register interface (read) + .qs(fw_qs) + ); + + + // R[fh]: V(False) + + prim_subreg #( + .DW (8), + .SWACCESS("RW"), + .RESVAL (8'h0) + ) u_fh ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(fh_we), + .wd(fh_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.fh.q), + + // to register interface (read) + .qs(fh_qs) + ); + + + // R[batch]: V(False) + + prim_subreg #( + .DW (8), + .SWACCESS("RW"), + .RESVAL (8'h0) + ) u_batch ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(batch_we), + .wd(batch_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.batch.q), + + // to register interface (read) + .qs(batch_qs) + ); + + + // R[num_ch]: V(False) + + prim_subreg #( + .DW (8), + .SWACCESS("RW"), + .RESVAL (8'h0) + ) u_num_ch ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(num_ch_we), + .wd(num_ch_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(reg2hw.num_ch.qe), + .q (reg2hw.num_ch.q), + + // to register interface (read) + .qs(num_ch_qs) + ); + + + // R[ch_col]: V(False) + + prim_subreg #( + .DW (16), + .SWACCESS("RW"), + .RESVAL (16'h0) + ) u_ch_col ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(ch_col_we), + .wd(ch_col_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.ch_col.q), + + // to register interface (read) + .qs(ch_col_qs) + ); + + + // R[n_patches_w]: V(False) + + prim_subreg #( + .DW (16), + .SWACCESS("RW"), + .RESVAL (16'h0) + ) u_n_patches_w ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(n_patches_w_we), + .wd(n_patches_w_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.n_patches_w.q), + + // to register interface (read) + .qs(n_patches_w_qs) + ); + + + // R[n_patches_h]: V(False) + + prim_subreg #( + .DW (16), + .SWACCESS("RW"), + .RESVAL (16'h0) + ) u_n_patches_h ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(n_patches_h_we), + .wd(n_patches_h_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.n_patches_h.q), + + // to register interface (read) + .qs(n_patches_h_qs) + ); + + + // R[adpt_pad_right]: V(False) + + prim_subreg #( + .DW (8), + .SWACCESS("RW"), + .RESVAL (8'h0) + ) u_adpt_pad_right ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(adpt_pad_right_we), + .wd(adpt_pad_right_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.adpt_pad_right.q), + + // to register interface (read) + .qs(adpt_pad_right_qs) + ); + + + // R[adpt_pad_bottom]: V(False) + + prim_subreg #( + .DW (8), + .SWACCESS("RW"), + .RESVAL (8'h0) + ) u_adpt_pad_bottom ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(adpt_pad_bottom_we), + .wd(adpt_pad_bottom_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.adpt_pad_bottom.q), + + // to register interface (read) + .qs(adpt_pad_bottom_qs) + ); + + + // R[log_strides_d1]: V(False) + + prim_subreg #( + .DW (4), + .SWACCESS("RW"), + .RESVAL (4'h0) + ) u_log_strides_d1 ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(log_strides_d1_we), + .wd(log_strides_d1_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.log_strides_d1.q), + + // to register interface (read) + .qs(log_strides_d1_qs) + ); + + + // R[log_strides_d2]: V(False) + + prim_subreg #( + .DW (4), + .SWACCESS("RW"), + .RESVAL (4'h0) + ) u_log_strides_d2 ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(log_strides_d2_we), + .wd(log_strides_d2_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.log_strides_d2.q), + + // to register interface (read) + .qs(log_strides_d2_qs) + ); + + + // R[status]: V(True) + + prim_subreg_ext #( + .DW(1) + ) u_status ( + .re (status_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status.d), + .qre(reg2hw.status.re), + .qe (), + .q (reg2hw.status.q), + .qs (status_qs) + ); + + + // R[slot]: V(False) + + // F[rx_trigger_slot]: 15:0 + prim_subreg #( + .DW (16), + .SWACCESS("RW"), + .RESVAL (16'h0) + ) u_slot_rx_trigger_slot ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(slot_rx_trigger_slot_we), + .wd(slot_rx_trigger_slot_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.slot.rx_trigger_slot.q), + + // to register interface (read) + .qs(slot_rx_trigger_slot_qs) + ); + + + // F[tx_trigger_slot]: 31:16 + prim_subreg #( + .DW (16), + .SWACCESS("RW"), + .RESVAL (16'h0) + ) u_slot_tx_trigger_slot ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(slot_tx_trigger_slot_we), + .wd(slot_tx_trigger_slot_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.slot.tx_trigger_slot.q), + + // to register interface (read) + .qs(slot_tx_trigger_slot_qs) + ); + + + // R[data_type]: V(False) + + prim_subreg #( + .DW (2), + .SWACCESS("RW"), + .RESVAL (2'h0) + ) u_data_type ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(data_type_we), + .wd(data_type_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.data_type.q), + + // to register interface (read) + .qs(data_type_qs) + ); + + + // R[pad_top]: V(False) + + prim_subreg #( + .DW (6), + .SWACCESS("RW"), + .RESVAL (6'h0) + ) u_pad_top ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(pad_top_we), + .wd(pad_top_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(reg2hw.pad_top.qe), + .q (reg2hw.pad_top.q), + + // to register interface (read) + .qs(pad_top_qs) + ); + + + // R[pad_bottom]: V(False) + + prim_subreg #( + .DW (6), + .SWACCESS("RW"), + .RESVAL (6'h0) + ) u_pad_bottom ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(pad_bottom_we), + .wd(pad_bottom_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(reg2hw.pad_bottom.qe), + .q (reg2hw.pad_bottom.q), + + // to register interface (read) + .qs(pad_bottom_qs) + ); + + + // R[pad_right]: V(False) + + prim_subreg #( + .DW (6), + .SWACCESS("RW"), + .RESVAL (6'h0) + ) u_pad_right ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(pad_right_we), + .wd(pad_right_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(reg2hw.pad_right.qe), + .q (reg2hw.pad_right.q), + + // to register interface (read) + .qs(pad_right_qs) + ); + + + // R[pad_left]: V(False) + + prim_subreg #( + .DW (6), + .SWACCESS("RW"), + .RESVAL (6'h0) + ) u_pad_left ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(pad_left_we), + .wd(pad_left_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(reg2hw.pad_left.qe), + .q (reg2hw.pad_left.q), + + // to register interface (read) + .qs(pad_left_qs) + ); + + + // R[interrupt_en]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_interrupt_en ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(interrupt_en_we), + .wd(interrupt_en_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.interrupt_en.q), + + // to register interface (read) + .qs(interrupt_en_qs) + ); + + + // R[spc_ifr]: V(True) + + prim_subreg_ext #( + .DW(1) + ) u_spc_ifr ( + .re (spc_ifr_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.spc_ifr.d), + .qre(reg2hw.spc_ifr.re), + .qe (), + .q (reg2hw.spc_ifr.q), + .qs (spc_ifr_qs) + ); + + + // R[spc_ch_mask]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h1) + ) u_spc_ch_mask ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(spc_ch_mask_we), + .wd(spc_ch_mask_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.spc_ch_mask.q), + + // to register interface (read) + .qs(spc_ch_mask_qs) + ); + + + // R[spc_ch_offset]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h1) + ) u_spc_ch_offset ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(spc_ch_offset_we), + .wd(spc_ch_offset_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.spc_ch_offset.q), + + // to register interface (read) + .qs(spc_ch_offset_qs) + ); + + + + + logic [25:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[0] = (reg_addr == IM2COL_SPC_SRC_PTR_OFFSET); + addr_hit[1] = (reg_addr == IM2COL_SPC_DST_PTR_OFFSET); + addr_hit[2] = (reg_addr == IM2COL_SPC_IW_OFFSET); + addr_hit[3] = (reg_addr == IM2COL_SPC_IH_OFFSET); + addr_hit[4] = (reg_addr == IM2COL_SPC_FW_OFFSET); + addr_hit[5] = (reg_addr == IM2COL_SPC_FH_OFFSET); + addr_hit[6] = (reg_addr == IM2COL_SPC_BATCH_OFFSET); + addr_hit[7] = (reg_addr == IM2COL_SPC_NUM_CH_OFFSET); + addr_hit[8] = (reg_addr == IM2COL_SPC_CH_COL_OFFSET); + addr_hit[9] = (reg_addr == IM2COL_SPC_N_PATCHES_W_OFFSET); + addr_hit[10] = (reg_addr == IM2COL_SPC_N_PATCHES_H_OFFSET); + addr_hit[11] = (reg_addr == IM2COL_SPC_ADPT_PAD_RIGHT_OFFSET); + addr_hit[12] = (reg_addr == IM2COL_SPC_ADPT_PAD_BOTTOM_OFFSET); + addr_hit[13] = (reg_addr == IM2COL_SPC_LOG_STRIDES_D1_OFFSET); + addr_hit[14] = (reg_addr == IM2COL_SPC_LOG_STRIDES_D2_OFFSET); + addr_hit[15] = (reg_addr == IM2COL_SPC_STATUS_OFFSET); + addr_hit[16] = (reg_addr == IM2COL_SPC_SLOT_OFFSET); + addr_hit[17] = (reg_addr == IM2COL_SPC_DATA_TYPE_OFFSET); + addr_hit[18] = (reg_addr == IM2COL_SPC_PAD_TOP_OFFSET); + addr_hit[19] = (reg_addr == IM2COL_SPC_PAD_BOTTOM_OFFSET); + addr_hit[20] = (reg_addr == IM2COL_SPC_PAD_RIGHT_OFFSET); + addr_hit[21] = (reg_addr == IM2COL_SPC_PAD_LEFT_OFFSET); + addr_hit[22] = (reg_addr == IM2COL_SPC_INTERRUPT_EN_OFFSET); + addr_hit[23] = (reg_addr == IM2COL_SPC_SPC_IFR_OFFSET); + addr_hit[24] = (reg_addr == IM2COL_SPC_SPC_CH_MASK_OFFSET); + addr_hit[25] = (reg_addr == IM2COL_SPC_SPC_CH_OFFSET_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[ 0] & (|(IM2COL_SPC_PERMIT[ 0] & ~reg_be))) | + (addr_hit[ 1] & (|(IM2COL_SPC_PERMIT[ 1] & ~reg_be))) | + (addr_hit[ 2] & (|(IM2COL_SPC_PERMIT[ 2] & ~reg_be))) | + (addr_hit[ 3] & (|(IM2COL_SPC_PERMIT[ 3] & ~reg_be))) | + (addr_hit[ 4] & (|(IM2COL_SPC_PERMIT[ 4] & ~reg_be))) | + (addr_hit[ 5] & (|(IM2COL_SPC_PERMIT[ 5] & ~reg_be))) | + (addr_hit[ 6] & (|(IM2COL_SPC_PERMIT[ 6] & ~reg_be))) | + (addr_hit[ 7] & (|(IM2COL_SPC_PERMIT[ 7] & ~reg_be))) | + (addr_hit[ 8] & (|(IM2COL_SPC_PERMIT[ 8] & ~reg_be))) | + (addr_hit[ 9] & (|(IM2COL_SPC_PERMIT[ 9] & ~reg_be))) | + (addr_hit[10] & (|(IM2COL_SPC_PERMIT[10] & ~reg_be))) | + (addr_hit[11] & (|(IM2COL_SPC_PERMIT[11] & ~reg_be))) | + (addr_hit[12] & (|(IM2COL_SPC_PERMIT[12] & ~reg_be))) | + (addr_hit[13] & (|(IM2COL_SPC_PERMIT[13] & ~reg_be))) | + (addr_hit[14] & (|(IM2COL_SPC_PERMIT[14] & ~reg_be))) | + (addr_hit[15] & (|(IM2COL_SPC_PERMIT[15] & ~reg_be))) | + (addr_hit[16] & (|(IM2COL_SPC_PERMIT[16] & ~reg_be))) | + (addr_hit[17] & (|(IM2COL_SPC_PERMIT[17] & ~reg_be))) | + (addr_hit[18] & (|(IM2COL_SPC_PERMIT[18] & ~reg_be))) | + (addr_hit[19] & (|(IM2COL_SPC_PERMIT[19] & ~reg_be))) | + (addr_hit[20] & (|(IM2COL_SPC_PERMIT[20] & ~reg_be))) | + (addr_hit[21] & (|(IM2COL_SPC_PERMIT[21] & ~reg_be))) | + (addr_hit[22] & (|(IM2COL_SPC_PERMIT[22] & ~reg_be))) | + (addr_hit[23] & (|(IM2COL_SPC_PERMIT[23] & ~reg_be))) | + (addr_hit[24] & (|(IM2COL_SPC_PERMIT[24] & ~reg_be))) | + (addr_hit[25] & (|(IM2COL_SPC_PERMIT[25] & ~reg_be))))); + end + + assign src_ptr_we = addr_hit[0] & reg_we & !reg_error; + assign src_ptr_wd = reg_wdata[31:0]; + + assign dst_ptr_we = addr_hit[1] & reg_we & !reg_error; + assign dst_ptr_wd = reg_wdata[31:0]; + + assign iw_we = addr_hit[2] & reg_we & !reg_error; + assign iw_wd = reg_wdata[15:0]; + + assign ih_we = addr_hit[3] & reg_we & !reg_error; + assign ih_wd = reg_wdata[15:0]; + + assign fw_we = addr_hit[4] & reg_we & !reg_error; + assign fw_wd = reg_wdata[7:0]; + + assign fh_we = addr_hit[5] & reg_we & !reg_error; + assign fh_wd = reg_wdata[7:0]; + + assign batch_we = addr_hit[6] & reg_we & !reg_error; + assign batch_wd = reg_wdata[7:0]; + + assign num_ch_we = addr_hit[7] & reg_we & !reg_error; + assign num_ch_wd = reg_wdata[7:0]; + + assign ch_col_we = addr_hit[8] & reg_we & !reg_error; + assign ch_col_wd = reg_wdata[15:0]; + + assign n_patches_w_we = addr_hit[9] & reg_we & !reg_error; + assign n_patches_w_wd = reg_wdata[15:0]; + + assign n_patches_h_we = addr_hit[10] & reg_we & !reg_error; + assign n_patches_h_wd = reg_wdata[15:0]; + + assign adpt_pad_right_we = addr_hit[11] & reg_we & !reg_error; + assign adpt_pad_right_wd = reg_wdata[7:0]; + + assign adpt_pad_bottom_we = addr_hit[12] & reg_we & !reg_error; + assign adpt_pad_bottom_wd = reg_wdata[7:0]; + + assign log_strides_d1_we = addr_hit[13] & reg_we & !reg_error; + assign log_strides_d1_wd = reg_wdata[3:0]; + + assign log_strides_d2_we = addr_hit[14] & reg_we & !reg_error; + assign log_strides_d2_wd = reg_wdata[3:0]; + + assign status_re = addr_hit[15] & reg_re & !reg_error; + + assign slot_rx_trigger_slot_we = addr_hit[16] & reg_we & !reg_error; + assign slot_rx_trigger_slot_wd = reg_wdata[15:0]; + + assign slot_tx_trigger_slot_we = addr_hit[16] & reg_we & !reg_error; + assign slot_tx_trigger_slot_wd = reg_wdata[31:16]; + + assign data_type_we = addr_hit[17] & reg_we & !reg_error; + assign data_type_wd = reg_wdata[1:0]; + + assign pad_top_we = addr_hit[18] & reg_we & !reg_error; + assign pad_top_wd = reg_wdata[5:0]; + + assign pad_bottom_we = addr_hit[19] & reg_we & !reg_error; + assign pad_bottom_wd = reg_wdata[5:0]; + + assign pad_right_we = addr_hit[20] & reg_we & !reg_error; + assign pad_right_wd = reg_wdata[5:0]; + + assign pad_left_we = addr_hit[21] & reg_we & !reg_error; + assign pad_left_wd = reg_wdata[5:0]; + + assign interrupt_en_we = addr_hit[22] & reg_we & !reg_error; + assign interrupt_en_wd = reg_wdata[0]; + + assign spc_ifr_re = addr_hit[23] & reg_re & !reg_error; + + assign spc_ch_mask_we = addr_hit[24] & reg_we & !reg_error; + assign spc_ch_mask_wd = reg_wdata[31:0]; + + assign spc_ch_offset_we = addr_hit[25] & reg_we & !reg_error; + assign spc_ch_offset_wd = reg_wdata[31:0]; + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[31:0] = src_ptr_qs; + end + + addr_hit[1]: begin + reg_rdata_next[31:0] = dst_ptr_qs; + end + + addr_hit[2]: begin + reg_rdata_next[15:0] = iw_qs; + end + + addr_hit[3]: begin + reg_rdata_next[15:0] = ih_qs; + end + + addr_hit[4]: begin + reg_rdata_next[7:0] = fw_qs; + end + + addr_hit[5]: begin + reg_rdata_next[7:0] = fh_qs; + end + + addr_hit[6]: begin + reg_rdata_next[7:0] = batch_qs; + end + + addr_hit[7]: begin + reg_rdata_next[7:0] = num_ch_qs; + end + + addr_hit[8]: begin + reg_rdata_next[15:0] = ch_col_qs; + end + + addr_hit[9]: begin + reg_rdata_next[15:0] = n_patches_w_qs; + end + + addr_hit[10]: begin + reg_rdata_next[15:0] = n_patches_h_qs; + end + + addr_hit[11]: begin + reg_rdata_next[7:0] = adpt_pad_right_qs; + end + + addr_hit[12]: begin + reg_rdata_next[7:0] = adpt_pad_bottom_qs; + end + + addr_hit[13]: begin + reg_rdata_next[3:0] = log_strides_d1_qs; + end + + addr_hit[14]: begin + reg_rdata_next[3:0] = log_strides_d2_qs; + end + + addr_hit[15]: begin + reg_rdata_next[0] = status_qs; + end + + addr_hit[16]: begin + reg_rdata_next[15:0] = slot_rx_trigger_slot_qs; + reg_rdata_next[31:16] = slot_tx_trigger_slot_qs; + end + + addr_hit[17]: begin + reg_rdata_next[1:0] = data_type_qs; + end + + addr_hit[18]: begin + reg_rdata_next[5:0] = pad_top_qs; + end + + addr_hit[19]: begin + reg_rdata_next[5:0] = pad_bottom_qs; + end + + addr_hit[20]: begin + reg_rdata_next[5:0] = pad_right_qs; + end + + addr_hit[21]: begin + reg_rdata_next[5:0] = pad_left_qs; + end + + addr_hit[22]: begin + reg_rdata_next[0] = interrupt_en_qs; + end + + addr_hit[23]: begin + reg_rdata_next[0] = spc_ifr_qs; + end + + addr_hit[24]: begin + reg_rdata_next[31:0] = spc_ch_mask_qs; + end + + addr_hit[25]: begin + reg_rdata_next[31:0] = spc_ch_offset_qs; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) + +endmodule + +module im2col_spc_reg_top_intf #( + parameter int AW = 7, + localparam int DW = 32 +) ( + input logic clk_i, + input logic rst_ni, + REG_BUS.in regbus_slave, + // To HW + output im2col_spc_reg_pkg::im2col_spc_reg2hw_t reg2hw, // Write + input im2col_spc_reg_pkg::im2col_spc_hw2reg_t hw2reg, // Read + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + localparam int unsigned STRB_WIDTH = DW / 8; + + `include "register_interface/typedef.svh" + `include "register_interface/assign.svh" + + // Define structs for reg_bus + typedef logic [AW-1:0] addr_t; + typedef logic [DW-1:0] data_t; + typedef logic [STRB_WIDTH-1:0] strb_t; + `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) + + reg_bus_req_t s_reg_req; + reg_bus_rsp_t s_reg_rsp; + + // Assign SV interface to structs + `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) + `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) + + + + im2col_spc_reg_top #( + .reg_req_t(reg_bus_req_t), + .reg_rsp_t(reg_bus_rsp_t), + .AW(AW) + ) i_regs ( + .clk_i, + .rst_ni, + .reg_req_i(s_reg_req), + .reg_rsp_o(s_reg_rsp), + .reg2hw, // Write + .hw2reg, // Read + .devmode_i + ); + +endmodule + + diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc_regintfc_controller.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc_regintfc_controller.sv new file mode 100644 index 00000000..6fa9092f --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/im2col_spc_regintfc_controller.sv @@ -0,0 +1,92 @@ +/* + * Copyright 2024 EPFL + * Solderpad Hardware License, Version 2.1, see LICENSE.md for details. + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Author: Tommaso Terzano + * + * + * Info: Register interface ontroller to comunicate with the AOPB. + */ + +module im2col_spc_regintfc_controller + import reg_pkg::*; +( + input logic clk_i, + input logic rst_ni, + input logic [31:0] addr_i, + input logic [31:0] wdata_i, + input logic start_i, + input reg_rsp_t aopb_resp_i, + output reg_req_t aopb_req_o, + output logic done_o +); + + /* General status signal */ + enum { + IDLE, + WAITING_READY, + SENDING, + DONE + } + im2col_status_q, im2col_status_d; + + always_comb begin + unique case (im2col_status_d) + IDLE: begin + if (start_i == 1'b1) begin + im2col_status_q = SENDING; + end else begin + im2col_status_q = IDLE; + end + end + + SENDING: begin + im2col_status_q = WAITING_READY; + end + + WAITING_READY: begin + if (aopb_resp_i.ready == 1'b1) begin + im2col_status_q = DONE; + end else begin + im2col_status_q = WAITING_READY; + end + end + + DONE: begin + im2col_status_q = IDLE; + end + endcase + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + im2col_status_d <= IDLE; + end else begin + im2col_status_d <= im2col_status_q; + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + aopb_req_o.valid <= 1'b0; + aopb_req_o.write <= 1'b0; + aopb_req_o.wstrb <= 4'b1111; + aopb_req_o.addr <= '0; + aopb_req_o.wdata <= '0; + end else begin + if (im2col_status_d == SENDING) begin + aopb_req_o.valid <= 1'b1; + aopb_req_o.write <= 1'b1; + aopb_req_o.wstrb <= 4'b1111; + aopb_req_o.addr <= addr_i; + aopb_req_o.wdata <= wdata_i; + end else if (im2col_status_q == DONE) begin + aopb_req_o.valid <= 1'b0; + end + end + end + + assign done_o = (im2col_status_d == DONE); + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/pipe_reg.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/pipe_reg.sv new file mode 100644 index 00000000..b819a941 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/im2col_spc/rtl/pipe_reg.sv @@ -0,0 +1,32 @@ +/* + * Copyright 2024 EPFL + * Solderpad Hardware License, Version 2.1, see LICENSE.md for details. + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Author: Tommaso Terzano + * + * + * Info: Generic pipe register + */ + +module pipe_reg #( + parameter WIDTH = 8 +) ( + input logic clk_i, + input logic rst_ni, + input logic [WIDTH-1:0] data_in, + output logic [WIDTH-1:0] data_out +); + + logic [WIDTH-1:0] reg_data; + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + reg_data <= '0; + end else begin + reg_data <= data_in; + end + end + + assign data_out = reg_data; +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.core b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.core new file mode 100644 index 00000000..2ef913ea --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.core @@ -0,0 +1,22 @@ +CAPI=2: + +name: "example:ip:simple_accelerator" +description: "core-v-mini-mcu iffifo peripheral" + +# Copyright 2024 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# +# Author: Davide Schiavone , EPFL, STI-SEL +# Date: 12.02.2024 + +filesets: + files_rtl: + files: + - simple_accelerator.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_rtl diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.sv new file mode 100644 index 00000000..846775af --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.sv @@ -0,0 +1,421 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +module simple_accelerator #( + parameter int unsigned FIFO_DEPTH = 4, + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter type obi_req_t = logic, + parameter type obi_resp_t = logic +) ( + input logic clk_i, + input logic rst_ni, + + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + + output obi_req_t acc_read_ch0_req_o, + input obi_resp_t acc_read_ch0_resp_i, + + output obi_req_t acc_write_ch0_req_o, + input obi_resp_t acc_write_ch0_resp_i + +); + + + + logic status_ready_d, status_ready_q, status_start_q; + logic [31:0] address_read_q, address_write_q; + logic [31:0] threshold_q; + logic [ 9:0] size_q; + + localparam int unsigned LastFifoUsage = FIFO_DEPTH - 1; + localparam int unsigned Addr_Fifo_Depth = (FIFO_DEPTH > 1) ? $clog2(FIFO_DEPTH) : 1; + + + logic [ 31:0] read_ptr_reg; + logic [ 31:0] read_ptr_valid_reg; + logic [ 31:0] write_ptr_reg; + logic [ 31:0] write_address; + logic [ 9:0] dma_cnt; + logic dma_start; + logic dma_done; + + + logic [Addr_Fifo_Depth-1:0] fifo_usage; + logic fifo_alm_full; + + logic data_in_req; + logic data_in_we; + logic [ 3:0] data_in_be; + logic [ 31:0] data_in_addr; + logic data_in_gnt; + logic data_in_rvalid; + logic [ 31:0] data_in_rdata; + + logic data_out_req; + logic data_out_we; + logic [ 3:0] data_out_be; + logic [ 31:0] data_out_addr; + logic [ 31:0] data_out_wdata; + logic data_out_gnt; + + logic fifo_flush; + logic fifo_full; + logic fifo_empty; + + + logic [ 31:0] fifo_input; + logic [ 31:0] fifo_output; + + logic [ 3:0] byte_enable_out; + + logic dma_start_pending; + + enum { + DMA_READY, + DMA_STARTING, + DMA_RUNNING + } + dma_state_q, dma_state_d; + + logic [Addr_Fifo_Depth-1:0] outstanding_req; + + enum logic { + DMA_READ_FSM_IDLE, + DMA_READ_FSM_ON + } + dma_read_fsm_state, dma_read_fsm_n_state; + + enum logic { + DMA_WRITE_FSM_IDLE, + DMA_WRITE_FSM_ON + } + dma_write_fsm_state, dma_write_fsm_n_state; + + assign acc_read_ch0_req_o.req = data_in_req; + assign acc_read_ch0_req_o.we = data_in_we; + assign acc_read_ch0_req_o.be = data_in_be; + assign acc_read_ch0_req_o.addr = data_in_addr; + assign acc_read_ch0_req_o.wdata = 32'h0; + + assign data_in_gnt = acc_read_ch0_resp_i.gnt; + assign data_in_rvalid = acc_read_ch0_resp_i.rvalid; + assign data_in_rdata = acc_read_ch0_resp_i.rdata; + + assign acc_write_ch0_req_o.req = data_out_req; + assign acc_write_ch0_req_o.we = data_out_we; + assign acc_write_ch0_req_o.be = data_out_be; + assign acc_write_ch0_req_o.addr = data_out_addr; + + //complete the function + assign acc_write_ch0_req_o.wdata = data_out_wdata > threshold_q ? data_out_wdata : threshold_q; + //assign acc_write_ch0_req_o.wdata = data_out_wdata; + + assign data_out_gnt = acc_write_ch0_resp_i.gnt; + + assign status_ready_d = (dma_state_q == DMA_READY); + + assign write_address = write_ptr_reg; + + assign fifo_alm_full = (fifo_usage == LastFifoUsage[Addr_Fifo_Depth-1:0]); + + assign dma_start = (dma_state_q == DMA_STARTING); + + //decoder + + //0 READ ADDRESS + //4 WRITE ADDRESS + //8 THRESHOLD + //C READY + //10 SIZE + //14 START + always_comb begin + reg_rsp_o.rdata = '0; + reg_rsp_o.error = 1'b0; + reg_rsp_o.ready = 1'b1; + + if (reg_req_i.valid) begin + if (reg_req_i.addr[7:0] == 8'h14) begin + reg_rsp_o.rdata = {31'h0, status_start_q}; + end + if (reg_req_i.addr[7:0] == 8'h10) begin + reg_rsp_o.rdata = {22'h0, size_q}; + end + if (reg_req_i.addr[7:0] == 8'hC) begin + reg_rsp_o.rdata = {31'h0, status_ready_q}; + end + if (reg_req_i.addr[7:0] == 8'h8) begin + reg_rsp_o.rdata = threshold_q; + end + if (reg_req_i.addr[7:0] == 8'h4) begin + reg_rsp_o.rdata = address_write_q; + end + if (reg_req_i.addr[7:0] == 8'h0) begin + reg_rsp_o.rdata = address_read_q; + end + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + status_start_q <= '0; + size_q <= '0; + status_ready_q <= '0; + threshold_q <= '0; + address_write_q <= '0; + address_read_q <= '0; + end else begin + if (reg_req_i.valid && reg_req_i.write) begin + if (reg_req_i.addr[7:0] == 8'h14) begin + status_start_q <= reg_req_i.wdata[0]; + end + if (reg_req_i.addr[7:0] == 8'h10) begin + size_q <= reg_req_i.wdata[9:0]; + end + if (reg_req_i.addr[7:0] == 8'hC) begin + status_ready_q <= reg_req_i.wdata[0]; + end + if (reg_req_i.addr[7:0] == 8'h8) begin + threshold_q <= reg_req_i.wdata; + end + if (reg_req_i.addr[7:0] == 8'h4) begin + address_write_q <= reg_req_i.wdata; + end + if (reg_req_i.addr[7:0] == 8'h0) begin + address_read_q <= reg_req_i.wdata; + end + end else begin + if (dma_done) status_ready_q <= 1'b1; + status_start_q <= '0; + end + end + end + + + // + // Main DMA state machine + // + // READY : idle, waiting for a write pulse to size registered in `dma_start_pending` + // STARTING: load transaction data + // RUNNING : waiting for transaction finish + // when `dma_done` rises either enter ready or restart in circular mode + // + always_comb begin + dma_state_d = dma_state_q; + case (dma_state_q) + DMA_READY: begin + if (dma_start_pending) begin + dma_state_d = DMA_STARTING; + end + end + DMA_STARTING: begin + dma_state_d = DMA_RUNNING; + end + DMA_RUNNING: begin + if (dma_done) begin + dma_state_d = DMA_READY; + end + end + endcase + end + + // update state + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + dma_state_q <= DMA_READY; + end else begin + dma_state_q <= dma_state_d; + end + end + + + // DMA pulse start when dma_start register is written + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_dma_start + if (~rst_ni) begin + dma_start_pending <= 1'b0; + end else begin + if (dma_start == 1'b1) begin + dma_start_pending <= 1'b0; + end else if (status_start_q && size_q != '0) begin + dma_start_pending <= 1'b1; + end + end + end + + // Store input data pointer and increment everytime read request is granted + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_in_reg + if (~rst_ni) begin + read_ptr_reg <= '0; + end else begin + if (dma_start == 1'b1) begin + read_ptr_reg <= address_read_q; + end else if (data_in_gnt == 1'b1) begin + read_ptr_reg <= read_ptr_reg + 32'h4; + end + end + end + + // Only update read_ptr_valid_reg when the data is stored in the fifo + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_valid_in_reg + if (~rst_ni) begin + read_ptr_valid_reg <= '0; + end else begin + if (dma_start == 1'b1) begin + read_ptr_valid_reg <= address_read_q; + end else if (data_in_rvalid == 1'b1) begin + read_ptr_valid_reg <= read_ptr_valid_reg + 32'h4; + end + end + end + + // Store output data pointer and increment everytime write request is granted + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_out_reg + if (~rst_ni) begin + write_ptr_reg <= '0; + end else begin + if (dma_start == 1'b1) begin + write_ptr_reg <= address_write_q; + end else if (data_out_gnt == 1'b1) begin + write_ptr_reg <= write_ptr_reg + 32'h4; + end + end + end + + // Store dma transfer size and decrement it everytime input data rvalid is asserted + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_dma_cnt_reg + if (~rst_ni) begin + dma_cnt <= '0; + end else begin + if (dma_start == 1'b1) begin + dma_cnt <= size_q; + end else if (data_in_gnt == 1'b1) begin + dma_cnt <= dma_cnt - 10'h1; + end + end + end + + assign byte_enable_out = 4'b1111; + + assign data_out_wdata = fifo_output; + + assign fifo_input = data_in_rdata; + + // FSM state update + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_fsm_state + if (~rst_ni) begin + dma_read_fsm_state <= DMA_READ_FSM_IDLE; + dma_write_fsm_state <= DMA_WRITE_FSM_IDLE; + outstanding_req <= '0; + end else begin + dma_read_fsm_state <= dma_read_fsm_n_state; + dma_write_fsm_state <= dma_write_fsm_n_state; + outstanding_req <= outstanding_req + (data_in_req && data_in_gnt) - data_in_rvalid; + end + end + + // Read master FSM + always_comb begin : proc_dma_read_fsm_logic + + dma_read_fsm_n_state = DMA_READ_FSM_IDLE; + + data_in_req = '0; + data_in_we = '0; + data_in_be = '0; + data_in_addr = '0; + + fifo_flush = 1'b0; + + unique case (dma_read_fsm_state) + + DMA_READ_FSM_IDLE: begin + // Wait for start signal + if (dma_start == 1'b1) begin + dma_read_fsm_n_state = DMA_READ_FSM_ON; + fifo_flush = 1'b1; + end else begin + dma_read_fsm_n_state = DMA_READ_FSM_IDLE; + end + end + // Read one word + DMA_READ_FSM_ON: begin + // If all input data read exit + if (|dma_cnt == 1'b0) begin + dma_read_fsm_n_state = DMA_READ_FSM_IDLE; + end else begin + dma_read_fsm_n_state = DMA_READ_FSM_ON; + // Wait if fifo is full, almost full (last data) + if (fifo_full == 1'b0 && fifo_alm_full == 1'b0) begin + data_in_req = 1'b1; + data_in_we = 1'b0; + data_in_be = 4'b1111; // always read all bytes + data_in_addr = read_ptr_reg; + end + end + end + endcase + end + + // Write master FSM + always_comb begin : proc_dma_write_fsm_logic + + dma_write_fsm_n_state = DMA_WRITE_FSM_IDLE; + dma_done = 1'b0; + + data_out_req = '0; + data_out_we = '0; + data_out_be = '0; + data_out_addr = '0; + + unique case (dma_write_fsm_state) + + DMA_WRITE_FSM_IDLE: begin + // Wait for start signal + if (dma_start == 1'b1) begin + dma_write_fsm_n_state = DMA_WRITE_FSM_ON; + end else begin + dma_write_fsm_n_state = DMA_WRITE_FSM_IDLE; + end + end + // Read one word + DMA_WRITE_FSM_ON: begin + // If all input data read exit + if (fifo_empty == 1'b1 && dma_read_fsm_state == DMA_READ_FSM_IDLE) begin + dma_done = outstanding_req == '0; + dma_write_fsm_n_state = dma_done ? DMA_WRITE_FSM_IDLE : DMA_WRITE_FSM_ON; + end else begin + dma_write_fsm_n_state = DMA_WRITE_FSM_ON; + // Wait if fifo is empty + if (fifo_empty == 1'b0) begin + data_out_req = 1'b1; + data_out_we = 1'b1; + data_out_be = byte_enable_out; + data_out_addr = write_address; + end + end + end + endcase + end + + fifo_v3 #( + .DEPTH(FIFO_DEPTH) + ) dma_fifo_i ( + .clk_i, + .rst_ni, + .flush_i(fifo_flush), + .testmode_i(1'b0), + // status flags + .full_o(fifo_full), + .empty_o(fifo_empty), + .usage_o(fifo_usage), + // as long as the queue is not full we can push new data + .data_i(fifo_input), + .push_i(data_in_rvalid), + // as long as the queue is not empty we can pop new elements + .data_o(fifo_output), + .pop_i(data_out_gnt) + ); + + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.vlt b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.vlt new file mode 100644 index 00000000..ac1ea03e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/simple_accelerator/simple_accelerator.vlt @@ -0,0 +1,10 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Author: Davide Schiavone , EPFL, STI-SEL +// Date: 12.02.2024 + +`verilator_config + +lint_off -rule UNUSED -file "*/simple_accelerator/simple_accelerator.sv" -match "*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/slow_memory/rtl/slow_memory.sv b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/slow_memory/rtl/slow_memory.sv index 785ddd46..6cedd80a 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/ip_examples/slow_memory/rtl/slow_memory.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/ip_examples/slow_memory/rtl/slow_memory.sv @@ -79,12 +79,21 @@ module slow_memory #( always_comb begin - gnt_o = 1'b0; - rvalid_o = rvalid_q; - state_n = state_q; - counter_n = counter_q - 1; - rvalid_n = rvalid_q; - + gnt_o = 1'b0; + rvalid_o = rvalid_q; + state_n = state_q; + counter_n = counter_q - 1; + rvalid_n = rvalid_q; + mem_req = '0; + mem_we = '0; + mem_addr = '0; + mem_wdata = '0; + mem_be = '0; + mem_req_n = mem_req_q; + mem_we_n = mem_we_q; + mem_addr_n = mem_addr_q; + mem_wdata_n = mem_wdata_q; + mem_be_n = mem_be_q; unique case (state_q) READY: begin @@ -92,13 +101,13 @@ module slow_memory #( if (req_i) begin gnt_o = random1[0]; if (gnt_o) begin - state_n = WAIT_RVALID; - counter_n = random2[4:0] + 1; - mem_req_n <= req_i; - mem_we_n <= we_i; - mem_addr_n <= addr_i; - mem_wdata_n <= wdata_i; - mem_be_n <= be_i; + state_n = WAIT_RVALID; + counter_n = random2[4:0] + 1; + mem_req_n = req_i; + mem_we_n = we_i; + mem_addr_n = addr_i; + mem_wdata_n = wdata_i; + mem_be_n = be_i; end end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/simulation/pad_cell_inout.sv b/hw/vendor/esl_epfl_x_heep/hw/simulation/pad_cell_inout.sv index 5dcc5449..3529b257 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/simulation/pad_cell_inout.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/simulation/pad_cell_inout.sv @@ -5,6 +5,7 @@ /* verilator lint_off UNUSED */ module pad_cell_inout #( parameter PADATTR = 16, + parameter core_v_mini_mcu_pkg::pad_side_e SIDE = core_v_mini_mcu_pkg::TOP, //do not touch these parameters parameter PADATTR_RND = PADATTR == 0 ? 1 : PADATTR ) ( diff --git a/hw/vendor/esl_epfl_x_heep/hw/simulation/pad_cell_input.sv b/hw/vendor/esl_epfl_x_heep/hw/simulation/pad_cell_input.sv index cfd9c426..5a7b053a 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/simulation/pad_cell_input.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/simulation/pad_cell_input.sv @@ -5,6 +5,7 @@ /* verilator lint_off UNUSED */ module pad_cell_input #( parameter PADATTR = 16, + parameter core_v_mini_mcu_pkg::pad_side_e SIDE = core_v_mini_mcu_pkg::TOP, //do not touch these parameters parameter PADATTR_RND = PADATTR == 0 ? 1 : PADATTR ) ( diff --git a/hw/vendor/esl_epfl_x_heep/hw/simulation/pad_cell_output.sv b/hw/vendor/esl_epfl_x_heep/hw/simulation/pad_cell_output.sv index cc4960ea..794e177d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/simulation/pad_cell_output.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/simulation/pad_cell_output.sv @@ -5,6 +5,7 @@ /* verilator lint_off UNUSED */ module pad_cell_output #( parameter PADATTR = 16, + parameter core_v_mini_mcu_pkg::pad_side_e SIDE = core_v_mini_mcu_pkg::TOP, //do not touch these parameters parameter PADATTR_RND = PADATTR == 0 ? 1 : PADATTR ) ( diff --git a/hw/vendor/esl_epfl_x_heep/hw/simulation/simulation.vlt b/hw/vendor/esl_epfl_x_heep/hw/simulation/simulation.vlt index 79d2edf4..0b30dd69 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/simulation/simulation.vlt +++ b/hw/vendor/esl_epfl_x_heep/hw/simulation/simulation.vlt @@ -5,3 +5,5 @@ `verilator_config lint_off -rule UNOPTFLAT -file "*/hw/simulation/pad_cell_*.sv" -match "Signal unoptimizable*" +lint_off -rule UNUSED -file "*/hw/simulation/sram_wrapper.sv" -match "Signal is not used: 'pwrgate_ni*" +lint_off -rule UNDRIVEN -file "*/hw/simulation/sram_wrapper.sv" -match "Signal is not driven: 'pwrgate_ack_no*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/simulation/sram_wrapper.sv b/hw/vendor/esl_epfl_x_heep/hw/simulation/sram_wrapper.sv index 7be64dcf..0986b3e2 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/simulation/sram_wrapper.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/simulation/sram_wrapper.sv @@ -22,6 +22,9 @@ module sram_wrapper #( input logic [AddrWidth-1:0] addr_i, input logic [31:0] wdata_i, input logic [3:0] be_i, + // power manager signals that goes to the ASIC macros + input logic pwrgate_ni, + output logic pwrgate_ack_no, input logic set_retentive_ni, // output ports output logic [31:0] rdata_o diff --git a/hw/vendor/esl_epfl_x_heep/hw/system/pad_control/data/pad_control.hjson.tpl b/hw/vendor/esl_epfl_x_heep/hw/system/pad_control/data/pad_control.hjson.tpl index 605843dc..466fd7d4 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/system/pad_control/data/pad_control.hjson.tpl +++ b/hw/vendor/esl_epfl_x_heep/hw/system/pad_control/data/pad_control.hjson.tpl @@ -26,7 +26,7 @@ % for pad in total_pad_list: { name: "PAD_ATTRIBUTE_${pad.name.upper()}", desc: "${pad.name} Attributes (Pull Up En, Pull Down En, etc. It is technology specific.", - resval: "0x00" + resval: "${pads_attributes['resval']}" swaccess: "rw", hwaccess: "hro", fields: [ diff --git a/hw/vendor/esl_epfl_x_heep/hw/system/x_heep_system.sv.tpl b/hw/vendor/esl_epfl_x_heep/hw/system/x_heep_system.sv.tpl index 7d58ed79..2a01983e 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/system/x_heep_system.sv.tpl +++ b/hw/vendor/esl_epfl_x_heep/hw/system/x_heep_system.sv.tpl @@ -11,7 +11,9 @@ module x_heep_system parameter ZFINX = 0, parameter EXT_XBAR_NMASTER = 0, parameter X_EXT = 0, // eXtension interface in cv32e40x + parameter AO_SPC_NUM = 0, //do not touch these parameters + parameter AO_SPC_NUM_RND = AO_SPC_NUM == 0 ? 1 : AO_SPC_NUM, parameter EXT_XBAR_NMASTER_RND = EXT_XBAR_NMASTER == 0 ? 1 : EXT_XBAR_NMASTER, parameter EXT_DOMAINS_RND = core_v_mini_mcu_pkg::EXTERNAL_DOMAINS == 0 ? 1 : core_v_mini_mcu_pkg::EXTERNAL_DOMAINS, parameter NEXT_INT_RND = core_v_mini_mcu_pkg::NEXT_INT == 0 ? 1 : core_v_mini_mcu_pkg::NEXT_INT @@ -29,13 +31,16 @@ module x_heep_system input obi_resp_t ext_core_data_resp_i, output obi_req_t ext_debug_master_req_o, input obi_resp_t ext_debug_master_resp_i, - output obi_req_t ext_dma_read_ch0_req_o, - input obi_resp_t ext_dma_read_ch0_resp_i, - output obi_req_t ext_dma_write_ch0_req_o, - input obi_resp_t ext_dma_write_ch0_resp_i, - output obi_req_t ext_dma_addr_ch0_req_o, - input obi_resp_t ext_dma_addr_ch0_resp_i, - + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_read_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_read_resp_i, + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_write_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_write_resp_i, + output obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_addr_req_o, + input obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] ext_dma_addr_resp_i, + + input reg_req_t [AO_SPC_NUM_RND-1:0] ext_ao_peripheral_req_i, + output reg_rsp_t [AO_SPC_NUM_RND-1:0] ext_ao_peripheral_resp_o, + output reg_req_t ext_peripheral_slave_req_o, input reg_rsp_t ext_peripheral_slave_resp_i, @@ -48,6 +53,10 @@ module x_heep_system output logic [31:0] exit_value_o, + input logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] ext_dma_slot_tx_i, + input logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] ext_dma_slot_rx_i, + input logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] ext_dma_stop_i, + // eXtension interface if_xif.cpu_compressed xif_compressed_if, if_xif.cpu_issue xif_issue_if, @@ -56,6 +65,9 @@ module x_heep_system if_xif.cpu_mem_result xif_mem_result_if, if_xif.cpu_result xif_result_if, + // External SPC interface + output logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] dma_done_o, + % for pad in total_pad_list: ${pad.x_heep_system_interface} % endfor @@ -63,13 +75,22 @@ ${pad.x_heep_system_interface} import core_v_mini_mcu_pkg::*; + + localparam EXT_HARTS = 0; + + //do not touch these parameter + localparam EXT_HARTS_RND = EXT_HARTS == 0 ? 1 : EXT_HARTS; + + + logic [EXT_HARTS_RND-1:0] ext_debug_req; + logic ext_cpu_subsystem_rst_n; + logic ext_debug_reset_n; + // PM signals logic cpu_subsystem_powergate_switch_n; logic cpu_subsystem_powergate_switch_ack_n; logic peripheral_subsystem_powergate_switch_n; logic peripheral_subsystem_powergate_switch_ack_n; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_n; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_ack_n; // PAD controller reg_req_t pad_req; @@ -88,12 +109,19 @@ ${pad.x_heep_system_interface} ${pad.internal_signals} % endfor +`ifdef FPGA_SYNTHESIS + assign cpu_subsystem_powergate_switch_ack_n = cpu_subsystem_powergate_switch_n; + assign peripheral_subsystem_powergate_switch_ack_n = peripheral_subsystem_powergate_switch_n; +`endif + core_v_mini_mcu #( .COREV_PULP(COREV_PULP), .FPU(FPU), .ZFINX(ZFINX), .EXT_XBAR_NMASTER(EXT_XBAR_NMASTER), - .X_EXT(X_EXT) + .X_EXT(X_EXT), + .AO_SPC_NUM(AO_SPC_NUM), + .EXT_HARTS(EXT_HARTS) ) core_v_mini_mcu_i ( .rst_ni(rst_ngen), @@ -111,33 +139,40 @@ ${pad.core_v_mini_mcu_bonding} .pad_resp_i(pad_resp), .ext_xbar_master_req_i, .ext_xbar_master_resp_o, + .ext_ao_peripheral_slave_req_i(ext_ao_peripheral_req_i), + .ext_ao_peripheral_slave_resp_o(ext_ao_peripheral_resp_o), .ext_core_instr_req_o, .ext_core_instr_resp_i, .ext_core_data_req_o, .ext_core_data_resp_i, .ext_debug_master_req_o, .ext_debug_master_resp_i, - .ext_dma_read_ch0_req_o, - .ext_dma_read_ch0_resp_i, - .ext_dma_write_ch0_req_o, - .ext_dma_write_ch0_resp_i, - .ext_dma_addr_ch0_req_o, - .ext_dma_addr_ch0_resp_i, + .ext_dma_read_req_o, + .ext_dma_read_resp_i, + .ext_dma_write_req_o, + .ext_dma_write_resp_i, + .ext_dma_addr_req_o, + .ext_dma_addr_resp_i, + .ext_dma_stop_i, .ext_peripheral_slave_req_o, .ext_peripheral_slave_resp_i, + .ext_debug_req_o(ext_debug_req), + .ext_debug_reset_no(ext_debug_reset_n), .cpu_subsystem_powergate_switch_no(cpu_subsystem_powergate_switch_n), .cpu_subsystem_powergate_switch_ack_ni(cpu_subsystem_powergate_switch_ack_n), .peripheral_subsystem_powergate_switch_no(peripheral_subsystem_powergate_switch_n), .peripheral_subsystem_powergate_switch_ack_ni(peripheral_subsystem_powergate_switch_ack_n), - .memory_subsystem_banks_powergate_switch_no(memory_subsystem_banks_powergate_switch_n), - .memory_subsystem_banks_powergate_switch_ack_ni(memory_subsystem_banks_powergate_switch_ack_n), .external_subsystem_powergate_switch_no, .external_subsystem_powergate_switch_ack_ni, .external_subsystem_powergate_iso_no, .external_subsystem_rst_no, + .ext_cpu_subsystem_rst_no(ext_cpu_subsystem_rst_n), .external_ram_banks_set_retentive_no, .external_subsystem_clkgate_en_no, - .exit_value_o + .exit_value_o, + .ext_dma_slot_tx_i, + .ext_dma_slot_rx_i, + .dma_done_o ); pad_ring pad_ring_i ( diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.core index 56a485a4..a31337d1 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.core @@ -60,3 +60,4 @@ targets: - files_rtl - ff_regfile - target_sim? (files_clk_gate) + - target_sim_sc? (files_clk_gate) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.lock.hjson index 39f77e7a..e307c5ae 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.lock.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/esl-epfl/cv32e40px.git - rev: acf3442b414725191fb7a2027facd0b5b4123c1c + rev: 10b08065c50d44b5355c1535cb8f740e68e4f106 } } diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.vendor.hjson index b261db04..4fc67fa6 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.vendor.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px.vendor.hjson @@ -7,11 +7,9 @@ upstream: { url: "https://github.com/esl-epfl/cv32e40px.git", - rev: "acf3442b414725191fb7a2027facd0b5b4123c1c", + rev: "10b08065c50d44b5355c1535cb8f740e68e4f106", }, - patch_dir: "patches/esl_epfl_cv32e40px", - exclude_from_upstream: [ "ci", ".github", diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/.gitignore b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/.gitignore index ef351b19..6c2cd791 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/.gitignore +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/.gitignore @@ -18,3 +18,11 @@ TAGS /build /Bender.lock /Bender.local +golden_reference_design +ref_design +golden.src +revised.src +cadence_conformal +synopsys_formality +questa_autocheck +reports diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/README.md b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/README.md index 0b23f841..2272b680 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/README.md +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/README.md @@ -1,8 +1,8 @@ [![Build Status](https://travis-ci.com/pulp-platform/riscv.svg?branch=master)](https://travis-ci.com/pulp-platform/riscv) -# OpenHW Group CORE-V CV32E40P RISC-V IP +# OpenHW Group CORE-V CV32E40PX RISC-V IP -CV32E40P is a small and efficient, 32-bit, in-order RISC-V core with a 4-stage pipeline that implements +CV32E40PX is a small and efficient, 32-bit, in-order RISC-V core with a 4-stage pipeline that implements the RV32IM\[F|Zfinx\]C instruction set architecture, and the PULP custom extensions for achieving higher code density, performance, and energy efficiency \[[1](https://doi.org/10.1109/TVLSI.2017.2654506)\], \[[2](https://doi.org/10.1109/PATMOS.2017.8106976)\]. It started its life as a fork of the OR10N CPU core that is based on the OpenRISC ISA. @@ -14,12 +14,12 @@ when it has been contributed to [OpenHW Group](https://www.openhwgroup.org/). ## Documentation -The CV32E40P user manual can be found in the _docs_ folder and it is +The CV32E40PX user manual can be found in the _docs_ folder and it is captured in reStructuredText, rendered to html using [Sphinx](https://docs.readthedocs.io/en/stable/intro/getting-started-with-sphinx.html). These documents are viewable using readthedocs and can be viewed [here](https://docs.openhwgroup.org/projects/cv32e40p-user-manual/). ## Verification -The verification environment for the CV32E40P is _not_ in this Repository. There is a small, simple testbench here which is +The verification environment for the CV32E40PX is _not_ in this Repository. There is a small, simple testbench here which is useful for experimentation only and should not be used to validate any changes to the RTL prior to pushing to the master branch of this repo. @@ -31,7 +31,7 @@ The Makefiles supported in the **core-v-verif** project automatically clone the ## Changelog A changelog is generated automatically in the documentation from the individual pull requests. -In order to enable automatic changelog generation within the CV32E40P documentation, the committer is required to label each pull request +In order to enable automatic changelog generation within the CV32E40PX documentation, the committer is required to label each pull request that touches any file in 'rtl' (or any of its subdirectories) with *Component:RTL* and label each pull request that touches any file in 'docs' (or any of its subdirectories) with *Component:Doc*. Pull requests that are not labeled or labeled with *ignore-for-release* are ignored for the changelog generation. @@ -40,7 +40,7 @@ Only the person who actually performs the merge can add these labels (you need c 1 label is applied and therefore pull requests that touches both RTL and documentation files in the same pull request are not allowed. ## Constraints -Example synthesis constraints for the CV32E40P are provided. +Example synthesis constraints for the CV32E40PX are provided. ## Contributing @@ -71,7 +71,7 @@ Run `./util/format-verible` to format all the files. ## Issues and Troubleshooting -If you find any problems or issues with CV32E40P or the documentation, please check out the [issue +If you find any problems or issues with CV32E40PX or the documentation, please check out the [issue tracker](https://github.com/openhwgroup/cv32e40p/issues) and create a new issue if your problem is not yet tracked. diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_instr_trace.svh b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_instr_trace.svh index 8c4ae99f..355bc738 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_instr_trace.svh +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_instr_trace.svh @@ -1,23 +1,37 @@ -// Copyright (c) 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. // -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +// This file, and derivatives thereof are licensed under the +// Solderpad License, Version 2.0 (the "License"). // -// https://solderpad.org/licenses/ +// Use of this file means you agree to the terms and conditions +// of the license and are in full compliance with the License. +// +// You may obtain a copy of the License at: +// +// https://solderpad.org/licenses/SHL-2.0/ // // Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// and hardware implementations thereof distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +// OF ANY KIND, EITHER EXPRESSED OR IMPLIED. +// // See the License for the specific language governing permissions and // limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 -// Tracer data structures and functions -// -// Contributors: Steve Richmond, Silicon Labs -// Pascal Gouedo, Dolphin Design +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Steve Richmond - steve.richmond@silabs.com // +// // +// Design Name: cv32e40p_tracer data structures // +// Project Name: CV32E40P // +// Language: SystemVerilog // +// // +// Description: Moves the class definition for instr_trace_t out of the // +// tracer module for readability and code partitioning // +// // +// Includes various enhancements to make the instr_trace_t // +// class more comprehensive // +// // +//////////////////////////////////////////////////////////////////////////////// typedef struct { logic [5:0] addr; @@ -35,9 +49,13 @@ typedef struct { class instr_trace_t; time simtime; + time stoptime; + bit external_time; int cycles; + int stopcycles; logic [31:0] pc; logic [31:0] instr; + string ctx; //Used to add context in the trace log file (Canceled, debug, interrput,....) bit compressed; bit wb_bypass; bit misaligned; @@ -56,10 +74,15 @@ class instr_trace_t; regs_read = {}; regs_write = {}; mem_access = {}; + external_time = 0; + stoptime = 0; + stopcycles = 0; endfunction function void init(int unsigned cycles, bit [31:0] pc, bit compressed, bit [31:0] instr); - this.simtime = $time; + if(!this.external_time) begin + this.simtime = $time; + end this.cycles = cycles; this.pc = pc; this.compressed = compressed; @@ -308,7 +331,23 @@ class instr_trace_t; begin string insn_str; // Accumulate writes into a single string to enable single $fwrite - insn_str = $sformatf("%t %15d %h %h %-36s", simtime, cycles, pc, instr, str); + if(simtime < 100ns) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else if (simtime < 1us) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else if (simtime < 10us) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else if (simtime < 100us) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else if (simtime < 1ms) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else if (simtime < 10ms) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else if (simtime < 100ms) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else begin + insn_str = $sformatf("%t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end foreach (regs_write[i]) begin if (regs_write[i].addr != 0) @@ -330,6 +369,12 @@ class instr_trace_t; insn_str = $sformatf("%s PA:%08x", insn_str, mem_acc.addr); end + casex (instr) + INSTR_FDIV: insn_str = $sformatf("%s %15d %t", insn_str, stopcycles, stoptime); + INSTR_FSQRT:insn_str = $sformatf("%s %15d %t", insn_str, stopcycles, stoptime); + default: ; + endcase + $fwrite(f, "%s\n", insn_str); end endfunction @@ -489,7 +534,7 @@ class instr_trace_t; begin mnemonic = {compressed ? "c." : "", mnemonic}; regs_read.push_back('{rs1, rs1_value, 0}); - str = $sformatf("%-16s %s, %0d", mnemonic, regAddrToStr(rs1), $signed(imm_sb_type)); + str = $sformatf("%-16s %s, %0d, %0d", mnemonic, regAddrToStr(rs1), $signed(imm_s2_type), $signed(imm_sb_type)); end endfunction // printSBInstr @@ -587,14 +632,14 @@ class instr_trace_t; // immediate post-incremented load regs_read.push_back('{rs1, rs1_value, 0}); regs_write.push_back('{rs1, 'x, 0}); - str = $sformatf("cv.%-13s %s, %0d(x%0d!)", mnemonic, regAddrToStr(rd), $signed(imm_i_type), rs1); + str = $sformatf("cv.%-13s %s, (x%0d), %0d", mnemonic, regAddrToStr(rd), rs1, $signed(imm_i_type)); end else if (instr[6:0] == OPCODE_CUSTOM_1) begin if (instr[27] == 1'b0) begin // reg-reg post-incremented load regs_read.push_back('{rs2, rs2_value, 0}); regs_read.push_back('{rs1, rs1_value, 0}); regs_write.push_back('{rs1, 'x, 0}); - str = $sformatf("cv.%-13s %s, %s(x%0d!)", mnemonic, regAddrToStr(rd), regAddrToStr(rs2), rs1); + str = $sformatf("cv.%-13s %s, (x%0d), %s", mnemonic, regAddrToStr(rd), rs1, regAddrToStr(rs2)); end else begin // reg-reg indexed load regs_read.push_back('{rs2, rs2_value, 0}); @@ -637,7 +682,7 @@ class instr_trace_t; regs_read.push_back('{rs2, rs2_value, 0}); regs_read.push_back('{rs1, rs1_value, 0}); regs_write.push_back('{rs1, 'x, 0}); - str = $sformatf("cv.%-14s %s, %0d(x%0d!)", mnemonic, regAddrToStr(rs2), $signed(imm_s_type), rs1); + str = $sformatf("cv.%-14s %s, (x%0d), %0d", mnemonic, regAddrToStr(rs2), rs1, $signed(imm_s_type)); end else if (instr[31:28] == 4'b0010) begin if (instr[27] == 1'b0) begin // reg-reg post-incremented store @@ -645,7 +690,7 @@ class instr_trace_t; regs_read.push_back('{rs3, rs3_value, 0}); regs_read.push_back('{rs1, rs1_value, 0}); regs_write.push_back('{rs1, 'x, 0}); - str = $sformatf("cv.%-13s %s, %s(x%0d!)", mnemonic, regAddrToStr(rs2), regAddrToStr(rs3), rs1); + str = $sformatf("cv.%-13s %s, (x%0d), %s", mnemonic, regAddrToStr(rs2), rs1, regAddrToStr(rs3)); end else begin // reg-reg indexed store regs_read.push_back('{rs2, rs2_value, 0}); @@ -679,22 +724,22 @@ class instr_trace_t; // decode and print instruction case (instr[11:8]) // cv.starti, cv.endi - 4'b0000, 4'b0010: str = $sformatf("%-16s %d, 0x%0x", mnemonic, rd[0], imm_iz_type); + 4'b0000, 4'b0010: str = $sformatf("%-16s %d, 0x%0x", mnemonic, instr[7], imm_iz_type); // cv.counti - 4'b0100: str = $sformatf("%-16s %d, %d", mnemonic, rd[0], imm_iz_type); + 4'b0100: str = $sformatf("%-16s %d, %d", mnemonic, instr[7], imm_iz_type); // cv.start, cv.end, cv.count 4'b0001, 4'b0011, 4'b0101: begin regs_read.push_back('{rs1, rs1_value, 0}); - str = $sformatf("%-16s %d, %s", mnemonic, rd[0], regAddrToStr(rs1)); + str = $sformatf("%-16s %d, %s", mnemonic, instr[7], regAddrToStr(rs1)); end // cv.setupi 4'b0110: begin - str = $sformatf("%-16s %d, %d, 0x%0x", mnemonic, rd[0], imm_iz_type, rs1); + str = $sformatf("%-16s %d, %d, 0x%0x", mnemonic, instr[7], imm_iz_type, rs1); end // cv.setup 4'b0111: begin regs_read.push_back('{rs1, rs1_value, 0}); - str = $sformatf("%-16s %d, %s, 0x%0x", mnemonic, rd[0], regAddrToStr(rs1), imm_iz_type); + str = $sformatf("%-16s %d, %s, 0x%0x", mnemonic, instr[7], regAddrToStr(rs1), imm_iz_type); end endcase end @@ -757,238 +802,429 @@ class instr_trace_t; else str_hb = ".h"; // set mnemonic - case (instr[31:26]) - 6'b000000: begin + case (instr) + INSTR_CVADDH , + INSTR_CVADDSCH , + INSTR_CVADDSCIH, + INSTR_CVADDB , + INSTR_CVADDSCB , + INSTR_CVADDSCIB : begin mnemonic = "cv.add"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b000010: begin + INSTR_CVSUBH , + INSTR_CVSUBSCH , + INSTR_CVSUBSCIH, + INSTR_CVSUBB , + INSTR_CVSUBSCB , + INSTR_CVSUBSCIB : begin mnemonic = "cv.sub"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b000100: begin + INSTR_CVAVGH , + INSTR_CVAVGSCH , + INSTR_CVAVGSCIH , + INSTR_CVAVGB , + INSTR_CVAVGSCB , + INSTR_CVAVGSCIB : begin mnemonic = "cv.avg"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b000110: begin + INSTR_CVAVGUH , + INSTR_CVAVGUSCH , + INSTR_CVAVGUSCIH, + INSTR_CVAVGUB , + INSTR_CVAVGUSCB , + INSTR_CVAVGUSCIB : begin mnemonic = "cv.avgu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b001000: begin + INSTR_CVMINH , + INSTR_CVMINSCH , + INSTR_CVMINSCIH, + INSTR_CVMINB , + INSTR_CVMINSCB , + INSTR_CVMINSCIB : begin mnemonic = "cv.min"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b001010: begin + INSTR_CVMINUH , + INSTR_CVMINUSCH , + INSTR_CVMINUSCIH, + INSTR_CVMINUB , + INSTR_CVMINUSCB , + INSTR_CVMINUSCIB : begin mnemonic = "cv.minu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b001100: begin + INSTR_CVMAXH , + INSTR_CVMAXSCH , + INSTR_CVMAXSCIH , + INSTR_CVMAXB , + INSTR_CVMAXSCB , + INSTR_CVMAXSCIB : begin mnemonic = "cv.max"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b001110: begin + INSTR_CVMAXUH , + INSTR_CVMAXUSCH , + INSTR_CVMAXUSCIH , + INSTR_CVMAXUB , + INSTR_CVMAXUSCB , + INSTR_CVMAXUSCIB : begin mnemonic = "cv.maxu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b010000: begin + INSTR_CVSRLH , + INSTR_CVSRLSCH , + INSTR_CVSRLSCIH , + INSTR_CVSRLB , + INSTR_CVSRLSCB , + INSTR_CVSRLSCIB : begin mnemonic = "cv.srl"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b010010: begin + INSTR_CVSRAH , + INSTR_CVSRASCH , + INSTR_CVSRASCIH, + INSTR_CVSRAB , + INSTR_CVSRASCB , + INSTR_CVSRASCIB : begin mnemonic = "cv.sra"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b010100: begin + INSTR_CVSLLH , + INSTR_CVSLLSCH , + INSTR_CVSLLSCIH, + INSTR_CVSLLB , + INSTR_CVSLLSCB , + INSTR_CVSLLSCIB : begin mnemonic = "cv.sll"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b010110: begin + INSTR_CVORH , + INSTR_CVORSCH , + INSTR_CVORSCIH, + INSTR_CVORB , + INSTR_CVORSCB , + INSTR_CVORSCIB : begin mnemonic = "cv.or"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b011000: begin + INSTR_CVXORH , + INSTR_CVXORSCH , + INSTR_CVXORSCIH , + INSTR_CVXORB , + INSTR_CVXORSCB , + INSTR_CVXORSCIB : begin mnemonic = "cv.xor"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b011010: begin + INSTR_CVANDH , + INSTR_CVANDSCH , + INSTR_CVANDSCIH , + INSTR_CVANDB , + INSTR_CVANDSCB , + INSTR_CVANDSCIB : begin mnemonic = "cv.and"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b011100: begin + INSTR_CVABSH, + INSTR_CVABSB : begin mnemonic = "cv.abs"; str_imm = $sformatf("0x%0h", imm_vs_type); end // dot products - 6'b100000: begin + INSTR_CVDOTUPH , + INSTR_CVDOTUPSCH , + INSTR_CVDOTUPSCIH, + INSTR_CVDOTUPB , + INSTR_CVDOTUPSCB , + INSTR_CVDOTUPSCIB : begin mnemonic = "cv.dotup"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b100010: begin + INSTR_CVDOTUSPH , + INSTR_CVDOTUSPSCH , + INSTR_CVDOTUSPSCIH, + INSTR_CVDOTUSPB , + INSTR_CVDOTUSPSCB , + INSTR_CVDOTUSPSCIB : begin mnemonic = "cv.dotusp"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b100100: begin + INSTR_CVDOTSPH , + INSTR_CVDOTSPSCH , + INSTR_CVDOTSPSCIH, + INSTR_CVDOTSPB , + INSTR_CVDOTSPSCB , + INSTR_CVDOTSPSCIB : begin mnemonic = "cv.dotsp"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b100110: begin + INSTR_CVSDOTUPH , + INSTR_CVSDOTUPSCH , + INSTR_CVSDOTUPSCIH, + INSTR_CVSDOTUPB , + INSTR_CVSDOTUPSCB , + INSTR_CVSDOTUPSCIB : begin mnemonic = "cv.sdotup"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b101000: begin + INSTR_CVSDOTUSPH , + INSTR_CVSDOTUSPSCH , + INSTR_CVSDOTUSPSCIH, + INSTR_CVSDOTUSPB , + INSTR_CVSDOTUSPSCB , + INSTR_CVSDOTUSPSCIB : begin mnemonic = "cv.sdotusp"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b101010: begin + INSTR_CVSDOTSPH , + INSTR_CVSDOTSPSCH , + INSTR_CVSDOTSPSCIH, + INSTR_CVSDOTSPB , + INSTR_CVSDOTSPSCB , + INSTR_CVSDOTSPSCIB : begin mnemonic = "cv.sdotsp"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b101110: begin - case (instr[14:13]) - 2'b00 : begin - mnemonic = "cv.extract"; - str_imm = $sformatf("0x%0h", imm_vs_type); - end - 2'b01 : begin - mnemonic = "cv.extractu"; - str_imm = $sformatf("0x%0h", imm_vu_type); - end - 2'b10 : begin - mnemonic = "cv.insert"; - str_imm = $sformatf("0x%0h", imm_vs_type); - end - endcase - str_sci = ""; + INSTR_CVEXTRACTH, + INSTR_CVEXTRACTB : begin + mnemonic = "cv.extract"; + str_imm = $sformatf("0x%0h", imm_vs_type); + str_sci = ""; + end + INSTR_CVEXTRACTUH, + INSTR_CVEXTRACTUB : begin + mnemonic = "cv.extractu"; + str_imm = $sformatf("0x%0h", imm_vu_type); + str_sci = ""; end - + INSTR_CVINSERTH, + INSTR_CVINSERTB : begin + mnemonic = "cv.insert"; + str_imm = $sformatf("0x%0h", imm_vs_type); + str_sci = ""; + end + // shuffle/pack - 6'b110000: begin - if (instr[14:12] == 3'b111) begin - mnemonic = "cv.shuffleI0"; - str_imm = $sformatf("0x%8h", imm_shuffle_type); - end else begin + INSTR_CVSHUFFLEH , + INSTR_CVSHUFFLESCIH, + INSTR_CVSHUFFLEB : begin mnemonic = "cv.shuffle"; if (instr[14:12] == 3'b110) begin str_imm = $sformatf("0x%8h", imm_shuffle_type); end - end end - 6'b110010: begin + + INSTR_CVSHUFFLEL0SCIB : begin + mnemonic = "cv.shuffleI0"; + str_imm = $sformatf("0x%8h", imm_shuffle_type); + end + INSTR_CVSHUFFLEL1SCIB : begin mnemonic = "cv.shuffleI1"; str_imm = $sformatf("0x%8h", imm_shuffle_type); end - 6'b110100: begin + INSTR_CVSHUFFLEL2SCIB : begin mnemonic = "cv.shuffleI2"; str_imm = $sformatf("0x%8h", imm_shuffle_type); end - 6'b110110: begin + INSTR_CVSHUFFLEL3SCIB : begin mnemonic = "cv.shuffleI3"; str_imm = $sformatf("0x%8h", imm_shuffle_type); end - 6'b111000: begin + INSTR_CVSHUFFLE2H, + INSTR_CVSHUFFLE2B : begin mnemonic = "cv.shuffle2"; end - 6'b111100: begin + INSTR_CVPACK, + INSTR_CVPACKH : begin mnemonic = "cv.pack"; if (instr[25] == 1'b0) begin str_hb = ""; end end - 6'b111110: begin - mnemonic = instr[25] ? "cv.packhi" : "cv.packlo"; - end + INSTR_CVPACKHIB : mnemonic = "cv.packhi"; + INSTR_CVPACKLOB : mnemonic = "cv.packlo"; // comparisons - 6'b000001: begin + INSTR_CVCMPEQH , + INSTR_CVCMPEQSCH , + INSTR_CVCMPEQSCIH, + INSTR_CVCMPEQB , + INSTR_CVCMPEQSCB , + INSTR_CVCMPEQSCIB : begin mnemonic = "cv.cmpeq"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b000011: begin + INSTR_CVCMPNEH , + INSTR_CVCMPNESCH , + INSTR_CVCMPNESCIH, + INSTR_CVCMPNEB , + INSTR_CVCMPNESCB , + INSTR_CVCMPNESCIB : begin mnemonic = "cv.cmpne"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b000101: begin + INSTR_CVCMPGTH , + INSTR_CVCMPGTSCH , + INSTR_CVCMPGTSCIH, + INSTR_CVCMPGTB , + INSTR_CVCMPGTSCB , + INSTR_CVCMPGTSCIB : begin mnemonic = "cv.cmpgt"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b000111: begin + INSTR_CVCMPGEH , + INSTR_CVCMPGESCH , + INSTR_CVCMPGESCIH, + INSTR_CVCMPGEB , + INSTR_CVCMPGESCB , + INSTR_CVCMPGESCIB : begin mnemonic = "cv.cmpge"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b001001: begin + INSTR_CVCMPLTH , + INSTR_CVCMPLTSCH , + INSTR_CVCMPLTSCIH, + INSTR_CVCMPLTB , + INSTR_CVCMPLTSCB , + INSTR_CVCMPLTSCIB : begin mnemonic = "cv.cmplt"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b001011: begin + INSTR_CVCMPLEH , + INSTR_CVCMPLESCH , + INSTR_CVCMPLESCIH, + INSTR_CVCMPLEB , + INSTR_CVCMPLESCB , + INSTR_CVCMPLESCIB : begin mnemonic = "cv.cmple"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b001101: begin + INSTR_CVCMPGTUH , + INSTR_CVCMPGTUSCH , + INSTR_CVCMPGTUSCIH, + INSTR_CVCMPGTUB , + INSTR_CVCMPGTUSCB , + INSTR_CVCMPGTUSCIB : begin mnemonic = "cv.cmpgtu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b001111: begin + INSTR_CVCMPGEUH , + INSTR_CVCMPGEUSCH , + INSTR_CVCMPGEUSCIH, + INSTR_CVCMPGEUB , + INSTR_CVCMPGEUSCB , + INSTR_CVCMPGEUSCIB : begin mnemonic = "cv.cmpgeu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b010001: begin + INSTR_CVCMPLTUH , + INSTR_CVCMPLTUSCH , + INSTR_CVCMPLTUSCIH, + INSTR_CVCMPLTUB , + INSTR_CVCMPLTUSCB , + INSTR_CVCMPLTUSCIB : begin mnemonic = "cv.cmpltu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b010011: begin + INSTR_CVCMPLEUH , + INSTR_CVCMPLEUSCH , + INSTR_CVCMPLEUSCIH, + INSTR_CVCMPLEUB , + INSTR_CVCMPLEUSCB , + INSTR_CVCMPLEUSCIB : begin mnemonic = "cv.cmpleu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b010101: begin - unique case (instr[14:13]) - 2'b00: mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r" : "cv.cplxmul.i"; - 2'b01: mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r.div2" : "cv.cplxmul.i.div2"; - 2'b10: mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r.div4" : "cv.cplxmul.i.div4"; - 2'b11: mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r.div8" : "cv.cplxmul.i.div8"; - endcase + INSTR_CVCPLXMULR, + INSTR_CVCPLXMULI : begin + mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r" : "cv.cplxmul.i"; str_sci = ""; str_hb = ""; end - - 6'b010111: begin - mnemonic = "cv.cplxconj"; - str_sci = ""; + INSTR_CVCPLXMULRDIV2, + INSTR_CVCPLXMULIDIV2 : begin + mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r.div2" : "cv.cplxmul.i.div2"; + str_sci = ""; str_hb = ""; end - - 6'b011001: begin - unique case (instr[14:13]) - 2'b00: mnemonic = "cv.subrotmj"; - 2'b01: mnemonic = "cv.subrotmj.div2"; - 2'b10: mnemonic = "cv.subrotmj.div4"; - 2'b11: mnemonic = "cv.subrotmj.div8"; - endcase + INSTR_CVCPLXMULRDIV4, + INSTR_CVCPLXMULIDIV4 : begin + mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r.div4" : "cv.cplxmul.i.div4"; str_sci = ""; str_hb = ""; end - - 6'b011011: begin - unique case (instr[14:13]) - 2'b01: mnemonic = "cv.add.div2"; - 2'b10: mnemonic = "cv.add.div4"; - 2'b11: mnemonic = "cv.add.div8"; - endcase + INSTR_CVCPLXMULRDIV8, + INSTR_CVCPLXMULIDIV8 : begin + mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r.div8" : "cv.cplxmul.i.div8"; str_sci = ""; str_hb = ""; end - 6'b011101: begin - unique case (instr[14:13]) - 2'b01: mnemonic = "cv.sub.div2"; - 2'b10: mnemonic = "cv.sub.div4"; - 2'b11: mnemonic = "cv.sub.div8"; - endcase - str_sci = ""; + INSTR_CVCPLXCONJ : begin + mnemonic = "cv.cplxconj"; + str_sci = ""; str_hb = ""; end + INSTR_CVSUBROTMJ : begin + mnemonic = "cv.subrotmj"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVSUBROTMJDIV2 : begin + mnemonic = "cv.subrotmj.div2"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVSUBROTMJDIV4 : begin + mnemonic = "cv.subrotmj.div4"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVSUBROTMJDIV8 : begin + mnemonic = "cv.subrotmj.div8"; + str_sci = ""; + str_hb = ""; + end + + INSTR_CVADDIV2 : begin + mnemonic = "cv.add.div2"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVADDIV4 : begin + mnemonic = "cv.add.div4"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVADDIV8 : begin + mnemonic = "cv.add.div8"; + str_sci = ""; + str_hb = ""; + end + + INSTR_CVSUBIV2 : begin + mnemonic = "cv.sub.div2"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVSUBIV4 : begin + mnemonic = "cv.sub.div4"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVSUBIV8 : begin + mnemonic = "cv.sub.div8"; + str_sci = ""; + str_hb = ""; + end + default: begin printMnemonic("INVALID"); return; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_rvfi.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_rvfi.sv index 868de33c..3675a950 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_rvfi.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_rvfi.sv @@ -1,24 +1,28 @@ -// Copyright (c) 2020 OpenHW Group +// Copyright 2024 Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. // You may obtain a copy of the License at // -// https://solderpad.org/licenses/ +// https://solderpad.org/licenses/SHL-2.1/ // -// Unless required by applicable law or agreed to in writing, software +// Unless required by applicable law or agreed to in writing, any work // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 -// CV32E40P RVFI interface -// -// Contributors: Davide Schiavone, OpenHW Group -// Halfdan Bechmann, Silicon Labs -// Yoann Pruvost, Dolphin Design +//////////////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Davide Schiavone, OpenHW Group // +// Halfdan Bechmann, Silicon Labs // +// Yoann Pruvost, Dolphin Design // +// // +// Description: CV32E40P RVFI interface // +// // +//////////////////////////////////////////////////////////////////////////////////// `include "cv32e40px_rvfi_pkg.sv" @@ -27,7 +31,8 @@ module cv32e40px_rvfi import cv32e40px_rvfi_pkg::*; #( parameter FPU = 0, - parameter ZFINX = 0 + parameter ZFINX = 0, + parameter NUM_MHPMCOUNTERS = 1 ) ( input logic clk_i, input logic rst_ni, @@ -73,6 +78,10 @@ module cv32e40px_rvfi input logic is_compressed_id_i, input logic ebrk_insn_dec_i, + input logic ecall_insn_dec_i, + + input logic mret_insn_dec_i, + input logic mret_dec_i, input logic [5:0] csr_cause_i, @@ -126,6 +135,9 @@ module cv32e40px_rvfi input logic [31:0] data_wdata_ex_i, input logic lsu_split_q_ex_i, + input logic mult_ready_i, + input logic alu_ready_i, + //// WB probes //// input logic [31:0] pc_wb_i, input logic wb_ready_i, @@ -202,6 +214,7 @@ module cv32e40px_rvfi input logic csr_we_i, input logic [31:0] csr_wdata_int_i, + input logic csr_fregs_we_i, input logic csr_jvt_we_i, input Status_t csr_mstatus_n_i, input Status_t csr_mstatus_q_i, @@ -282,7 +295,7 @@ module cv32e40px_rvfi // performance counters // cycle, instret, hpcounter, cycleh, instreth, hpcounterh // mcycle, minstret, mhpcounter, mcycleh, minstreth, mhpcounterh - input logic [31:0][MHPMCOUNTER_WIDTH-1:0] csr_mhpmcounter_q_i, + input logic [63:0][MHPMCOUNTER_WIDTH-1:0] csr_mhpmcounter_q_i, input logic [31:0] csr_mhpmcounter_write_lower_i, input logic [31:0] csr_mhpmcounter_write_upper_i, @@ -319,6 +332,10 @@ module cv32e40px_rvfi // the convention of RISC-V Formal Interface Specification. output logic [ 0:0] rvfi_valid, output logic [63:0] rvfi_order, + output integer rvfi_start_cycle, + output time rvfi_start_time, + output integer rvfi_stop_cycle, + output time rvfi_stop_time, output logic [31:0] rvfi_insn, output rvfi_trap_t rvfi_trap, output logic [ 0:0] rvfi_halt, @@ -338,6 +355,7 @@ module cv32e40px_rvfi output logic rvfi_frd_wvalid [1:0], output logic [ 4:0] rvfi_frd_addr [1:0], output logic [31:0] rvfi_frd_wdata [1:0], + output logic rvfi_2_rd, output logic [ 4:0] rvfi_rs1_addr, output logic [ 4:0] rvfi_rs2_addr, output logic [ 4:0] rvfi_rs3_addr, @@ -358,8 +376,8 @@ module cv32e40px_rvfi output logic [31:0] rvfi_pc_wdata, output logic [31:0] rvfi_mem_addr, - output logic [ 3:0] rvfi_mem_rmask, - output logic [ 3:0] rvfi_mem_wmask, + output logic [31:0] rvfi_mem_rmask, + output logic [31:0] rvfi_mem_wmask, output logic [31:0] rvfi_mem_rdata, output logic [31:0] rvfi_mem_wdata, @@ -610,6 +628,13 @@ module cv32e40px_rvfi bit clk_i_d; assign #0.01 clk_i_d = clk_i; + integer cycles; + // cycle counter + always_ff @(posedge clk_i_d, negedge rst_ni) begin + if (rst_ni == 1'b0) cycles <= 0; + else cycles <= cycles + 1; + end + logic pc_mux_debug; logic pc_mux_dret; logic pc_mux_exception; @@ -617,6 +642,11 @@ module cv32e40px_rvfi logic pc_mux_interrupt; logic pc_mux_nmi; + localparam logic [31:0] MSTATUS_WRITE_MASK = 32'h0000_6088; + localparam logic [31:0] MCOUNTINHIBIT_WRITE_MASK = {{(29-NUM_MHPMCOUNTERS){1'b0}}, {(NUM_MHPMCOUNTERS){1'b1}}, 3'b101}; + localparam NUM_HPM_EVENTS = 16; + localparam logic [31:0] MHPMEVENT_WRITE_MASK = {{(31-NUM_HPM_EVENTS){1'b0}}, {(NUM_HPM_EVENTS){1'b1}}}; + `include "pipe_freeze_trace.sv" `include "insn_trace.sv" @@ -633,6 +663,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; logic [2:0] saved_debug_cause; integer next_send; + event e_empty_queue; function void empty_fifo(); integer i, trace_q_size; trace_q_size = wb_bypass_trace_q.size(); @@ -648,6 +679,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; new_rvfi_trace.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; rvfi_trace_q.push_back(new_rvfi_trace); next_send = next_send + 1; + ->e_empty_queue; end else begin wb_bypass_trace_q.push_back(new_rvfi_trace); end @@ -658,6 +690,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; /* * Function used to alocate a new insn and send it to the rvfi driver */ + event e_add_to_bypass; function void send_rvfi(insn_trace_t m_wb_insn); insn_trace_t new_rvfi_trace; new_rvfi_trace = new(); @@ -667,6 +700,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; next_send = next_send + 1; end else begin wb_bypass_trace_q.push_back(new_rvfi_trace); + ->e_add_to_bypass; end empty_fifo(); endfunction @@ -733,6 +767,10 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end rvfi_order = new_rvfi_trace.m_order; + rvfi_start_cycle = new_rvfi_trace.m_start_cycle; + rvfi_start_time = new_rvfi_trace.m_start_time; + rvfi_stop_cycle = new_rvfi_trace.m_stop_cycle; + rvfi_stop_time = new_rvfi_trace.m_stop_time; rvfi_pc_rdata = new_rvfi_trace.m_pc_rdata; rvfi_insn = new_rvfi_trace.m_insn; @@ -787,6 +825,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; rvfi_frd_addr[1] = '0; rvfi_frd_wdata[1] = '0; + rvfi_2_rd = new_rvfi_trace.m_2_rd_insn; if (new_rvfi_trace.m_rd_addr[0][5] == 1'b0) begin rvfi_rd_addr[0] = new_rvfi_trace.m_rd_addr[0][4:0]; rvfi_rd_wdata[0] = new_rvfi_trace.m_rd_wdata[0]; @@ -837,7 +876,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; //CSR rvfi_csr_mstatus_rmask = new_rvfi_trace.m_csr.mstatus_rmask | new_rvfi_trace.m_csr.mstatus_fs_rmask; - rvfi_csr_mstatus_wmask = new_rvfi_trace.m_csr.mstatus_wmask; + rvfi_csr_mstatus_wmask = new_rvfi_trace.m_csr.mstatus_wmask & MSTATUS_WRITE_MASK; rvfi_csr_mstatus_wmask[31] = new_rvfi_trace.m_csr.mstatus_fs_wmask[31]; rvfi_csr_mstatus_wmask[14:13] = new_rvfi_trace.m_csr.mstatus_fs_wmask[14:13]; @@ -870,7 +909,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end rvfi_csr_mstatus_wdata[30:18] = '0; // MPRV is not implemented in the target configuration, writes to it are ignored - rvfi_csr_mstatus_wdata[17] = 1'b0;//new_rvfi_trace.m_csr.mstatus_wdata.mprv; + rvfi_csr_mstatus_wdata[17] = 1'b0; //new_rvfi_trace.m_csr.mstatus_wdata.mprv; rvfi_csr_mstatus_wdata[16:15] = '0; if (FPU == 1 && ZFINX == 0) begin rvfi_csr_mstatus_wdata[14:13] = new_rvfi_trace.m_csr.mstatus_fs_wdata; @@ -882,24 +921,59 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; rvfi_csr_mstatus_wdata[7] = new_rvfi_trace.m_csr.mstatus_wdata.mpie; rvfi_csr_mstatus_wdata[6:5] = '0; // UPIE is not implemented in the target configuration, writes to it are ignored - rvfi_csr_mstatus_wdata[4] = 1'b0;//new_rvfi_trace.m_csr.mstatus_wdata.upie; + rvfi_csr_mstatus_wdata[4] = 1'b0; //new_rvfi_trace.m_csr.mstatus_wdata.upie; rvfi_csr_mstatus_wdata[3] = new_rvfi_trace.m_csr.mstatus_wdata.mie; rvfi_csr_mstatus_wdata[2:1] = '0; // UIE is not implemented in the target configuration, writes to it are ignored - rvfi_csr_mstatus_wdata[0] = 1'b0;//new_rvfi_trace.m_csr.mstatus_wdata.uie; + rvfi_csr_mstatus_wdata[0] = 1'b0; //new_rvfi_trace.m_csr.mstatus_wdata.uie; `SET_RVFI_CSR_FROM_INSN(misa) `SET_RVFI_CSR_FROM_INSN(mie) `SET_RVFI_CSR_FROM_INSN(mtvec) - `SET_RVFI_CSR_FROM_INSN(mcountinhibit) + + rvfi_csr_mcountinhibit_rdata = new_rvfi_trace.m_csr.mcountinhibit_rdata; + rvfi_csr_mcountinhibit_rmask = new_rvfi_trace.m_csr.mcountinhibit_rmask; + rvfi_csr_mcountinhibit_wdata = new_rvfi_trace.m_csr.mcountinhibit_wdata; + rvfi_csr_mcountinhibit_wmask = new_rvfi_trace.m_csr.mcountinhibit_wmask & MCOUNTINHIBIT_WRITE_MASK; + `SET_RVFI_CSR_FROM_INSN(mscratch) `SET_RVFI_CSR_FROM_INSN(mepc) `SET_RVFI_CSR_FROM_INSN(mcause) + `SET_RVFI_CSR_FROM_INSN(mcycle) `SET_RVFI_CSR_FROM_INSN(minstret) + `SET_RVFI_CSR_FROM_INSN(minstreth) + + // `SET_RVFI_CSR_FROM_INSN(cycle) + // `SET_RVFI_CSR_FROM_INSN(instret) + rvfi_csr_instret_rdata = new_rvfi_trace.m_csr.minstret_rdata; + rvfi_csr_instret_rmask = new_rvfi_trace.m_csr.minstret_rmask; + rvfi_csr_instret_wdata = new_rvfi_trace.m_csr.minstret_wdata; + rvfi_csr_instret_wmask = new_rvfi_trace.m_csr.minstret_wmask; + + for(int idx=3; idx<32; idx++) begin + rvfi_csr_mhpmcounter_rmask[idx] = new_rvfi_trace.m_csr.mhpmcounter_rmask[idx][31:0]; + rvfi_csr_mhpmcounter_wmask[idx] = new_rvfi_trace.m_csr.mhpmcounter_wmask[idx][31:0]; + rvfi_csr_mhpmcounter_rdata[idx] = new_rvfi_trace.m_csr.mhpmcounter_rdata[idx][31:0]; + rvfi_csr_mhpmcounter_wdata[idx] = new_rvfi_trace.m_csr.mhpmcounter_wdata[idx][31:0]; + + rvfi_csr_mhpmcounterh_rmask[idx] = new_rvfi_trace.m_csr.mhpmcounter_rmask[idx][63:32]; + rvfi_csr_mhpmcounterh_wmask[idx] = new_rvfi_trace.m_csr.mhpmcounter_wmask[idx][63:32]; + rvfi_csr_mhpmcounterh_rdata[idx] = new_rvfi_trace.m_csr.mhpmcounter_rdata[idx][63:32]; + rvfi_csr_mhpmcounterh_wdata[idx] = new_rvfi_trace.m_csr.mhpmcounter_wdata[idx][63:32]; + + rvfi_csr_mhpmevent_rmask[idx] = new_rvfi_trace.m_csr.mhpmevent_rmask[idx]; + rvfi_csr_mhpmevent_wmask[idx] = new_rvfi_trace.m_csr.mhpmevent_wmask[idx] & MHPMEVENT_WRITE_MASK; + rvfi_csr_mhpmevent_rdata[idx] = new_rvfi_trace.m_csr.mhpmevent_rdata[idx]; + rvfi_csr_mhpmevent_wdata[idx] = new_rvfi_trace.m_csr.mhpmevent_wdata[idx]; + end + // `SET_RVFI_CSR_FROM_INSN(instreth) + rvfi_csr_instreth_rdata = new_rvfi_trace.m_csr.minstreth_rdata; + rvfi_csr_instreth_rmask = new_rvfi_trace.m_csr.minstreth_rmask; + rvfi_csr_instreth_wdata = new_rvfi_trace.m_csr.minstreth_wdata; + rvfi_csr_instreth_wmask = new_rvfi_trace.m_csr.minstreth_wmask; + `SET_RVFI_CSR_FROM_INSN(mip) - // if(rvfi_order == 64'h00000000_00000167) begin - // rvfi_csr_mip_rdata = 32'h0010_0000; - // end + rvfi_csr_tdata_rdata[0] = 'Z; rvfi_csr_tdata_rmask[0] = '0; // Does not exist rvfi_csr_tdata_wdata[0] = 'Z; // Does not exist @@ -945,36 +1019,134 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; endfunction // set_rvfi - function void minstret_to_id(); - trace_id.m_csr.minstret_we = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2]; - trace_id.m_csr.minstret_rdata = r_pipe_freeze_trace.csr.mhpmcounter_q[2]; - trace_id.m_csr.minstret_rmask = '1; - trace_id.m_csr.minstret_wdata = r_pipe_freeze_trace.csr.mhpmcounter_q; - trace_id.m_csr.minstret_wmask = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2] ? '1 : '0; + function void sample_perf_counter_to_id(int idx); + trace_id.m_csr.mhpmcounter_rdata[idx][31:0] = r_pipe_freeze_trace.csr.mhpmcounter_q[idx][31:0]; + trace_id.m_csr.mhpmcounter_rmask[idx][31:0] = '1; + endfunction + + function void perf_counter_to_id(int idx); + if(!trace_id.m_csr.mhpmcounter_we[idx][0]) begin + trace_id.m_csr.mhpmcounter_wdata[idx][31:0] = r_pipe_freeze_trace.csr.wdata_int; + end + if(r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx]) begin + trace_id.m_csr.mhpmcounter_we[idx][0] = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx]; + trace_id.m_csr.mhpmcounter_wdata[idx][31:0] = r_pipe_freeze_trace.csr.wdata_int; + trace_id.m_csr.mhpmcounter_wmask[idx][31:0] = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx] ? '1 : '0; + end + sample_perf_counter_to_id(idx); + endfunction + + function void sample_perf_event_to_trace(int idx, insn_trace_t m_trace); + m_trace.m_csr.mhpmevent_rdata[idx] = r_pipe_freeze_trace.csr.mhpmevent_q[idx]; + m_trace.m_csr.mhpmevent_rmask[idx] = '1; endfunction - function void minstret_to_ex(); - trace_ex.m_csr.minstret_we = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2]; - trace_ex.m_csr.minstret_rdata = r_pipe_freeze_trace.csr.mhpmcounter_q[2]; - trace_ex.m_csr.minstret_rmask = '1; - trace_ex.m_csr.minstret_wdata = r_pipe_freeze_trace.csr.mhpmcounter_q; - trace_ex.m_csr.minstret_wmask = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2] ? '1 : '0; + function void perf_event_to_trace(int idx, insn_trace_t m_trace); + if(!m_trace.m_csr.mhpmevent_we[idx]) begin + m_trace.m_csr.mhpmevent_wdata[idx] = r_pipe_freeze_trace.csr.wdata_int; + end + if(r_pipe_freeze_trace.csr.mhpmevent_we[idx]) begin + m_trace.m_csr.mhpmevent_we[idx] = r_pipe_freeze_trace.csr.mhpmevent_we[idx]; + m_trace.m_csr.mhpmevent_wdata[idx] = r_pipe_freeze_trace.csr.wdata_int; + m_trace.m_csr.mhpmevent_wmask[idx] = r_pipe_freeze_trace.csr.mhpmevent_we[idx] ? '1 : '0; + end + sample_perf_event_to_trace(idx, m_trace); endfunction - function void tinfo_to_id(); - trace_id.m_csr.tinfo_we = '0; // READ ONLY csr_tinfo_we_i; - trace_id.m_csr.tinfo_rdata = r_pipe_freeze_trace.csr.tinfo_q; - trace_id.m_csr.tinfo_rmask = '1; - trace_id.m_csr.tinfo_wdata = r_pipe_freeze_trace.csr.tinfo_n; - trace_id.m_csr.tinfo_wmask = '0; + function void sample_minstret_to_trace(insn_trace_t m_trace); + m_trace.m_csr.minstret_rdata = r_pipe_freeze_trace.csr.mhpmcounter_q[2][31:0]; + m_trace.m_csr.minstret_rmask = '1; endfunction - function void tinfo_to_ex(); - trace_ex.m_csr.tinfo_we = '0; // READ ONLY csr_tinfo_we_i; - trace_ex.m_csr.tinfo_rdata = r_pipe_freeze_trace.csr.tinfo_q; - trace_ex.m_csr.tinfo_rmask = '1; - trace_ex.m_csr.tinfo_wdata = r_pipe_freeze_trace.csr.tinfo_n; - trace_ex.m_csr.tinfo_wmask = '0; + function void minstret_to_trace(insn_trace_t m_trace); + if(!m_trace.m_csr.minstret_we) begin + m_trace.m_csr.minstret_wdata = r_pipe_freeze_trace.csr.wdata_int; + end + if(r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2]) begin + m_trace.m_csr.minstret_we = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2]; + m_trace.m_csr.minstret_wdata = r_pipe_freeze_trace.csr.wdata_int; + m_trace.m_csr.minstret_wmask = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2] ? '1 : '0; + end + sample_minstret_to_trace(m_trace); + endfunction + + function void sample_perf_counter_h_to_id(int idx); + trace_id.m_csr.mhpmcounter_rdata[idx][63:32] = r_pipe_freeze_trace.csr.mhpmcounter_q[idx][63:0]; + trace_id.m_csr.mhpmcounter_rmask[idx][63:32] = '1; + endfunction + + function void perf_counter_h_to_id(int idx); + if(!trace_id.m_csr.mhpmcounter_we[idx][1]) begin + trace_id.m_csr.mhpmcounter_wdata[idx][63:32] = r_pipe_freeze_trace.csr.wdata_int; + end + if(r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx]) begin + trace_id.m_csr.mhpmcounter_we[idx][1] = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx]; + trace_id.m_csr.mhpmcounter_wdata[idx][63:32] = r_pipe_freeze_trace.csr.wdata_int; + trace_id.m_csr.mhpmcounter_wmask[idx][63:32] = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx] ? '1 : '0; + end + sample_perf_counter_h_to_id(idx); + endfunction + + function void sample_minstreth_to_trace(insn_trace_t m_trace); + m_trace.m_csr.minstreth_rdata = r_pipe_freeze_trace.csr.mhpmcounter_q[2][63:32]; + m_trace.m_csr.minstreth_rmask = '1; + endfunction + + function void sample_mcycle_to_trace(insn_trace_t m_trace); + m_trace.m_csr.mcycle_we = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[0]; + m_trace.m_csr.mcycle_rdata = r_pipe_freeze_trace.csr.mhpmcounter_q[0][31:0]; + m_trace.m_csr.mcycle_rmask = '1; + m_trace.m_csr.mcycle_wdata = r_pipe_freeze_trace.csr.mhpmcounter_q[31:0]; + m_trace.m_csr.mcycle_wmask = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[0] ? '1 : '0; + endfunction + + function void minstreth_to_trace(insn_trace_t m_trace); + if(!m_trace.m_csr.minstreth_we) begin + m_trace.m_csr.minstreth_wdata = r_pipe_freeze_trace.csr.wdata_int; + end + if(r_pipe_freeze_trace.csr.mhpmcounter_write_upper[2]) begin + m_trace.m_csr.minstreth_we = r_pipe_freeze_trace.csr.mhpmcounter_write_upper[2]; + m_trace.m_csr.minstreth_wdata = r_pipe_freeze_trace.csr.wdata_int; + m_trace.m_csr.minstreth_wmask = r_pipe_freeze_trace.csr.mhpmcounter_write_upper[2] ? '1 : '0; + end + sample_minstreth_to_trace(m_trace); + endfunction + + function void sample_perf_counter_to_trace(insn_trace_t m_trace); + sample_minstret_to_trace(m_trace); + sample_minstreth_to_trace(m_trace); + sample_mcycle_to_trace(m_trace); + for(int idx=3; idx<32; idx++)begin + sample_perf_event_to_trace(idx, m_trace); //TO CHANGE + end + endfunction + + function void perf_counter_to_trace(insn_trace_t m_trace); + if(r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2]) begin + minstret_to_trace(m_trace); + end + if(r_pipe_freeze_trace.csr.mhpmcounter_write_upper[2]) begin + minstreth_to_trace(m_trace); + end + for(int idx=3; idx<32; idx++) begin + if(r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx]) begin + perf_counter_to_id(idx); + end + if(r_pipe_freeze_trace.csr.mhpmcounter_write_upper[idx]) begin + perf_counter_h_to_id(idx); + end + if(r_pipe_freeze_trace.csr.mhpmevent_we[idx]) begin + perf_event_to_trace(idx, m_trace); + end + end + endfunction + + function void tinfo_to_trace(insn_trace_t m_trace); + m_trace.m_csr.tinfo_we = '0; // READ ONLY csr_tinfo_we_i; + m_trace.m_csr.tinfo_rdata = r_pipe_freeze_trace.csr.tinfo_q; + m_trace.m_csr.tinfo_rmask = '1; + m_trace.m_csr.tinfo_wdata = r_pipe_freeze_trace.csr.tinfo_n; + m_trace.m_csr.tinfo_wmask = '0; endfunction function void mtvec_to_id(); @@ -1069,8 +1241,6 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; lpcount1_to_id(); lpend1_to_id(); lpstart1_to_id(); - - endfunction bit s_was_flush; //debug exception is flagged as trap only if preceed by a flush @@ -1111,6 +1281,9 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; * The third updates the rvfi interface */ `define CSR_FROM_PIPE(TRACE_NAME, CSR_NAME) \ + if(!trace_``TRACE_NAME``.m_csr.``CSR_NAME``_we) begin \ + trace_``TRACE_NAME``.m_csr.``CSR_NAME``_wdata = r_pipe_freeze_trace.csr.``CSR_NAME``_n; \ + end\ if (r_pipe_freeze_trace.csr.``CSR_NAME``_we) begin \ trace_``TRACE_NAME``.m_csr.``CSR_NAME``_we = r_pipe_freeze_trace.csr.``CSR_NAME``_we; \ trace_``TRACE_NAME``.m_csr.``CSR_NAME``_wdata = r_pipe_freeze_trace.csr.``CSR_NAME``_n; \ @@ -1120,9 +1293,14 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_``TRACE_NAME``.m_csr.``CSR_NAME``_rmask = '1; event e_mstatus_to_id; + event e_fregs_dirty_1, e_fregs_dirty_2, e_fregs_dirty_3; function void mstatus_to_id(); `CSR_FROM_PIPE(id, mstatus) `CSR_FROM_PIPE(id, mstatus_fs) + if(r_pipe_freeze_trace.csr.fregs_we && !r_pipe_freeze_trace.csr.mstatus_fs_we && !(r_pipe_freeze_trace.csr.we && r_pipe_freeze_trace.csr.mstatus_fs_we)) begin //writes happening in ex that needs to be reported to id + trace_id.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; + ->e_fregs_dirty_2; + end ->e_mstatus_to_id; endfunction //those event are for debug purpose @@ -1133,10 +1311,11 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; e_dev_commit_rf_to_ex_3, e_dev_commit_rf_to_ex_4, e_dev_commit_rf_to_ex_5; - event e_if_2_id_1, e_if_2_id_2; + event e_if_2_id_1, e_if_2_id_2, e_if_2_id_3, e_if_2_id_4; event e_ex_to_wb_1, e_ex_to_wb_2; event e_id_to_ex_1, e_id_to_ex_2; event e_commit_dpc; + event e_csr_in_ex, e_csr_irq; event e_send_rvfi_trace_apu_resp; event @@ -1160,12 +1339,17 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; `CSR_FROM_PIPE(apu_resp, fcsr) `CSR_FROM_PIPE(apu_resp, fflags) - // `CSR_FROM_PIPE(apu_resp, mstatus) `CSR_FROM_PIPE(apu_resp, mstatus_fs) - if (r_pipe_freeze_trace.csr.mstatus_we) begin + if (r_pipe_freeze_trace.csr.mstatus_fs_we && (trace_id.m_order > trace_apu_resp.m_order)) begin + trace_id.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; + end + if (r_pipe_freeze_trace.csr.mstatus_fs_we && (trace_ex.m_order > trace_apu_resp.m_order)) begin trace_ex.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; end + if (r_pipe_freeze_trace.csr.mstatus_fs_we && (trace_wb.m_order > trace_apu_resp.m_order)) begin + trace_wb.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; + end endfunction function void csr_to_apu_req(); @@ -1229,6 +1413,9 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end end csr_to_apu_resp(); + + trace_apu_resp.m_stop_cycle = cycles; + trace_apu_resp.m_stop_time = $time; send_rvfi(trace_apu_resp); ->e_send_rvfi_trace_apu_resp; end @@ -1243,27 +1430,48 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; bit s_is_irq_start; bit s_id_done; function void if_to_id(); + if (trace_id.m_valid) begin + `CSR_FROM_PIPE(id, misa) + `CSR_FROM_PIPE(id, tdata1) + `CSR_FROM_PIPE(id, tdata2) + tinfo_to_trace(trace_id); + `CSR_FROM_PIPE(id, mip) + send_rvfi(trace_id); + end trace_id.init(trace_if); trace_id.m_trap = ~r_pipe_freeze_trace.minstret; - trace_id.m_is_illegal = r_pipe_freeze_trace.is_illegal; + trace_id.m_is_illegal = trace_id.m_is_illegal | r_pipe_freeze_trace.is_illegal; + `CSR_FROM_PIPE(id, dpc) s_is_pc_set = 1'b0; s_is_irq_start = 1'b0; trace_if.m_valid = 1'b0; s_id_done = 1'b0; - `CSR_FROM_PIPE(id, dpc) endfunction function logic [31:0] be_to_mask(logic [3:0] be); logic [31:0] mask; - mask[7:0] = be[0] ? 8'hFF : 8'h00; - mask[15:8] = be[0] ? 8'hFF : 8'h00; - mask[23:16] = be[0] ? 8'hFF : 8'h00; - mask[31:24] = be[0] ? 8'hFF : 8'h00; + mask[7:0] = (be[0] == 1'b1) ? 8'hFF : 8'h00; + mask[15:8] = (be[1] == 1'b1) ? 8'hFF : 8'h00; + mask[23:16] = (be[2] == 1'b1) ? 8'hFF : 8'h00; + mask[31:24] = (be[3] == 1'b1) ? 8'hFF : 8'h00; be_to_mask = mask; return mask; endfunction + function void commit_rf_to_trace(insn_trace_t m_trace); + if (m_trace.m_got_ex_reg) begin + m_trace.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; + m_trace.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; + m_trace.m_2_rd_insn = 1'b1; + m_trace.m_got_first_data = 1'b1; + end else begin + m_trace.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; + m_trace.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; + m_trace.m_got_first_data = 1'b1; + end + endfunction + task compute_pipeline(); bit s_new_valid_insn; bit s_ex_valid_adjusted; @@ -1280,34 +1488,44 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; bit s_core_is_decoding; // For readability, ctrl_fsm is DECODE or DECODE_HWLOOP - trace_if = new(); - trace_id = new(); - trace_ex = new(); - trace_wb = new(); - s_new_valid_insn = 1'b0; - s_ex_valid_adjusted = 1'b0; + bit s_ex_reg_we_adjusted; //ex_reg_we + bit s_rf_we_wb_adjusted; // + + bit s_dont_override_mstatus_fs_id; + + trace_if = new(); + trace_id = new(); + trace_ex = new(); + trace_wb = new(); + s_new_valid_insn = 1'b0; + s_ex_valid_adjusted = 1'b0; + + s_id_done = 1'b0; + s_apu_wb_ok = 1'b0; + s_apu_0_cycle_reps = 1'b0; + + next_send = 1; + cnt_data_req = 0; + cnt_data_resp = 0; + cnt_apu_req = 0; + cnt_apu_resp = 0; + csr_is_irq = '0; + is_dbg_taken = '0; + s_was_flush = 1'b0; - s_id_done = 1'b0; - s_apu_wb_ok = 1'b0; - s_apu_0_cycle_reps = 1'b0; + s_is_pc_set = 1'b0; + s_is_irq_start = 1'b0; - next_send = 1; - cnt_data_req = 0; - cnt_data_resp = 0; - cnt_apu_req = 0; - cnt_apu_resp = 0; - csr_is_irq = '0; - is_dbg_taken = '0; - s_was_flush = 1'b0; + s_is_pc_set = 1'b0; + s_is_irq_start = 1'b0; + s_skip_wb = 1'b0; - s_is_pc_set = 1'b0; - s_is_irq_start = 1'b0; + s_core_is_decoding = 1'b0; - s_is_pc_set = 1'b0; - s_is_irq_start = 1'b0; - s_skip_wb = 1'b0; + s_ex_reg_we_adjusted = 1'b0; + s_rf_we_wb_adjusted = 1'b0; - s_core_is_decoding = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; forever begin wait(e_pipe_monitor_ok.triggered); // event triggered @@ -1325,23 +1543,11 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end if (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_ID && r_pipe_freeze_trace.ebrk_insn_dec) begin - if (trace_wb.m_valid) begin - send_rvfi(trace_wb); - trace_wb.m_valid = 1'b0; - ->e_send_rvfi_trace_wb_1; - end - if (trace_ex.m_valid) begin - send_rvfi(trace_ex); - trace_ex.m_valid = 1'b0; - ->e_send_rvfi_trace_ex_1; - end if (trace_id.m_valid) begin - - minstret_to_id(); `CSR_FROM_PIPE(id, misa) `CSR_FROM_PIPE(id, tdata1) `CSR_FROM_PIPE(id, tdata2) - tinfo_to_id(); + tinfo_to_trace(trace_id); `CSR_FROM_PIPE(id, mip) end end @@ -1375,7 +1581,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; if (trace_ex.m_valid & s_wb_valid_adjusted) begin // Used flopped values in case write happened before wb_valid - minstret_to_ex(); + sample_perf_counter_to_trace(trace_ex); trace_ex.m_csr.got_minstret = '1; end @@ -1387,7 +1593,9 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; s_new_valid_insn = r_pipe_freeze_trace.id_valid && r_pipe_freeze_trace.is_decoding;// && !r_pipe_freeze_trace.apu_rvalid; - s_wb_valid_adjusted = r_pipe_freeze_trace.wb_valid && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_EX));// && !r_pipe_freeze_trace.apu_rvalid;; + s_wb_valid_adjusted = r_pipe_freeze_trace.wb_valid && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_EX) || (r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_WB) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_FLUSH) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_ID) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_IF));// && !r_pipe_freeze_trace.apu_rvalid;; + s_ex_reg_we_adjusted = r_pipe_freeze_trace.ex_reg_we && r_pipe_freeze_trace.mult_ready && r_pipe_freeze_trace.alu_ready && r_pipe_freeze_trace.lsu_ready_ex && !s_apu_to_alu_port; + s_rf_we_wb_adjusted = r_pipe_freeze_trace.rf_we_wb && (~r_pipe_freeze_trace.data_misaligned_ex && r_pipe_freeze_trace.wb_ready) && (!s_apu_to_lsu_port || r_pipe_freeze_trace.wb_contention_lsu); s_fflags_we_non_apu = 1'b0; if (r_pipe_freeze_trace.csr.fflags_we) begin @@ -1418,60 +1626,55 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; s_skip_wb = 1'b1; end end - if (trace_wb.m_valid && !s_skip_wb) begin - if (r_pipe_freeze_trace.rf_we_wb) begin - if((trace_wb.m_rd_addr[0] == r_pipe_freeze_trace.rf_addr_wb) && (cnt_data_resp == trace_wb.m_mem_req_id[0]) && trace_wb.m_mem_req_id_valid[0]) begin - trace_wb.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; - trace_wb.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - trace_wb.m_mem_req_id_valid[0] = 1'b0; - end else if (trace_wb.m_2_rd_insn && (trace_wb.m_rd_addr[1] == r_pipe_freeze_trace.rf_addr_wb) && (cnt_data_resp == trace_wb.m_mem_req_id[1]) && trace_wb.m_mem_req_id_valid[1]) begin - trace_wb.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; - trace_wb.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; - trace_wb.m_mem_req_id_valid[1] = 1'b0; - end - end - if (!trace_wb.m_data_missaligned) begin - send_rvfi(trace_wb); - ->e_dev_send_wb_1; ->e_send_rvfi_trace_wb_2; - trace_wb.m_valid = 1'b0; + if (trace_wb.m_valid && !s_skip_wb && s_rf_we_wb_adjusted) begin + if (trace_wb.m_2_rd_insn) begin + trace_wb.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; + trace_wb.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; + end else if (trace_wb.m_ex_fw) begin + trace_wb.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; + trace_wb.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; + trace_wb.m_2_rd_insn = 1'b1; end else begin - if (s_wb_valid_adjusted) begin - if (r_pipe_freeze_trace.rf_we_wb) begin - if (!trace_wb.m_ex_fw) begin - trace_wb.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; - trace_wb.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - end - if (trace_wb.m_data_missaligned && !trace_wb.m_got_first_data) begin - trace_wb.m_got_first_data = 1'b1; - end else begin - send_rvfi(trace_wb); - ->e_dev_send_wb_2; ->e_send_rvfi_trace_wb_3; - trace_wb.m_valid = 1'b0; - end - end // rf_we_wb + trace_wb.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; + trace_wb.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; + end + + if (r_pipe_freeze_trace.csr.fregs_we) begin + `CSR_FROM_PIPE(wb, mstatus_fs) + trace_wb.m_csr.mstatus_fs_we = 1'b1; + trace_wb.m_csr.mstatus_fs_wmask = '1; + if(r_pipe_freeze_trace.csr.we && r_pipe_freeze_trace.csr.mstatus_fs_we) begin //In this specific case, two writes to mstatus_fs happen at the same time. We need to recreate the writes caused by fregs_we + trace_wb.m_csr.mstatus_fs_wdata = FS_DIRTY; end + ->e_fregs_dirty_1; end + + send_rvfi(trace_wb); + ->e_dev_send_wb_1; ->e_send_rvfi_trace_wb_2; + trace_wb.m_valid = 1'b0; + end if (trace_ex.m_valid) begin - - if (!trace_ex.m_csr.got_minstret) begin - minstret_to_ex(); + if(trace_ex.m_instret_smaple_trigger == 1) begin //time to sample instret + sample_perf_counter_to_trace(trace_ex); end + trace_ex.m_instret_smaple_trigger = trace_ex.m_instret_smaple_trigger + 1; + `CSR_FROM_PIPE(ex, misa) `CSR_FROM_PIPE(ex, tdata1) `CSR_FROM_PIPE(ex, tdata2) - tinfo_to_ex(); + tinfo_to_trace(trace_ex); - if (r_pipe_freeze_trace.regfile_we_lsu) begin + if (s_rf_we_wb_adjusted) begin ->e_dev_commit_rf_to_ex_4; - if ((cnt_data_resp == trace_ex.m_mem_req_id[0]) && !(trace_ex.m_got_ex_reg) && trace_ex.m_mem_req_id_valid[0]) begin + if (!(trace_ex.m_got_ex_reg) && trace_ex.m_mem_req_id_valid[0]) begin trace_ex.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; trace_ex.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; trace_ex.m_got_first_data = 1'b1; trace_ex.m_mem_req_id_valid[0] = 1'b0; - end else if ((cnt_data_resp == trace_ex.m_mem_req_id[1]) && trace_ex.m_mem_req_id_valid[1]) begin + end else if (trace_ex.m_mem_req_id_valid[1]) begin trace_ex.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; trace_ex.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; trace_ex.m_got_first_data = 1'b1; @@ -1485,66 +1688,86 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_ex.m_valid = 1'b0; ->e_send_rvfi_trace_ex_2; end else begin - if (r_pipe_freeze_trace.rf_we_wb && !s_apu_to_lsu_port) begin + + if (s_rf_we_wb_adjusted) begin ->e_dev_commit_rf_to_ex_1; - if (trace_ex.m_got_ex_reg) begin - trace_ex.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; - trace_ex.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; - trace_ex.m_2_rd_insn = 1'b1; - trace_ex.m_got_first_data = 1'b1; - end else begin - trace_ex.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; - trace_ex.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - trace_ex.m_got_first_data = 1'b1; + commit_rf_to_trace(trace_ex); + + if (r_pipe_freeze_trace.csr.fregs_we && (r_pipe_freeze_trace.rf_we_wb && r_pipe_freeze_trace.rf_addr_wb[5])) begin //Catching mstatus_fs updates caused by flw + `CSR_FROM_PIPE(ex, mstatus_fs) + trace_ex.m_csr.mstatus_fs_we = 1'b1; + trace_ex.m_csr.mstatus_fs_wmask = '1; + if(r_pipe_freeze_trace.csr.we && r_pipe_freeze_trace.csr.mstatus_fs_we) begin //In this specific case, two writes to mstatus_fs happen at the same time. We need to recreate the writes caused by fregs_we + trace_ex.m_csr.mstatus_fs_wdata = FS_DIRTY; + end else begin + trace_id.m_csr.mstatus_fs_rdata = trace_ex.m_csr.mstatus_fs_wdata; + s_dont_override_mstatus_fs_id = 1'b1; + end + ->e_fregs_dirty_3; end - end - if (!s_ex_valid_adjusted & !trace_ex.m_csr.got_minstret) begin - minstret_to_ex(); - end - if (trace_ex.m_is_load) begin // only move relevant instr in wb stage - ->e_ex_to_wb_1; - trace_wb.move_down_pipe(trace_ex); + send_rvfi(trace_ex); + trace_ex.m_valid = 1'b0; + end else begin - if (!trace_ex.m_csr.got_minstret) begin - minstret_to_ex(); + if (trace_ex.m_is_load) begin // only move relevant instr in wb stage + ->e_ex_to_wb_1; + trace_wb.move_down_pipe(trace_ex); + end else begin + send_rvfi(trace_ex); + ->e_send_rvfi_trace_ex_6; end - send_rvfi(trace_ex); - ->e_send_rvfi_trace_ex_6; + trace_ex.m_valid = 1'b0; end - trace_ex.m_valid = 1'b0; end - end else if (r_pipe_freeze_trace.rf_we_wb && !s_apu_to_lsu_port && !s_was_flush) begin + end else if (s_rf_we_wb_adjusted && !s_was_flush) begin ->e_dev_commit_rf_to_ex_2; - if (trace_ex.m_got_ex_reg) begin - trace_ex.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; - trace_ex.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; - trace_ex.m_2_rd_insn = 1'b1; - trace_ex.m_got_first_data = 1'b1; - end else begin - trace_ex.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; - trace_ex.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - trace_ex.m_got_first_data = 1'b1; - end + commit_rf_to_trace(trace_ex); end end - s_ex_valid_adjusted = (r_pipe_freeze_trace.ex_valid && r_pipe_freeze_trace.ex_ready) && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_IF)) && (!r_pipe_freeze_trace.apu_rvalid || r_pipe_freeze_trace.data_req_ex); + // If mret, we need to keep the instruction in Id during flush_ex because mstatus update happens at that time + s_ex_valid_adjusted = (r_pipe_freeze_trace.ex_valid && r_pipe_freeze_trace.ex_ready) && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_IF) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_ID) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_FLUSH) || ((r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_EX) && !r_pipe_freeze_trace.mret_insn_dec)); //EX_STAGE - if (trace_id.m_valid) begin - mtvec_to_id(); - `CSR_FROM_PIPE(id, mip) - `CSR_FROM_PIPE(id, misa) + if (trace_id.m_valid) begin + if(trace_id.m_instret_smaple_trigger == 1) begin //time to sample instret + sample_perf_counter_to_trace(trace_id); + for(int idx=3; idx<32; idx++) begin + sample_perf_counter_to_id(idx); + sample_perf_counter_h_to_id(idx); + sample_perf_event_to_trace(idx, trace_id); + end + end + trace_id.m_instret_smaple_trigger = trace_id.m_instret_smaple_trigger + 1; - if (!csr_is_irq && !s_is_irq_start) begin - mstatus_to_id(); + if(trace_id.m_sample_csr_write_in_ex && !csr_is_irq && !s_is_irq_start) begin //First cycle after id_ready, csr write is asserted in this cycle + `CSR_FROM_PIPE(id, mstatus) + if(!s_dont_override_mstatus_fs_id) begin + `CSR_FROM_PIPE(id, mstatus_fs) + end `CSR_FROM_PIPE(id, mepc) - if (trace_id.m_csr.mcause_we == '0) begin //for debug purpose - `CSR_FROM_PIPE(id, mcause) + `CSR_FROM_PIPE(id, mcause) + `CSR_FROM_PIPE(id, dscratch0) + `CSR_FROM_PIPE(id, dscratch1) + if(r_pipe_freeze_trace.csr.we && (r_pipe_freeze_trace.csr.addr == CSR_DPC)) begin + `CSR_FROM_PIPE(id, dpc) end + + `CSR_FROM_PIPE(id, mcountinhibit) + + perf_counter_to_trace(trace_id); + ->e_csr_in_ex; end + if(r_pipe_freeze_trace.is_decoding) begin + trace_id.m_sample_csr_write_in_ex = 1'b0; + end + mtvec_to_id(); + + `CSR_FROM_PIPE(id, mip) + `CSR_FROM_PIPE(id, misa) + `CSR_FROM_PIPE(id, mcountinhibit) `CSR_FROM_PIPE(id, mscratch) `CSR_FROM_PIPE(id, mie) @@ -1553,10 +1776,6 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; `CSR_FROM_PIPE(id, frm) `CSR_FROM_PIPE(id, fcsr) - if (r_pipe_freeze_trace.csr.we) begin - `CSR_FROM_PIPE(id, dpc) - end - if (r_pipe_freeze_trace.csr.dcsr_we) begin dcsr_to_id(); end @@ -1577,6 +1796,15 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_ex.m_csr.frm_wmask = '0; trace_ex.m_csr.fcsr_wmask = '0; + if(r_pipe_freeze_trace.ctrl_fsm_cs == XRET_JUMP) begin //xret exit pipeline + tinfo_to_trace(trace_id); + `CSR_FROM_PIPE(id, tdata1) + `CSR_FROM_PIPE(id, tdata2) + send_rvfi(trace_id); + trace_id.m_valid = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; + end + if (r_pipe_freeze_trace.apu_req && r_pipe_freeze_trace.apu_gnt) begin trace_id.m_is_apu = 1'b1; trace_id.m_apu_req_id = cnt_apu_req; @@ -1586,6 +1814,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_apu_req.set_to_apu(); apu_trace_q.push_back(trace_apu_req); trace_id.m_valid = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; if(r_pipe_freeze_trace.apu_rvalid && (cnt_apu_req == cnt_apu_resp)) begin//APU return in the same cycle apu_resp(); @@ -1603,10 +1832,10 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_rd_addr[0] = r_pipe_freeze_trace.ex_reg_addr; trace_id.m_rd_wdata[0] = r_pipe_freeze_trace.ex_reg_wdata; trace_id.m_got_ex_reg = 1'b1; - end else if (!trace_ex.m_valid & r_pipe_freeze_trace.rf_we_wb & !trace_id.m_ex_fw) begin + end else if (!trace_ex.m_valid & s_rf_we_wb_adjusted & !trace_id.m_ex_fw) begin trace_id.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; trace_id.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - end else if (r_pipe_freeze_trace.rf_we_wb) begin + end else if (s_rf_we_wb_adjusted) begin trace_id.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; trace_id.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; trace_id.m_2_rd_insn = 1'b1; @@ -1621,19 +1850,16 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_mem.addr = r_pipe_freeze_trace.data_addr_pmp; if (r_pipe_freeze_trace.data_misaligned) begin cnt_data_req = cnt_data_req + 1; + trace_id.m_mem_req_id[0] = cnt_data_req; end + if (!r_pipe_freeze_trace.data_we_ex) begin trace_id.m_is_load = 1'b1; trace_id.m_mem.wmask = be_to_mask(r_pipe_freeze_trace.lsu_data_be); //'1; - if (r_pipe_freeze_trace.data_misaligned) begin - trace_id.m_data_missaligned = 1'b1; - trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; - trace_id.m_mem_req_id[0] = cnt_data_req; - trace_id.m_mem_req_id_valid[1] = 1'b1; - end end else begin trace_id.m_mem.rmask = be_to_mask(r_pipe_freeze_trace.lsu_data_be); //'1; end + if (trace_id.m_got_ex_reg) begin // Shift index 0 to 1 trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; trace_id.m_mem_req_id[0] = 0; @@ -1644,6 +1870,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; hwloop_to_id(); trace_ex.move_down_pipe(trace_id); // The instruction moves forward from ID to EX trace_id.m_valid = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; ->e_id_to_ex_1; end else if (r_pipe_freeze_trace.ex_reg_we && r_pipe_freeze_trace.rf_alu_we_ex) begin @@ -1667,9 +1894,6 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; if (s_new_valid_insn) begin // There is a new valid instruction if (trace_id.m_valid) begin if (trace_ex.m_valid) begin - if (!trace_ex.m_csr.got_minstret) begin - minstret_to_ex(); - end if (trace_wb.m_valid) begin send_rvfi(trace_ex); ->e_send_rvfi_trace_ex_4; @@ -1692,15 +1916,10 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_mem.addr = r_pipe_freeze_trace.data_addr_pmp; if (r_pipe_freeze_trace.data_misaligned) begin cnt_data_req = cnt_data_req + 1; + trace_id.m_mem_req_id[0] = cnt_data_req; end if (!r_pipe_freeze_trace.data_we_ex) begin trace_id.m_is_load = 1'b1; - if (r_pipe_freeze_trace.data_misaligned) begin - trace_id.m_data_missaligned = 1'b1; - trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; - trace_id.m_mem_req_id[0] = cnt_data_req; - trace_id.m_mem_req_id_valid[1] = 1'b1; - end end if (trace_id.m_got_ex_reg) begin // Shift index 0 to 1 trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; @@ -1708,7 +1927,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_mem_req_id_valid[0] = 1'b0; trace_id.m_mem_req_id_valid[1] = 1'b1; end - end else if (r_pipe_freeze_trace.rf_we_wb && !r_pipe_freeze_trace.ex_reg_we) begin + end else if (s_rf_we_wb_adjusted && !r_pipe_freeze_trace.ex_reg_we) begin trace_id.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; trace_id.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; end @@ -1716,6 +1935,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; hwloop_to_id(); trace_ex.move_down_pipe(trace_id); trace_id.m_valid = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; ->e_id_to_ex_2; end if_to_id(); @@ -1733,13 +1953,28 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end //IF_STAGE - if (r_pipe_freeze_trace.if_valid && r_pipe_freeze_trace.if_ready) begin - if(trace_if.m_valid && r_pipe_freeze_trace.id_valid && r_pipe_freeze_trace.id_ready && !trace_id.m_valid && r_pipe_freeze_trace.ebrk_insn_dec) begin - if_to_id(); - trace_id.m_is_ebreak = '1; //trace_if.m_is_ebreak; - ->e_if_2_id_2; + if(trace_if.m_valid) begin + if(r_pipe_freeze_trace.is_illegal && r_pipe_freeze_trace.is_decoding) begin + trace_if.m_is_illegal = 1'b1; + end + end + + if (r_pipe_freeze_trace.if_valid && r_pipe_freeze_trace.if_ready && r_pipe_freeze_trace.instr_valid_if) begin + if (trace_if.m_valid) begin + if (r_pipe_freeze_trace.id_valid && r_pipe_freeze_trace.id_ready && !trace_id.m_valid && r_pipe_freeze_trace.ebrk_insn_dec) begin + if_to_id(); + trace_id.m_is_ebreak = '1; //trace_if.m_is_ebreak; + ->e_if_2_id_2; + end else if (trace_if.m_is_illegal) begin + if_to_id(); + ->e_if_2_id_3; + end else if (r_pipe_freeze_trace.ecall_insn_dec) begin + if_to_id(); + ->e_if_2_id_4; + end end + trace_if.m_insn = r_pipe_freeze_trace.instr_if; //Instr comes from if, buffer for one cycle trace_if.m_pc_rdata = r_pipe_freeze_trace.pc_if; trace_if.m_dbg_taken = is_dbg_taken; @@ -1754,6 +1989,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; mstatus_to_id(); `CSR_FROM_PIPE(id, mepc) `CSR_FROM_PIPE(id, mcause) + ->e_csr_irq; end if (!s_id_done && r_pipe_freeze_trace.is_decoding) begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_rvfi_trace.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_rvfi_trace.sv index bfb02579..bdbe6127 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_rvfi_trace.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_rvfi_trace.sv @@ -1,26 +1,31 @@ -// Copyright (c) 2020 OpenHW Group +// Copyright 2024 Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. // You may obtain a copy of the License at // -// https://solderpad.org/licenses/ +// https://solderpad.org/licenses/SHL-2.1/ // -// Unless required by applicable law or agreed to in writing, software +// Unless required by applicable law or agreed to in writing, any work // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 -// CV32E40P RVFI interface -// -// Contributors: Halfdan Bechmann, Silicon Labs -// Yoann Pruvost, Dolphin Design +//////////////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Halfdan Bechmann, Silicon Labs // +// Yoann Pruvost, Dolphin Design // +// // +// Description: CV32E40P RVFI tracer // +// // +//////////////////////////////////////////////////////////////////////////////////// module cv32e40px_rvfi_trace import cv32e40px_pkg::*; + import cv32e40px_rvfi_pkg::*; #( parameter FPU = 0, parameter ZFINX = 0 @@ -32,9 +37,14 @@ module cv32e40px_rvfi_trace input logic [31:0] imm_s3_type, - input logic rvfi_valid, - input logic [31:0] rvfi_insn, - input logic [31:0] rvfi_pc_rdata, + input logic rvfi_valid, + input logic [31:0] rvfi_insn, + input integer rvfi_start_cycle, + input time rvfi_start_time, + input integer rvfi_stop_cycle, + input time rvfi_stop_time, + input logic [31:0] rvfi_pc_rdata, + input rvfi_trap_t rvfi_trap, input logic [ 4:0] rvfi_rd_addr [1:0], input logic [31:0] rvfi_rd_wdata[1:0], @@ -42,6 +52,7 @@ module cv32e40px_rvfi_trace input logic rvfi_frd_wvalid[1:0], input logic [ 4:0] rvfi_frd_addr [1:0], input logic [31:0] rvfi_frd_wdata [1:0], + input logic rvfi_2_rd, input logic [ 4:0] rvfi_rs1_addr, input logic [ 4:0] rvfi_rs2_addr, @@ -61,8 +72,8 @@ module cv32e40px_rvfi_trace input logic [31:0] rvfi_frs3_rdata, input logic [31:0] rvfi_mem_addr, - input logic [ 3:0] rvfi_mem_rmask, - input logic [ 3:0] rvfi_mem_wmask, + input logic [31:0] rvfi_mem_rmask, + input logic [31:0] rvfi_mem_wmask, input logic [31:0] rvfi_mem_rdata, input logic [31:0] rvfi_mem_wdata ); @@ -74,7 +85,7 @@ module cv32e40px_rvfi_trace integer f; //file pointer string fn; - integer cycles; + // integer cycles; string info_tag; logic is_compressed; @@ -125,7 +136,13 @@ module cv32e40px_rvfi_trace rs3_value = rvfi_rs3_rdata; end - if (rvfi_frd_wvalid[0]) begin + if (rvfi_2_rd) begin + if (rvfi_frd_wvalid[1]) begin + rd = {1'b1, rvfi_frd_addr[1]}; + end else begin + rd = {1'b0, rvfi_rd_addr[1]}; + end + end else if (rvfi_frd_wvalid[0]) begin rd = {1'b1, rvfi_frd_addr[0]}; end else begin rd = {1'b0, rvfi_rd_addr[0]}; @@ -134,57 +151,69 @@ module cv32e40px_rvfi_trace assign rs4 = rs3; - assign imm_i_type = {{20{rvfi_insn[31]}}, rvfi_insn[31:20]}; - assign imm_iz_type = {20'b0, rvfi_insn[31:20]}; - assign imm_s_type = {{20{rvfi_insn[31]}}, rvfi_insn[31:25], rvfi_insn[11:7]}; + cv32e40p_compressed_decoder #( + .FPU(FPU) + ) rvfi_trace_decompress_i ( + .instr_i(rvfi_insn), + .instr_o(decomp_insn), + .is_compressed_o(is_compressed) + ); + + assign imm_i_type = {{20{decomp_insn[31]}}, decomp_insn[31:20]}; + assign imm_iz_type = {20'b0, decomp_insn[31:20]}; + assign imm_s_type = {{20{decomp_insn[31]}}, decomp_insn[31:25], decomp_insn[11:7]}; assign imm_sb_type = { - {19{rvfi_insn[31]}}, rvfi_insn[31], rvfi_insn[7], rvfi_insn[30:25], rvfi_insn[11:8], 1'b0 + {19{decomp_insn[31]}}, + decomp_insn[31], + decomp_insn[7], + decomp_insn[30:25], + decomp_insn[11:8], + 1'b0 }; - assign imm_u_type = {rvfi_insn[31:12], 12'b0}; + assign imm_u_type = {decomp_insn[31:12], 12'b0}; assign imm_uj_type = { - {12{rvfi_insn[31]}}, rvfi_insn[19:12], rvfi_insn[20], rvfi_insn[30:21], 1'b0 + {12{decomp_insn[31]}}, decomp_insn[19:12], decomp_insn[20], decomp_insn[30:21], 1'b0 }; - assign imm_z_type = '0; //{27'b0, rvfi_insn[REG_S1_MSB:REG_S1_LSB]}; + assign imm_z_type = '0; //{27'b0, decomp_insn[REG_S1_MSB:REG_S1_LSB]}; - assign imm_s2_type = {27'b0, rvfi_insn[24:20]}; + assign imm_s2_type = {27'b0, decomp_insn[24:20]}; assign imm_vs_type = '0; assign imm_vu_type = '0; assign imm_shuffle_type = '0; assign imm_clip_type = '0; - cv32e40px_compressed_decoder #( - .FPU(FPU) - ) rvfi_trace_decompress_i ( - .instr_i(rvfi_insn), - .instr_o(decomp_insn), - .is_compressed_o(is_compressed) - ); - `include "cv32e40px_instr_trace.svh" instr_trace_t trace_retire; function instr_trace_t trace_new_instr(); instr_trace_t trace; trace = new(); - trace.init(.cycles(cycles), .pc(rvfi_pc_rdata), .compressed(is_compressed), + trace.external_time = 1; + trace.simtime = rvfi_start_time - 1ns; + trace.stoptime = rvfi_stop_time; + trace.stopcycles = rvfi_stop_cycle; + trace.ctx = (rvfi_trap.trap) ? "(C)" : ""; + trace.init(.cycles(rvfi_start_cycle), .pc(rvfi_pc_rdata), .compressed(is_compressed), .instr(decomp_insn)); return trace; endfunction : trace_new_instr function void apply_reg_write(); foreach (trace_retire.regs_write[i]) begin - if (rvfi_frd_wvalid[0] && (trace_retire.regs_write[i].addr == {1'b1, rvfi_frd_addr[0]})) begin - trace_retire.regs_write[i].value = rvfi_frd_wdata[0]; - end else if (trace_retire.regs_write[i].addr == rvfi_rd_addr[0]) begin - trace_retire.regs_write[i].value = rvfi_rd_wdata[0]; - end if (rvfi_frd_wvalid[1] && (trace_retire.regs_write[i].addr == {1'b1, rvfi_frd_addr[1]})) begin trace_retire.regs_write[i].value = rvfi_frd_wdata[1]; end else if (trace_retire.regs_write[i].addr == rvfi_rd_addr[1]) begin trace_retire.regs_write[i].value = rvfi_rd_wdata[1]; end end + foreach (trace_retire.regs_write[i]) begin + if (rvfi_frd_wvalid[0] && (trace_retire.regs_write[i].addr == {1'b1, rvfi_frd_addr[0]})) begin + trace_retire.regs_write[i].value = rvfi_frd_wdata[0]; + end else if (trace_retire.regs_write[i].addr == rvfi_rd_addr[0]) begin + trace_retire.regs_write[i].value = rvfi_rd_wdata[0]; + end + end endfunction : apply_reg_write function void apply_mem_access(); @@ -202,11 +231,9 @@ instr_trace_t trace_retire; end endfunction : apply_mem_access - // cycle counter - always_ff @(posedge clk_i, negedge rst_ni) begin - if (rst_ni == 1'b0) cycles <= 0; - else cycles <= cycles + 1; - end + string insn_disas; + logic [31:0] insn_pc; + logic [31:0] insn_val; always @(posedge clk_i) begin if (rvfi_valid) begin @@ -214,6 +241,9 @@ instr_trace_t trace_retire; apply_reg_write(); apply_mem_access(); trace_retire.printInstrTrace(); + insn_disas = trace_retire.str; + insn_pc = trace_retire.pc; + insn_val = trace_retire.instr; end end @@ -223,7 +253,8 @@ instr_trace_t trace_retire; $sformat(info_tag, "CORE_TRACER %2d", hart_id_i); $display("[%s] Output filename is: %s", info_tag, fn); f = $fopen(fn, "w"); - $fwrite(f, "Time\tCycle\tPC\tInstr\tDecoded instruction\tRegister and memory contents\n"); + $fwrite(f, + " Time Cycle PC Instr Ctx Decoded instruction Register and memory contents Stop cycle Stop time\n"); end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_tb_wrapper.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_tb_wrapper.sv index 1b40b80e..c14b131b 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_tb_wrapper.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_tb_wrapper.sv @@ -1,45 +1,49 @@ -// Copyright (c) 2020 OpenHW Group +// Copyright 2024 Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. // You may obtain a copy of the License at // -// https://solderpad.org/licenses/ +// https://solderpad.org/licenses/SHL-2.1/ // -// Unless required by applicable law or agreed to in writing, software +// Unless required by applicable law or agreed to in writing, any work // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 -// Wrapper for a cv32e40px, containing cv32e40px_top, and rvfi_tracer -// -// Contributors: Davide Schiavone, OpenHW Group -// Yoann Pruvost, Dolphin Design +//////////////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Davide Schiavone, OpenHW Group // +// Yoann Pruvost, Dolphin Design // +// // +// Description: Test-bench wrapper for cv32e40px_top, tracer and and rvfi_tracer // +// // +//////////////////////////////////////////////////////////////////////////////////// -`ifdef CV32E40P_ASSERT_ON +`ifdef CV32E40PX_ASSERT_ON `include "cv32e40px_prefetch_controller_sva.sv" `endif -`ifdef CV32E40P_CORE_LOG +`ifdef CV32E40PX_CORE_LOG `include "cv32e40px_core_log.sv" `endif -`ifdef CV32E40P_APU_TRACE +`ifdef CV32E40PX_APU_TRACE `include "cv32e40px_apu_tracer.sv" `endif -`ifdef CV32E40P_TRACE_EXECUTION +`ifdef CV32E40PX_TRACE_EXECUTION `include "cv32e40px_tracer.sv" `endif -`ifdef CV32E40P_RVFI +`ifdef CV32E40PX_RVFI `include "cv32e40px_rvfi.sv" `endif -`ifdef CV32E40P_RVFI_TRACE_EXECUTION +`ifdef CV32E40PX_RVFI_TRACE_EXECUTION `include "cv32e40px_rvfi_trace.sv" `endif @@ -101,7 +105,7 @@ module cv32e40px_tb_wrapper output logic core_sleep_o ); -`ifdef CV32E40P_ASSERT_ON +`ifdef CV32E40PX_ASSERT_ON // RTL Assertions bind cv32e40px_prefetch_controller: @@ -114,9 +118,9 @@ module cv32e40px_tb_wrapper .FIFO_ADDR_DEPTH(FIFO_ADDR_DEPTH) ) prefetch_controller_sva (.*); -`endif // CV32E40P_ASSERT_ON +`endif // CV32E40PX_ASSERT_ON -`ifdef CV32E40P_CORE_LOG +`ifdef CV32E40PX_CORE_LOG cv32e40px_core_log #( .COREV_PULP (COREV_PULP), .COREV_CLUSTER (COREV_CLUSTER), @@ -130,9 +134,9 @@ module cv32e40px_tb_wrapper .hart_id_i (cv32e40px_top_i.core_i.hart_id_i), .pc_id_i (cv32e40px_top_i.core_i.pc_id) ); -`endif // CV32E40P_CORE_LOG +`endif // CV32E40PX_CORE_LOG -`ifdef CV32E40P_APU_TRACE +`ifdef CV32E40PX_APU_TRACE cv32e40px_apu_tracer apu_tracer_i ( .clk_i (cv32e40px_top_i.core_i.rst_ni), .rst_n (cv32e40px_top_i.core_i.clk_i), @@ -143,7 +147,7 @@ module cv32e40px_tb_wrapper ); `endif -`ifdef CV32E40P_TRACE_EXECUTION +`ifdef CV32E40PX_TRACE_EXECUTION cv32e40px_tracer #( .FPU (FPU), .ZFINX(ZFINX) @@ -210,11 +214,11 @@ module cv32e40px_tb_wrapper .apu_en_i (cv32e40px_top_i.apu_req), .apu_singlecycle_i(cv32e40px_top_i.core_i.ex_stage_i.apu_singlecycle), .apu_multicycle_i (cv32e40px_top_i.core_i.ex_stage_i.apu_multicycle), - .apu_rvalid_i (cv32e40px_top_i.apu_rvalid) + .apu_rvalid_i (cv32e40px_top_i.core_i.ex_stage_i.apu_valid) ); `endif -`ifdef CV32E40P_RVFI +`ifdef CV32E40PX_RVFI logic [1:0][31:0] hwlp_start_q; logic [1:0][31:0] hwlp_end_q; logic [1:0][31:0] hwlp_counter_q; @@ -234,8 +238,9 @@ module cv32e40px_tb_wrapper endgenerate cv32e40px_rvfi #( - .FPU (FPU), - .ZFINX(ZFINX) + .FPU(FPU), + .ZFINX(ZFINX), + .NUM_MHPMCOUNTERS(NUM_MHPMCOUNTERS) ) rvfi_i ( .clk_i (cv32e40px_top_i.core_i.clk_i), .rst_ni(cv32e40px_top_i.core_i.rst_ni), @@ -272,13 +277,19 @@ module cv32e40px_tb_wrapper .rs1_addr_id_i (cv32e40px_top_i.core_i.id_stage_i.regfile_addr_ra_id), .rs2_addr_id_i (cv32e40px_top_i.core_i.id_stage_i.regfile_addr_rb_id), + .rs3_addr_id_i (cv32e40px_top_i.core_i.id_stage_i.regfile_addr_rc_id), .operand_a_fw_id_i (cv32e40px_top_i.core_i.id_stage_i.operand_a_fw_id), .operand_b_fw_id_i (cv32e40px_top_i.core_i.id_stage_i.operand_b_fw_id), + .operand_c_fw_id_i (cv32e40px_top_i.core_i.id_stage_i.operand_c_fw_id), // .instr (cv32e40px_top_i.core_i.id_stage_i.instr ), .is_compressed_id_i(cv32e40px_top_i.core_i.id_stage_i.is_compressed_i), .ebrk_insn_dec_i (cv32e40px_top_i.core_i.id_stage_i.ebrk_insn_dec), - .csr_cause_i (cv32e40px_top_i.core_i.csr_cause), - .debug_csr_save_i (cv32e40px_top_i.core_i.debug_csr_save), + .ecall_insn_dec_i (cv32e40px_top_i.core_i.id_stage_i.ecall_insn_dec), + .mret_insn_dec_i (cv32e40px_top_i.core_i.id_stage_i.mret_insn_dec), + .mret_dec_i (cv32e40px_top_i.core_i.id_stage_i.mret_dec), + + .csr_cause_i (cv32e40px_top_i.core_i.csr_cause), + .debug_csr_save_i(cv32e40px_top_i.core_i.debug_csr_save), // HWLOOP regs .hwlp_start_q_i (hwlp_start_q), @@ -298,14 +309,16 @@ module cv32e40px_tb_wrapper .apu_multicycle_i (cv32e40px_top_i.core_i.ex_stage_i.apu_multicycle), .wb_contention_lsu_i(cv32e40px_top_i.core_i.ex_stage_i.wb_contention_lsu), .wb_contention_i (cv32e40px_top_i.core_i.ex_stage_i.wb_contention), - + .regfile_we_lsu_i (cv32e40px_top_i.core_i.ex_stage_i.regfile_we_lsu), // .rf_we_alu_i (cv32e40px_top_i.core_i.id_stage_i.regfile_alu_we_fw_i), // .rf_addr_alu_i (cv32e40px_top_i.core_i.id_stage_i.regfile_alu_waddr_fw_i), // .rf_wdata_alu_i (cv32e40px_top_i.core_i.id_stage_i.regfile_alu_wdata_fw_i), + .mult_ready_i (cv32e40px_top_i.core_i.ex_stage_i.mult_ready), + .alu_ready_i (cv32e40px_top_i.core_i.ex_stage_i.alu_ready), //// WB probes //// - .wb_valid_i(cv32e40px_top_i.core_i.wb_valid), - + .wb_valid_i (cv32e40px_top_i.core_i.wb_valid), + .wb_ready_i (cv32e40px_top_i.core_i.lsu_ready_wb), //// LSU probes //// .data_we_ex_i (cv32e40px_top_i.core_i.data_we_ex), .data_atop_ex_i (cv32e40px_top_i.core_i.data_atop_ex), @@ -325,6 +338,8 @@ module cv32e40px_tb_wrapper .lsu_ready_ex_i (cv32e40px_top_i.core_i.lsu_ready_ex), .lsu_ready_wb_i (cv32e40px_top_i.core_i.lsu_ready_wb), + .lsu_data_be_i(cv32e40px_top_i.core_i.load_store_unit_i.data_be), + .data_req_pmp_i(cv32e40px_top_i.core_i.data_req_pmp), .data_gnt_pmp_i(cv32e40px_top_i.core_i.data_gnt_pmp), .data_rvalid_i(cv32e40px_top_i.core_i.data_rvalid_i), @@ -339,11 +354,12 @@ module cv32e40px_tb_wrapper .rf_we_wb_i(cv32e40px_top_i.core_i.id_stage_i.regfile_we_wb_i), .rf_addr_wb_i(cv32e40px_top_i.core_i.id_stage_i.regfile_waddr_wb_i), .rf_wdata_wb_i(cv32e40px_top_i.core_i.id_stage_i.regfile_wdata_wb_i), + .regfile_alu_we_ex_i(cv32e40px_top_i.core_i.id_stage_i.regfile_alu_we_ex_o), // APU .apu_req_i (cv32e40px_top_i.core_i.apu_req_o), .apu_gnt_i (cv32e40px_top_i.core_i.apu_gnt_i), - .apu_rvalid_i(cv32e40px_top_i.core_i.apu_rvalid_i), + .apu_rvalid_i(cv32e40px_top_i.core_i.ex_stage_i.apu_valid), // Controller FSM probes .ctrl_fsm_cs_i(cv32e40px_top_i.core_i.id_stage_i.controller_i.ctrl_fsm_cs), @@ -355,6 +371,8 @@ module cv32e40px_tb_wrapper .csr_we_i (cv32e40px_top_i.core_i.cs_registers_i.csr_we_int), .csr_wdata_int_i(cv32e40px_top_i.core_i.cs_registers_i.csr_wdata_int), + .csr_fregs_we_i(cv32e40px_top_i.core_i.cs_registers_i.fregs_we_i), + .csr_mstatus_n_i (cv32e40px_top_i.core_i.cs_registers_i.mstatus_n), .csr_mstatus_q_i (cv32e40px_top_i.core_i.cs_registers_i.mstatus_q), .csr_mstatus_fs_n_i(cv32e40px_top_i.core_i.cs_registers_i.mstatus_fs_n), @@ -367,6 +385,10 @@ module cv32e40px_tb_wrapper .csr_tdata1_q_i (cv32e40px_top_i.core_i.cs_registers_i.tmatch_control_rdata),//gen_trigger_regs.tmatch_control_exec_q ), .csr_tdata1_we_i(cv32e40px_top_i.core_i.cs_registers_i.gen_trigger_regs.tmatch_control_we), + .csr_tdata2_n_i (cv32e40px_top_i.core_i.cs_registers_i.tmatch_value_rdata),//csr_wdata_int ), + .csr_tdata2_q_i (cv32e40px_top_i.core_i.cs_registers_i.tmatch_value_rdata),//gen_trigger_regs.tmatch_control_exec_q ), + .csr_tdata2_we_i(cv32e40px_top_i.core_i.cs_registers_i.gen_trigger_regs.tmatch_value_we), + .csr_tinfo_n_i({16'h0, cv32e40px_top_i.core_i.cs_registers_i.tinfo_types}), .csr_tinfo_q_i({16'h0, cv32e40px_top_i.core_i.cs_registers_i.tinfo_types}), @@ -382,6 +404,9 @@ module cv32e40px_tb_wrapper .csr_mcountinhibit_n_i (cv32e40px_top_i.core_i.cs_registers_i.mcountinhibit_n), .csr_mcountinhibit_we_i(cv32e40px_top_i.core_i.cs_registers_i.mcountinhibit_we), + .csr_mhpmevent_n_i(cv32e40px_top_i.core_i.cs_registers_i.mhpmevent_n), + .csr_mhpmevent_q_i(cv32e40px_top_i.core_i.cs_registers_i.mhpmevent_q), + .csr_mhpmevent_we_i(cv32e40px_top_i.core_i.cs_registers_i.mhpmevent_we), .csr_mscratch_q_i(cv32e40px_top_i.core_i.cs_registers_i.mscratch_q), .csr_mscratch_n_i(cv32e40px_top_i.core_i.cs_registers_i.mscratch_n), .csr_mepc_q_i(cv32e40px_top_i.core_i.cs_registers_i.mepc_q), @@ -424,7 +449,7 @@ module cv32e40px_tb_wrapper ); `endif -`ifdef CV32E40P_RVFI_TRACE_EXECUTION +`ifdef CV32E40PX_RVFI_TRACE_EXECUTION bind cv32e40px_rvfi: rvfi_i cv32e40px_rvfi_trace #( .FPU (FPU), .ZFINX(ZFINX) @@ -437,22 +462,38 @@ module cv32e40px_tb_wrapper .rvfi_valid(rvfi_valid), .rvfi_insn(rvfi_insn), + .rvfi_start_cycle(rvfi_start_cycle), + .rvfi_start_time(rvfi_start_time), + .rvfi_stop_cycle(rvfi_stop_cycle), + .rvfi_stop_time(rvfi_stop_time), .rvfi_pc_rdata(rvfi_pc_rdata), + .rvfi_trap(rvfi_trap), .rvfi_rd_addr(rvfi_rd_addr), .rvfi_rd_wdata(rvfi_rd_wdata), .rvfi_frd_wvalid(rvfi_frd_wvalid), .rvfi_frd_addr(rvfi_frd_addr), .rvfi_frd_wdata(rvfi_frd_wdata), + .rvfi_2_rd(rvfi_2_rd), .rvfi_rs1_addr(rvfi_rs1_addr), .rvfi_rs2_addr(rvfi_rs2_addr), + .rvfi_rs3_addr(rvfi_rs3_addr), .rvfi_rs1_rdata(rvfi_rs1_rdata), .rvfi_rs2_rdata(rvfi_rs2_rdata), + .rvfi_rs3_rdata(rvfi_rs3_rdata), .rvfi_frs1_addr(rvfi_frs1_addr), .rvfi_frs2_addr(rvfi_frs2_addr), + .rvfi_frs3_addr(rvfi_frs3_addr), .rvfi_frs1_rvalid(rvfi_frs1_rvalid), .rvfi_frs2_rvalid(rvfi_frs2_rvalid), + .rvfi_frs3_rvalid(rvfi_frs3_rvalid), .rvfi_frs1_rdata(rvfi_frs1_rdata), - .rvfi_frs2_rdata(rvfi_frs2_rdata) + .rvfi_frs2_rdata(rvfi_frs2_rdata), + .rvfi_frs3_rdata(rvfi_frs3_rdata), + .rvfi_mem_addr(rvfi_mem_addr), + .rvfi_mem_rmask(rvfi_mem_rmask), + .rvfi_mem_wmask(rvfi_mem_wmask), + .rvfi_mem_rdata(rvfi_mem_rdata), + .rvfi_mem_wdata(rvfi_mem_wdata) ); `endif // Instantiate the Core and the optinal FPU diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_tracer.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_tracer.sv index c0c13315..9254ccea 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_tracer.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/cv32e40px_tracer.sv @@ -1,24 +1,26 @@ -// Copyright (c) 2020 OpenHW Group -// -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://solderpad.org/licenses/ -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 - -// Traces the executed instructions -// -// Contributors: Andreas Traber, ETHZ -// Davide Schiavone, OpenHW Group -// Pascal Gouedo, Dolphin Design +// Copyright 2018 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Andreas Traber - atraber@iis.ee.ethz.ch // +// // +// Additional contributions by: // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// // +// Design Name: RISC-V Tracer // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Traces the executed instructions // +// // +//////////////////////////////////////////////////////////////////////////////// `ifdef CV32E40P_TRACE_EXECUTION @@ -183,7 +185,8 @@ module cv32e40px_tracer $sformat(info_tag, "CORE_TRACER %2d", hart_id_i); $display("[%s] Output filename is: %s", info_tag, fn); f = $fopen(fn, "w"); - $fwrite(f, "Time\tCycle\tPC\tInstr\tDecoded instruction\tRegister and memory contents\n"); + $fwrite(f, + " Time Cycle PC Instr Ctx Decoded instruction Register and memory contents\n"); end //initial begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/include/cv32e40px_rvfi_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/include/cv32e40px_rvfi_pkg.sv index 9a131a68..5a43daf6 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/include/cv32e40px_rvfi_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/include/cv32e40px_rvfi_pkg.sv @@ -1,24 +1,28 @@ -// Copyright (c) 2020 OpenHW Group +// Copyright 2024 Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. // You may obtain a copy of the License at // -// https://solderpad.org/licenses/ +// https://solderpad.org/licenses/SHL-2.1/ // -// Unless required by applicable law or agreed to in writing, software +// Unless required by applicable law or agreed to in writing, any work // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 -// Includes to print info about the RVFI output -// -// Contributors: Davide Schiavone, OpenHW Group -// Halfdan Bechmann, Silicon Labs -// Yoann Pruvost, Dolphin Design +//////////////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Davide Schiavone, OpenHW Group // +// Halfdan Bechmann, Silicon Labs // +// Yoann Pruvost, Dolphin Design // +// // +// Description: Package to print info on RVFI interface // +// // +//////////////////////////////////////////////////////////////////////////////////// package cv32e40px_rvfi_pkg; import cv32e40px_pkg::*; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/include/cv32e40px_tracer_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/include/cv32e40px_tracer_pkg.sv index 40edce03..2046dd74 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/include/cv32e40px_tracer_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/include/cv32e40px_tracer_pkg.sv @@ -1,23 +1,13 @@ -// Copyright (c) 2020 OpenHW Group -// -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://solderpad.org/licenses/ -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 - -// Tracer package -// -// Contributors: Steve Richmond, Silicon Labs -// Pascal Gouedo, Dolphin Design +// Copyright 2018 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + package cv32e40px_tracer_pkg; import cv32e40px_pkg::*; @@ -196,8 +186,8 @@ package cv32e40px_tracer_pkg; parameter INSTR_CVEND0 = {12'b000000000000, 5'b?, 3'b100, 4'b0011, 1'b0, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNTI0 = {12'b?, 5'b00000, 3'b100, 4'b0100, 1'b0, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNT0 = {12'b000000000000, 5'b?, 3'b100, 4'b0101, 1'b0, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUPI0 = {12'b?, 5'b00000, 3'b100, 4'b0110, 1'b0, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUP0 = {12'b?, 5'b00000, 3'b100, 4'b0111, 1'b0, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUPI0 = {17'b?, 3'b100, 4'b0110, 1'b0, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUP0 = {12'b?, 5'b?, 3'b100, 4'b0111, 1'b0, OPCODE_CUSTOM_1}; parameter INSTR_CVSTARTI1 = {12'b?, 5'b00000, 3'b100, 4'b0000, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_CVSTART1 = {12'b000000000000, 5'b?, 3'b100, 4'b0001, 1'b1, OPCODE_CUSTOM_1}; @@ -205,8 +195,8 @@ package cv32e40px_tracer_pkg; parameter INSTR_CVEND1 = {12'b000000000000, 5'b?, 3'b100, 4'b0011, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNTI1 = {12'b?, 5'b00000, 3'b100, 4'b0100, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNT1 = {12'b000000000000, 5'b?, 3'b100, 4'b0101, 1'b1, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUPI1 = {12'b?, 5'b00000, 3'b100, 4'b0110, 1'b1, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUP1 = {12'b?, 5'b00000, 3'b100, 4'b0111, 1'b1, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUPI1 = {17'b?, 3'b100, 4'b0110, 1'b1, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUP1 = {12'b?, 5'b?, 3'b100, 4'b0111, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_FF1 = {7'b0100001, 5'b0, 5'b?, 3'b011, 5'b?, OPCODE_CUSTOM_1}; @@ -449,8 +439,8 @@ package cv32e40px_tracer_pkg; parameter INSTR_CVSHUFFLE2H = {5'b11100, 1'b0, 1'b0, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; parameter INSTR_CVSHUFFLE2B = {5'b11100, 1'b0, 1'b0, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_CUSTOM_3}; - parameter INSTR_CVPACK = {5'b11101, 1'b0, 1'b0, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; - parameter INSTR_CVPACKH = {5'b11101, 1'b0, 1'b1, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; + parameter INSTR_CVPACK = {5'b11110, 1'b0, 1'b0, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; + parameter INSTR_CVPACKH = {5'b11110, 1'b0, 1'b1, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; parameter INSTR_CVPACKHIB = {5'b11111, 1'b0, 1'b1, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_CUSTOM_3}; parameter INSTR_CVPACKLOB = {5'b11111, 1'b0, 1'b0, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_CUSTOM_3}; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/insn_trace.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/insn_trace.sv index 3db2a7ee..8cdc06d9 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/insn_trace.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/insn_trace.sv @@ -1,5 +1,26 @@ -// Copyright 2022 Dolphin Design -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// Copyright 2024 OpenHW Group and Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//////////////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Yoann Pruvost, Dolphin Design // +// // +// Description: Macros and Functions to print information on RVFI interface // +// // +//////////////////////////////////////////////////////////////////////////////////// `define DEFINE_CSR(CSR_NAME) \ logic ``CSR_NAME``_we; \ @@ -23,6 +44,10 @@ class insn_trace_t; bit m_valid; logic [63:0] m_order; + integer m_start_cycle; + integer m_stop_cycle; + time m_start_time; + time m_stop_time; bit m_skip_order; //next order was used by trap; logic [31:0] m_pc_rdata; logic [31:0] m_insn; @@ -65,12 +90,15 @@ bit m_move_down_pipe; int m_instret_cnt; + int m_instret_smaple_trigger; //We need to sample minstret from csr 2 cycle after id is doen + + bit m_sample_csr_write_in_ex; struct { logic [31:0] addr ; - logic [ 3:0] rmask; + logic [31:0] rmask; logic [31:0] rdata; - logic [ 3:0] wmask; + logic [31:0] wmask; logic [31:0] wdata; } m_mem; @@ -100,9 +128,28 @@ `DEFINE_CSR(mscratch) `DEFINE_CSR(mepc) `DEFINE_CSR(mcause) + `DEFINE_CSR(mcycle) `DEFINE_CSR(minstret) bit got_minstret; - + `DEFINE_CSR(mcycleh) + `DEFINE_CSR(minstreth) + `DEFINE_CSR(cycle) + `DEFINE_CSR(instret) + // bit got_minstret; + `DEFINE_CSR(cycleh) + `DEFINE_CSR(instreth) + + logic [31:0][ 1:0] mhpmcounter_we; + logic [31:0][63:0] mhpmcounter_rdata; + logic [31:0][63:0] mhpmcounter_rmask; + logic [31:0][63:0] mhpmcounter_wdata; + logic [31:0][63:0] mhpmcounter_wmask; + + logic [31:0] mhpmevent_we; + logic [31:0][31:0] mhpmevent_rdata; + logic [31:0][31:0] mhpmevent_rmask; + logic [31:0][31:0] mhpmevent_wdata; + logic [31:0][31:0] mhpmevent_wmask; `DEFINE_CSR(mip) //mnxti //mintstatus @@ -145,32 +192,38 @@ function new(); - this.m_order = 0; - this.m_skip_order = 1'b0; - this.m_valid = 1'b0; - this.m_move_down_pipe = 1'b0; - this.m_data_missaligned = 1'b0; - this.m_got_first_data = 1'b0; - this.m_got_ex_reg = 1'b0; - this.m_intr = '0; - this.m_dbg_taken = 1'b0; - this.m_dbg_cause = '0; - this.m_is_ebreak = '0; - this.m_is_illegal = '0; - this.m_is_irq = '0; - this.m_is_memory = 1'b0; - this.m_is_load = 1'b0; - this.m_is_apu = 1'b0; - this.m_is_apu_ok = 1'b0; - this.m_apu_req_id = 0; - this.m_mem_req_id[0] = 0; - this.m_mem_req_id[1] = 0; - this.m_mem_req_id_valid = '0; - this.m_trap = 1'b0; - this.m_fflags_we_non_apu = 1'b0; - this.m_frm_we_non_apu = 1'b0; - this.m_fcsr_we_non_apu = 1'b0; - this.m_instret_cnt = 0; + this.m_order = 0; + this.m_start_cycle = 0; + this.m_stop_cycle = 0; + this.m_start_time = 0; + this.m_stop_time = 0; + this.m_skip_order = 1'b0; + this.m_valid = 1'b0; + this.m_move_down_pipe = 1'b0; + this.m_data_missaligned = 1'b0; + this.m_got_first_data = 1'b0; + this.m_got_ex_reg = 1'b0; + this.m_intr = '0; + this.m_dbg_taken = 1'b0; + this.m_dbg_cause = '0; + this.m_is_ebreak = '0; + this.m_is_illegal = '0; + this.m_is_irq = '0; + this.m_is_memory = 1'b0; + this.m_is_load = 1'b0; + this.m_is_apu = 1'b0; + this.m_is_apu_ok = 1'b0; + this.m_apu_req_id = 0; + this.m_mem_req_id[0] = 0; + this.m_mem_req_id[1] = 0; + this.m_mem_req_id_valid = '0; + this.m_trap = 1'b0; + this.m_fflags_we_non_apu = 1'b0; + this.m_frm_we_non_apu = 1'b0; + this.m_fcsr_we_non_apu = 1'b0; + this.m_instret_cnt = 0; + this.m_instret_smaple_trigger = 0; + this.m_sample_csr_write_in_ex = 1'b1; endfunction function void get_mnemonic(); @@ -610,12 +663,12 @@ INSTR_CVCMPLEB : this.m_mnemonic = "cv.cmple.b"; INSTR_CVCMPLESCB : this.m_mnemonic = "cv.cmple.sc.b"; INSTR_CVCMPLESCIB : this.m_mnemonic = "cv.cmple.sci.b"; - INSTR_CVCMPGTUH : this.m_mnemonic = "cv.cmptu.h"; - INSTR_CVCMPGTUSCH : this.m_mnemonic = "cv.cmptu.sc.h"; - INSTR_CVCMPGTUSCIH : this.m_mnemonic = "cv.cmptu.sci.h"; - INSTR_CVCMPGTUB : this.m_mnemonic = "cv.cmptu.b"; - INSTR_CVCMPGTUSCB : this.m_mnemonic = "cv.cmptu.sc.b"; - INSTR_CVCMPGTUSCIB : this.m_mnemonic = "cv.cmptu.sci.b"; + INSTR_CVCMPGTUH : this.m_mnemonic = "cv.cmpgtu.h"; + INSTR_CVCMPGTUSCH : this.m_mnemonic = "cv.cmpgtu.sc.h"; + INSTR_CVCMPGTUSCIH : this.m_mnemonic = "cv.cmpgtu.sci.h"; + INSTR_CVCMPGTUB : this.m_mnemonic = "cv.cmpgtu.b"; + INSTR_CVCMPGTUSCB : this.m_mnemonic = "cv.cmpgtu.sc.b"; + INSTR_CVCMPGTUSCIB : this.m_mnemonic = "cv.cmpgtu.sci.b"; INSTR_CVCMPGEUH : this.m_mnemonic = "cv.cmpgeu.h"; INSTR_CVCMPGEUSCH : this.m_mnemonic = "cv.cmpgeu.sc.h"; INSTR_CVCMPGEUSCIH : this.m_mnemonic = "cv.cmpgeu.sci.h"; @@ -844,7 +897,18 @@ `INIT_CSR(mscratch) `INIT_CSR(mepc) `INIT_CSR(mcause) + `INIT_CSR(mcycle) `INIT_CSR(minstret) + `INIT_CSR(mcycleh) + `INIT_CSR(minstreth) + `INIT_CSR(cycle) + `INIT_CSR(instret) + `INIT_CSR(cycleh) + `INIT_CSR(instreth) + this.m_csr.mhpmcounter_we = '0; + this.m_csr.mhpmcounter_wmask = '0; + this.m_csr.mhpmevent_we = '0; + this.m_csr.mhpmevent_wmask = '0; `INIT_CSR(mip) `INIT_CSR(tdata1) `INIT_CSR(tdata2) @@ -872,40 +936,46 @@ this.m_valid = 1'b1; this.m_stage = ID; this.m_order = this.m_order + 64'h1; + this.m_start_cycle = cycles; + this.m_stop_cycle = 0; + this.m_start_time = $time; + this.m_stop_time = 0; if(this.m_skip_order) begin this.m_order = this.m_order + 64'h1; end - this.m_skip_order = 1'b0; - this.m_pc_rdata = r_pipe_freeze_trace.pc_id; - this.m_is_illegal = 1'b0; - this.m_is_irq = 1'b0; - this.m_is_memory = 1'b0; - this.m_is_load = 1'b0; - this.m_is_apu = 1'b0; - this.m_is_apu_ok = 1'b0; - this.m_apu_req_id = 0; - this.m_mem_req_id[0] = 0; - this.m_mem_req_id[1] = 0; - this.m_mem_req_id_valid = '0; - this.m_data_missaligned = 1'b0; - this.m_got_first_data = 1'b0; - this.m_got_ex_reg = 1'b0; - this.m_got_regs_write = 1'b0; - this.m_move_down_pipe = 1'b0; - this.m_instret_cnt = 0; - this.m_rd_addr[0] = '0; - this.m_rd_addr[1] = '0; - this.m_2_rd_insn = 1'b0; - this.m_rs1_addr = '0; - this.m_rs2_addr = '0; - this.m_rs3_addr = '0; - this.m_ex_fw = '0; - this.m_csr.got_minstret = '0; - this.m_dbg_taken = '0; - this.m_trap = 1'b0; - this.m_fflags_we_non_apu = 1'b0; - this.m_frm_we_non_apu = 1'b0; - this.m_fcsr_we_non_apu = 1'b0; + this.m_skip_order = 1'b0; + this.m_pc_rdata = r_pipe_freeze_trace.pc_id; + this.m_is_illegal = 1'b0; + this.m_is_irq = 1'b0; + this.m_is_memory = 1'b0; + this.m_is_load = 1'b0; + this.m_is_apu = 1'b0; + this.m_is_apu_ok = 1'b0; + this.m_apu_req_id = 0; + this.m_mem_req_id[0] = 0; + this.m_mem_req_id[1] = 0; + this.m_mem_req_id_valid = '0; + this.m_data_missaligned = 1'b0; + this.m_got_first_data = 1'b0; + this.m_got_ex_reg = 1'b0; + this.m_got_regs_write = 1'b0; + this.m_move_down_pipe = 1'b0; + this.m_instret_cnt = 0; + this.m_instret_smaple_trigger = 0; + this.m_sample_csr_write_in_ex = 1'b1; + this.m_rd_addr[0] = '0; + this.m_rd_addr[1] = '0; + this.m_2_rd_insn = 1'b0; + this.m_rs1_addr = '0; + this.m_rs2_addr = '0; + this.m_rs3_addr = '0; + this.m_ex_fw = '0; + this.m_csr.got_minstret = '0; + this.m_dbg_taken = '0; + this.m_trap = 1'b0; + this.m_fflags_we_non_apu = 1'b0; + this.m_frm_we_non_apu = 1'b0; + this.m_fcsr_we_non_apu = 1'b0; this.m_csr.mcause_we = '0; if (is_compressed_id_i) begin this.m_insn[31:16] = '0; @@ -944,47 +1014,53 @@ endfunction function void copy_full(insn_trace_t m_source); - this.m_valid = m_source.m_valid; - this.m_stage = m_source.m_stage; - this.m_order = m_source.m_order; - this.m_pc_rdata = m_source.m_pc_rdata; - this.m_insn = m_source.m_insn; - this.m_mnemonic = m_source.m_mnemonic; - this.m_is_memory = m_source.m_is_memory; - this.m_is_load = m_source.m_is_load; - this.m_is_apu = m_source.m_is_apu; - this.m_is_apu_ok = m_source.m_is_apu_ok; - this.m_apu_req_id = m_source.m_apu_req_id; - this.m_mem_req_id = m_source.m_mem_req_id; - this.m_mem_req_id_valid = m_source.m_mem_req_id_valid; - this.m_data_missaligned = m_source.m_data_missaligned; - this.m_got_first_data = m_source.m_got_first_data; - this.m_got_ex_reg = m_source.m_got_ex_reg; - this.m_dbg_taken = m_source.m_dbg_taken; - this.m_dbg_cause = m_source.m_dbg_cause; - this.m_is_ebreak = m_source.m_is_ebreak; - this.m_is_illegal = m_source.m_is_illegal; - this.m_is_irq = m_source.m_is_irq; - this.m_instret_cnt = m_source.m_instret_cnt; - this.m_rs1_addr = m_source.m_rs1_addr; - this.m_rs2_addr = m_source.m_rs2_addr; - this.m_rs3_addr = m_source.m_rs3_addr; - this.m_rs1_rdata = m_source.m_rs1_rdata; - this.m_rs2_rdata = m_source.m_rs2_rdata; - this.m_rs3_rdata = m_source.m_rs3_rdata; - - this.m_ex_fw = m_source.m_ex_fw; - this.m_rd_addr = m_source.m_rd_addr; - this.m_2_rd_insn = m_source.m_2_rd_insn; - this.m_rd_wdata = m_source.m_rd_wdata; - - this.m_intr = m_source.m_intr; - this.m_trap = m_source.m_trap; - this.m_fflags_we_non_apu = m_source.m_fflags_we_non_apu; - this.m_frm_we_non_apu = m_source.m_frm_we_non_apu ; - this.m_fcsr_we_non_apu = m_source.m_fcsr_we_non_apu; - - this.m_mem = m_source.m_mem; + this.m_valid = m_source.m_valid; + this.m_stage = m_source.m_stage; + this.m_order = m_source.m_order; + this.m_start_cycle = m_source.m_start_cycle; + this.m_stop_cycle = m_source.m_stop_cycle; + this.m_start_time = m_source.m_start_time; + this.m_stop_time = m_source.m_stop_time; + this.m_pc_rdata = m_source.m_pc_rdata; + this.m_insn = m_source.m_insn; + this.m_mnemonic = m_source.m_mnemonic; + this.m_is_memory = m_source.m_is_memory; + this.m_is_load = m_source.m_is_load; + this.m_is_apu = m_source.m_is_apu; + this.m_is_apu_ok = m_source.m_is_apu_ok; + this.m_apu_req_id = m_source.m_apu_req_id; + this.m_mem_req_id = m_source.m_mem_req_id; + this.m_mem_req_id_valid = m_source.m_mem_req_id_valid; + this.m_data_missaligned = m_source.m_data_missaligned; + this.m_got_first_data = m_source.m_got_first_data; + this.m_got_ex_reg = m_source.m_got_ex_reg; + this.m_dbg_taken = m_source.m_dbg_taken; + this.m_dbg_cause = m_source.m_dbg_cause; + this.m_is_ebreak = m_source.m_is_ebreak; + this.m_is_illegal = m_source.m_is_illegal; + this.m_is_irq = m_source.m_is_irq; + this.m_instret_cnt = m_source.m_instret_cnt; + this.m_instret_smaple_trigger = m_source.m_instret_smaple_trigger; + this.m_sample_csr_write_in_ex = m_source.m_sample_csr_write_in_ex; + this.m_rs1_addr = m_source.m_rs1_addr; + this.m_rs2_addr = m_source.m_rs2_addr; + this.m_rs3_addr = m_source.m_rs3_addr; + this.m_rs1_rdata = m_source.m_rs1_rdata; + this.m_rs2_rdata = m_source.m_rs2_rdata; + this.m_rs3_rdata = m_source.m_rs3_rdata; + + this.m_ex_fw = m_source.m_ex_fw; + this.m_rd_addr = m_source.m_rd_addr; + this.m_2_rd_insn = m_source.m_2_rd_insn; + this.m_rd_wdata = m_source.m_rd_wdata; + + this.m_intr = m_source.m_intr; + this.m_trap = m_source.m_trap; + this.m_fflags_we_non_apu = m_source.m_fflags_we_non_apu; + this.m_frm_we_non_apu = m_source.m_frm_we_non_apu ; + this.m_fcsr_we_non_apu = m_source.m_fcsr_we_non_apu; + + this.m_mem = m_source.m_mem; //CRS `ASSIGN_CSR(mstatus) `ASSIGN_CSR(mstatus_fs) @@ -995,8 +1071,26 @@ `ASSIGN_CSR(mscratch) `ASSIGN_CSR(mepc) `ASSIGN_CSR(mcause) + `ASSIGN_CSR(mcycle) `ASSIGN_CSR(minstret) this.m_csr.got_minstret = m_source.m_csr.got_minstret; + `ASSIGN_CSR(mcycleh) + `ASSIGN_CSR(minstreth) + `ASSIGN_CSR(cycle) + `ASSIGN_CSR(instret) + // this.m_csr.got_minstret = m_source.m_csr.got_minstret; + `ASSIGN_CSR(cycleh) + `ASSIGN_CSR(instreth) + this.m_csr.mhpmcounter_we = m_source.m_csr.mhpmcounter_we; + this.m_csr.mhpmcounter_rdata = m_source.m_csr.mhpmcounter_rdata; + this.m_csr.mhpmcounter_rmask = m_source.m_csr.mhpmcounter_rmask; + this.m_csr.mhpmcounter_wdata = m_source.m_csr.mhpmcounter_wdata; + this.m_csr.mhpmcounter_wmask = m_source.m_csr.mhpmcounter_wmask; + this.m_csr.mhpmevent_we = m_source.m_csr.mhpmevent_we; + this.m_csr.mhpmevent_rdata = m_source.m_csr.mhpmevent_rdata; + this.m_csr.mhpmevent_rmask = m_source.m_csr.mhpmevent_rmask; + this.m_csr.mhpmevent_wdata = m_source.m_csr.mhpmevent_wdata; + this.m_csr.mhpmevent_wmask = m_source.m_csr.mhpmevent_wmask; `ASSIGN_CSR(mip) `ASSIGN_CSR(tdata1) `ASSIGN_CSR(tdata2) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/pipe_freeze_trace.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/pipe_freeze_trace.sv index 58051ab8..39a16fa6 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/pipe_freeze_trace.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/bhv/pipe_freeze_trace.sv @@ -1,27 +1,29 @@ -// Copyright (c) 2023 OpenHW Group +// Copyright 2024 OpenHW Group and Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. // You may obtain a copy of the License at // -// https://solderpad.org/licenses/ +// https://solderpad.org/licenses/SHL-2.1/ // -// Unless required by applicable law or agreed to in writing, software +// Unless required by applicable law or agreed to in writing, any work // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 -// CV32E40P -// -// Contributors: Yoann Pruvost, Dolphin Design +//////////////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Yoann Pruvost, Dolphin Design // +// // +// Description: Structures, Functions and Task used to store all information // +// coming from the core pipeline at every posedge. // +// Those information will then be processed by RVFI. // +// // +//////////////////////////////////////////////////////////////////////////////////// -/* - * This struct is used to store all information comming from the core at every posedge - * The information will then be processed - */ typedef struct { logic is_decoding; logic is_illegal; @@ -64,6 +66,9 @@ typedef struct { logic is_compressed_id; logic ebrk_insn_dec; + logic ecall_insn_dec; + logic mret_insn_dec; + logic mret_dec; logic [5:0] csr_cause; @@ -112,6 +117,9 @@ typedef struct { logic [31:0] data_wdata_ex; logic lsu_split_q_ex; + logic mult_ready; + logic alu_ready; + //// WB probes //// logic [31:0] pc_wb; logic wb_ready; @@ -198,6 +206,8 @@ typedef struct { logic mcause_we; logic dcsr_we; + logic fregs_we; + logic jvt_we; Status_t mstatus_n; Status_t mstatus_q; @@ -341,6 +351,7 @@ function compute_csr_we(); r_pipe_freeze_trace.csr.fflags_we = 1'b0; r_pipe_freeze_trace.csr.frm_we = 1'b0; r_pipe_freeze_trace.csr.fcsr_we = 1'b0; + r_pipe_freeze_trace.csr.mhpmevent_we = '0; r_pipe_freeze_trace.csr.dpc_we = csr_dpc_we_i; if (r_pipe_freeze_trace.csr.we) begin case (r_pipe_freeze_trace.csr.addr) @@ -348,18 +359,33 @@ function compute_csr_we(); r_pipe_freeze_trace.csr.mstatus_we = 1'b1; r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; end - CSR_MISA: r_pipe_freeze_trace.csr.misa_we = 1'b1; - CSR_MTVEC: r_pipe_freeze_trace.csr.mtvec_we = 1'b1; - CSR_MSCRATCH: r_pipe_freeze_trace.csr.mscratch_we = 1'b1; - CSR_MEPC: r_pipe_freeze_trace.csr.mepc_we = 1'b1; - CSR_MCAUSE: r_pipe_freeze_trace.csr.mcause_we = 1'b1; - CSR_DCSR: r_pipe_freeze_trace.csr.dcsr_we = 1'b1; - CSR_FFLAGS: r_pipe_freeze_trace.csr.fflags_we = 1'b1; - CSR_FRM: r_pipe_freeze_trace.csr.frm_we = 1'b1; - CSR_FCSR: r_pipe_freeze_trace.csr.fcsr_we = 1'b1; - CSR_DPC: r_pipe_freeze_trace.csr.dpc_we = 1'b1; + CSR_MISA: r_pipe_freeze_trace.csr.misa_we = 1'b1; + CSR_MTVEC: r_pipe_freeze_trace.csr.mtvec_we = 1'b1; + CSR_MSCRATCH: r_pipe_freeze_trace.csr.mscratch_we = 1'b1; + CSR_MEPC: r_pipe_freeze_trace.csr.mepc_we = 1'b1; + CSR_MCAUSE: r_pipe_freeze_trace.csr.mcause_we = 1'b1; + CSR_DCSR: r_pipe_freeze_trace.csr.dcsr_we = 1'b1; + CSR_FFLAGS: begin + r_pipe_freeze_trace.csr.fflags_we = 1'b1; + r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; + end + CSR_FRM: begin + r_pipe_freeze_trace.csr.frm_we = 1'b1; + r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; + end + CSR_FCSR: begin + r_pipe_freeze_trace.csr.fcsr_we = 1'b1; + r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; + end + CSR_DPC: r_pipe_freeze_trace.csr.dpc_we = 1'b1; + CSR_DSCRATCH0: r_pipe_freeze_trace.csr.dscratch0_we = 1'b1; + CSR_DSCRATCH1: r_pipe_freeze_trace.csr.dscratch1_we = 1'b1; endcase end + + if (csr_mhpmevent_we_i) begin + r_pipe_freeze_trace.csr.mhpmevent_we[r_pipe_freeze_trace.csr.addr[4:0]] = 1'b1; + end // CSR_MCAUSE: r_pipe_freeze_trace.csr.mcause_we = r_pipe_freeze_trace.csr.mcause_n != r_pipe_freeze_trace.csr.mcause_q; //for debug purpose endfunction /* @@ -416,6 +442,9 @@ task monitor_pipeline(); r_pipe_freeze_trace.jump_target_id = jump_target_id_i; r_pipe_freeze_trace.is_compressed_id = is_compressed_id_i; r_pipe_freeze_trace.ebrk_insn_dec = ebrk_insn_dec_i; + r_pipe_freeze_trace.ecall_insn_dec = ecall_insn_dec_i; + r_pipe_freeze_trace.mret_insn_dec = mret_insn_dec_i; + r_pipe_freeze_trace.mret_dec = mret_dec_i; r_pipe_freeze_trace.csr_cause = csr_cause_i; r_pipe_freeze_trace.debug_csr_save = debug_csr_save_i; r_pipe_freeze_trace.minstret = minstret_i; @@ -462,6 +491,8 @@ task monitor_pipeline(); r_pipe_freeze_trace.data_wdata_ex = data_wdata_ex_i; r_pipe_freeze_trace.lsu_split_q_ex = lsu_split_q_ex_i; + r_pipe_freeze_trace.mult_ready = mult_ready_i; + r_pipe_freeze_trace.alu_ready = alu_ready_i; //// WB probes //// r_pipe_freeze_trace.pc_wb = pc_wb_i; r_pipe_freeze_trace.wb_ready = wb_ready_i; @@ -526,6 +557,8 @@ task monitor_pipeline(); r_pipe_freeze_trace.csr.we = csr_we_i; r_pipe_freeze_trace.csr.wdata_int = csr_wdata_int_i; + r_pipe_freeze_trace.csr.fregs_we = csr_fregs_we_i; + r_pipe_freeze_trace.csr.jvt_we = csr_jvt_we_i; r_pipe_freeze_trace.csr.mstatus_n = csr_mstatus_n_i; r_pipe_freeze_trace.csr.mstatus_q = csr_mstatus_q_i; @@ -550,7 +583,6 @@ task monitor_pipeline(); r_pipe_freeze_trace.csr.mcountinhibit_we = csr_mcountinhibit_we_i; r_pipe_freeze_trace.csr.mhpmevent_n = csr_mhpmevent_n_i; r_pipe_freeze_trace.csr.mhpmevent_q = csr_mhpmevent_q_i; - r_pipe_freeze_trace.csr.mhpmevent_we = csr_mhpmevent_we_i; r_pipe_freeze_trace.csr.mscratch_n = csr_mscratch_n_i; r_pipe_freeze_trace.csr.mscratch_q = csr_mscratch_q_i; r_pipe_freeze_trace.csr.mepc_n = csr_mepc_n_i; @@ -650,10 +682,6 @@ task monitor_pipeline(); if (r_pipe_freeze_trace.csr.fcsr_we) begin r_pipe_freeze_trace.csr.fflags_we = 1'b1; r_pipe_freeze_trace.csr.frm_we = 1'b1; - end else begin - if (r_pipe_freeze_trace.csr.fflags_we || r_pipe_freeze_trace.csr.frm_we) begin - r_pipe_freeze_trace.csr.fcsr_we = 1'b1; - end end if (csr_fcsr_fflags_we_i) begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_controller.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_controller.sv index 6516f932..19e21067 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_controller.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_controller.sv @@ -110,6 +110,10 @@ module cv32e40px_controller import cv32e40px_pkg::*; output logic apu_stall_o, + // X-IF signals + output logic x_branch_or_async_taken_o, + output logic x_control_illegal_reset_o, + // jump/branch signals input logic branch_taken_ex_i, // branch taken signal from EX ALU input logic [1:0] ctrl_transfer_insn_in_id_i, // jump is being calculated in ALU @@ -240,7 +244,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; logic debug_req_q; logic debug_req_pending; - // qualify wfi vs nosleep locally + // qualify wfi vs nosleep locally logic wfi_active; @@ -327,6 +331,9 @@ module cv32e40px_controller import cv32e40px_pkg::*; // ensures that the target is kept constant even if pc_id is no more HWLP_END hwlp_targ_addr_o = ((hwlp_start1_leq_pc && hwlp_end1_geq_pc) && !(hwlp_start0_leq_pc && hwlp_end0_geq_pc)) ? hwlp_start_addr_i[1] : hwlp_start_addr_i[0]; + x_branch_or_async_taken_o = 1'b0; + x_control_illegal_reset_o = 1'b0; + unique case (ctrl_fsm_cs) // We were just reset, wait for fetch_enable RESET: @@ -438,6 +445,8 @@ module cv32e40px_controller import cv32e40px_pkg::*; pc_mux_o = PC_BRANCH; pc_set_o = 1'b1; + x_branch_or_async_taken_o = 1'b1; + // if we want to debug, flush the pipeline // the current_pc_if will take the value of the next instruction to // be executed (NPC) @@ -491,10 +500,12 @@ module cv32e40px_controller import cv32e40px_pkg::*; if ( (debug_req_pending || trigger_match_i) & ~debug_mode_q ) begin //Serving the debug + is_decoding_o = COREV_PULP ? 1'b0 : 1'b1; halt_if_o = 1'b1; halt_id_o = 1'b1; ctrl_fsm_ns = DBG_FLUSH; debug_req_entry_n = 1'b1; + x_branch_or_async_taken_o = 1'b1; end else if (irq_req_ctrl_i && ~debug_mode_q) begin @@ -510,6 +521,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; exc_pc_mux_o = EXC_PC_IRQ; exc_cause_o = irq_id_ctrl_i; csr_irq_sec_o = irq_sec_ctrl_i; + x_branch_or_async_taken_o = 1'b1; // IRQ interface irq_ack_o = 1'b1; @@ -533,6 +545,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; halt_id_o = 1'b0; ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE; illegal_insn_n = 1'b1; + x_control_illegal_reset_o = 1'b1; end else begin @@ -596,7 +609,17 @@ module cv32e40px_controller import cv32e40px_pkg::*; csr_status_i: begin halt_if_o = 1'b1; - ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE; + if (~id_ready_i) begin + ctrl_fsm_ns = DECODE; + end else begin + ctrl_fsm_ns = FLUSH_EX; + if (hwlp_end0_eq_pc) begin + hwlp_dec_cnt_o[0] = 1'b1; + end + if (hwlp_end1_eq_pc) begin + hwlp_dec_cnt_o[1] = 1'b1; + end + end end data_load_event_i: begin @@ -616,7 +639,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; ctrl_fsm_ns = hwlp_end0_eq_pc_plus4 || hwlp_end1_eq_pc_plus4 ? DECODE : DECODE_HWLOOP; // we can be at the end of HWloop due to a return from interrupt or ecall or ebreak or exceptions - if(hwlp_end0_eq_pc && hwlp_counter0_gt_1) begin + if (hwlp_end0_eq_pc && hwlp_counter0_gt_1) begin pc_mux_o = PC_HWLOOP; if (~jump_done_q) begin pc_set_o = 1'b1; @@ -668,6 +691,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; illegal_insn_i | ecall_insn_i: begin ctrl_fsm_ns = FLUSH_EX; + x_control_illegal_reset_o = illegal_insn_i; end (~ebrk_force_debug_mode & ebrk_insn_i): @@ -712,10 +736,12 @@ module cv32e40px_controller import cv32e40px_pkg::*; if ( (debug_req_pending || trigger_match_i) & ~debug_mode_q ) begin //Serving the debug + is_decoding_o = COREV_PULP ? 1'b0 : 1'b1; halt_if_o = 1'b1; halt_id_o = 1'b1; ctrl_fsm_ns = DBG_FLUSH; debug_req_entry_n = 1'b1; + x_branch_or_async_taken_o = 1'b1; end else if (irq_req_ctrl_i && ~debug_mode_q) begin @@ -731,6 +757,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; exc_pc_mux_o = EXC_PC_IRQ; exc_cause_o = irq_id_ctrl_i; csr_irq_sec_o = irq_sec_ctrl_i; + x_branch_or_async_taken_o = 1'b1; // IRQ interface irq_ack_o = 1'b1; @@ -756,6 +783,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; halt_id_o = 1'b1; ctrl_fsm_ns = FLUSH_EX; illegal_insn_n = 1'b1; + x_control_illegal_reset_o = 1'b1; end else begin @@ -764,7 +792,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; ebrk_insn_i: begin halt_if_o = 1'b1; - halt_id_o = 1'b1; + halt_id_o = 1'b0; if (debug_mode_q) // we got back to the park loop in the debug rom @@ -776,20 +804,30 @@ module cv32e40px_controller import cv32e40px_pkg::*; else begin // otherwise just a normal ebreak exception - ctrl_fsm_ns = FLUSH_EX; + ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE_HWLOOP; end end ecall_insn_i: begin halt_if_o = 1'b1; - halt_id_o = 1'b1; - ctrl_fsm_ns = FLUSH_EX; + halt_id_o = 1'b0; + ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE_HWLOOP; end csr_status_i: begin halt_if_o = 1'b1; - ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE_HWLOOP; + if (~id_ready_i) begin + ctrl_fsm_ns = DECODE_HWLOOP; + end else begin + ctrl_fsm_ns = FLUSH_EX; + if (hwlp_end0_eq_pc) begin + hwlp_dec_cnt_o[0] = 1'b1; + end + if (hwlp_end1_eq_pc) begin + hwlp_dec_cnt_o[1] = 1'b1; + end + end end data_load_event_i: begin @@ -843,6 +881,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; illegal_insn_i | ecall_insn_i: begin ctrl_fsm_ns = FLUSH_EX; + x_control_illegal_reset_o = illegal_insn_i; end (~ebrk_force_debug_mode & ebrk_insn_i): @@ -1065,16 +1104,10 @@ module cv32e40px_controller import cv32e40px_pkg::*; end csr_status_i: begin - - if(hwlp_end0_eq_pc && hwlp_counter0_gt_1) begin - pc_mux_o = PC_HWLOOP; - pc_set_o = 1'b1; - hwlp_dec_cnt_o[0] = 1'b1; - end - if(hwlp_end1_eq_pc && hwlp_counter1_gt_1) begin - pc_mux_o = PC_HWLOOP; - pc_set_o = 1'b1; - hwlp_dec_cnt_o[1] = 1'b1; + if ((hwlp_end0_eq_pc && !hwlp_counter0_eq_0) || + (hwlp_end1_eq_pc && !hwlp_counter1_eq_0)) begin + pc_mux_o = PC_HWLOOP; + pc_set_o = 1'b1; end end @@ -1191,7 +1224,7 @@ module cv32e40px_controller import cv32e40px_pkg::*; exc_pc_mux_o = EXC_PC_DBD; csr_save_cause_o = 1'b1; debug_csr_save_o = 1'b1; - if (debug_force_wakeup_q) + if (debug_force_wakeup_q) debug_cause_o = DBG_CAUSE_HALTREQ; else if (debug_single_step_i) debug_cause_o = DBG_CAUSE_STEP; // pri 0 @@ -1463,7 +1496,7 @@ endgenerate assign debug_wfi_no_sleep_o = debug_mode_q || debug_req_pending || debug_single_step_i || trigger_match_i || COREV_CLUSTER; - // Gate off wfi + // Gate off wfi assign wfi_active = wfi_i & ~debug_wfi_no_sleep_o; // sticky version of debug_req (must be on clk_ungated_i such that incoming pulse before core is enabled is not missed) @@ -1559,7 +1592,7 @@ endgenerate // HWLoop 0 and 1 having target address constraints property p_hwlp_same_target_address; - @(posedge clk) (hwlp_counter_i[1] > 1 && hwlp_counter_i[0] > 1) |-> ( hwlp_end_addr_i[1] - 4 >= hwlp_end_addr_i[0] - 4 + 8 ); + @(posedge clk) (hwlp_counter_i[1] > 1 && hwlp_counter_i[0] > 1 && pc_id_i >= hwlp_start_addr_i[0] && pc_id_i <= hwlp_end_addr_i[0] - 4) |-> ( hwlp_end_addr_i[1] - 4 >= hwlp_end_addr_i[0] - 4 + 8 ); endproperty a_hwlp_same_target_address : assert property(p_hwlp_same_target_address) else $warning("%t, HWLoops target address do not respect constraints", $time); @@ -1584,7 +1617,7 @@ endgenerate // Ensure DBG_TAKEN_IF can only be enterred if in single step mode or woken // up from sleep by debug_req_i - + a_single_step_dbg_taken_if : assert property (@(posedge clk) disable iff (!rst_n) (ctrl_fsm_ns==DBG_TAKEN_IF) |-> ((~debug_mode_q && debug_single_step_i) || debug_force_wakeup_n)); // Ensure DBG_FLUSH state is only one cycle. This implies that cause is either trigger, debug_req_entry, or ebreak diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_core.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_core.sv index fc301b91..91c4eb8d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_core.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_core.sv @@ -72,7 +72,8 @@ module cv32e40px_core output logic [31:0] data_wdata_o, input logic [31:0] data_rdata_i, - // apu-interconnect + // CVFPU interface + output logic apu_busy_o, // handshake signals output logic apu_req_o, input logic apu_gnt_i, @@ -194,11 +195,11 @@ module cv32e40px_core logic [31:0] jump_target_id, jump_target_ex; logic branch_in_ex; logic branch_decision; + logic [ 1:0] ctrl_transfer_insn_in_dec; logic ctrl_busy; logic if_busy; logic lsu_busy; - logic apu_busy; logic [31:0] pc_ex; // PC of last executed branch or cv.elw @@ -237,6 +238,7 @@ module cv32e40px_core logic [ C_RM-1:0] frm_csr; logic [ C_FFLAG-1:0] fflags_csr; logic fflags_we; + logic fregs_we; // APU logic apu_en_ex; @@ -272,6 +274,7 @@ module cv32e40px_core logic regfile_we_ex; logic [ 5:0] regfile_waddr_fw_wb_o; // From WB to ID logic regfile_we_wb; + logic regfile_we_wb_power; logic [ 31:0] regfile_wdata; logic [ 5:0] regfile_alu_waddr_ex; @@ -279,6 +282,7 @@ module cv32e40px_core logic [ 5:0] regfile_alu_waddr_fw; logic regfile_alu_we_fw; + logic regfile_alu_we_fw_power; logic [ 31:0] regfile_alu_wdata_fw; // CSR control @@ -441,7 +445,7 @@ module cv32e40px_core .if_busy_i (if_busy), .ctrl_busy_i(ctrl_busy), .lsu_busy_i (lsu_busy), - .apu_busy_i (apu_busy), + .apu_busy_i (apu_busy_o), // PULP cluster .pulp_clock_en_i (pulp_clock_en_i), @@ -596,9 +600,10 @@ module cv32e40px_core .instr_req_o (instr_req_int), // Jumps and branches - .branch_in_ex_o (branch_in_ex), - .branch_decision_i(branch_decision), - .jump_target_o (jump_target_id), + .branch_in_ex_o (branch_in_ex), + .branch_decision_i (branch_decision), + .jump_target_o (jump_target_id), + .ctrl_transfer_insn_in_dec_o(ctrl_transfer_insn_in_dec), // IF and ID control signals .clear_instr_valid_o(clear_instr_valid), @@ -685,7 +690,7 @@ module cv32e40px_core .apu_write_regs_valid_o (apu_write_regs_valid), .apu_write_dep_i (apu_write_dep), .apu_perf_dep_o (perf_apu_dep), - .apu_busy_i (apu_busy), + .apu_busy_i (apu_busy_o), // CORE-V-XIF // Compressed Interface @@ -790,13 +795,15 @@ module cv32e40px_core .wake_from_sleep_o(wake_from_sleep), // Forward Signals - .regfile_waddr_wb_i(regfile_waddr_fw_wb_o), // Write address ex-wb pipeline - .regfile_we_wb_i (regfile_we_wb), // write enable for the register file - .regfile_wdata_wb_i(regfile_wdata), // write data to commit in the register file + .regfile_waddr_wb_i (regfile_waddr_fw_wb_o), // Write address ex-wb pipeline + .regfile_we_wb_i (regfile_we_wb), // write enable for the register file + .regfile_we_wb_power_i(regfile_we_wb_power), + .regfile_wdata_wb_i (regfile_wdata), // write data to commit in the register file - .regfile_alu_waddr_fw_i(regfile_alu_waddr_fw), - .regfile_alu_we_fw_i (regfile_alu_we_fw), - .regfile_alu_wdata_fw_i(regfile_alu_wdata_fw), + .regfile_alu_waddr_fw_i (regfile_alu_waddr_fw), + .regfile_alu_we_fw_i (regfile_alu_we_fw), + .regfile_alu_we_fw_power_i(regfile_alu_we_fw_power), + .regfile_alu_wdata_fw_i (regfile_alu_wdata_fw), // from ALU .mult_multicycle_i(mult_multicycle), @@ -828,6 +835,7 @@ module cv32e40px_core // // ///////////////////////////////////////////////////// cv32e40px_ex_stage #( + .COREV_PULP (COREV_PULP), .FPU (FPU), .APU_NARGS_CPU (APU_NARGS_CPU), .APU_WOP_CPU (APU_WOP_CPU), @@ -876,6 +884,8 @@ module cv32e40px_core .data_misaligned_ex_i(data_misaligned_ex), // from ID/EX pipeline .data_misaligned_i (data_misaligned), + .ctrl_transfer_insn_in_dec_i(ctrl_transfer_insn_in_dec), + // FPU .fpu_fflags_we_o(fflags_we), .fpu_fflags_o (fflags_csr), @@ -899,9 +909,9 @@ module cv32e40px_core .apu_perf_cont_o(perf_apu_cont), .apu_perf_wb_o (perf_apu_wb), .apu_ready_wb_o (apu_ready_wb), - .apu_busy_o (apu_busy), + .apu_busy_o (apu_busy_o), - // apu-interconnect + // CVFPU interface // handshake signals .apu_req_o (apu_req_o), .apu_gnt_i (apu_gnt_i), @@ -941,18 +951,20 @@ module cv32e40px_core .regfile_we_i (regfile_we_ex), // Output of ex stage pipeline - .regfile_waddr_wb_o(regfile_waddr_fw_wb_o), - .regfile_we_wb_o (regfile_we_wb), - .regfile_wdata_wb_o(regfile_wdata), + .regfile_waddr_wb_o (regfile_waddr_fw_wb_o), + .regfile_we_wb_o (regfile_we_wb), + .regfile_we_wb_power_o(regfile_we_wb_power), + .regfile_wdata_wb_o (regfile_wdata), // To IF: Jump and branch target and decision .jump_target_o (jump_target_ex), .branch_decision_o(branch_decision), // To ID stage: Forwarding signals - .regfile_alu_waddr_fw_o(regfile_alu_waddr_fw), - .regfile_alu_we_fw_o (regfile_alu_we_fw), - .regfile_alu_wdata_fw_o(regfile_alu_wdata_fw), + .regfile_alu_waddr_fw_o (regfile_alu_waddr_fw), + .regfile_alu_we_fw_o (regfile_alu_we_fw), + .regfile_alu_we_fw_power_o(regfile_alu_we_fw_power), + .regfile_alu_wdata_fw_o (regfile_alu_wdata_fw), // stall control .is_decoding_i (is_decoding), @@ -1072,6 +1084,7 @@ module cv32e40px_core .frm_o (frm_csr), .fflags_i (fflags_csr), .fflags_we_i(fflags_we), + .fregs_we_i (fregs_we), // Interrupt related control signals .mie_bypass_o (mie_bypass), @@ -1140,13 +1153,16 @@ module cv32e40px_core ); // CSR access - assign csr_addr = csr_addr_int; - assign csr_wdata = alu_operand_a_ex; - assign csr_op = csr_op_ex; + assign csr_addr = csr_addr_int; + assign csr_wdata = alu_operand_a_ex; + assign csr_op = csr_op_ex; assign csr_addr_int = csr_num_e'(csr_access_ex ? alu_operand_b_ex[11:0] : '0); - + // Floating-Point registers write + assign fregs_we = (FPU == 1 & ZFINX == 0) ? ((regfile_alu_we_fw && regfile_alu_waddr_fw[5]) || + (regfile_we_wb && regfile_waddr_fw_wb_o[5])) + : 1'b0; /////////////////////////// // ____ __ __ ____ // diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_cs_registers.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_cs_registers.sv index 2d873452..53005725 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_cs_registers.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_cs_registers.sv @@ -68,6 +68,7 @@ module cv32e40px_cs_registers output logic [ 2:0] frm_o, input logic [C_FFLAG-1:0] fflags_i, input logic fflags_we_i, + input logic fregs_we_i, // Interrupts output logic [31:0] mie_bypass_o, @@ -212,6 +213,7 @@ module cv32e40px_cs_registers logic [31:0] exception_pc; Status_t mstatus_q, mstatus_n; + logic mstatus_we_int; FS_t mstatus_fs_q, mstatus_fs_n; logic [5:0] mcause_q, mcause_n; logic [5:0] ucause_q, ucause_n; @@ -507,7 +509,7 @@ module cv32e40px_cs_registers // mimpid, Machine Implementation ID CSR_MIMPID: begin - csr_rdata_int = (FPU || COREV_PULP || COREV_CLUSTER) ? 32'h1 : 'b0; + csr_rdata_int = (FPU == 1 || COREV_PULP == 1 || COREV_CLUSTER == 1) ? 32'h1 : 'b0; end // unimplemented, read 0 CSRs @@ -897,6 +899,7 @@ module cv32e40px_cs_registers dscratch0_n = dscratch0_q; dscratch1_n = dscratch1_q; + mstatus_we_int = 1'b0; mstatus_n = mstatus_q; mcause_n = mcause_q; ucause_n = '0; // Not used if PULP_SECURE == 0 @@ -957,7 +960,8 @@ module cv32e40px_cs_registers mprv: csr_wdata_int[MSTATUS_MPRV_BIT] }; if (FPU == 1 && ZFINX == 0) begin - mstatus_fs_n = FS_t'(csr_wdata_int[MSTATUS_FS_BIT_HIGH:MSTATUS_FS_BIT_LOW]); + mstatus_we_int = 1'b1; + mstatus_fs_n = FS_t'(csr_wdata_int[MSTATUS_FS_BIT_HIGH:MSTATUS_FS_BIT_LOW]); end end // mie: machine interrupt enable @@ -1027,7 +1031,7 @@ module cv32e40px_cs_registers if (ZFINX == 0) begin // FPU Register File/Flags implicit update or modified by CSR instructions - if (fflags_we_i || fcsr_update) begin + if ((fregs_we_i && !(mstatus_we_int && mstatus_fs_n != FS_DIRTY)) || fflags_we_i || fcsr_update) begin mstatus_fs_n = FS_DIRTY; end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_decoder.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_decoder.sv index 3d55fdbc..c8e11cc3 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_decoder.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_decoder.sv @@ -1057,7 +1057,6 @@ module cv32e40px_decoder 5'b00000: begin fpu_op = cv32e40px_fpu_pkg::ADD; fp_op_group = ADDMUL; - apu_op_o = 2'b0; alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; end @@ -1066,7 +1065,6 @@ module cv32e40px_decoder fpu_op = cv32e40px_fpu_pkg::ADD; fpu_op_mod = 1'b1; fp_op_group = ADDMUL; - apu_op_o = 2'b1; alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; end @@ -1085,7 +1083,6 @@ module cv32e40px_decoder regb_used_o = 1'b0; fpu_op = cv32e40px_fpu_pkg::SQRT; fp_op_group = DIVSQRT; - apu_op_o = 1'b1; // rs2 must be zero if (instr_rdata_i[24:20] != 5'b00000) illegal_insn_o = 1'b1; end @@ -1213,7 +1210,6 @@ module cv32e40px_decoder fpu_op = cv32e40px_fpu_pkg::F2I; fp_op_group = CONV; fpu_op_mod = instr_rdata_i[20]; // signed/unsigned switch - apu_op_o = 2'b1; unique case (instr_rdata_i[26:25]) //fix for casting to different formats other than FP32 2'b00: begin @@ -1249,7 +1245,6 @@ module cv32e40px_decoder fpu_op = cv32e40px_fpu_pkg::I2F; fp_op_group = CONV; fpu_op_mod = instr_rdata_i[20]; // signed/unsigned switch - apu_op_o = 2'b0; // bits [21:20] used, other bits must be 0 if (instr_rdata_i[24:21]) illegal_insn_o = 1'b1; // in RV32, no casts to L allowed. end @@ -1323,20 +1318,20 @@ module cv32e40px_decoder // check rounding mode if (check_fprm) begin unique case (instr_rdata_i[14:12]) inside - [3'b000:3'b100]: ; //legal rounding modes + 3'b000, 3'b001, 3'b010, 3'b011, 3'b100: ; //legal rounding modes 3'b101: begin // Alternative Half-Precsision encded as fmt=10 and rm=101 if (~C_XF16ALT || fpu_dst_fmt_o != cv32e40px_fpu_pkg::FP16ALT) illegal_insn_o = 1'b1; // actual rounding mode from frm csr unique case (frm_i) inside - [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes - default : illegal_insn_o = 1'b1; + 3'b000, 3'b001, 3'b010, 3'b011, 3'b100 : fp_rnd_mode_o = frm_i; //legal rounding modes + default : illegal_insn_o = 1'b1; endcase end 3'b111: begin // rounding mode from frm csr unique case (frm_i) inside - [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes - default : illegal_insn_o = 1'b1; + 3'b000, 3'b001, 3'b010, 3'b011, 3'b100 : fp_rnd_mode_o = frm_i; //legal rounding modes + default : illegal_insn_o = 1'b1; endcase end default : illegal_insn_o = 1'b1; @@ -1364,6 +1359,7 @@ module cv32e40px_decoder NONCOMP : apu_lat_o = (FPU_OTHERS_LAT<2) ? FPU_OTHERS_LAT+1 : 2'h3; // CONV uses the same latency for all formats CONV : apu_lat_o = (FPU_OTHERS_LAT<2) ? FPU_OTHERS_LAT+1 : 2'h3; + default: ; endcase // Set FPnew OP and OPMOD as the APU op @@ -1425,25 +1421,21 @@ module cv32e40px_decoder unique case (instr_rdata_i[6:0]) // fmadd.fmt - FP Fused multiply-add OPCODE_OP_FMADD : begin - fpu_op = cv32e40px_fpu_pkg::FMADD; - apu_op_o = 2'b00; + fpu_op = cv32e40px_fpu_pkg::FMADD; end // fmsub.fmt - FP Fused multiply-subtract OPCODE_OP_FMSUB : begin - fpu_op = cv32e40px_fpu_pkg::FMADD; - fpu_op_mod = 1'b1; - apu_op_o = 2'b01; + fpu_op = cv32e40px_fpu_pkg::FMADD; + fpu_op_mod = 1'b1; end // fnmsub.fmt - FP Negated fused multiply-subtract OPCODE_OP_FNMSUB : begin - fpu_op = cv32e40px_fpu_pkg::FNMSUB; - apu_op_o = 2'b10; + fpu_op = cv32e40px_fpu_pkg::FNMSUB; end // fnmadd.fmt - FP Negated fused multiply-add OPCODE_OP_FNMADD : begin - fpu_op = cv32e40px_fpu_pkg::FNMSUB; - fpu_op_mod = 1'b1; - apu_op_o = 2'b11; + fpu_op = cv32e40px_fpu_pkg::FNMSUB; + fpu_op_mod = 1'b1; end default : ; endcase @@ -1459,19 +1451,19 @@ module cv32e40px_decoder // check rounding mode unique case (instr_rdata_i[14:12]) inside - [3'b000:3'b100]: ; //legal rounding modes + 3'b000, 3'b001, 3'b010, 3'b011, 3'b100: ; //legal rounding modes 3'b101: begin // Alternative Half-Precsision encded as fmt=10 and rm=101 if (~C_XF16ALT || fpu_dst_fmt_o != cv32e40px_fpu_pkg::FP16ALT) illegal_insn_o = 1'b1; // actual rounding mode from frm csr unique case (frm_i) inside - [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes + 3'b000, 3'b001, 3'b010, 3'b011, 3'b100 : fp_rnd_mode_o = frm_i; //legal rounding modes default : illegal_insn_o = 1'b1; endcase end 3'b111: begin // rounding mode from frm csr unique case (frm_i) inside - [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes + 3'b000, 3'b001, 3'b010, 3'b011, 3'b100 : fp_rnd_mode_o = frm_i; //legal rounding modes default : illegal_insn_o = 1'b1; endcase end @@ -1493,6 +1485,7 @@ module cv32e40px_decoder // Set FPnew OP and OPMOD as the APU op apu_op_o = {fpu_vec_op, fpu_op_mod, fpu_op}; + // No FPU or (ZFINX == 0 && MSTATUS.FS == FS_OFF) end else begin illegal_insn_o = 1'b1; @@ -1900,15 +1893,14 @@ module cv32e40px_decoder alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; unique case (instr_rdata_i[27:25]) - 3'b000: alu_operator_o = ALU_ADD; // cv.addNr - 3'b001: alu_operator_o = ALU_ADDU; // cv.adduNr - 3'b010: alu_operator_o = ALU_ADDR; // cv.addRNr - 3'b011: alu_operator_o = ALU_ADDUR; // cv.adduRNr - 3'b100: alu_operator_o = ALU_SUB; // cv.subNr - 3'b101: alu_operator_o = ALU_SUBU; // cv.subuNr - 3'b110: alu_operator_o = ALU_SUBR; // cv.subRNr - 3'b111: alu_operator_o = ALU_SUBUR; // cv.subuRNr - default: alu_operator_o = ALU_ADD; + 3'b001: alu_operator_o = ALU_ADDU; // cv.adduNr + 3'b010: alu_operator_o = ALU_ADDR; // cv.addRNr + 3'b011: alu_operator_o = ALU_ADDUR; // cv.adduRNr + 3'b100: alu_operator_o = ALU_SUB; // cv.subNr + 3'b101: alu_operator_o = ALU_SUBU; // cv.subuNr + 3'b110: alu_operator_o = ALU_SUBR; // cv.subRNr + 3'b111: alu_operator_o = ALU_SUBUR; // cv.subuRNr + default: alu_operator_o = ALU_ADD; // cv.addNr endcase end @@ -2085,7 +2077,6 @@ module cv32e40px_decoder // decide between using unsigned and rounding, and combinations unique case ({instr_rdata_i[31:30], instr_rdata_i[12]}) - {2'b00, 1'b0}: alu_operator_o = ALU_ADD; // cv.addN {2'b01, 1'b0}: alu_operator_o = ALU_ADDU; // cv.adduN {2'b10, 1'b0}: alu_operator_o = ALU_ADDR; // cv.addRN {2'b11, 1'b0}: alu_operator_o = ALU_ADDUR; // cv.adduRN @@ -2093,12 +2084,12 @@ module cv32e40px_decoder {2'b01, 1'b1}: alu_operator_o = ALU_SUBU; // cv.subuN {2'b10, 1'b1}: alu_operator_o = ALU_SUBR; // cv.subRN {2'b11, 1'b1}: alu_operator_o = ALU_SUBUR; // cv.subuRN - default : alu_operator_o = ALU_ADD; + default : alu_operator_o = ALU_ADD; // cv.addN endcase end - 2'b10, 2'b11: begin + default: begin // MUL/MAC with subword selection alu_en = 1'b0; mult_int_en = 1'b1; @@ -2126,7 +2117,6 @@ module cv32e40px_decoder mult_operator_o = MUL_I; end end - default: illegal_insn_o = 1'b1; endcase end else begin illegal_insn_o = 1'b1; @@ -2267,6 +2257,11 @@ module cv32e40px_decoder instr_rdata_i[25] != 1'b0) begin illegal_insn_o = 1'b1; end + // Imm6 restrictions + if ((instr_rdata_i[14:12] == 3'b110 && instr_rdata_i[24:23] != 2'b0) || + (instr_rdata_i[14:12] == 3'b111 && instr_rdata_i[24:22] != 3'b0)) begin + illegal_insn_o = 1'b1; + end end 6'b01001_0: begin // cv.sra alu_operator_o = ALU_SRA; @@ -2278,6 +2273,11 @@ module cv32e40px_decoder instr_rdata_i[25] != 1'b0) begin illegal_insn_o = 1'b1; end + // Imm6 restrictions + if ((instr_rdata_i[14:12] == 3'b110 && instr_rdata_i[24:23] != 2'b0) || + (instr_rdata_i[14:12] == 3'b111 && instr_rdata_i[24:22] != 3'b0)) begin + illegal_insn_o = 1'b1; + end end 6'b01010_0: begin // cv.sll alu_operator_o = ALU_SLL; @@ -2289,6 +2289,11 @@ module cv32e40px_decoder instr_rdata_i[25] != 1'b0) begin illegal_insn_o = 1'b1; end + // Imm6 restrictions + if ((instr_rdata_i[14:12] == 3'b110 && instr_rdata_i[24:23] != 2'b0) || + (instr_rdata_i[14:12] == 3'b111 && instr_rdata_i[24:22] != 3'b0)) begin + illegal_insn_o = 1'b1; + end end 6'b01011_0: begin // cv.or alu_operator_o = ALU_OR; @@ -2425,6 +2430,11 @@ module cv32e40px_decoder end default: illegal_insn_o = 1'b1; endcase + // Imm6 restrictions + if ((instr_rdata_i[12] == 1'b0 && instr_rdata_i[24:20] != 5'b0) || + (instr_rdata_i[12] == 1'b1 && instr_rdata_i[24:21] != 4'b0)) begin + illegal_insn_o = 1'b1; + end end 6'b11000_0: begin // cv.shuffle, cv.shuffleI0 alu_operator_o = ALU_SHUF; @@ -2439,6 +2449,10 @@ module cv32e40px_decoder instr_rdata_i[25] != 1'b0) begin illegal_insn_o = 1'b1; end + // Imm6 restriction + if (instr_rdata_i[14:12] == 3'b110 && instr_rdata_i[24:21] != 4'b0) begin + illegal_insn_o = 1'b1; + end end 6'b11001_0, 6'b11010_0, diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_ex_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_ex_stage.sv index 6ab1b01b..02876108 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_ex_stage.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_ex_stage.sv @@ -34,6 +34,7 @@ module cv32e40px_ex_stage import cv32e40px_apu_core_pkg::*; import cv32e40px_core_v_xif_pkg::*; #( + parameter COREV_PULP = 0, parameter FPU = 0, parameter APU_NARGS_CPU = 3, parameter APU_WOP_CPU = 6, @@ -82,6 +83,8 @@ module cv32e40px_ex_stage input logic data_misaligned_ex_i, input logic data_misaligned_i, + input logic [1:0] ctrl_transfer_insn_in_dec_i, + // FPU signals output logic fpu_fflags_we_o, output logic [APU_NUSFLAGS_CPU-1:0] fpu_fflags_o, @@ -152,11 +155,13 @@ module cv32e40px_ex_stage // Output of EX stage pipeline output logic [ 5:0] regfile_waddr_wb_o, output logic regfile_we_wb_o, + output logic regfile_we_wb_power_o, output logic [31:0] regfile_wdata_wb_o, // Forwarding ports : to ID stage output logic [ 5:0] regfile_alu_waddr_fw_o, output logic regfile_alu_we_fw_o, + output logic regfile_alu_we_fw_power_o, output logic [31:0] regfile_alu_wdata_fw_o, // forward to RF and ID/EX pipe, ALU & MUL // To IF: Jump and branch target and decision @@ -204,30 +209,36 @@ module cv32e40px_ex_stage // ALU write port mux always_comb begin - regfile_alu_wdata_fw_o = '0; - regfile_alu_waddr_fw_o = '0; - regfile_alu_we_fw_o = '0; - wb_contention = 1'b0; - result_fw_to_x_o = '0; + regfile_alu_wdata_fw_o = '0; + regfile_alu_waddr_fw_o = '0; + regfile_alu_we_fw_o = '0; + wb_contention = 1'b0; + result_fw_to_x_o = '0; + regfile_alu_we_fw_power_o = 1'b0; if (x_result_valid_assigned_i & x_result_we_i & (x_result_rd_i != 5'b00000)) begin - regfile_alu_we_fw_o = 1'b1; - regfile_alu_waddr_fw_o = {1'b0, x_result_rd_i}; - regfile_alu_wdata_fw_o = x_result_data_i; + regfile_alu_we_fw_o = 1'b1; + regfile_alu_we_fw_power_o = 1'b1; + regfile_alu_waddr_fw_o = {1'b0, x_result_rd_i}; + regfile_alu_wdata_fw_o = x_result_data_i; if (regfile_alu_we_i) begin wb_contention = 1'b1; end end else begin // APU single cycle operations, and multicycle operations (>2cycles) are written back on ALU port if (apu_valid & (apu_singlecycle | apu_multicycle)) begin - regfile_alu_we_fw_o = 1'b1; - regfile_alu_waddr_fw_o = apu_waddr; - regfile_alu_wdata_fw_o = apu_result; - result_fw_to_x_o = apu_result; + regfile_alu_we_fw_o = 1'b1; + regfile_alu_we_fw_power_o = 1'b1; + regfile_alu_waddr_fw_o = apu_waddr; + regfile_alu_wdata_fw_o = apu_result; + result_fw_to_x_o = apu_result; if (regfile_alu_we_i & ~apu_en_i) begin wb_contention = 1'b1; end end else begin - regfile_alu_we_fw_o = regfile_alu_we_i & ~apu_en_i; // private fpu incomplete? + regfile_alu_we_fw_o = regfile_alu_we_i & ~apu_en_i; // private fpu incomplete? + regfile_alu_we_fw_power_o = !COREV_PULP ? regfile_alu_we_i & ~apu_en_i : + regfile_alu_we_i & ~apu_en_i & + mult_ready & alu_ready & lsu_ready_ex_i; regfile_alu_waddr_fw_o = regfile_alu_waddr_i; if (alu_en_i) begin regfile_alu_wdata_fw_o = alu_result; @@ -247,21 +258,24 @@ module cv32e40px_ex_stage // LSU write port mux always_comb begin - regfile_we_wb_o = 1'b0; - regfile_waddr_wb_o = regfile_waddr_lsu; - regfile_wdata_wb_o = lsu_rdata_i; - wb_contention_lsu = 1'b0; + regfile_we_wb_o = 1'b0; + regfile_we_wb_power_o = 1'b0; + regfile_waddr_wb_o = regfile_waddr_lsu; + regfile_wdata_wb_o = lsu_rdata_i; + wb_contention_lsu = 1'b0; if (regfile_we_lsu) begin - regfile_we_wb_o = 1'b1; + regfile_we_wb_o = 1'b1; + regfile_we_wb_power_o = (COREV_PULP == 0) ? 1'b1 : ~data_misaligned_ex_i & wb_ready_i; if (apu_valid & (!apu_singlecycle & !apu_multicycle)) begin wb_contention_lsu = 1'b1; end // APU two-cycle operations are written back on LSU port end else if (apu_valid & (!apu_singlecycle & !apu_multicycle)) begin - regfile_we_wb_o = 1'b1; - regfile_waddr_wb_o = apu_waddr; - regfile_wdata_wb_o = apu_result; + regfile_we_wb_o = 1'b1; + regfile_we_wb_power_o = 1'b1; + regfile_waddr_wb_o = apu_waddr; + regfile_wdata_wb_o = apu_result; end end @@ -406,11 +420,20 @@ module cv32e40px_ex_stage apu_result_q <= 'b0; apu_flags_q <= 'b0; end else begin - if (apu_rvalid_i && apu_multicycle && (data_misaligned_i || data_misaligned_ex_i || (data_req_i && regfile_alu_we_i) || (mulh_active && (mult_operator_i == MUL_H)))) begin + if (apu_rvalid_i && apu_multicycle && + (data_misaligned_i || data_misaligned_ex_i || + ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || + (mulh_active && (mult_operator_i == MUL_H)) || + ((ctrl_transfer_insn_in_dec_i == BRANCH_JALR) && + regfile_alu_we_i && ~apu_read_dep_for_jalr_o))) begin apu_rvalid_q <= 1'b1; apu_result_q <= apu_result_i; apu_flags_q <= apu_flags_i; - end else if (apu_rvalid_q && !(data_misaligned_i || data_misaligned_ex_i || ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || (mulh_active && (mult_operator_i == MUL_H)))) begin + end else if (apu_rvalid_q && !(data_misaligned_i || data_misaligned_ex_i || + ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || + (mulh_active && (mult_operator_i == MUL_H)) || + ((ctrl_transfer_insn_in_dec_i == BRANCH_JALR) && + regfile_alu_we_i && ~apu_read_dep_for_jalr_o))) begin apu_rvalid_q <= 1'b0; end end @@ -418,7 +441,12 @@ module cv32e40px_ex_stage assign apu_req_o = apu_req; assign apu_gnt = apu_gnt_i; - assign apu_valid = (apu_multicycle && (data_misaligned_i || data_misaligned_ex_i || ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || (mulh_active && (mult_operator_i == MUL_H)))) ? 1'b0 : (apu_rvalid_i || apu_rvalid_q); + assign apu_valid = (apu_multicycle && (data_misaligned_i || data_misaligned_ex_i || + ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || + (mulh_active && (mult_operator_i == MUL_H)) || + ((ctrl_transfer_insn_in_dec_i == BRANCH_JALR) && + regfile_alu_we_i && ~apu_read_dep_for_jalr_o))) + ? 1'b0 : (apu_rvalid_i || apu_rvalid_q); assign apu_operands_o = apu_operands_i; assign apu_op_o = apu_op_i; assign apu_result = apu_rvalid_q ? apu_result_q : apu_result_i; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_fp_wrapper.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_fp_wrapper.sv index 8502e341..126a1f44 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_fp_wrapper.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_fp_wrapper.sv @@ -14,7 +14,7 @@ module cv32e40px_fp_wrapper import cv32e40px_apu_core_pkg::*; #( - parameter FPU_ADDMUL_LAT = 0, // Floating-Point ADDition/MULtiplication computing lane pipeline registers number + parameter FPU_ADDMUL_LAT = 0, // Floating-Point ADDition/MULtiplication computing lane pipeline registers number parameter FPU_OTHERS_LAT = 0 // Floating-Point COMParison/CONVersion computing lanes pipeline registers number ) ( // Clock and Reset @@ -111,7 +111,7 @@ module cv32e40px_fp_wrapper .int_fmt_i (fpnew_pkg::int_format_e'(fpu_int_fmt)), .vectorial_op_i(fpu_vec_op), .tag_i (1'b0), - .simd_mask_i ('b0), + .simd_mask_i (1'b0), .in_valid_i (apu_req_i), .in_ready_o (apu_gnt_o), .flush_i (1'b0), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_id_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_id_stage.sv index 4c513d27..883b5ff1 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_id_stage.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_id_stage.sv @@ -72,6 +72,7 @@ module cv32e40px_id_stage output logic branch_in_ex_o, input logic branch_decision_i, output logic [31:0] jump_target_o, + output logic [ 1:0] ctrl_transfer_insn_in_dec_o, // IF and ID stage signals output logic clear_instr_valid_o, @@ -263,10 +264,12 @@ module cv32e40px_id_stage // Forward Signals input logic [5:0] regfile_waddr_wb_i, input logic regfile_we_wb_i, + input logic regfile_we_wb_power_i, input logic [31:0] regfile_wdata_wb_i, // From wb_stage: selects data from data memory, ex_stage result and sp rdata input logic [ 5:0] regfile_alu_waddr_fw_i, input logic regfile_alu_we_fw_i, + input logic regfile_alu_we_fw_power_i, input logic [31:0] regfile_alu_wdata_fw_i, // from ALU @@ -302,6 +305,9 @@ module cv32e40px_id_stage localparam REG_D_MSB = 11; localparam REG_D_LSB = 7; + + localparam REGFILE_NUM_READ_PORTS = ((COREV_X_IF == 1) & (X_DUALREAD == 1)) ? 2 : 1; + logic [31:0] instr; @@ -381,9 +387,9 @@ module cv32e40px_id_stage logic [ 5:0] regfile_alu_waddr_id; logic regfile_alu_we_id, regfile_alu_we_dec_id; - logic [31:0] regfile_data_ra_id; - logic [31:0] regfile_data_rb_id; - logic [31:0] regfile_data_rc_id; + logic [REGFILE_NUM_READ_PORTS-1:0][31:0] regfile_data_ra_id; + logic [REGFILE_NUM_READ_PORTS-1:0][31:0] regfile_data_rb_id; + logic [REGFILE_NUM_READ_PORTS-1:0][31:0] regfile_data_rc_id; // ALU Control logic alu_en; @@ -430,6 +436,8 @@ module cv32e40px_id_stage // X-Interface logic illegal_insn; logic x_illegal_insn; + logic x_branch_or_async_taken; + logic x_control_illegal_reset; logic [4:0] waddr_id; logic [4:0] waddr_ex; logic [4:0] waddr_wb; @@ -438,8 +446,8 @@ module cv32e40px_id_stage logic [2:0][4:0] x_rs_addr; logic x_mem_data_req; logic x_mem_valid; - logic [2:0] x_ex_fwd; - logic [2:0] x_wb_fwd; + logic [RF_READ_PORTS-1:0] x_ex_fwd; + logic [RF_READ_PORTS-1:0] x_wb_fwd; // Register Write Control logic regfile_we_id; @@ -622,17 +630,18 @@ module cv32e40px_id_stage // \___/ \__,_|_| |_| |_| .__/ |_|\__,_|_| \__, |\___|\__| // // |_| |___/ // ////////////////////////////////////////////////////////////////// - - always_comb begin : jump_target_mux - unique case (ctrl_transfer_target_mux_sel) - JT_JAL: jump_target = pc_id_i + imm_uj_type; - JT_COND: jump_target = pc_id_i + imm_sb_type; - - // JALR: Cannot forward RS1, since the path is too long - JT_JALR: jump_target = regfile_data_ra_id + imm_i_type; - default: jump_target = regfile_data_ra_id + imm_i_type; - endcase - end + generate + always_comb begin : jump_target_mux + unique case (ctrl_transfer_target_mux_sel) + JT_JAL: jump_target = pc_id_i + imm_uj_type; + JT_COND: jump_target = pc_id_i + imm_sb_type; + + // JALR: Cannot forward RS1, since the path is too long + JT_JALR: jump_target = regfile_data_ra_id[0] + imm_i_type; + default: jump_target = regfile_data_ra_id[0] + imm_i_type; + endcase + end + endgenerate assign jump_target_o = jump_target; @@ -666,16 +675,18 @@ module cv32e40px_id_stage endcase end - // Operand a forwarding mux - always_comb begin : operand_a_fw_mux - case (operand_a_fw_mux_sel) - SEL_FW_EX: operand_a_fw_id = regfile_alu_wdata_fw_i; - SEL_FW_WB: operand_a_fw_id = regfile_wdata_wb_i; - SEL_REGFILE: operand_a_fw_id = regfile_data_ra_id; - default: operand_a_fw_id = regfile_data_ra_id; - endcase - ; // case (operand_a_fw_mux_sel) - end + generate + // Operand a forwarding mux + always_comb begin : operand_a_fw_mux + case (operand_a_fw_mux_sel) + SEL_FW_EX: operand_a_fw_id = regfile_alu_wdata_fw_i; + SEL_FW_WB: operand_a_fw_id = regfile_wdata_wb_i; + SEL_REGFILE: operand_a_fw_id = regfile_data_ra_id[0]; + default: operand_a_fw_id = regfile_data_ra_id[0]; + endcase + ; // case (operand_a_fw_mux_sel) + end + endgenerate ////////////////////////////////////////////////////// // ___ _ ____ // @@ -732,16 +743,31 @@ module cv32e40px_id_stage assign alu_operand_b = (scalar_replication == 1'b1) ? operand_b_vec : operand_b; - // Operand b forwarding mux - always_comb begin : operand_b_fw_mux - case (operand_b_fw_mux_sel) - SEL_FW_EX: operand_b_fw_id = regfile_alu_wdata_fw_i; - SEL_FW_WB: operand_b_fw_id = regfile_wdata_wb_i; - SEL_REGFILE: operand_b_fw_id = regfile_data_rb_id; - default: operand_b_fw_id = regfile_data_rb_id; - endcase - ; // case (operand_b_fw_mux_sel) - end + generate + if (X_DUALREAD == 0) begin : no_dualread_fw_b + // Operand b forwarding mux + always_comb begin : operand_b_fw_mux + case (operand_b_fw_mux_sel) + SEL_FW_EX: operand_b_fw_id = regfile_alu_wdata_fw_i; + SEL_FW_WB: operand_b_fw_id = regfile_wdata_wb_i; + SEL_REGFILE: operand_b_fw_id = regfile_data_rb_id; + default: operand_b_fw_id = regfile_data_rb_id; + endcase + ; // case (operand_b_fw_mux_sel) + end + end else begin : dualread_fw_b + // Operand b forwarding mux + always_comb begin : operand_b_fw_mux + case (operand_b_fw_mux_sel) + SEL_FW_EX: operand_b_fw_id = regfile_alu_wdata_fw_i; + SEL_FW_WB: operand_b_fw_id = regfile_wdata_wb_i; + SEL_REGFILE: operand_b_fw_id = regfile_data_rb_id[0]; + default: operand_b_fw_id = regfile_data_rb_id[0]; + endcase + ; // case (operand_b_fw_mux_sel) + end + end + endgenerate ////////////////////////////////////////////////////// @@ -777,17 +803,31 @@ module cv32e40px_id_stage assign alu_operand_c = (scalar_replication_c == 1'b1) ? operand_c_vec : operand_c; - // Operand c forwarding mux - always_comb begin : operand_c_fw_mux - case (operand_c_fw_mux_sel) - SEL_FW_EX: operand_c_fw_id = regfile_alu_wdata_fw_i; - SEL_FW_WB: operand_c_fw_id = regfile_wdata_wb_i; - SEL_REGFILE: operand_c_fw_id = regfile_data_rc_id; - default: operand_c_fw_id = regfile_data_rc_id; - endcase - ; // case (operand_c_fw_mux_sel) - end - + generate + if (X_DUALREAD == 0) begin : no_dualread_fw_c + // Operand c forwarding mux + always_comb begin : operand_c_fw_mux + case (operand_c_fw_mux_sel) + SEL_FW_EX: operand_c_fw_id = regfile_alu_wdata_fw_i; + SEL_FW_WB: operand_c_fw_id = regfile_wdata_wb_i; + SEL_REGFILE: operand_c_fw_id = regfile_data_rc_id; + default: operand_c_fw_id = regfile_data_rc_id; + endcase + ; // case (operand_c_fw_mux_sel) + end + end else begin : dualread_fw_c + // Operand c forwarding mux + always_comb begin : operand_c_fw_mux + case (operand_c_fw_mux_sel) + SEL_FW_EX: operand_c_fw_id = regfile_alu_wdata_fw_i; + SEL_FW_WB: operand_c_fw_id = regfile_wdata_wb_i; + SEL_REGFILE: operand_c_fw_id = regfile_data_rc_id[0]; + default: operand_c_fw_id = regfile_data_rc_id[0]; + endcase + ; // case (operand_c_fw_mux_sel) + end + end + endgenerate /////////////////////////////////////////////////////////////////////////// // ___ _ _ _ ___ ____ // @@ -865,6 +905,9 @@ module cv32e40px_id_stage if (ctrl_transfer_target_mux_sel == JT_JALR) begin apu_read_regs[0] = regfile_addr_ra_id; apu_read_regs_valid[0] = 1'b1; + end else begin + apu_read_regs[0] = regfile_addr_ra_id; + apu_read_regs_valid[0] = 1'b0; end end // OP_A_CURRPC: OP_A_REGA_OR_FWD: begin @@ -982,13 +1025,17 @@ module cv32e40px_id_stage .ADDR_WIDTH(6), .DATA_WIDTH(32), .FPU (FPU), - .ZFINX (ZFINX) + .ZFINX (ZFINX), + .COREV_X_IF(COREV_X_IF), + .X_DUALREAD(X_DUALREAD) ) register_file_i ( .clk (clk), .rst_n(rst_n), .scan_cg_en_i(scan_cg_en_i), + .dualread_i(x_issue_resp_i.dualread), + // Read port a .raddr_a_i(regfile_addr_ra_id), .rdata_a_o(regfile_data_ra_id), @@ -1004,12 +1051,12 @@ module cv32e40px_id_stage // Write port a .waddr_a_i(regfile_waddr_wb_i), .wdata_a_i(regfile_wdata_wb_i), - .we_a_i (regfile_we_wb_i), + .we_a_i (regfile_we_wb_power_i), // Write port b .waddr_b_i(regfile_alu_waddr_fw_i), .wdata_b_i(regfile_alu_wdata_fw_i), - .we_b_i (regfile_alu_we_fw_i) + .we_b_i (regfile_alu_we_fw_power_i) ); logic [1:0] x_mem_data_type_id; @@ -1037,6 +1084,7 @@ module cv32e40px_id_stage .x_issue_valid_o (x_issue_valid_o), .x_issue_ready_i (x_issue_ready_i), .x_issue_resp_writeback_i(x_issue_resp_i.writeback), + .x_issue_resp_dualread_i (x_issue_resp_i.dualread), .x_issue_resp_accept_i (x_issue_resp_i.accept), .x_issue_resp_loadstore_i(x_issue_resp_i.loadstore), .x_issue_req_rs_valid_o (x_issue_req_o.rs_valid), @@ -1078,7 +1126,7 @@ module cv32e40px_id_stage .mem_instr_waddr_ex_i(regfile_waddr_ex_o[4:0]), .mem_instr_we_ex_i (regfile_we_ex_o), .regs_used_i (regs_used), - .branch_or_jump_i (pc_set_o), + .branch_or_jump_i (x_branch_or_async_taken), .instr_valid_i (instr_valid_i), .x_rs_addr_i (x_rs_addr), .x_ex_fwd_o (x_ex_fwd), @@ -1090,14 +1138,15 @@ module cv32e40px_id_stage .wb_ready_i (wb_ready_i), // additional status signals - .x_stall_o (x_stall), - .x_illegal_insn_o (x_illegal_insn), - .x_illegal_insn_dec_i(illegal_insn_dec), - .id_ready_i (id_ready_o), - .ex_valid_i (ex_valid_i), - .ex_ready_i (ex_ready_i), - .current_priv_lvl_i (current_priv_lvl_i), - .data_req_dec_i (data_req_id) + .x_stall_o (x_stall), + .x_illegal_insn_o (x_illegal_insn), + .x_illegal_insn_dec_i (illegal_insn_dec), + .x_control_illegal_reset_i(x_control_illegal_reset), + .id_ready_i (id_ready_o), + .ex_valid_i (ex_valid_i), + .ex_ready_i (ex_ready_i), + .current_priv_lvl_i (current_priv_lvl_i), + .data_req_dec_i (data_req_id) ); @@ -1118,22 +1167,25 @@ module cv32e40px_id_stage assign x_mem_valid = x_mem_valid_i; // xif integer souce operand selection - for (genvar i = 0; i < 3; i++) begin : xif_operand_assignment - always_comb begin - if (i == 0) begin - x_issue_req_o.rs[i] = regfile_data_ra_id; - end else if (i == 1) begin - x_issue_req_o.rs[i] = regfile_data_rb_id; - end else begin - x_issue_req_o.rs[i] = regfile_data_rc_id; - end - if (x_ex_fwd[i]) begin - x_issue_req_o.rs[i] = result_fw_to_x_i; - end else if (x_wb_fwd[i]) begin - x_issue_req_o.rs[i] = regfile_wdata_wb_i; + for (genvar j = 0; j < REGFILE_NUM_READ_PORTS; j++) begin : xif_operand_assignment_dualread + for (genvar i = 0; i < 3; i++) begin : xif_operand_assignment + always_comb begin + if (i == 0) begin + x_issue_req_o.rs[i+3*j] = regfile_data_ra_id[j]; + end else if (i == 1) begin + x_issue_req_o.rs[i+3*j] = regfile_data_rb_id[j]; + end else begin + x_issue_req_o.rs[i+3*j] = regfile_data_rc_id[j]; + end + if (x_ex_fwd[i+3*j]) begin + x_issue_req_o.rs[i+3*j] = result_fw_to_x_i; + end else if (x_wb_fwd[i+3*j]) begin + x_issue_req_o.rs[i+3*j] = regfile_wdata_wb_i; + end end end end + // LSU signal assignment/MUX always_comb begin x_mem_data_type_id = 2'b00; @@ -1300,7 +1352,7 @@ module cv32e40px_id_stage .debug_wfi_no_sleep_i(debug_wfi_no_sleep), // jump/branches - .ctrl_transfer_insn_in_dec_o (ctrl_transfer_insn_in_dec), + .ctrl_transfer_insn_in_dec_o (ctrl_transfer_insn_in_dec_o), .ctrl_transfer_insn_in_id_o (ctrl_transfer_insn_in_id), .ctrl_transfer_target_mux_sel_o(ctrl_transfer_target_mux_sel), @@ -1396,11 +1448,13 @@ module cv32e40px_id_stage .apu_write_dep_i (apu_write_dep_i), .apu_stall_o(apu_stall), + .x_branch_or_async_taken_o(x_branch_or_async_taken), + .x_control_illegal_reset_o(x_control_illegal_reset), // jump/branch control .branch_taken_ex_i (branch_taken_ex), .ctrl_transfer_insn_in_id_i (ctrl_transfer_insn_in_id), - .ctrl_transfer_insn_in_dec_i(ctrl_transfer_insn_in_dec), + .ctrl_transfer_insn_in_dec_i(ctrl_transfer_insn_in_dec_o), // Interrupt signals .irq_wu_ctrl_i (irq_wu_ctrl), @@ -1723,9 +1777,13 @@ module cv32e40px_id_stage if (id_valid_o) begin // unstall the whole pipeline alu_en_ex_o <= alu_en; if (alu_en) begin - alu_operator_ex_o <= alu_operator; - alu_operand_a_ex_o <= alu_operand_a; - alu_operand_b_ex_o <= alu_operand_b; + alu_operator_ex_o <= alu_operator; + alu_operand_a_ex_o <= alu_operand_a; + if (alu_op_b_mux_sel == OP_B_REGB_OR_FWD && (alu_operator == ALU_CLIP || alu_operator == ALU_CLIPU)) begin + alu_operand_b_ex_o <= {1'b0, alu_operand_b[30:0]}; + end else begin + alu_operand_b_ex_o <= alu_operand_b; + end alu_operand_c_ex_o <= alu_operand_c; bmask_a_ex_o <= bmask_a_id; bmask_b_ex_o <= bmask_b_id; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_load_store_unit.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_load_store_unit.sv index 674da664..92194ccd 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_load_store_unit.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_load_store_unit.sv @@ -121,18 +121,18 @@ module cv32e40px_load_store_unit #( 2'b00: begin // Writing a word if (misaligned_st == 1'b0) begin // non-misaligned case case (data_addr_int[1:0]) - 2'b00: data_be = 4'b1111; - 2'b01: data_be = 4'b1110; - 2'b10: data_be = 4'b1100; - 2'b11: data_be = 4'b1000; + 2'b00: data_be = 4'b1111; + 2'b01: data_be = 4'b1110; + 2'b10: data_be = 4'b1100; + default: data_be = 4'b1000; endcase ; // case (data_addr_int[1:0]) end else begin // misaligned case case (data_addr_int[1:0]) - 2'b00: data_be = 4'b0000; // this is not used, but included for completeness - 2'b01: data_be = 4'b0001; - 2'b10: data_be = 4'b0011; - 2'b11: data_be = 4'b0111; + 2'b01: data_be = 4'b0001; + 2'b10: data_be = 4'b0011; + 2'b11: data_be = 4'b0111; + default: data_be = 4'b0000; // this is not used, but included for completeness endcase ; // case (data_addr_int[1:0]) end @@ -141,10 +141,10 @@ module cv32e40px_load_store_unit #( 2'b01: begin // Writing a half word if (misaligned_st == 1'b0) begin // non-misaligned case case (data_addr_int[1:0]) - 2'b00: data_be = 4'b0011; - 2'b01: data_be = 4'b0110; - 2'b10: data_be = 4'b1100; - 2'b11: data_be = 4'b1000; + 2'b00: data_be = 4'b0011; + 2'b01: data_be = 4'b0110; + 2'b10: data_be = 4'b1100; + default: data_be = 4'b1000; endcase ; // case (data_addr_int[1:0]) end else begin // misaligned case @@ -154,10 +154,10 @@ module cv32e40px_load_store_unit #( 2'b10, 2'b11: begin // Writing a byte case (data_addr_int[1:0]) - 2'b00: data_be = 4'b0001; - 2'b01: data_be = 4'b0010; - 2'b10: data_be = 4'b0100; - 2'b11: data_be = 4'b1000; + 2'b00: data_be = 4'b0001; + 2'b01: data_be = 4'b0010; + 2'b10: data_be = 4'b0100; + default: data_be = 4'b1000; endcase ; // case (data_addr_int[1:0]) end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_ff.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_ff.sv index 1543f6e9..d0aad583 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_ff.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_ff.sv @@ -31,7 +31,9 @@ module cv32e40px_register_file #( parameter ADDR_WIDTH = 5, parameter DATA_WIDTH = 32, parameter FPU = 0, - parameter ZFINX = 0 + parameter ZFINX = 0, + parameter COREV_X_IF = 0, + parameter X_DUALREAD = 0 ) ( // Clock and Reset input logic clk, @@ -39,17 +41,19 @@ module cv32e40px_register_file #( input logic scan_cg_en_i, + input logic [2:0] dualread_i, + //Read port R1 - input logic [ADDR_WIDTH-1:0] raddr_a_i, - output logic [DATA_WIDTH-1:0] rdata_a_o, + input logic [ADDR_WIDTH-1:0] raddr_a_i, + output logic [X_DUALREAD:0][DATA_WIDTH-1:0] rdata_a_o, //Read port R2 - input logic [ADDR_WIDTH-1:0] raddr_b_i, - output logic [DATA_WIDTH-1:0] rdata_b_o, + input logic [ADDR_WIDTH-1:0] raddr_b_i, + output logic [X_DUALREAD:0][DATA_WIDTH-1:0] rdata_b_o, //Read port R3 - input logic [ADDR_WIDTH-1:0] raddr_c_i, - output logic [DATA_WIDTH-1:0] rdata_c_o, + input logic [ADDR_WIDTH-1:0] raddr_c_i, + output logic [X_DUALREAD:0][DATA_WIDTH-1:0] rdata_c_o, // Write port W1 input logic [ADDR_WIDTH-1:0] waddr_a_i, @@ -86,17 +90,53 @@ module cv32e40px_register_file #( //----------------------------------------------------------------------------- //-- READ : Read address decoder RAD //----------------------------------------------------------------------------- - assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; - assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; - assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; - + generate + if (COREV_X_IF != 0) begin + if (X_DUALREAD) begin + always_comb begin + rdata_a_o[0] = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + rdata_b_o[0] = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + rdata_c_o[0] = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + if (dualread_i[0] == 1) + rdata_a_o[1] = raddr_a_i[5] ? (mem_fp[{ + raddr_a_i[4:1], raddr_a_i[0]|1'b1 + }]) : (mem[{ + raddr_a_i[4:1], raddr_a_i[0]|1'b1 + }]); + else rdata_a_o[1] = '0; + if (dualread_i[1] == 1) + rdata_b_o[1] = raddr_b_i[5] ? (mem_fp[{ + raddr_b_i[4:1], raddr_b_i[0]|1'b1 + }]) : (mem[{ + raddr_b_i[4:1], raddr_b_i[0]|1'b1 + }]); + else rdata_b_o[1] = '0; + if (dualread_i[2] == 1) + rdata_c_o[1] = raddr_c_i[5] ? (mem_fp[{ + raddr_c_i[4:1], raddr_c_i[0]|1'b1 + }]) : (mem[{ + raddr_c_i[4:1], raddr_c_i[0]|1'b1 + }]); + else rdata_c_o[1] = '0; + end + end else begin + assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + end + end else begin + assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + end + endgenerate //----------------------------------------------------------------------------- //-- WRITE : Write Address Decoder (WAD), combinatorial process //----------------------------------------------------------------------------- // Mask top bit of write address to disable fp regfile - assign waddr_a = waddr_a_i; - assign waddr_b = waddr_b_i; + assign waddr_a = waddr_a_i; + assign waddr_b = waddr_b_i; genvar gidx; generate diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_latch.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_latch.sv index 037db7c4..63a23228 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_latch.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_register_file_latch.sv @@ -33,7 +33,9 @@ module cv32e40px_register_file #( parameter ADDR_WIDTH = 5, parameter DATA_WIDTH = 32, parameter FPU = 0, - parameter ZFINX = 0 + parameter ZFINX = 0, + parameter COREV_X_IF = 0, + parameter X_DUALREAD = 0 ) ( // Clock and Reset input logic clk, @@ -41,17 +43,19 @@ module cv32e40px_register_file #( input logic scan_cg_en_i, + input logic dualread_i, + //Read port R1 - input logic [ADDR_WIDTH-1:0] raddr_a_i, - output logic [DATA_WIDTH-1:0] rdata_a_o, + input logic [ADDR_WIDTH-1:0] raddr_a_i, + output logic [X_DUALREAD:0][DATA_WIDTH-1:0] rdata_a_o, //Read port R2 - input logic [ADDR_WIDTH-1:0] raddr_b_i, - output logic [DATA_WIDTH-1:0] rdata_b_o, + input logic [ADDR_WIDTH-1:0] raddr_b_i, + output logic [X_DUALREAD:0][DATA_WIDTH-1:0] rdata_b_o, //Read port R3 - input logic [ADDR_WIDTH-1:0] raddr_c_i, - output logic [DATA_WIDTH-1:0] rdata_c_o, + input logic [ADDR_WIDTH-1:0] raddr_c_i, + output logic [X_DUALREAD:0][DATA_WIDTH-1:0] rdata_c_o, // Write port W1 input logic [ADDR_WIDTH-1:0] waddr_a_i, @@ -98,10 +102,37 @@ module cv32e40px_register_file #( //----------------------------------------------------------------------------- //-- READ : Read address decoder RAD //----------------------------------------------------------------------------- - assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; - assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; - assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; - + generate + if (COREV_X_IF != 0) begin + if (X_DUALREAD) begin + always_comb begin + if (dualread_i) begin + rdata_a_o[0] = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + rdata_b_o[0] = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + rdata_c_o[0] = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + rdata_a_o[1] = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0] | 5'b00001] : mem[raddr_a_i[4:0] | 5'b00001]; + rdata_b_o[1] = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0] | 5'b00001] : mem[raddr_b_i[4:0] | 5'b00001]; + rdata_c_o[1] = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0] | 5'b00001] : mem[raddr_c_i[4:0] | 5'b00001]; + end else begin + rdata_a_o[0] = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + rdata_b_o[0] = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + rdata_c_o[0] = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + rdata_b_o[1] = '0; + rdata_a_o[1] = '0; + rdata_c_o[1] = '0; + end + end + end else begin + assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + end + end else begin + assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + end + endgenerate //----------------------------------------------------------------------------- // WRITE : SAMPLE INPUT DATA //--------------------------------------------------------------------------- @@ -172,8 +203,8 @@ module cv32e40px_register_file #( mem[0] = '0; for (k = 1; k < NUM_WORDS; k++) begin : w_WordIter - if (~rst_n) mem[k] = '0; - else if (mem_clocks[k] == 1'b1) mem[k] = waddr_onehot_b_q[k] ? wdata_b_q : wdata_a_q; + if (~rst_n) mem[k] <= '0; + else if (mem_clocks[k] == 1'b1) mem[k] <= waddr_onehot_b_q[k] ? wdata_b_q : wdata_a_q; end end @@ -182,9 +213,9 @@ module cv32e40px_register_file #( always_latch begin : latch_wdata_fp if (FPU == 1) begin for (l = 0; l < NUM_FP_WORDS; l++) begin : w_WordIter - if (~rst_n) mem_fp[l] = '0; + if (~rst_n) mem_fp[l] <= '0; else if (mem_clocks[l+NUM_WORDS] == 1'b1) - mem_fp[l] = waddr_onehot_b_q[l+NUM_WORDS] ? wdata_b_q : wdata_a_q; + mem_fp[l] <= waddr_onehot_b_q[l+NUM_WORDS] ? wdata_b_q : wdata_a_q; end end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_top.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_top.sv index ad3dc986..03b99626 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_top.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_top.sv @@ -1,15 +1,27 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Top file instantiating a CV32E40P core and an optional FPU -// Contributor: Davide Schiavone +// Copyright 2024 Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +///////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Pascal Gouedo, Dolphin Design // +// // +// Description: Top level module of CV32E40P instantiating the Core and // +// an optional CVFPU with its clock gating cell. // +// // +///////////////////////////////////////////////////////////////////////////// module cv32e40px_top import cv32e40px_core_v_xif_pkg::*; @@ -105,7 +117,7 @@ module cv32e40px_top import cv32e40px_apu_core_pkg::*; // Core to FPU - logic clk; + logic apu_busy; logic apu_req; logic [ APU_NARGS_CPU-1:0][31:0] apu_operands; logic [ APU_WOP_CPU-1:0] apu_op; @@ -117,6 +129,8 @@ module cv32e40px_top logic [ 31:0] apu_rdata; logic [APU_NUSFLAGS_CPU-1:0] apu_rflags; + logic apu_clk_en, apu_clk; + // Instantiate the Core cv32e40px_core #( .COREV_X_IF (COREV_X_IF), @@ -155,6 +169,7 @@ module cv32e40px_top .data_wdata_o (data_wdata_o), .data_rdata_i (data_rdata_i), + .apu_busy_o (apu_busy), .apu_req_o (apu_req), .apu_gnt_i (apu_gnt), .apu_operands_o(apu_operands), @@ -211,12 +226,15 @@ module cv32e40px_top generate if (FPU) begin : fpu_gen + + assign apu_clk_en = apu_req | apu_busy; + // FPU clock gate cv32e40px_clock_gate core_clock_gate_i ( .clk_i (clk_i), - .en_i (!core_sleep_o), + .en_i (apu_clk_en), .scan_cg_en_i(scan_cg_en_i), - .clk_o (clk) + .clk_o (apu_clk) ); // Instantiate the FPU wrapper @@ -224,7 +242,7 @@ module cv32e40px_top .FPU_ADDMUL_LAT(FPU_ADDMUL_LAT), .FPU_OTHERS_LAT(FPU_OTHERS_LAT) ) fp_wrapper_i ( - .clk_i (clk), + .clk_i (apu_clk), .rst_ni (rst_ni), .apu_req_i (apu_req), .apu_gnt_o (apu_gnt), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_x_disp.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_x_disp.sv index 71bbf665..f326b3f9 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_x_disp.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/cv32e40px_x_disp.sv @@ -8,16 +8,16 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. -//////////////////////////////////////////////////////////////////////////////// -// Engineer: Moritz Imfeld - moimfeld@student.ethz.ch // -// // -// Design Name: x-interface dispatcher // -// Project Name: cv32e40px // -// Language: SystemVerilog // -// // -// Description: Dispatcher for sending instructions to the x-interface. // -// // -//////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// Engineer: Moritz Imfeld - moimfeld@ee.ethz.ch // +// // +// Design Name: x-interface dispatcher // +// Project Name: cv32e40px // +// Language: SystemVerilog // +// // +// Description: Dispatcher for sending instructions to the x-interface. // +// // +///////////////////////////////////////////////////////////////////////////// module cv32e40px_x_disp import cv32e40px_core_v_xif_pkg::*; @@ -33,11 +33,13 @@ module cv32e40px_x_disp input logic x_issue_ready_i, input logic x_issue_resp_accept_i, input logic x_issue_resp_writeback_i, - input logic x_issue_resp_loadstore_i, // unused - output logic [2:0] x_issue_req_rs_valid_o, - output logic [3:0] x_issue_req_id_o, - output logic [1:0] x_issue_req_mode_o, - output logic x_issue_req_ecs_valid, + + input logic [ 2:0] x_issue_resp_dualread_i, + input logic x_issue_resp_loadstore_i, // unused + output logic [RF_READ_PORTS-1:0] x_issue_req_rs_valid_o, + output logic [ 3:0] x_issue_req_id_o, + output logic [ 1:0] x_issue_req_mode_o, + output logic x_issue_req_ecs_valid, // commit interface output logic x_commit_valid_o, @@ -65,19 +67,19 @@ module cv32e40px_x_disp input logic x_result_we_i, // scoreboard, dependency check, stall, forwarding - input logic [4:0] waddr_id_i, - input logic [4:0] waddr_ex_i, - input logic [4:0] waddr_wb_i, - input logic we_ex_i, - input logic we_wb_i, - input logic [4:0] mem_instr_waddr_ex_i, - input logic mem_instr_we_ex_i, - input logic [2:0] regs_used_i, - input logic branch_or_jump_i, - input logic instr_valid_i, - input logic [2:0][4:0] x_rs_addr_i, - output logic [2:0] x_ex_fwd_o, - output logic [2:0] x_wb_fwd_o, + input logic [ 4:0] waddr_id_i, + input logic [ 4:0] waddr_ex_i, + input logic [ 4:0] waddr_wb_i, + input logic we_ex_i, + input logic we_wb_i, + input logic [ 4:0] mem_instr_waddr_ex_i, + input logic mem_instr_we_ex_i, + input logic [ 2:0] regs_used_i, + input logic branch_or_jump_i, + input logic instr_valid_i, + input logic [ 2:0][4:0] x_rs_addr_i, + output logic [RF_READ_PORTS-1:0] x_ex_fwd_o, + output logic [RF_READ_PORTS-1:0] x_wb_fwd_o, // memory request core-internal status signals output logic x_mem_data_req_o, @@ -88,6 +90,7 @@ module cv32e40px_x_disp output logic x_stall_o, output logic x_illegal_insn_o, input logic x_illegal_insn_dec_i, + input logic x_control_illegal_reset_i, input logic id_ready_i, input logic ex_valid_i, input logic ex_ready_i, @@ -105,18 +108,37 @@ module cv32e40px_x_disp logic x_if_not_ready; logic x_if_memory_instr; logic illegal_forwarding_prevention; + logic x_issue_illegal; + logic x_illegal_insn_q, x_illegal_insn_n; // issue interface assign x_issue_valid_o = x_illegal_insn_dec_i & ~branch_or_jump_i & ~instr_offloaded_q & instr_valid_i & ~illegal_forwarding_prevention; assign x_issue_req_id_o = id_q; - assign x_issue_req_rs_valid_o[0] = (~scoreboard_q[x_rs_addr_i[0]] | x_ex_fwd_o[0] | x_wb_fwd_o[0]) - & ~(x_rs_addr_i[0] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[0] == waddr_wb_i & ~ex_valid_i); - assign x_issue_req_rs_valid_o[1] = (~scoreboard_q[x_rs_addr_i[1]] | x_ex_fwd_o[1] | x_wb_fwd_o[1]) - & ~(x_rs_addr_i[1] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[1] == waddr_wb_i & ~ex_valid_i); - assign x_issue_req_rs_valid_o[2] = (~scoreboard_q[x_rs_addr_i[2]] | x_ex_fwd_o[2] | x_wb_fwd_o[2]) - & ~(x_rs_addr_i[2] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[2] == waddr_wb_i & ~ex_valid_i); - assign x_issue_req_ecs_valid = 1'b1; // extension context status is not implemented in cv32e40px - + generate + if (X_DUALREAD != 0) begin + assign x_issue_req_rs_valid_o[0] = (~scoreboard_q[x_rs_addr_i[0]] | x_ex_fwd_o[0] | x_wb_fwd_o[0]) + & ~(x_rs_addr_i[0] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[0] == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[1] = (~scoreboard_q[x_rs_addr_i[1]] | x_ex_fwd_o[1] | x_wb_fwd_o[1]) + & ~(x_rs_addr_i[1] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[1] == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[2] = (~scoreboard_q[x_rs_addr_i[2]] | x_ex_fwd_o[2] | x_wb_fwd_o[2]) + & ~(x_rs_addr_i[2] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[2] == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[3] = (~scoreboard_q[x_rs_addr_i[0] | 5'b00001] | x_ex_fwd_o[3] | x_wb_fwd_o[3]) + & ~((x_rs_addr_i[0] | 5'b00001) == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~((x_rs_addr_i[0] | 5'b00001) == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[4] = (~scoreboard_q[x_rs_addr_i[1] | 5'b00001] | x_ex_fwd_o[4] | x_wb_fwd_o[4]) + & ~((x_rs_addr_i[1] | 5'b00001) == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~((x_rs_addr_i[1] | 5'b00001) == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[5] = (~scoreboard_q[x_rs_addr_i[2] | 5'b00001] | x_ex_fwd_o[5] | x_wb_fwd_o[5]) + & ~((x_rs_addr_i[2] | 5'b00001) == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~((x_rs_addr_i[2] | 5'b00001) == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_ecs_valid = 1'b1; // extension context status is not implemented in cv32e40px + end else begin + assign x_issue_req_rs_valid_o[0] = (~scoreboard_q[x_rs_addr_i[0]] | x_ex_fwd_o[0] | x_wb_fwd_o[0]) + & ~(x_rs_addr_i[0] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[0] == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[1] = (~scoreboard_q[x_rs_addr_i[1]] | x_ex_fwd_o[1] | x_wb_fwd_o[1]) + & ~(x_rs_addr_i[1] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[1] == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_rs_valid_o[2] = (~scoreboard_q[x_rs_addr_i[2]] | x_ex_fwd_o[2] | x_wb_fwd_o[2]) + & ~(x_rs_addr_i[2] == mem_instr_waddr_ex_i & mem_instr_we_ex_i) & ~(x_rs_addr_i[2] == waddr_wb_i & ~ex_valid_i); + assign x_issue_req_ecs_valid = 1'b1; // extension context status is not implemented in cv32e40px + end + endgenerate // commit interface assign x_commit_valid_o = x_issue_valid_o; assign x_commit_id_o = id_q; @@ -140,22 +162,46 @@ module cv32e40px_x_disp // core stall signal assign x_stall_o = dep | outstanding_mem | x_if_not_ready | x_if_memory_instr | illegal_forwarding_prevention; - assign dep = ~x_illegal_insn_o & ((regs_used_i[0] & scoreboard_q[x_rs_addr_i[0]] & (x_result_rd_i != x_rs_addr_i[0])) - | (regs_used_i[1] & scoreboard_q[x_rs_addr_i[1]] & (x_result_rd_i != x_rs_addr_i[1])) - | (regs_used_i[2] & scoreboard_q[x_rs_addr_i[2]] & (x_result_rd_i != x_rs_addr_i[2]))); + assign outstanding_mem = data_req_dec_i & (mem_counter_q != '0); assign x_if_memory_instr = x_mem_data_req_o & ~(x_issue_valid_o & x_issue_ready_i); assign x_if_not_ready = x_issue_valid_o & ~x_issue_ready_i; - assign illegal_forwarding_prevention = x_result_valid_i & (x_ex_fwd_o[0] | x_ex_fwd_o[1] | x_ex_fwd_o[2]); + assign illegal_forwarding_prevention = x_result_valid_i & (|x_ex_fwd_o); // forwarding - assign x_ex_fwd_o[0] = x_rs_addr_i[0] == waddr_ex_i & we_ex_i & ex_valid_i; - assign x_ex_fwd_o[1] = x_rs_addr_i[1] == waddr_ex_i & we_ex_i & ex_valid_i; - assign x_ex_fwd_o[2] = x_rs_addr_i[2] == waddr_ex_i & we_ex_i & ex_valid_i; - assign x_wb_fwd_o[0] = x_rs_addr_i[0] == waddr_wb_i & we_wb_i & ex_valid_i; - assign x_wb_fwd_o[1] = x_rs_addr_i[1] == waddr_wb_i & we_wb_i & ex_valid_i; - assign x_wb_fwd_o[2] = x_rs_addr_i[2] == waddr_wb_i & we_wb_i & ex_valid_i; + generate + if (X_DUALREAD != 0) begin + assign x_ex_fwd_o[0] = x_rs_addr_i[0] == waddr_ex_i & we_ex_i & ex_valid_i; + assign x_ex_fwd_o[1] = x_rs_addr_i[1] == waddr_ex_i & we_ex_i & ex_valid_i; + assign x_ex_fwd_o[2] = x_rs_addr_i[2] == waddr_ex_i & we_ex_i & ex_valid_i; + assign x_ex_fwd_o[3] = (x_rs_addr_i[0] | 5'b00001) == waddr_ex_i & we_ex_i & ex_valid_i & x_issue_resp_dualread_i[0]; + assign x_ex_fwd_o[4] = (x_rs_addr_i[1] | 5'b00001) == waddr_ex_i & we_ex_i & ex_valid_i & x_issue_resp_dualread_i[1]; + assign x_ex_fwd_o[5] = (x_rs_addr_i[2] | 5'b00001) == waddr_ex_i & we_ex_i & ex_valid_i & x_issue_resp_dualread_i[2]; + assign x_wb_fwd_o[0] = x_rs_addr_i[0] == waddr_wb_i & we_wb_i & ex_valid_i; + assign x_wb_fwd_o[1] = x_rs_addr_i[1] == waddr_wb_i & we_wb_i & ex_valid_i; + assign x_wb_fwd_o[2] = x_rs_addr_i[2] == waddr_wb_i & we_wb_i & ex_valid_i; + assign x_wb_fwd_o[3] = (x_rs_addr_i[0] | 5'b00001) == waddr_wb_i & we_wb_i & ex_valid_i & x_issue_resp_dualread_i[0]; + assign x_wb_fwd_o[4] = (x_rs_addr_i[1] | 5'b00001) == waddr_wb_i & we_wb_i & ex_valid_i & x_issue_resp_dualread_i[1]; + assign x_wb_fwd_o[5] = (x_rs_addr_i[2] | 5'b00001) == waddr_wb_i & we_wb_i & ex_valid_i & x_issue_resp_dualread_i[2]; + assign dep = ~x_illegal_insn_n & ((regs_used_i[0] & scoreboard_q[x_rs_addr_i[0]] & (x_result_rd_i != x_rs_addr_i[0])) + | (regs_used_i[1] & scoreboard_q[x_rs_addr_i[1]] & (x_result_rd_i != x_rs_addr_i[1])) + | (regs_used_i[2] & scoreboard_q[x_rs_addr_i[2]] & (x_result_rd_i != x_rs_addr_i[2])) + | (((regs_used_i[0] & x_issue_resp_dualread_i[0]) & scoreboard_q[x_rs_addr_i[0] | 5'b00001] & (x_result_rd_i != (x_rs_addr_i[0] | 5'b00001))) & x_issue_resp_dualread_i[0]) + | (((regs_used_i[1] & x_issue_resp_dualread_i[1]) & scoreboard_q[x_rs_addr_i[1] | 5'b00001] & (x_result_rd_i != (x_rs_addr_i[1] | 5'b00001))) & x_issue_resp_dualread_i[1]) + | (((regs_used_i[2] & x_issue_resp_dualread_i[2]) & scoreboard_q[x_rs_addr_i[2] | 5'b00001] & (x_result_rd_i != (x_rs_addr_i[2] | 5'b00001))) & x_issue_resp_dualread_i[2])); + end else begin + assign x_ex_fwd_o[0] = x_rs_addr_i[0] == waddr_ex_i & we_ex_i & ex_valid_i; + assign x_ex_fwd_o[1] = x_rs_addr_i[1] == waddr_ex_i & we_ex_i & ex_valid_i; + assign x_ex_fwd_o[2] = x_rs_addr_i[2] == waddr_ex_i & we_ex_i & ex_valid_i; + assign x_wb_fwd_o[0] = x_rs_addr_i[0] == waddr_wb_i & we_wb_i & ex_valid_i; + assign x_wb_fwd_o[1] = x_rs_addr_i[1] == waddr_wb_i & we_wb_i & ex_valid_i; + assign x_wb_fwd_o[2] = x_rs_addr_i[2] == waddr_wb_i & we_wb_i & ex_valid_i; + assign dep = ~x_illegal_insn_n & ((regs_used_i[0] & scoreboard_q[x_rs_addr_i[0]] & (x_result_rd_i != x_rs_addr_i[0])) + | (regs_used_i[1] & scoreboard_q[x_rs_addr_i[1]] & (x_result_rd_i != x_rs_addr_i[1])) + | (regs_used_i[2] & scoreboard_q[x_rs_addr_i[2]] & (x_result_rd_i != x_rs_addr_i[2]))); + end + endgenerate // id generation assign x_compressed_id_o = id_d; @@ -200,13 +246,15 @@ module cv32e40px_x_disp end end - // illegal instruction assertion + // illegal instruction assignment + assign x_issue_illegal = x_illegal_insn_dec_i & ~instr_offloaded_q & instr_valid_i; always_comb begin - x_illegal_insn_o = 1'b0; - if (x_issue_valid_o & x_issue_ready_i & ~x_issue_resp_accept_i) begin - x_illegal_insn_o = 1'b1; + x_illegal_insn_n = 1'b0; + if (x_issue_illegal & x_issue_ready_i & ~x_issue_resp_accept_i) begin + x_illegal_insn_n = 1'b1; end end + assign x_illegal_insn_o = x_illegal_insn_q; // scoreboard and status signal register always_ff @(posedge clk_i or negedge rst_ni) begin @@ -215,11 +263,17 @@ module cv32e40px_x_disp instr_offloaded_q <= 1'b0; id_q <= '0; mem_counter_q <= '0; + x_illegal_insn_q <= 1'b0; end else begin scoreboard_q <= scoreboard_d; instr_offloaded_q <= instr_offloaded_d; id_q <= id_d; mem_counter_q <= mem_counter_d; + if (x_control_illegal_reset_i) begin + x_illegal_insn_q <= 1'b0; + end else begin + x_illegal_insn_q <= x_illegal_insn_n; + end end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/include/cv32e40px_core_v_xif_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/include/cv32e40px_core_v_xif_pkg.sv index 499fec31..678635d0 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/include/cv32e40px_core_v_xif_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/esl_epfl_cv32e40px/rtl/include/cv32e40px_core_v_xif_pkg.sv @@ -15,6 +15,7 @@ package cv32e40px_core_v_xif_pkg; // cv-x-if parameters parameter int X_NUM_RS = 3; + parameter int X_DUALREAD = 0; // 0: single read, 1: dual read parameter int X_ID_WIDTH = 4; parameter int X_MEM_WIDTH = 32; parameter int X_RFR_WIDTH = 32; @@ -23,6 +24,8 @@ package cv32e40px_core_v_xif_pkg; parameter logic [1:0] X_ECS_XS = '0; localparam int XLEN = 32; + localparam int RF_READ_PORTS = (X_DUALREAD == 1) ? 2 * X_NUM_RS : X_NUM_RS; + typedef struct packed { logic [15:0] instr; // Offloaded compressed instruction @@ -39,8 +42,8 @@ package cv32e40px_core_v_xif_pkg; logic [31:0] instr; // Offloaded instruction logic [1:0] mode; // Privilege level logic [X_ID_WIDTH-1:0] id; // Identification of the offloaded instruction - logic [X_NUM_RS -1:0][X_RFR_WIDTH-1:0] rs; // Register file source operands for the offloaded instruction - logic [X_NUM_RS -1:0] rs_valid; // Validity of the register file source operand(s) + logic [RF_READ_PORTS-1:0][X_RFR_WIDTH-1:0] rs; // Register file source operands for the offloaded instruction + logic [RF_READ_PORTS-1:0] rs_valid; // Validity of the register file source operand(s) logic [5:0] ecs; // Extension Context Status ({mstatus.xs, mstatus.fs, mstatus.vs}) logic ecs_valid; // Validity of the Extension Context Status } x_issue_req_t; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/lowrisc_opentitan/hw/dv/dpi/uartdpi/uartdpi.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/lowrisc_opentitan/hw/dv/dpi/uartdpi/uartdpi.sv index 07c75cf8..2be4df54 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/lowrisc_opentitan/hw/dv/dpi/uartdpi/uartdpi.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/lowrisc_opentitan/hw/dv/dpi/uartdpi/uartdpi.sv @@ -84,11 +84,13 @@ module uartdpi #( `ifndef VCS `ifndef MODELSIM +`ifndef XCELIUM initial begin // Prevent falling edges of rx_i before reset causing spurious characters seen_reset = 0; end `endif +`endif `endif // RX diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/.readthedocs.yaml b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/.readthedocs.yaml new file mode 100644 index 00000000..00178f19 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/.readthedocs.yaml @@ -0,0 +1,23 @@ +# Copyright 2023 OpenHW Group +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +build: + os: "ubuntu-20.04" + tools: + python: "3.9" + +# Build from the docs directory with Sphinx +sphinx: + configuration: doc/conf.py + +# Explicitly set the Python requirements +python: + install: + - requirements: doc/requirements.txt \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/bhv/cve2_sim_clock_gate.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/bhv/cve2_sim_clock_gate.sv index 8cc81dd3..7974cf92 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/bhv/cve2_sim_clock_gate.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/bhv/cve2_sim_clock_gate.sv @@ -27,4 +27,4 @@ module cve2_clock_gate ( assign clk_o = clk_i & clk_en; -endmodule // cv32e40p_clock_gate +endmodule // cve2_clock_gate diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist new file mode 100644 index 00000000..4a0142d8 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cv32e20_manifest.flist @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2022 OpenHW Group +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +/////////////////////////////////////////////////////////////////////////////// +// +// Manifest for the CV32E20 RTL model. +// - Format based on manifest used by other CORE-V cores. +// - Intended to be used by both synthesis and simulation. +// - Relevent synthesis and simulation scripts/Makefiles must set the shell +// ENV variable DESIGN_RTL_DIR as required. +// +// TODO: Replace once-and-for-all with unified manifest (FuseSoc?) +// +/////////////////////////////////////////////////////////////////////////////// + ++incdir+${DESIGN_RTL_DIR}/../shared/rtl/ ++incdir+${DESIGN_RTL_DIR}/../rtl ++incdir+${DESIGN_RTL_DIR}/../shared/rtl/sim ++incdir+${DESIGN_RTL_DIR}/../vendor/lowrisc_ip/ip/prim/rtl ++incdir+${DESIGN_RTL_DIR}/../vendor/lowrisc_ip/dv/sv/dv_utils + +${DESIGN_RTL_DIR}/cve2_pkg.sv +${DESIGN_RTL_DIR}/cve2_tracer_pkg.sv +${DESIGN_RTL_DIR}/../vendor/lowrisc_ip/ip/prim/rtl/prim_secded_pkg.sv +${DESIGN_RTL_DIR}/../vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_pkg.sv +${DESIGN_RTL_DIR}/cve2_alu.sv +${DESIGN_RTL_DIR}/cve2_compressed_decoder.sv +${DESIGN_RTL_DIR}/cve2_controller.sv +${DESIGN_RTL_DIR}/cve2_cs_registers.sv +${DESIGN_RTL_DIR}/cve2_csr.sv +${DESIGN_RTL_DIR}/cve2_counter.sv +${DESIGN_RTL_DIR}/cve2_decoder.sv +${DESIGN_RTL_DIR}/cve2_ex_block.sv +${DESIGN_RTL_DIR}/cve2_fetch_fifo.sv +${DESIGN_RTL_DIR}/cve2_id_stage.sv +${DESIGN_RTL_DIR}/cve2_if_stage.sv +${DESIGN_RTL_DIR}/cve2_load_store_unit.sv +${DESIGN_RTL_DIR}/cve2_multdiv_fast.sv +${DESIGN_RTL_DIR}/cve2_multdiv_slow.sv +${DESIGN_RTL_DIR}/cve2_prefetch_buffer.sv +${DESIGN_RTL_DIR}/cve2_pmp.sv +${DESIGN_RTL_DIR}/cve2_register_file_ff.sv +${DESIGN_RTL_DIR}/cve2_wb.sv +${DESIGN_RTL_DIR}/cve2_core.sv +${DESIGN_RTL_DIR}/cve2_top.sv +${DESIGN_RTL_DIR}/cve2_top_tracing.sv +${DESIGN_RTL_DIR}/cve2_tracer.sv + +${DESIGN_RTL_DIR}/../bhv/cve2_sim_clock_gate.sv diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_configs.yaml b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_configs.yaml new file mode 100644 index 00000000..1dba358d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_configs.yaml @@ -0,0 +1,94 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +# Ibex configurations files, holds the parameter sets that are tested under CI. +# Each configuration must specify the same set of parameters + +# Two-stage pipeline without additional branch target ALU and 3 cycle multiplier +# (4 cycles for mulh), resulting in 2 stall cycles for mul (3 for mulh) +small: + RV32E : 0 + RV32M : "cve2_pkg::RV32MFast" + RV32B : "cve2_pkg::RV32BNone" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 0 + PMPEnable : 0 + PMPGranularity : 0 + PMPNumRegions : 4 + +# Configuration to match that used in the OpenTitan project +opentitan: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BOTEarlGrey" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + PMPEnable : 1 + PMPGranularity : 0 + PMPNumRegions : 16 + +# =============================== +# * EXPERIMENTAL CONFIGURATIONS * +# =============================== + +# Three-stage pipeline with additional branch traget ALU and 1 cycle multiplier +# (2 cycles for mulh) so mul does not stall (mulh stall 1 cycles). This is the +# maximum performance configuration. +experimental-maxperf: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BNone" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + PMPEnable : 0 + PMPGranularity : 0 + PMPNumRegions : 4 + +# experimental-maxperf config above plus PMP enabled with 16 regions. +experimental-maxperf-pmp: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BNone" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + PMPEnable : 1 + PMPGranularity : 0 + PMPNumRegions : 16 + +# experimental-maxperf-pmp config above with balanced bitmanip extension +experimental-maxperf-pmp-bmbalanced: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BBalanced" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + PMPEnable : 1 + PMPGranularity : 0 + PMPNumRegions : 16 + +# experimental-maxperf-pmp config above with full bitmanip extension +experimental-maxperf-pmp-bmfull: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BFull" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + PMPEnable : 1 + PMPGranularity : 0 + PMPNumRegions : 16 + +# experimental-maxperf with branch predictor switched on. This exists to allow +# easy use of Ibex with the branch predictor in particular for CI runs. The +# branch predictor will be enabled in all the 'maxperf' configs after further +# development. +experimental-branch-predictor: + RV32E : 0 + RV32M : "cve2_pkg::RV32MSingleCycle" + RV32B : "cve2_pkg::RV32BNone" + RegFile : "cve2_pkg::RegFileFF" + WritebackStage : 1 + PMPEnable : 0 + PMPGranularity : 0 + PMPNumRegions : 4 + diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_core.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_core.core new file mode 100644 index 00000000..6d621a43 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_core.core @@ -0,0 +1,115 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "openhwgroup:cve2:cve2_core:0.1" +description: "Ibex CPU Core Components" + +filesets: + files_rtl: + depend: + - lowrisc:prim:assert + - openhwgroup:cve2:cve2_pkg + - lowrisc:dv:dv_fcov_macros + files: + - rtl/cve2_alu.sv + - rtl/cve2_branch_predict.sv + - rtl/cve2_compressed_decoder.sv + - rtl/cve2_controller.sv + - rtl/cve2_cs_registers.sv + - rtl/cve2_csr.sv + - rtl/cve2_counter.sv + - rtl/cve2_decoder.sv + - rtl/cve2_ex_block.sv + - rtl/cve2_fetch_fifo.sv + - rtl/cve2_id_stage.sv + - rtl/cve2_if_stage.sv + - rtl/cve2_load_store_unit.sv + - rtl/cve2_multdiv_fast.sv + - rtl/cve2_multdiv_slow.sv + - rtl/cve2_prefetch_buffer.sv + - rtl/cve2_pmp.sv + - rtl/cve2_wb.sv + - rtl/cve2_core.sv + - rtl/cve2_pmp_reset_default.svh: {is_include_file: true} + file_type: systemVerilogSource + + files_lint_verilator: + files: + - lint/verilator_waiver.vlt: {file_type: vlt} + + files_lint_verible: + files: + - lint/verible_waiver.vbw: {file_type: veribleLintWaiver} + + files_check_tool_requirements: + depend: + - lowrisc:tool:check_tool_requirements + +parameters: + RVFI: + datatype: bool + paramtype: vlogdefine + + SYNTHESIS: + datatype: bool + paramtype: vlogdefine + + FPGA_XILINX: + datatype: bool + description: Identifies Xilinx FPGA targets to set DSP pragmas for performance counters. + default: false + paramtype: vlogdefine + + RV32E: + datatype: int + default: 0 + paramtype: vlogparam + + RV32M: + datatype: str + default: cve2_pkg::RV32MFast + paramtype: vlogdefine + description: "RV32M implementation parameter enum. See the cve2_pkg::rv32m_e enum in cve2_pkg.sv for permitted values." + + RV32B: + datatype: str + default: cve2_pkg::RV32BNone + paramtype: vlogdefine + description: "Bitmanip implementation parameter enum. See the cve2_pkg::rv32b_e enum in cve2_pkg.sv for permitted values." + +targets: + default: &default_target + filesets: + - tool_verilator ? (files_lint_verilator) + - tool_veriblelint ? (files_lint_verible) + - files_rtl + toplevel: cve2_core + parameters: + - tool_vivado ? (FPGA_XILINX=true) + lint: + <<: *default_target + parameters: + - SYNTHESIS=true + - RVFI=true + default_tool: verilator + tools: + verilator: + mode: lint-only + verilator_options: + - "-Wall" + # RAM primitives wider than 64bit (required for ECC) fail to build in + # Verilator without increasing the unroll count (see Verilator#1266) + - "--unroll-count 72" + format: + filesets: + - files_rtl + parameters: + - SYNTHESIS=true + - RVFI=true + default_tool: veribleformat + toplevel: cve2_core + tools: + veribleformat: + verible_format_args: + - "--inplace" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_icache.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_icache.core new file mode 100644 index 00000000..ad2c2617 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_icache.core @@ -0,0 +1,22 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:cve2:cve2_icache:0.1" +description: "Ibex instruction cache" +filesets: + files_rtl: + depend: + - lowrisc:prim:secded + - lowrisc:prim:assert + - lowrisc:cve2:cve2_pkg + files: + - rtl/cve2_icache.sv + file_type: systemVerilogSource + +targets: + default: &default_target + filesets: + - files_rtl + toplevel: cve2_icache + default_tool: vcs diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_multdiv.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_multdiv.core new file mode 100644 index 00000000..700e6c9e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_multdiv.core @@ -0,0 +1,28 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:cve2:cve2_multdiv:0.1" +description: "Multiplier and divider" + +filesets: + files_rtl: + depend: + - lowrisc:prim:assert + - lowrisc:cve2:cve2_pkg + files: + - rtl/cve2_multdiv_fast.sv + - rtl/cve2_multdiv_slow.sv + file_type: systemVerilogSource + +parameters: + RV32M: + datatype: int + default: 2 + paramtype: vlogparam + description: "Selection of multiplication implementation. Switch to enable single cycle multiplications." + +targets: + default: &default_target + filesets: + - files_rtl diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/ibex_pkg.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_pkg.core similarity index 73% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/ibex_pkg.core rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_pkg.core index 17f47e08..a89c9e12 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/ibex_pkg.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_pkg.core @@ -2,13 +2,13 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -name: "lowrisc:ibex:ibex_pkg:0.1" -description: "Header package for Ibex" +name: "openhwgroup:cve2:cve2_pkg:0.1" +description: "Header package for CVE2" filesets: files_rtl: files: - - rtl/ibex_pkg.sv + - rtl/cve2_pkg.sv file_type: systemVerilogSource targets: diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_top.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_top.core new file mode 100644 index 00000000..0d9d2c5c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_top.core @@ -0,0 +1,115 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "openhwgroup:cve2:cve2_top:0.1" +description: "Ibex, a small RV32 CPU core" + +filesets: + files_rtl: + depend: + - openhwgroup:cve2:cve2_pkg + - openhwgroup:cve2:cve2_core + - lowrisc:prim:buf + - lowrisc:prim:clock_mux2 + - lowrisc:prim:flop + - lowrisc:prim:ram_1p_scr + files: + - rtl/cve2_register_file_ff.sv # generic FF-based + - rtl/cve2_top.sv + file_type: systemVerilogSource + + files_lint_verilator: + files: + - lint/verilator_waiver.vlt: {file_type: vlt} + + files_lint_verible: + files: + - lint/verible_waiver.vbw: {file_type: veribleLintWaiver} + + files_check_tool_requirements: + depend: + - lowrisc:tool:check_tool_requirements + + files_clk_gate: + files: + - bhv/cve2_sim_clock_gate.sv + file_type: systemVerilogSource + +parameters: + RVFI: + datatype: bool + paramtype: vlogdefine + + SYNTHESIS: + datatype: bool + paramtype: vlogdefine + + FPGA_XILINX: + datatype: bool + description: Identifies Xilinx FPGA targets to set DSP pragmas for performance counters. + default: false + paramtype: vlogdefine + + RV32E: + datatype: int + default: 0 + paramtype: vlogparam + + RV32M: + datatype: str + default: cve2_pkg::RV32MFast + paramtype: vlogdefine + description: "RV32M implementation parameter enum. See the cve2_pkg::rv32m_e enum in cve2_pkg.sv for permitted values." + + RV32B: + datatype: str + default: cve2_pkg::RV32BNone + paramtype: vlogdefine + description: "Bitmanip implementation parameter enum. See the cve2_pkg::rv32b_e enum in cve2_pkg.sv for permitted values." + +targets: + default: &default_target + filesets: + - tool_verilator ? (files_lint_verilator) + - tool_veriblelint ? (files_lint_verible) + - files_rtl + - target_sim ? (files_clk_gate) + - target_sim_sc ? (files_clk_gate) + toplevel: cve2_top + parameters: + - tool_vivado ? (FPGA_XILINX=true) + + lint: + <<: *default_target + parameters: + - SYNTHESIS=true + - RVFI=true + filesets_append: + - files_clk_gate + default_tool: verilator + tools: + verilator: + mode: lint-only + verilator_options: + - "-Wall" + # RAM primitives wider than 64bit (required for ECC) fail to build in + # Verilator without increasing the unroll count (see Verilator#1266) + - "--unroll-count 72" + + format: + filesets: + - files_rtl + parameters: + - SYNTHESIS=true + - RVFI=true + default_tool: veribleformat + toplevel: cve2_top + tools: + veribleformat: + verible_format_args: + - "--inplace" + - "--formal_parameters_indentation=indent" + - "--named_parameter_indentation=indent" + - "--named_port_indentation=indent" + - "--port_declarations_indentation=indent" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_top_tracing.core similarity index 52% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2.core rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_top_tracing.core index ec43f9cb..65d2b5b7 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_top_tracing.core @@ -2,68 +2,28 @@ CAPI=2: # Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 - -name: "openhwgroup.org:ip:cve2" -description: "OpenHW Group RISC-V Core CVE2" - +name: "lowrisc:cve2:cve2_top_tracing:0.1" +description: "Ibex, a small RV32 CPU core with tracing enabled" filesets: files_rtl: depend: - - lowrisc:prim:assert - - lowrisc:ibex:ibex_pkg - files: - - rtl/ibex_alu.sv - - rtl/ibex_branch_predict.sv - - rtl/ibex_compressed_decoder.sv - - rtl/ibex_controller.sv - - rtl/ibex_cs_registers.sv - - rtl/ibex_csr.sv - - rtl/ibex_counter.sv - - rtl/ibex_decoder.sv - - rtl/ibex_ex_block.sv - - rtl/ibex_fetch_fifo.sv - - rtl/ibex_id_stage.sv - - rtl/ibex_if_stage.sv - - rtl/ibex_load_store_unit.sv - - rtl/ibex_multdiv_fast.sv - - rtl/ibex_multdiv_slow.sv - - rtl/ibex_prefetch_buffer.sv - - rtl/ibex_pmp.sv - - rtl/ibex_wb_stage.sv - - rtl/ibex_dummy_instr.sv - - rtl/ibex_core.sv - - rtl/cve2_sleep_unit.sv - - rtl/ibex_pmp_reset_default.svh: {is_include_file: true} - file_type: systemVerilogSource - - files_lint_verilator: - files: - - lint/verilator_waiver.vlt: {file_type: vlt} - - files_lint_verible: - files: - - lint/verible_waiver.vbw: {file_type: veribleLintWaiver} - - files_clk_gate: + - lowrisc:cve2:cve2_top + - lowrisc:cve2:cve2_tracer files: - - bhv/cve2_sim_clock_gate.sv + - rtl/cve2_top_tracing.sv file_type: systemVerilogSource parameters: + # The tracer uses the RISC-V Formal Interface (RVFI) to collect trace signals. RVFI: datatype: bool paramtype: vlogdefine + default: true SYNTHESIS: datatype: bool paramtype: vlogdefine - FPGA_XILINX: - datatype: bool - description: Identifies Xilinx FPGA targets to set DSP pragmas for performance counters. - default: false - paramtype: vlogdefine - RV32E: datatype: int default: 0 @@ -71,21 +31,21 @@ parameters: RV32M: datatype: str - default: ibex_pkg::RV32MFast + default: cve2_pkg::RV32MFast paramtype: vlogdefine - description: "RV32M implementation parameter enum. See the ibex_pkg::rv32m_e enum in ibex_pkg.sv for permitted values." + description: "RV32M implementation parameter enum. See the cve2_pkg::rv32m_e enum in cve2_pkg.sv for permitted values." RV32B: datatype: str - default: ibex_pkg::RV32BNone + default: cve2_pkg::RV32BNone paramtype: vlogdefine - description: "Bitmanip implementation parameter enum. See the ibex_pkg::rv32b_e enum in ibex_pkg.sv for permitted values." + description: "Bitmanip implementation parameter enum. See the cve2_pkg::rv32b_e enum in cve2_pkg.sv for permitted values." RegFile: datatype: str - default: ibex_pkg::RegFileFF + default: cve2_pkg::RegFileFF paramtype: vlogdefine - description: "Register file implementation parameter enum. See the ibex_pkg::regfile_e enum in ibex_pkg.sv for permitted values." + description: "Register file implementation parameter enum. See the cve2_pkg::regfile_e enum in cve2_pkg.sv for permitted values." ICache: datatype: int @@ -99,29 +59,23 @@ parameters: paramtype: vlogparam description: "Enable ECC protection in instruction cache" - BranchTargetALU: - datatype: int - default: 0 - paramtype: vlogparam - description: "Enables separate branch target ALU (increasing branch performance EXPERIMENTAL) [0/1]" - WritebackStage: datatype: int default: 0 paramtype: vlogparam description: "Enables third pipeline stage (EXPERIMENTAL) [0/1]" - BranchPredictor: + SecureCVE2: datatype: int - paramtype: vlogparam default: 0 - description: "Enables static branch prediction (EXPERIMENTAL)" + paramtype: vlogparam + description: "Enables security hardening features (EXPERIMENTAL) [0/1]" - SecureIbex: + ICacheScramble: datatype: int default: 0 paramtype: vlogparam - description: "Enables security hardening features (EXPERIMENTAL) [0/1]" + description: "Enables ICache scrambling feature (EXPERIMENTAL) [0/1]" PMPEnable: datatype: int @@ -144,19 +98,28 @@ parameters: targets: default: &default_target filesets: - - tool_verilator ? (files_lint_verilator) - - tool_veriblelint ? (files_lint_verible) - files_rtl - - target_sim? (files_clk_gate) - - target_sim-opt? (files_clk_gate) - toplevel: ibex_core parameters: - - tool_vivado ? (FPGA_XILINX=true) + - RVFI=true + toplevel: cve2_top_tracing + lint: <<: *default_target parameters: - - SYNTHESIS=true - RVFI=true + - SYNTHESIS=true + - RV32E + - RV32M + - RV32B + - RegFile + - ICache + - ICacheECC + - WritebackStage + - SecureCVE2 + - ICacheScramble + - PMPEnable + - PMPGranularity + - PMPNumRegions default_tool: verilator tools: verilator: @@ -173,8 +136,12 @@ targets: - SYNTHESIS=true - RVFI=true default_tool: veribleformat - toplevel: ibex_core + toplevel: cve2_top_tracing tools: veribleformat: verible_format_args: - "--inplace" + - "--formal_parameters_indentation=indent" + - "--named_parameter_indentation=indent" + - "--named_port_indentation=indent" + - "--port_declarations_indentation=indent" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_tracer.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_tracer.core new file mode 100644 index 00000000..0e43a806 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/cve2_tracer.core @@ -0,0 +1,20 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:cve2:cve2_tracer:0.1" +description: "Tracer for use with Ibex using the RVFI interface" +filesets: + files_rtl: + depend: + - lowrisc:prim:assert + - lowrisc:cve2:cve2_pkg + files: + - rtl/cve2_tracer_pkg.sv + - rtl/cve2_tracer.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_rtl diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/lint/verilator_waiver.vlt b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/lint/verilator_waiver.vlt index b7c952ca..bac40c20 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/lint/verilator_waiver.vlt +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/lint/verilator_waiver.vlt @@ -12,7 +12,7 @@ `verilator_config lint_off -rule PINCONNECTEMPTY -// We have some boolean top-level parameters in e.g. ibex_core_tracing.sv. +// We have some boolean top-level parameters in e.g. cve2_core_tracing.sv. // When building with fusesoc, these get set with defines like // -GRV32M=1 (rather than -GRV32M=1'b1), leading to warnings like: // @@ -23,13 +23,13 @@ lint_off -rule PINCONNECTEMPTY // matches when you set a 1-bit value to a literal 1, so it won't hide // silly mistakes like setting it to 2. // -lint_off -rule WIDTH -file "*/rtl/ibex_top_tracing.sv" +lint_off -rule WIDTH -file "*/rtl/cve2_top_tracing.sv" -match "*expects 1 bits*Initial value's CONST '32'h1'*" // Operator expects 1 bit on initial value but initial value's CONST generates // 32 bits, need a specific RV32B waiver as it uses enums so the above catch-all // waiver doesn't work. -lint_off -rule WIDTH -file "*/rtl/ibex_top_tracing.sv" -match "*'RV32B'*" +lint_off -rule WIDTH -file "*/rtl/cve2_top_tracing.sv" -match "*'RV32B'*" // Bits of signal are not used: be_i[3:1] // Bits of signal are not used: addr_i[31:10,1:0] @@ -52,21 +52,25 @@ lint_off -rule UNUSED -file "*/rtl/timer.sv" -match "*'timer_addr_i'[31:10]*" // Signal is not used: clk_i // leaving clk and reset connected in-case we want to add assertions -lint_off -rule UNUSED -file "*/rtl/ibex_pmp.sv" -match "*clk_i*" -lint_off -rule UNUSED -file "*/rtl/ibex_compressed_decoder.sv" -match "*clk_i*" -lint_off -rule UNUSED -file "*/rtl/ibex_decoder.sv" -match "*clk_i*" -lint_off -rule UNUSED -file "*/rtl/ibex_branch_predict.sv" -match "*clk_i*" +lint_off -rule UNUSED -file "*/rtl/cve2_pmp.sv" -match "*clk_i*" +lint_off -rule UNUSED -file "*/rtl/cve2_compressed_decoder.sv" -match "*clk_i*" +lint_off -rule UNUSED -file "*/rtl/cve2_decoder.sv" -match "*clk_i*" +lint_off -rule UNUSED -file "*/rtl/cve2_branch_predict.sv" -match "*clk_i*" // Signal is not used: rst_ni // leaving clk and reset connected in-case we want to add assertions -lint_off -rule UNUSED -file "*/rtl/ibex_pmp.sv" -match "*rst_ni*" -lint_off -rule UNUSED -file "*/rtl/ibex_compressed_decoder.sv" -match "*rst_ni*" -lint_off -rule UNUSED -file "*/rtl/ibex_decoder.sv" -match "*rst_ni*" -lint_off -rule UNUSED -file "*/rtl/ibex_branch_predict.sv" -match "*rst_ni*" +lint_off -rule UNUSED -file "*/rtl/cve2_pmp.sv" -match "*rst_ni*" +lint_off -rule UNUSED -file "*/rtl/cve2_compressed_decoder.sv" -match "*rst_ni*" +lint_off -rule UNUSED -file "*/rtl/cve2_decoder.sv" -match "*rst_ni*" +lint_off -rule UNUSED -file "*/rtl/cve2_branch_predict.sv" -match "*rst_ni*" // Temporary waivers until OpenTitan primitives are lint-clean // https://github.com/lowRISC/opentitan/issues/2313 lint_off -file "*/lowrisc_prim_*/rtl/*.sv" -lint_off -rule UNUSED -file "*/rtl/ibex_top_tracing.sv" -match "*RndCnstLfsrSeed*" -lint_off -rule UNUSED -file "*/rtl/ibex_top_tracing.sv" -match "*RndCnstLfsrPerm*" +lint_off -rule UNUSED -file "*/rtl/cve2_top_tracing.sv" -match "*RndCnstLfsrSeed*" +lint_off -rule UNUSED -file "*/rtl/cve2_top_tracing.sv" -match "*RndCnstLfsrPerm*" +lint_off -rule DECLFILENAME -file "*/bhv/cve2_sim_clock_gate.sv" -match "Filename 'cve2_sim_clock_gate' does not match MODULE name: 'cve2_clock_gate'" +lint_off -rule UNOPTFLAT -file "*/rtl/cve2_core.sv" -match "Signal unoptimizable: Feedback to clock or circular logic: 'cve2_top.u_cve2_core.irqs'" +lint_off -rule UNUSED -file "*/rtl/cve2_wb.sv" -match "Signal is not used: 'clk_i'*" +lint_off -rule UNUSED -file "*/rtl/cve2_wb.sv" -match "Signal is not used: 'rst_ni'*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_alu.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_alu.sv similarity index 99% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_alu.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_alu.sv index eb6afcae..2471c621 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_alu.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_alu.sv @@ -6,10 +6,10 @@ /** * Arithmetic logic unit */ -module ibex_alu #( - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone +module cve2_alu #( + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( - input ibex_pkg::alu_op_e operator_i, + input cve2_pkg::alu_op_e operator_i, input logic [31:0] operand_a_i, input logic [31:0] operand_b_i, @@ -31,7 +31,7 @@ module ibex_alu #( output logic comparison_result_o, output logic is_equal_result_o ); - import ibex_pkg::*; + import cve2_pkg::*; logic [31:0] operand_a_rev; logic [32:0] operand_b_neg; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_branch_predict.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_branch_predict.sv similarity index 98% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_branch_predict.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_branch_predict.sv index 87f83836..e49c7007 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_branch_predict.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_branch_predict.sv @@ -17,7 +17,7 @@ `include "prim_assert.sv" -module ibex_branch_predict ( +module cve2_branch_predict ( input logic clk_i, input logic rst_ni, @@ -30,7 +30,7 @@ module ibex_branch_predict ( output logic predict_branch_taken_o, output logic [31:0] predict_branch_pc_o ); - import ibex_pkg::*; + import cve2_pkg::*; logic [31:0] imm_j_type; logic [31:0] imm_b_type; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_compressed_decoder.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_compressed_decoder.sv similarity index 99% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_compressed_decoder.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_compressed_decoder.sv index e3c6aa52..1b5b17ff 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_compressed_decoder.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_compressed_decoder.sv @@ -13,7 +13,7 @@ `include "prim_assert.sv" -module ibex_compressed_decoder ( +module cve2_compressed_decoder ( input logic clk_i, input logic rst_ni, input logic valid_i, @@ -22,7 +22,7 @@ module ibex_compressed_decoder ( output logic is_compressed_o, output logic illegal_instr_o ); - import ibex_pkg::*; + import cve2_pkg::*; // valid_i indicates if instr_i is valid and is used for assertions only. // The following signal is used to avoid possible lint errors. diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_controller.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv similarity index 82% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_controller.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv index 0f2ae7bc..fba4352f 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_controller.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_controller.sv @@ -8,15 +8,14 @@ */ `include "prim_assert.sv" -//`include "dv_fcov_macros.svh" +`include "dv_fcov_macros.svh" -module ibex_controller #( - parameter bit WritebackStage = 0, - parameter bit BranchPredictor = 0 +module cve2_controller #( ) ( input logic clk_i, input logic rst_ni, + input logic fetch_enable_i, // core can fetch instructions leave RESET state output logic ctrl_busy_o, // core is busy processing instrs // decoder related signals @@ -33,7 +32,6 @@ module ibex_controller #( input logic [31:0] instr_i, // uncompressed instr data for mtval input logic [15:0] instr_compressed_i, // instr compressed data for mtval input logic instr_is_compressed_i, // instr is compressed - input logic instr_bp_taken_i, // instr was predicted taken branch input logic instr_fetch_err_i, // instr has error input logic instr_fetch_err_plus2_i, // instr error is x32 input logic [31:0] pc_id_i, // instr address @@ -47,37 +45,32 @@ module ibex_controller #( // to prefetcher output logic instr_req_o, // start fetching instructions output logic pc_set_o, // jump to address set by pc_mux - output ibex_pkg::pc_sel_e pc_mux_o, // IF stage fetch address selector + output cve2_pkg::pc_sel_e pc_mux_o, // IF stage fetch address selector // (boot, normal, exception...) - output logic nt_branch_mispredict_o, // Not-taken branch in ID/EX was - // mispredicted (predicted taken) - output ibex_pkg::exc_pc_sel_e exc_pc_mux_o, // IF stage selector for exception PC - output ibex_pkg::exc_cause_e exc_cause_o, // for IF stage, CSRs + output cve2_pkg::exc_pc_sel_e exc_pc_mux_o, // IF stage selector for exception PC + output cve2_pkg::exc_cause_e exc_cause_o, // for IF stage, CSRs // LSU input logic [31:0] lsu_addr_last_i, // for mtval input logic load_err_i, input logic store_err_i, - output logic wb_exception_o, // Instruction in WB taking an exception - output logic id_exception_o, // Instruction in ID taking an exception // jump/branch signals input logic branch_set_i, // branch set signal (branch definitely // taken) - input logic branch_not_set_i, // branch is definitely not taken input logic jump_set_i, // jump taken set signal // interrupt signals input logic csr_mstatus_mie_i, // M-mode interrupt enable bit input logic irq_pending_i, // interrupt request pending - input ibex_pkg::irqs_t irqs_i, // interrupt requests qualified with + input cve2_pkg::irqs_t irqs_i, // interrupt requests qualified with // mie CSR input logic irq_nm_i, // non-maskeable interrupt output logic nmi_mode_o, // core executing NMI handler // debug signals input logic debug_req_i, - output ibex_pkg::dbg_cause_e debug_cause_o, + output cve2_pkg::dbg_cause_e debug_cause_o, output logic debug_csr_save_o, output logic debug_mode_o, input logic debug_single_step_i, @@ -85,24 +78,18 @@ module ibex_controller #( input logic debug_ebreaku_i, input logic trigger_match_i, - // Wakeup Signal - output logic wake_from_sleep_o, - output logic csr_save_if_o, output logic csr_save_id_o, - output logic csr_save_wb_o, output logic csr_restore_mret_id_o, output logic csr_restore_dret_id_o, output logic csr_save_cause_o, output logic [31:0] csr_mtval_o, - input ibex_pkg::priv_lvl_e priv_mode_i, + input cve2_pkg::priv_lvl_e priv_mode_i, input logic csr_mstatus_tw_i, // stall & flush signals input logic stall_id_i, - input logic stall_wb_i, output logic flush_id_o, - input logic ready_wb_i, // performance monitors output logic perf_jump_o, // we are executing a jump @@ -110,7 +97,7 @@ module ibex_controller #( output logic perf_tbranch_o // we are executing a taken branch // instruction ); - import ibex_pkg::*; + import cve2_pkg::*; // FSM state encoding typedef enum logic [3:0] { @@ -153,8 +140,6 @@ module ibex_controller #( logic enter_debug_mode; logic ebreak_into_debug; logic handle_irq; - logic id_wb_pending; - logic [3:0] mfip_id; logic unused_irq_timer; @@ -173,8 +158,8 @@ module ibex_controller #( always_ff @(negedge clk_i) begin // print warning in case of decoding errors if ((ctrl_fsm_cs == DECODE) && instr_valid_i && !instr_fetch_err_i && illegal_insn_d) begin - $display("%t: Illegal instruction (hart %0x) at PC 0x%h: 0x%h", $time, ibex_core.hart_id_i, - ibex_id_stage.pc_id_i, ibex_id_stage.instr_rdata_i); + $display("%m @ %t: Illegal instruction (hart %0x) at PC 0x%h: 0x%h", $time, cve2_core.hart_id_i, + cve2_id_stage.pc_id_i, cve2_id_stage.instr_rdata_i); end end // synopsys translate_on @@ -206,7 +191,7 @@ module ibex_controller #( (mret_insn | (csr_mstatus_tw_i & wfi_insn)); // This is recorded in the illegal_insn_q flop to help timing. Specifically - // it is needed to break the path from ibex_cs_registers/illegal_csr_insn_o + // it is needed to break the path from cve2_cs_registers/illegal_csr_insn_o // to pc_set_o. Clear when controller is in FLUSH so it won't remain set // once illegal instruction is handled. // All terms in this expression are qualified by instr_valid_i @@ -223,8 +208,6 @@ module ibex_controller #( // LSU exception requests assign exc_req_lsu = store_err_i | load_err_i; - assign id_exception_o = exc_req_d; - // special requests: special instructions, pipeline flushes, exceptions... // All terms in these expressions are qualified by instr_valid_i except exc_req_lsu which can come // from the Writeback stage with no instr_valid_i from the ID stage @@ -239,40 +222,7 @@ module ibex_controller #( // generic special request signal, applies to all instructions assign special_req = special_req_pc_change | special_req_flush_only; - // Is there an instruction in ID or WB that has yet to complete? - assign id_wb_pending = instr_valid_i | ~ready_wb_i; - // Exception/fault prioritisation is taken from Table 3.7 of Priviledged Spec v1.11 - if (WritebackStage) begin : g_wb_exceptions - always_comb begin - instr_fetch_err_prio = 0; - illegal_insn_prio = 0; - ecall_insn_prio = 0; - ebrk_insn_prio = 0; - store_err_prio = 0; - load_err_prio = 0; - - // Note that with the writeback stage store/load errors occur on the instruction in writeback, - // all other exception/faults occur on the instruction in ID/EX. The faults from writeback - // must take priority as that instruction is architecurally ordered before the one in ID/EX. - if (store_err_q) begin - store_err_prio = 1'b1; - end else if (load_err_q) begin - load_err_prio = 1'b1; - end else if (instr_fetch_err) begin - instr_fetch_err_prio = 1'b1; - end else if (illegal_insn_q) begin - illegal_insn_prio = 1'b1; - end else if (ecall_insn) begin - ecall_insn_prio = 1'b1; - end else if (ebrk_insn) begin - ebrk_insn_prio = 1'b1; - end - end - - // Instruction in writeback is generating an exception so instruction in ID must not execute - assign wb_exception_o = load_err_q | store_err_q | load_err_i | store_err_i; - end else begin : g_no_wb_exceptions always_comb begin instr_fetch_err_prio = 0; illegal_insn_prio = 0; @@ -295,8 +245,6 @@ module ibex_controller #( load_err_prio = 1'b1; end end - assign wb_exception_o = 1'b0; - end `ASSERT_IF(IbexExceptionPrioOnehot, $onehot({instr_fetch_err_prio, @@ -346,6 +294,7 @@ module ibex_controller #( // - while in debug mode [Debug Spec v0.13.2, p.39], // - while in NMI mode (nested NMIs are not supported, NMI has highest priority and // cannot be interrupted by regular interrupts). + // - while single stepping. assign handle_irq = ~debug_mode_q & ~nmi_mode_q & (irq_nm_i | (irq_pending_i & csr_mstatus_mie_i)); @@ -353,7 +302,7 @@ module ibex_controller #( always_comb begin : gen_mfip_id mfip_id = 4'd0; - for (int i = 14; i >= 0; i--) begin + for (int i = 15; i >= 0; i--) begin if (irqs_i.irq_fast[i]) begin mfip_id = i[3:0]; end @@ -372,7 +321,6 @@ module ibex_controller #( csr_save_if_o = 1'b0; csr_save_id_o = 1'b0; - csr_save_wb_o = 1'b0; csr_restore_mret_id_o = 1'b0; csr_restore_dret_id_o = 1'b0; csr_save_cause_o = 1'b0; @@ -384,7 +332,6 @@ module ibex_controller #( // helping timing. pc_mux_o = PC_BOOT; pc_set_o = 1'b0; - nt_branch_mispredict_o = 1'b0; exc_pc_mux_o = EXC_PC_IRQ; exc_cause_o = EXC_CAUSE_INSN_ADDR_MISA; // = 6'h00 @@ -412,9 +359,11 @@ module ibex_controller #( instr_req_o = 1'b0; pc_mux_o = PC_BOOT; pc_set_o = 1'b1; - ctrl_fsm_ns = BOOT_SET; + if (fetch_enable_i == 1'b1) + begin + ctrl_fsm_ns = BOOT_SET; + end end - BOOT_SET: begin // copy boot address to instr fetch address instr_req_o = 1'b1; @@ -441,13 +390,12 @@ module ibex_controller #( // normal execution flow // in debug mode or single step mode we leave immediately (wfi=nop) - if (wake_from_sleep_o) begin - ctrl_fsm_ns = FIRST_FETCH; + if (irq_nm_i || irq_pending_i || debug_req_i || debug_mode_q || debug_single_step_i) begin + ctrl_fsm_ns = FIRST_FETCH; end else begin // Make sure clock remains disabled. ctrl_busy_o = 1'b0; end - end FIRST_FETCH: begin @@ -497,40 +445,25 @@ module ibex_controller #( // FLUSH state. retain_id = 1'b1; - // Wait for the writeback stage to either be ready for a new instruction or raise its own - // exception before going to FLUSH. If the instruction in writeback raises an exception it - // must take priority over any exception from an instruction in ID/EX. Only once the - // writeback stage is ready can we be certain that won't happen. Without a writeback - // stage ready_wb_i == 1 so the FSM will always go directly to FLUSH. + // The FSM will always go directly to FLUSH. - if (ready_wb_i | wb_exception_o) begin - ctrl_fsm_ns = FLUSH; - end + ctrl_fsm_ns = FLUSH; end if (branch_set_i || jump_set_i) begin - // Only set the PC if the branch predictor hasn't already done the branch for us - pc_set_o = BranchPredictor ? ~instr_bp_taken_i : 1'b1; + pc_set_o = 1'b1; perf_tbranch_o = branch_set_i; perf_jump_o = jump_set_i; end - if (BranchPredictor) begin - if (instr_bp_taken_i & branch_not_set_i) begin - // If the instruction is a branch that was predicted to be taken but was not taken - // signal a mispredict. - nt_branch_mispredict_o = 1'b1; - end - end - // If entering debug mode or handling an IRQ the core needs to wait until any instruction in - // ID or WB has finished executing. Stall IF during that time. - if ((enter_debug_mode || handle_irq) && (stall || id_wb_pending)) begin + // ID has finished executing. Stall IF during that time. + if ((enter_debug_mode || handle_irq) && (stall || instr_valid_i)) begin halt_if = 1'b1; end - if (!stall && !special_req && !id_wb_pending) begin + if (!stall && !special_req && !instr_valid_i) begin if (enter_debug_mode) begin // enter debug mode ctrl_fsm_ns = DBG_TAKEN_IF; @@ -565,12 +498,13 @@ module ibex_controller #( if (irq_nm_i && !nmi_mode_q) begin exc_cause_o = EXC_CAUSE_IRQ_NM; nmi_mode_d = 1'b1; // enter NMI mode - end else if (irqs_i.irq_fast != 15'b0) begin + end else if (irqs_i.irq_fast != 16'b0) begin // generate exception cause ID from fast interrupt ID: // - first bit distinguishes interrupts from exceptions, - // - second bit adds 16 to fast interrupt ID - // for example EXC_CAUSE_IRQ_FAST_0 = {1'b1, 5'd16} - exc_cause_o = exc_cause_e'({2'b11, mfip_id}); + // - third bit adds 16 to fast interrupt ID so that the interrup 0 becomes 16 and the interrupt 15 becomes 31 (hence 5bits) + // - second bit is always 0 as the FAST interrupts are represented in the first 5bits, the 6th is always 0 cause is used by the NMI (in that case is 1 as represented by the number 32) + // for example EXC_CAUSE_IRQ_FAST_0 = {1'b1, 6'd16} + exc_cause_o = exc_cause_e'({3'b101, mfip_id}); end else if (irqs_i.irq_external) begin exc_cause_o = EXC_CAUSE_IRQ_EXTERNAL_M; end else if (irqs_i.irq_software) begin @@ -597,11 +531,11 @@ module ibex_controller #( csr_save_cause_o = 1'b1; if (trigger_match_i) begin - debug_cause_o = DBG_CAUSE_TRIGGER; - end else if (debug_single_step_i) begin - debug_cause_o = DBG_CAUSE_STEP; + debug_cause_o = DBG_CAUSE_TRIGGER; // (priority 4) + end else if (debug_req_i) begin + debug_cause_o = DBG_CAUSE_HALTREQ; // (priority 1) end else begin - debug_cause_o = DBG_CAUSE_HALTREQ; + debug_cause_o = DBG_CAUSE_STEP; // (priority 0, lowest) end // enter debug mode @@ -657,13 +591,7 @@ module ibex_controller #( pc_mux_o = PC_EXC; exc_pc_mux_o = debug_mode_q ? EXC_PC_DBG_EXC : EXC_PC_EXC; - if (WritebackStage) begin : g_writeback_mepc_save - // With the writeback stage present whether an instruction accessing memory will cause - // an exception is only known when it is in writeback. So when taking such an exception - // epc must come from writeback. - csr_save_id_o = ~(store_err_q | load_err_q); - csr_save_wb_o = store_err_q | load_err_q; - end else begin : g_no_writeback_mepc_save + begin : g_no_writeback_mepc_save csr_save_id_o = 1'b0; end @@ -742,9 +670,6 @@ module ibex_controller #( csr_restore_dret_id_o = 1'b1; end else if (wfi_insn) begin ctrl_fsm_ns = WAIT_SLEEP; - end else if (csr_pipe_flush && handle_irq) begin - // start handling IRQs when doing CSR-related pipeline flushes - ctrl_fsm_ns = IRQ_TAKEN; end end // exc_req_q @@ -754,9 +679,14 @@ module ibex_controller #( // Leave all other signals as is to ensure CSRs and PC get set as if // core was entering exception handler, entry to debug mode will then // see the appropriate state and setup dpc correctly. + // If an EBREAK instruction is causing us to enter debug mode on the // same cycle as a debug_req or single step, honor the EBREAK and - // proceed to DBG_TAKEN_ID. + // proceed to DBG_TAKEN_ID, as it has the highest priority. + // [Debug Spec v1.0.0-STABLE, p.53] + // cause==EBREAK -> prio 3 (highest) + // cause==debug_req -> prio 2 + // cause==step -> prio 1 (lowest) if (enter_debug_mode_prio_q && !(ebrk_insn_prio && ebreak_into_debug)) begin ctrl_fsm_ns = DBG_TAKEN_IF; end @@ -782,9 +712,8 @@ module ibex_controller #( /////////////////// // If high current instruction cannot complete this cycle. Either because it needs more cycles to - // finish (stall_id_i) or because the writeback stage cannot accept it yet (stall_wb_i). If there - // is no writeback stage stall_wb_i is a constant 0. - assign stall = stall_id_i | stall_wb_i; + // finish (stall_id_i) + assign stall = stall_id_i; // signal to IF stage that ID stage is ready for next instr assign id_in_ready_o = ~stall & ~halt_if & ~retain_id; @@ -821,27 +750,22 @@ module ibex_controller #( end end - assign wake_from_sleep_o = irq_nm_i || irq_pending_i || debug_req_i || debug_mode_q || debug_single_step_i; - - ////////// // FCOV // ////////// - //`DV_FCOV_SIGNAL(logic, interrupt_taken, (ctrl_fsm_cs != IRQ_TAKEN) & (ctrl_fsm_ns == IRQ_TAKEN)) - //`DV_FCOV_SIGNAL(logic, debug_entry_if, - // (ctrl_fsm_cs != DBG_TAKEN_IF) & (ctrl_fsm_ns == DBG_TAKEN_IF)) - //`DV_FCOV_SIGNAL(logic, debug_entry_id, - // (ctrl_fsm_cs != DBG_TAKEN_ID) & (ctrl_fsm_ns == DBG_TAKEN_ID)) - //`DV_FCOV_SIGNAL(logic, pipe_flush, (ctrl_fsm_cs != FLUSH) & (ctrl_fsm_ns == FLUSH)) - //`DV_FCOV_SIGNAL(logic, debug_req, debug_req_i & ~debug_mode_q) + `DV_FCOV_SIGNAL(logic, interrupt_taken, (ctrl_fsm_cs != IRQ_TAKEN) & (ctrl_fsm_ns == IRQ_TAKEN)) + `DV_FCOV_SIGNAL(logic, debug_entry_if, + (ctrl_fsm_cs != DBG_TAKEN_IF) & (ctrl_fsm_ns == DBG_TAKEN_IF)) + `DV_FCOV_SIGNAL(logic, debug_entry_id, + (ctrl_fsm_cs != DBG_TAKEN_ID) & (ctrl_fsm_ns == DBG_TAKEN_ID)) + `DV_FCOV_SIGNAL(logic, pipe_flush, (ctrl_fsm_cs != FLUSH) & (ctrl_fsm_ns == FLUSH)) + `DV_FCOV_SIGNAL(logic, debug_req, debug_req_i & ~debug_mode_q) //////////////// // Assertions // //////////////// - `ASSERT(AlwaysInstrClearOnMispredict, nt_branch_mispredict_o |-> instr_valid_clear_o) - // Selectors must be known/valid. `ASSERT(IbexCtrlStateValid, ctrl_fsm_cs inside { RESET, BOOT_SET, WAIT_SLEEP, SLEEP, FIRST_FETCH, DECODE, FLUSH, @@ -923,7 +847,7 @@ module ibex_controller #( `ifdef RVFI // Workaround for internal verilator error when using hierarchical refers to calcuate this - // directly in ibex_core + // directly in cve2_core logic rvfi_flush_next; assign rvfi_flush_next = ctrl_fsm_ns == FLUSH; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.f b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.f new file mode 100644 index 00000000..3250f707 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.f @@ -0,0 +1,17 @@ +cve2_pkg.sv +cve2_alu.sv +cve2_compressed_decoder.sv +cve2_controller.sv +cve2_counter.sv +cve2_cs_registers.sv +cve2_decoder.sv +cve2_ex_block.sv +cve2_id_stage.sv +cve2_if_stage.sv +cve2_load_store_unit.sv +cve2_multdiv_slow.sv +cve2_multdiv_fast.sv +cve2_prefetch_buffer.sv +cve2_fetch_fifo.sv +cve2_register_file_ff.sv +cve2_core.sv diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv similarity index 73% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv index f57c87d9..aff3d0d4 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_core.sv @@ -12,7 +12,7 @@ /** * Top level module of the ibex RISC-V core */ -module ibex_core import ibex_pkg::*; #( +module cve2_core import cve2_pkg::*; #( parameter bit PMPEnable = 1'b0, parameter int unsigned PMPGranularity = 0, parameter int unsigned PMPNumRegions = 4, @@ -21,23 +21,8 @@ module ibex_core import ibex_pkg::*; #( parameter bit RV32E = 1'b0, parameter rv32m_e RV32M = RV32MFast, parameter rv32b_e RV32B = RV32BNone, - parameter bit BranchTargetALU = 1'b0, - parameter bit WritebackStage = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter int unsigned BusSizeECC = BUS_SIZE, - parameter int unsigned TagSizeECC = IC_TAG_SIZE, - parameter int unsigned LineSizeECC = IC_LINE_SIZE, - parameter bit BranchPredictor = 1'b0, parameter bit DbgTriggerEn = 1'b0, parameter int unsigned DbgHwBreakNum = 1, - parameter bit ResetAll = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, - parameter bit SecureIbex = 1'b0, - parameter bit DummyInstructions = 1'b0, - parameter bit RegFileECC = 1'b0, - parameter int unsigned RegFileDataWidth = 32, parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808 ) ( @@ -45,6 +30,8 @@ module ibex_core import ibex_pkg::*; #( input logic clk_i, input logic rst_ni, + input logic test_en_i, + input logic [31:0] hart_id_i, input logic [31:0] boot_addr_i, @@ -67,34 +54,11 @@ module ibex_core import ibex_pkg::*; #( input logic [31:0] data_rdata_i, input logic data_err_i, - // Register file interface - output logic dummy_instr_id_o, - output logic [4:0] rf_raddr_a_o, - output logic [4:0] rf_raddr_b_o, - output logic [4:0] rf_waddr_wb_o, - output logic rf_we_wb_o, - output logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_o, - input logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_i, - input logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_i, - - // RAMs interface - output logic [IC_NUM_WAYS-1:0] ic_tag_req_o, - output logic ic_tag_write_o, - output logic [IC_INDEX_W-1:0] ic_tag_addr_o, - output logic [TagSizeECC-1:0] ic_tag_wdata_o, - input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], - output logic [IC_NUM_WAYS-1:0] ic_data_req_o, - output logic ic_data_write_o, - output logic [IC_INDEX_W-1:0] ic_data_addr_o, - output logic [LineSizeECC-1:0] ic_data_wdata_o, - input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], - input logic ic_scr_key_valid_i, - // Interrupt inputs input logic irq_software_i, input logic irq_timer_i, input logic irq_external_i, - input logic [14:0] irq_fast_i, + input logic [15:0] irq_fast_i, input logic irq_nm_i, // non-maskeable interrupt output logic irq_pending_o, @@ -103,7 +67,6 @@ module ibex_core import ibex_pkg::*; #( output crash_dump_t crash_dump_o, // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC - output logic double_fault_seen_o, // RISC-V Formal Interface // Does not comply with the coding standards of _i/_o suffixes, but follows @@ -139,22 +102,14 @@ module ibex_core import ibex_pkg::*; #( `endif // CPU Control Signals - // SEC_CM: FETCH.CTRL.LC_GATED input logic fetch_enable_i, - output logic alert_minor_o, - output logic alert_major_o, - output logic icache_inval_o, - output logic core_sleep_o + output logic core_busy_o ); localparam int unsigned PMP_NUM_CHAN = 3; // SEC_CM: CORE.DATA_REG_SW.SCA - localparam bit DataIndTiming = SecureIbex; - localparam bit PCIncrCheck = SecureIbex; - localparam bit ShadowCSR = 1'b0; // IF/ID signals - logic dummy_instr_id; logic instr_valid_id; logic instr_new_id; logic [31:0] instr_rdata_id; // Instruction sampled inside IF stage @@ -163,33 +118,18 @@ module ibex_core import ibex_pkg::*; #( logic [15:0] instr_rdata_c_id; // Compressed instruction sampled inside IF stage logic instr_is_compressed_id; logic instr_perf_count_id; - logic instr_bp_taken_id; logic instr_fetch_err; // Bus error on instr fetch logic instr_fetch_err_plus2; // Instruction error is misaligned logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage logic [31:0] pc_if; // Program counter in IF stage logic [31:0] pc_id; // Program counter in ID stage - logic [31:0] pc_wb; // Program counter in WB stage logic [33:0] imd_val_d_ex[2]; // Intermediate register for multicycle Ops logic [33:0] imd_val_q_ex[2]; // Intermediate register for multicycle Ops logic [1:0] imd_val_we_ex; - logic data_ind_timing; - logic dummy_instr_en; - logic [2:0] dummy_instr_mask; - logic dummy_instr_seed_en; - logic [31:0] dummy_instr_seed; - logic icache_enable; - logic icache_inval; - logic icache_ecc_error; - logic pc_mismatch_alert; - logic csr_shadow_err; - logic instr_first_cycle_id; logic instr_valid_clear; logic pc_set; - logic nt_branch_mispredict; - logic [31:0] nt_branch_addr; pc_sel_e pc_mux_id; // Mux selector for next PC exc_pc_sel_e exc_pc_mux_id; // Mux selector for exception PC exc_cause_e exc_cause; // Exception cause @@ -221,26 +161,19 @@ module ibex_core import ibex_pkg::*; #( logic [31:0] rf_wdata_wb; // Writeback register write data that can be used on the forwarding path (doesn't factor in memory // read data as this is too late for the forwarding path) - logic [31:0] rf_wdata_fwd_wb; logic [31:0] rf_wdata_lsu; logic rf_we_wb; logic rf_we_lsu; - logic rf_ecc_err_comb; logic [4:0] rf_waddr_id; logic [31:0] rf_wdata_id; logic rf_we_id; - logic rf_rd_a_wb_match; - logic rf_rd_b_wb_match; // ALU Control alu_op_e alu_operator_ex; logic [31:0] alu_operand_a_ex; logic [31:0] alu_operand_b_ex; - logic [31:0] bt_a_operand; - logic [31:0] bt_b_operand; - logic [31:0] alu_adder_result_ex; // Used to forward computed address to LSU logic [31:0] result_ex; @@ -253,7 +186,6 @@ module ibex_core import ibex_pkg::*; #( logic [1:0] multdiv_signed_mode_ex; logic [31:0] multdiv_operand_a_ex; logic [31:0] multdiv_operand_b_ex; - logic multdiv_ready_id; // CSR control logic csr_access; @@ -272,7 +204,6 @@ module ibex_core import ibex_pkg::*; #( logic lsu_sign_ext; logic lsu_req; logic [31:0] lsu_wdata; - logic lsu_req_done; // stall control logic id_in_ready; @@ -285,13 +216,8 @@ module ibex_core import ibex_pkg::*; #( logic instr_req_int; // Id stage asserts a req to instruction core interface logic instr_req_gated; - // Writeback stage - logic en_wb; - wb_instr_type_e instr_type_wb; - logic ready_wb; - logic rf_write_wb; - logic outstanding_load_wb; - logic outstanding_store_wb; + // Writeback + logic en_wb; // Interrupts logic nmi_mode; @@ -308,7 +234,6 @@ module ibex_core import ibex_pkg::*; #( logic csr_save_if; logic csr_save_id; - logic csr_save_wb; logic csr_restore_mret_id; logic csr_restore_dret_id; logic csr_save_cause; @@ -331,15 +256,12 @@ module ibex_core import ibex_pkg::*; #( // signals relating to instruction movements between pipeline stages // used by performance counters and RVFI logic instr_id_done; - logic instr_done_wb; logic perf_instr_ret_wb; logic perf_instr_ret_compressed_wb; - logic perf_instr_ret_wb_spec; - logic perf_instr_ret_compressed_wb_spec; logic perf_iside_wait; logic perf_dside_wait; - logic perf_mul_wait; + logic perf_wfi_wait; logic perf_div_wait; logic perf_jump; logic perf_branch; @@ -350,63 +272,23 @@ module ibex_core import ibex_pkg::*; #( // for RVFI logic illegal_insn_id, unused_illegal_insn_id; // ID stage sees an illegal instruction - ////////////////////////////////////////////////////////////////////////////////////////////// - // ____ _ _ __ __ _ // - // / ___| | ___ ___| | __ | \/ | __ _ _ __ __ _ __ _ ___ _ __ ___ ___ _ __ | |_ // - // | | | |/ _ \ / __| |/ / | |\/| |/ _` | '_ \ / _` |/ _` |/ _ \ '_ ` _ \ / _ \ '_ \| __| // - // | |___| | (_) | (__| < | | | | (_| | | | | (_| | (_| | __/ | | | | | __/ | | | |_ // - // \____|_|\___/ \___|_|\_\ |_| |_|\__,_|_| |_|\__,_|\__, |\___|_| |_| |_|\___|_| |_|\__| // - // |___/ // - ////////////////////////////////////////////////////////////////////////////////////////////// - - logic clk; - logic fetch_enable; - logic wake_from_sleep; - - cve2_sleep_unit sleep_unit_i ( - // Clock, reset interface - .clk_ungated_i(clk_i), // Ungated clock - .rst_n (rst_ni), - .clk_gated_o (clk), // Gated clock - .scan_cg_en_i (1'b0), - - // Core sleep - .core_sleep_o(core_sleep_o), - - // Fetch enable - .fetch_enable_i(fetch_enable_i), - .fetch_enable_o(fetch_enable), - - // Core status - .if_busy_i (if_busy), - .ctrl_busy_i(ctrl_busy), - .lsu_busy_i (lsu_busy), - - // WFI wake - .wake_from_sleep_i(wake_from_sleep) - ); + ////////////////////// + // Clock management // + ////////////////////// + // Before going to sleep, wait for I- and D-side + // interfaces to finish ongoing operations. + assign core_busy_o = ctrl_busy | if_busy | lsu_busy; ////////////// // IF stage // ////////////// - ibex_if_stage #( + cve2_if_stage #( .DmHaltAddr (DmHaltAddr), - .DmExceptionAddr (DmExceptionAddr), - .DummyInstructions(DummyInstructions), - .ICache (ICache), - .ICacheECC (ICacheECC), - .BusSizeECC (BusSizeECC), - .TagSizeECC (TagSizeECC), - .LineSizeECC (LineSizeECC), - .PCIncrCheck (PCIncrCheck), - .ResetAll ( ResetAll ), - .RndCnstLfsrSeed ( RndCnstLfsrSeed ), - .RndCnstLfsrPerm ( RndCnstLfsrPerm ), - .BranchPredictor (BranchPredictor) + .DmExceptionAddr (DmExceptionAddr) ) if_stage_i ( - .clk_i (clk), + .clk_i (clk_i), .rst_ni(rst_ni), .boot_addr_i(boot_addr_i), @@ -420,18 +302,6 @@ module ibex_core import ibex_pkg::*; #( .instr_rdata_i (instr_rdata_i), .instr_err_i (instr_err_i), - .ic_tag_req_o (ic_tag_req_o), - .ic_tag_write_o (ic_tag_write_o), - .ic_tag_addr_o (ic_tag_addr_o), - .ic_tag_wdata_o (ic_tag_wdata_o), - .ic_tag_rdata_i (ic_tag_rdata_i), - .ic_data_req_o (ic_data_req_o), - .ic_data_write_o (ic_data_write_o), - .ic_data_addr_o (ic_data_addr_o), - .ic_data_wdata_o (ic_data_wdata_o), - .ic_data_rdata_i (ic_data_rdata_i), - .ic_scr_key_valid_i(ic_scr_key_valid_i), - // outputs to ID stage .instr_valid_id_o (instr_valid_id), .instr_new_id_o (instr_new_id), @@ -439,11 +309,9 @@ module ibex_core import ibex_pkg::*; #( .instr_rdata_alu_id_o (instr_rdata_alu_id), .instr_rdata_c_id_o (instr_rdata_c_id), .instr_is_compressed_id_o(instr_is_compressed_id), - .instr_bp_taken_o (instr_bp_taken_id), .instr_fetch_err_o (instr_fetch_err), .instr_fetch_err_plus2_o (instr_fetch_err_plus2), .illegal_c_insn_id_o (illegal_c_insn_id), - .dummy_instr_id_o (dummy_instr_id), .pc_if_o (pc_if), .pc_id_o (pc_id), .pmp_err_if_i (pmp_req_err[PMP_I]), @@ -453,20 +321,11 @@ module ibex_core import ibex_pkg::*; #( .instr_valid_clear_i (instr_valid_clear), .pc_set_i (pc_set), .pc_mux_i (pc_mux_id), - .nt_branch_mispredict_i(nt_branch_mispredict), .exc_pc_mux_i (exc_pc_mux_id), .exc_cause (exc_cause), - .dummy_instr_en_i (dummy_instr_en), - .dummy_instr_mask_i (dummy_instr_mask), - .dummy_instr_seed_en_i (dummy_instr_seed_en), - .dummy_instr_seed_i (dummy_instr_seed), - .icache_enable_i (icache_enable), - .icache_inval_i (icache_inval), - .icache_ecc_error_o (icache_ecc_error), // branch targets .branch_target_ex_i(branch_target_ex), - .nt_branch_addr_i (nt_branch_addr), // CSRs .csr_mepc_i (csr_mepc), // exception return address @@ -477,7 +336,6 @@ module ibex_core import ibex_pkg::*; #( // pipeline stalls .id_in_ready_i(id_in_ready), - .pc_mismatch_alert_o(pc_mismatch_alert), .if_busy_o (if_busy) ); @@ -485,27 +343,23 @@ module ibex_core import ibex_pkg::*; #( // available assign perf_iside_wait = id_in_ready & ~instr_valid_id; - // fetch_enable_i can be used to stop the core fetching new instructions - assign instr_req_gated = instr_req_int & fetch_enable; + // For non secure Ibex only the bottom bit of fetch enable is considered + assign instr_req_gated = instr_req_int; ////////////// // ID stage // ////////////// - ibex_id_stage #( + cve2_id_stage #( .RV32E (RV32E), .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU(BranchTargetALU), - .DataIndTiming (DataIndTiming), - .WritebackStage (WritebackStage), - .BranchPredictor(BranchPredictor) + .RV32B (RV32B) ) id_stage_i ( - - .clk_i(clk), + .clk_i (clk_i), .rst_ni(rst_ni), // Processor Enable + .fetch_enable_i(fetch_enable_i), .ctrl_busy_o (ctrl_busy), .illegal_insn_o(illegal_insn_id), @@ -515,7 +369,6 @@ module ibex_core import ibex_pkg::*; #( .instr_rdata_alu_i (instr_rdata_alu_id), .instr_rdata_c_i (instr_rdata_c_id), .instr_is_compressed_i(instr_is_compressed_id), - .instr_bp_taken_i (instr_bp_taken_id), // Jumps and branches .branch_decision_i(branch_decision), @@ -527,11 +380,8 @@ module ibex_core import ibex_pkg::*; #( .instr_req_o (instr_req_int), .pc_set_o (pc_set), .pc_mux_o (pc_mux_id), - .nt_branch_mispredict_o(nt_branch_mispredict), - .nt_branch_addr_o (nt_branch_addr), .exc_pc_mux_o (exc_pc_mux_id), .exc_cause_o (exc_cause), - .icache_inval_o (icache_inval), .instr_fetch_err_i (instr_fetch_err), .instr_fetch_err_plus2_i(instr_fetch_err_plus2), @@ -551,9 +401,6 @@ module ibex_core import ibex_pkg::*; #( .imd_val_d_ex_i (imd_val_d_ex), .imd_val_we_ex_i(imd_val_we_ex), - .bt_a_operand_o(bt_a_operand), - .bt_b_operand_o(bt_b_operand), - .mult_en_ex_o (mult_en_ex), .div_en_ex_o (div_en_ex), .mult_sel_ex_o (mult_sel_ex), @@ -562,7 +409,6 @@ module ibex_core import ibex_pkg::*; #( .multdiv_signed_mode_ex_o(multdiv_signed_mode_ex), .multdiv_operand_a_ex_o (multdiv_operand_a_ex), .multdiv_operand_b_ex_o (multdiv_operand_b_ex), - .multdiv_ready_id_o (multdiv_ready_id), // CSR ID/EX .csr_access_o (csr_access), @@ -570,7 +416,6 @@ module ibex_core import ibex_pkg::*; #( .csr_op_en_o (csr_op_en), .csr_save_if_o (csr_save_if), // control signal to save PC .csr_save_id_o (csr_save_id), // control signal to save PC - .csr_save_wb_o (csr_save_wb), // control signal to save PC .csr_restore_mret_id_o(csr_restore_mret_id), // restore mstatus upon MRET .csr_restore_dret_id_o(csr_restore_dret_id), // restore mstatus upon MRET .csr_save_cause_o (csr_save_cause), @@ -578,7 +423,6 @@ module ibex_core import ibex_pkg::*; #( .priv_mode_i (priv_mode_id), .csr_mstatus_tw_i (csr_mstatus_tw), .illegal_csr_insn_i (illegal_csr_insn_id), - .data_ind_timing_i (data_ind_timing), // LSU .lsu_req_o (lsu_req), // to load store unit @@ -586,7 +430,6 @@ module ibex_core import ibex_pkg::*; #( .lsu_type_o (lsu_type), // to load store unit .lsu_sign_ext_o(lsu_sign_ext), // to load store unit .lsu_wdata_o (lsu_wdata), // to load store unit - .lsu_req_done_i(lsu_req_done), // from load store unit .lsu_addr_incr_req_i(lsu_addr_incr_req), .lsu_addr_last_i (lsu_addr_last), @@ -611,9 +454,6 @@ module ibex_core import ibex_pkg::*; #( .debug_ebreaku_i (debug_ebreaku), .trigger_match_i (trigger_match), - // Wakeup Signal - .wake_from_sleep_o(wake_from_sleep), - // write data to commit in the register file .result_ex_i(result_ex), .csr_rdata_i(csr_rdata), @@ -627,40 +467,28 @@ module ibex_core import ibex_pkg::*; #( .rf_waddr_id_o (rf_waddr_id), .rf_wdata_id_o (rf_wdata_id), .rf_we_id_o (rf_we_id), - .rf_rd_a_wb_match_o(rf_rd_a_wb_match), - .rf_rd_b_wb_match_o(rf_rd_b_wb_match), - .rf_waddr_wb_i (rf_waddr_wb), - .rf_wdata_fwd_wb_i(rf_wdata_fwd_wb), - .rf_write_wb_i (rf_write_wb), - - .en_wb_o (en_wb), - .instr_type_wb_o (instr_type_wb), + .en_wb_o (en_wb), .instr_perf_count_id_o (instr_perf_count_id), - .ready_wb_i (ready_wb), - .outstanding_load_wb_i (outstanding_load_wb), - .outstanding_store_wb_i(outstanding_store_wb), // Performance Counters .perf_jump_o (perf_jump), .perf_branch_o (perf_branch), .perf_tbranch_o (perf_tbranch), .perf_dside_wait_o(perf_dside_wait), - .perf_mul_wait_o (perf_mul_wait), + .perf_wfi_wait_o (perf_wfi_wait), .perf_div_wait_o (perf_div_wait), .instr_id_done_o (instr_id_done) ); - assign icache_inval_o = icache_inval; // for RVFI only assign unused_illegal_insn_id = illegal_insn_id; - ibex_ex_block #( + cve2_ex_block #( .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU(BranchTargetALU) + .RV32B (RV32B) ) ex_block_i ( - .clk_i (clk), + .clk_i (clk_i), .rst_ni(rst_ni), // ALU signal from ID stage @@ -669,10 +497,6 @@ module ibex_core import ibex_pkg::*; #( .alu_operand_b_i (alu_operand_b_ex), .alu_instr_first_cycle_i(instr_first_cycle_id), - // Branch target ALU signal from ID stage - .bt_a_operand_i(bt_a_operand), - .bt_b_operand_i(bt_b_operand), - // Multipler/Divider signal from ID stage .multdiv_operator_i (multdiv_operator_ex), .mult_en_i (mult_en_ex), @@ -682,8 +506,6 @@ module ibex_core import ibex_pkg::*; #( .multdiv_signed_mode_i(multdiv_signed_mode_ex), .multdiv_operand_a_i (multdiv_operand_a_ex), .multdiv_operand_b_i (multdiv_operand_b_ex), - .multdiv_ready_id_i (multdiv_ready_id), - .data_ind_timing_i (data_ind_timing), // Intermediate value register .imd_val_we_o(imd_val_we_ex), @@ -707,8 +529,8 @@ module ibex_core import ibex_pkg::*; #( assign data_req_o = data_req_out & ~pmp_req_err[PMP_D]; assign lsu_resp_err = lsu_load_err | lsu_store_err; - ibex_load_store_unit load_store_unit_i ( - .clk_i (clk), + cve2_load_store_unit load_store_unit_i ( + .clk_i (clk_i), .rst_ni(rst_ni), // data interface @@ -733,7 +555,6 @@ module ibex_core import ibex_pkg::*; #( .lsu_rdata_o (rf_wdata_lsu), .lsu_rdata_valid_o(rf_we_lsu), .lsu_req_i (lsu_req), - .lsu_req_done_o (lsu_req_done), .adder_result_ex_i(alu_adder_result_ex), @@ -753,27 +574,17 @@ module ibex_core import ibex_pkg::*; #( .perf_store_o(perf_store) ); - ibex_wb_stage #( - .ResetAll ( ResetAll ), - .WritebackStage(WritebackStage) - ) wb_stage_i ( - .clk_i (clk), - .rst_ni (rst_ni), - .en_wb_i (en_wb), - .instr_type_wb_i (instr_type_wb), - .pc_id_i (pc_id), + cve2_wb #( + ) wb_i ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .en_wb_i (en_wb), + .instr_is_compressed_id_i(instr_is_compressed_id), .instr_perf_count_id_i (instr_perf_count_id), - .ready_wb_o (ready_wb), - .rf_write_wb_o (rf_write_wb), - .outstanding_load_wb_o (outstanding_load_wb), - .outstanding_store_wb_o (outstanding_store_wb), - .pc_wb_o (pc_wb), .perf_instr_ret_wb_o (perf_instr_ret_wb), .perf_instr_ret_compressed_wb_o (perf_instr_ret_compressed_wb), - .perf_instr_ret_wb_spec_o (perf_instr_ret_wb_spec), - .perf_instr_ret_compressed_wb_spec_o(perf_instr_ret_compressed_wb_spec), .rf_waddr_id_i(rf_waddr_id), .rf_wdata_id_i(rf_wdata_id), @@ -782,79 +593,14 @@ module ibex_core import ibex_pkg::*; #( .rf_wdata_lsu_i(rf_wdata_lsu), .rf_we_lsu_i (rf_we_lsu), - .rf_wdata_fwd_wb_o(rf_wdata_fwd_wb), - .rf_waddr_wb_o(rf_waddr_wb), .rf_wdata_wb_o(rf_wdata_wb), .rf_we_wb_o (rf_we_wb), .lsu_resp_valid_i(lsu_resp_valid), - .lsu_resp_err_i (lsu_resp_err), - - .instr_done_wb_o(instr_done_wb) + .lsu_resp_err_i (lsu_resp_err) ); - ///////////////////////////// - // Register file interface // - ///////////////////////////// - - assign dummy_instr_id_o = dummy_instr_id; - assign rf_raddr_a_o = rf_raddr_a; - assign rf_waddr_wb_o = rf_waddr_wb; - assign rf_we_wb_o = rf_we_wb; - assign rf_raddr_b_o = rf_raddr_b; - - if (RegFileECC) begin : gen_regfile_ecc - - // SEC_CM: DATA_REG_SW.INTEGRITY - logic [1:0] rf_ecc_err_a, rf_ecc_err_b; - logic rf_ecc_err_a_id, rf_ecc_err_b_id; - - // ECC checkbit generation for regiter file wdata - prim_secded_inv_39_32_enc regfile_ecc_enc ( - .data_i(rf_wdata_wb), - .data_o(rf_wdata_wb_ecc_o) - ); - - // ECC checking on register file rdata - prim_secded_inv_39_32_dec regfile_ecc_dec_a ( - .data_i (rf_rdata_a_ecc_i), - .data_o (), - .syndrome_o(), - .err_o (rf_ecc_err_a) - ); - prim_secded_inv_39_32_dec regfile_ecc_dec_b ( - .data_i (rf_rdata_b_ecc_i), - .data_o (), - .syndrome_o(), - .err_o (rf_ecc_err_b) - ); - - // Assign read outputs - no error correction, just trigger an alert - assign rf_rdata_a = rf_rdata_a_ecc_i[31:0]; - assign rf_rdata_b = rf_rdata_b_ecc_i[31:0]; - - // Calculate errors - qualify with WB forwarding to avoid xprop into the alert signal - assign rf_ecc_err_a_id = |rf_ecc_err_a & rf_ren_a & ~rf_rd_a_wb_match; - assign rf_ecc_err_b_id = |rf_ecc_err_b & rf_ren_b & ~rf_rd_b_wb_match; - - // Combined error - assign rf_ecc_err_comb = instr_valid_id & (rf_ecc_err_a_id | rf_ecc_err_b_id); - - end else begin : gen_no_regfile_ecc - logic unused_rf_ren_a, unused_rf_ren_b; - logic unused_rf_rd_a_wb_match, unused_rf_rd_b_wb_match; - - assign unused_rf_ren_a = rf_ren_a; - assign unused_rf_ren_b = rf_ren_b; - assign unused_rf_rd_a_wb_match = rf_rd_a_wb_match; - assign unused_rf_rd_b_wb_match = rf_rd_b_wb_match; - assign rf_wdata_wb_ecc_o = rf_wdata_wb; - assign rf_rdata_a = rf_rdata_a_ecc_i; - assign rf_rdata_b = rf_rdata_b_ecc_i; - assign rf_ecc_err_comb = 1'b0; - end - /////////////////////// // Crash dump output // /////////////////////// @@ -864,15 +610,6 @@ module ibex_core import ibex_pkg::*; #( assign crash_dump_o.last_data_addr = lsu_addr_last; assign crash_dump_o.exception_addr = csr_mepc; - /////////////////// - // Alert outputs // - /////////////////// - - // Minor alert - core is in a recoverable state - assign alert_minor_o = icache_ecc_error; - - // Major alert - core is unrecoverable - assign alert_major_o = rf_ecc_err_comb | pc_mismatch_alert | csr_shadow_err; // Explict INC_ASSERT block to avoid unused signal lint warnings were asserts are not included `ifdef INC_ASSERT @@ -888,26 +625,12 @@ module ibex_core import ibex_pkg::*; #( assign outstanding_store_id = id_stage_i.instr_executing & id_stage_i.lsu_req_dec & id_stage_i.lsu_we; - if (WritebackStage) begin : gen_wb_stage - // When the writeback stage is present a load/store could be in ID or WB. A Load/store in ID can - // see a response before it moves to WB when it is unaligned otherwise we should only see - // a response when load/store is in WB. - assign outstanding_load_resp = outstanding_load_wb | - (outstanding_load_id & load_store_unit_i.split_misaligned_access); - - assign outstanding_store_resp = outstanding_store_wb | - (outstanding_store_id & load_store_unit_i.split_misaligned_access); - - // When writing back the result of a load, the load must have made it to writeback - `ASSERT(NoMemRFWriteWithoutPendingLoad, rf_we_lsu |-> outstanding_load_wb, clk_i, !rst_ni) - end else begin : gen_no_wb_stage - // Without writeback stage only look into whether load or store is in ID to determine if - // a response is expected. - assign outstanding_load_resp = outstanding_load_id; - assign outstanding_store_resp = outstanding_store_id; - - `ASSERT(NoMemRFWriteWithoutPendingLoad, rf_we_lsu |-> outstanding_load_id, clk_i, !rst_ni) - end + // Without writeback stage only look into whether load or store is in ID to determine if + // a response is expected. + assign outstanding_load_resp = outstanding_load_id; + assign outstanding_store_resp = outstanding_store_id; + + `ASSERT(NoMemRFWriteWithoutPendingLoad, rf_we_lsu |-> outstanding_load_id, clk_i, !rst_ni) `ASSERT(NoMemResponseWithoutPendingAccess, data_rvalid_i |-> outstanding_load_resp | outstanding_store_resp, clk_i, !rst_ni) @@ -916,8 +639,24 @@ module ibex_core import ibex_pkg::*; #( //////////////////////// // RF (Register File) // //////////////////////// -`ifdef RVFI -`endif + cve2_register_file_ff #( + .RV32E (RV32E), + .DataWidth (32), + .WordZeroVal (32'h0) + ) register_file_i ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .test_en_i(test_en_i), + + .raddr_a_i(rf_raddr_a), + .rdata_a_o(rf_rdata_a), + .raddr_b_i(rf_raddr_b), + .rdata_b_o(rf_rdata_b), + .waddr_a_i(rf_waddr_wb), + .wdata_a_i(rf_wdata_wb), + .we_a_i (rf_we_wb) + ); ///////////////////////////////////////// @@ -927,13 +666,9 @@ module ibex_core import ibex_pkg::*; #( assign csr_wdata = alu_operand_a_ex; assign csr_addr = csr_num_e'(csr_access ? alu_operand_b_ex[11:0] : 12'b0); - ibex_cs_registers #( + cve2_cs_registers #( .DbgTriggerEn (DbgTriggerEn), .DbgHwBreakNum (DbgHwBreakNum), - .DataIndTiming (DataIndTiming), - .DummyInstructions(DummyInstructions), - .ShadowCSR (ShadowCSR), - .ICache (ICache), .MHPMCounterNum (MHPMCounterNum), .MHPMCounterWidth (MHPMCounterWidth), .PMPEnable (PMPEnable), @@ -943,7 +678,7 @@ module ibex_core import ibex_pkg::*; #( .RV32M (RV32M), .RV32B (RV32B) ) cs_registers_i ( - .clk_i (clk), + .clk_i (clk_i), .rst_ni(rst_ni), // Hart ID from outside @@ -993,19 +728,9 @@ module ibex_core import ibex_pkg::*; #( .pc_if_i(pc_if), .pc_id_i(pc_id), - .pc_wb_i(pc_wb), - - .data_ind_timing_o (data_ind_timing), - .dummy_instr_en_o (dummy_instr_en), - .dummy_instr_mask_o (dummy_instr_mask), - .dummy_instr_seed_en_o(dummy_instr_seed_en), - .dummy_instr_seed_o (dummy_instr_seed), - .icache_enable_o (icache_enable), - .csr_shadow_err_o (csr_shadow_err), .csr_save_if_i (csr_save_if), .csr_save_id_i (csr_save_id), - .csr_save_wb_i (csr_save_wb), .csr_restore_mret_i(csr_restore_mret_id), .csr_restore_dret_i(csr_restore_dret_id), .csr_save_cause_i (csr_save_cause), @@ -1013,13 +738,9 @@ module ibex_core import ibex_pkg::*; #( .csr_mtval_i (csr_mtval), .illegal_csr_insn_o(illegal_csr_insn_id), - .double_fault_seen_o, - // performance counter related signals .instr_ret_i (perf_instr_ret_wb), .instr_ret_compressed_i (perf_instr_ret_compressed_wb), - .instr_ret_spec_i (perf_instr_ret_wb_spec), - .instr_ret_compressed_spec_i(perf_instr_ret_compressed_wb_spec), .iside_wait_i (perf_iside_wait), .jump_i (perf_jump), .branch_i (perf_branch), @@ -1027,7 +748,7 @@ module ibex_core import ibex_pkg::*; #( .mem_load_i (perf_load), .mem_store_i (perf_store), .dside_wait_i (perf_dside_wait), - .mul_wait_i (perf_mul_wait), + .wfi_wait_i (perf_wfi_wait), .div_wait_i (perf_div_wait) ); @@ -1055,7 +776,7 @@ module ibex_core import ibex_pkg::*; #( assign pmp_req_type[PMP_D] = data_we_o ? PMP_ACC_WRITE : PMP_ACC_READ; assign pmp_priv_lvl[PMP_D] = priv_mode_lsu; - ibex_pmp #( + cve2_pmp #( .PMPGranularity(PMPGranularity), .PMPNumChan (PMP_NUM_CHAN), .PMPNumRegions (PMPNumRegions) @@ -1096,7 +817,7 @@ module ibex_core import ibex_pkg::*; #( // second stage. RVFI outputs are all straight from flops. So 2 stage pipeline requires a single // set of flops (instr_info => RVFI_out), 3 stage pipeline requires two sets (instr_info => wb // => RVFI_out) - localparam int RVFI_STAGES = WritebackStage ? 2 : 1; + localparam int RVFI_STAGES = 1; logic rvfi_stage_valid [RVFI_STAGES]; logic [63:0] rvfi_stage_order [RVFI_STAGES]; @@ -1153,22 +874,20 @@ module ibex_core import ibex_pkg::*; #( logic [31:0] rvfi_mem_addr_d; logic [31:0] rvfi_mem_addr_q; logic rvfi_trap_id; - logic rvfi_trap_wb; logic [63:0] rvfi_stage_order_d; logic rvfi_id_done; - logic rvfi_wb_done; logic new_debug_req; logic new_nmi; logic new_irq; - ibex_pkg::irqs_t captured_mip; + cve2_pkg::irqs_t captured_mip; logic captured_nmi; logic captured_debug_req; logic captured_valid; // RVFI extension for co-simulation support // debug_req and MIP captured at IF -> ID transition so one extra stage - ibex_pkg::irqs_t rvfi_ext_stage_mip [RVFI_STAGES+1]; + cve2_pkg::irqs_t rvfi_ext_stage_mip [RVFI_STAGES+1]; logic rvfi_ext_stage_nmi [RVFI_STAGES+1]; logic rvfi_ext_stage_debug_req [RVFI_STAGES+1]; logic [63:0] rvfi_ext_stage_mcycle [RVFI_STAGES]; @@ -1226,56 +945,20 @@ module ibex_core import ibex_pkg::*; #( // Factor in exceptions taken in ID so RVFI tracking picks up flushed instructions that took // a trap - assign rvfi_id_done = instr_id_done | (id_stage_i.controller_i.rvfi_flush_next & - id_stage_i.controller_i.id_exception_o); - - if (WritebackStage) begin : gen_rvfi_wb_stage - logic unused_instr_new_id; - - assign unused_instr_new_id = instr_new_id; + // MRET causes MSTATUS to get written one clock later. Fix rvfi_valid when executing MRET + assign rvfi_id_done = (instr_id_done & !id_stage_i.controller_i.mret_insn)| + id_stage_i.csr_restore_mret_id_o | + (id_stage_i.controller_i.rvfi_flush_next & id_stage_i.controller_i.exc_req_d); - // With writeback stage first RVFI stage buffers instruction information captured in ID/EX - // awaiting instruction retirement and RF Write data/Mem read data whilst instruction is in WB - // So first stage becomes valid when instruction leaves ID/EX stage and remains valid until - // instruction leaves WB - assign rvfi_stage_valid_d[0] = (rvfi_id_done & ~dummy_instr_id) | - (rvfi_stage_valid[0] & ~rvfi_wb_done); - // Second stage is output stage so simple valid cycle after instruction leaves WB (and so has - // retired) - assign rvfi_stage_valid_d[1] = rvfi_wb_done; + // Without writeback stage first RVFI stage is output stage so simply valid the cycle after + // instruction leaves ID/EX (and so has retired) + assign rvfi_stage_valid_d[0] = rvfi_id_done; + // Without writeback stage signal new instr_new_wb when instruction enters ID/EX to correctly + // setup register write signals + assign rvfi_instr_new_wb = instr_new_id; + assign rvfi_trap_id = id_stage_i.controller_i.exc_req_d | id_stage_i.controller_i.exc_req_lsu; - // Signal new instruction in WB cycle after instruction leaves ID/EX (to enter WB) - logic rvfi_instr_new_wb_q; - - // Signal new instruction in WB either when one has just entered or when a trap is progressing - // through the tracking pipeline - assign rvfi_instr_new_wb = rvfi_instr_new_wb_q | (rvfi_stage_valid[0] & rvfi_stage_trap[0]); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - rvfi_instr_new_wb_q <= 0; - end else begin - rvfi_instr_new_wb_q <= rvfi_id_done; - end - end - - assign rvfi_trap_id = id_stage_i.controller_i.id_exception_o; - assign rvfi_trap_wb = id_stage_i.controller_i.exc_req_lsu; - // WB is instantly done in the tracking pipeline when a trap is progress through the pipeline - assign rvfi_wb_done = instr_done_wb | (rvfi_stage_valid[0] & rvfi_stage_trap[0]); - end else begin : gen_rvfi_no_wb_stage - // Without writeback stage first RVFI stage is output stage so simply valid the cycle after - // instruction leaves ID/EX (and so has retired) - assign rvfi_stage_valid_d[0] = rvfi_id_done & ~dummy_instr_id; - // Without writeback stage signal new instr_new_wb when instruction enters ID/EX to correctly - // setup register write signals - assign rvfi_instr_new_wb = instr_new_id; - assign rvfi_trap_id = id_stage_i.controller_i.exc_req_d | id_stage_i.controller_i.exc_req_lsu; - assign rvfi_trap_wb = 1'b0; - assign rvfi_wb_done = instr_done_wb; - end - - assign rvfi_stage_order_d = dummy_instr_id ? rvfi_stage_order[0] : rvfi_stage_order[0] + 64'd1; + assign rvfi_stage_order_d = rvfi_stage_order[0] + 64'd1; // For interrupts and debug Ibex will take the relevant trap as soon as whatever instruction in ID // finishes or immediately if the ID stage is empty. The rvfi_ext interface provides the DV @@ -1409,10 +1092,12 @@ module ibex_core import ibex_pkg::*; #( rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i]; rvfi_ext_stage_mcycle[i] <= cs_registers_i.mcycle_counter_i.counter_val_o; end + else begin + rvfi_stage_trap[i] <= 0; + end end else begin - if (rvfi_wb_done) begin rvfi_stage_halt[i] <= rvfi_stage_halt[i-1]; - rvfi_stage_trap[i] <= rvfi_stage_trap[i-1] | rvfi_trap_wb; + rvfi_stage_trap[i] <= rvfi_stage_trap[i-1]; rvfi_stage_intr[i] <= rvfi_stage_intr[i-1]; rvfi_stage_order[i] <= rvfi_stage_order[i-1]; rvfi_stage_insn[i] <= rvfi_stage_insn[i-1]; @@ -1443,7 +1128,6 @@ module ibex_core import ibex_pkg::*; #( rvfi_ext_stage_nmi[i+1] <= rvfi_ext_stage_nmi[i]; rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i]; rvfi_ext_stage_mcycle[i] <= rvfi_ext_stage_mcycle[i-1]; - end end end end @@ -1596,13 +1280,9 @@ module ibex_core import ibex_pkg::*; #( end `else - logic unused_instr_new_id, unused_instr_id_done, unused_instr_done_wb; + logic unused_instr_new_id, unused_instr_id_done; assign unused_instr_id_done = instr_id_done; assign unused_instr_new_id = instr_new_id; - assign unused_instr_done_wb = instr_done_wb; `endif - // Certain parameter combinations are not supported - `ASSERT_INIT(IllegalParamSecure, !(SecureIbex && (RV32M == RV32MNone))) - endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_counter.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_counter.sv similarity index 99% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_counter.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_counter.sv index a6187b78..417614b1 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_counter.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_counter.sv @@ -1,4 +1,4 @@ -module ibex_counter #( +module cve2_counter #( parameter int CounterWidth = 32, // When set `counter_val_upd_o` provides an incremented version of the counter value, otherwise // the output is hard-wired to 0. This is required to allow Xilinx DSP inference to work diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_cs_registers.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv similarity index 85% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_cs_registers.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv index aa328205..9678638d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_cs_registers.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_cs_registers.sv @@ -12,22 +12,19 @@ `include "prim_assert.sv" -module ibex_cs_registers #( +module cve2_cs_registers #( parameter bit DbgTriggerEn = 0, parameter int unsigned DbgHwBreakNum = 1, - parameter bit DataIndTiming = 1'b0, - parameter bit DummyInstructions = 1'b0, - parameter bit ShadowCSR = 1'b0, - parameter bit ICache = 1'b0, parameter int unsigned MHPMCounterNum = 10, parameter int unsigned MHPMCounterWidth = 40, parameter bit PMPEnable = 0, parameter int unsigned PMPGranularity = 0, parameter int unsigned PMPNumRegions = 4, parameter bit RV32E = 0, - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast, + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( + // Clock and Reset input logic clk_i, input logic rst_ni, @@ -36,8 +33,8 @@ module ibex_cs_registers #( input logic [31:0] hart_id_i, // Privilege mode - output ibex_pkg::priv_lvl_e priv_mode_id_o, - output ibex_pkg::priv_lvl_e priv_mode_lsu_o, + output cve2_pkg::priv_lvl_e priv_mode_id_o, + output cve2_pkg::priv_lvl_e priv_mode_lsu_o, output logic csr_mstatus_tw_o, // mtvec @@ -47,9 +44,9 @@ module ibex_cs_registers #( // Interface to registers (SRAM like) input logic csr_access_i, - input ibex_pkg::csr_num_e csr_addr_i, + input cve2_pkg::csr_num_e csr_addr_i, input logic [31:0] csr_wdata_i, - input ibex_pkg::csr_op_e csr_op_i, + input cve2_pkg::csr_op_e csr_op_i, input csr_op_en_i, output logic [31:0] csr_rdata_o, @@ -57,21 +54,21 @@ module ibex_cs_registers #( input logic irq_software_i, input logic irq_timer_i, input logic irq_external_i, - input logic [14:0] irq_fast_i, + input logic [15:0] irq_fast_i, input logic nmi_mode_i, output logic irq_pending_o, // interrupt request pending - output ibex_pkg::irqs_t irqs_o, // interrupt requests qualified with mie + output cve2_pkg::irqs_t irqs_o, // interrupt requests qualified with mie output logic csr_mstatus_mie_o, output logic [31:0] csr_mepc_o, // PMP - output ibex_pkg::pmp_cfg_t csr_pmp_cfg_o [PMPNumRegions], + output cve2_pkg::pmp_cfg_t csr_pmp_cfg_o [PMPNumRegions], output logic [33:0] csr_pmp_addr_o [PMPNumRegions], - output ibex_pkg::pmp_mseccfg_t csr_pmp_mseccfg_o, + output cve2_pkg::pmp_mseccfg_t csr_pmp_mseccfg_o, // debug input logic debug_mode_i, - input ibex_pkg::dbg_cause_e debug_cause_i, + input cve2_pkg::dbg_cause_e debug_cause_i, input logic debug_csr_save_i, output logic [31:0] csr_depc_o, output logic debug_single_step_o, @@ -81,35 +78,21 @@ module ibex_cs_registers #( input logic [31:0] pc_if_i, input logic [31:0] pc_id_i, - input logic [31:0] pc_wb_i, - - // CPU control bits - output logic data_ind_timing_o, - output logic dummy_instr_en_o, - output logic [2:0] dummy_instr_mask_o, - output logic dummy_instr_seed_en_o, - output logic [31:0] dummy_instr_seed_o, - output logic icache_enable_o, - output logic csr_shadow_err_o, // Exception save/restore input logic csr_save_if_i, input logic csr_save_id_i, - input logic csr_save_wb_i, input logic csr_restore_mret_i, input logic csr_restore_dret_i, input logic csr_save_cause_i, - input ibex_pkg::exc_cause_e csr_mcause_i, + input cve2_pkg::exc_cause_e csr_mcause_i, input logic [31:0] csr_mtval_i, output logic illegal_csr_insn_o, // access to non-existent CSR, // with wrong priviledge level, or // missing write permissions - output logic double_fault_seen_o, // Performance Counters input logic instr_ret_i, // instr retired in ID/EX stage input logic instr_ret_compressed_i, // compressed instr retired - input logic instr_ret_spec_i, // speculative instr_ret_i - input logic instr_ret_compressed_spec_i, // speculative instr_ret_compressed_i input logic iside_wait_i, // core waiting for the iside input logic jump_i, // jump instr seen (j, jr, jal, jalr) input logic branch_i, // branch instr seen (bf, bnf) @@ -117,11 +100,11 @@ module ibex_cs_registers #( input logic mem_load_i, // load from memory in this cycle input logic mem_store_i, // store to memory in this cycle input logic dside_wait_i, // core waiting for the dside - input logic mul_wait_i, // core waiting for multiply + input logic wfi_wait_i, // core waiting for interrupt input logic div_wait_i // core waiting for divide ); - import ibex_pkg::*; +import cve2_pkg::*; localparam int unsigned RV32BEnabled = (RV32B == RV32BNone) ? 0 : 1; localparam int unsigned RV32MEnabled = (RV32M == RV32MNone) ? 0 : 1; @@ -174,23 +157,12 @@ module ibex_cs_registers #( priv_lvl_e prv; } dcsr_t; - // CPU control register fields - typedef struct packed { - logic double_fault_seen; - logic sync_exc_seen; - logic [2:0] dummy_instr_mask; - logic dummy_instr_en; - logic data_ind_timing; - logic icache_enable; - } cpu_ctrl_t; - // Interrupt and exception control signals logic [31:0] exception_pc; // CSRs priv_lvl_e priv_lvl_q, priv_lvl_d; status_t mstatus_q, mstatus_d; - logic mstatus_err; logic mstatus_en; irqs_t mie_q, mie_d; logic mie_en; @@ -198,12 +170,11 @@ module ibex_cs_registers #( logic mscratch_en; logic [31:0] mepc_q, mepc_d; logic mepc_en; - logic [5:0] mcause_q, mcause_d; + logic [6:0] mcause_q, mcause_d; logic mcause_en; logic [31:0] mtval_q, mtval_d; logic mtval_en; logic [31:0] mtvec_q, mtvec_d; - logic mtvec_err; logic mtvec_en; irqs_t mip; dcsr_t dcsr_q, dcsr_d; @@ -219,12 +190,11 @@ module ibex_cs_registers #( status_stk_t mstack_q, mstack_d; logic mstack_en; logic [31:0] mstack_epc_q, mstack_epc_d; - logic [5:0] mstack_cause_q, mstack_cause_d; + logic [6:0] mstack_cause_q, mstack_cause_d; // PMP Signals logic [31:0] pmp_addr_rdata [PMP_MAX_REGIONS]; logic [PMP_CFG_W-1:0] pmp_cfg_rdata [PMP_MAX_REGIONS]; - logic pmp_csr_err; pmp_mseccfg_t pmp_mseccfg; // Hardware performance monitor signals @@ -246,18 +216,13 @@ module ibex_cs_registers #( logic unused_mhpmcounterh_we_1; logic unused_mhpmcounter_incr_1; - logic [63:0] minstret_next, minstret_raw; + logic [63:0] minstret_raw; // Debug / trigger registers logic [31:0] tselect_rdata; logic [31:0] tmatch_control_rdata; logic [31:0] tmatch_value_rdata; - // CPU control bits - cpu_ctrl_t cpuctrl_q, cpuctrl_d, cpuctrl_wdata_raw, cpuctrl_wdata; - logic cpuctrl_we; - logic cpuctrl_err; - // CSR update logic logic [31:0] csr_wdata_int; logic [31:0] csr_rdata_int; @@ -308,6 +273,8 @@ module ibex_cs_registers #( CSR_MIMPID: csr_rdata_int = CSR_MIMPID_VALUE; // mhartid: unique hardware thread id CSR_MHARTID: csr_rdata_int = hart_id_i; + // mconfigptr: pointer to configuration data structre + CSR_MCONFIGPTR: csr_rdata_int = CSR_MCONFIGPTR_VALUE; // mstatus: always M-mode, contains IE bit CSR_MSTATUS: begin @@ -319,6 +286,13 @@ module ibex_cs_registers #( csr_rdata_int[CSR_MSTATUS_TW_BIT] = mstatus_q.tw; end + // mstatush: All zeros for Ibex (fixed little endian and all other bits reserved) + CSR_MSTATUSH: csr_rdata_int = '0; + + // menvcfg: machine environment configuration, all zeros for Ibex (none of the relevant + // features are implemented) + CSR_MENVCFG, CSR_MENVCFGH: csr_rdata_int = '0; + // misa CSR_MISA: csr_rdata_int = MISA_VALUE; @@ -345,7 +319,7 @@ module ibex_cs_registers #( CSR_MEPC: csr_rdata_int = mepc_q; // mcause: exception cause - CSR_MCAUSE: csr_rdata_int = {mcause_q[5], 26'b0, mcause_q[4:0]}; + CSR_MCAUSE: csr_rdata_int = {mcause_q[6], 25'b0, mcause_q[5:0]}; // mtval: trap value CSR_MTVAL: csr_rdata_int = mtval_q; @@ -486,11 +460,6 @@ module ibex_cs_registers #( illegal_csr = ~DbgTriggerEn; end - // Custom CSR for controlling CPU features - CSR_CPUCTRL: begin - csr_rdata_int = {{32 - $bits(cpu_ctrl_t) {1'b0}}, cpuctrl_q}; - end - // Custom CSR for LFSR re-seeding (cannot be read) CSR_SECURESEED: begin csr_rdata_int = '0; @@ -500,6 +469,16 @@ module ibex_cs_registers #( illegal_csr = 1'b1; end endcase + + if (!PMPEnable) begin + if (csr_addr inside {CSR_PMPCFG0, CSR_PMPCFG1, CSR_PMPCFG2, CSR_PMPCFG3, + CSR_PMPADDR0, CSR_PMPADDR1, CSR_PMPADDR2, CSR_PMPADDR3, + CSR_PMPADDR4, CSR_PMPADDR5, CSR_PMPADDR6, CSR_PMPADDR7, + CSR_PMPADDR8, CSR_PMPADDR9, CSR_PMPADDR10, CSR_PMPADDR11, + CSR_PMPADDR12, CSR_PMPADDR13, CSR_PMPADDR14, CSR_PMPADDR15}) begin + illegal_csr = 1'b1; + end + end end // write logic @@ -514,7 +493,7 @@ module ibex_cs_registers #( mepc_en = 1'b0; mepc_d = {csr_wdata_int[31:1], 1'b0}; mcause_en = 1'b0; - mcause_d = {csr_wdata_int[31], csr_wdata_int[4:0]}; + mcause_d = {csr_wdata_int[31], csr_wdata_int[5:0]}; mtval_en = 1'b0; mtval_d = csr_wdata_int; mtvec_en = csr_mtvec_init_i; @@ -539,11 +518,6 @@ module ibex_cs_registers #( mhpmcounter_we = '0; mhpmcounterh_we = '0; - cpuctrl_we = 1'b0; - cpuctrl_d = cpuctrl_q; - - double_fault_seen_o = 1'b0; - if (csr_we_int) begin unique case (csr_addr_i) // mstatus: IE bit @@ -641,11 +615,6 @@ module ibex_cs_registers #( mhpmcounterh_we[mhpmcounter_idx] = 1'b1; end - CSR_CPUCTRL: begin - cpuctrl_d = cpuctrl_wdata; - cpuctrl_we = 1'b1; - end - default:; endcase end @@ -661,9 +630,6 @@ module ibex_cs_registers #( csr_save_id_i: begin exception_pc = pc_id_i; end - csr_save_wb_i: begin - exception_pc = pc_wb_i; - end default:; endcase @@ -695,17 +661,6 @@ module ibex_cs_registers #( // save previous status for recoverable NMI mstack_en = 1'b1; - if (!mcause_d[5]) begin - // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC - // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC - cpuctrl_we = 1'b1; - - cpuctrl_d.sync_exc_seen = 1'b1; - if (cpuctrl_q.sync_exc_seen) begin - double_fault_seen_o = 1'b1; - cpuctrl_d.double_fault_seen = 1'b1; - end - end end end // csr_save_cause_i @@ -718,10 +673,12 @@ module ibex_cs_registers #( mstatus_en = 1'b1; mstatus_d.mie = mstatus_q.mpie; // re-enable interrupts + if (mstatus_q.mpp != PRIV_LVL_M) begin + mstatus_d.mprv = 1'b0; + end + // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC - cpuctrl_we = 1'b1; - cpuctrl_d.sync_exc_seen = 1'b0; if (nmi_mode_i) begin // when returning from an NMI restore state from mstack CSR @@ -797,13 +754,12 @@ module ibex_cs_registers #( // MSTATUS localparam status_t MSTATUS_RST_VAL = '{mie: 1'b0, - mpie: 1'b1, - mpp: PRIV_LVL_U, + mpie: 1'b0, + mpp: PRIV_LVL_M, mprv: 1'b0, tw: 1'b0}; - ibex_csr #( + cve2_csr #( .Width ($bits(status_t)), - .ShadowCopy(ShadowCSR), .ResetValue({MSTATUS_RST_VAL}) ) u_mstatus_csr ( .clk_i (clk_i), @@ -811,11 +767,11 @@ module ibex_cs_registers #( .wr_data_i ({mstatus_d}), .wr_en_i (mstatus_en), .rd_data_o (mstatus_q), - .rd_error_o(mstatus_err) + .rd_error_o() ); // MEPC - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -833,7 +789,7 @@ module ibex_cs_registers #( assign mie_d.irq_timer = csr_wdata_int[CSR_MTIX_BIT]; assign mie_d.irq_external = csr_wdata_int[CSR_MEIX_BIT]; assign mie_d.irq_fast = csr_wdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW]; - ibex_csr #( + cve2_csr #( .Width ($bits(irqs_t)), .ShadowCopy(1'b0), .ResetValue('0) @@ -847,7 +803,7 @@ module ibex_cs_registers #( ); // MSCRATCH - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -861,8 +817,8 @@ module ibex_cs_registers #( ); // MCAUSE - ibex_csr #( - .Width (6), + cve2_csr #( + .Width (7), .ShadowCopy(1'b0), .ResetValue('0) ) u_mcause_csr ( @@ -875,7 +831,7 @@ module ibex_cs_registers #( ); // MTVAL - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -889,9 +845,8 @@ module ibex_cs_registers #( ); // MTVEC - ibex_csr #( + cve2_csr #( .Width (32), - .ShadowCopy(ShadowCSR), .ResetValue(32'd1) ) u_mtvec_csr ( .clk_i (clk_i), @@ -899,7 +854,7 @@ module ibex_cs_registers #( .wr_data_i (mtvec_d), .wr_en_i (mtvec_en), .rd_data_o (mtvec_q), - .rd_error_o(mtvec_err) + .rd_error_o() ); // DCSR @@ -909,7 +864,7 @@ module ibex_cs_registers #( prv: PRIV_LVL_M, default: '0 }; - ibex_csr #( + cve2_csr #( .Width ($bits(dcsr_t)), .ShadowCopy(1'b0), .ResetValue({DCSR_RESET_VAL}) @@ -923,7 +878,7 @@ module ibex_cs_registers #( ); // DEPC - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -937,7 +892,7 @@ module ibex_cs_registers #( ); // DSCRATCH0 - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -951,7 +906,7 @@ module ibex_cs_registers #( ); // DSCRATCH1 - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -966,7 +921,7 @@ module ibex_cs_registers #( // MSTACK localparam status_stk_t MSTACK_RESET_VAL = '{mpie: 1'b1, mpp: PRIV_LVL_U}; - ibex_csr #( + cve2_csr #( .Width ($bits(status_stk_t)), .ShadowCopy(1'b0), .ResetValue({MSTACK_RESET_VAL}) @@ -980,7 +935,7 @@ module ibex_cs_registers #( ); // MSTACK_EPC - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -994,8 +949,8 @@ module ibex_cs_registers #( ); // MSTACK_CAUSE - ibex_csr #( - .Width (6), + cve2_csr #( + .Width (7), .ShadowCopy(1'b0), .ResetValue('0) ) u_mstack_cause_csr ( @@ -1013,10 +968,10 @@ module ibex_cs_registers #( if (PMPEnable) begin : g_pmp_registers // PMP reset values - `ifdef IBEX_CUSTOM_PMP_RESET_VALUES - `include "ibex_pmp_reset.svh" + `ifdef CVE2_CUSTOM_PMP_RESET_VALUES + `include "cve2_pmp_reset.svh" `else - `include "ibex_pmp_reset_default.svh" + `include "cve2_pmp_reset_default.svh" `endif pmp_mseccfg_t pmp_mseccfg_q, pmp_mseccfg_d; @@ -1102,9 +1057,8 @@ module ibex_cs_registers #( &csr_wdata_int[(i%4)*PMP_CFG_W+:2]; assign pmp_cfg_wdata[i].read = csr_wdata_int[(i%4)*PMP_CFG_W]; - ibex_csr #( + cve2_csr #( .Width ($bits(pmp_cfg_t)), - .ShadowCopy(ShadowCSR), .ResetValue(pmp_cfg_rst[i]) ) u_pmp_cfg_csr ( .clk_i (clk_i), @@ -1131,9 +1085,8 @@ module ibex_cs_registers #( (csr_addr == (CSR_OFF_PMP_ADDR + i[11:0])); end - ibex_csr #( + cve2_csr #( .Width (PMPAddrWidth), - .ShadowCopy(ShadowCSR), .ResetValue(pmp_addr_rst[i][33-:PMPAddrWidth]) ) u_pmp_addr_csr ( .clk_i (clk_i), @@ -1164,9 +1117,8 @@ module ibex_cs_registers #( // MSECCFG.RLB cannot be set again assign pmp_mseccfg_d.rlb = any_pmp_entry_locked ? 1'b0 : csr_wdata_int[CSR_MSECCFG_RLB_BIT]; - ibex_csr #( + cve2_csr #( .Width ($bits(pmp_mseccfg_t)), - .ShadowCopy(ShadowCSR), .ResetValue(pmp_mseccfg_rst) ) u_pmp_mseccfg ( .clk_i (clk_i), @@ -1177,7 +1129,6 @@ module ibex_cs_registers #( .rd_error_o(pmp_mseccfg_err) ); - assign pmp_csr_err = (|pmp_cfg_err) | (|pmp_addr_err) | pmp_mseccfg_err; assign pmp_mseccfg = pmp_mseccfg_q; end else begin : g_no_pmp_tieoffs @@ -1190,7 +1141,6 @@ module ibex_cs_registers #( assign csr_pmp_cfg_o[i] = pmp_cfg_t'(1'b0); assign csr_pmp_addr_o[i] = '0; end - assign pmp_csr_err = 1'b0; assign pmp_mseccfg = '0; end @@ -1219,7 +1169,7 @@ module ibex_cs_registers #( end // When adding or altering performance counter meanings and default - // mappings please update dv/verilator/pcount/cpp/ibex_pcounts.cc + // mappings please update dv/verilator/pcount/cpp/cve2_pcounts.cc // appropriately. // // active counters @@ -1234,7 +1184,7 @@ module ibex_cs_registers #( mhpmcounter_incr[8] = branch_i; // num of branches (conditional) mhpmcounter_incr[9] = branch_taken_i; // num of taken branches (conditional) mhpmcounter_incr[10] = instr_ret_compressed_i; // num of compressed instr - mhpmcounter_incr[11] = mul_wait_i; // cycles waiting for multiply + mhpmcounter_incr[11] = wfi_wait_i; // cycles waiting for multiply mhpmcounter_incr[12] = div_wait_i; // cycles waiting for divide end @@ -1255,7 +1205,7 @@ module ibex_cs_registers #( end // mcycle - ibex_counter #( + cve2_counter #( .CounterWidth(64) ) mcycle_counter_i ( .clk_i(clk_i), @@ -1270,7 +1220,7 @@ module ibex_cs_registers #( // minstret - ibex_counter #( + cve2_counter #( .CounterWidth(64), .ProvideValUpd(1) ) minstret_counter_i ( @@ -1281,7 +1231,7 @@ module ibex_cs_registers #( .counter_we_i(mhpmcounter_we[2]), .counter_val_i(csr_wdata_int), .counter_val_o(minstret_raw), - .counter_val_upd_o(minstret_next) + .counter_val_upd_o() ); // Where the writeback stage is present instruction in ID observing value of minstret must take @@ -1291,7 +1241,7 @@ module ibex_cs_registers #( // so the incorrect value doesn't matter. A similar behaviour is required for the compressed // instruction retired counter below. When the writeback stage isn't present the speculative // signals are always 0. - assign mhpmcounter[2] = instr_ret_spec_i & ~mcountinhibit[2] ? minstret_next : minstret_raw; + assign mhpmcounter[2] = minstret_raw; // reserved: assign mhpmcounter[1] = '0; @@ -1306,7 +1256,7 @@ module ibex_cs_registers #( if (i < MHPMCounterNum) begin : gen_imp logic [63:0] mhpmcounter_raw, mhpmcounter_next; - ibex_counter #( + cve2_counter #( .CounterWidth(MHPMCounterWidth), .ProvideValUpd(Cnt == 10) ) mcounters_variable_i ( @@ -1324,7 +1274,6 @@ module ibex_cs_registers #( // Special behaviour for reading compressed instruction retired counter, see comment on // `mhpmcounter[2]` above for further information. assign mhpmcounter[Cnt] = - instr_ret_compressed_spec_i & ~mcountinhibit[Cnt] ? mhpmcounter_next: mhpmcounter_raw; end else begin : gen_other_cnts logic [63:0] unused_mhpmcounter_next; @@ -1334,11 +1283,6 @@ module ibex_cs_registers #( end end else begin : gen_unimp assign mhpmcounter[Cnt] = '0; - - if (Cnt == 10) begin : gen_no_compressed_instr_cnt - logic unused_instr_ret_compressed_spec_i; - assign unused_instr_ret_compressed_spec_i = instr_ret_compressed_spec_i; - end end end @@ -1407,7 +1351,7 @@ module ibex_cs_registers #( assign tmatch_value_d = csr_wdata_int[31:0]; // Registers - ibex_csr #( + cve2_csr #( .Width (DbgHwNumLen), .ShadowCopy(1'b0), .ResetValue('0) @@ -1421,7 +1365,7 @@ module ibex_cs_registers #( ); for (genvar i = 0; i < DbgHwBreakNum; i++) begin : g_dbg_tmatch_reg - ibex_csr #( + cve2_csr #( .Width (1), .ShadowCopy(1'b0), .ResetValue('0) @@ -1434,7 +1378,7 @@ module ibex_cs_registers #( .rd_error_o() ); - ibex_csr #( + cve2_csr #( .Width (32), .ShadowCopy(1'b0), .ResetValue('0) @@ -1501,88 +1445,88 @@ module ibex_cs_registers #( // CPU control register // ////////////////////////// - // Cast register write data - assign cpuctrl_wdata_raw = cpu_ctrl_t'(csr_wdata_int[$bits(cpu_ctrl_t)-1:0]); - - // Generate fixed time execution bit - if (DataIndTiming) begin : gen_dit - // SEC_CM: CORE.DATA_REG_SW.SCA - assign cpuctrl_wdata.data_ind_timing = cpuctrl_wdata_raw.data_ind_timing; - - end else begin : gen_no_dit - // tieoff for the unused bit - logic unused_dit; - assign unused_dit = cpuctrl_wdata_raw.data_ind_timing; - - // field will always read as zero if not configured - assign cpuctrl_wdata.data_ind_timing = 1'b0; - end - - assign data_ind_timing_o = cpuctrl_q.data_ind_timing; - - // Generate dummy instruction signals - if (DummyInstructions) begin : gen_dummy - // SEC_CM: CTRL_FLOW.UNPREDICTABLE - assign cpuctrl_wdata.dummy_instr_en = cpuctrl_wdata_raw.dummy_instr_en; - assign cpuctrl_wdata.dummy_instr_mask = cpuctrl_wdata_raw.dummy_instr_mask; - - // Signal a write to the seed register - assign dummy_instr_seed_en_o = csr_we_int && (csr_addr == CSR_SECURESEED); - assign dummy_instr_seed_o = csr_wdata_int; - - end else begin : gen_no_dummy - // tieoff for the unused bit - logic unused_dummy_en; - logic [2:0] unused_dummy_mask; - assign unused_dummy_en = cpuctrl_wdata_raw.dummy_instr_en; - assign unused_dummy_mask = cpuctrl_wdata_raw.dummy_instr_mask; - - // field will always read as zero if not configured - assign cpuctrl_wdata.dummy_instr_en = 1'b0; - assign cpuctrl_wdata.dummy_instr_mask = 3'b000; - assign dummy_instr_seed_en_o = 1'b0; - assign dummy_instr_seed_o = '0; - end - - assign dummy_instr_en_o = cpuctrl_q.dummy_instr_en; - assign dummy_instr_mask_o = cpuctrl_q.dummy_instr_mask; - - // Generate icache enable bit - if (ICache) begin : gen_icache_enable - assign cpuctrl_wdata.icache_enable = cpuctrl_wdata_raw.icache_enable; - end else begin : gen_no_icache - // tieoff for the unused icen bit - logic unused_icen; - assign unused_icen = cpuctrl_wdata_raw.icache_enable; - - // icen field will always read as zero if ICache not configured - assign cpuctrl_wdata.icache_enable = 1'b0; - end - - assign cpuctrl_wdata.double_fault_seen = cpuctrl_wdata_raw.double_fault_seen; - assign cpuctrl_wdata.sync_exc_seen = cpuctrl_wdata_raw.sync_exc_seen; - - assign icache_enable_o = cpuctrl_q.icache_enable; +`ifdef RVFI + logic [63:0] mstatus_extended_read; + logic [63:0] mstatus_extended_write; + + assign mstatus_extended_read[CSR_MSTATUS_MIE_BIT] = mstatus_q.mie; + assign mstatus_extended_read[CSR_MSTATUS_MPIE_BIT] = mstatus_q.mpie; + assign mstatus_extended_read[CSR_MSTATUS_MPP_BIT_HIGH:CSR_MSTATUS_MPP_BIT_LOW] = mstatus_q.mpp; + assign mstatus_extended_read[CSR_MSTATUS_MPRV_BIT] = mstatus_q.mprv; + assign mstatus_extended_read[CSR_MSTATUS_TW_BIT] = mstatus_q.tw; + + assign mstatus_extended_write[CSR_MSTATUS_MIE_BIT] = mstatus_d.mie; + assign mstatus_extended_write[CSR_MSTATUS_MPIE_BIT] = mstatus_d.mpie; + assign mstatus_extended_write[CSR_MSTATUS_MPP_BIT_HIGH:CSR_MSTATUS_MPP_BIT_LOW] = mstatus_d.mpp; + assign mstatus_extended_write[CSR_MSTATUS_MPRV_BIT] = mstatus_d.mprv; + assign mstatus_extended_write[CSR_MSTATUS_TW_BIT] = mstatus_d.tw; + + wire [63:0] rvfi_csr_bypass; + + assign rvfi_csr_bypass = csr_save_cause_i; + + bit [63:0] rvfi_csr_addr; + bit [63:0] rvfi_csr_rdata; + bit [63:0] rvfi_csr_wdata; + bit [63:0] rvfi_csr_rmask; + bit [63:0] rvfi_csr_wmask; + wire [63:0] rvfi_csr_wmask_q; + wire [63:0] rvfi_csr_rmask_q; + assign rvfi_csr_if.rvfi_csr_addr = rvfi_csr_addr; + assign rvfi_csr_if.rvfi_csr_rdata = rvfi_csr_rdata; + assign rvfi_csr_if.rvfi_csr_wdata = rvfi_csr_wdata; + assign rvfi_csr_if.rvfi_csr_rmask = rvfi_csr_rmask; + assign rvfi_csr_if.rvfi_csr_wmask = rvfi_csr_wmask; + assign rvfi_csr_rmask_q = ((~csr_wr & csr_op_en_i & ~illegal_csr_insn_o)) ? -1 : 0; + assign rvfi_csr_wmask_q = ((csr_wr & csr_op_en_i & ~illegal_csr_insn_o)) ? -1 : 0; + always @(posedge clknrst_if.clk) begin + rvfi_csr_addr = csr_addr_i; + rvfi_csr_rdata = csr_rdata_int; + rvfi_csr_wdata = csr_wdata_int; + rvfi_csr_rmask = (rvfi_csr_rmask_q); + rvfi_csr_wmask = (rvfi_csr_wmask_q); + end - ibex_csr #( - .Width ($bits(cpu_ctrl_t)), - .ShadowCopy(ShadowCSR), - .ResetValue('0) - ) u_cpuctrl_csr ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .wr_data_i ({cpuctrl_d}), - .wr_en_i (cpuctrl_we), - .rd_data_o (cpuctrl_q), - .rd_error_o(cpuctrl_err) - ); +`define RVFI_CONNECT(CSR_ADDR, CSR_NAME, CSR_RDATA, CSR_WDATA, CSR_RMASK, CSR_WMASK) \ + bit [63:0] rvfi_``CSR_NAME``_csr_rdata;\ + bit [63:0] rvfi_``CSR_NAME``_csr_wdata;\ + bit [63:0] rvfi_``CSR_NAME``_csr_rmask;\ + bit [63:0] rvfi_``CSR_NAME``_csr_wmask;\ + wire [63:0] rvfi_``CSR_NAME``_csr_wmask_q; \ + wire [63:0] rvfi_``CSR_NAME``_csr_rmask_q; \ + assign rvfi_csr_if.rvfi_named_csr_rdata[CSR_ADDR] = (!rvfi_csr_bypass) ? rvfi_``CSR_NAME``_csr_rdata : ``CSR_RDATA``; \ + assign rvfi_csr_if.rvfi_named_csr_wdata[CSR_ADDR] = (!rvfi_csr_bypass) ? rvfi_``CSR_NAME``_csr_wdata : ``CSR_WDATA``; \ + assign rvfi_csr_if.rvfi_named_csr_rmask[CSR_ADDR] = (!rvfi_csr_bypass) ? rvfi_``CSR_NAME``_csr_rmask : rvfi_``CSR_NAME``_csr_rmask_q; \ + assign rvfi_csr_if.rvfi_named_csr_wmask[CSR_ADDR] = (!rvfi_csr_bypass) ? rvfi_``CSR_NAME``_csr_wmask : rvfi_``CSR_NAME``_csr_wmask_q; \ + assign rvfi_``CSR_NAME``_csr_rmask_q = ((~csr_wr & csr_op_en_i & ~illegal_csr_insn_o & (csr_addr_i == CSR_ADDR)) CSR_RMASK) ? -1 : 0; \ + assign rvfi_``CSR_NAME``_csr_wmask_q = ((csr_wr & csr_op_en_i & ~illegal_csr_insn_o & (csr_addr_i == CSR_ADDR)) CSR_WMASK) ? -1 : 0; \ + always @(posedge clknrst_if.clk) begin \ + rvfi_``CSR_NAME``_csr_rdata = ``CSR_RDATA``; \ + rvfi_``CSR_NAME``_csr_wdata = ``CSR_WDATA``; \ + rvfi_``CSR_NAME``_csr_rmask = (rvfi_``CSR_NAME``_csr_rmask_q); \ + rvfi_``CSR_NAME``_csr_wmask = (rvfi_``CSR_NAME``_csr_wmask_q); \ + end - assign csr_shadow_err_o = mstatus_err | mtvec_err | pmp_csr_err | cpuctrl_err; + `RVFI_CONNECT( CSR_MSTATUS, mstatus , mstatus_extended_read , mstatus_extended_write , , || mstatus_en) + `RVFI_CONNECT( CSR_MIE, mie , mie_q , mie_d , , || mie_en ) + `RVFI_CONNECT( CSR_MIP, mip , mip , csr_wdata_i , , ) + `RVFI_CONNECT( CSR_MISA, misa , MISA_VALUE , csr_wdata_i , , ) + `RVFI_CONNECT( CSR_MTVEC, mtvec , mtvec_q , mtvec_d , , || mtvec_en ) + `RVFI_CONNECT( CSR_MEPC, mepc , mepc_q , mepc_d , , || mepc_en ) + `RVFI_CONNECT( CSR_MCAUSE, mcause , mcause_q , mcause_d , , || mcause_en ) + `RVFI_CONNECT( CSR_MTVAL, mtval , mtval_q , mtval_d , , || mtval_en ) + `RVFI_CONNECT( CSR_MSTATUSH, mstatush , 'h0 , csr_wdata_i , , ) + `RVFI_CONNECT( CSR_DCSR, dcsr , dcsr_q , dcsr_d , , || dcsr_en) + `RVFI_CONNECT( CSR_DPC, dpc , depc_q , depc_d , , || depc_en) + `RVFI_CONNECT( CSR_DSCRATCH0, dscratch0 , dscratch0_q , csr_wdata_i , , || dscratch0_en) + `RVFI_CONNECT( CSR_DSCRATCH1, dscratch1 , dscratch1_q , csr_wdata_i , , || dscratch1_en) + +`endif //////////////// // Assertions // //////////////// - `ASSERT(IbexCsrOpEnRequiresAccess, csr_op_en_i |-> csr_access_i) + `ASSERT(CVE2CsrOpEnRequiresAccess, csr_op_en_i |-> csr_access_i) endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_csr.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_csr.sv similarity index 98% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_csr.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_csr.sv index 309a325f..b464bcce 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_csr.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_csr.sv @@ -8,7 +8,7 @@ `include "prim_assert.sv" -module ibex_csr #( +module cve2_csr #( parameter int unsigned Width = 32, parameter bit ShadowCopy = 1'b0, parameter bit [Width-1:0] ResetValue = '0 diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_decoder.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_decoder.sv similarity index 94% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_decoder.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_decoder.sv index 4b019593..5b9cbca1 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_decoder.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_decoder.sv @@ -13,11 +13,10 @@ `include "prim_assert.sv" -module ibex_decoder #( +module cve2_decoder #( parameter bit RV32E = 0, - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone, - parameter bit BranchTargetALU = 0 + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast, + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( input logic clk_i, input logic rst_ni, @@ -31,8 +30,6 @@ module ibex_decoder #( output logic ecall_insn_o, // syscall instr encountered output logic wfi_insn_o, // wait for interrupt instr encountered output logic jump_set_o, // jump taken set signal - input logic branch_taken_i, // registered branch decision - output logic icache_inval_o, // from IF-ID pipeline register input logic instr_first_cycle_i, // instruction read is in its first cycle @@ -43,10 +40,8 @@ module ibex_decoder #( input logic illegal_c_insn_i, // compressed instruction decode failed // immediates - output ibex_pkg::imm_a_sel_e imm_a_mux_sel_o, // immediate selection for operand a - output ibex_pkg::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b - output ibex_pkg::op_a_sel_e bt_a_mux_sel_o, // branch target selection operand a - output ibex_pkg::imm_b_sel_e bt_b_mux_sel_o, // branch target selection operand b + output cve2_pkg::imm_a_sel_e imm_a_mux_sel_o, // immediate selection for operand a + output cve2_pkg::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b output logic [31:0] imm_i_type_o, output logic [31:0] imm_s_type_o, output logic [31:0] imm_b_type_o, @@ -55,7 +50,7 @@ module ibex_decoder #( output logic [31:0] zimm_rs1_type_o, // register file - output ibex_pkg::rf_wd_sel_e rf_wdata_sel_o, // RF write data selection + output cve2_pkg::rf_wd_sel_e rf_wdata_sel_o, // RF write data selection output logic rf_we_o, // write enable for regfile output logic [4:0] rf_raddr_a_o, output logic [4:0] rf_raddr_b_o, @@ -64,10 +59,10 @@ module ibex_decoder #( output logic rf_ren_b_o, // Instruction reads from RF addr B // ALU - output ibex_pkg::alu_op_e alu_operator_o, // ALU operation selection - output ibex_pkg::op_a_sel_e alu_op_a_mux_sel_o, // operand a selection: reg value, PC, + output cve2_pkg::alu_op_e alu_operator_o, // ALU operation selection + output cve2_pkg::op_a_sel_e alu_op_a_mux_sel_o, // operand a selection: reg value, PC, // immediate or zero - output ibex_pkg::op_b_sel_e alu_op_b_mux_sel_o, // operand b selection: reg value or + output cve2_pkg::op_b_sel_e alu_op_b_mux_sel_o, // operand b selection: reg value or // immediate output logic alu_multicycle_o, // ternary bitmanip instruction @@ -77,12 +72,12 @@ module ibex_decoder #( output logic mult_sel_o, // as above but static, for data muxes output logic div_sel_o, // as above but static, for data muxes - output ibex_pkg::md_op_e multdiv_operator_o, + output cve2_pkg::md_op_e multdiv_operator_o, output logic [1:0] multdiv_signed_mode_o, // CSRs output logic csr_access_o, // access to CSR - output ibex_pkg::csr_op_e csr_op_o, // operation to perform on CSR + output cve2_pkg::csr_op_e csr_op_o, // operation to perform on CSR // LSU output logic data_req_o, // start transaction to data memory @@ -97,7 +92,7 @@ module ibex_decoder #( output logic branch_in_dec_o ); - import ibex_pkg::*; + import cve2_pkg::*; logic illegal_insn; logic illegal_reg_rv32e; @@ -206,7 +201,6 @@ module ibex_decoder #( jump_in_dec_o = 1'b0; jump_set_o = 1'b0; branch_in_dec_o = 1'b0; - icache_inval_o = 1'b0; multdiv_operator_o = MD_OP_MULL; multdiv_signed_mode_o = 2'b00; @@ -244,8 +238,8 @@ module ibex_decoder #( jump_in_dec_o = 1'b1; if (instr_first_cycle_i) begin - // Calculate jump target (and store PC + 4 if BranchTargetALU is configured) - rf_we = BranchTargetALU; + // Calculate jump target (and store PC) + rf_we = 1'b0; jump_set_o = 1'b1; end else begin // Calculate and store PC+4 @@ -257,8 +251,8 @@ module ibex_decoder #( jump_in_dec_o = 1'b1; if (instr_first_cycle_i) begin - // Calculate jump target (and store PC + 4 if BranchTargetALU is configured) - rf_we = BranchTargetALU; + // Calculate jump target (and store PC) + rf_we = 1'b0; jump_set_o = 1'b1; end else begin // Calculate and store PC+4 @@ -572,14 +566,12 @@ module ibex_decoder #( // FENCE.I is implemented as a jump to the next PC, this gives the required flushing // behaviour (iside prefetch buffer flushed and response to any outstanding iside // requests will be ignored). - // If present, the ICache will also be flushed. jump_in_dec_o = 1'b1; rf_we = 1'b0; if (instr_first_cycle_i) begin jump_set_o = 1'b1; - icache_inval_o = 1'b1; end end default: begin @@ -676,10 +668,6 @@ module ibex_decoder #( imm_a_mux_sel_o = IMM_A_ZERO; imm_b_mux_sel_o = IMM_B_I; - bt_a_mux_sel_o = OP_A_CURRPC; - bt_b_mux_sel_o = IMM_B_I; - - opcode_alu = opcode_e'(instr_alu[6:0]); use_rs3_d = 1'b0; @@ -694,13 +682,8 @@ module ibex_decoder #( /////////// OPCODE_JAL: begin // Jump and Link - if (BranchTargetALU) begin - bt_a_mux_sel_o = OP_A_CURRPC; - bt_b_mux_sel_o = IMM_B_J; - end - // Jumps take two cycles without the BTALU - if (instr_first_cycle_i && !BranchTargetALU) begin + if (instr_first_cycle_i) begin // Calculate jump target alu_op_a_mux_sel_o = OP_A_CURRPC; alu_op_b_mux_sel_o = OP_B_IMM; @@ -716,13 +699,8 @@ module ibex_decoder #( end OPCODE_JALR: begin // Jump and Link Register - if (BranchTargetALU) begin - bt_a_mux_sel_o = OP_A_REG_A; - bt_b_mux_sel_o = IMM_B_I; - end - // Jumps take two cycles without the BTALU - if (instr_first_cycle_i && !BranchTargetALU) begin + if (instr_first_cycle_i) begin // Calculate jump target alu_op_a_mux_sel_o = OP_A_REG_A; alu_op_b_mux_sel_o = OP_B_IMM; @@ -749,24 +727,18 @@ module ibex_decoder #( default: ; endcase - if (BranchTargetALU) begin - bt_a_mux_sel_o = OP_A_CURRPC; - // Not-taken branch will jump to next instruction (used in secure mode) - bt_b_mux_sel_o = branch_taken_i ? IMM_B_B : IMM_B_INCR_PC; - end - // Without branch target ALU, a branch is a two-stage operation using the Main ALU in both // stages if (instr_first_cycle_i) begin // First evaluate the branch condition alu_op_a_mux_sel_o = OP_A_REG_A; alu_op_b_mux_sel_o = OP_B_REG_B; - end else if (!BranchTargetALU) begin + end else begin // Then calculate jump target alu_op_a_mux_sel_o = OP_A_CURRPC; alu_op_b_mux_sel_o = OP_B_IMM; // Not-taken branch will jump to next instruction (used in secure mode) - imm_b_mux_sel_o = branch_taken_i ? IMM_B_B : IMM_B_INCR_PC; + imm_b_mux_sel_o = IMM_B_B; alu_operator_o = ALU_ADD; end end @@ -1147,15 +1119,10 @@ module ibex_decoder #( end 3'b001: begin // FENCE.I will flush the IF stage, prefetch buffer and ICache if present. - if (BranchTargetALU) begin - bt_a_mux_sel_o = OP_A_CURRPC; - bt_b_mux_sel_o = IMM_B_INCR_PC; - end else begin alu_op_a_mux_sel_o = OP_A_CURRPC; alu_op_b_mux_sel_o = OP_B_IMM; imm_b_mux_sel_o = IMM_B_INCR_PC; alu_operator_o = ALU_ADD; - end end default: ; endcase diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_ex_block.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_ex_block.sv similarity index 80% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_ex_block.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_ex_block.sv index ee900164..98713a3d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_ex_block.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_ex_block.sv @@ -8,27 +8,21 @@ * * Execution block: Hosts ALU and MUL/DIV unit */ -module ibex_ex_block #( - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone, - parameter bit BranchTargetALU = 0 +module cve2_ex_block #( + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast, + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( input logic clk_i, input logic rst_ni, // ALU - input ibex_pkg::alu_op_e alu_operator_i, + input cve2_pkg::alu_op_e alu_operator_i, input logic [31:0] alu_operand_a_i, input logic [31:0] alu_operand_b_i, input logic alu_instr_first_cycle_i, - // Branch Target ALU - // All of these signals are unusued when BranchTargetALU == 0 - input logic [31:0] bt_a_operand_i, - input logic [31:0] bt_b_operand_i, - // Multiplier/Divider - input ibex_pkg::md_op_e multdiv_operator_i, + input cve2_pkg::md_op_e multdiv_operator_i, input logic mult_en_i, // dynamic enable signal, for FSM control input logic div_en_i, // dynamic enable signal, for FSM control input logic mult_sel_i, // static decoder output, for data muxes @@ -36,8 +30,6 @@ module ibex_ex_block #( input logic [1:0] multdiv_signed_mode_i, input logic [31:0] multdiv_operand_a_i, input logic [31:0] multdiv_operand_b_i, - input logic multdiv_ready_id_i, - input logic data_ind_timing_i, // intermediate val reg output logic [1:0] imd_val_we_o, @@ -53,7 +45,7 @@ module ibex_ex_block #( output logic ex_valid_o // EX has valid output ); - import ibex_pkg::*; + import cve2_pkg::*; logic [31:0] alu_result, multdiv_result; @@ -91,29 +83,16 @@ module ibex_ex_block #( // branch handling assign branch_decision_o = alu_cmp_result; - if (BranchTargetALU) begin : g_branch_target_alu - logic [32:0] bt_alu_result; - logic unused_bt_carry; - - assign bt_alu_result = bt_a_operand_i + bt_b_operand_i; - - assign unused_bt_carry = bt_alu_result[32]; - assign branch_target_o = bt_alu_result[31:0]; - end else begin : g_no_branch_target_alu - // Unused bt_operand signals cause lint errors, this avoids them - logic [31:0] unused_bt_a_operand, unused_bt_b_operand; + // Unused bt_operand signals cause lint errors, this avoids them + //logic [31:0] unused_bt_a_operand, unused_bt_b_operand; - assign unused_bt_a_operand = bt_a_operand_i; - assign unused_bt_b_operand = bt_b_operand_i; - - assign branch_target_o = alu_adder_result_ex_o; - end + assign branch_target_o = alu_adder_result_ex_o; ///////// // ALU // ///////// - ibex_alu #( + cve2_alu #( .RV32B(RV32B) ) alu_i ( .operator_i (alu_operator_i), @@ -138,7 +117,7 @@ module ibex_ex_block #( //////////////// if (RV32M == RV32MSlow) begin : gen_multdiv_slow - ibex_multdiv_slow multdiv_i ( + cve2_multdiv_slow multdiv_i ( .clk_i (clk_i), .rst_ni (rst_ni), .mult_en_i (mult_en_i), @@ -152,18 +131,17 @@ module ibex_ex_block #( .alu_adder_ext_i (alu_adder_result_ext), .alu_adder_i (alu_adder_result_ex_o), .equal_to_zero_i (alu_is_equal_result), - .data_ind_timing_i (data_ind_timing_i), .valid_o (multdiv_valid), .alu_operand_a_o (multdiv_alu_operand_a), .alu_operand_b_o (multdiv_alu_operand_b), .imd_val_q_i (imd_val_q_i), .imd_val_d_o (multdiv_imd_val_d), .imd_val_we_o (multdiv_imd_val_we), - .multdiv_ready_id_i(multdiv_ready_id_i), + .multdiv_ready_id_i(1'b1), .multdiv_result_o (multdiv_result) ); end else if (RV32M == RV32MFast || RV32M == RV32MSingleCycle) begin : gen_multdiv_fast - ibex_multdiv_fast #( + cve2_multdiv_fast #( .RV32M(RV32M) ) multdiv_i ( .clk_i (clk_i), @@ -181,11 +159,9 @@ module ibex_ex_block #( .alu_adder_ext_i (alu_adder_result_ext), .alu_adder_i (alu_adder_result_ex_o), .equal_to_zero_i (alu_is_equal_result), - .data_ind_timing_i (data_ind_timing_i), .imd_val_q_i (imd_val_q_i), .imd_val_d_o (multdiv_imd_val_d), .imd_val_we_o (multdiv_imd_val_we), - .multdiv_ready_id_i(multdiv_ready_id_i), .valid_o (multdiv_valid), .multdiv_result_o (multdiv_result) ); diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_fetch_fifo.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_fetch_fifo.sv similarity index 92% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_fetch_fifo.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_fetch_fifo.sv index 61179ed0..60933a03 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_fetch_fifo.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_fetch_fifo.sv @@ -12,9 +12,8 @@ `include "prim_assert.sv" -module ibex_fetch_fifo #( - parameter int unsigned NUM_REQS = 2, - parameter bit ResetAll = 1'b0 +module cve2_fetch_fifo #( + parameter int unsigned NUM_REQS = 2 ) ( input logic clk_i, input logic rst_ni, @@ -149,19 +148,11 @@ module ibex_fetch_fifo #( assign instr_addr_d = clear_i ? in_addr_i[31:1] : instr_addr_next; - if (ResetAll) begin : g_instr_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_addr_q <= '0; - end else if (instr_addr_en) begin - instr_addr_q <= instr_addr_d; - end - end - end else begin : g_instr_addr_nr - always_ff @(posedge clk_i) begin - if (instr_addr_en) begin - instr_addr_q <= instr_addr_d; - end + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + instr_addr_q <= '0; + end else if (instr_addr_en) begin + instr_addr_q <= instr_addr_d; end end @@ -234,7 +225,6 @@ module ibex_fetch_fifo #( end for (genvar i = 0; i < DEPTH; i++) begin : g_fifo_regs - if (ResetAll) begin : g_rdata_ra always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin rdata_q[i] <= '0; @@ -244,14 +234,6 @@ module ibex_fetch_fifo #( err_q[i] <= err_d[i]; end end - end else begin : g_rdata_nr - always_ff @(posedge clk_i) begin - if (entry_en[i]) begin - rdata_q[i] <= rdata_d[i]; - err_q[i] <= err_d[i]; - end - end - end end //////////////// diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_id_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv similarity index 60% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_id_stage.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv index 1644d072..e7ebf52c 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_id_stage.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_id_stage.sv @@ -15,20 +15,17 @@ */ `include "prim_assert.sv" -//`include "dv_fcov_macros.svh" +`include "dv_fcov_macros.svh" -module ibex_id_stage #( +module cve2_id_stage #( parameter bit RV32E = 0, - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast, - parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone, - parameter bit DataIndTiming = 1'b0, - parameter bit BranchTargetALU = 0, - parameter bit WritebackStage = 0, - parameter bit BranchPredictor = 0 + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast, + parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone ) ( input logic clk_i, input logic rst_ni, + input logic fetch_enable_i, output logic ctrl_busy_o, output logic illegal_insn_o, @@ -38,23 +35,19 @@ module ibex_id_stage #( input logic [31:0] instr_rdata_alu_i, // from IF-ID pipeline registers input logic [15:0] instr_rdata_c_i, // from IF-ID pipeline registers input logic instr_is_compressed_i, - input logic instr_bp_taken_i, output logic instr_req_o, output logic instr_first_cycle_id_o, output logic instr_valid_clear_o, // kill instr in IF-ID reg output logic id_in_ready_o, // ID stage is ready for next instr - output logic icache_inval_o, // Jumps and branches input logic branch_decision_i, // IF and ID stage signals output logic pc_set_o, - output ibex_pkg::pc_sel_e pc_mux_o, - output logic nt_branch_mispredict_o, - output logic [31:0] nt_branch_addr_o, - output ibex_pkg::exc_pc_sel_e exc_pc_mux_o, - output ibex_pkg::exc_cause_e exc_cause_o, + output cve2_pkg::pc_sel_e pc_mux_o, + output cve2_pkg::exc_pc_sel_e exc_pc_mux_o, + output cve2_pkg::exc_cause_e exc_cause_o, input logic illegal_c_insn_i, input logic instr_fetch_err_i, @@ -66,7 +59,7 @@ module ibex_id_stage #( input logic ex_valid_i, // EX stage has valid output input logic lsu_resp_valid_i, // LSU has valid output, or is done // ALU - output ibex_pkg::alu_op_e alu_operator_ex_o, + output cve2_pkg::alu_op_e alu_operator_ex_o, output logic [31:0] alu_operand_a_ex_o, output logic [31:0] alu_operand_b_ex_o, @@ -75,36 +68,29 @@ module ibex_id_stage #( input logic [33:0] imd_val_d_ex_i[2], output logic [33:0] imd_val_q_ex_o[2], - // Branch target ALU - output logic [31:0] bt_a_operand_o, - output logic [31:0] bt_b_operand_o, - // MUL, DIV output logic mult_en_ex_o, output logic div_en_ex_o, output logic mult_sel_ex_o, output logic div_sel_ex_o, - output ibex_pkg::md_op_e multdiv_operator_ex_o, + output cve2_pkg::md_op_e multdiv_operator_ex_o, output logic [1:0] multdiv_signed_mode_ex_o, output logic [31:0] multdiv_operand_a_ex_o, output logic [31:0] multdiv_operand_b_ex_o, - output logic multdiv_ready_id_o, // CSR output logic csr_access_o, - output ibex_pkg::csr_op_e csr_op_o, + output cve2_pkg::csr_op_e csr_op_o, output logic csr_op_en_o, output logic csr_save_if_o, output logic csr_save_id_o, - output logic csr_save_wb_o, output logic csr_restore_mret_id_o, output logic csr_restore_dret_id_o, output logic csr_save_cause_o, output logic [31:0] csr_mtval_o, - input ibex_pkg::priv_lvl_e priv_mode_i, + input cve2_pkg::priv_lvl_e priv_mode_i, input logic csr_mstatus_tw_i, input logic illegal_csr_insn_i, - input logic data_ind_timing_i, // Interface to load store unit output logic lsu_req_o, @@ -113,18 +99,13 @@ module ibex_id_stage #( output logic lsu_sign_ext_o, output logic [31:0] lsu_wdata_o, - input logic lsu_req_done_i, // Data req to LSU is complete and - // instruction can move to writeback - // (only relevant where writeback stage is - // present) - input logic lsu_addr_incr_req_i, input logic [31:0] lsu_addr_last_i, // Interrupt signals input logic csr_mstatus_mie_i, input logic irq_pending_i, - input ibex_pkg::irqs_t irqs_i, + input cve2_pkg::irqs_t irqs_i, input logic irq_nm_i, output logic nmi_mode_o, @@ -133,7 +114,7 @@ module ibex_id_stage #( // Debug Signal output logic debug_mode_o, - output ibex_pkg::dbg_cause_e debug_cause_o, + output cve2_pkg::dbg_cause_e debug_cause_o, output logic debug_csr_save_o, input logic debug_req_i, input logic debug_single_step_i, @@ -141,9 +122,6 @@ module ibex_id_stage #( input logic debug_ebreaku_i, input logic trigger_match_i, - // Wakeup Signal - output logic wake_from_sleep_o, - // Write back signal input logic [31:0] result_ex_i, input logic [31:0] csr_rdata_i, @@ -160,20 +138,9 @@ module ibex_id_stage #( output logic [4:0] rf_waddr_id_o, output logic [31:0] rf_wdata_id_o, output logic rf_we_id_o, - output logic rf_rd_a_wb_match_o, - output logic rf_rd_b_wb_match_o, - - // Register write information from writeback (for resolving data hazards) - input logic [4:0] rf_waddr_wb_i, - input logic [31:0] rf_wdata_fwd_wb_i, - input logic rf_write_wb_i, output logic en_wb_o, - output ibex_pkg::wb_instr_type_e instr_type_wb_o, output logic instr_perf_count_id_o, - input logic ready_wb_i, - input logic outstanding_load_wb_i, - input logic outstanding_store_wb_i, // Performance Counters output logic perf_jump_o, // executing a jump instr @@ -181,12 +148,12 @@ module ibex_id_stage #( output logic perf_tbranch_o, // executing a taken branch instr output logic perf_dside_wait_o, // instruction in ID/EX is awaiting memory // access to finish before proceeding - output logic perf_mul_wait_o, + output logic perf_wfi_wait_o, output logic perf_div_wait_o, output logic instr_id_done_o ); - import ibex_pkg::*; + import cve2_pkg::*; // Decoder/Controller, ID stage internal signals logic illegal_insn_dec; @@ -196,14 +163,9 @@ module ibex_id_stage #( logic ecall_insn_dec; logic wfi_insn_dec; - logic wb_exception; - logic id_exception; - logic branch_in_dec; logic branch_set, branch_set_raw, branch_set_raw_d; logic branch_jump_set_done_q, branch_jump_set_done_d; - logic branch_not_set; - logic branch_taken; logic jump_in_dec; logic jump_set_dec; logic jump_set, jump_set_raw; @@ -213,13 +175,11 @@ module ibex_id_stage #( logic instr_executing; logic instr_done; logic controller_run; - logic stall_ld_hz; logic stall_mem; logic stall_multdiv; logic stall_branch; logic stall_jump; logic stall_id; - logic stall_wb; logic flush_id; logic multicycle_done; @@ -260,9 +220,6 @@ module ibex_id_stage #( logic [33:0] imd_val_q[2]; - op_a_sel_e bt_a_mux_sel; - imm_b_sel_e bt_b_mux_sel; - imm_a_sel_e imm_a_mux_sel; imm_b_sel_e imm_b_mux_sel, imm_b_mux_sel_dec; @@ -313,75 +270,30 @@ module ibex_id_stage #( endcase end - if (BranchTargetALU) begin : g_btalu_muxes - // Branch target ALU operand A mux - always_comb begin : bt_operand_a_mux - unique case (bt_a_mux_sel) - OP_A_REG_A: bt_a_operand_o = rf_rdata_a_fwd; - OP_A_CURRPC: bt_a_operand_o = pc_id_i; - default: bt_a_operand_o = pc_id_i; - endcase - end - - // Branch target ALU operand B mux - always_comb begin : bt_immediate_b_mux - unique case (bt_b_mux_sel) - IMM_B_I: bt_b_operand_o = imm_i_type; - IMM_B_B: bt_b_operand_o = imm_b_type; - IMM_B_J: bt_b_operand_o = imm_j_type; - IMM_B_INCR_PC: bt_b_operand_o = instr_is_compressed_i ? 32'h2 : 32'h4; - default: bt_b_operand_o = instr_is_compressed_i ? 32'h2 : 32'h4; - endcase - end - - // Reduced main ALU immediate MUX for Operand B - always_comb begin : immediate_b_mux - unique case (imm_b_mux_sel) - IMM_B_I: imm_b = imm_i_type; - IMM_B_S: imm_b = imm_s_type; - IMM_B_U: imm_b = imm_u_type; - IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4; - IMM_B_INCR_ADDR: imm_b = 32'h4; - default: imm_b = 32'h4; - endcase - end - `ASSERT(IbexImmBMuxSelValid, instr_valid_i |-> imm_b_mux_sel inside { - IMM_B_I, - IMM_B_S, - IMM_B_U, - IMM_B_INCR_PC, - IMM_B_INCR_ADDR}) - end else begin : g_nobtalu - op_a_sel_e unused_a_mux_sel; - imm_b_sel_e unused_b_mux_sel; - - assign unused_a_mux_sel = bt_a_mux_sel; - assign unused_b_mux_sel = bt_b_mux_sel; - assign bt_a_operand_o = '0; - assign bt_b_operand_o = '0; - - // Full main ALU immediate MUX for Operand B - always_comb begin : immediate_b_mux - unique case (imm_b_mux_sel) - IMM_B_I: imm_b = imm_i_type; - IMM_B_S: imm_b = imm_s_type; - IMM_B_B: imm_b = imm_b_type; - IMM_B_U: imm_b = imm_u_type; - IMM_B_J: imm_b = imm_j_type; - IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4; - IMM_B_INCR_ADDR: imm_b = 32'h4; - default: imm_b = 32'h4; - endcase - end - `ASSERT(IbexImmBMuxSelValid, instr_valid_i |-> imm_b_mux_sel inside { - IMM_B_I, - IMM_B_S, - IMM_B_B, - IMM_B_U, - IMM_B_J, - IMM_B_INCR_PC, - IMM_B_INCR_ADDR}) + op_a_sel_e unused_a_mux_sel; + imm_b_sel_e unused_b_mux_sel; + + // Full main ALU immediate MUX for Operand B + always_comb begin : immediate_b_mux + unique case (imm_b_mux_sel) + IMM_B_I: imm_b = imm_i_type; + IMM_B_S: imm_b = imm_s_type; + IMM_B_B: imm_b = imm_b_type; + IMM_B_U: imm_b = imm_u_type; + IMM_B_J: imm_b = imm_j_type; + IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4; + IMM_B_INCR_ADDR: imm_b = 32'h4; + default: imm_b = 32'h4; + endcase end + `ASSERT(IbexImmBMuxSelValid, instr_valid_i |-> imm_b_mux_sel inside { + IMM_B_I, + IMM_B_S, + IMM_B_B, + IMM_B_U, + IMM_B_J, + IMM_B_INCR_PC, + IMM_B_INCR_ADDR}) // ALU MUX for Operand B assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : rf_rdata_b_fwd; @@ -422,11 +334,10 @@ module ibex_id_stage #( // Decoder // ///////////// - ibex_decoder #( + cve2_decoder #( .RV32E (RV32E), .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU(BranchTargetALU) + .RV32B (RV32B) ) decoder_i ( .clk_i (clk_i), .rst_ni(rst_ni), @@ -439,8 +350,6 @@ module ibex_id_stage #( .ecall_insn_o (ecall_insn_dec), .wfi_insn_o (wfi_insn_dec), .jump_set_o (jump_set_dec), - .branch_taken_i(branch_taken), - .icache_inval_o(icache_inval_o), // from IF-ID pipeline register .instr_first_cycle_i(instr_first_cycle), @@ -451,8 +360,6 @@ module ibex_id_stage #( // immediates .imm_a_mux_sel_o(imm_a_mux_sel), .imm_b_mux_sel_o(imm_b_mux_sel_dec), - .bt_a_mux_sel_o (bt_a_mux_sel), - .bt_b_mux_sel_o (bt_b_mux_sel), .imm_i_type_o (imm_i_type), .imm_s_type_o (imm_s_type), @@ -501,7 +408,7 @@ module ibex_id_stage #( ); ///////////////////////////////// - // CSR-related pipline flushes // + // CSR-related pipeline flushes // ///////////////////////////////// always_comb begin : csr_pipeline_flushes csr_pipe_flush = 1'b0; @@ -510,10 +417,15 @@ module ibex_id_stage #( // - When enabling interrupts, pending IRQs become visible to the controller only during // the next cycle. If during that cycle the core disables interrupts again, it does not // see any pending IRQs and consequently does not start to handle interrupts. + // - When modifying any PMP CSR, PMP check of the next instruction might get invalidated. + // Hence, a pipeline flush is needed to instantiate another PMP check with the updated CSRs. // - When modifying debug CSRs - TODO: Check if this is really needed if (csr_op_en_o == 1'b1 && (csr_op_o == CSR_OP_WRITE || csr_op_o == CSR_OP_SET)) begin - if (csr_num_e'(instr_rdata_i[31:20]) == CSR_MSTATUS || - csr_num_e'(instr_rdata_i[31:20]) == CSR_MIE) begin + if (csr_num_e'(instr_rdata_i[31:20]) == CSR_MSTATUS || + csr_num_e'(instr_rdata_i[31:20]) == CSR_MIE || + csr_num_e'(instr_rdata_i[31:20]) == CSR_MSECCFG || + // To catch all PMPCFG/PMPADDR registers, get the shared top most 7 bits. + instr_rdata_i[31:25] == 7'h1D) begin csr_pipe_flush = 1'b1; end end else if (csr_op_en_o == 1'b1 && csr_op_o != CSR_OP_READ) begin @@ -532,13 +444,12 @@ module ibex_id_stage #( assign illegal_insn_o = instr_valid_i & (illegal_insn_dec | illegal_csr_insn_i); - ibex_controller #( - .WritebackStage (WritebackStage), - .BranchPredictor(BranchPredictor) + cve2_controller #( ) controller_i ( .clk_i (clk_i), .rst_ni(rst_ni), + .fetch_enable_i(fetch_enable_i), .ctrl_busy_o(ctrl_busy_o), // decoder related signals @@ -555,7 +466,6 @@ module ibex_id_stage #( .instr_i (instr_rdata_i), .instr_compressed_i (instr_rdata_c_i), .instr_is_compressed_i (instr_is_compressed_i), - .instr_bp_taken_i (instr_bp_taken_i), .instr_fetch_err_i (instr_fetch_err_i), .instr_fetch_err_plus2_i(instr_fetch_err_plus2_i), .pc_id_i (pc_id_i), @@ -569,7 +479,6 @@ module ibex_id_stage #( .instr_req_o (instr_req_o), .pc_set_o (pc_set_o), .pc_mux_o (pc_mux_o), - .nt_branch_mispredict_o(nt_branch_mispredict_o), .exc_pc_mux_o (exc_pc_mux_o), .exc_cause_o (exc_cause_o), @@ -577,12 +486,8 @@ module ibex_id_stage #( .lsu_addr_last_i(lsu_addr_last_i), .load_err_i (lsu_load_err_i), .store_err_i (lsu_store_err_i), - .wb_exception_o (wb_exception), - .id_exception_o (id_exception), - // jump/branch control .branch_set_i (branch_set), - .branch_not_set_i (branch_not_set), .jump_set_i (jump_set), // interrupt signals @@ -595,7 +500,6 @@ module ibex_id_stage #( // CSR Controller Signals .csr_save_if_o (csr_save_if_o), .csr_save_id_o (csr_save_id_o), - .csr_save_wb_o (csr_save_wb_o), .csr_restore_mret_id_o(csr_restore_mret_id_o), .csr_restore_dret_id_o(csr_restore_dret_id_o), .csr_save_cause_o (csr_save_cause_o), @@ -613,13 +517,8 @@ module ibex_id_stage #( .debug_ebreaku_i (debug_ebreaku_i), .trigger_match_i (trigger_match_i), - // Wakeup Signal - .wake_from_sleep_o(wake_from_sleep_o), - .stall_id_i(stall_id), - .stall_wb_i(stall_wb), .flush_id_o(flush_id), - .ready_wb_i(ready_wb_i), // Performance Counters .perf_jump_o (perf_jump_o), @@ -659,31 +558,24 @@ module ibex_id_stage #( // Branch set control // //////////////////////// - if (BranchTargetALU && !DataIndTiming) begin : g_branch_set_direct - // Branch set fed straight to controller with branch target ALU - // (condition pass/fail used same cycle as generated instruction request) - assign branch_set_raw = branch_set_raw_d; - end else begin : g_branch_set_flop - // SEC_CM: CORE.DATA_REG_SW.SCA - // Branch set flopped without branch target ALU, or in fixed time execution mode - // (condition pass/fail used next cycle where branch target is calculated) - logic branch_set_raw_q; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - branch_set_raw_q <= 1'b0; - end else begin - branch_set_raw_q <= branch_set_raw_d; - end + // SEC_CM: CORE.DATA_REG_SW.SCA + // Branch set flopped without branch target ALU, or in fixed time execution mode + // (condition pass/fail used next cycle where branch target is calculated) + logic branch_set_raw_q; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + branch_set_raw_q <= 1'b0; + end else begin + branch_set_raw_q <= branch_set_raw_d; end + end - // Branches always take two cycles in fixed time execution mode, with or without the branch - // target ALU (to avoid a path from the branch decision into the branch target ALU operand - // muxing). - assign branch_set_raw = (BranchTargetALU && !data_ind_timing_i) ? branch_set_raw_d : - branch_set_raw_q; + // Branches always take two cycles in fixed time execution mode, with or without the branch + // target ALU (to avoid a path from the branch decision into the branch target ALU operand + // muxing). + assign branch_set_raw = branch_set_raw_q; - end // Track whether the current instruction in ID/EX has done a branch or jump set. assign branch_jump_set_done_d = (branch_set_raw | jump_set_raw | branch_jump_set_done_q) & @@ -707,46 +599,6 @@ module ibex_id_stage #( assign jump_set = jump_set_raw & ~branch_jump_set_done_q; assign branch_set = branch_set_raw & ~branch_jump_set_done_q; - // Branch condition is calculated in the first cycle and flopped for use in the second cycle - // (only used in fixed time execution mode to determine branch destination). - if (DataIndTiming) begin : g_sec_branch_taken - // SEC_CM: CORE.DATA_REG_SW.SCA - logic branch_taken_q; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - branch_taken_q <= 1'b0; - end else begin - branch_taken_q <= branch_decision_i; - end - end - - assign branch_taken = ~data_ind_timing_i | branch_taken_q; - - end else begin : g_nosec_branch_taken - - // Signal unused without fixed time execution mode - only taken branches will trigger - // branch_set_raw - assign branch_taken = 1'b1; - - end - - // Holding branch_set/jump_set high for more than one cycle should not cause a functional issue. - // However it could generate needless prefetch buffer flushes and instruction fetches. The ID/EX - // designs ensures that this never happens for non-predicted branches. - `ASSERT(NeverDoubleBranch, branch_set & ~instr_bp_taken_i |=> ~branch_set) - `ASSERT(NeverDoubleJump, jump_set & ~instr_bp_taken_i |=> ~jump_set) - - ////////////////////////////// - // Branch not-taken address // - ////////////////////////////// - - if (BranchPredictor) begin : g_calc_nt_addr - assign nt_branch_addr_o = pc_id_i + (instr_is_compressed_i ? 32'd2 : 32'd4); - end else begin : g_n_calc_nt_addr - assign nt_branch_addr_o = 32'd0; - end - /////////////// // ID-EX FSM // /////////////// @@ -775,7 +627,6 @@ module ibex_id_stage #( stall_branch = 1'b0; stall_alu = 1'b0; branch_set_raw_d = 1'b0; - branch_not_set = 1'b0; jump_set_raw = 1'b0; perf_branch_o = 1'b0; @@ -784,13 +635,9 @@ module ibex_id_stage #( FIRST_CYCLE: begin unique case (1'b1) lsu_req_dec: begin - if (!WritebackStage) begin + begin // LSU operation id_fsm_d = MULTI_CYCLE; - end else begin - if(~lsu_req_done_i) begin - id_fsm_d = MULTI_CYCLE; - end end end multdiv_en_dec: begin @@ -808,22 +655,17 @@ module ibex_id_stage #( // All branches take two cycles in fixed time execution mode, regardless of branch // condition. // SEC_CM: CORE.DATA_REG_SW.SCA - id_fsm_d = (data_ind_timing_i || (!BranchTargetALU && branch_decision_i)) ? + id_fsm_d = (branch_decision_i) ? MULTI_CYCLE : FIRST_CYCLE; - stall_branch = (~BranchTargetALU & branch_decision_i) | data_ind_timing_i; - branch_set_raw_d = (branch_decision_i | data_ind_timing_i); - - if (BranchPredictor) begin - branch_not_set = ~branch_decision_i; - end + stall_branch = branch_decision_i; + branch_set_raw_d = branch_decision_i; perf_branch_o = 1'b1; end jump_in_dec: begin // uncond branch operation - // BTALU means jumps only need one cycle - id_fsm_d = BranchTargetALU ? FIRST_CYCLE : MULTI_CYCLE; - stall_jump = ~BranchTargetALU; + id_fsm_d = MULTI_CYCLE; + stall_jump = 1'b1; jump_set_raw = jump_set_dec; end alu_multicycle_dec: begin @@ -842,7 +684,7 @@ module ibex_id_stage #( rf_we_raw = rf_we_dec & ex_valid_i; end - if (multicycle_done & ready_wb_i) begin + if (multicycle_done) begin id_fsm_d = FIRST_CYCLE; end else begin stall_multdiv = multdiv_en_dec; @@ -858,22 +700,19 @@ module ibex_id_stage #( end end - // Note for the two-stage configuration ready_wb_i is always set - assign multdiv_ready_id_o = ready_wb_i; - `ASSERT(StallIDIfMulticycle, (id_fsm_q == FIRST_CYCLE) & (id_fsm_d == MULTI_CYCLE) |-> stall_id) // Stall ID/EX stage for reason that relates to instruction in ID/EX, update assertion below if // modifying this. - assign stall_id = stall_ld_hz | stall_mem | stall_multdiv | stall_jump | stall_branch | + assign stall_id = stall_mem | stall_multdiv | stall_jump | stall_branch | stall_alu; // Generally illegal instructions have no reason to stall, however they must still stall waiting // for outstanding memory requests so exceptions related to them take priority over the illegal // instruction exception. `ASSERT(IllegalInsnStallMustBeMemStall, illegal_insn_o & stall_id |-> stall_mem & - ~(stall_ld_hz | stall_multdiv | stall_jump | stall_branch | stall_alu)) + ~(stall_multdiv | stall_jump | stall_branch | stall_alu)) assign instr_done = ~stall_id & ~flush_id & instr_executing; @@ -884,119 +723,6 @@ module ibex_id_stage #( // Used by ALU to access RS3 if ternary instruction. assign instr_first_cycle_id_o = instr_first_cycle; - if (WritebackStage) begin : gen_stall_mem - // Register read address matches write address in WB - logic rf_rd_a_wb_match; - logic rf_rd_b_wb_match; - // Hazard between registers being read and written - logic rf_rd_a_hz; - logic rf_rd_b_hz; - - logic outstanding_memory_access; - - logic instr_kill; - - assign multicycle_done = lsu_req_dec ? ~stall_mem : ex_valid_i; - - // Is a memory access ongoing that isn't finishing this cycle - assign outstanding_memory_access = (outstanding_load_wb_i | outstanding_store_wb_i) & - ~lsu_resp_valid_i; - - // Can start a new memory access if any previous one has finished or is finishing - assign data_req_allowed = ~outstanding_memory_access; - - // Instruction won't execute because: - // - There is a pending exception in writeback - // The instruction in ID/EX will be flushed and the core will jump to an exception handler - // - The controller isn't running instructions - // This either happens in preparation for a flush and jump to an exception handler e.g. in - // response to an IRQ or debug request or whilst the core is sleeping or resetting/fetching - // first instruction in which case any valid instruction in ID/EX should be ignored. - // - There was an error on instruction fetch - assign instr_kill = instr_fetch_err_i | - wb_exception | - id_exception | - ~controller_run; - - // With writeback stage instructions must be prevented from executing if there is: - // - A load hazard - // - A pending memory access - // If it receives an error response this results in a precise exception from WB so ID/EX - // instruction must not execute until error response is known). - // - A load/store error - // This will cause a precise exception for the instruction in WB so ID/EX instruction must not - // execute - // - // instr_executing_spec is a speculative signal. It indicates an instruction can execute - // assuming there are no exceptions from writeback and any outstanding memory access won't - // receive an error. It is required so branch and jump requests don't factor in an incoming dmem - // error (that in turn would factor directly into imem requests leading to a feedthrough path). - // - // instr_executing is the full signal, it will only allow execution once any potential - // exceptions from writeback have been resolved. - assign instr_executing_spec = instr_valid_i & - ~instr_fetch_err_i & - controller_run & - ~stall_ld_hz; - - assign instr_executing = instr_valid_i & - ~instr_kill & - ~stall_ld_hz & - ~outstanding_memory_access; - - `ASSERT(IbexExecutingSpecIfExecuting, instr_executing |-> instr_executing_spec) - - `ASSERT(IbexStallIfValidInstrNotExecuting, - instr_valid_i & ~instr_kill & ~instr_executing |-> stall_id) - - `ASSERT(IbexCannotRetireWithPendingExceptions, - instr_done |-> ~(wb_exception | outstanding_memory_access)) - - // Stall for reasons related to memory: - // * There is an outstanding memory access that won't resolve this cycle (need to wait to allow - // precise exceptions) - // * There is a load/store request not being granted or which is unaligned and waiting to issue - // a second request (needs to stay in ID for the address calculation) - assign stall_mem = instr_valid_i & - (outstanding_memory_access | (lsu_req_dec & ~lsu_req_done_i)); - - // If we stall a load in ID for any reason, it must not make an LSU request - // (otherwide we might issue two requests for the same instruction) - `ASSERT(IbexStallMemNoRequest, - instr_valid_i & lsu_req_dec & ~instr_done |-> ~lsu_req_done_i) - - assign rf_rd_a_wb_match = (rf_waddr_wb_i == rf_raddr_a_o) & |rf_raddr_a_o; - assign rf_rd_b_wb_match = (rf_waddr_wb_i == rf_raddr_b_o) & |rf_raddr_b_o; - - assign rf_rd_a_wb_match_o = rf_rd_a_wb_match; - assign rf_rd_b_wb_match_o = rf_rd_b_wb_match; - - // If instruction is reading register that load will be writing stall in - // ID until load is complete. No need to stall when reading zero register. - assign rf_rd_a_hz = rf_rd_a_wb_match & rf_ren_a; - assign rf_rd_b_hz = rf_rd_b_wb_match & rf_ren_b; - - // If instruction is read register that writeback is writing forward writeback data to read - // data. Note this doesn't factor in load data as it arrives too late, such hazards are - // resolved via a stall (see above). - assign rf_rdata_a_fwd = rf_rd_a_wb_match & rf_write_wb_i ? rf_wdata_fwd_wb_i : rf_rdata_a_i; - assign rf_rdata_b_fwd = rf_rd_b_wb_match & rf_write_wb_i ? rf_wdata_fwd_wb_i : rf_rdata_b_i; - - assign stall_ld_hz = outstanding_load_wb_i & (rf_rd_a_hz | rf_rd_b_hz); - - assign instr_type_wb_o = ~lsu_req_dec ? WB_INSTR_OTHER : - lsu_we ? WB_INSTR_STORE : - WB_INSTR_LOAD; - - assign instr_id_done_o = en_wb_o & ready_wb_i; - - // Stall ID/EX as instruction in ID/EX cannot proceed to writeback yet - assign stall_wb = en_wb_o & ~ready_wb_i; - - assign perf_dside_wait_o = instr_valid_i & ~instr_kill & - (outstanding_memory_access | stall_ld_hz); - end else begin : gen_no_stall_mem - assign multicycle_done = lsu_req_dec ? lsu_resp_valid_i : ex_valid_i; assign data_req_allowed = instr_first_cycle; @@ -1005,9 +731,6 @@ module ibex_id_stage #( // Then stall until it is complete assign stall_mem = instr_valid_i & (lsu_req_dec & (~lsu_resp_valid_i | instr_first_cycle)); - // No load hazards without Writeback Stage - assign stall_ld_hz = 1'b0; - // Without writeback stage any valid instruction that hasn't seen an error will execute assign instr_executing_spec = instr_valid_i & ~instr_fetch_err_i & controller_run; assign instr_executing = instr_executing_spec; @@ -1020,60 +743,35 @@ module ibex_id_stage #( assign rf_rdata_a_fwd = rf_rdata_a_i; assign rf_rdata_b_fwd = rf_rdata_b_i; - assign rf_rd_a_wb_match_o = 1'b0; - assign rf_rd_b_wb_match_o = 1'b0; - // Unused Writeback stage only IO & wiring // Assign inputs and internal wiring to unused signals to satisfy lint checks // Tie-off outputs to constant values logic unused_data_req_done_ex; - logic [4:0] unused_rf_waddr_wb; - logic unused_rf_write_wb; - logic unused_outstanding_load_wb; - logic unused_outstanding_store_wb; - logic unused_wb_exception; - logic [31:0] unused_rf_wdata_fwd_wb; - logic unused_id_exception; - - assign unused_data_req_done_ex = lsu_req_done_i; - assign unused_rf_waddr_wb = rf_waddr_wb_i; - assign unused_rf_write_wb = rf_write_wb_i; - assign unused_outstanding_load_wb = outstanding_load_wb_i; - assign unused_outstanding_store_wb = outstanding_store_wb_i; - assign unused_wb_exception = wb_exception; - assign unused_rf_wdata_fwd_wb = rf_wdata_fwd_wb_i; - assign unused_id_exception = id_exception; - - assign instr_type_wb_o = WB_INSTR_OTHER; - assign stall_wb = 1'b0; assign perf_dside_wait_o = instr_executing & lsu_req_dec & ~lsu_resp_valid_i; assign instr_id_done_o = instr_done; - end // Signal which instructions to count as retired in minstret, all traps along with ebrk and // ecall instructions are not counted. assign instr_perf_count_id_o = ~ebrk_insn & ~ecall_insn_dec & ~illegal_insn_dec & + ~(dret_insn_dec & ~debug_mode_o) & ~illegal_csr_insn_i & ~instr_fetch_err_i; - // An instruction is ready to move to the writeback stage (or retire if there is no writeback - // stage) + // An instruction is ready to move to the writeback assign en_wb_o = instr_done; - assign perf_mul_wait_o = stall_multdiv & mult_en_dec; + assign perf_wfi_wait_o = wfi_insn_dec; assign perf_div_wait_o = stall_multdiv & div_en_dec; ////////// // FCOV // ////////// - //`DV_FCOV_SIGNAL_GEN_IF(logic, rf_rd_wb_hz, - // (gen_stall_mem.rf_rd_a_hz | gen_stall_mem.rf_rd_b_hz) & instr_valid_i, WritebackStage) - //`DV_FCOV_SIGNAL(logic, branch_taken, - // instr_executing & (id_fsm_q == FIRST_CYCLE) & branch_decision_i) - //`DV_FCOV_SIGNAL(logic, branch_not_taken, - // instr_executing & (id_fsm_q == FIRST_CYCLE) & ~branch_decision_i) + `DV_FCOV_SIGNAL(logic, branch_taken, + instr_executing & (id_fsm_q == FIRST_CYCLE) & branch_decision_i) + `DV_FCOV_SIGNAL(logic, branch_not_taken, + instr_executing & (id_fsm_q == FIRST_CYCLE) & ~branch_decision_i) //////////////// // Assertions // @@ -1086,16 +784,6 @@ module ibex_id_stage #( OP_A_FWD, OP_A_CURRPC, OP_A_IMM}) - `ASSERT_KNOWN_IF(IbexBTAluAOpMuxSelKnown, bt_a_mux_sel, instr_valid_i) - `ASSERT(IbexBTAluAOpMuxSelValid, instr_valid_i |-> bt_a_mux_sel inside { - OP_A_REG_A, - OP_A_CURRPC}) - `ASSERT_KNOWN_IF(IbexBTAluBOpMuxSelKnown, bt_b_mux_sel, instr_valid_i) - `ASSERT(IbexBTAluBOpMuxSelValid, instr_valid_i |-> bt_b_mux_sel inside { - IMM_B_I, - IMM_B_B, - IMM_B_J, - IMM_B_INCR_PC}) `ASSERT(IbexRegfileWdataSelValid, instr_valid_i |-> rf_wdata_sel inside { RF_WD_EX, RF_WD_CSR}) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv new file mode 100644 index 00000000..cbb05054 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_if_stage.sv @@ -0,0 +1,278 @@ +// Copyright lowRISC contributors. +// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +/** + * Instruction Fetch Stage + * + * Instruction fetch unit: Selection of the next PC, and buffering (sampling) of + * the read instruction. + */ + +`include "prim_assert.sv" + +module cve2_if_stage import cve2_pkg::*; #( + parameter int unsigned DmHaltAddr = 32'h1A110800, + parameter int unsigned DmExceptionAddr = 32'h1A110808 +) ( + input logic clk_i, + input logic rst_ni, + + input logic [31:0] boot_addr_i, // also used for mtvec + input logic req_i, // instruction request control + + // instruction cache interface + output logic instr_req_o, + output logic [31:0] instr_addr_o, + input logic instr_gnt_i, + input logic instr_rvalid_i, + input logic [31:0] instr_rdata_i, + input logic instr_err_i, + + // output of ID stage + output logic instr_valid_id_o, // instr in IF-ID is valid + output logic instr_new_id_o, // instr in IF-ID is new + output logic [31:0] instr_rdata_id_o, // instr for ID stage + output logic [31:0] instr_rdata_alu_id_o, // replicated instr for ID stage + // to reduce fan-out + output logic [15:0] instr_rdata_c_id_o, // compressed instr for ID stage + // (mtval), meaningful only if + // instr_is_compressed_id_o = 1'b1 + output logic instr_is_compressed_id_o, // compressed decoder thinks this + // is a compressed instr + output logic instr_fetch_err_o, // bus error on fetch + output logic instr_fetch_err_plus2_o, // bus error misaligned + output logic illegal_c_insn_id_o, // compressed decoder thinks this + // is an invalid instr + output logic [31:0] pc_if_o, + output logic [31:0] pc_id_o, + input logic pmp_err_if_i, + input logic pmp_err_if_plus2_i, + + // control signals + input logic instr_valid_clear_i, // clear instr valid bit in IF-ID + input logic pc_set_i, // set the PC to a new value + input pc_sel_e pc_mux_i, // selector for PC multiplexer + input exc_pc_sel_e exc_pc_mux_i, // selects ISR address + input exc_cause_e exc_cause, // selects ISR address for + // vectorized interrupt lines + // jump and branch target + input logic [31:0] branch_target_ex_i, // branch/jump target address + + // CSRs + input logic [31:0] csr_mepc_i, // PC to restore after handling + // the interrupt/exception + input logic [31:0] csr_depc_i, // PC to restore after handling + // the debug request + input logic [31:0] csr_mtvec_i, // base PC to jump to on exception + output logic csr_mtvec_init_o, // tell CS regfile to init mtvec + + // pipeline stall + input logic id_in_ready_i, // ID stage is ready for new instr + + // misc signals + output logic if_busy_o // IF stage is busy fetching instr +); + + logic instr_valid_id_d, instr_valid_id_q; + logic instr_new_id_d, instr_new_id_q; + + // prefetch buffer related signals + logic prefetch_busy; + logic branch_req; + logic [31:0] fetch_addr_n; + logic unused_fetch_addr_n0; + + logic fetch_valid; + logic fetch_ready; + logic [31:0] fetch_rdata; + logic [31:0] fetch_addr; + logic fetch_err; + logic fetch_err_plus2; + + logic [31:0] instr_decompressed; + logic illegal_c_insn; + logic instr_is_compressed; + + logic if_instr_pmp_err; + logic if_instr_err; + logic if_instr_err_plus2; + + logic [31:0] exc_pc; + + logic [6:0] irq_id; + logic unused_irq_bit; + + logic if_id_pipe_reg_we; // IF-ID pipeline reg write enable + + cve2_pkg::pc_sel_e pc_mux_internal; + + logic [7:0] unused_boot_addr; + logic [7:0] unused_csr_mtvec; + + assign unused_boot_addr = boot_addr_i[7:0]; + assign unused_csr_mtvec = csr_mtvec_i[7:0]; + + // extract interrupt ID from exception cause + assign irq_id = {exc_cause}; + assign unused_irq_bit = irq_id[6]; // MSB distinguishes interrupts from exceptions + + // exception PC selection mux + always_comb begin : exc_pc_mux + unique case (exc_pc_mux_i) + EXC_PC_EXC: exc_pc = { csr_mtvec_i[31:8], 8'h00 }; + EXC_PC_IRQ: exc_pc = { csr_mtvec_i[31:8], irq_id[5:0], 2'b00 }; + EXC_PC_DBD: exc_pc = DmHaltAddr; + EXC_PC_DBG_EXC: exc_pc = DmExceptionAddr; + default: exc_pc = { csr_mtvec_i[31:8], 8'h00 }; + endcase + end + + assign pc_mux_internal = + pc_mux_i; + + // fetch address selection mux + always_comb begin : fetch_addr_mux + unique case (pc_mux_internal) + PC_BOOT: fetch_addr_n = { boot_addr_i[31:8], 8'h00 }; + PC_JUMP: fetch_addr_n = branch_target_ex_i; + PC_EXC: fetch_addr_n = exc_pc; // set PC to exception handler + PC_ERET: fetch_addr_n = csr_mepc_i; // restore PC when returning from EXC + PC_DRET: fetch_addr_n = csr_depc_i; + default: fetch_addr_n = { boot_addr_i[31:8], 8'h00 }; + endcase + end + + // tell CS register file to initialize mtvec on boot + assign csr_mtvec_init_o = (pc_mux_i == PC_BOOT) & pc_set_i; + + // prefetch buffer, caches a fixed number of instructions + cve2_prefetch_buffer #( + ) prefetch_buffer_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .req_i ( req_i ), + + .branch_i ( branch_req ), + .addr_i ( {fetch_addr_n[31:1], 1'b0} ), + + .ready_i ( fetch_ready ), + .valid_o ( fetch_valid ), + .rdata_o ( fetch_rdata ), + .addr_o ( fetch_addr ), + .err_o ( fetch_err ), + .err_plus2_o ( fetch_err_plus2 ), + + .instr_req_o ( instr_req_o ), + .instr_addr_o ( instr_addr_o ), + .instr_gnt_i ( instr_gnt_i ), + .instr_rvalid_i ( instr_rvalid_i ), + .instr_rdata_i ( instr_rdata_i ), + .instr_err_i ( instr_err_i ), + + .busy_o ( prefetch_busy ) + ); + + assign unused_fetch_addr_n0 = fetch_addr_n[0]; + + assign branch_req = pc_set_i; + + assign pc_if_o = fetch_addr; + assign if_busy_o = prefetch_busy; + + // PMP errors + // An error can come from the instruction address, or the next instruction address for unaligned, + // uncompressed instructions. + assign if_instr_pmp_err = pmp_err_if_i | + (fetch_addr[2] & ~instr_is_compressed & pmp_err_if_plus2_i); + + // Combine bus errors and pmp errors + assign if_instr_err = fetch_err | if_instr_pmp_err; + + // Capture the second half of the address for errors on the second part of an instruction + assign if_instr_err_plus2 = ((fetch_addr[2] & ~instr_is_compressed & pmp_err_if_plus2_i) | + fetch_err_plus2) & ~pmp_err_if_i; + + // compressed instruction decoding, or more precisely compressed instruction + // expander + // + // since it does not matter where we decompress instructions, we do it here + // to ease timing closure + cve2_compressed_decoder compressed_decoder_i ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .valid_i (fetch_valid & ~fetch_err), + .instr_i (fetch_rdata), + .instr_o (instr_decompressed), + .is_compressed_o(instr_is_compressed), + .illegal_instr_o(illegal_c_insn) + ); + + // The ID stage becomes valid as soon as any instruction is registered in the ID stage flops. + // Note that the current instruction is squashed by the incoming pc_set_i signal. + // Valid is held until it is explicitly cleared (due to an instruction completing or an exception) + assign instr_valid_id_d = (fetch_valid & id_in_ready_i & ~pc_set_i) | + (instr_valid_id_q & ~instr_valid_clear_i); + assign instr_new_id_d = fetch_valid & id_in_ready_i; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + instr_valid_id_q <= 1'b0; + instr_new_id_q <= 1'b0; + end else begin + instr_valid_id_q <= instr_valid_id_d; + instr_new_id_q <= instr_new_id_d; + end + end + + assign instr_valid_id_o = instr_valid_id_q; + // Signal when a new instruction enters the ID stage (only used for RVFI signalling). + assign instr_new_id_o = instr_new_id_q; + + // IF-ID pipeline registers, frozen when the ID stage is stalled + assign if_id_pipe_reg_we = instr_new_id_d; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + instr_rdata_id_o <= '0; + instr_rdata_alu_id_o <= '0; + instr_fetch_err_o <= '0; + instr_fetch_err_plus2_o <= '0; + instr_rdata_c_id_o <= '0; + instr_is_compressed_id_o <= '0; + illegal_c_insn_id_o <= '0; + pc_id_o <= '0; + end else if (if_id_pipe_reg_we) begin + instr_rdata_id_o <= instr_decompressed; + // To reduce fan-out and help timing from the instr_rdata_id flops they are replicated. + instr_rdata_alu_id_o <= instr_decompressed; + instr_fetch_err_o <= if_instr_err; + instr_fetch_err_plus2_o <= if_instr_err_plus2; + instr_rdata_c_id_o <= fetch_rdata[15:0]; //if_instr_rdata[15:0]; + instr_is_compressed_id_o <= instr_is_compressed; + illegal_c_insn_id_o <= illegal_c_insn; + pc_id_o <= pc_if_o; + end + end + + assign fetch_ready = id_in_ready_i; + + //////////////// + // Assertions // + //////////////// + + // Selectors must be known/valid. + `ASSERT_KNOWN(IbexExcPcMuxKnown, exc_pc_mux_i) + + // Boot address must be aligned to 256 bytes. + `ASSERT(IbexBootAddrUnaligned, boot_addr_i[7:0] == 8'h00) + + // Address must not contain X when request is sent. + `ASSERT(IbexInstrAddrUnknown, instr_req_o |-> !$isunknown(instr_addr_o)) + + // Address must be word aligned when request is sent. + `ASSERT(IbexInstrAddrUnaligned, instr_req_o |-> (instr_addr_o[1:0] == 2'b00)) + +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_load_store_unit.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_load_store_unit.sv similarity index 96% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_load_store_unit.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_load_store_unit.sv index 6ec55b07..3575fadf 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_load_store_unit.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_load_store_unit.sv @@ -12,9 +12,9 @@ */ `include "prim_assert.sv" -//`include "dv_fcov_macros.svh" +`include "dv_fcov_macros.svh" -module ibex_load_store_unit +module cve2_load_store_unit ( input logic clk_i, input logic rst_ni, @@ -50,10 +50,6 @@ module ibex_load_store_unit // -> mtval // -> AGU for misaligned accesses - output logic lsu_req_done_o, // Signals that data request is complete - // (only need to await final data - // response) -> to ID/EX - output logic lsu_resp_valid_o, // LSU has response from transaction -> to ID/EX // exception signals @@ -453,8 +449,6 @@ module ibex_load_store_unit endcase end - assign lsu_req_done_o = (lsu_req_i | (ls_fsm_cs != IDLE)) & (ls_fsm_ns == IDLE); - // registers for FSM always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin @@ -503,8 +497,8 @@ module ibex_load_store_unit // FCOV // ////////// - //`DV_FCOV_SIGNAL(logic, ls_error_exception, (load_err_o | store_err_o) & ~pmp_err_q) - //`DV_FCOV_SIGNAL(logic, ls_pmp_exception, (load_err_o | store_err_o) & pmp_err_q) + `DV_FCOV_SIGNAL(logic, ls_error_exception, (load_err_o | store_err_o) & ~pmp_err_q) + `DV_FCOV_SIGNAL(logic, ls_pmp_exception, (load_err_o | store_err_o) & pmp_err_q) //////////////// // Assertions // diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_fast.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_fast.sv similarity index 96% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_fast.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_fast.sv index 3f0d27ac..d1d400a3 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_fast.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_fast.sv @@ -14,8 +14,8 @@ `include "prim_assert.sv" -module ibex_multdiv_fast #( - parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast +module cve2_multdiv_fast #( + parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast ) ( input logic clk_i, input logic rst_ni, @@ -23,14 +23,13 @@ module ibex_multdiv_fast #( input logic div_en_i, // dynamic enable signal, for FSM control input logic mult_sel_i, // static decoder output, for data muxes input logic div_sel_i, // static decoder output, for data muxes - input ibex_pkg::md_op_e operator_i, + input cve2_pkg::md_op_e operator_i, input logic [1:0] signed_mode_i, input logic [31:0] op_a_i, input logic [31:0] op_b_i, input logic [33:0] alu_adder_ext_i, input logic [31:0] alu_adder_i, input logic equal_to_zero_i, - input logic data_ind_timing_i, output logic [32:0] alu_operand_a_o, output logic [32:0] alu_operand_b_o, @@ -39,13 +38,11 @@ module ibex_multdiv_fast #( output logic [33:0] imd_val_d_o[2], output logic [1:0] imd_val_we_o, - input logic multdiv_ready_id_i, - output logic [31:0] multdiv_result_o, output logic valid_o ); - import ibex_pkg::*; + import cve2_pkg::*; // Both multiplier variants logic signed [34:0] mac_res_signed; @@ -210,7 +207,7 @@ module ibex_multdiv_fast #( mult_valid = 1'b0; mult_state_d = MULH; end else begin - mult_hold = ~multdiv_ready_id_i; + mult_hold = 1'b0; end end @@ -229,7 +226,7 @@ module ibex_multdiv_fast #( mult_state_d = MULL; mult_valid = 1'b1; - mult_hold = ~multdiv_ready_id_i; + mult_hold = 1'b0; end default: begin @@ -328,7 +325,7 @@ module ibex_multdiv_fast #( // Note no state transition will occur if mult_hold is set mult_state_d = ALBL; - mult_hold = ~multdiv_ready_id_i; + mult_hold = 1'b0; end else begin accum = imd_val_q_i[0]; mac_res_d = mac_res; @@ -351,7 +348,7 @@ module ibex_multdiv_fast #( // Note no state transition will occur if mult_hold is set mult_state_d = ALBL; - mult_hold = ~multdiv_ready_id_i; + mult_hold = 1'b0; end default: begin mult_state_d = ALBL; @@ -424,7 +421,7 @@ module ibex_multdiv_fast #( // normal and will naturally return -1 op_remainder_d = '1; // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A; + md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A; // Record that this is a div by zero to stop the sign change at the end of the // division (in data_ind_timing mode). div_by_zero_d = equal_to_zero_i; @@ -435,7 +432,7 @@ module ibex_multdiv_fast #( // normal and will naturally return operand a op_remainder_d = {2'b0, op_a_i}; // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A; + md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A; end // 0 - B = 0 iff B == 0 alu_operand_a_o = {32'h0 , 1'b1}; @@ -508,7 +505,7 @@ module ibex_multdiv_fast #( // Hold result until ID stage is ready to accept it // Note no state transition will occur if div_hold is set md_state_d = MD_IDLE; - div_hold = ~multdiv_ready_id_i; + div_hold = 1'b0; div_valid = 1'b1; end @@ -530,4 +527,4 @@ module ibex_multdiv_fast #( `endif `endif -endmodule // ibex_mult +endmodule // cve2_mult diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_slow.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_slow.sv similarity index 96% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_slow.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_slow.sv index 214d3f59..70732cc6 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_multdiv_slow.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_multdiv_slow.sv @@ -11,7 +11,7 @@ `include "prim_assert.sv" -module ibex_multdiv_slow +module cve2_multdiv_slow ( input logic clk_i, input logic rst_ni, @@ -19,14 +19,13 @@ module ibex_multdiv_slow input logic div_en_i, // dynamic enable signal, for FSM control input logic mult_sel_i, // static decoder output, for data muxes input logic div_sel_i, // static decoder output, for data muxes - input ibex_pkg::md_op_e operator_i, + input cve2_pkg::md_op_e operator_i, input logic [1:0] signed_mode_i, input logic [31:0] op_a_i, input logic [31:0] op_b_i, input logic [33:0] alu_adder_ext_i, input logic [31:0] alu_adder_i, input logic equal_to_zero_i, - input logic data_ind_timing_i, output logic [32:0] alu_operand_a_o, output logic [32:0] alu_operand_b_o, @@ -42,7 +41,7 @@ module ibex_multdiv_slow output logic valid_o ); - import ibex_pkg::*; + import cve2_pkg::*; typedef enum logic [2:0] { MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH @@ -191,7 +190,7 @@ module ibex_multdiv_slow op_b_shift_d = op_b_ext >> 1; // Proceed with multiplication by 0/1 in data-independent time mode // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && ((op_b_ext >> 1) == 0)) ? MD_LAST : MD_COMP; + md_state_d = ((op_b_ext >> 1) == 0) ? MD_LAST : MD_COMP; end MD_OP_MULH: begin op_a_shift_d = op_a_ext; @@ -207,7 +206,7 @@ module ibex_multdiv_slow // normal and will naturally return -1 accum_window_d = {33{1'b1}}; // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A; + md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A; // Record that this is a div by zero to stop the sign change at the end of the // division (in data_ind_timing mode). div_by_zero_d = equal_to_zero_i; @@ -219,7 +218,7 @@ module ibex_multdiv_slow // normal and will naturally return operand a accum_window_d = op_a_ext; // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A; + md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A; end default:; endcase @@ -252,7 +251,7 @@ module ibex_multdiv_slow // Multiplication is complete once op_b is zero, unless in data_ind_timing mode where // the maximum possible shift-add operations will be completed regardless of op_b // SEC_CM: CORE.DATA_REG_SW.SCA - md_state_d = ((!data_ind_timing_i && (op_b_shift_d == 0)) || + md_state_d = ((op_b_shift_d == 0) || (multdiv_count_q == 5'd1)) ? MD_LAST : MD_COMP; end MD_OP_MULH: begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv similarity index 74% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pkg.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv index fec80fdf..2e5b3535 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pkg.sv @@ -6,7 +6,7 @@ /** * Package with constants used by Ibex */ -package ibex_pkg; +package cve2_pkg; //////////////// // IO Structs // @@ -31,12 +31,6 @@ package ibex_pkg; // Parameter Enums // ///////////////////// - typedef enum integer { - RegFileFF = 0, - RegFileFPGA = 1, - RegFileLatch = 2 - } regfile_e; - typedef enum integer { RV32MNone = 0, RV32MSlow = 1, @@ -298,26 +292,25 @@ package ibex_pkg; logic irq_software; logic irq_timer; logic irq_external; - logic [14:0] irq_fast; // 15 fast interrupts, - // one interrupt is reserved for NMI (not visible through mip/mie) + logic [15:0] irq_fast; // 16 fast interrupts } irqs_t; // Exception cause - typedef enum logic [5:0] { - EXC_CAUSE_IRQ_SOFTWARE_M = {1'b1, 5'd03}, - EXC_CAUSE_IRQ_TIMER_M = {1'b1, 5'd07}, - EXC_CAUSE_IRQ_EXTERNAL_M = {1'b1, 5'd11}, - // EXC_CAUSE_IRQ_FAST_0 = {1'b1, 5'd16}, - // EXC_CAUSE_IRQ_FAST_14 = {1'b1, 5'd30}, - EXC_CAUSE_IRQ_NM = {1'b1, 5'd31}, // == EXC_CAUSE_IRQ_FAST_15 - EXC_CAUSE_INSN_ADDR_MISA = {1'b0, 5'd00}, - EXC_CAUSE_INSTR_ACCESS_FAULT = {1'b0, 5'd01}, - EXC_CAUSE_ILLEGAL_INSN = {1'b0, 5'd02}, - EXC_CAUSE_BREAKPOINT = {1'b0, 5'd03}, - EXC_CAUSE_LOAD_ACCESS_FAULT = {1'b0, 5'd05}, - EXC_CAUSE_STORE_ACCESS_FAULT = {1'b0, 5'd07}, - EXC_CAUSE_ECALL_UMODE = {1'b0, 5'd08}, - EXC_CAUSE_ECALL_MMODE = {1'b0, 5'd11} + typedef enum logic [6:0] { + EXC_CAUSE_IRQ_SOFTWARE_M = {1'b1, 6'd03}, + EXC_CAUSE_IRQ_TIMER_M = {1'b1, 6'd07}, + EXC_CAUSE_IRQ_EXTERNAL_M = {1'b1, 6'd11}, + // EXC_CAUSE_IRQ_FAST_0 = {1'b1, 6'd16}, + // EXC_CAUSE_IRQ_FAST_15 = {1'b1, 6'd31}, + EXC_CAUSE_IRQ_NM = {1'b1, 6'd32}, + EXC_CAUSE_INSN_ADDR_MISA = {1'b0, 6'd00}, + EXC_CAUSE_INSTR_ACCESS_FAULT = {1'b0, 6'd01}, + EXC_CAUSE_ILLEGAL_INSN = {1'b0, 6'd02}, + EXC_CAUSE_BREAKPOINT = {1'b0, 6'd03}, + EXC_CAUSE_LOAD_ACCESS_FAULT = {1'b0, 6'd05}, + EXC_CAUSE_STORE_ACCESS_FAULT = {1'b0, 6'd07}, + EXC_CAUSE_ECALL_UMODE = {1'b0, 6'd08}, + EXC_CAUSE_ECALL_MMODE = {1'b0, 6'd11} } exc_cause_e; // Debug cause @@ -329,27 +322,6 @@ package ibex_pkg; DBG_CAUSE_STEP = 3'h4 } dbg_cause_e; - // ICache constants - parameter int unsigned ADDR_W = 32; - parameter int unsigned BUS_SIZE = 32; - parameter int unsigned BUS_BYTES = BUS_SIZE/8; - parameter int unsigned BUS_W = $clog2(BUS_BYTES); - parameter int unsigned IC_SIZE_BYTES = 4096; - parameter int unsigned IC_NUM_WAYS = 2; - parameter int unsigned IC_LINE_SIZE = 64; - parameter int unsigned IC_LINE_BYTES = IC_LINE_SIZE/8; - parameter int unsigned IC_LINE_W = $clog2(IC_LINE_BYTES); - parameter int unsigned IC_NUM_LINES = IC_SIZE_BYTES / IC_NUM_WAYS / IC_LINE_BYTES; - parameter int unsigned IC_LINE_BEATS = IC_LINE_BYTES / BUS_BYTES; - parameter int unsigned IC_LINE_BEATS_W = $clog2(IC_LINE_BEATS); - parameter int unsigned IC_INDEX_W = $clog2(IC_NUM_LINES); - parameter int unsigned IC_INDEX_HI = IC_INDEX_W + IC_LINE_W - 1; - parameter int unsigned IC_TAG_SIZE = ADDR_W - IC_INDEX_W - IC_LINE_W + 1; // 1 valid bit - parameter int unsigned IC_OUTPUT_BEATS = (BUS_BYTES / 2); // number of halfwords - // ICache Scrambling Parameters - parameter int unsigned SCRAMBLE_KEY_W = 128; - parameter int unsigned SCRAMBLE_NONCE_W = 64; - // PMP constants parameter int unsigned PMP_MAX_REGIONS = 16; parameter int unsigned PMP_CFG_W = 8; @@ -391,10 +363,11 @@ package ibex_pkg; // CSRs typedef enum logic[11:0] { // Machine information - CSR_MVENDORID = 12'hF11, - CSR_MARCHID = 12'hF12, - CSR_MIMPID = 12'hF13, - CSR_MHARTID = 12'hF14, + CSR_MVENDORID = 12'hF11, + CSR_MARCHID = 12'hF12, + CSR_MIMPID = 12'hF13, + CSR_MHARTID = 12'hF14, + CSR_MCONFIGPTR = 12'hF15, // Machine trap setup CSR_MSTATUS = 12'h300, @@ -402,6 +375,10 @@ package ibex_pkg; CSR_MIE = 12'h304, CSR_MTVEC = 12'h305, CSR_MCOUNTEREN= 12'h306, + CSR_MSTATUSH = 12'h310, + + CSR_MENVCFG = 12'h30A, + CSR_MENVCFGH = 12'h31A, // Machine trap handling CSR_MSCRATCH = 12'h340, @@ -569,52 +546,113 @@ package ibex_pkg; parameter int unsigned CSR_MTIX_BIT = 7; parameter int unsigned CSR_MEIX_BIT = 11; parameter int unsigned CSR_MFIX_BIT_LOW = 16; - parameter int unsigned CSR_MFIX_BIT_HIGH = 30; + parameter int unsigned CSR_MFIX_BIT_HIGH = 31; // CSR Machine Security Configuration bits parameter int unsigned CSR_MSECCFG_MML_BIT = 0; parameter int unsigned CSR_MSECCFG_MMWP_BIT = 1; parameter int unsigned CSR_MSECCFG_RLB_BIT = 2; - // Vendor ID - // No JEDEC ID has been allocated to lowRISC so the value is 0 to indicate the field is not - // implemented - localparam logic [31:0] CSR_MVENDORID_VALUE = 32'b0; + // Machine Vendor ID - OpenHW JEDEC ID is '2 decimal (bank 13)' + parameter MVENDORID_OFFSET = 7'h2; // Final byte without parity bit + parameter MVENDORID_BANK = 25'hC; // Number of continuation codes + + // Machine Architecture ID (https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md) + parameter MARCHID = 32'd35; - // Architecture ID - // Top bit is unset to indicate an open source project. The lower bits are an ID allocated by the - // RISC-V Foundation. Note this is allocated specifically to Ibex, should significant changes be - // made a different architecture ID should be supplied. - localparam logic [31:0] CSR_MARCHID_VALUE = {1'b0, 31'd22}; + localparam logic [31:0] CSR_MVENDORID_VALUE = {MVENDORID_BANK, MVENDORID_OFFSET}; + localparam logic [31:0] CSR_MARCHID_VALUE = MARCHID; // Implementation ID - // 0 indicates this field is not implemeted. Ibex implementors may wish to indicate an RTL/netlist + // 0 indicates this field is not implemeted. cve2 implementors may wish to indicate an RTL/netlist // version here using their own unique encoding (e.g. 32 bits of the git hash of the implemented // commit). localparam logic [31:0] CSR_MIMPID_VALUE = 32'b0; - // These LFSR parameters have been generated with - // $ opentitan/util/design/gen-lfsr-seed.py --width 32 --seed 2480124384 --prefix "" - parameter int LfsrWidth = 32; - typedef logic [LfsrWidth-1:0] lfsr_seed_t; - typedef logic [LfsrWidth-1:0][$clog2(LfsrWidth)-1:0] lfsr_perm_t; - parameter lfsr_seed_t RndCnstLfsrSeedDefault = 32'hac533bf4; - parameter lfsr_perm_t RndCnstLfsrPermDefault = { - 160'h1e35ecba467fd1b12e958152c04fa43878a8daed - }; - parameter logic [SCRAMBLE_KEY_W-1:0] RndCnstIbexKeyDefault = - 128'h14e8cecae3040d5e12286bb3cc113298; - parameter logic [SCRAMBLE_NONCE_W-1:0] RndCnstIbexNonceDefault = - 64'hf79780bc735f3843; - - // Fetch enable. Mult-bit signal used for security hardening. For non-secure implementation all - // bits other than the bottom bit are ignored. - typedef logic [3:0] fetch_enable_t; - - // Note that if adjusting these parameters it is assumed the bottom bit is set for On and unset - // for Off. This allows the use of FetchEnableOn/FetchEnableOff to work for both secure and - // non-secure Ibex. If this assumption is broken the RTL that uses the fetch_enable signal within - // `ibex_core` may need adjusting. - parameter fetch_enable_t FetchEnableOn = 4'b1001; - parameter fetch_enable_t FetchEnableOff = 4'b0110; + // Machine Configuration Pointer + // 0 indicates the configuration data structure does not eixst. cve2 implementors may wish to + // alter this to point to their system specific configuration data structure. + localparam logic [31:0] CSR_MCONFIGPTR_VALUE = 32'b0; + + // RVFI CSR element + typedef struct packed { + bit [63:0] rdata; + bit [63:0] rmask; + bit [63:0] wdata; + bit [63:0] wmask; + } rvfi_csr_elmt_t; + + // RVFI CSR structure + typedef struct packed { + rvfi_csr_elmt_t fflags; + rvfi_csr_elmt_t frm; + rvfi_csr_elmt_t fcsr; + rvfi_csr_elmt_t ftran; + rvfi_csr_elmt_t dcsr; + rvfi_csr_elmt_t dpc; + rvfi_csr_elmt_t dscratch0; + rvfi_csr_elmt_t dscratch1; + rvfi_csr_elmt_t sstatus; + rvfi_csr_elmt_t sie; + rvfi_csr_elmt_t sip; + rvfi_csr_elmt_t stvec; + rvfi_csr_elmt_t scounteren; + rvfi_csr_elmt_t sscratch; + rvfi_csr_elmt_t sepc; + rvfi_csr_elmt_t scause; + rvfi_csr_elmt_t stval; + rvfi_csr_elmt_t satp; + rvfi_csr_elmt_t mstatus; + rvfi_csr_elmt_t mstatush; + rvfi_csr_elmt_t misa; + rvfi_csr_elmt_t medeleg; + rvfi_csr_elmt_t mideleg; + rvfi_csr_elmt_t mie; + rvfi_csr_elmt_t mtvec; + rvfi_csr_elmt_t mcounteren; + rvfi_csr_elmt_t mscratch; + rvfi_csr_elmt_t mepc; + rvfi_csr_elmt_t mcause; + rvfi_csr_elmt_t mtval; + rvfi_csr_elmt_t mip; + rvfi_csr_elmt_t menvcfg; + rvfi_csr_elmt_t menvcfgh; + rvfi_csr_elmt_t mvendorid; + rvfi_csr_elmt_t marchid; + rvfi_csr_elmt_t mhartid; + rvfi_csr_elmt_t mcountinhibit; + rvfi_csr_elmt_t mcycle; + rvfi_csr_elmt_t mcycleh; + rvfi_csr_elmt_t minstret; + rvfi_csr_elmt_t minstreth; + rvfi_csr_elmt_t cycle; + rvfi_csr_elmt_t cycleh; + rvfi_csr_elmt_t instret; + rvfi_csr_elmt_t instreth; + rvfi_csr_elmt_t dcache; + rvfi_csr_elmt_t icache; + rvfi_csr_elmt_t acc_cons; + rvfi_csr_elmt_t pmpcfg0; + rvfi_csr_elmt_t pmpcfg1; + rvfi_csr_elmt_t pmpcfg2; + rvfi_csr_elmt_t pmpcfg3; + rvfi_csr_elmt_t pmpaddr0; + rvfi_csr_elmt_t pmpaddr1; + rvfi_csr_elmt_t pmpaddr2; + rvfi_csr_elmt_t pmpaddr3; + rvfi_csr_elmt_t pmpaddr4; + rvfi_csr_elmt_t pmpaddr5; + rvfi_csr_elmt_t pmpaddr6; + rvfi_csr_elmt_t pmpaddr7; + rvfi_csr_elmt_t pmpaddr8; + rvfi_csr_elmt_t pmpaddr9; + rvfi_csr_elmt_t pmpaddr10; + rvfi_csr_elmt_t pmpaddr11; + rvfi_csr_elmt_t pmpaddr12; + rvfi_csr_elmt_t pmpaddr13; + rvfi_csr_elmt_t pmpaddr14; + rvfi_csr_elmt_t pmpaddr15; + } rvfi_csr_t; + endpackage + diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp.sv similarity index 95% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp.sv index 16e806a2..b531eefd 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp.sv @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 -module ibex_pmp #( +module cve2_pmp #( // Granularity of NAPOT access, // 0 = No restriction, 1 = 8 byte, 2 = 16 byte, 3 = 32 byte, etc. parameter int unsigned PMPGranularity = 0, @@ -16,19 +16,19 @@ module ibex_pmp #( input logic rst_ni, // Interface to CSRs - input ibex_pkg::pmp_cfg_t csr_pmp_cfg_i [PMPNumRegions], + input cve2_pkg::pmp_cfg_t csr_pmp_cfg_i [PMPNumRegions], input logic [33:0] csr_pmp_addr_i [PMPNumRegions], - input ibex_pkg::pmp_mseccfg_t csr_pmp_mseccfg_i, + input cve2_pkg::pmp_mseccfg_t csr_pmp_mseccfg_i, - input ibex_pkg::priv_lvl_e priv_mode_i [PMPNumChan], + input cve2_pkg::priv_lvl_e priv_mode_i [PMPNumChan], // Access checking channels input logic [33:0] pmp_req_addr_i [PMPNumChan], - input ibex_pkg::pmp_req_e pmp_req_type_i [PMPNumChan], + input cve2_pkg::pmp_req_e pmp_req_type_i [PMPNumChan], output logic pmp_req_err_o [PMPNumChan] ); - import ibex_pkg::*; + import cve2_pkg::*; // Access Checking Signals logic [33:0] region_start_addr [PMPNumRegions]; @@ -177,7 +177,7 @@ module ibex_pmp #( assign pmp_req_err_o[c] = access_fault[c]; end - // RLB, rule locking bypass, is only relevant to ibex_cs_registers which controls writes to the + // RLB, rule locking bypass, is only relevant to cve2_cs_registers which controls writes to the // PMP CSRs. Tie to unused signal here to prevent lint warnings. logic unused_csr_pmp_mseccfg_rlb; assign unused_csr_pmp_mseccfg_rlb = csr_pmp_mseccfg_i.rlb; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp_reset_default.svh b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp_reset_default.svh similarity index 100% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_pmp_reset_default.svh rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_pmp_reset_default.svh diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_prefetch_buffer.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_prefetch_buffer.sv similarity index 81% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_prefetch_buffer.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_prefetch_buffer.sv index 5b834ce2..51b1195c 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_prefetch_buffer.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_prefetch_buffer.sv @@ -9,8 +9,7 @@ * Prefetch Buffer that caches instructions. This cuts overly long critical * paths to the instruction cache. */ -module ibex_prefetch_buffer #( - parameter bit ResetAll = 1'b0 +module cve2_prefetch_buffer #( ) ( input logic clk_i, input logic rst_ni, @@ -18,8 +17,6 @@ module ibex_prefetch_buffer #( input logic req_i, input logic branch_i, - input logic branch_mispredict_i, - input logic [31:0] mispredict_addr_i, input logic [31:0] addr_i, @@ -65,16 +62,12 @@ module ibex_prefetch_buffer #( logic valid_raw; - logic branch_or_mispredict; - //////////////////////////// // Prefetch buffer status // //////////////////////////// assign busy_o = (|rdata_outstanding_q) | instr_req_o; - assign branch_or_mispredict = branch_i | branch_mispredict_i; - ////////////////////////////////////////////// // Fetch fifo - consumes addresses and data // ////////////////////////////////////////////// @@ -82,7 +75,7 @@ module ibex_prefetch_buffer #( // A branch will invalidate any previously fetched instructions. // Note that the FENCE.I instruction relies on this flushing behaviour on branch. If it is // altered the FENCE.I implementation may require changes. - assign fifo_clear = branch_or_mispredict; + assign fifo_clear = branch_i; // Reversed version of rdata_outstanding_q which can be overlaid with fifo fill state for (genvar i = 0; i < NUM_REQS; i++) begin : gen_rd_rev @@ -94,9 +87,8 @@ module ibex_prefetch_buffer #( // Overlay the fifo fill state with the outstanding requests to see if there is space. assign fifo_ready = ~&(fifo_busy | rdata_outstanding_rev); - ibex_fetch_fifo #( - .NUM_REQS (NUM_REQS), - .ResetAll (ResetAll) + cve2_fetch_fifo #( + .NUM_REQS (NUM_REQS) ) fifo_i ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -122,7 +114,7 @@ module ibex_prefetch_buffer #( ////////////// // Make a new request any time there is space in the FIFO, and space in the request queue - assign valid_new_req = req_i & (fifo_ready | branch_or_mispredict) & + assign valid_new_req = req_i & (fifo_ready | branch_i) & ~rdata_outstanding_q[NUM_REQS-1]; assign valid_req = valid_req_q | valid_new_req; @@ -131,7 +123,7 @@ module ibex_prefetch_buffer #( assign valid_req_d = valid_req & ~instr_gnt_i; // Record whether an outstanding bus request is cancelled by a branch - assign discard_req_d = valid_req_q & (branch_or_mispredict | discard_req_q); + assign discard_req_d = valid_req_q & (branch_i | discard_req_q); //////////////// // Fetch addr // @@ -156,52 +148,34 @@ module ibex_prefetch_buffer #( assign stored_addr_d = instr_addr; // CPU resets with a branch, so no need to reset these addresses - if (ResetAll) begin : g_stored_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - stored_addr_q <= '0; - end else if (stored_addr_en) begin - stored_addr_q <= stored_addr_d; - end - end - end else begin : g_stored_addr_nr - always_ff @(posedge clk_i) begin - if (stored_addr_en) begin - stored_addr_q <= stored_addr_d; - end + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + stored_addr_q <= '0; + end else if (stored_addr_en) begin + stored_addr_q <= stored_addr_d; end end // 2. fetch_addr_q // Update on a branch or as soon as a request is issued - assign fetch_addr_en = branch_or_mispredict | (valid_new_req & ~valid_req_q); + assign fetch_addr_en = branch_i | (valid_new_req & ~valid_req_q); assign fetch_addr_d = (branch_i ? addr_i : - branch_mispredict_i ? {mispredict_addr_i[31:2], 2'b00} : {fetch_addr_q[31:2], 2'b00}) + // Current address + 4 {{29{1'b0}},(valid_new_req & ~valid_req_q),2'b00}; - if (ResetAll) begin : g_fetch_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fetch_addr_q <= '0; - end else if (fetch_addr_en) begin - fetch_addr_q <= fetch_addr_d; - end - end - end else begin : g_fetch_addr_nr - always_ff @(posedge clk_i) begin - if (fetch_addr_en) begin - fetch_addr_q <= fetch_addr_d; - end + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + fetch_addr_q <= '0; + end else if (fetch_addr_en) begin + fetch_addr_q <= fetch_addr_d; end end // Address mux assign instr_addr = valid_req_q ? stored_addr_q : branch_i ? addr_i : - branch_mispredict_i ? mispredict_addr_i : fetch_addr_q; assign instr_addr_w_aligned = {instr_addr[31:2], 2'b00}; @@ -220,7 +194,7 @@ module ibex_prefetch_buffer #( // If a branch is received at any point while a request is outstanding, it must be tracked // to ensure we discard the data once received assign branch_discard_n[i] = (valid_req & instr_gnt_i & discard_req_d) | - (branch_or_mispredict & rdata_outstanding_q[i]) | + (branch_i & rdata_outstanding_q[i]) | branch_discard_q[i]; end else begin : g_reqtop @@ -232,7 +206,7 @@ module ibex_prefetch_buffer #( rdata_outstanding_q[i]; assign branch_discard_n[i] = (valid_req & instr_gnt_i & discard_req_d & rdata_outstanding_q[i-1]) | - (branch_or_mispredict & rdata_outstanding_q[i]) | + (branch_i & rdata_outstanding_q[i]) | branch_discard_q[i]; end end @@ -246,7 +220,7 @@ module ibex_prefetch_buffer #( // Push a new entry to the FIFO once complete (and not cancelled by a branch) assign fifo_valid = instr_rvalid_i & ~branch_discard_q[0]; - assign fifo_addr = branch_i ? addr_i : mispredict_addr_i; + assign fifo_addr = addr_i; /////////////// // Registers // @@ -273,6 +247,6 @@ module ibex_prefetch_buffer #( assign instr_req_o = valid_req; assign instr_addr_o = instr_addr_w_aligned; - assign valid_o = valid_raw & ~branch_mispredict_i; + assign valid_o = valid_raw; endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_ff.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_register_file_ff.sv similarity index 66% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_ff.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_register_file_ff.sv index 90b0c719..148ba225 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_ff.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_register_file_ff.sv @@ -10,10 +10,9 @@ * This register file is based on flip flops. Use this register file when * targeting FPGA synthesis or Verilator simulation. */ -module ibex_register_file_ff #( +module cve2_register_file_ff #( parameter bit RV32E = 0, parameter int unsigned DataWidth = 32, - parameter bit DummyInstructions = 0, parameter logic [DataWidth-1:0] WordZeroVal = '0 ) ( // Clock and Reset @@ -21,7 +20,6 @@ module ibex_register_file_ff #( input logic rst_ni, input logic test_en_i, - input logic dummy_instr_id_i, //Read port R1 input logic [4:0] raddr_a_i, @@ -63,34 +61,8 @@ module ibex_register_file_ff #( end end - // With dummy instructions enabled, R0 behaves as a real register but will always return 0 for - // real instructions. - if (DummyInstructions) begin : g_dummy_r0 - // SEC_CM: CTRL_FLOW.UNPREDICTABLE - logic we_r0_dummy; - logic [DataWidth-1:0] rf_r0_q; - - // Write enable for dummy R0 register (waddr_a_i will always be 0 for dummy instructions) - assign we_r0_dummy = we_a_i & dummy_instr_id_i; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - rf_r0_q <= WordZeroVal; - end else if (we_r0_dummy) begin - rf_r0_q <= wdata_a_i; - end - end - - // Output the dummy data for dummy instructions, otherwise R0 reads as zero - assign rf_reg[0] = dummy_instr_id_i ? rf_r0_q : WordZeroVal; - - end else begin : g_normal_r0 - logic unused_dummy_instr_id; - assign unused_dummy_instr_id = dummy_instr_id_i; - - // R0 is nil - assign rf_reg[0] = WordZeroVal; - end + // R0 is nil + assign rf_reg[0] = WordZeroVal; assign rf_reg[NUM_WORDS-1:1] = rf_reg_q[NUM_WORDS-1:1]; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_sleep_unit.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_sleep_unit.sv deleted file mode 100644 index 80388031..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_sleep_unit.sv +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2020 Silicon Labs, Inc. -// -// This file, and derivatives thereof are licensed under the -// Solderpad License, Version 2.0 (the "License"). -// -// Use of this file means you agree to the terms and conditions -// of the license and are in full compliance with the License. -// -// You may obtain a copy of the License at: -// -// https://solderpad.org/licenses/SHL-2.0/ -// -// Unless required by applicable law or agreed to in writing, software -// and hardware implementations thereof distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED. -// -// See the License for the specific language governing permissions and -// limitations under the License. - -//////////////////////////////////////////////////////////////////////////////// -// Engineer: Arjan Bink - arjan.bink@silabs.com // -// // -// Design Name: Sleep Unit // -// Project Name: CVE2 // -// Language: SystemVerilog // -// // -// Description: Sleep unit containing the instantiated clock gate which // -// provides the gated clock (clk_gated_o) for the rest // -// of the design. Forked version of cv32e40p // -// // -// The clock is gated for the following scenarios: // -// // -// - While waiting for fetch to become enabled // -// - While blocked on a WFI (PULP_CLUSTER = 0) // -// - While clock_en_i = 0 during a p.elw (PULP_CLUSTER = 1) // -// // -// Sleep is signaled via core_sleep_o when: // -// - During a WFI (except in debug) // -// // -// // -//////////////////////////////////////////////////////////////////////////////// - -module cve2_sleep_unit ( - // Clock, reset interface - input logic clk_ungated_i, // Free running clock - input logic rst_n, - output logic clk_gated_o, // Gated clock - input logic scan_cg_en_i, // Enable all clock gates for testing - - // Core sleep - output logic core_sleep_o, - - // Fetch enable - input logic fetch_enable_i, - output logic fetch_enable_o, - - // Core status - input logic if_busy_i, - input logic ctrl_busy_i, - input logic lsu_busy_i, - - // WFI wake - input logic wake_from_sleep_i -); - - logic fetch_enable_q; // Sticky version of fetch_enable_i - logic fetch_enable_d; - logic core_busy_q; // Is core still busy (and requires a clock) with what needs to finish before entering sleep? - logic core_busy_d; - logic clock_en; // Final clock enable - - ////////////////////////////////////////////////////////////////////////////// - // Sleep FSM - ////////////////////////////////////////////////////////////////////////////// - - // Make sticky version of fetch_enable_i - assign fetch_enable_d = fetch_enable_i ? 1'b1 : fetch_enable_q; - - - // Busy when any of the sub units is busy (typically wait for the instruction buffer to fill up) - assign core_busy_d = if_busy_i || ctrl_busy_i || lsu_busy_i; - - // Enable the clock only after the initial fetch enable while busy or waking up to become busy - assign clock_en = fetch_enable_q && (wake_from_sleep_i || core_busy_q); - - // Sleep only in response to WFI which leads to clock disable; debug_wfi_no_sleep_o in - // cv32e40p_controller determines the scenarios for which WFI can(not) cause sleep. - assign core_sleep_o = fetch_enable_q && !clock_en; - - - always_ff @(posedge clk_ungated_i, negedge rst_n) begin - if (rst_n == 1'b0) begin - core_busy_q <= 1'b0; - fetch_enable_q <= 1'b0; - end else begin - core_busy_q <= core_busy_d; - fetch_enable_q <= fetch_enable_d; - end - end - - // Fetch enable for Controller - assign fetch_enable_o = fetch_enable_q; - - // Main clock gate of CV32E40P - cve2_clock_gate core_clock_gate_i ( - .clk_i (clk_ungated_i), - .en_i (clock_en), - .scan_cg_en_i(scan_cg_en_i), - .clk_o (clk_gated_o) - ); - - //---------------------------------------------------------------------------- - // Assertions - TODO - //---------------------------------------------------------------------------- - - -endmodule // cve2_sleep_unit diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv new file mode 100644 index 00000000..00c38a4a --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top.sv @@ -0,0 +1,272 @@ +// Copyright lowRISC contributors. +// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`ifdef RISCV_FORMAL + `define RVFI +`endif + +`include "prim_assert.sv" + +/** + * Top level module of the ibex RISC-V core + */ +module cve2_top import cve2_pkg::*; #( + parameter int unsigned MHPMCounterNum = 0, + parameter int unsigned MHPMCounterWidth = 40, + parameter bit RV32E = 1'b0, + parameter rv32m_e RV32M = RV32MFast, + parameter int unsigned DmHaltAddr = 32'h1A110800, + parameter int unsigned DmExceptionAddr = 32'h1A110808 +) ( + // Clock and Reset + input logic clk_i, + input logic rst_ni, + + input logic test_en_i, // enable all clock gates for testing + input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, + + input logic [31:0] hart_id_i, + input logic [31:0] boot_addr_i, + + // Instruction memory interface + output logic instr_req_o, + input logic instr_gnt_i, + input logic instr_rvalid_i, + output logic [31:0] instr_addr_o, + input logic [31:0] instr_rdata_i, + input logic instr_err_i, + + // Data memory interface + output logic data_req_o, + input logic data_gnt_i, + input logic data_rvalid_i, + output logic data_we_o, + output logic [3:0] data_be_o, + output logic [31:0] data_addr_o, + output logic [31:0] data_wdata_o, + input logic [31:0] data_rdata_i, + input logic data_err_i, + + // Interrupt inputs + input logic irq_software_i, + input logic irq_timer_i, + input logic irq_external_i, + input logic [15:0] irq_fast_i, + input logic irq_nm_i, // non-maskeable interrupt + + // Debug Interface + input logic debug_req_i, + output crash_dump_t crash_dump_o, + + // RISC-V Formal Interface + // Does not comply with the coding standards of _i/_o suffixes, but follows + // the convention of RISC-V Formal Interface Specification. +`ifdef RVFI + output logic rvfi_valid, + output logic [63:0] rvfi_order, + output logic [31:0] rvfi_insn, + output logic rvfi_trap, + output logic rvfi_halt, + output logic rvfi_intr, + output logic [ 1:0] rvfi_mode, + output logic [ 1:0] rvfi_ixl, + output logic [ 4:0] rvfi_rs1_addr, + output logic [ 4:0] rvfi_rs2_addr, + output logic [ 4:0] rvfi_rs3_addr, + output logic [31:0] rvfi_rs1_rdata, + output logic [31:0] rvfi_rs2_rdata, + output logic [31:0] rvfi_rs3_rdata, + output logic [ 4:0] rvfi_rd_addr, + output logic [31:0] rvfi_rd_wdata, + output logic [31:0] rvfi_pc_rdata, + output logic [31:0] rvfi_pc_wdata, + output logic [31:0] rvfi_mem_addr, + output logic [ 3:0] rvfi_mem_rmask, + output logic [ 3:0] rvfi_mem_wmask, + output logic [31:0] rvfi_mem_rdata, + output logic [31:0] rvfi_mem_wdata, + output logic [31:0] rvfi_ext_mip, + output logic rvfi_ext_nmi, + output logic rvfi_ext_debug_req, + output logic [63:0] rvfi_ext_mcycle, +`endif + + // CPU Control Signals + input logic fetch_enable_i, + output logic core_sleep_o +); + + // Scrambling Parameter + localparam int unsigned NumAddrScrRounds = 0; + + // Physical Memory Protection + localparam bit PMPEnable = 1'b0; + localparam int unsigned PMPGranularity = 0; + localparam int unsigned PMPNumRegions = 4; + + // Trigger support + localparam bit DbgTriggerEn = 1'b1; + localparam int unsigned DbgHwBreakNum = 1; + + // Bit manipulation extension + localparam rv32b_e RV32B = RV32BNone; + + // Clock signals + logic clk; + logic core_busy_d, core_busy_q; + logic clock_en; + logic fetch_enable_d, fetch_enable_q; + logic irq_pending; + + ///////////////////// + // Main clock gate // + ///////////////////// + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + core_busy_q <= 1'b0; + fetch_enable_q <= 1'b0; + end else begin + core_busy_q <= core_busy_d; + fetch_enable_q <= fetch_enable_d; + end + end + + assign clock_en = fetch_enable_q & (core_busy_q | debug_req_i | irq_pending | irq_nm_i); + assign core_sleep_o = fetch_enable_q & !clock_en; + assign fetch_enable_d = fetch_enable_i ? 1'b1 : fetch_enable_q; + + cve2_clock_gate core_clock_gate_i ( + .clk_i (clk_i), + .en_i (clock_en), + .scan_cg_en_i(test_en_i), + .clk_o (clk) + ); + + //////////////////////// + // Core instantiation // + //////////////////////// + + cve2_core #( + .PMPEnable (PMPEnable), + .PMPGranularity (PMPGranularity), + .PMPNumRegions (PMPNumRegions), + .MHPMCounterNum (MHPMCounterNum), + .MHPMCounterWidth (MHPMCounterWidth), + .RV32E (RV32E), + .RV32M (RV32M), + .RV32B (RV32B), + .DbgTriggerEn (DbgTriggerEn), + .DbgHwBreakNum (DbgHwBreakNum), + .DmHaltAddr (DmHaltAddr), + .DmExceptionAddr (DmExceptionAddr) + ) u_cve2_core ( + .clk_i(clk), + .rst_ni, + .test_en_i, + + .hart_id_i, + .boot_addr_i, + + .instr_req_o, + .instr_gnt_i, + .instr_rvalid_i, + .instr_addr_o, + .instr_rdata_i, + .instr_err_i, + + .data_req_o, + .data_gnt_i, + .data_rvalid_i, + .data_we_o, + .data_be_o, + .data_addr_o, + .data_wdata_o, + .data_rdata_i, + .data_err_i, + + .irq_software_i, + .irq_timer_i, + .irq_external_i, + .irq_fast_i, + .irq_nm_i, + .irq_pending_o(irq_pending), + + .debug_req_i, + .crash_dump_o, + +`ifdef RVFI + .rvfi_valid, + .rvfi_order, + .rvfi_insn, + .rvfi_trap, + .rvfi_halt, + .rvfi_intr, + .rvfi_mode, + .rvfi_ixl, + .rvfi_rs1_addr, + .rvfi_rs2_addr, + .rvfi_rs3_addr, + .rvfi_rs1_rdata, + .rvfi_rs2_rdata, + .rvfi_rs3_rdata, + .rvfi_rd_addr, + .rvfi_rd_wdata, + .rvfi_pc_rdata, + .rvfi_pc_wdata, + .rvfi_mem_addr, + .rvfi_mem_rmask, + .rvfi_mem_wmask, + .rvfi_mem_rdata, + .rvfi_mem_wdata, + .rvfi_ext_mip, + .rvfi_ext_nmi, + .rvfi_ext_debug_req, + .rvfi_ext_mcycle, +`endif + + .fetch_enable_i (fetch_enable_q), + .core_busy_o (core_busy_d) + ); + + //////////////////////// + // Rams Instantiation // + //////////////////////// + + prim_ram_1p_pkg::ram_1p_cfg_t unused_ram_cfg; + logic unused_ram_inputs; + + assign unused_ram_cfg = ram_cfg_i; + assign unused_ram_inputs = (|NumAddrScrRounds); + + + // X checks for top-level outputs + `ASSERT_KNOWN(IbexInstrReqX, instr_req_o) + `ASSERT_KNOWN_IF(IbexInstrReqPayloadX, instr_addr_o, instr_req_o) + + `ASSERT_KNOWN(IbexDataReqX, data_req_o) + `ASSERT_KNOWN_IF(IbexDataReqPayloadX, + {data_we_o, data_be_o, data_addr_o, data_wdata_o}, data_req_o) + + `ASSERT_KNOWN(IbexCoreSleepX, core_sleep_o) + + // X check for top-level inputs + `ASSERT_KNOWN(IbexTestEnX, test_en_i) + `ASSERT_KNOWN(IbexRamCfgX, ram_cfg_i) + `ASSERT_KNOWN(IbexHartIdX, hart_id_i) + `ASSERT_KNOWN(IbexBootAddrX, boot_addr_i) + + `ASSERT_KNOWN(IbexInstrGntX, instr_gnt_i) + `ASSERT_KNOWN(IbexInstrRValidX, instr_rvalid_i) + `ASSERT_KNOWN_IF(IbexInstrRPayloadX, + {instr_rdata_i, instr_err_i}, instr_rvalid_i) + + `ASSERT_KNOWN(IbexDataGntX, data_gnt_i) + `ASSERT_KNOWN(IbexDataRValidX, data_rvalid_i) + + `ASSERT_KNOWN(IbexIrqX, {irq_software_i, irq_timer_i, irq_external_i, irq_fast_i, irq_nm_i}) + + `ASSERT_KNOWN(IbexDebugReqX, debug_req_i) +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top_tracing.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv similarity index 64% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top_tracing.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv index f4384653..7589bc3a 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top_tracing.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_top_tracing.sv @@ -3,30 +3,14 @@ // SPDX-License-Identifier: Apache-2.0 /** - * Top level module of the ibex RISC-V core with tracing enabled + * Top level module of the cve2 RISC-V core with tracing enabled */ -module ibex_top_tracing import ibex_pkg::*; #( - parameter bit PMPEnable = 1'b0, - parameter int unsigned PMPGranularity = 0, - parameter int unsigned PMPNumRegions = 4, +module cve2_top_tracing import cve2_pkg::*; #( parameter int unsigned MHPMCounterNum = 0, parameter int unsigned MHPMCounterWidth = 40, parameter bit RV32E = 1'b0, parameter rv32m_e RV32M = RV32MFast, - parameter rv32b_e RV32B = RV32BNone, - parameter regfile_e RegFile = RegFileFF, - parameter bit BranchTargetALU = 1'b0, - parameter bit WritebackStage = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter bit BranchPredictor = 1'b0, - parameter bit DbgTriggerEn = 1'b0, - parameter int unsigned DbgHwBreakNum = 1, - parameter bit SecureIbex = 1'b0, - parameter bit ICacheScramble = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808 ) ( @@ -35,7 +19,6 @@ module ibex_top_tracing import ibex_pkg::*; #( input logic rst_ni, input logic test_en_i, // enable all clock gates for testing - input logic scan_rst_ni, input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, @@ -48,7 +31,6 @@ module ibex_top_tracing import ibex_pkg::*; #( input logic instr_rvalid_i, output logic [31:0] instr_addr_o, input logic [31:0] instr_rdata_i, - input logic [6:0] instr_rdata_intg_i, input logic instr_err_i, // Data memory interface @@ -59,39 +41,27 @@ module ibex_top_tracing import ibex_pkg::*; #( output logic [3:0] data_be_o, output logic [31:0] data_addr_o, output logic [31:0] data_wdata_o, - output logic [6:0] data_wdata_intg_o, input logic [31:0] data_rdata_i, - input logic [6:0] data_rdata_intg_i, input logic data_err_i, // Interrupt inputs input logic irq_software_i, input logic irq_timer_i, input logic irq_external_i, - input logic [14:0] irq_fast_i, + input logic [15:0] irq_fast_i, input logic irq_nm_i, // non-maskeable interrupt - // Scrambling Interface - input logic scramble_key_valid_i, - input logic [SCRAMBLE_KEY_W-1:0] scramble_key_i, - input logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_i, - output logic scramble_req_o, - // Debug Interface input logic debug_req_i, output crash_dump_t crash_dump_o, - output logic double_fault_seen_o, // CPU Control Signals - input fetch_enable_t fetch_enable_i, - output logic alert_minor_o, - output logic alert_major_internal_o, - output logic alert_major_bus_o, + input logic fetch_enable_i, output logic core_sleep_o ); - // ibex_tracer relies on the signals from the RISC-V Formal Interface + // cve2_tracer relies on the signals from the RISC-V Formal Interface `ifndef RVFI $fatal("Fatal error: RVFI needs to be defined globally."); `endif @@ -136,35 +106,18 @@ module ibex_top_tracing import ibex_pkg::*; #( assign unused_rvfi_ext_debug_req = rvfi_ext_debug_req; assign unused_rvfi_ext_mcycle = rvfi_ext_mcycle; - ibex_top #( - .PMPEnable ( PMPEnable ), - .PMPGranularity ( PMPGranularity ), - .PMPNumRegions ( PMPNumRegions ), + cve2_top #( .MHPMCounterNum ( MHPMCounterNum ), .MHPMCounterWidth ( MHPMCounterWidth ), .RV32E ( RV32E ), .RV32M ( RV32M ), - .RV32B ( RV32B ), - .RegFile ( RegFile ), - .BranchTargetALU ( BranchTargetALU ), - .ICache ( ICache ), - .ICacheECC ( ICacheECC ), - .BranchPredictor ( BranchPredictor ), - .DbgTriggerEn ( DbgTriggerEn ), - .DbgHwBreakNum ( DbgHwBreakNum ), - .WritebackStage ( WritebackStage ), - .SecureIbex ( SecureIbex ), - .ICacheScramble ( ICacheScramble ), - .RndCnstLfsrSeed ( RndCnstLfsrSeed ), - .RndCnstLfsrPerm ( RndCnstLfsrPerm ), .DmHaltAddr ( DmHaltAddr ), .DmExceptionAddr ( DmExceptionAddr ) - ) u_ibex_top ( + ) u_cve2_top ( .clk_i, .rst_ni, .test_en_i, - .scan_rst_ni, .ram_cfg_i, .hart_id_i, @@ -175,7 +128,6 @@ module ibex_top_tracing import ibex_pkg::*; #( .instr_rvalid_i, .instr_addr_o, .instr_rdata_i, - .instr_rdata_intg_i, .instr_err_i, .data_req_o, @@ -185,9 +137,7 @@ module ibex_top_tracing import ibex_pkg::*; #( .data_be_o, .data_addr_o, .data_wdata_o, - .data_wdata_intg_o, .data_rdata_i, - .data_rdata_intg_i, .data_err_i, .irq_software_i, @@ -196,14 +146,8 @@ module ibex_top_tracing import ibex_pkg::*; #( .irq_fast_i, .irq_nm_i, - .scramble_key_valid_i, - .scramble_key_i, - .scramble_nonce_i, - .scramble_req_o, - .debug_req_i, .crash_dump_o, - .double_fault_seen_o, .rvfi_valid, .rvfi_order, @@ -234,14 +178,11 @@ module ibex_top_tracing import ibex_pkg::*; #( .rvfi_ext_mcycle, .fetch_enable_i, - .alert_minor_o, - .alert_major_internal_o, - .alert_major_bus_o, .core_sleep_o ); - ibex_tracer - u_ibex_tracer ( + cve2_tracer + u_cve2_tracer ( .clk_i, .rst_ni, diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer.sv similarity index 98% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer.sv index bd36a214..707419e4 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer.sv @@ -12,12 +12,12 @@ * All traced instructions are written to a log file. By default, the log file is named * trace_core_.log, with being the 8 digit hart ID of the core being traced. * - * The file name base, defaulting to "trace_core" can be set using the "ibex_tracer_file_base" - * plusarg passed to the simulation, e.g. "+ibex_tracer_file_base=ibex_my_trace". The exact syntax + * The file name base, defaulting to "trace_core" can be set using the "cve2_tracer_file_base" + * plusarg passed to the simulation, e.g. "+cve2_tracer_file_base=cve2_my_trace". The exact syntax * of passing plusargs to a simulation depends on the simulator. * * The creation of the instruction trace is enabled by default but can be disabled for a simulation. - * This behaviour is controlled by the plusarg "ibex_tracer_enable". Use "ibex_tracer_enable=0" to + * This behaviour is controlled by the plusarg "cve2_tracer_enable". Use "cve2_tracer_enable=0" to * disable the tracer. * * The trace contains six columns, separated by tabs: @@ -34,7 +34,7 @@ * to the one produced by objdump. This simplifies the correlation between the static program * information from the objdump-generated disassembly, and the runtime information from this tracer. */ -module ibex_tracer ( +module cve2_tracer ( input logic clk_i, input logic rst_ni, @@ -79,7 +79,7 @@ module ibex_tracer ( logic [ 1:0] unused_rvfi_mode = rvfi_mode; logic [ 1:0] unused_rvfi_ixl = rvfi_ixl; - import ibex_tracer_pkg::*; + import cve2_tracer_pkg::*; int file_handle; string file_name; @@ -98,7 +98,7 @@ module ibex_tracer ( logic trace_log_enable; initial begin - if ($value$plusargs("ibex_tracer_enable=%b", trace_log_enable)) begin + if ($value$plusargs("cve2_tracer_enable=%b", trace_log_enable)) begin if (trace_log_enable == 1'b0) begin $display("%m: Instruction trace disabled."); end @@ -112,7 +112,7 @@ module ibex_tracer ( if (file_handle == 32'h0) begin string file_name_base = "trace_core"; - void'($value$plusargs("ibex_tracer_file_base=%s", file_name_base)); + void'($value$plusargs("cve2_tracer_file_base=%s", file_name_base)); $sformat(file_name, "%s_%h.log", file_name_base, hart_id_i); $display("%m: Writing execution trace to %s", file_name); diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer_pkg.sv similarity index 99% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer_pkg.sv rename to hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer_pkg.sv index 6dbbfc90..700dd37b 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_tracer_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_tracer_pkg.sv @@ -3,8 +3,8 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 -package ibex_tracer_pkg; - import ibex_pkg::*; +package cve2_tracer_pkg; + import cve2_pkg::*; parameter logic [1:0] OPCODE_C0 = 2'b00; parameter logic [1:0] OPCODE_C1 = 2'b01; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb.sv new file mode 100644 index 00000000..dee73f74 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/cve2_wb.sv @@ -0,0 +1,69 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +/** + * Writeback passthrough + * + * The writeback stage is not present therefore this module acts as + * a simple passthrough to write data direct to the register file. + */ + +`include "prim_assert.sv" +`include "dv_fcov_macros.svh" + +module cve2_wb #( +) ( + input logic clk_i, + input logic rst_ni, + input logic en_wb_i, + + input logic instr_is_compressed_id_i, + input logic instr_perf_count_id_i, + + output logic perf_instr_ret_wb_o, + output logic perf_instr_ret_compressed_wb_o, + + input logic [4:0] rf_waddr_id_i, + input logic [31:0] rf_wdata_id_i, + input logic rf_we_id_i, + + input logic [31:0] rf_wdata_lsu_i, + input logic rf_we_lsu_i, + + output logic [4:0] rf_waddr_wb_o, + output logic [31:0] rf_wdata_wb_o, + output logic rf_we_wb_o, + + input logic lsu_resp_valid_i, + input logic lsu_resp_err_i +); + + import cve2_pkg::*; + + // 0 == RF write from ID + // 1 == RF write from LSU + logic [31:0] rf_wdata_wb_mux [2]; + logic [1:0] rf_wdata_wb_mux_we; + + // without writeback stage just pass through register write signals + assign rf_waddr_wb_o = rf_waddr_id_i; + assign rf_wdata_wb_mux[0] = rf_wdata_id_i; + assign rf_wdata_wb_mux_we[0] = rf_we_id_i; + + // Increment instruction retire counters for valid instructions which are not lsu errors. + assign perf_instr_ret_wb_o = instr_perf_count_id_i & en_wb_i & + ~(lsu_resp_valid_i & lsu_resp_err_i); + assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & instr_is_compressed_id_i; + + assign rf_wdata_wb_mux[1] = rf_wdata_lsu_i; + assign rf_wdata_wb_mux_we[1] = rf_we_lsu_i; + + // RF write data can come from ID results (all RF writes that aren't because of loads will come + // from here) or the LSU (RF writes for load data) + assign rf_wdata_wb_o = ({32{rf_wdata_wb_mux_we[0]}} & rf_wdata_wb_mux[0]) | + ({32{rf_wdata_wb_mux_we[1]}} & rf_wdata_wb_mux[1]); + assign rf_we_wb_o = |rf_wdata_wb_mux_we; + + `ASSERT(RFWriteFromOneSourceOnly, $onehot0(rf_wdata_wb_mux_we)) +endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.f b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.f deleted file mode 100644 index 83e8396b..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_core.f +++ /dev/null @@ -1,17 +0,0 @@ -ibex_pkg.sv -ibex_alu.sv -ibex_compressed_decoder.sv -ibex_controller.sv -ibex_counter.sv -ibex_cs_registers.sv -ibex_decoder.sv -ibex_ex_block.sv -ibex_id_stage.sv -ibex_if_stage.sv -ibex_load_store_unit.sv -ibex_multdiv_slow.sv -ibex_multdiv_fast.sv -ibex_prefetch_buffer.sv -ibex_fetch_fifo.sv -ibex_register_file_ff.sv -ibex_core.sv diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_dummy_instr.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_dummy_instr.sv deleted file mode 100644 index ba33adc4..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_dummy_instr.sv +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * Dummy instruction module - * - * Provides pseudo-randomly inserted fake instructions for secure code obfuscation - */ - -// SEC_CM: CTRL_FLOW.UNPREDICTABLE -module ibex_dummy_instr import ibex_pkg::*; #( - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault -) ( - // Clock and reset - input logic clk_i, - input logic rst_ni, - - // Interface to CSRs - input logic dummy_instr_en_i, - input logic [2:0] dummy_instr_mask_i, - input logic dummy_instr_seed_en_i, - input logic [31:0] dummy_instr_seed_i, - - // Interface to IF stage - input logic fetch_valid_i, - input logic id_in_ready_i, - output logic insert_dummy_instr_o, - output logic [31:0] dummy_instr_data_o -); - - localparam int unsigned TIMEOUT_CNT_W = 5; - localparam int unsigned OP_W = 5; - - typedef enum logic [1:0] { - DUMMY_ADD = 2'b00, - DUMMY_MUL = 2'b01, - DUMMY_DIV = 2'b10, - DUMMY_AND = 2'b11 - } dummy_instr_e; - - typedef struct packed { - dummy_instr_e instr_type; - logic [OP_W-1:0] op_b; - logic [OP_W-1:0] op_a; - logic [TIMEOUT_CNT_W-1:0] cnt; - } lfsr_data_t; - localparam int unsigned LFSR_OUT_W = $bits(lfsr_data_t); - - lfsr_data_t lfsr_data; - logic [TIMEOUT_CNT_W-1:0] dummy_cnt_incr, dummy_cnt_threshold; - logic [TIMEOUT_CNT_W-1:0] dummy_cnt_d, dummy_cnt_q; - logic dummy_cnt_en; - logic lfsr_en; - logic [LFSR_OUT_W-1:0] lfsr_state; - logic insert_dummy_instr; - logic [6:0] dummy_set; - logic [2:0] dummy_opcode; - logic [31:0] dummy_instr; - logic [31:0] dummy_instr_seed_q, dummy_instr_seed_d; - - // Shift the LFSR every time we insert an instruction - assign lfsr_en = insert_dummy_instr & id_in_ready_i; - - assign dummy_instr_seed_d = dummy_instr_seed_q ^ dummy_instr_seed_i; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - dummy_instr_seed_q <= '0; - end else if (dummy_instr_seed_en_i) begin - dummy_instr_seed_q <= dummy_instr_seed_d; - end - end - - prim_lfsr #( - .LfsrDw ( LfsrWidth ), - .StateOutDw ( LFSR_OUT_W ), - .DefaultSeed ( RndCnstLfsrSeed ), - .StatePermEn ( 1'b1 ), - .StatePerm ( RndCnstLfsrPerm ) - ) lfsr_i ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .seed_en_i ( dummy_instr_seed_en_i ), - .seed_i ( dummy_instr_seed_d ), - .lfsr_en_i ( lfsr_en ), - .entropy_i ( '0 ), - .state_o ( lfsr_state ) - ); - - // Extract fields from LFSR - assign lfsr_data = lfsr_data_t'(lfsr_state); - - // Set count threshold for inserting a new instruction. This is the pseudo-random value from the - // LFSR with a mask applied (based on CSR config data) to shorten the period if required. - assign dummy_cnt_threshold = lfsr_data.cnt & {dummy_instr_mask_i,{TIMEOUT_CNT_W-3{1'b1}}}; - assign dummy_cnt_incr = dummy_cnt_q + {{TIMEOUT_CNT_W-1{1'b0}},1'b1}; - // Clear the counter everytime a new instruction is inserted - assign dummy_cnt_d = insert_dummy_instr ? '0 : dummy_cnt_incr; - // Increment the counter for each executed instruction while dummy instuctions are - // enabled. - assign dummy_cnt_en = dummy_instr_en_i & id_in_ready_i & - (fetch_valid_i | insert_dummy_instr); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - dummy_cnt_q <= '0; - end else if (dummy_cnt_en) begin - dummy_cnt_q <= dummy_cnt_d; - end - end - - // Insert a dummy instruction each time the counter hits the threshold - assign insert_dummy_instr = dummy_instr_en_i & (dummy_cnt_q == dummy_cnt_threshold); - - // Encode instruction - always_comb begin - unique case (lfsr_data.instr_type) - DUMMY_ADD: begin - dummy_set = 7'b0000000; - dummy_opcode = 3'b000; - end - DUMMY_MUL: begin - dummy_set = 7'b0000001; - dummy_opcode = 3'b000; - end - DUMMY_DIV: begin - dummy_set = 7'b0000001; - dummy_opcode = 3'b100; - end - DUMMY_AND: begin - dummy_set = 7'b0000000; - dummy_opcode = 3'b111; - end - default: begin - dummy_set = 7'b0000000; - dummy_opcode = 3'b000; - end - endcase - end - - // SET RS2 RS1 OP RD - assign dummy_instr = {dummy_set, lfsr_data.op_b, lfsr_data.op_a, dummy_opcode, 5'h00, 7'h33}; - - // Assign outputs - assign insert_dummy_instr_o = insert_dummy_instr; - assign dummy_instr_data_o = dummy_instr; - -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_icache.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_icache.sv deleted file mode 100644 index c15a29b5..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_icache.sv +++ /dev/null @@ -1,1165 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * Instruction cache - * - * Provides an instruction cache along with cache management, instruction buffering and prefetching - */ - -`include "prim_assert.sv" - -module ibex_icache import ibex_pkg::*; #( - parameter bit ICacheECC = 1'b0, - parameter bit ResetAll = 1'b0, - parameter int unsigned BusSizeECC = BUS_SIZE, - parameter int unsigned TagSizeECC = IC_TAG_SIZE, - parameter int unsigned LineSizeECC = IC_LINE_SIZE, - // Only cache branch targets - parameter bit BranchCache = 1'b0 -) ( - // Clock and reset - input logic clk_i, - input logic rst_ni, - - // Signal that the core would like instructions - input logic req_i, - - // Set the cache's address counter - input logic branch_i, - input logic branch_mispredict_i, - input logic [31:0] mispredict_addr_i, - input logic [31:0] addr_i, - - // IF stage interface: Pass fetched instructions to the core - input logic ready_i, - output logic valid_o, - output logic [31:0] rdata_o, - output logic [31:0] addr_o, - output logic err_o, - output logic err_plus2_o, - - // Instruction memory / interconnect interface: Fetch instruction data from memory - output logic instr_req_o, - input logic instr_gnt_i, - output logic [31:0] instr_addr_o, - input logic [BUS_SIZE-1:0] instr_rdata_i, - input logic instr_err_i, - input logic instr_rvalid_i, - - // RAM IO - output logic [IC_NUM_WAYS-1:0] ic_tag_req_o, - output logic ic_tag_write_o, - output logic [IC_INDEX_W-1:0] ic_tag_addr_o, - output logic [TagSizeECC-1:0] ic_tag_wdata_o, - input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], - output logic [IC_NUM_WAYS-1:0] ic_data_req_o, - output logic ic_data_write_o, - output logic [IC_INDEX_W-1:0] ic_data_addr_o, - output logic [LineSizeECC-1:0] ic_data_wdata_o, - input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], - input logic ic_scr_key_valid_i, - - // Cache status - input logic icache_enable_i, - input logic icache_inval_i, - output logic busy_o, - output logic ecc_error_o -); - - // Number of fill buffers (must be >= 2) - localparam int unsigned NUM_FB = 4; - // Request throttling threshold - localparam int unsigned FB_THRESHOLD = NUM_FB - 2; - - // Prefetch signals - logic [ADDR_W-1:0] lookup_addr_aligned; - logic [ADDR_W-1:0] prefetch_addr_d, prefetch_addr_q; - logic prefetch_addr_en; - logic branch_or_mispredict; - // Cache pipelipe IC0 signals - logic lookup_throttle; - logic lookup_req_ic0; - logic [ADDR_W-1:0] lookup_addr_ic0; - logic [IC_INDEX_W-1:0] lookup_index_ic0; - logic fill_req_ic0; - logic [IC_INDEX_W-1:0] fill_index_ic0; - logic [IC_TAG_SIZE-1:0] fill_tag_ic0; - logic [IC_LINE_SIZE-1:0] fill_wdata_ic0; - logic lookup_grant_ic0; - logic lookup_actual_ic0; - logic fill_grant_ic0; - logic tag_req_ic0; - logic [IC_INDEX_W-1:0] tag_index_ic0; - logic [IC_NUM_WAYS-1:0] tag_banks_ic0; - logic tag_write_ic0; - logic [TagSizeECC-1:0] tag_wdata_ic0; - logic data_req_ic0; - logic [IC_INDEX_W-1:0] data_index_ic0; - logic [IC_NUM_WAYS-1:0] data_banks_ic0; - logic data_write_ic0; - logic [LineSizeECC-1:0] data_wdata_ic0; - // Cache pipelipe IC1 signals - logic [TagSizeECC-1:0] tag_rdata_ic1 [IC_NUM_WAYS]; - logic [LineSizeECC-1:0] data_rdata_ic1 [IC_NUM_WAYS]; - logic [LineSizeECC-1:0] hit_data_ecc_ic1; - logic [IC_LINE_SIZE-1:0] hit_data_ic1; - logic lookup_valid_ic1; - logic [ADDR_W-1:IC_INDEX_HI+1] lookup_addr_ic1; - logic [IC_NUM_WAYS-1:0] tag_match_ic1; - logic tag_hit_ic1; - logic [IC_NUM_WAYS-1:0] tag_invalid_ic1; - logic [IC_NUM_WAYS-1:0] lowest_invalid_way_ic1; - logic [IC_NUM_WAYS-1:0] round_robin_way_ic1, round_robin_way_q; - logic [IC_NUM_WAYS-1:0] sel_way_ic1; - logic ecc_err_ic1; - logic ecc_write_req; - logic [IC_NUM_WAYS-1:0] ecc_write_ways; - logic [IC_INDEX_W-1:0] ecc_write_index; - // Fill buffer signals - logic [$clog2(NUM_FB)-1:0] fb_fill_level; - logic fill_cache_new; - logic fill_new_alloc; - logic fill_spec_req, fill_spec_done, fill_spec_hold; - logic [NUM_FB-1:0][NUM_FB-1:0] fill_older_d, fill_older_q; - logic [NUM_FB-1:0] fill_alloc_sel, fill_alloc; - logic [NUM_FB-1:0] fill_busy_d, fill_busy_q; - logic [NUM_FB-1:0] fill_done; - logic [NUM_FB-1:0] fill_in_ic1; - logic [NUM_FB-1:0] fill_stale_d, fill_stale_q; - logic [NUM_FB-1:0] fill_cache_d, fill_cache_q; - logic [NUM_FB-1:0] fill_hit_ic1, fill_hit_d, fill_hit_q; - logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_ext_cnt_d, fill_ext_cnt_q; - logic [NUM_FB-1:0] fill_ext_hold_d, fill_ext_hold_q; - logic [NUM_FB-1:0] fill_ext_done_d, fill_ext_done_q; - logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_rvd_cnt_d, fill_rvd_cnt_q; - logic [NUM_FB-1:0] fill_rvd_done; - logic [NUM_FB-1:0] fill_ram_done_d, fill_ram_done_q; - logic [NUM_FB-1:0] fill_out_grant; - logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_out_cnt_d, fill_out_cnt_q; - logic [NUM_FB-1:0] fill_out_done; - logic [NUM_FB-1:0] fill_ext_req, fill_rvd_exp, fill_ram_req, fill_out_req; - logic [NUM_FB-1:0] fill_data_sel, fill_data_reg; - logic [NUM_FB-1:0] fill_data_hit, fill_data_rvd; - logic [NUM_FB-1:0][IC_LINE_BEATS_W-1:0] fill_ext_off, fill_rvd_off; - logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_ext_beat, fill_rvd_beat; - logic [NUM_FB-1:0] fill_ext_arb, fill_ram_arb, fill_out_arb; - logic [NUM_FB-1:0] fill_rvd_arb; - logic [NUM_FB-1:0] fill_entry_en; - logic [NUM_FB-1:0] fill_addr_en; - logic [NUM_FB-1:0] fill_way_en; - logic [NUM_FB-1:0][IC_LINE_BEATS-1:0] fill_data_en; - logic [NUM_FB-1:0][IC_LINE_BEATS-1:0] fill_err_d, fill_err_q; - logic [ADDR_W-1:0] fill_addr_q [NUM_FB]; - logic [IC_NUM_WAYS-1:0] fill_way_q [NUM_FB]; - logic [IC_LINE_SIZE-1:0] fill_data_d [NUM_FB]; - logic [IC_LINE_SIZE-1:0] fill_data_q [NUM_FB]; - logic [ADDR_W-1:BUS_W] fill_ext_req_addr; - logic [ADDR_W-1:0] fill_ram_req_addr; - logic [IC_NUM_WAYS-1:0] fill_ram_req_way; - logic [IC_LINE_SIZE-1:0] fill_ram_req_data; - logic [IC_LINE_SIZE-1:0] fill_out_data; - logic [IC_LINE_BEATS-1:0] fill_out_err; - // External req signals - logic instr_req; - logic [ADDR_W-1:BUS_W] instr_addr; - // Data output signals - logic skid_complete_instr; - logic skid_ready; - logic output_compressed; - logic skid_valid_d, skid_valid_q, skid_en; - logic [15:0] skid_data_d, skid_data_q; - logic skid_err_q; - logic output_valid; - logic addr_incr_two; - logic output_addr_en; - logic [ADDR_W-1:1] output_addr_incr; - logic [ADDR_W-1:1] output_addr_d, output_addr_q; - logic [15:0] output_data_lo, output_data_hi; - logic data_valid, output_ready; - logic [IC_LINE_SIZE-1:0] line_data; - logic [IC_LINE_BEATS-1:0] line_err; - logic [31:0] line_data_muxed; - logic line_err_muxed; - logic [31:0] output_data; - logic output_err; - // Invalidations - logic start_inval, inval_done; - logic inval_lock, inval_req_d, inval_req_q; - logic reset_inval_q; - logic inval_prog_d, inval_prog_q; - logic [IC_INDEX_W-1:0] inval_index_d, inval_index_q; - - ////////////////////////// - // Instruction prefetch // - ////////////////////////// - - assign branch_or_mispredict = branch_i | branch_mispredict_i; - - assign lookup_addr_aligned = {lookup_addr_ic0[ADDR_W-1:IC_LINE_W], {IC_LINE_W{1'b0}}}; - - // The prefetch address increments by one cache line for each granted request. - // This address is also updated if there is a branch that is not granted, since the target - // address (addr_i) is only valid for one cycle while branch_i is high. - - // The captured branch target address is not forced to be aligned since the offset in the cache - // line must also be recorded for later use by the fill buffers. - assign prefetch_addr_d = - lookup_grant_ic0 ? (lookup_addr_aligned + - {{ADDR_W-IC_LINE_W-1{1'b0}}, 1'b1, {IC_LINE_W{1'b0}}}) : - branch_i ? addr_i : - mispredict_addr_i; - - assign prefetch_addr_en = branch_or_mispredict | lookup_grant_ic0; - - if (ResetAll) begin : g_prefetch_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - prefetch_addr_q <= '0; - end else if (prefetch_addr_en) begin - prefetch_addr_q <= prefetch_addr_d; - end - end - end else begin : g_prefetch_addr_nr - always_ff @(posedge clk_i) begin - if (prefetch_addr_en) begin - prefetch_addr_q <= prefetch_addr_d; - end - end - end - - //////////////////////// - // Pipeline stage IC0 // - //////////////////////// - - // Cache lookup - assign lookup_throttle = (fb_fill_level > FB_THRESHOLD[$clog2(NUM_FB)-1:0]); - - assign lookup_req_ic0 = req_i & ~&fill_busy_q & (branch_or_mispredict | ~lookup_throttle) & - ~ecc_write_req; - assign lookup_addr_ic0 = branch_i ? addr_i : - branch_mispredict_i ? mispredict_addr_i : - prefetch_addr_q; - assign lookup_index_ic0 = lookup_addr_ic0[IC_INDEX_HI:IC_LINE_W]; - - // Cache write - assign fill_req_ic0 = (|fill_ram_req); - assign fill_index_ic0 = fill_ram_req_addr[IC_INDEX_HI:IC_LINE_W]; - assign fill_tag_ic0 = {(~inval_prog_q & ~ecc_write_req), - fill_ram_req_addr[ADDR_W-1:IC_INDEX_HI+1]}; - assign fill_wdata_ic0 = fill_ram_req_data; - - // Arbitrated signals - lookups have highest priority - assign lookup_grant_ic0 = lookup_req_ic0; - assign fill_grant_ic0 = fill_req_ic0 & ~lookup_req_ic0 & ~inval_prog_q & - ~ecc_write_req; - // Qualified lookup grant to mask ram signals in IC1 if access was not made - assign lookup_actual_ic0 = lookup_grant_ic0 & icache_enable_i & ~inval_prog_q & - ~icache_inval_i & ~inval_lock & ~start_inval; - - // Tagram - assign tag_req_ic0 = lookup_req_ic0 | fill_req_ic0 | inval_prog_q | ecc_write_req; - assign tag_index_ic0 = inval_prog_q ? inval_index_q : - ecc_write_req ? ecc_write_index : - fill_grant_ic0 ? fill_index_ic0 : - lookup_index_ic0; - assign tag_banks_ic0 = ecc_write_req ? ecc_write_ways : - fill_grant_ic0 ? fill_ram_req_way : - {IC_NUM_WAYS{1'b1}}; - assign tag_write_ic0 = fill_grant_ic0 | inval_prog_q | ecc_write_req; - - // Dataram - assign data_req_ic0 = lookup_req_ic0 | fill_req_ic0; - assign data_index_ic0 = tag_index_ic0; - assign data_banks_ic0 = tag_banks_ic0; - assign data_write_ic0 = tag_write_ic0; - - // Append ECC checkbits to write data if required - if (ICacheECC) begin : gen_ecc_wdata - // SEC_CM: ICACHE.MEM.INTEGRITY - // Tagram ECC - // Reuse the same ecc encoding module for larger cache sizes by padding with zeros - logic [21:0] tag_ecc_input_padded; - logic [27:0] tag_ecc_output_padded; - logic [22-IC_TAG_SIZE:0] unused_tag_ecc_output; - - assign tag_ecc_input_padded = {{22-IC_TAG_SIZE{1'b0}},fill_tag_ic0}; - assign unused_tag_ecc_output = tag_ecc_output_padded[21:IC_TAG_SIZE-1]; - - prim_secded_inv_28_22_enc tag_ecc_enc ( - .data_i (tag_ecc_input_padded), - .data_o (tag_ecc_output_padded) - ); - - assign tag_wdata_ic0 = {tag_ecc_output_padded[27:22],tag_ecc_output_padded[IC_TAG_SIZE-1:0]}; - - // Dataram ECC - for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks - prim_secded_inv_39_32_enc data_ecc_enc ( - .data_i (fill_wdata_ic0[bank*BUS_SIZE+:BUS_SIZE]), - .data_o (data_wdata_ic0[bank*BusSizeECC+:BusSizeECC]) - ); - end - - end else begin : gen_noecc_wdata - assign tag_wdata_ic0 = fill_tag_ic0; - assign data_wdata_ic0 = fill_wdata_ic0; - end - - //////////////// - // IC0 -> IC1 // - //////////////// - - // Tag RAMs outputs - assign ic_tag_req_o = {IC_NUM_WAYS{tag_req_ic0}} & tag_banks_ic0; - assign ic_tag_write_o = tag_write_ic0; - assign ic_tag_addr_o = tag_index_ic0; - assign ic_tag_wdata_o = tag_wdata_ic0; - - // Tag RAMs inputs - assign tag_rdata_ic1 = ic_tag_rdata_i; - - // Data RAMs outputs - assign ic_data_req_o = {IC_NUM_WAYS{data_req_ic0}} & data_banks_ic0; - assign ic_data_write_o = data_write_ic0; - assign ic_data_addr_o = data_index_ic0; - assign ic_data_wdata_o = data_wdata_ic0; - - // Data RAMs inputs - assign data_rdata_ic1 = ic_data_rdata_i; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - lookup_valid_ic1 <= 1'b0; - end else begin - lookup_valid_ic1 <= lookup_actual_ic0; - end - end - - if (ResetAll) begin : g_lookup_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - lookup_addr_ic1 <= '0; - fill_in_ic1 <= '0; - end else if (lookup_grant_ic0) begin - lookup_addr_ic1 <= lookup_addr_ic0[ADDR_W-1:IC_INDEX_HI+1]; - fill_in_ic1 <= fill_alloc_sel; - end - end - end else begin : g_lookup_addr_nr - always_ff @(posedge clk_i) begin - if (lookup_grant_ic0) begin - lookup_addr_ic1 <= lookup_addr_ic0[ADDR_W-1:IC_INDEX_HI+1]; - fill_in_ic1 <= fill_alloc_sel; - end - end - end - - //////////////////////// - // Pipeline stage IC1 // - //////////////////////// - - // Tag matching - for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_tag_match - assign tag_match_ic1[way] = (tag_rdata_ic1[way][IC_TAG_SIZE-1:0] == - {1'b1,lookup_addr_ic1[ADDR_W-1:IC_INDEX_HI+1]}); - assign tag_invalid_ic1[way] = ~tag_rdata_ic1[way][IC_TAG_SIZE-1]; - end - - assign tag_hit_ic1 = |tag_match_ic1; - - // Hit data mux - always_comb begin - hit_data_ecc_ic1 = 'b0; - for (int way = 0; way < IC_NUM_WAYS; way++) begin - if (tag_match_ic1[way]) begin - hit_data_ecc_ic1 |= data_rdata_ic1[way]; - end - end - end - - // Way selection for allocations to the cache (onehot signals) - // 1 first invalid way - // 2 global round-robin (pseudorandom) way - assign lowest_invalid_way_ic1[0] = tag_invalid_ic1[0]; - assign round_robin_way_ic1[0] = round_robin_way_q[IC_NUM_WAYS-1]; - for (genvar way = 1; way < IC_NUM_WAYS; way++) begin : gen_lowest_way - assign lowest_invalid_way_ic1[way] = tag_invalid_ic1[way] & ~|tag_invalid_ic1[way-1:0]; - assign round_robin_way_ic1[way] = round_robin_way_q[way-1]; - end - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - round_robin_way_q <= {{IC_NUM_WAYS-1{1'b0}}, 1'b1}; - end else if (lookup_valid_ic1) begin - round_robin_way_q <= round_robin_way_ic1; - end - end - - assign sel_way_ic1 = |tag_invalid_ic1 ? lowest_invalid_way_ic1 : - round_robin_way_q; - - // ECC checking logic - if (ICacheECC) begin : gen_data_ecc_checking - // SEC_CM: ICACHE.MEM.INTEGRITY - logic [IC_NUM_WAYS-1:0] tag_err_ic1; - logic [IC_LINE_BEATS*2-1:0] data_err_ic1; - logic ecc_correction_write_d, ecc_correction_write_q; - logic [IC_NUM_WAYS-1:0] ecc_correction_ways_d, ecc_correction_ways_q; - logic [IC_INDEX_W-1:0] lookup_index_ic1, ecc_correction_index_q; - - // Tag ECC checking - for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_tag_ecc - logic [1:0] tag_err_bank_ic1; - logic [27:0] tag_rdata_padded_ic1; - - // Expand the tag rdata with extra padding if the tag size is less than the maximum - assign tag_rdata_padded_ic1 = {tag_rdata_ic1[way][TagSizeECC-1-:6], - {22-IC_TAG_SIZE{1'b0}}, - tag_rdata_ic1[way][IC_TAG_SIZE-1:0]}; - - prim_secded_inv_28_22_dec data_ecc_dec ( - .data_i (tag_rdata_padded_ic1), - .data_o (), - .syndrome_o (), - .err_o (tag_err_bank_ic1) - ); - assign tag_err_ic1[way] = |tag_err_bank_ic1; - end - - // Data ECC checking - // Note - could generate for all ways and mux after - for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks - prim_secded_inv_39_32_dec data_ecc_dec ( - .data_i (hit_data_ecc_ic1[bank*BusSizeECC+:BusSizeECC]), - .data_o (), - .syndrome_o (), - .err_o (data_err_ic1[bank*2+:2]) - ); - - assign hit_data_ic1[bank*BUS_SIZE+:BUS_SIZE] = - hit_data_ecc_ic1[bank*BusSizeECC+:BUS_SIZE]; - - end - - // Tag ECC across all ways is always expected to be correct so the check does not need to be - // qualified by hit or tag valid. Initial (invalid with correct ECC) tags are written on reset - // and all further tag writes produce correct ECC. For data ECC no initialisation is done on - // reset so unused data (in particular those ways that don't have a valid tag) may have - // incorrect ECC. We only check data ECC where tags indicate it is valid and we have hit on it. - assign ecc_err_ic1 = lookup_valid_ic1 & (((|data_err_ic1) & tag_hit_ic1) | (|tag_err_ic1)); - - // Error correction - // All ways will be invalidated on a tag error to prevent X-propagation from data_err_ic1 on - // spurious hits. Also prevents the same line being allocated twice when there was a true - // hit and a spurious hit. - assign ecc_correction_ways_d = {IC_NUM_WAYS{|tag_err_ic1}} | - (tag_match_ic1 & {IC_NUM_WAYS{|data_err_ic1}}); - assign ecc_correction_write_d = ecc_err_ic1; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - ecc_correction_write_q <= 1'b0; - end else begin - ecc_correction_write_q <= ecc_correction_write_d; - end - end - - // The index is required in IC1 only when ECC is configured so is registered here - if (ResetAll) begin : g_lookup_ind_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - lookup_index_ic1 <= '0; - end else if (lookup_grant_ic0) begin - lookup_index_ic1 <= lookup_addr_ic0[IC_INDEX_HI-:IC_INDEX_W]; - end - end - end else begin : g_lookup_ind_nr - always_ff @(posedge clk_i) begin - if (lookup_grant_ic0) begin - lookup_index_ic1 <= lookup_addr_ic0[IC_INDEX_HI-:IC_INDEX_W]; - end - end - end - - // Store the ways with errors to be invalidated - if (ResetAll) begin : g_ecc_correction_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - ecc_correction_ways_q <= '0; - ecc_correction_index_q <= '0; - end else if (ecc_err_ic1) begin - ecc_correction_ways_q <= ecc_correction_ways_d; - ecc_correction_index_q <= lookup_index_ic1; - end - end - end else begin : g_ecc_correction_nr - always_ff @(posedge clk_i) begin - if (ecc_err_ic1) begin - ecc_correction_ways_q <= ecc_correction_ways_d; - ecc_correction_index_q <= lookup_index_ic1; - end - end - end - - assign ecc_write_req = ecc_correction_write_q; - assign ecc_write_ways = ecc_correction_ways_q; - assign ecc_write_index = ecc_correction_index_q; - - assign ecc_error_o = ecc_err_ic1; - end else begin : gen_no_data_ecc - assign ecc_err_ic1 = 1'b0; - assign ecc_write_req = 1'b0; - assign ecc_write_ways = '0; - assign ecc_write_index = '0; - assign hit_data_ic1 = hit_data_ecc_ic1; - - assign ecc_error_o = 1'b0; - end - - /////////////////////////////// - // Cache allocation decision // - /////////////////////////////// - - if (BranchCache) begin : gen_caching_logic - - // Cache branch target + a number of subsequent lines - localparam int unsigned CACHE_AHEAD = 2; - localparam int unsigned CACHE_CNT_W = (CACHE_AHEAD == 1) ? 1 : $clog2(CACHE_AHEAD) + 1; - logic cache_cnt_dec; - logic [CACHE_CNT_W-1:0] cache_cnt_d, cache_cnt_q; - - assign cache_cnt_dec = lookup_grant_ic0 & (|cache_cnt_q); - assign cache_cnt_d = branch_i ? CACHE_AHEAD[CACHE_CNT_W-1:0] : - (cache_cnt_q - {{CACHE_CNT_W-1{1'b0}},cache_cnt_dec}); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - cache_cnt_q <= '0; - end else begin - cache_cnt_q <= cache_cnt_d; - end - end - - assign fill_cache_new = (branch_i | (|cache_cnt_q)) & icache_enable_i & - ~icache_inval_i & ~inval_lock & ~inval_prog_q; - - end else begin : gen_cache_all - - // Cache all missing fetches - assign fill_cache_new = icache_enable_i & ~start_inval & ~inval_prog_q; - end - - ////////////////////////// - // Fill buffer tracking // - ////////////////////////// - - always_comb begin - fb_fill_level = '0; - for (int i = 0; i < NUM_FB; i++) begin - if (fill_busy_q[i] & ~fill_stale_q[i]) begin - fb_fill_level += {{$clog2(NUM_FB) - 1{1'b0}}, 1'b1}; - end - end - end - - // Allocate a new buffer for every granted lookup - assign fill_new_alloc = lookup_grant_ic0; - // Track whether a speculative external request was made from IC0, and whether it was granted - // Speculative requests are only made for branches, or if the cache is disabled - assign fill_spec_req = (~icache_enable_i | branch_or_mispredict) & ~|fill_ext_req; - assign fill_spec_done = fill_spec_req & instr_gnt_i; - assign fill_spec_hold = fill_spec_req & ~instr_gnt_i; - - for (genvar fb = 0; fb < NUM_FB; fb++) begin : gen_fbs - - ///////////////////////////// - // Fill buffer allocations // - ///////////////////////////// - - // Allocate the lowest available buffer - if (fb == 0) begin : gen_fb_zero - assign fill_alloc_sel[fb] = ~fill_busy_q[fb]; - end else begin : gen_fb_rest - assign fill_alloc_sel[fb] = ~fill_busy_q[fb] & (&fill_busy_q[fb-1:0]); - end - - assign fill_alloc[fb] = fill_alloc_sel[fb] & fill_new_alloc; - assign fill_busy_d[fb] = fill_alloc[fb] | (fill_busy_q[fb] & ~fill_done[fb]); - - // Track which other fill buffers are older than this one (for age-based arbitration) - // TODO sparsify - assign fill_older_d[fb] = (fill_alloc[fb] ? fill_busy_q : fill_older_q[fb]) & ~fill_done; - - // A fill buffer can release once all its actions are completed - // all data written to the cache (unless hit or error) - assign fill_done[fb] = (fill_ram_done_q[fb] | fill_hit_q[fb] | ~fill_cache_q[fb] | - (|fill_err_q[fb])) & - // all data output unless stale due to intervening branch - (fill_out_done[fb] | fill_stale_q[fb] | branch_or_mispredict) & - // all external requests completed - fill_rvd_done[fb]; - - ///////////////////////////////// - // Fill buffer status tracking // - ///////////////////////////////// - - // Track staleness (requests become stale when a branch intervenes) - assign fill_stale_d[fb] = fill_busy_q[fb] & (branch_or_mispredict | fill_stale_q[fb]); - // Track whether or not this request should allocate to the cache - // Any invalidation or disabling of the cache while the buffer is busy will stop allocation - assign fill_cache_d[fb] = (fill_alloc[fb] & fill_cache_new) | - (fill_cache_q[fb] & fill_busy_q[fb] & - icache_enable_i & ~icache_inval_i & ~inval_lock); - // Record whether the request hit in the cache - assign fill_hit_ic1[fb] = lookup_valid_ic1 & fill_in_ic1[fb] & tag_hit_ic1 & ~ecc_err_ic1; - assign fill_hit_d[fb] = fill_hit_ic1[fb] | (fill_hit_q[fb] & fill_busy_q[fb]); - - /////////////////////////////////////////// - // Fill buffer external request tracking // - /////////////////////////////////////////// - - // Make an external request - assign fill_ext_req[fb] = fill_busy_q[fb] & ~fill_ext_done_d[fb]; - - // Count the number of completed external requests (each line requires IC_LINE_BEATS requests) - assign fill_ext_cnt_d[fb] = fill_alloc[fb] ? - {{IC_LINE_BEATS_W{1'b0}},fill_spec_done} : - (fill_ext_cnt_q[fb] + {{IC_LINE_BEATS_W{1'b0}}, - fill_ext_arb[fb] & instr_gnt_i}); - // External request must be held until granted - assign fill_ext_hold_d[fb] = (fill_alloc[fb] & fill_spec_hold) | - (fill_ext_arb[fb] & ~instr_gnt_i); - // External requests are completed when the counter is filled or when the request is cancelled - assign fill_ext_done_d[fb] = (fill_ext_cnt_q[fb][IC_LINE_BEATS_W] | - // external requests are considered complete if the request hit - fill_hit_ic1[fb] | fill_hit_q[fb] | - // cancel if the line won't be cached and, it is stale - (~fill_cache_q[fb] & (branch_or_mispredict | fill_stale_q[fb] | - // or we're already at the end of the line - fill_ext_beat[fb][IC_LINE_BEATS_W]))) & - // can't cancel while we are waiting for a grant on the bus - ~fill_ext_hold_q[fb] & fill_busy_q[fb]; - // Track whether this fill buffer expects to receive beats of data - assign fill_rvd_exp[fb] = fill_busy_q[fb] & ~fill_rvd_done[fb]; - // Count the number of rvalid beats received - assign fill_rvd_cnt_d[fb] = fill_alloc[fb] ? '0 : - (fill_rvd_cnt_q[fb] + - {{IC_LINE_BEATS_W{1'b0}},fill_rvd_arb[fb]}); - // External data is complete when all issued external requests have received their data - assign fill_rvd_done[fb] = (fill_ext_done_q[fb] & ~fill_ext_hold_q[fb]) & - (fill_rvd_cnt_q[fb] == fill_ext_cnt_q[fb]); - - ////////////////////////////////////// - // Fill buffer data output tracking // - ////////////////////////////////////// - - // Send data to the IF stage for requests that are not stale, have not completed their - // data output, and have data available to send. - // Data is available if: - // - The request hit in the cache - // - Buffered data is available (fill_rvd_cnt_q is ahead of fill_out_cnt_q) - // - Data is available from the bus this cycle (fill_rvd_arb) - assign fill_out_req[fb] = fill_busy_q[fb] & ~fill_stale_q[fb] & ~fill_out_done[fb] & - (fill_hit_ic1[fb] | fill_hit_q[fb] | - (fill_rvd_beat[fb] > fill_out_cnt_q[fb]) | fill_rvd_arb[fb]); - - // Calculate when a beat of data is output. Any ECC error squashes the output that cycle. - assign fill_out_grant[fb] = fill_out_arb[fb] & output_ready; - - // Count the beats of data output to the IF stage - assign fill_out_cnt_d[fb] = fill_alloc[fb] ? {1'b0,lookup_addr_ic0[IC_LINE_W-1:BUS_W]} : - (fill_out_cnt_q[fb] + - {{IC_LINE_BEATS_W{1'b0}},fill_out_grant[fb]}); - // Data output complete when the counter fills - assign fill_out_done[fb] = fill_out_cnt_q[fb][IC_LINE_BEATS_W]; - - ////////////////////////////////////// - // Fill buffer ram request tracking // - ////////////////////////////////////// - - // make a fill request once all data beats received - assign fill_ram_req[fb] = fill_busy_q[fb] & fill_rvd_cnt_q[fb][IC_LINE_BEATS_W] & - // unless the request hit, was non-allocating or got an error - ~fill_hit_q[fb] & fill_cache_q[fb] & ~|fill_err_q[fb] & - // or the request was already completed - ~fill_ram_done_q[fb]; - - // Record when a cache allocation request has been completed - assign fill_ram_done_d[fb] = fill_ram_arb[fb] | (fill_ram_done_q[fb] & fill_busy_q[fb]); - - ////////////////////////////// - // Fill buffer line offsets // - ////////////////////////////// - - // When we branch into the middle of a line, the output count will not start from zero. This - // beat count is used to know which incoming rdata beats are relevant. - assign fill_ext_beat[fb] = {1'b0,fill_addr_q[fb][IC_LINE_W-1:BUS_W]} + - fill_ext_cnt_q[fb][IC_LINE_BEATS_W:0]; - assign fill_ext_off[fb] = fill_ext_beat[fb][IC_LINE_BEATS_W-1:0]; - assign fill_rvd_beat[fb] = {1'b0,fill_addr_q[fb][IC_LINE_W-1:BUS_W]} + - fill_rvd_cnt_q[fb][IC_LINE_BEATS_W:0]; - assign fill_rvd_off[fb] = fill_rvd_beat[fb][IC_LINE_BEATS_W-1:0]; - - ///////////////////////////// - // Fill buffer arbitration // - ///////////////////////////// - - // Age based arbitration - all these signals are one-hot - assign fill_ext_arb[fb] = fill_ext_req[fb] & ~|(fill_ext_req & fill_older_q[fb]); - assign fill_ram_arb[fb] = fill_ram_req[fb] & fill_grant_ic0 & - ~|(fill_ram_req & fill_older_q[fb]); - // Calculate which fill buffer is the oldest one which still needs to output data to IF - assign fill_data_sel[fb] = ~|(fill_busy_q & ~fill_out_done & ~fill_stale_q & - fill_older_q[fb]); - // Arbitrate the request which has data available to send, and is the oldest outstanding - assign fill_out_arb[fb] = fill_out_req[fb] & fill_data_sel[fb]; - // Assign incoming rvalid data to the oldest fill buffer expecting it - assign fill_rvd_arb[fb] = instr_rvalid_i & fill_rvd_exp[fb] & - ~|(fill_rvd_exp & fill_older_q[fb]); - - ///////////////////////////// - // Fill buffer data muxing // - ///////////////////////////// - - // Output data muxing controls - // 1. Select data from the fill buffer data register - assign fill_data_reg[fb] = fill_busy_q[fb] & ~fill_stale_q[fb] & - ~fill_out_done[fb] & fill_data_sel[fb] & - // The incoming data is already ahead of the output count - ((fill_rvd_beat[fb] > fill_out_cnt_q[fb]) | fill_hit_q[fb] | - (|fill_err_q[fb])); - // 2. Select IC1 hit data - assign fill_data_hit[fb] = fill_busy_q[fb] & fill_hit_ic1[fb] & fill_data_sel[fb]; - // 3. Select incoming instr_rdata_i - assign fill_data_rvd[fb] = fill_busy_q[fb] & fill_rvd_arb[fb] & ~fill_hit_q[fb] & - ~fill_hit_ic1[fb] & ~fill_stale_q[fb] & ~fill_out_done[fb] & - // The incoming data lines up with the output count - (fill_rvd_beat[fb] == fill_out_cnt_q[fb]) & fill_data_sel[fb]; - - - /////////////////////////// - // Fill buffer registers // - /////////////////////////// - - // Fill buffer general enable - assign fill_entry_en[fb] = fill_alloc[fb] | fill_busy_q[fb]; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_busy_q[fb] <= 1'b0; - fill_older_q[fb] <= '0; - fill_stale_q[fb] <= 1'b0; - fill_cache_q[fb] <= 1'b0; - fill_hit_q[fb] <= 1'b0; - fill_ext_cnt_q[fb] <= '0; - fill_ext_hold_q[fb] <= 1'b0; - fill_ext_done_q[fb] <= 1'b0; - fill_rvd_cnt_q[fb] <= '0; - fill_ram_done_q[fb] <= 1'b0; - fill_out_cnt_q[fb] <= '0; - end else if (fill_entry_en[fb]) begin - fill_busy_q[fb] <= fill_busy_d[fb]; - fill_older_q[fb] <= fill_older_d[fb]; - fill_stale_q[fb] <= fill_stale_d[fb]; - fill_cache_q[fb] <= fill_cache_d[fb]; - fill_hit_q[fb] <= fill_hit_d[fb]; - fill_ext_cnt_q[fb] <= fill_ext_cnt_d[fb]; - fill_ext_hold_q[fb] <= fill_ext_hold_d[fb]; - fill_ext_done_q[fb] <= fill_ext_done_d[fb]; - fill_rvd_cnt_q[fb] <= fill_rvd_cnt_d[fb]; - fill_ram_done_q[fb] <= fill_ram_done_d[fb]; - fill_out_cnt_q[fb] <= fill_out_cnt_d[fb]; - end - end - - //////////////////////////////////////// - // Fill buffer address / data storage // - //////////////////////////////////////// - - assign fill_addr_en[fb] = fill_alloc[fb]; - assign fill_way_en[fb] = (lookup_valid_ic1 & fill_in_ic1[fb]); - - if (ResetAll) begin : g_fill_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_addr_q[fb] <= '0; - end else if (fill_addr_en[fb]) begin - fill_addr_q[fb] <= lookup_addr_ic0; - end - end - end else begin : g_fill_addr_nr - always_ff @(posedge clk_i) begin - if (fill_addr_en[fb]) begin - fill_addr_q[fb] <= lookup_addr_ic0; - end - end - end - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_way_q[fb] <= '0; - end else if (fill_way_en[fb]) begin - fill_way_q[fb] <= sel_way_ic1; - end - end - - // Data either comes from the cache or the bus. If there was an ECC error, we must take - // the incoming bus data since the cache hit data is corrupted. - assign fill_data_d[fb] = fill_hit_ic1[fb] ? hit_data_ic1 : - {IC_LINE_BEATS{instr_rdata_i}}; - - for (genvar b = 0; b < IC_LINE_BEATS; b++) begin : gen_data_buf - // Error tracking (per beat) - assign fill_err_d[fb][b] = (fill_rvd_arb[fb] & instr_err_i & - (fill_rvd_off[fb] == b[IC_LINE_BEATS_W-1:0])) | - // Hold the error once recorded - (fill_busy_q[fb] & fill_err_q[fb][b]); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_err_q[fb][b] <= '0; - end else if (fill_entry_en[fb]) begin - fill_err_q[fb][b] <= fill_err_d[fb][b]; - end - end - - // Enable the relevant part of the data register (or all for cache hits) - // Ignore incoming rvalid data when we already have cache hit data - assign fill_data_en[fb][b] = fill_hit_ic1[fb] | - (fill_rvd_arb[fb] & ~fill_hit_q[fb] & - (fill_rvd_off[fb] == b[IC_LINE_BEATS_W-1:0])); - - if (ResetAll) begin : g_fill_data_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - fill_data_q[fb][b*BUS_SIZE+:BUS_SIZE] <= '0; - end else if (fill_data_en[fb][b]) begin - fill_data_q[fb][b*BUS_SIZE+:BUS_SIZE] <= fill_data_d[fb][b*BUS_SIZE+:BUS_SIZE]; - end - end - end else begin : g_fill_data_nr - always_ff @(posedge clk_i) begin - if (fill_data_en[fb][b]) begin - fill_data_q[fb][b*BUS_SIZE+:BUS_SIZE] <= fill_data_d[fb][b*BUS_SIZE+:BUS_SIZE]; - end - end - end - - end - end - - //////////////////////////////// - // Fill buffer one-hot muxing // - //////////////////////////////// - - // External req info - always_comb begin - fill_ext_req_addr = '0; - for (int i = 0; i < NUM_FB; i++) begin - if (fill_ext_arb[i]) begin - fill_ext_req_addr |= {fill_addr_q[i][ADDR_W-1:IC_LINE_W], fill_ext_off[i]}; - end - end - end - - // Cache req info - always_comb begin - fill_ram_req_addr = '0; - fill_ram_req_way = '0; - fill_ram_req_data = '0; - for (int i = 0; i < NUM_FB; i++) begin - if (fill_ram_arb[i]) begin - fill_ram_req_addr |= fill_addr_q[i]; - fill_ram_req_way |= fill_way_q[i]; - fill_ram_req_data |= fill_data_q[i]; - end - end - end - - // IF stage output data - always_comb begin - fill_out_data = '0; - fill_out_err = '0; - for (int i = 0; i < NUM_FB; i++) begin - if (fill_data_reg[i]) begin - fill_out_data |= fill_data_q[i]; - // Ignore any speculative errors accumulated on cache hits - fill_out_err |= (fill_err_q[i] & ~{IC_LINE_BEATS{fill_hit_q[i]}}); - end - end - end - - /////////////////////// - // External requests // - /////////////////////// - - assign instr_req = ((~icache_enable_i | branch_or_mispredict) & lookup_grant_ic0) | - (|fill_ext_req); - - assign instr_addr = |fill_ext_req ? fill_ext_req_addr : - lookup_addr_ic0[ADDR_W-1:BUS_W]; - - assign instr_req_o = instr_req; - assign instr_addr_o = {instr_addr[ADDR_W-1:BUS_W],{BUS_W{1'b0}}}; - - //////////////////////// - // Output data muxing // - //////////////////////// - - // Mux between line-width data sources - assign line_data = |fill_data_hit ? hit_data_ic1 : fill_out_data; - assign line_err = |fill_data_hit ? {IC_LINE_BEATS{1'b0}} : fill_out_err; - - // Mux the relevant beat of line data, based on the output address - always_comb begin - line_data_muxed = '0; - line_err_muxed = 1'b0; - for (int unsigned i = 0; i < IC_LINE_BEATS; i++) begin - // When data has been skidded, the output address is behind by one - if ((output_addr_q[IC_LINE_W-1:BUS_W] + {{IC_LINE_BEATS_W-1{1'b0}},skid_valid_q}) == - i[IC_LINE_BEATS_W-1:0]) begin - line_data_muxed |= line_data[i*32+:32]; - line_err_muxed |= line_err[i]; - end - end - end - - // Mux between incoming rdata and the muxed line data - assign output_data = |fill_data_rvd ? instr_rdata_i : line_data_muxed; - assign output_err = |fill_data_rvd ? instr_err_i : line_err_muxed; - - // Output data is valid (from any of the three possible sources). Note that fill_out_arb - // must be used here rather than fill_out_req because data can become valid out of order - // (e.g. cache hit data can become available ahead of an older outstanding miss). - assign data_valid = |fill_out_arb; - - // Skid buffer data - assign skid_data_d = output_data[31:16]; - - assign skid_en = data_valid & (ready_i | skid_ready); - - if (ResetAll) begin : g_skid_data_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - skid_data_q <= '0; - skid_err_q <= '0; - end else if (skid_en) begin - skid_data_q <= skid_data_d; - skid_err_q <= output_err; - end - end - end else begin : g_skid_data_nr - always_ff @(posedge clk_i) begin - if (skid_en) begin - skid_data_q <= skid_data_d; - skid_err_q <= output_err; - end - end - end - - // The data in the skid buffer is ready if it's a complete compressed instruction or if there's - // an error (no need to wait for the second half) - assign skid_complete_instr = skid_valid_q & ((skid_data_q[1:0] != 2'b11) | skid_err_q); - - // Data can be loaded into the skid buffer for an unaligned uncompressed instruction - assign skid_ready = output_addr_q[1] & ~skid_valid_q & (~output_compressed | output_err); - - assign output_ready = (ready_i | skid_ready) & ~skid_complete_instr; - - assign output_compressed = (rdata_o[1:0] != 2'b11); - - assign skid_valid_d = - // Branches invalidate the skid buffer - branch_or_mispredict ? 1'b0 : - // Once valid, the skid buffer stays valid until a compressed instruction realigns the stream - (skid_valid_q ? ~(ready_i & ((skid_data_q[1:0] != 2'b11) | skid_err_q)) : - // The skid buffer becomes valid when: - // - we branch to an unaligned uncompressed instruction - (data_valid & - (((output_addr_q[1] & (~output_compressed | output_err)) | - // - a compressed instruction misaligns the stream - (~output_addr_q[1] & output_compressed & ~output_err & ready_i))))); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - skid_valid_q <= 1'b0; - end else begin - skid_valid_q <= skid_valid_d; - end - end - - // Signal that valid data is available to the IF stage - // Note that if the first half of an unaligned instruction reports an error, we do not need - // to wait for the second half - // Compressed instruction completely satisfied by skid buffer - assign output_valid = skid_complete_instr | - // Output data available and, output stream aligned, or skid data available, - (data_valid & (~output_addr_q[1] | skid_valid_q | - // or this is an error or an unaligned compressed instruction - output_err | (output_data[17:16] != 2'b11))); - - // Update the address on branches and every time an instruction is driven - assign output_addr_en = branch_or_mispredict | (ready_i & valid_o); - - // Increment the address by two every time a compressed instruction is popped - assign addr_incr_two = output_compressed & ~err_o; - - // Next IF stage PC - assign output_addr_incr = (output_addr_q[31:1] + - // Increment address by 4 or 2 - {29'd0, ~addr_incr_two, addr_incr_two}); - - // Redirect the address on branches or mispredicts - assign output_addr_d = branch_i ? addr_i[31:1] : - branch_mispredict_i ? mispredict_addr_i[31:1] : - output_addr_incr; - - if (ResetAll) begin : g_output_addr_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - output_addr_q <= '0; - end else if (output_addr_en) begin - output_addr_q <= output_addr_d; - end - end - end else begin : g_output_addr_nr - always_ff @(posedge clk_i) begin - if (output_addr_en) begin - output_addr_q <= output_addr_d; - end - end - end - - // Mux the data from BUS_SIZE to halfword - // This muxing realigns data when instruction words are split across BUS_W e.g. - // word 1 |----|*h1*| - // word 0 |*h0*|----| --> |*h1*|*h0*| - // 31 15 0 31 15 0 - always_comb begin - output_data_lo = '0; - for (int unsigned i = 0; i < IC_OUTPUT_BEATS; i++) begin - if (output_addr_q[BUS_W-1:1] == i[BUS_W-2:0]) begin - output_data_lo |= output_data[i*16+:16]; - end - end - end - - always_comb begin - output_data_hi = '0; - for (int unsigned i = 0; i < IC_OUTPUT_BEATS - 1; i++) begin - if (output_addr_q[BUS_W-1:1] == i[BUS_W-2:0]) begin - output_data_hi |= output_data[(i+1)*16+:16]; - end - end - if (&output_addr_q[BUS_W-1:1]) begin - output_data_hi |= output_data[15:0]; - end - end - - assign valid_o = output_valid & ~branch_mispredict_i; - assign rdata_o = {output_data_hi, (skid_valid_q ? skid_data_q : output_data_lo)}; - assign addr_o = {output_addr_q, 1'b0}; - assign err_o = (skid_valid_q & skid_err_q) | (~skid_complete_instr & output_err); - // Error caused by the second half of a misaligned uncompressed instruction - // (only relevant when err_o is set) - assign err_plus2_o = skid_valid_q & ~skid_err_q; - - /////////////////// - // Invalidations // - /////////////////// - - - // We need to save the invalidation request inside a register. That way we can wait - // until we have a valid scrambling key to do it. Since the key itself is needed for - // starting to fill in the RAMs and read from them, ICache also needs to stop operating. - assign inval_req_d = (inval_req_q | icache_inval_i) & ~(inval_done & inval_prog_q); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - inval_req_q <= 1'b0; - end else begin - inval_req_q <= inval_req_d; - end - end - - // This will act like a lock mechanism. - // Main idea is to lock the invalidation request until we got a valid scrambling key. - assign inval_lock = inval_req_d & ~ic_scr_key_valid_i; - - // Invalidate on reset, or when instructed. If an invalidation request is received while a - // previous invalidation is ongoing, it does not need to be restarted. Do not start - // this process until inval lock is removed meaning the scrambling key is valid. - assign start_inval = ~inval_lock & (~reset_inval_q | inval_req_q) & ~inval_prog_q ; - assign inval_prog_d = ~inval_lock & (start_inval | (inval_prog_q & ~inval_done)); - assign inval_done = &inval_index_q; - assign inval_index_d = start_inval ? '0 : (inval_index_q + {{IC_INDEX_W-1{1'b0}},1'b1}); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - inval_prog_q <= 1'b0; - reset_inval_q <= 1'b0; - end else begin - inval_prog_q <= inval_prog_d; - reset_inval_q <= 1'b1; - end - end - - if (ResetAll) begin : g_inval_index_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - inval_index_q <= '0; - end else if (inval_prog_d) begin - inval_index_q <= inval_index_d; - end - end - end else begin : g_inval_index_nr - always_ff @(posedge clk_i) begin - if (inval_prog_d) begin - inval_index_q <= inval_index_d; - end - end - end - - ///////////////// - // Busy status // - ///////////////// - - // Only busy (for WFI purposes) while an invalidation is in-progress, or external requests are - // outstanding. - assign busy_o = inval_req_q | (|(fill_busy_q & ~fill_rvd_done)); - - //////////////// - // Assertions // - //////////////// - - `ASSERT_INIT(size_param_legal, (IC_LINE_SIZE > 32)) - - // ECC primitives will need to be changed for different sizes - `ASSERT_INIT(ecc_tag_param_legal, (IC_TAG_SIZE <= 27)) - `ASSERT_INIT(ecc_data_param_legal, !ICacheECC || (BUS_SIZE == 32)) - - // Lookups in the tag ram should always give a known result - `ASSERT_KNOWN(TagHitKnown, lookup_valid_ic1 & tag_hit_ic1) - `ASSERT_KNOWN(TagInvalidKnown, lookup_valid_ic1 & tag_invalid_ic1) - - // This is only used for the Yosys-based formal flow. Once we have working bind support, we can - // get rid of it. -`ifdef FORMAL - `ifdef YOSYS - // Unfortunately, Yosys doesn't support passing unpacked arrays as ports. Explicitly pack up the - // signals we need. - logic [NUM_FB-1:0][ADDR_W-1:0] packed_fill_addr_q; - always_comb begin - for (int i = 0; i < NUM_FB; i++) begin - packed_fill_addr_q[i][ADDR_W-1:0] = fill_addr_q[i]; - end - end - - `include "formal_tb_frag.svh" - `endif -`endif - - -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_if_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_if_stage.sv deleted file mode 100644 index c430b669..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_if_stage.sv +++ /dev/null @@ -1,750 +0,0 @@ -// Copyright lowRISC contributors. -// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * Instruction Fetch Stage - * - * Instruction fetch unit: Selection of the next PC, and buffering (sampling) of - * the read instruction. - */ - -`include "prim_assert.sv" - -module ibex_if_stage import ibex_pkg::*; #( - parameter int unsigned DmHaltAddr = 32'h1A110800, - parameter int unsigned DmExceptionAddr = 32'h1A110808, - parameter bit DummyInstructions = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter int unsigned BusSizeECC = BUS_SIZE, - parameter int unsigned TagSizeECC = IC_TAG_SIZE, - parameter int unsigned LineSizeECC = IC_LINE_SIZE, - parameter bit PCIncrCheck = 1'b0, - parameter bit ResetAll = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, - parameter bit BranchPredictor = 1'b0 -) ( - input logic clk_i, - input logic rst_ni, - - input logic [31:0] boot_addr_i, // also used for mtvec - input logic req_i, // instruction request control - - // instruction cache interface - output logic instr_req_o, - output logic [31:0] instr_addr_o, - input logic instr_gnt_i, - input logic instr_rvalid_i, - input logic [31:0] instr_rdata_i, - input logic instr_err_i, - - // ICache RAM IO - output logic [IC_NUM_WAYS-1:0] ic_tag_req_o, - output logic ic_tag_write_o, - output logic [IC_INDEX_W-1:0] ic_tag_addr_o, - output logic [TagSizeECC-1:0] ic_tag_wdata_o, - input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], - output logic [IC_NUM_WAYS-1:0] ic_data_req_o, - output logic ic_data_write_o, - output logic [IC_INDEX_W-1:0] ic_data_addr_o, - output logic [LineSizeECC-1:0] ic_data_wdata_o, - input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], - input logic ic_scr_key_valid_i, - - // output of ID stage - output logic instr_valid_id_o, // instr in IF-ID is valid - output logic instr_new_id_o, // instr in IF-ID is new - output logic [31:0] instr_rdata_id_o, // instr for ID stage - output logic [31:0] instr_rdata_alu_id_o, // replicated instr for ID stage - // to reduce fan-out - output logic [15:0] instr_rdata_c_id_o, // compressed instr for ID stage - // (mtval), meaningful only if - // instr_is_compressed_id_o = 1'b1 - output logic instr_is_compressed_id_o, // compressed decoder thinks this - // is a compressed instr - output logic instr_bp_taken_o, // instruction was predicted to be - // a taken branch - output logic instr_fetch_err_o, // bus error on fetch - output logic instr_fetch_err_plus2_o, // bus error misaligned - output logic illegal_c_insn_id_o, // compressed decoder thinks this - // is an invalid instr - output logic dummy_instr_id_o, // Instruction is a dummy - output logic [31:0] pc_if_o, - output logic [31:0] pc_id_o, - input logic pmp_err_if_i, - input logic pmp_err_if_plus2_i, - - // control signals - input logic instr_valid_clear_i, // clear instr valid bit in IF-ID - input logic pc_set_i, // set the PC to a new value - input pc_sel_e pc_mux_i, // selector for PC multiplexer - input logic nt_branch_mispredict_i, // Not-taken branch in ID/EX was - // mispredicted (predicted taken) - input logic [31:0] nt_branch_addr_i, // Not-taken branch address in ID/EX - input exc_pc_sel_e exc_pc_mux_i, // selects ISR address - input exc_cause_e exc_cause, // selects ISR address for - // vectorized interrupt lines - input logic dummy_instr_en_i, - input logic [2:0] dummy_instr_mask_i, - input logic dummy_instr_seed_en_i, - input logic [31:0] dummy_instr_seed_i, - input logic icache_enable_i, - input logic icache_inval_i, - output logic icache_ecc_error_o, - - // jump and branch target - input logic [31:0] branch_target_ex_i, // branch/jump target address - - // CSRs - input logic [31:0] csr_mepc_i, // PC to restore after handling - // the interrupt/exception - input logic [31:0] csr_depc_i, // PC to restore after handling - // the debug request - input logic [31:0] csr_mtvec_i, // base PC to jump to on exception - output logic csr_mtvec_init_o, // tell CS regfile to init mtvec - - // pipeline stall - input logic id_in_ready_i, // ID stage is ready for new instr - - // misc signals - output logic pc_mismatch_alert_o, - output logic if_busy_o // IF stage is busy fetching instr -); - - logic instr_valid_id_d, instr_valid_id_q; - logic instr_new_id_d, instr_new_id_q; - - // prefetch buffer related signals - logic prefetch_busy; - logic branch_req; - logic [31:0] fetch_addr_n; - logic unused_fetch_addr_n0; - - logic fetch_valid; - logic fetch_ready; - logic [31:0] fetch_rdata; - logic [31:0] fetch_addr; - logic fetch_err; - logic fetch_err_plus2; - - logic [31:0] instr_decompressed; - logic illegal_c_insn; - logic instr_is_compressed; - - logic if_instr_valid; - logic [31:0] if_instr_rdata; - logic [31:0] if_instr_addr; - logic if_instr_bus_err; - logic if_instr_pmp_err; - logic if_instr_err; - logic if_instr_err_plus2; - - logic [31:0] exc_pc; - - logic [5:0] irq_id; - logic unused_irq_bit; - - logic if_id_pipe_reg_we; // IF-ID pipeline reg write enable - - // Dummy instruction signals - logic stall_dummy_instr; - logic [31:0] instr_out; - logic instr_is_compressed_out; - logic illegal_c_instr_out; - logic instr_err_out; - - logic predict_branch_taken; - logic [31:0] predict_branch_pc; - - ibex_pkg::pc_sel_e pc_mux_internal; - - logic [7:0] unused_boot_addr; - logic [7:0] unused_csr_mtvec; - - assign unused_boot_addr = boot_addr_i[7:0]; - assign unused_csr_mtvec = csr_mtvec_i[7:0]; - - // extract interrupt ID from exception cause - assign irq_id = {exc_cause}; - assign unused_irq_bit = irq_id[5]; // MSB distinguishes interrupts from exceptions - - // exception PC selection mux - always_comb begin : exc_pc_mux - unique case (exc_pc_mux_i) - EXC_PC_EXC: exc_pc = { csr_mtvec_i[31:8], 8'h00 }; - EXC_PC_IRQ: exc_pc = { csr_mtvec_i[31:8], 1'b0, irq_id[4:0], 2'b00 }; - EXC_PC_DBD: exc_pc = DmHaltAddr; - EXC_PC_DBG_EXC: exc_pc = DmExceptionAddr; - default: exc_pc = { csr_mtvec_i[31:8], 8'h00 }; - endcase - end - - // The Branch predictor can provide a new PC which is internal to if_stage. Only override the mux - // select to choose this if the core isn't already trying to set a PC. - assign pc_mux_internal = - (BranchPredictor && predict_branch_taken && !pc_set_i) ? PC_BP : pc_mux_i; - - // fetch address selection mux - always_comb begin : fetch_addr_mux - unique case (pc_mux_internal) - PC_BOOT: fetch_addr_n = { boot_addr_i[31:8], 8'h00 }; - PC_JUMP: fetch_addr_n = branch_target_ex_i; - PC_EXC: fetch_addr_n = exc_pc; // set PC to exception handler - PC_ERET: fetch_addr_n = csr_mepc_i; // restore PC when returning from EXC - PC_DRET: fetch_addr_n = csr_depc_i; - // Without branch predictor will never get pc_mux_internal == PC_BP. We still handle no branch - // predictor case here to ensure redundant mux logic isn't synthesised. - PC_BP: fetch_addr_n = BranchPredictor ? predict_branch_pc : { boot_addr_i[31:8], 8'h00 }; - default: fetch_addr_n = { boot_addr_i[31:8], 8'h00 }; - endcase - end - - // tell CS register file to initialize mtvec on boot - assign csr_mtvec_init_o = (pc_mux_i == PC_BOOT) & pc_set_i; - - if (ICache) begin : gen_icache - // Full I-Cache option - ibex_icache #( - .ICacheECC (ICacheECC), - .ResetAll (ResetAll), - .BusSizeECC (BusSizeECC), - .TagSizeECC (TagSizeECC), - .LineSizeECC (LineSizeECC) - ) icache_i ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - - .req_i ( req_i ), - - .branch_i ( branch_req ), - .branch_mispredict_i ( nt_branch_mispredict_i ), - .mispredict_addr_i ( nt_branch_addr_i ), - .addr_i ( {fetch_addr_n[31:1], 1'b0} ), - - .ready_i ( fetch_ready ), - .valid_o ( fetch_valid ), - .rdata_o ( fetch_rdata ), - .addr_o ( fetch_addr ), - .err_o ( fetch_err ), - .err_plus2_o ( fetch_err_plus2 ), - - .instr_req_o ( instr_req_o ), - .instr_addr_o ( instr_addr_o ), - .instr_gnt_i ( instr_gnt_i ), - .instr_rvalid_i ( instr_rvalid_i ), - .instr_rdata_i ( instr_rdata_i ), - .instr_err_i ( instr_err_i ), - - .ic_tag_req_o ( ic_tag_req_o ), - .ic_tag_write_o ( ic_tag_write_o ), - .ic_tag_addr_o ( ic_tag_addr_o ), - .ic_tag_wdata_o ( ic_tag_wdata_o ), - .ic_tag_rdata_i ( ic_tag_rdata_i ), - .ic_data_req_o ( ic_data_req_o ), - .ic_data_write_o ( ic_data_write_o ), - .ic_data_addr_o ( ic_data_addr_o ), - .ic_data_wdata_o ( ic_data_wdata_o ), - .ic_data_rdata_i ( ic_data_rdata_i ), - .ic_scr_key_valid_i ( ic_scr_key_valid_i ), - - .icache_enable_i ( icache_enable_i ), - .icache_inval_i ( icache_inval_i ), - .busy_o ( prefetch_busy ), - .ecc_error_o ( icache_ecc_error_o ) - ); - end else begin : gen_prefetch_buffer - // prefetch buffer, caches a fixed number of instructions - ibex_prefetch_buffer #( - .ResetAll (ResetAll) - ) prefetch_buffer_i ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - - .req_i ( req_i ), - - .branch_i ( branch_req ), - .branch_mispredict_i ( nt_branch_mispredict_i ), - .mispredict_addr_i ( nt_branch_addr_i ), - .addr_i ( {fetch_addr_n[31:1], 1'b0} ), - - .ready_i ( fetch_ready ), - .valid_o ( fetch_valid ), - .rdata_o ( fetch_rdata ), - .addr_o ( fetch_addr ), - .err_o ( fetch_err ), - .err_plus2_o ( fetch_err_plus2 ), - - .instr_req_o ( instr_req_o ), - .instr_addr_o ( instr_addr_o ), - .instr_gnt_i ( instr_gnt_i ), - .instr_rvalid_i ( instr_rvalid_i ), - .instr_rdata_i ( instr_rdata_i ), - .instr_err_i ( instr_err_i ), - - .busy_o ( prefetch_busy ) - ); - // ICache tieoffs - logic unused_icen, unused_icinv, unused_scr_key_valid; - logic [TagSizeECC-1:0] unused_tag_ram_input [IC_NUM_WAYS]; - logic [LineSizeECC-1:0] unused_data_ram_input [IC_NUM_WAYS]; - assign unused_icen = icache_enable_i; - assign unused_icinv = icache_inval_i; - assign unused_tag_ram_input = ic_tag_rdata_i; - assign unused_data_ram_input = ic_data_rdata_i; - assign unused_scr_key_valid = ic_scr_key_valid_i; - assign ic_tag_req_o = 'b0; - assign ic_tag_write_o = 'b0; - assign ic_tag_addr_o = 'b0; - assign ic_tag_wdata_o = 'b0; - assign ic_data_req_o = 'b0; - assign ic_data_write_o = 'b0; - assign ic_data_addr_o = 'b0; - assign ic_data_wdata_o = 'b0; - assign icache_ecc_error_o = 'b0; - -`ifndef SYNTHESIS - // If we don't instantiate an icache and this is a simulation then we have a problem because the - // simulator might discard the icache module entirely, including some DPI exports that it - // implies. This then causes problems for linking against C++ testbench code that expected them. - // As a slightly ugly hack, let's define the DPI functions here (the real versions are defined - // in prim_util_get_scramble_params.svh) - export "DPI-C" function simutil_get_scramble_key; - export "DPI-C" function simutil_get_scramble_nonce; - function automatic int simutil_get_scramble_key(output bit [127:0] val); - return 0; - endfunction - function automatic int simutil_get_scramble_nonce(output bit [319:0] nonce); - return 0; - endfunction -`endif - end - - assign unused_fetch_addr_n0 = fetch_addr_n[0]; - - assign branch_req = pc_set_i | predict_branch_taken; - - assign pc_if_o = if_instr_addr; - assign if_busy_o = prefetch_busy; - - // PMP errors - // An error can come from the instruction address, or the next instruction address for unaligned, - // uncompressed instructions. - assign if_instr_pmp_err = pmp_err_if_i | - (if_instr_addr[2] & ~instr_is_compressed & pmp_err_if_plus2_i); - - // Combine bus errors and pmp errors - assign if_instr_err = if_instr_bus_err | if_instr_pmp_err; - - // Capture the second half of the address for errors on the second part of an instruction - assign if_instr_err_plus2 = ((if_instr_addr[2] & ~instr_is_compressed & pmp_err_if_plus2_i) | - fetch_err_plus2) & ~pmp_err_if_i; - - // compressed instruction decoding, or more precisely compressed instruction - // expander - // - // since it does not matter where we decompress instructions, we do it here - // to ease timing closure - ibex_compressed_decoder compressed_decoder_i ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .valid_i (fetch_valid & ~fetch_err), - .instr_i (if_instr_rdata), - .instr_o (instr_decompressed), - .is_compressed_o(instr_is_compressed), - .illegal_instr_o(illegal_c_insn) - ); - - // Dummy instruction insertion - if (DummyInstructions) begin : gen_dummy_instr - // SEC_CM: CTRL_FLOW.UNPREDICTABLE - logic insert_dummy_instr; - logic [31:0] dummy_instr_data; - - ibex_dummy_instr #( - .RndCnstLfsrSeed (RndCnstLfsrSeed), - .RndCnstLfsrPerm (RndCnstLfsrPerm) - ) dummy_instr_i ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .dummy_instr_en_i (dummy_instr_en_i), - .dummy_instr_mask_i (dummy_instr_mask_i), - .dummy_instr_seed_en_i(dummy_instr_seed_en_i), - .dummy_instr_seed_i (dummy_instr_seed_i), - .fetch_valid_i (fetch_valid), - .id_in_ready_i (id_in_ready_i), - .insert_dummy_instr_o (insert_dummy_instr), - .dummy_instr_data_o (dummy_instr_data) - ); - - // Mux between actual instructions and dummy instructions - assign instr_out = insert_dummy_instr ? dummy_instr_data : instr_decompressed; - assign instr_is_compressed_out = insert_dummy_instr ? 1'b0 : instr_is_compressed; - assign illegal_c_instr_out = insert_dummy_instr ? 1'b0 : illegal_c_insn; - assign instr_err_out = insert_dummy_instr ? 1'b0 : if_instr_err; - - // Stall the IF stage if we insert a dummy instruction. The dummy will execute between whatever - // is currently in the ID stage and whatever is valid from the prefetch buffer this cycle. The - // PC of the dummy instruction will match whatever is next from the prefetch buffer. - assign stall_dummy_instr = insert_dummy_instr; - - // Register the dummy instruction indication into the ID stage - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - dummy_instr_id_o <= 1'b0; - end else if (if_id_pipe_reg_we) begin - dummy_instr_id_o <= insert_dummy_instr; - end - end - - end else begin : gen_no_dummy_instr - logic unused_dummy_en; - logic [2:0] unused_dummy_mask; - logic unused_dummy_seed_en; - logic [31:0] unused_dummy_seed; - - assign unused_dummy_en = dummy_instr_en_i; - assign unused_dummy_mask = dummy_instr_mask_i; - assign unused_dummy_seed_en = dummy_instr_seed_en_i; - assign unused_dummy_seed = dummy_instr_seed_i; - assign instr_out = instr_decompressed; - assign instr_is_compressed_out = instr_is_compressed; - assign illegal_c_instr_out = illegal_c_insn; - assign instr_err_out = if_instr_err; - assign stall_dummy_instr = 1'b0; - assign dummy_instr_id_o = 1'b0; - end - - // The ID stage becomes valid as soon as any instruction is registered in the ID stage flops. - // Note that the current instruction is squashed by the incoming pc_set_i signal. - // Valid is held until it is explicitly cleared (due to an instruction completing or an exception) - assign instr_valid_id_d = (if_instr_valid & id_in_ready_i & ~pc_set_i) | - (instr_valid_id_q & ~instr_valid_clear_i); - assign instr_new_id_d = if_instr_valid & id_in_ready_i; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_valid_id_q <= 1'b0; - instr_new_id_q <= 1'b0; - end else begin - instr_valid_id_q <= instr_valid_id_d; - instr_new_id_q <= instr_new_id_d; - end - end - - assign instr_valid_id_o = instr_valid_id_q; - // Signal when a new instruction enters the ID stage (only used for RVFI signalling). - assign instr_new_id_o = instr_new_id_q; - - // IF-ID pipeline registers, frozen when the ID stage is stalled - assign if_id_pipe_reg_we = instr_new_id_d; - - if (ResetAll) begin : g_instr_rdata_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_rdata_id_o <= '0; - instr_rdata_alu_id_o <= '0; - instr_fetch_err_o <= '0; - instr_fetch_err_plus2_o <= '0; - instr_rdata_c_id_o <= '0; - instr_is_compressed_id_o <= '0; - illegal_c_insn_id_o <= '0; - pc_id_o <= '0; - end else if (if_id_pipe_reg_we) begin - instr_rdata_id_o <= instr_out; - // To reduce fan-out and help timing from the instr_rdata_id flops they are replicated. - instr_rdata_alu_id_o <= instr_out; - instr_fetch_err_o <= instr_err_out; - instr_fetch_err_plus2_o <= if_instr_err_plus2; - instr_rdata_c_id_o <= if_instr_rdata[15:0]; - instr_is_compressed_id_o <= instr_is_compressed_out; - illegal_c_insn_id_o <= illegal_c_instr_out; - pc_id_o <= pc_if_o; - end - end - end else begin : g_instr_rdata_nr - always_ff @(posedge clk_i) begin - if (if_id_pipe_reg_we) begin - instr_rdata_id_o <= instr_out; - // To reduce fan-out and help timing from the instr_rdata_id flops they are replicated. - instr_rdata_alu_id_o <= instr_out; - instr_fetch_err_o <= instr_err_out; - instr_fetch_err_plus2_o <= if_instr_err_plus2; - instr_rdata_c_id_o <= if_instr_rdata[15:0]; - instr_is_compressed_id_o <= instr_is_compressed_out; - illegal_c_insn_id_o <= illegal_c_instr_out; - pc_id_o <= pc_if_o; - end - end - end - - // Check for expected increments of the PC when security hardening enabled - if (PCIncrCheck) begin : g_secure_pc - // SEC_CM: PC.CTRL_FLOW.CONSISTENCY - logic [31:0] prev_instr_addr_incr, prev_instr_addr_incr_buf; - logic prev_instr_seq_q, prev_instr_seq_d; - - // Do not check for sequential increase after a branch, jump, exception, interrupt or debug - // request, all of which will set branch_req. Also do not check after reset or for dummys. - assign prev_instr_seq_d = (prev_instr_seq_q | instr_new_id_d) & - ~branch_req & ~if_instr_err & ~stall_dummy_instr; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - prev_instr_seq_q <= 1'b0; - end else begin - prev_instr_seq_q <= prev_instr_seq_d; - end - end - - assign prev_instr_addr_incr = pc_id_o + (instr_is_compressed_id_o ? 32'd2 : 32'd4); - - // Buffer anticipated next PC address to ensure optimiser cannot remove the check. - prim_buf #(.Width(32)) u_prev_instr_addr_incr_buf ( - .in_i (prev_instr_addr_incr), - .out_o(prev_instr_addr_incr_buf) - ); - - // Check that the address equals the previous address +2/+4 - assign pc_mismatch_alert_o = prev_instr_seq_q & (pc_if_o != prev_instr_addr_incr_buf); - - end else begin : g_no_secure_pc - assign pc_mismatch_alert_o = 1'b0; - end - - if (BranchPredictor) begin : g_branch_predictor - logic [31:0] instr_skid_data_q; - logic [31:0] instr_skid_addr_q; - logic instr_skid_bp_taken_q; - logic instr_skid_valid_q, instr_skid_valid_d; - logic instr_skid_en; - logic instr_bp_taken_q, instr_bp_taken_d; - - logic predict_branch_taken_raw; - - // ID stages needs to know if branch was predicted taken so it can signal mispredicts - if (ResetAll) begin : g_bp_taken_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_bp_taken_q <= '0; - end else if (if_id_pipe_reg_we) begin - instr_bp_taken_q <= instr_bp_taken_d; - end - end - end else begin : g_bp_taken_nr - always_ff @(posedge clk_i) begin - if (if_id_pipe_reg_we) begin - instr_bp_taken_q <= instr_bp_taken_d; - end - end - end - - // When branch prediction is enabled a skid buffer between the IF and ID/EX stage is introduced. - // If an instruction in IF is predicted to be a taken branch and ID/EX is not ready the - // instruction in IF is moved to the skid buffer which becomes the output of the IF stage until - // the ID/EX stage accepts the instruction. The skid buffer is required as otherwise the ID/EX - // ready signal is coupled to the instr_req_o output which produces a feedthrough path from - // data_gnt_i -> instr_req_o (which needs to be avoided as for some interconnects this will - // result in a combinational loop). - - assign instr_skid_en = predict_branch_taken & ~pc_set_i & ~id_in_ready_i & ~instr_skid_valid_q; - - assign instr_skid_valid_d = (instr_skid_valid_q & ~id_in_ready_i & ~stall_dummy_instr) | - instr_skid_en; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_skid_valid_q <= 1'b0; - end else begin - instr_skid_valid_q <= instr_skid_valid_d; - end - end - - if (ResetAll) begin : g_instr_skid_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_skid_bp_taken_q <= '0; - instr_skid_data_q <= '0; - instr_skid_addr_q <= '0; - end else if (instr_skid_en) begin - instr_skid_bp_taken_q <= predict_branch_taken; - instr_skid_data_q <= fetch_rdata; - instr_skid_addr_q <= fetch_addr; - end - end - end else begin : g_instr_skid_nr - always_ff @(posedge clk_i) begin - if (instr_skid_en) begin - instr_skid_bp_taken_q <= predict_branch_taken; - instr_skid_data_q <= fetch_rdata; - instr_skid_addr_q <= fetch_addr; - end - end - end - - ibex_branch_predict branch_predict_i ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .fetch_rdata_i(fetch_rdata), - .fetch_pc_i (fetch_addr), - .fetch_valid_i(fetch_valid), - - .predict_branch_taken_o(predict_branch_taken_raw), - .predict_branch_pc_o (predict_branch_pc) - ); - - // If there is an instruction in the skid buffer there must be no branch prediction. - // Instructions are only placed in the skid after they have been predicted to be a taken branch - // so with the skid valid any prediction has already occurred. - // Do not branch predict on instruction errors. - assign predict_branch_taken = predict_branch_taken_raw & ~instr_skid_valid_q & ~fetch_err; - - assign if_instr_valid = fetch_valid | (instr_skid_valid_q & ~nt_branch_mispredict_i); - assign if_instr_rdata = instr_skid_valid_q ? instr_skid_data_q : fetch_rdata; - assign if_instr_addr = instr_skid_valid_q ? instr_skid_addr_q : fetch_addr; - - // Don't branch predict on instruction error so only instructions without errors end up in the - // skid buffer. - assign if_instr_bus_err = ~instr_skid_valid_q & fetch_err; - assign instr_bp_taken_d = instr_skid_valid_q ? instr_skid_bp_taken_q : predict_branch_taken; - - assign fetch_ready = id_in_ready_i & ~stall_dummy_instr & ~instr_skid_valid_q; - - assign instr_bp_taken_o = instr_bp_taken_q; - - `ASSERT(NoPredictSkid, instr_skid_valid_q |-> ~predict_branch_taken) - `ASSERT(NoPredictIllegal, predict_branch_taken |-> ~illegal_c_insn) - end else begin : g_no_branch_predictor - assign instr_bp_taken_o = 1'b0; - assign predict_branch_taken = 1'b0; - assign predict_branch_pc = 32'b0; - - assign if_instr_valid = fetch_valid; - assign if_instr_rdata = fetch_rdata; - assign if_instr_addr = fetch_addr; - assign if_instr_bus_err = fetch_err; - assign fetch_ready = id_in_ready_i & ~stall_dummy_instr; - end - - //////////////// - // Assertions // - //////////////// - - // Selectors must be known/valid. - `ASSERT_KNOWN(IbexExcPcMuxKnown, exc_pc_mux_i) - - if (BranchPredictor) begin : g_branch_predictor_asserts - `ASSERT_IF(IbexPcMuxValid, pc_mux_internal inside { - PC_BOOT, - PC_JUMP, - PC_EXC, - PC_ERET, - PC_DRET, - PC_BP}, - pc_set_i) - -`ifdef INC_ASSERT - /** - * Checks for branch prediction interface to fetch_fifo/icache - * - * The interface has two signals: - * - predicted_branch_i: When set with a branch (branch_i) indicates the branch is a predicted - * one, it should be ignored when a branch_i isn't set. - * - branch_mispredict_i: Indicates the previously predicted branch was mis-predicted and - * execution should resume with the not-taken side of the branch (i.e. continue with the PC - * that followed the predicted branch). This must be raised before the instruction that is - * made available following a predicted branch is accepted (Following a cycle with branch_i - * & predicted_branch_i, branch_mispredict_i can only be asserted before or on the same cycle - * as seeing fetch_valid & fetch_ready). When branch_mispredict_i is asserted, fetch_valid may - * be asserted in response. If fetch_valid is asserted on the same cycle as - * branch_mispredict_i this indicates the fetch_fifo/icache has the not-taken side of the - * branch immediately ready for use - */ - logic predicted_branch_live_q, predicted_branch_live_d; - logic [31:0] predicted_branch_nt_pc_q, predicted_branch_nt_pc_d; - logic [31:0] awaiting_instr_after_mispredict_q, awaiting_instr_after_mispredict_d; - logic [31:0] next_pc; - - logic mispredicted, mispredicted_d, mispredicted_q; - - assign next_pc = fetch_addr + (instr_is_compressed_out ? 32'd2 : 32'd4); - - logic predicted_branch; - - // pc_set_i takes precendence over branch prediction - assign predicted_branch = predict_branch_taken & ~pc_set_i; - - always_comb begin - predicted_branch_live_d = predicted_branch_live_q; - mispredicted_d = mispredicted_q; - - if (branch_req & predicted_branch) begin - predicted_branch_live_d = 1'b1; - mispredicted_d = 1'b0; - end else if (predicted_branch_live_q) begin - if (fetch_valid & fetch_ready) begin - predicted_branch_live_d = 1'b0; - end else if (nt_branch_mispredict_i) begin - mispredicted_d = 1'b1; - end - end - end - - always @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - predicted_branch_live_q <= 1'b0; - mispredicted_q <= 1'b0; - end else begin - predicted_branch_live_q <= predicted_branch_live_d; - mispredicted_q <= mispredicted_d; - end - end - - always @(posedge clk_i) begin - if (branch_req & predicted_branch) begin - predicted_branch_nt_pc_q <= next_pc; - end - end - - // Must only see mispredict after we've performed a predicted branch but before we've accepted - // any instruction (with fetch_ready & fetch_valid) that follows that predicted branch. - `ASSERT(MispredictOnlyImmediatelyAfterPredictedBranch, - nt_branch_mispredict_i |-> predicted_branch_live_q) - // Check that on mispredict we get the correct PC for the non-taken side of the branch when - // prefetch buffer/icache makes that PC available. - `ASSERT(CorrectPCOnMispredict, - predicted_branch_live_q & mispredicted_d & fetch_valid |-> - fetch_addr == predicted_branch_nt_pc_q) - // Must not signal mispredict over multiple cycles but it's possible to have back to back - // mispredicts for different branches (core signals mispredict, prefetch buffer/icache immediate - // has not-taken side of the mispredicted branch ready, which itself is a predicted branch, - // following cycle core signal that that branch has mispredicted). - `ASSERT(MispredictSingleCycle, - nt_branch_mispredict_i & ~(fetch_valid & fetch_ready) |=> ~nt_branch_mispredict_i) - // Note that we should never see a mispredict and an incoming branch on the same cycle. - // The mispredict also cancels any predicted branch so overall branch_req must be low. - `ASSERT(NoMispredBranch, nt_branch_mispredict_i |-> ~branch_req) -`endif - - end else begin : g_no_branch_predictor_asserts - `ASSERT_IF(IbexPcMuxValid, pc_mux_internal inside { - PC_BOOT, - PC_JUMP, - PC_EXC, - PC_ERET, - PC_DRET}, - pc_set_i) - end - - // Boot address must be aligned to 256 bytes. - `ASSERT(IbexBootAddrUnaligned, boot_addr_i[7:0] == 8'h00) - - // Address must not contain X when request is sent. - `ASSERT(IbexInstrAddrUnknown, instr_req_o |-> !$isunknown(instr_addr_o)) - - // Address must be word aligned when request is sent. - `ASSERT(IbexInstrAddrUnaligned, instr_req_o |-> (instr_addr_o[1:0] == 2'b00)) - -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_lockstep.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_lockstep.sv deleted file mode 100644 index 4f986d0c..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_lockstep.sv +++ /dev/null @@ -1,491 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -// Ibex lockstep module -// This module instantiates a second copy of the core logic, and compares it's outputs against -// those from the main core. The second core runs synchronously with the main core, delayed by -// LockstepOffset cycles. - -// SEC_CM: LOGIC.SHADOW -module ibex_lockstep import ibex_pkg::*; #( - parameter int unsigned LockstepOffset = 2, - parameter bit PMPEnable = 1'b0, - parameter int unsigned PMPGranularity = 0, - parameter int unsigned PMPNumRegions = 4, - parameter int unsigned MHPMCounterNum = 0, - parameter int unsigned MHPMCounterWidth = 40, - parameter bit RV32E = 1'b0, - parameter rv32m_e RV32M = RV32MFast, - parameter rv32b_e RV32B = RV32BNone, - parameter bit BranchTargetALU = 1'b0, - parameter bit WritebackStage = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter int unsigned BusSizeECC = BUS_SIZE, - parameter int unsigned TagSizeECC = IC_TAG_SIZE, - parameter int unsigned LineSizeECC = IC_LINE_SIZE, - parameter bit BranchPredictor = 1'b0, - parameter bit DbgTriggerEn = 1'b0, - parameter int unsigned DbgHwBreakNum = 1, - parameter bit ResetAll = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, - parameter bit SecureIbex = 1'b0, - parameter bit DummyInstructions = 1'b0, - parameter bit RegFileECC = 1'b0, - parameter int unsigned RegFileDataWidth = 32, - parameter int unsigned DmHaltAddr = 32'h1A110800, - parameter int unsigned DmExceptionAddr = 32'h1A110808 -) ( - input logic clk_i, - input logic rst_ni, - - input logic [31:0] hart_id_i, - input logic [31:0] boot_addr_i, - - input logic instr_req_i, - input logic instr_gnt_i, - input logic instr_rvalid_i, - input logic [31:0] instr_addr_i, - input logic [31:0] instr_rdata_i, - input logic [6:0] instr_rdata_intg_i, - input logic instr_err_i, - - input logic data_req_i, - input logic data_gnt_i, - input logic data_rvalid_i, - input logic data_we_i, - input logic [3:0] data_be_i, - input logic [31:0] data_addr_i, - input logic [31:0] data_wdata_i, - output logic [6:0] data_wdata_intg_o, - input logic [31:0] data_rdata_i, - input logic [6:0] data_rdata_intg_i, - input logic data_err_i, - - input logic dummy_instr_id_i, - input logic [4:0] rf_raddr_a_i, - input logic [4:0] rf_raddr_b_i, - input logic [4:0] rf_waddr_wb_i, - input logic rf_we_wb_i, - input logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_i, - input logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_i, - input logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_i, - - input logic [IC_NUM_WAYS-1:0] ic_tag_req_i, - input logic ic_tag_write_i, - input logic [IC_INDEX_W-1:0] ic_tag_addr_i, - input logic [TagSizeECC-1:0] ic_tag_wdata_i, - input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS], - input logic [IC_NUM_WAYS-1:0] ic_data_req_i, - input logic ic_data_write_i, - input logic [IC_INDEX_W-1:0] ic_data_addr_i, - input logic [LineSizeECC-1:0] ic_data_wdata_i, - input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS], - input logic ic_scr_key_valid_i, - - input logic irq_software_i, - input logic irq_timer_i, - input logic irq_external_i, - input logic [14:0] irq_fast_i, - input logic irq_nm_i, - input logic irq_pending_i, - - input logic debug_req_i, - input crash_dump_t crash_dump_i, - input logic double_fault_seen_i, - - input fetch_enable_t fetch_enable_i, - output logic alert_minor_o, - output logic alert_major_internal_o, - output logic alert_major_bus_o, - input logic icache_inval_i, - input logic core_busy_i, - input logic test_en_i, - input logic scan_rst_ni -); - - localparam int unsigned LockstepOffsetW = $clog2(LockstepOffset); - // Core outputs are delayed for an extra cycle due to shadow output registers - localparam int unsigned OutputsOffset = LockstepOffset + 1; - - ////////////////////// - // Reset generation // - ////////////////////// - - // Upon reset, the comparison is stopped and the shadow core is reset, both immediately. A - // counter is started. After LockstepOffset clock cycles: - // - The counter is stopped. - // - The reset of the shadow core is synchronously released. - // The comparison is started in the following clock cycle. - - logic [LockstepOffsetW-1:0] rst_shadow_cnt_d, rst_shadow_cnt_q, rst_shadow_cnt_incr; - // Internally generated resets cause IMPERFECTSCH warnings - /* verilator lint_off IMPERFECTSCH */ - logic rst_shadow_set_d, rst_shadow_set_q; - logic rst_shadow_n, enable_cmp_q; - /* verilator lint_on IMPERFECTSCH */ - - assign rst_shadow_cnt_incr = rst_shadow_cnt_q + LockstepOffsetW'(1); - - assign rst_shadow_set_d = (rst_shadow_cnt_q == LockstepOffsetW'(LockstepOffset - 1)); - assign rst_shadow_cnt_d = rst_shadow_set_d ? rst_shadow_cnt_q : rst_shadow_cnt_incr; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - rst_shadow_cnt_q <= '0; - enable_cmp_q <= '0; - end else begin - rst_shadow_cnt_q <= rst_shadow_cnt_d; - enable_cmp_q <= rst_shadow_set_q; - end - end - - // The primitives below are used to place size-only constraints in order to prevent - // synthesis optimizations and preserve anchor points for constraining backend tools. - prim_flop #( - .Width(1), - .ResetValue(1'b0) - ) u_prim_rst_shadow_set_flop ( - .clk_i (clk_i), - .rst_ni(rst_ni), - .d_i (rst_shadow_set_d), - .q_o (rst_shadow_set_q) - ); - - prim_clock_mux2 #( - .NoFpgaBufG(1'b1) - ) u_prim_rst_shadow_n_mux2 ( - .clk0_i(rst_shadow_set_q), - .clk1_i(scan_rst_ni), - .sel_i (test_en_i), - .clk_o (rst_shadow_n) - ); - - ////////////////// - // Input delays // - ////////////////// - - typedef struct packed { - logic instr_gnt; - logic instr_rvalid; - logic [31:0] instr_rdata; - logic instr_err; - logic data_gnt; - logic data_rvalid; - logic [31:0] data_rdata; - logic data_err; - logic [RegFileDataWidth-1:0] rf_rdata_a_ecc; - logic [RegFileDataWidth-1:0] rf_rdata_b_ecc; - logic irq_software; - logic irq_timer; - logic irq_external; - logic [14:0] irq_fast; - logic irq_nm; - logic debug_req; - fetch_enable_t fetch_enable; - logic ic_scr_key_valid; - } delayed_inputs_t; - - delayed_inputs_t [LockstepOffset-1:0] shadow_inputs_q; - delayed_inputs_t shadow_inputs_in; - logic [6:0] instr_rdata_intg_q, data_rdata_intg_q; - // Packed arrays must be dealt with separately - logic [TagSizeECC-1:0] shadow_tag_rdata_q [IC_NUM_WAYS][LockstepOffset]; - logic [LineSizeECC-1:0] shadow_data_rdata_q [IC_NUM_WAYS][LockstepOffset]; - - // Assign the inputs to the delay structure - assign shadow_inputs_in.instr_gnt = instr_gnt_i; - assign shadow_inputs_in.instr_rvalid = instr_rvalid_i; - assign shadow_inputs_in.instr_rdata = instr_rdata_i; - assign shadow_inputs_in.instr_err = instr_err_i; - assign shadow_inputs_in.data_gnt = data_gnt_i; - assign shadow_inputs_in.data_rvalid = data_rvalid_i; - assign shadow_inputs_in.data_rdata = data_rdata_i; - assign shadow_inputs_in.data_err = data_err_i; - assign shadow_inputs_in.rf_rdata_a_ecc = rf_rdata_a_ecc_i; - assign shadow_inputs_in.rf_rdata_b_ecc = rf_rdata_b_ecc_i; - assign shadow_inputs_in.irq_software = irq_software_i; - assign shadow_inputs_in.irq_timer = irq_timer_i; - assign shadow_inputs_in.irq_external = irq_external_i; - assign shadow_inputs_in.irq_fast = irq_fast_i; - assign shadow_inputs_in.irq_nm = irq_nm_i; - assign shadow_inputs_in.debug_req = debug_req_i; - assign shadow_inputs_in.fetch_enable = fetch_enable_i; - assign shadow_inputs_in.ic_scr_key_valid = ic_scr_key_valid_i; - - // Delay the inputs - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - instr_rdata_intg_q <= '0; - data_rdata_intg_q <= '0; - for (int unsigned i = 0; i < LockstepOffset; i++) begin - shadow_inputs_q[i] <= delayed_inputs_t'('0); - shadow_tag_rdata_q[i] <= '{default: 0}; - shadow_data_rdata_q[i] <= '{default: 0}; - end - end else begin - instr_rdata_intg_q <= instr_rdata_intg_i; - data_rdata_intg_q <= data_rdata_intg_i; - for (int unsigned i = 0; i < LockstepOffset - 1; i++) begin - shadow_inputs_q[i] <= shadow_inputs_q[i+1]; - shadow_tag_rdata_q[i] <= shadow_tag_rdata_q[i+1]; - shadow_data_rdata_q[i] <= shadow_data_rdata_q[i+1]; - end - shadow_inputs_q[LockstepOffset-1] <= shadow_inputs_in; - shadow_tag_rdata_q[LockstepOffset-1] <= ic_tag_rdata_i; - shadow_data_rdata_q[LockstepOffset-1] <= ic_data_rdata_i; - end - end - - //////////////////////////// - // Bus integrity checking // - //////////////////////////// - - // SEC_CM: BUS.INTEGRITY - logic bus_intg_err; - logic [1:0] instr_intg_err, data_intg_err; - logic [31:0] unused_wdata; - - // Checks on incoming data - prim_secded_inv_39_32_dec u_instr_intg_dec ( - .data_i ({instr_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].instr_rdata}), - .data_o (), - .syndrome_o (), - .err_o (instr_intg_err) - ); - - prim_secded_inv_39_32_dec u_data_intg_dec ( - .data_i ({data_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].data_rdata}), - .data_o (), - .syndrome_o (), - .err_o (data_intg_err) - ); - - assign bus_intg_err = (shadow_inputs_q[LockstepOffset-1].instr_rvalid & |instr_intg_err) | - (shadow_inputs_q[LockstepOffset-1].data_rvalid & |data_intg_err); - - // Generate integrity bits - prim_secded_inv_39_32_enc u_data_gen ( - .data_i (data_wdata_i), - .data_o ({data_wdata_intg_o, unused_wdata}) - ); - - /////////////////// - // Output delays // - /////////////////// - - typedef struct packed { - logic instr_req; - logic [31:0] instr_addr; - logic data_req; - logic data_we; - logic [3:0] data_be; - logic [31:0] data_addr; - logic [31:0] data_wdata; - logic dummy_instr_id; - logic [4:0] rf_raddr_a; - logic [4:0] rf_raddr_b; - logic [4:0] rf_waddr_wb; - logic rf_we_wb; - logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc; - logic [IC_NUM_WAYS-1:0] ic_tag_req; - logic ic_tag_write; - logic [IC_INDEX_W-1:0] ic_tag_addr; - logic [TagSizeECC-1:0] ic_tag_wdata; - logic [IC_NUM_WAYS-1:0] ic_data_req; - logic ic_data_write; - logic [IC_INDEX_W-1:0] ic_data_addr; - logic [LineSizeECC-1:0] ic_data_wdata; - logic irq_pending; - crash_dump_t crash_dump; - logic double_fault_seen; - logic icache_inval; - logic core_busy; - } delayed_outputs_t; - - delayed_outputs_t [OutputsOffset-1:0] core_outputs_q; - delayed_outputs_t core_outputs_in; - delayed_outputs_t shadow_outputs_d, shadow_outputs_q; - - // Assign core outputs to the structure - assign core_outputs_in.instr_req = instr_req_i; - assign core_outputs_in.instr_addr = instr_addr_i; - assign core_outputs_in.data_req = data_req_i; - assign core_outputs_in.data_we = data_we_i; - assign core_outputs_in.data_be = data_be_i; - assign core_outputs_in.data_addr = data_addr_i; - assign core_outputs_in.data_wdata = data_wdata_i; - assign core_outputs_in.dummy_instr_id = dummy_instr_id_i; - assign core_outputs_in.rf_raddr_a = rf_raddr_a_i; - assign core_outputs_in.rf_raddr_b = rf_raddr_b_i; - assign core_outputs_in.rf_waddr_wb = rf_waddr_wb_i; - assign core_outputs_in.rf_we_wb = rf_we_wb_i; - assign core_outputs_in.rf_wdata_wb_ecc = rf_wdata_wb_ecc_i; - assign core_outputs_in.ic_tag_req = ic_tag_req_i; - assign core_outputs_in.ic_tag_write = ic_tag_write_i; - assign core_outputs_in.ic_tag_addr = ic_tag_addr_i; - assign core_outputs_in.ic_tag_wdata = ic_tag_wdata_i; - assign core_outputs_in.ic_data_req = ic_data_req_i; - assign core_outputs_in.ic_data_write = ic_data_write_i; - assign core_outputs_in.ic_data_addr = ic_data_addr_i; - assign core_outputs_in.ic_data_wdata = ic_data_wdata_i; - assign core_outputs_in.irq_pending = irq_pending_i; - assign core_outputs_in.crash_dump = crash_dump_i; - assign core_outputs_in.double_fault_seen = double_fault_seen_i; - assign core_outputs_in.icache_inval = icache_inval_i; - assign core_outputs_in.core_busy = core_busy_i; - - // Delay the outputs - always_ff @(posedge clk_i) begin - for (int unsigned i = 0; i < OutputsOffset - 1; i++) begin - core_outputs_q[i] <= core_outputs_q[i+1]; - end - core_outputs_q[OutputsOffset-1] <= core_outputs_in; - end - - /////////////////////////////// - // Shadow core instantiation // - /////////////////////////////// - - logic shadow_alert_minor, shadow_alert_major; - - ibex_core #( - .PMPEnable ( PMPEnable ), - .PMPGranularity ( PMPGranularity ), - .PMPNumRegions ( PMPNumRegions ), - .MHPMCounterNum ( MHPMCounterNum ), - .MHPMCounterWidth ( MHPMCounterWidth ), - .RV32E ( RV32E ), - .RV32M ( RV32M ), - .RV32B ( RV32B ), - .BranchTargetALU ( BranchTargetALU ), - .ICache ( ICache ), - .ICacheECC ( ICacheECC ), - .BusSizeECC ( BusSizeECC ), - .TagSizeECC ( TagSizeECC ), - .LineSizeECC ( LineSizeECC ), - .BranchPredictor ( BranchPredictor ), - .DbgTriggerEn ( DbgTriggerEn ), - .DbgHwBreakNum ( DbgHwBreakNum ), - .WritebackStage ( WritebackStage ), - .ResetAll ( ResetAll ), - .RndCnstLfsrSeed ( RndCnstLfsrSeed ), - .RndCnstLfsrPerm ( RndCnstLfsrPerm ), - .SecureIbex ( SecureIbex ), - .DummyInstructions ( DummyInstructions ), - .RegFileECC ( RegFileECC ), - .RegFileDataWidth ( RegFileDataWidth ), - .DmHaltAddr ( DmHaltAddr ), - .DmExceptionAddr ( DmExceptionAddr ) - ) u_shadow_core ( - .clk_i (clk_i), - .rst_ni (rst_shadow_n), - - .hart_id_i (hart_id_i), - .boot_addr_i (boot_addr_i), - - .instr_req_o (shadow_outputs_d.instr_req), - .instr_gnt_i (shadow_inputs_q[0].instr_gnt), - .instr_rvalid_i (shadow_inputs_q[0].instr_rvalid), - .instr_addr_o (shadow_outputs_d.instr_addr), - .instr_rdata_i (shadow_inputs_q[0].instr_rdata), - .instr_err_i (shadow_inputs_q[0].instr_err), - - .data_req_o (shadow_outputs_d.data_req), - .data_gnt_i (shadow_inputs_q[0].data_gnt), - .data_rvalid_i (shadow_inputs_q[0].data_rvalid), - .data_we_o (shadow_outputs_d.data_we), - .data_be_o (shadow_outputs_d.data_be), - .data_addr_o (shadow_outputs_d.data_addr), - .data_wdata_o (shadow_outputs_d.data_wdata), - .data_rdata_i (shadow_inputs_q[0].data_rdata), - .data_err_i (shadow_inputs_q[0].data_err), - - .dummy_instr_id_o (shadow_outputs_d.dummy_instr_id), - .rf_raddr_a_o (shadow_outputs_d.rf_raddr_a), - .rf_raddr_b_o (shadow_outputs_d.rf_raddr_b), - .rf_waddr_wb_o (shadow_outputs_d.rf_waddr_wb), - .rf_we_wb_o (shadow_outputs_d.rf_we_wb), - .rf_wdata_wb_ecc_o (shadow_outputs_d.rf_wdata_wb_ecc), - .rf_rdata_a_ecc_i (shadow_inputs_q[0].rf_rdata_a_ecc), - .rf_rdata_b_ecc_i (shadow_inputs_q[0].rf_rdata_b_ecc), - - .ic_tag_req_o (shadow_outputs_d.ic_tag_req), - .ic_tag_write_o (shadow_outputs_d.ic_tag_write), - .ic_tag_addr_o (shadow_outputs_d.ic_tag_addr), - .ic_tag_wdata_o (shadow_outputs_d.ic_tag_wdata), - .ic_tag_rdata_i (shadow_tag_rdata_q[0]), - .ic_data_req_o (shadow_outputs_d.ic_data_req), - .ic_data_write_o (shadow_outputs_d.ic_data_write), - .ic_data_addr_o (shadow_outputs_d.ic_data_addr), - .ic_data_wdata_o (shadow_outputs_d.ic_data_wdata), - .ic_data_rdata_i (shadow_data_rdata_q[0]), - .ic_scr_key_valid_i (shadow_inputs_q[0].ic_scr_key_valid), - - .irq_software_i (shadow_inputs_q[0].irq_software), - .irq_timer_i (shadow_inputs_q[0].irq_timer), - .irq_external_i (shadow_inputs_q[0].irq_external), - .irq_fast_i (shadow_inputs_q[0].irq_fast), - .irq_nm_i (shadow_inputs_q[0].irq_nm), - .irq_pending_o (shadow_outputs_d.irq_pending), - - .debug_req_i (shadow_inputs_q[0].debug_req), - .crash_dump_o (shadow_outputs_d.crash_dump), - .double_fault_seen_o (shadow_outputs_d.double_fault_seen), - -`ifdef RVFI - .rvfi_valid (), - .rvfi_order (), - .rvfi_insn (), - .rvfi_trap (), - .rvfi_halt (), - .rvfi_intr (), - .rvfi_mode (), - .rvfi_ixl (), - .rvfi_rs1_addr (), - .rvfi_rs2_addr (), - .rvfi_rs3_addr (), - .rvfi_rs1_rdata (), - .rvfi_rs2_rdata (), - .rvfi_rs3_rdata (), - .rvfi_rd_addr (), - .rvfi_rd_wdata (), - .rvfi_pc_rdata (), - .rvfi_pc_wdata (), - .rvfi_mem_addr (), - .rvfi_mem_rmask (), - .rvfi_mem_wmask (), - .rvfi_mem_rdata (), - .rvfi_mem_wdata (), - .rvfi_ext_mip (), - .rvfi_ext_nmi (), - .rvfi_ext_debug_req (), - .rvfi_ext_mcycle (), -`endif - - .fetch_enable_i (shadow_inputs_q[0].fetch_enable), - .alert_minor_o (shadow_alert_minor), - .alert_major_o (shadow_alert_major), - .icache_inval_o (shadow_outputs_d.icache_inval), - .core_busy_o (shadow_outputs_d.core_busy) - ); - - // Register the shadow core outputs - always_ff @(posedge clk_i) begin - shadow_outputs_q <= shadow_outputs_d; - end - - ///////////////////////// - // Compare the outputs // - ///////////////////////// - - logic outputs_mismatch; - - assign outputs_mismatch = enable_cmp_q & (shadow_outputs_q != core_outputs_q[0]); - assign alert_major_internal_o = outputs_mismatch | shadow_alert_major; - assign alert_major_bus_o = bus_intg_err; - assign alert_minor_o = shadow_alert_minor; - -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_fpga.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_fpga.sv deleted file mode 100644 index 678549ab..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_fpga.sv +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright lowRISC contributors. -// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * RISC-V register file - * - * Register file with 31 or 15x 32 bit wide registers. Register 0 is fixed to 0. - * - * This register file is designed to make FPGA synthesis tools infer RAM primitives. For Xilinx - * FPGA architectures, it will produce RAM32M primitives. Other vendors have not yet been tested. - */ -module ibex_register_file_fpga #( - parameter bit RV32E = 0, - parameter int unsigned DataWidth = 32, - parameter bit DummyInstructions = 0, - parameter logic [DataWidth-1:0] WordZeroVal = '0 -) ( - // Clock and Reset - input logic clk_i, - input logic rst_ni, - - input logic test_en_i, - input logic dummy_instr_id_i, - - //Read port R1 - input logic [ 4:0] raddr_a_i, - output logic [DataWidth-1:0] rdata_a_o, - //Read port R2 - input logic [ 4:0] raddr_b_i, - output logic [DataWidth-1:0] rdata_b_o, - // Write port W1 - input logic [ 4:0] waddr_a_i, - input logic [DataWidth-1:0] wdata_a_i, - input logic we_a_i -); - - localparam int ADDR_WIDTH = RV32E ? 4 : 5; - localparam int NUM_WORDS = 2 ** ADDR_WIDTH; - - logic [DataWidth-1:0] mem[NUM_WORDS]; - logic we; // write enable if writing to any register other than R0 - - // async_read a - assign rdata_a_o = (raddr_a_i == '0) ? '0 : mem[raddr_a_i]; - - // async_read b - assign rdata_b_o = (raddr_b_i == '0) ? '0 : mem[raddr_b_i]; - - // we select - assign we = (waddr_a_i == '0) ? 1'b0 : we_a_i; - - // Note that the SystemVerilog LRM requires variables on the LHS of assignments within - // "always_ff" to not be written to by any other process. However, to enable the initialization - // of the inferred RAM32M primitives with non-zero values, below "initial" procedure is needed. - // Therefore, we use "always" instead of the generally preferred "always_ff" for the synchronous - // write procedure. - always @(posedge clk_i) begin : sync_write - if (we == 1'b1) begin - mem[waddr_a_i] <= wdata_a_i; - end - end : sync_write - - // Make sure we initialize the BRAM with the correct register reset value. - initial begin - for (int k = 0; k < NUM_WORDS; k++) begin - mem[k] = WordZeroVal; - end - end - - // Reset not used in this register file version - logic unused_rst_ni; - assign unused_rst_ni = rst_ni; - - // Dummy instruction changes not relevant for FPGA implementation - logic unused_dummy_instr; - assign unused_dummy_instr = dummy_instr_id_i; - // Test enable signal not used in FPGA implementation - logic unused_test_en; - assign unused_test_en = test_en_i; - -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_latch.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_latch.sv deleted file mode 100644 index f1e4df75..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_register_file_latch.sv +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright lowRISC contributors. -// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * RISC-V register file - * - * Register file with 31 or 15x 32 bit wide registers. Register 0 is fixed to 0. - * This register file is based on latches and is thus smaller than the flip-flop - * based RF. It requires a target technology-specific clock gating cell. Use this - * register file when targeting ASIC synthesis or event-based simulators. - */ -module ibex_register_file_latch #( - parameter bit RV32E = 0, - parameter int unsigned DataWidth = 32, - parameter bit DummyInstructions = 0, - parameter logic [DataWidth-1:0] WordZeroVal = '0 -) ( - // Clock and Reset - input logic clk_i, - input logic rst_ni, - - input logic test_en_i, - input logic dummy_instr_id_i, - - //Read port R1 - input logic [4:0] raddr_a_i, - output logic [DataWidth-1:0] rdata_a_o, - - //Read port R2 - input logic [4:0] raddr_b_i, - output logic [DataWidth-1:0] rdata_b_o, - - // Write port W1 - input logic [4:0] waddr_a_i, - input logic [DataWidth-1:0] wdata_a_i, - input logic we_a_i - -); - - localparam int unsigned ADDR_WIDTH = RV32E ? 4 : 5; - localparam int unsigned NUM_WORDS = 2**ADDR_WIDTH; - - logic [DataWidth-1:0] mem[NUM_WORDS]; - - logic [NUM_WORDS-1:1] waddr_onehot_a; - - logic [NUM_WORDS-1:1] mem_clocks; - logic [DataWidth-1:0] wdata_a_q; - - // internal addresses - logic [ADDR_WIDTH-1:0] raddr_a_int, raddr_b_int, waddr_a_int; - - assign raddr_a_int = raddr_a_i[ADDR_WIDTH-1:0]; - assign raddr_b_int = raddr_b_i[ADDR_WIDTH-1:0]; - assign waddr_a_int = waddr_a_i[ADDR_WIDTH-1:0]; - - logic clk_int; - - ////////// - // READ // - ////////// - assign rdata_a_o = mem[raddr_a_int]; - assign rdata_b_o = mem[raddr_b_int]; - - /////////// - // WRITE // - /////////// - // Global clock gating - prim_clock_gating cg_we_global ( - .clk_i ( clk_i ), - .en_i ( we_a_i ), - .test_en_i ( test_en_i ), - .clk_o ( clk_int ) - ); - - // Sample input data - // Use clk_int here, since otherwise we don't want to write anything anyway. - always_ff @(posedge clk_int or negedge rst_ni) begin : sample_wdata - if (!rst_ni) begin - wdata_a_q <= WordZeroVal; - end else begin - if (we_a_i) begin - wdata_a_q <= wdata_a_i; - end - end - end - - // Write address decoding - always_comb begin : wad - for (int i = 1; i < NUM_WORDS; i++) begin : wad_word_iter - if (we_a_i && (waddr_a_int == 5'(i))) begin - waddr_onehot_a[i] = 1'b1; - end else begin - waddr_onehot_a[i] = 1'b0; - end - end - end - - // Individual clock gating (if integrated clock-gating cells are available) - for (genvar x = 1; x < NUM_WORDS; x++) begin : gen_cg_word_iter - prim_clock_gating cg_i ( - .clk_i ( clk_int ), - .en_i ( waddr_onehot_a[x] ), - .test_en_i ( test_en_i ), - .clk_o ( mem_clocks[x] ) - ); - end - - // Actual write operation: - // Generate the sequential process for the NUM_WORDS words of the memory. - // The process is synchronized with the clocks mem_clocks[i], i = 1, ..., NUM_WORDS-1. - for (genvar i = 1; i < NUM_WORDS; i++) begin : g_rf_latches - always_latch begin - if (mem_clocks[i]) begin - mem[i] = wdata_a_q; - end - end - end - - // With dummy instructions enabled, R0 behaves as a real register but will always return 0 for - // real instructions. - if (DummyInstructions) begin : g_dummy_r0 - // SEC_CM: CTRL_FLOW.UNPREDICTABLE - logic we_r0_dummy; - logic r0_clock; - logic [DataWidth-1:0] mem_r0; - - // Write enable for dummy R0 register (waddr_a_i will always be 0 for dummy instructions) - assign we_r0_dummy = we_a_i & dummy_instr_id_i; - - // R0 clock gate - prim_clock_gating cg_i ( - .clk_i ( clk_int ), - .en_i ( we_r0_dummy ), - .test_en_i ( test_en_i ), - .clk_o ( r0_clock ) - ); - - always_latch begin : latch_wdata - if (r0_clock) begin - mem_r0 = wdata_a_q; - end - end - - // Output the dummy data for dummy instructions, otherwise R0 reads as zero - assign mem[0] = dummy_instr_id_i ? mem_r0 : WordZeroVal; - - end else begin : g_normal_r0 - logic unused_dummy_instr_id; - assign unused_dummy_instr_id = dummy_instr_id_i; - - assign mem[0] = WordZeroVal; - end - -`ifdef VERILATOR - initial begin - $display("Latch-based register file not supported for Verilator simulation"); - $fatal; - end -`endif - -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top.sv deleted file mode 100644 index b566bb17..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_top.sv +++ /dev/null @@ -1,978 +0,0 @@ -// Copyright lowRISC contributors. -// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -`ifdef RISCV_FORMAL - `define RVFI -`endif - -`include "prim_assert.sv" - -/** - * Top level module of the ibex RISC-V core - */ -module ibex_top import ibex_pkg::*; #( - parameter bit PMPEnable = 1'b0, - parameter int unsigned PMPGranularity = 0, - parameter int unsigned PMPNumRegions = 4, - parameter int unsigned MHPMCounterNum = 0, - parameter int unsigned MHPMCounterWidth = 40, - parameter bit RV32E = 1'b0, - parameter rv32m_e RV32M = RV32MFast, - parameter rv32b_e RV32B = RV32BNone, - parameter regfile_e RegFile = RegFileFF, - parameter bit BranchTargetALU = 1'b0, - parameter bit WritebackStage = 1'b0, - parameter bit ICache = 1'b0, - parameter bit ICacheECC = 1'b0, - parameter bit BranchPredictor = 1'b0, - parameter bit DbgTriggerEn = 1'b0, - parameter int unsigned DbgHwBreakNum = 1, - parameter bit SecureIbex = 1'b0, - parameter bit ICacheScramble = 1'b0, - parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, - parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, - parameter int unsigned DmHaltAddr = 32'h1A110800, - parameter int unsigned DmExceptionAddr = 32'h1A110808, - // Default seed and nonce for scrambling - parameter logic [SCRAMBLE_KEY_W-1:0] RndCnstIbexKey = RndCnstIbexKeyDefault, - parameter logic [SCRAMBLE_NONCE_W-1:0] RndCnstIbexNonce = RndCnstIbexNonceDefault -) ( - // Clock and Reset - input logic clk_i, - input logic rst_ni, - - input logic test_en_i, // enable all clock gates for testing - input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, - - input logic [31:0] hart_id_i, - input logic [31:0] boot_addr_i, - - // Instruction memory interface - output logic instr_req_o, - input logic instr_gnt_i, - input logic instr_rvalid_i, - output logic [31:0] instr_addr_o, - input logic [31:0] instr_rdata_i, - input logic [6:0] instr_rdata_intg_i, - input logic instr_err_i, - - // Data memory interface - output logic data_req_o, - input logic data_gnt_i, - input logic data_rvalid_i, - output logic data_we_o, - output logic [3:0] data_be_o, - output logic [31:0] data_addr_o, - output logic [31:0] data_wdata_o, - output logic [6:0] data_wdata_intg_o, - input logic [31:0] data_rdata_i, - input logic [6:0] data_rdata_intg_i, - input logic data_err_i, - - // Interrupt inputs - input logic irq_software_i, - input logic irq_timer_i, - input logic irq_external_i, - input logic [14:0] irq_fast_i, - input logic irq_nm_i, // non-maskeable interrupt - - // Scrambling Interface - input logic scramble_key_valid_i, - input logic [SCRAMBLE_KEY_W-1:0] scramble_key_i, - input logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_i, - output logic scramble_req_o, - - // Debug Interface - input logic debug_req_i, - output crash_dump_t crash_dump_o, - output logic double_fault_seen_o, - - // RISC-V Formal Interface - // Does not comply with the coding standards of _i/_o suffixes, but follows - // the convention of RISC-V Formal Interface Specification. -`ifdef RVFI - output logic rvfi_valid, - output logic [63:0] rvfi_order, - output logic [31:0] rvfi_insn, - output logic rvfi_trap, - output logic rvfi_halt, - output logic rvfi_intr, - output logic [ 1:0] rvfi_mode, - output logic [ 1:0] rvfi_ixl, - output logic [ 4:0] rvfi_rs1_addr, - output logic [ 4:0] rvfi_rs2_addr, - output logic [ 4:0] rvfi_rs3_addr, - output logic [31:0] rvfi_rs1_rdata, - output logic [31:0] rvfi_rs2_rdata, - output logic [31:0] rvfi_rs3_rdata, - output logic [ 4:0] rvfi_rd_addr, - output logic [31:0] rvfi_rd_wdata, - output logic [31:0] rvfi_pc_rdata, - output logic [31:0] rvfi_pc_wdata, - output logic [31:0] rvfi_mem_addr, - output logic [ 3:0] rvfi_mem_rmask, - output logic [ 3:0] rvfi_mem_wmask, - output logic [31:0] rvfi_mem_rdata, - output logic [31:0] rvfi_mem_wdata, - output logic [31:0] rvfi_ext_mip, - output logic rvfi_ext_nmi, - output logic rvfi_ext_debug_req, - output logic [63:0] rvfi_ext_mcycle, -`endif - - // CPU Control Signals - input fetch_enable_t fetch_enable_i, - output logic alert_minor_o, - output logic alert_major_internal_o, - output logic alert_major_bus_o, - output logic core_sleep_o, - - // DFT bypass controls - input logic scan_rst_ni -); - - localparam bit Lockstep = SecureIbex; - localparam bit ResetAll = Lockstep; - localparam bit DummyInstructions = SecureIbex; - localparam bit RegFileECC = SecureIbex; - localparam int unsigned RegFileDataWidth = RegFileECC ? 32 + 7 : 32; - // Icache parameters - localparam int unsigned BusSizeECC = ICacheECC ? (BUS_SIZE + 7) : BUS_SIZE; - localparam int unsigned LineSizeECC = BusSizeECC * IC_LINE_BEATS; - localparam int unsigned TagSizeECC = ICacheECC ? (IC_TAG_SIZE + 6) : IC_TAG_SIZE; - // Scrambling Parameter - localparam int unsigned NumAddrScrRounds = ICacheScramble ? 2 : 0; - localparam int unsigned NumDiffRounds = NumAddrScrRounds; - - // Clock signals - logic clk; - logic core_busy_d, core_busy_q; - logic clock_en; - logic irq_pending; - // Core <-> Register file signals - logic dummy_instr_id; - logic [4:0] rf_raddr_a; - logic [4:0] rf_raddr_b; - logic [4:0] rf_waddr_wb; - logic rf_we_wb; - logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc; - logic [RegFileDataWidth-1:0] rf_rdata_a_ecc, rf_rdata_a_ecc_buf; - logic [RegFileDataWidth-1:0] rf_rdata_b_ecc, rf_rdata_b_ecc_buf; - // Core <-> RAMs signals - logic [IC_NUM_WAYS-1:0] ic_tag_req; - logic ic_tag_write; - logic [IC_INDEX_W-1:0] ic_tag_addr; - logic [TagSizeECC-1:0] ic_tag_wdata; - logic [TagSizeECC-1:0] ic_tag_rdata [IC_NUM_WAYS]; - logic [IC_NUM_WAYS-1:0] ic_data_req; - logic ic_data_write; - logic [IC_INDEX_W-1:0] ic_data_addr; - logic [LineSizeECC-1:0] ic_data_wdata; - logic [LineSizeECC-1:0] ic_data_rdata [IC_NUM_WAYS]; - // Alert signals - logic core_alert_major, core_alert_minor; - logic lockstep_alert_major_internal, lockstep_alert_major_bus; - logic lockstep_alert_minor; - // Scramble signals - logic icache_inval; - logic [SCRAMBLE_KEY_W-1:0] scramble_key_q; - logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_q; - logic scramble_key_valid_d, scramble_key_valid_q; - logic scramble_req_d, scramble_req_q; - - fetch_enable_t fetch_enable_buf; - - ///////////////////// - // Main clock gate // - ///////////////////// - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - core_busy_q <= 1'b0; - end else begin - core_busy_q <= core_busy_d; - end - end - - assign clock_en = core_busy_q | debug_req_i | irq_pending | irq_nm_i; - assign core_sleep_o = ~clock_en; - - prim_clock_gating core_clock_gate_i ( - .clk_i (clk_i), - .en_i (clock_en), - .test_en_i(test_en_i), - .clk_o (clk) - ); - - //////////////////////// - // Core instantiation // - //////////////////////// - - // Buffer security critical signals to prevent synthesis optimisation removing them - prim_buf #(.Width($bits(fetch_enable_t))) u_fetch_enable_buf ( - .in_i (fetch_enable_i), - .out_o(fetch_enable_buf) - ); - - prim_buf #(.Width(RegFileDataWidth)) u_rf_rdata_a_ecc_buf ( - .in_i (rf_rdata_a_ecc), - .out_o(rf_rdata_a_ecc_buf) - ); - - prim_buf #(.Width(RegFileDataWidth)) u_rf_rdata_b_ecc_buf ( - .in_i (rf_rdata_b_ecc), - .out_o(rf_rdata_b_ecc_buf) - ); - - ibex_core #( - .PMPEnable (PMPEnable), - .PMPGranularity (PMPGranularity), - .PMPNumRegions (PMPNumRegions), - .MHPMCounterNum (MHPMCounterNum), - .MHPMCounterWidth (MHPMCounterWidth), - .RV32E (RV32E), - .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU (BranchTargetALU), - .ICache (ICache), - .ICacheECC (ICacheECC), - .BusSizeECC (BusSizeECC), - .TagSizeECC (TagSizeECC), - .LineSizeECC (LineSizeECC), - .BranchPredictor (BranchPredictor), - .DbgTriggerEn (DbgTriggerEn), - .DbgHwBreakNum (DbgHwBreakNum), - .WritebackStage (WritebackStage), - .ResetAll (ResetAll), - .RndCnstLfsrSeed (RndCnstLfsrSeed), - .RndCnstLfsrPerm (RndCnstLfsrPerm), - .SecureIbex (SecureIbex), - .DummyInstructions(DummyInstructions), - .RegFileECC (RegFileECC), - .RegFileDataWidth (RegFileDataWidth), - .DmHaltAddr (DmHaltAddr), - .DmExceptionAddr (DmExceptionAddr) - ) u_ibex_core ( - .clk_i(clk), - .rst_ni, - - .hart_id_i, - .boot_addr_i, - - .instr_req_o, - .instr_gnt_i, - .instr_rvalid_i, - .instr_addr_o, - .instr_rdata_i, - .instr_err_i, - - .data_req_o, - .data_gnt_i, - .data_rvalid_i, - .data_we_o, - .data_be_o, - .data_addr_o, - .data_wdata_o, - .data_rdata_i, - .data_err_i, - - .dummy_instr_id_o (dummy_instr_id), - .rf_raddr_a_o (rf_raddr_a), - .rf_raddr_b_o (rf_raddr_b), - .rf_waddr_wb_o (rf_waddr_wb), - .rf_we_wb_o (rf_we_wb), - .rf_wdata_wb_ecc_o(rf_wdata_wb_ecc), - .rf_rdata_a_ecc_i (rf_rdata_a_ecc_buf), - .rf_rdata_b_ecc_i (rf_rdata_b_ecc_buf), - - .ic_tag_req_o (ic_tag_req), - .ic_tag_write_o (ic_tag_write), - .ic_tag_addr_o (ic_tag_addr), - .ic_tag_wdata_o (ic_tag_wdata), - .ic_tag_rdata_i (ic_tag_rdata), - .ic_data_req_o (ic_data_req), - .ic_data_write_o (ic_data_write), - .ic_data_addr_o (ic_data_addr), - .ic_data_wdata_o (ic_data_wdata), - .ic_data_rdata_i (ic_data_rdata), - .ic_scr_key_valid_i(scramble_key_valid_q), - - .irq_software_i, - .irq_timer_i, - .irq_external_i, - .irq_fast_i, - .irq_nm_i, - .irq_pending_o(irq_pending), - - .debug_req_i, - .crash_dump_o, - .double_fault_seen_o, - -`ifdef RVFI - .rvfi_valid, - .rvfi_order, - .rvfi_insn, - .rvfi_trap, - .rvfi_halt, - .rvfi_intr, - .rvfi_mode, - .rvfi_ixl, - .rvfi_rs1_addr, - .rvfi_rs2_addr, - .rvfi_rs3_addr, - .rvfi_rs1_rdata, - .rvfi_rs2_rdata, - .rvfi_rs3_rdata, - .rvfi_rd_addr, - .rvfi_rd_wdata, - .rvfi_pc_rdata, - .rvfi_pc_wdata, - .rvfi_mem_addr, - .rvfi_mem_rmask, - .rvfi_mem_wmask, - .rvfi_mem_rdata, - .rvfi_mem_wdata, - .rvfi_ext_mip, - .rvfi_ext_nmi, - .rvfi_ext_debug_req, - .rvfi_ext_mcycle, -`endif - - .fetch_enable_i(fetch_enable_buf), - .alert_minor_o (core_alert_minor), - .alert_major_o (core_alert_major), - .icache_inval_o(icache_inval), - .core_busy_o (core_busy_d) - ); - - ///////////////////////////////// - // Register file Instantiation // - ///////////////////////////////// - - if (RegFile == RegFileFF) begin : gen_regfile_ff - ibex_register_file_ff #( - .RV32E (RV32E), - .DataWidth (RegFileDataWidth), - .DummyInstructions(DummyInstructions), - .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord)) - ) register_file_i ( - .clk_i (clk), - .rst_ni(rst_ni), - - .test_en_i (test_en_i), - .dummy_instr_id_i(dummy_instr_id), - - .raddr_a_i(rf_raddr_a), - .rdata_a_o(rf_rdata_a_ecc), - .raddr_b_i(rf_raddr_b), - .rdata_b_o(rf_rdata_b_ecc), - .waddr_a_i(rf_waddr_wb), - .wdata_a_i(rf_wdata_wb_ecc), - .we_a_i (rf_we_wb) - ); - end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga - ibex_register_file_fpga #( - .RV32E (RV32E), - .DataWidth (RegFileDataWidth), - .DummyInstructions(DummyInstructions), - .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord)) - ) register_file_i ( - .clk_i (clk), - .rst_ni(rst_ni), - - .test_en_i (test_en_i), - .dummy_instr_id_i(dummy_instr_id), - - .raddr_a_i(rf_raddr_a), - .rdata_a_o(rf_rdata_a_ecc), - .raddr_b_i(rf_raddr_b), - .rdata_b_o(rf_rdata_b_ecc), - .waddr_a_i(rf_waddr_wb), - .wdata_a_i(rf_wdata_wb_ecc), - .we_a_i (rf_we_wb) - ); - end else if (RegFile == RegFileLatch) begin : gen_regfile_latch - ibex_register_file_latch #( - .RV32E (RV32E), - .DataWidth (RegFileDataWidth), - .DummyInstructions(DummyInstructions), - .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord)) - ) register_file_i ( - .clk_i (clk), - .rst_ni(rst_ni), - - .test_en_i (test_en_i), - .dummy_instr_id_i(dummy_instr_id), - - .raddr_a_i(rf_raddr_a), - .rdata_a_o(rf_rdata_a_ecc), - .raddr_b_i(rf_raddr_b), - .rdata_b_o(rf_rdata_b_ecc), - .waddr_a_i(rf_waddr_wb), - .wdata_a_i(rf_wdata_wb_ecc), - .we_a_i (rf_we_wb) - ); - end - - /////////////////////////////// - // Scrambling Infrastructure // - /////////////////////////////// - - if (ICacheScramble) begin : gen_scramble - - // SEC_CM: ICACHE.MEM.SCRAMBLE - // Scramble key valid starts with OTP returning new valid key and stays high - // until we request a new valid key. - assign scramble_key_valid_d = scramble_req_q ? scramble_key_valid_i : - icache_inval ? 1'b0 : - scramble_key_valid_q; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - scramble_key_q <= RndCnstIbexKey; - scramble_nonce_q <= RndCnstIbexNonce; - end else if (scramble_key_valid_i) begin - scramble_key_q <= scramble_key_i; - scramble_nonce_q <= scramble_nonce_i; - end - end - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - scramble_key_valid_q <= 1'b1; - scramble_req_q <= '0; - end else begin - scramble_key_valid_q <= scramble_key_valid_d; - scramble_req_q <= scramble_req_d; - end - end - - // Scramble key request starts with invalidate signal from ICache and stays high - // until we got a valid key. - assign scramble_req_d = scramble_req_q ? ~scramble_key_valid_i : icache_inval; - assign scramble_req_o = scramble_req_q; - - end else begin : gen_noscramble - - logic unused_scramble_inputs = scramble_key_valid_i & (|scramble_key_i) & (|RndCnstIbexKey) & - (|scramble_nonce_i) & (|RndCnstIbexNonce) & scramble_req_q & - icache_inval & scramble_key_valid_d & scramble_req_d; - - assign scramble_req_d = 1'b0; - assign scramble_req_q = 1'b0; - assign scramble_req_o = 1'b0; - assign scramble_key_q = '0; - assign scramble_nonce_q = '0; - assign scramble_key_valid_q = 1'b1; - assign scramble_key_valid_d = 1'b1; - end - - //////////////////////// - // Rams Instantiation // - //////////////////////// - - if (ICache) begin : gen_rams - - for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams_inner - - // SEC_CM: ICACHE.MEM.SCRAMBLE - // Tag RAM instantiation - prim_ram_1p_scr #( - .Width (TagSizeECC), - .Depth (IC_NUM_LINES), - .DataBitsPerMask (TagSizeECC), - .EnableParity (0), - .DiffWidth (TagSizeECC), - .NumAddrScrRounds (NumAddrScrRounds), - .NumDiffRounds (NumDiffRounds) - ) tag_bank ( - .clk_i, - .rst_ni, - - .key_valid_i (scramble_key_valid_q), - .key_i (scramble_key_q), - .nonce_i (scramble_nonce_q), - - .req_i (ic_tag_req[way]), - - .gnt_o (), - .write_i (ic_tag_write), - .addr_i (ic_tag_addr), - .wdata_i (ic_tag_wdata), - .wmask_i ({TagSizeECC{1'b1}}), - .intg_error_i(1'b0), - - .rdata_o (ic_tag_rdata[way]), - .rvalid_o (), - .raddr_o (), - .rerror_o (), - .cfg_i (ram_cfg_i) - ); - - // Data RAM instantiation - prim_ram_1p_scr #( - .Width (LineSizeECC), - .Depth (IC_NUM_LINES), - .DataBitsPerMask (LineSizeECC), - .ReplicateKeyStream (1), - .EnableParity (0), - .DiffWidth (LineSizeECC), - .NumAddrScrRounds (NumAddrScrRounds), - .NumDiffRounds (NumDiffRounds) - ) data_bank ( - .clk_i, - .rst_ni, - - .key_valid_i (scramble_key_valid_q), - .key_i (scramble_key_q), - .nonce_i (scramble_nonce_q), - - .req_i (ic_data_req[way]), - - .gnt_o (), - .write_i (ic_data_write), - .addr_i (ic_data_addr), - .wdata_i (ic_data_wdata), - .wmask_i ({LineSizeECC{1'b1}}), - .intg_error_i(1'b0), - - .rdata_o (ic_data_rdata[way]), - .rvalid_o (), - .raddr_o (), - .rerror_o (), - .cfg_i (ram_cfg_i) - ); - end - - end else begin : gen_norams - - prim_ram_1p_pkg::ram_1p_cfg_t unused_ram_cfg; - logic unused_ram_inputs; - - assign unused_ram_cfg = ram_cfg_i; - assign unused_ram_inputs = (|ic_tag_req) & ic_tag_write & (|ic_tag_addr) & (|ic_tag_wdata) & - (|ic_data_req) & ic_data_write & (|ic_data_addr) & (|ic_data_wdata) & - (|scramble_key_q) & (|scramble_nonce_q) & scramble_key_valid_q & - scramble_key_valid_d & (|scramble_nonce_q) & - (|NumAddrScrRounds); - - assign ic_tag_rdata = '{default:'b0}; - assign ic_data_rdata = '{default:'b0}; - - end - - // Redundant lockstep core implementation - if (Lockstep) begin : gen_lockstep - // SEC_CM: LOGIC.SHADOW - // Note: certain synthesis tools like DC are very smart at optimizing away redundant logic. - // Hence, we have to insert an optimization barrier at the IOs of the lockstep Ibex. - // This is achieved by manually buffering each bit using prim_buf. - // Our Xilinx and DC synthesis flows make sure that these buffers cannot be optimized away - // using keep attributes (Vivado) and size_only constraints (DC). - - localparam int NumBufferBits = $bits({ - hart_id_i, - boot_addr_i, - instr_req_o, - instr_gnt_i, - instr_rvalid_i, - instr_addr_o, - instr_rdata_i, - instr_rdata_intg_i, - instr_err_i, - data_req_o, - data_gnt_i, - data_rvalid_i, - data_we_o, - data_be_o, - data_addr_o, - data_wdata_o, - data_rdata_i, - data_rdata_intg_i, - data_err_i, - dummy_instr_id, - rf_raddr_a, - rf_raddr_b, - rf_waddr_wb, - rf_we_wb, - rf_wdata_wb_ecc, - rf_rdata_a_ecc, - rf_rdata_b_ecc, - ic_tag_req, - ic_tag_write, - ic_tag_addr, - ic_tag_wdata, - ic_data_req, - ic_data_write, - ic_data_addr, - ic_data_wdata, - scramble_key_valid_i, - irq_software_i, - irq_timer_i, - irq_external_i, - irq_fast_i, - irq_nm_i, - irq_pending, - debug_req_i, - crash_dump_o, - double_fault_seen_o, - fetch_enable_i, - icache_inval, - core_busy_d - }); - - logic [NumBufferBits-1:0] buf_in, buf_out; - - logic [31:0] hart_id_local; - logic [31:0] boot_addr_local; - - logic instr_req_local; - logic instr_gnt_local; - logic instr_rvalid_local; - logic [31:0] instr_addr_local; - logic [31:0] instr_rdata_local; - logic [6:0] instr_rdata_intg_local; - logic instr_err_local; - - logic data_req_local; - logic data_gnt_local; - logic data_rvalid_local; - logic data_we_local; - logic [3:0] data_be_local; - logic [31:0] data_addr_local; - logic [31:0] data_wdata_local; - logic [6:0] data_wdata_intg_local; - logic [31:0] data_rdata_local; - logic [6:0] data_rdata_intg_local; - logic data_err_local; - - logic dummy_instr_id_local; - logic [4:0] rf_raddr_a_local; - logic [4:0] rf_raddr_b_local; - logic [4:0] rf_waddr_wb_local; - logic rf_we_wb_local; - logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_local; - logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_local; - logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_local; - - logic [IC_NUM_WAYS-1:0] ic_tag_req_local; - logic ic_tag_write_local; - logic [IC_INDEX_W-1:0] ic_tag_addr_local; - logic [TagSizeECC-1:0] ic_tag_wdata_local; - logic [IC_NUM_WAYS-1:0] ic_data_req_local; - logic ic_data_write_local; - logic [IC_INDEX_W-1:0] ic_data_addr_local; - logic [LineSizeECC-1:0] ic_data_wdata_local; - logic scramble_key_valid_local; - - logic irq_software_local; - logic irq_timer_local; - logic irq_external_local; - logic [14:0] irq_fast_local; - logic irq_nm_local; - logic irq_pending_local; - - logic debug_req_local; - crash_dump_t crash_dump_local; - logic double_fault_seen_local; - fetch_enable_t fetch_enable_local; - - logic icache_inval_local; - logic core_busy_local; - - assign buf_in = { - hart_id_i, - boot_addr_i, - instr_req_o, - instr_gnt_i, - instr_rvalid_i, - instr_addr_o, - instr_rdata_i, - instr_rdata_intg_i, - instr_err_i, - data_req_o, - data_gnt_i, - data_rvalid_i, - data_we_o, - data_be_o, - data_addr_o, - data_wdata_o, - data_rdata_i, - data_rdata_intg_i, - data_err_i, - dummy_instr_id, - rf_raddr_a, - rf_raddr_b, - rf_waddr_wb, - rf_we_wb, - rf_wdata_wb_ecc, - rf_rdata_a_ecc, - rf_rdata_b_ecc, - ic_tag_req, - ic_tag_write, - ic_tag_addr, - ic_tag_wdata, - ic_data_req, - ic_data_write, - ic_data_addr, - ic_data_wdata, - scramble_key_valid_q, - irq_software_i, - irq_timer_i, - irq_external_i, - irq_fast_i, - irq_nm_i, - irq_pending, - debug_req_i, - crash_dump_o, - double_fault_seen_o, - fetch_enable_i, - icache_inval, - core_busy_d - }; - - assign { - hart_id_local, - boot_addr_local, - instr_req_local, - instr_gnt_local, - instr_rvalid_local, - instr_addr_local, - instr_rdata_local, - instr_rdata_intg_local, - instr_err_local, - data_req_local, - data_gnt_local, - data_rvalid_local, - data_we_local, - data_be_local, - data_addr_local, - data_wdata_local, - data_rdata_local, - data_rdata_intg_local, - data_err_local, - dummy_instr_id_local, - rf_raddr_a_local, - rf_raddr_b_local, - rf_waddr_wb_local, - rf_we_wb_local, - rf_wdata_wb_ecc_local, - rf_rdata_a_ecc_local, - rf_rdata_b_ecc_local, - ic_tag_req_local, - ic_tag_write_local, - ic_tag_addr_local, - ic_tag_wdata_local, - ic_data_req_local, - ic_data_write_local, - ic_data_addr_local, - ic_data_wdata_local, - scramble_key_valid_local, - irq_software_local, - irq_timer_local, - irq_external_local, - irq_fast_local, - irq_nm_local, - irq_pending_local, - debug_req_local, - crash_dump_local, - double_fault_seen_local, - fetch_enable_local, - icache_inval_local, - core_busy_local - } = buf_out; - - // Manually buffer all input signals. - prim_buf #(.Width(NumBufferBits)) u_signals_prim_buf ( - .in_i(buf_in), - .out_o(buf_out) - ); - - logic [TagSizeECC-1:0] ic_tag_rdata_local [IC_NUM_WAYS]; - logic [LineSizeECC-1:0] ic_data_rdata_local [IC_NUM_WAYS]; - for (genvar k = 0; k < IC_NUM_WAYS; k++) begin : gen_ways - prim_buf #(.Width(TagSizeECC)) u_tag_prim_buf ( - .in_i(ic_tag_rdata[k]), - .out_o(ic_tag_rdata_local[k]) - ); - prim_buf #(.Width(LineSizeECC)) u_data_prim_buf ( - .in_i(ic_data_rdata[k]), - .out_o(ic_data_rdata_local[k]) - ); - end - - logic lockstep_alert_minor_local, lockstep_alert_major_internal_local; - logic lockstep_alert_major_bus_local; - - ibex_lockstep #( - .PMPEnable (PMPEnable), - .PMPGranularity (PMPGranularity), - .PMPNumRegions (PMPNumRegions), - .MHPMCounterNum (MHPMCounterNum), - .MHPMCounterWidth (MHPMCounterWidth), - .RV32E (RV32E), - .RV32M (RV32M), - .RV32B (RV32B), - .BranchTargetALU (BranchTargetALU), - .ICache (ICache), - .ICacheECC (ICacheECC), - .BusSizeECC (BusSizeECC), - .TagSizeECC (TagSizeECC), - .LineSizeECC (LineSizeECC), - .BranchPredictor (BranchPredictor), - .DbgTriggerEn (DbgTriggerEn), - .DbgHwBreakNum (DbgHwBreakNum), - .WritebackStage (WritebackStage), - .ResetAll (ResetAll), - .RndCnstLfsrSeed (RndCnstLfsrSeed), - .RndCnstLfsrPerm (RndCnstLfsrPerm), - .SecureIbex (SecureIbex), - .DummyInstructions(DummyInstructions), - .RegFileECC (RegFileECC), - .RegFileDataWidth (RegFileDataWidth), - .DmHaltAddr (DmHaltAddr), - .DmExceptionAddr (DmExceptionAddr) - ) u_ibex_lockstep ( - .clk_i (clk), - .rst_ni (rst_ni), - - .hart_id_i (hart_id_local), - .boot_addr_i (boot_addr_local), - - .instr_req_i (instr_req_local), - .instr_gnt_i (instr_gnt_local), - .instr_rvalid_i (instr_rvalid_local), - .instr_addr_i (instr_addr_local), - .instr_rdata_i (instr_rdata_local), - .instr_rdata_intg_i (instr_rdata_intg_local), - .instr_err_i (instr_err_local), - - .data_req_i (data_req_local), - .data_gnt_i (data_gnt_local), - .data_rvalid_i (data_rvalid_local), - .data_we_i (data_we_local), - .data_be_i (data_be_local), - .data_addr_i (data_addr_local), - .data_wdata_i (data_wdata_local), - .data_wdata_intg_o (data_wdata_intg_local), - .data_rdata_i (data_rdata_local), - .data_rdata_intg_i (data_rdata_intg_local), - .data_err_i (data_err_local), - - .dummy_instr_id_i (dummy_instr_id_local), - .rf_raddr_a_i (rf_raddr_a_local), - .rf_raddr_b_i (rf_raddr_b_local), - .rf_waddr_wb_i (rf_waddr_wb_local), - .rf_we_wb_i (rf_we_wb_local), - .rf_wdata_wb_ecc_i (rf_wdata_wb_ecc_local), - .rf_rdata_a_ecc_i (rf_rdata_a_ecc_local), - .rf_rdata_b_ecc_i (rf_rdata_b_ecc_local), - - .ic_tag_req_i (ic_tag_req_local), - .ic_tag_write_i (ic_tag_write_local), - .ic_tag_addr_i (ic_tag_addr_local), - .ic_tag_wdata_i (ic_tag_wdata_local), - .ic_tag_rdata_i (ic_tag_rdata_local), - .ic_data_req_i (ic_data_req_local), - .ic_data_write_i (ic_data_write_local), - .ic_data_addr_i (ic_data_addr_local), - .ic_data_wdata_i (ic_data_wdata_local), - .ic_data_rdata_i (ic_data_rdata_local), - .ic_scr_key_valid_i (scramble_key_valid_local), - - .irq_software_i (irq_software_local), - .irq_timer_i (irq_timer_local), - .irq_external_i (irq_external_local), - .irq_fast_i (irq_fast_local), - .irq_nm_i (irq_nm_local), - .irq_pending_i (irq_pending_local), - - .debug_req_i (debug_req_local), - .crash_dump_i (crash_dump_local), - .double_fault_seen_i (double_fault_seen_local), - - .fetch_enable_i (fetch_enable_local), - .alert_minor_o (lockstep_alert_minor_local), - .alert_major_internal_o (lockstep_alert_major_internal_local), - .alert_major_bus_o (lockstep_alert_major_bus_local), - .icache_inval_i (icache_inval_local), - .core_busy_i (core_busy_local), - .test_en_i (test_en_i), - .scan_rst_ni (scan_rst_ni) - ); - - // Manually buffer the output signals. - prim_buf #(.Width (7)) u_prim_buf_wdata_intg ( - .in_i(data_wdata_intg_local), - .out_o(data_wdata_intg_o) - ); - - prim_buf u_prim_buf_alert_minor ( - .in_i (lockstep_alert_minor_local), - .out_o(lockstep_alert_minor) - ); - - prim_buf u_prim_buf_alert_major_internal ( - .in_i (lockstep_alert_major_internal_local), - .out_o(lockstep_alert_major_internal) - ); - - prim_buf u_prim_buf_alert_major_bus ( - .in_i (lockstep_alert_major_bus_local), - .out_o(lockstep_alert_major_bus) - ); - - end else begin : gen_no_lockstep - assign lockstep_alert_major_internal = 1'b0; - assign lockstep_alert_major_bus = 1'b0; - assign lockstep_alert_minor = 1'b0; - assign data_wdata_intg_o = 'b0; - logic unused_scan, unused_intg; - assign unused_scan = scan_rst_ni; - assign unused_intg = |{instr_rdata_intg_i, data_rdata_intg_i}; - end - - assign alert_major_internal_o = core_alert_major | lockstep_alert_major_internal; - assign alert_major_bus_o = lockstep_alert_major_bus; - assign alert_minor_o = core_alert_minor | lockstep_alert_minor; - - // X checks for top-level outputs - `ASSERT_KNOWN(IbexInstrReqX, instr_req_o) - `ASSERT_KNOWN_IF(IbexInstrReqPayloadX, instr_addr_o, instr_req_o) - - `ASSERT_KNOWN(IbexDataReqX, data_req_o) - `ASSERT_KNOWN_IF(IbexDataReqPayloadX, - {data_we_o, data_be_o, data_addr_o, data_wdata_o, data_wdata_intg_o}, data_req_o) - - `ASSERT_KNOWN(IbexScrambleReqX, scramble_req_o) - `ASSERT_KNOWN(IbexDoubleFaultSeenX, double_fault_seen_o) - `ASSERT_KNOWN(IbexAlertMinorX, alert_minor_o) - `ASSERT_KNOWN(IbexAlertMajorInternalX, alert_major_internal_o) - `ASSERT_KNOWN(IbexAlertMajorBusX, alert_major_bus_o) - `ASSERT_KNOWN(IbexCoreSleepX, core_sleep_o) - - // X check for top-level inputs - `ASSERT_KNOWN(IbexTestEnX, test_en_i) - `ASSERT_KNOWN(IbexRamCfgX, ram_cfg_i) - `ASSERT_KNOWN(IbexHartIdX, hart_id_i) - `ASSERT_KNOWN(IbexBootAddrX, boot_addr_i) - - `ASSERT_KNOWN(IbexInstrGntX, instr_gnt_i) - `ASSERT_KNOWN(IbexInstrRValidX, instr_rvalid_i) - `ASSERT_KNOWN_IF(IbexInstrRPayloadX, - {instr_rdata_i, instr_rdata_intg_i, instr_err_i}, instr_rvalid_i) - - `ASSERT_KNOWN(IbexDataGntX, data_gnt_i) - `ASSERT_KNOWN(IbexDataRValidX, data_rvalid_i) - `ASSERT_KNOWN_IF(IbexDataRPayloadX, {data_rdata_i, data_rdata_intg_i, data_err_i}, data_rvalid_i) - - `ASSERT_KNOWN(IbexIrqX, {irq_software_i, irq_timer_i, irq_external_i, irq_fast_i, irq_nm_i}) - - `ASSERT_KNOWN(IbexScrambleKeyValidX, scramble_key_valid_i) - `ASSERT_KNOWN_IF(IbexScramblePayloadX, {scramble_key_i, scramble_nonce_i}, scramble_key_valid_i) - - `ASSERT_KNOWN(IbexDebugReqX, debug_req_i) - `ASSERT_KNOWN(IbexFetchEnableX, fetch_enable_i) -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_wb_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_wb_stage.sv deleted file mode 100644 index 14364c57..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/rtl/ibex_wb_stage.sv +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -/** - * Writeback Stage - * - * Writeback is an optional third pipeline stage. It writes data back to the register file that was - * produced in the ID/EX stage or awaits a response to a load/store (LSU writes direct to register - * file for load data). If the writeback stage is not present (WritebackStage == 0) this acts as - * a simple passthrough to write data direct to the register file. - */ - -`include "prim_assert.sv" -//`include "dv_fcov_macros.svh" - -module ibex_wb_stage #( - parameter bit ResetAll = 1'b0, - parameter bit WritebackStage = 1'b0 -) ( - input logic clk_i, - input logic rst_ni, - - input logic en_wb_i, - input ibex_pkg::wb_instr_type_e instr_type_wb_i, - input logic [31:0] pc_id_i, - input logic instr_is_compressed_id_i, - input logic instr_perf_count_id_i, - - output logic ready_wb_o, - output logic rf_write_wb_o, - output logic outstanding_load_wb_o, - output logic outstanding_store_wb_o, - output logic [31:0] pc_wb_o, - output logic perf_instr_ret_wb_o, - output logic perf_instr_ret_compressed_wb_o, - output logic perf_instr_ret_wb_spec_o, - output logic perf_instr_ret_compressed_wb_spec_o, - - input logic [4:0] rf_waddr_id_i, - input logic [31:0] rf_wdata_id_i, - input logic rf_we_id_i, - - input logic [31:0] rf_wdata_lsu_i, - input logic rf_we_lsu_i, - - output logic [31:0] rf_wdata_fwd_wb_o, - - output logic [4:0] rf_waddr_wb_o, - output logic [31:0] rf_wdata_wb_o, - output logic rf_we_wb_o, - - input logic lsu_resp_valid_i, - input logic lsu_resp_err_i, - - output logic instr_done_wb_o -); - - import ibex_pkg::*; - - // 0 == RF write from ID - // 1 == RF write from LSU - logic [31:0] rf_wdata_wb_mux [2]; - logic [1:0] rf_wdata_wb_mux_we; - - if (WritebackStage) begin : g_writeback_stage - logic [31:0] rf_wdata_wb_q; - logic rf_we_wb_q; - logic [4:0] rf_waddr_wb_q; - - logic wb_done; - - logic wb_valid_q; - logic [31:0] wb_pc_q; - logic wb_compressed_q; - logic wb_count_q; - wb_instr_type_e wb_instr_type_q; - - logic wb_valid_d; - - // Stage becomes valid if an instruction enters for ID/EX and valid is cleared when instruction - // is done - assign wb_valid_d = (en_wb_i & ready_wb_o) | (wb_valid_q & ~wb_done); - - // Writeback for non load/store instructions always completes in a cycle (so instantly done) - // Writeback for load/store must wait for response to be received by the LSU - // Signal only relevant if wb_valid_q set - assign wb_done = (wb_instr_type_q == WB_INSTR_OTHER) | lsu_resp_valid_i; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - wb_valid_q <= 1'b0; - end else begin - wb_valid_q <= wb_valid_d; - end - end - - if (ResetAll) begin : g_wb_regs_ra - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - rf_we_wb_q <= '0; - rf_waddr_wb_q <= '0; - rf_wdata_wb_q <= '0; - wb_instr_type_q <= wb_instr_type_e'(0); - wb_pc_q <= '0; - wb_compressed_q <= '0; - wb_count_q <= '0; - end else if (en_wb_i) begin - rf_we_wb_q <= rf_we_id_i; - rf_waddr_wb_q <= rf_waddr_id_i; - rf_wdata_wb_q <= rf_wdata_id_i; - wb_instr_type_q <= instr_type_wb_i; - wb_pc_q <= pc_id_i; - wb_compressed_q <= instr_is_compressed_id_i; - wb_count_q <= instr_perf_count_id_i; - end - end - end else begin : g_wb_regs_nr - always_ff @(posedge clk_i) begin - if (en_wb_i) begin - rf_we_wb_q <= rf_we_id_i; - rf_waddr_wb_q <= rf_waddr_id_i; - rf_wdata_wb_q <= rf_wdata_id_i; - wb_instr_type_q <= instr_type_wb_i; - wb_pc_q <= pc_id_i; - wb_compressed_q <= instr_is_compressed_id_i; - wb_count_q <= instr_perf_count_id_i; - end - end - end - - assign rf_waddr_wb_o = rf_waddr_wb_q; - assign rf_wdata_wb_mux[0] = rf_wdata_wb_q; - assign rf_wdata_wb_mux_we[0] = rf_we_wb_q & wb_valid_q; - - assign ready_wb_o = ~wb_valid_q | wb_done; - - // Instruction in writeback will be writing to register file if either rf_we is set or writeback - // is awaiting load data. This is used for determining RF read hazards in ID/EX - assign rf_write_wb_o = wb_valid_q & (rf_we_wb_q | (wb_instr_type_q == WB_INSTR_LOAD)); - - assign outstanding_load_wb_o = wb_valid_q & (wb_instr_type_q == WB_INSTR_LOAD); - assign outstanding_store_wb_o = wb_valid_q & (wb_instr_type_q == WB_INSTR_STORE); - - assign pc_wb_o = wb_pc_q; - - assign instr_done_wb_o = wb_valid_q & wb_done; - - // Increment instruction retire counters for valid instructions which are not lsu errors. - // Speculative versions of the signals do not factor in exceptions and whether the instruction - // is done yet. These are used to get correct values for instructions reading the relevant - // performance counters in the ID stage. - assign perf_instr_ret_wb_spec_o = wb_count_q; - assign perf_instr_ret_compressed_wb_spec_o = perf_instr_ret_wb_spec_o & wb_compressed_q; - assign perf_instr_ret_wb_o = instr_done_wb_o & wb_count_q & - ~(lsu_resp_valid_i & lsu_resp_err_i); - assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & wb_compressed_q; - - // Forward data that will be written to the RF back to ID to resolve data hazards. The flopped - // rf_wdata_wb_q is used rather than rf_wdata_wb_o as the latter includes read data from memory - // that returns too late to be used on the forwarding path. - assign rf_wdata_fwd_wb_o = rf_wdata_wb_q; - end else begin : g_bypass_wb - // without writeback stage just pass through register write signals - assign rf_waddr_wb_o = rf_waddr_id_i; - assign rf_wdata_wb_mux[0] = rf_wdata_id_i; - assign rf_wdata_wb_mux_we[0] = rf_we_id_i; - - // Increment instruction retire counters for valid instructions which are not lsu errors. - // The speculative signals are always 0 when no writeback stage is present as the raw counter - // values will be correct. - assign perf_instr_ret_wb_spec_o = 1'b0; - assign perf_instr_ret_compressed_wb_spec_o = 1'b0; - assign perf_instr_ret_wb_o = instr_perf_count_id_i & en_wb_i & - ~(lsu_resp_valid_i & lsu_resp_err_i); - assign perf_instr_ret_compressed_wb_o = perf_instr_ret_wb_o & instr_is_compressed_id_i; - - // ready needs to be constant 1 without writeback stage (otherwise ID/EX stage will stall) - assign ready_wb_o = 1'b1; - - // Unused Writeback stage only IO & wiring - // Assign inputs and internal wiring to unused signals to satisfy lint checks - // Tie-off outputs to constant values - logic unused_clk; - logic unused_rst; - wb_instr_type_e unused_instr_type_wb; - logic [31:0] unused_pc_id; - - assign unused_clk = clk_i; - assign unused_rst = rst_ni; - assign unused_instr_type_wb = instr_type_wb_i; - assign unused_pc_id = pc_id_i; - - assign outstanding_load_wb_o = 1'b0; - assign outstanding_store_wb_o = 1'b0; - assign pc_wb_o = '0; - assign rf_write_wb_o = 1'b0; - assign rf_wdata_fwd_wb_o = 32'b0; - assign instr_done_wb_o = 1'b0; - end - - assign rf_wdata_wb_mux[1] = rf_wdata_lsu_i; - assign rf_wdata_wb_mux_we[1] = rf_we_lsu_i; - - // RF write data can come from ID results (all RF writes that aren't because of loads will come - // from here) or the LSU (RF writes for load data) - assign rf_wdata_wb_o = ({32{rf_wdata_wb_mux_we[0]}} & rf_wdata_wb_mux[0]) | - ({32{rf_wdata_wb_mux_we[1]}} & rf_wdata_wb_mux[1]); - assign rf_we_wb_o = |rf_wdata_wb_mux_we; - - //`DV_FCOV_SIGNAL_GEN_IF(logic, wb_valid, g_writeback_stage.wb_valid_q, WritebackStage) - - `ASSERT(RFWriteFromOneSourceOnly, $onehot0(rf_wdata_wb_mux_we)) -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/README.md b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/README.md new file mode 100644 index 00000000..e69de29b diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.core new file mode 100644 index 00000000..02c03356 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.core @@ -0,0 +1,17 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:dv_fcov_macros" +description: "DV FCOV macros" + +filesets: + files_fcov: + files: + - dv_fcov_macros.svh: {is_include_file: true} + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_fcov diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.svh b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.svh new file mode 100644 index 00000000..8ca12cdc --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_fcov_macros.svh @@ -0,0 +1,112 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Include FCOV RTL by default. Disable it for synthesis and where explicitly requested (by defining +// DV_FCOV_DISABLE). +`ifdef SYNTHESIS + `define DV_FCOV_DISABLE +`elsif YOSYS + `define DV_FCOV_DISABLE +`endif + +// Disable instantiations of FCOV coverpoints or covergroups. +`ifdef VERILATOR + `define DV_FCOV_DISABLE_CP +`elsif DV_FCOV_DISABLE + `define DV_FCOV_DISABLE_CP +`endif + +// Instantiates a covergroup in an interface or module. +// +// This macro assumes that a covergroup of the same name as the NAME_ arg is defined in the +// interface or module. It just adds some extra signals and logic to control the creation of the +// covergroup instance with ~bit en_~. This defaults to 0. It is ORed with the external +// COND_ signal. The testbench can modify it at t = 0 based on the test being run. +// NOTE: This is not meant to be invoked inside a class. +// +// NAME_ : Name of the covergroup. +// COND_ : External condition / expr that controls the creation of the covergroup. +// ARGS_ : Arguments to covergroup instance, if any. Args MUST BE wrapped in (..). +`ifndef DV_FCOV_INSTANTIATE_CG +`ifdef DV_FCOV_DISABLE_CP + `define DV_FCOV_INSTANTIATE_CG(NAME_, COND_ = 1'b1, ARGS_ = ()) +`else + `define DV_FCOV_INSTANTIATE_CG(NAME_, COND_ = 1'b1, ARGS_ = ()) \ + bit en_``NAME_ = 1'b0; \ + NAME_ NAME_``_inst; \ + initial begin \ + /* The #1 delay below allows any part of the tb to control the conditions first at t = 0. */ \ + #1; \ + if ((en_``NAME_) || (COND_)) begin \ + $display("%0t: (%0s:%0d) [%m] %0s", $time, `__FILE__, `__LINE__, \ + {"Creating covergroup ", `"NAME_`"}); \ + NAME_``_inst = new``ARGS_; \ + end \ + end +`endif +`endif + +// Creates a coverpoint for an expression where only the expression true case is of interest for +// coverage (e.g. where the expression indicates an event has occured). +`ifndef DV_FCOV_EXPR_SEEN +`ifdef DV_FCOV_DISABLE_CP + `define DV_FCOV_EXPR_SEEN(NAME_, EXPR_) +`else + `define DV_FCOV_EXPR_SEEN(NAME_, EXPR_) cp_``NAME_: coverpoint EXPR_ { bins seen = {1}; } +`endif +`endif + +// Creates a SVA cover that can be used in a covergroup. +// +// This macro creates an unnamed SVA cover from the property (or an expression) `PROP_` and an event +// with the name `EV_NAME_`. When the SVA cover is hit, the event is triggered. A coverpoint can +// cover the `triggered` property of the event. +`ifndef DV_FCOV_SVA +`ifdef DV_FCOV_DISABLE + `define DV_FCOV_SVA(EV_NAME_, PROP_, CLK_ = clk_i, RST_ = rst_ni) +`else + `define DV_FCOV_SVA(EV_NAME_, PROP_, CLK_ = clk_i, RST_ = rst_ni) \ + event EV_NAME_; \ + cover property (@(posedge CLK_) disable iff (RST_ == 0) (PROP_)) begin \ + -> EV_NAME_; \ + end +`endif +`endif + +// Coverage support is not always available but it's useful to include extra fcov signals for +// linting purposes. They need to be marked as unused to avoid warnings. +`ifndef DV_FCOV_MARK_UNUSED + `define DV_FCOV_MARK_UNUSED(TYPE_, NAME_) \ + TYPE_ unused_fcov_``NAME_; \ + assign unused_fcov_``NAME_ = fcov_``NAME_; +`endif + +// Define a signal and expression in the design for capture in functional coverage +`ifndef DV_FCOV_SIGNAL +`ifdef DV_FCOV_DISABLE + `define DV_FCOV_SIGNAL(TYPE_, NAME_, EXPR_) +`else + `define DV_FCOV_SIGNAL(TYPE_, NAME_, EXPR_) \ + TYPE_ fcov_``NAME_; \ + assign fcov_``NAME_ = EXPR_; \ + `DV_FCOV_MARK_UNUSED(TYPE_, NAME_) +`endif +`endif + +// Define a signal and expression in the design for capture in functional coverage depending on +// design configuration. The input GEN_COND_ must be a constant or parameter. +`ifndef DV_FCOV_SIGNAL_GEN_IF +`ifdef DV_FCOV_DISABLE + `define DV_FCOV_SIGNAL_GEN_IF(TYPE_, NAME_, EXPR_, GEN_COND_, DEFAULT_ = '0) +`else + `define DV_FCOV_SIGNAL_GEN_IF(TYPE_, NAME_, EXPR_, GEN_COND_, DEFAULT_ = '0) \ + TYPE_ fcov_``NAME_; \ + if (GEN_COND_) begin : g_fcov_``NAME_ \ + assign fcov_``NAME_ = EXPR_; \ + end else begin : g_no_fcov_``NAME_ \ + assign fcov_``NAME_ = DEFAULT_; \ + end \ + `DV_FCOV_MARK_UNUSED(TYPE_, NAME_) +`endif +`endif diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.core new file mode 100644 index 00000000..5f2fb800 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.core @@ -0,0 +1,17 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:dv_macros" +description: "A collection of macros used in DV." + +filesets: + files_dv: + files: + - dv_macros.svh: {is_include_file: true} + file_type: systemVerilogSource + +targets: + default: &default_target + filesets: + - files_dv diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh new file mode 100644 index 00000000..2e5e1375 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_macros.svh @@ -0,0 +1,536 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`ifdef UVM + `include "uvm_macros.svh" +`endif + +// UVM speficic macros +`ifndef gfn +`ifdef UVM + // verilog_lint: waive macro-name-style + `define gfn get_full_name() +`else + // verilog_lint: waive macro-name-style + `define gfn $sformatf("%m") +`endif +`endif + +`ifndef gtn + // verilog_lint: waive macro-name-style + `define gtn get_type_name() +`endif + +`ifndef gn + // verilog_lint: waive macro-name-style + `define gn get_name() +`endif + +`ifndef gmv + // verilog_lint: waive macro-name-style + `define gmv(csr) csr.get_mirrored_value() +`endif + +// cast base class obj holding extended class handle to extended class handle; +// throw error if cast fails +`ifndef downcast + // verilog_lint: waive macro-name-style + `define downcast(EXT_, BASE_, MSG_="", SEV_=fatal, ID_=`gfn) \ + begin \ + if (!$cast(EXT_, BASE_)) begin \ + `dv_``SEV_($sformatf({"Cast failed: base class variable %0s ", \ + "does not hold extended class %0s handle %s"}, \ + `"BASE_`", `"EXT_`", MSG_), ID_) \ + end \ + end +`endif + +// Note, UVM provides a macro `uvm_new_func -- which only applies to uvm_components +`ifndef uvm_object_new + `define uvm_object_new \ + function new (string name=""); \ + super.new(name); \ + endfunction : new +`endif + +`ifndef uvm_create_obj + `define uvm_create_obj(_type_name_, _inst_name_) \ + _inst_name_ = _type_name_::type_id::create(`"_inst_name_`"); +`endif + +`ifndef uvm_component_new + `define uvm_component_new \ + function new (string name="", uvm_component parent=null); \ + super.new(name, parent); \ + endfunction : new +`endif + +`ifndef uvm_create_comp + `define uvm_create_comp(_type_name_, _inst_name_) \ + _inst_name_ = _type_name_::type_id::create(`"_inst_name_`", this); +`endif + +// Convert arbitrary text / expression to string. +`ifndef DV_STRINGIFY + `define DV_STRINGIFY(I_) `"I_`" +`endif + +`ifndef DUT_HIER_STR + `define DUT_HIER_STR `DV_STRINGIFY(`DUT_HIER) +`endif + +// Common check macros used by DV_CHECK error and fatal macros. +// Note: Should not be called by user code +`ifndef DV_CHECK + `define DV_CHECK(T_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!(T_)) begin \ + `dv_``SEV_($sformatf("Check failed (%s) %s ", `"T_`", MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_EQ + `define DV_CHECK_EQ(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) == (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s == %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_NE + `define DV_CHECK_NE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) != (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s != %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_CASE_EQ + `define DV_CHECK_CASE_EQ(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) === (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s === %s (0x%0h [%0b] vs 0x%0h [%0b]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_CASE_NE + `define DV_CHECK_CASE_NE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) !== (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s !== %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_LT + `define DV_CHECK_LT(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) < (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s < %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_GT + `define DV_CHECK_GT(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) > (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s > %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_LE + `define DV_CHECK_LE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) <= (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s <= %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_GE + `define DV_CHECK_GE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + begin \ + if (!((ACT_) >= (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed %s >= %s (%0d [0x%0h] vs %0d [0x%0h]) %s", \ + `"ACT_`", `"EXP_`", ACT_, ACT_, EXP_, EXP_, MSG_), ID_) \ + end \ + end +`endif + +`ifndef DV_CHECK_STREQ + `define DV_CHECK_STREQ(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + if (!((ACT_) == (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed \"%s\" == \"%s\" %s", ACT_, EXP_, MSG_), ID_) \ + end +`endif + +`ifndef DV_CHECK_STRNE + `define DV_CHECK_STRNE(ACT_, EXP_, MSG_="", SEV_=error, ID_=`gfn) \ + if (!((ACT_) != (EXP_))) begin \ + `dv_``SEV_($sformatf("Check failed \"%s\" != \"%s\" %s", ACT_, EXP_, MSG_), ID_) \ + end +`endif + +// Fatal version of the checks +`ifndef DV_CHECK_FATAL + `define DV_CHECK_FATAL(T_, MSG_="", ID_=`gfn) \ + `DV_CHECK(T_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_EQ_FATAL + `define DV_CHECK_EQ_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_EQ(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_NE_FATAL + `define DV_CHECK_NE_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_NE(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_LT_FATAL + `define DV_CHECK_LT_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_LT(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_GT_FATAL + `define DV_CHECK_GT_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_GT(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_LE_FATAL + `define DV_CHECK_LE_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_LE(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_GE_FATAL + `define DV_CHECK_GE_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_GE(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_STREQ_FATAL + `define DV_CHECK_STREQ_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_STREQ(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +`ifndef DV_CHECK_STRNE_FATAL + `define DV_CHECK_STRNE_FATAL(ACT_, EXP_, MSG_="", ID_=`gfn) \ + `DV_CHECK_STRNE(ACT_, EXP_, MSG_, fatal, ID_) +`endif + +// Shorthand for common foo.randomize() + fatal check +`ifndef DV_CHECK_RANDOMIZE_FATAL + `define DV_CHECK_RANDOMIZE_FATAL(VAR_, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(VAR_.randomize(), MSG_, ID_) +`endif + +// Shorthand for common foo.randomize() with { } + fatal check +`ifndef DV_CHECK_RANDOMIZE_WITH_FATAL + `define DV_CHECK_RANDOMIZE_WITH_FATAL(VAR_, WITH_C_, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(VAR_.randomize() with {WITH_C_}, MSG_, ID_) +`endif + +// Shorthand for common std::randomize(foo) + fatal check +`ifndef DV_CHECK_STD_RANDOMIZE_FATAL + `define DV_CHECK_STD_RANDOMIZE_FATAL(VAR_, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(std::randomize(VAR_), MSG_, ID_) +`endif + +// Shorthand for common std::randomize(foo) with { } + fatal check +`ifndef DV_CHECK_STD_RANDOMIZE_WITH_FATAL + `define DV_CHECK_STD_RANDOMIZE_WITH_FATAL(VAR_, WITH_C_, MSG_="Randomization failed!",ID_=`gfn) \ + `DV_CHECK_FATAL(std::randomize(VAR_) with {WITH_C_}, MSG_, ID_) +`endif + +// Shorthand for common cls_inst.randomize(member) + fatal check +// Randomizes a specific member of a class instance. +`ifndef DV_CHECK_MEMBER_RANDOMIZE_FATAL + `define DV_CHECK_MEMBER_RANDOMIZE_FATAL(VAR_, CLS_INST_=this, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(CLS_INST_.randomize(VAR_), MSG_, ID_) +`endif + +// Shorthand for common cls_inst.randomize(member) with { } + fatal check +// Randomizes a specific member of a class instance with inline constraints. +`ifndef DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL + `define DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(VAR_, C_, CLS_INST_=this, MSG_="Randomization failed!", ID_=`gfn) \ + `DV_CHECK_FATAL(CLS_INST_.randomize(VAR_) with {C_}, MSG_, ID_) +`endif + +// print static/dynamic 1d array or queue +`ifndef DV_PRINT_ARR_CONTENTS +`define DV_PRINT_ARR_CONTENTS(ARR_, V_=uvm_pkg::UVM_MEDIUM, ID_=`gfn) \ + begin \ + foreach (ARR_[i]) begin \ + `dv_info($sformatf("%s[%0d] = %0d (0x%0h)", `"ARR_`", i, ARR_[i], ARR_[i]), V_, ID_) \ + end \ + end +`endif + +// print non-empty tlm fifos that were uncompared at end of test +`ifndef DV_EOT_PRINT_TLM_FIFO_CONTENTS +`define DV_EOT_PRINT_TLM_FIFO_CONTENTS(TYP_, FIFO_, SEV_=error, ID_=`gfn) \ + begin \ + while (!FIFO_.is_empty()) begin \ + TYP_ item; \ + void'(FIFO_.try_get(item)); \ + `dv_``SEV_($sformatf("%s item uncompared:\n%s", `"FIFO_`", item.sprint()), ID_) \ + end \ + end +`endif + +// print non-empty tlm fifos that were uncompared at end of test +`ifndef DV_EOT_PRINT_TLM_FIFO_ARR_CONTENTS +`define DV_EOT_PRINT_TLM_FIFO_ARR_CONTENTS(TYP_, FIFO_, SEV_=error, ID_=`gfn) \ + begin \ + foreach (FIFO_[i]) begin \ + while (!FIFO_[i].is_empty()) begin \ + TYP_ item; \ + void'(FIFO_[i].try_get(item)); \ + `dv_``SEV_($sformatf("%s[%0d] item uncompared:\n%s", `"FIFO_`", i, item.sprint()), ID_) \ + end \ + end \ + end +`endif + +// print non-empty tlm fifos that were uncompared at end of test +`ifndef DV_EOT_PRINT_Q_CONTENTS +`define DV_EOT_PRINT_Q_CONTENTS(TYP_, Q_, SEV_=error, ID_=`gfn) \ + begin \ + while (Q_.size() != 0) begin \ + TYP_ item = Q_.pop_front(); \ + `dv_``SEV_($sformatf("%s item uncompared:\n%s", `"Q_`", item.sprint()), ID_) \ + end \ + end +`endif + +// print non-empty tlm fifos that were uncompared at end of test +`ifndef DV_EOT_PRINT_Q_ARR_CONTENTS +`define DV_EOT_PRINT_Q_ARR_CONTENTS(TYP_, Q_, SEV_=error, ID_=`gfn) \ + begin \ + foreach (Q_[i]) begin \ + while (Q_[i].size() != 0) begin \ + TYP_ item = Q_[i].pop_front(); \ + `dv_``SEV_($sformatf("%s[%0d] item uncompared:\n%s", `"Q_`", i, item.sprint()), ID_) \ + end \ + end \ + end +`endif + +// check for non-empty mailbox and print items that were uncompared at end of test +`ifndef DV_EOT_PRINT_MAILBOX_CONTENTS +`define DV_EOT_PRINT_MAILBOX_CONTENTS(TYP_, MAILBOX_, SEV_=error, ID_=`gfn) \ + begin \ + while (MAILBOX_.num() != 0) begin \ + TYP_ item; \ + void'(MAILBOX_.try_get(item)); \ + `dv_``SEV_($sformatf("%s item uncompared:\n%s", `"MAILBOX_`", item.sprint()), ID_) \ + end \ + end +`endif + +// get parity - implemented as a macro so that it can be invoked in constraints as well +`ifndef GET_PARITY + `define GET_PARITY(val, odd=0) (^val ^ odd) +`endif + +// Wait a task or statement with exit condition +// Kill the thread when either the wait statement is completed or exit condition occurs +// input WAIT_ need to be a statement. Here are some examples +// `DV_SPINWAIT(wait(...);, "Wait for ...") +// `DV_SPINWAIT( +// while (1) begin +// ... +// end) +`ifndef DV_SPINWAIT_EXIT +`define DV_SPINWAIT_EXIT(WAIT_, EXIT_, MSG_ = "exit condition occurred!", ID_ =`gfn) \ + begin \ + fork begin \ + fork \ + begin \ + WAIT_ \ + end \ + begin \ + EXIT_ \ + if (MSG_ != "") begin \ + `dv_info(MSG_, uvm_pkg::UVM_HIGH, ID_) \ + end \ + end \ + join_any \ + disable fork; \ + end join \ + end +`endif + +// wait a task or statement with timer watchdog +`ifndef DV_SPINWAIT +`define DV_SPINWAIT(WAIT_, MSG_ = "timeout occurred!", TIMEOUT_NS_ = default_spinwait_timeout_ns, ID_ =`gfn) \ + `DV_SPINWAIT_EXIT(WAIT_, wait_timeout(TIMEOUT_NS_, ID_, MSG_);, "", ID_) +`endif + +// Control assertions in the DUT. +// +// This macro is invoked in top level testbench that instantiates the DUT. It spawns off an initial +// block that forever waits for a resource of type bit named by the string arg ~LABEL_~ that +// can be set by any entity in the testbench. Based on the value set, it enables or disables the +// assertions at the hierarchy of the provided path. The entity setting the resource value invokes +// uvm_config_db#(bit)::set(...) and this macro calls the corresponding get. +// +// LABEL_ : Name of the assertion control resource bit (string). +// HIER_ : Path to the module within which the assertion is controlled. +// LEVELS_: Number of levels within the module to control the assertions. +// SCOPE_ : Hierarchical string path to the testbench where this macro is invoked, example: %m. +// ID_ : Identifier string used for UVM logs. +`ifndef DV_ASSERT_CTRL +`define DV_ASSERT_CTRL(LABEL_, HIER_, LEVELS_ = 0, SCOPE_ = "", ID_ = $sformatf("%m")) \ + initial begin \ + bit assert_en; \ + forever begin \ + uvm_config_db#(bit)::wait_modified(null, SCOPE_, LABEL_); \ + if (!uvm_config_db#(bit)::get(null, SCOPE_, LABEL_, assert_en)) begin \ + `uvm_fatal(ID_, $sformatf("Failed to get \"%0s\" from uvm_config_db", LABEL_)) \ + end \ + if (assert_en) begin \ + `uvm_info(ID_, $sformatf("Enabling assertions: %0s", `DV_STRINGIFY(HIER_)), UVM_LOW) \ + $asserton(LEVELS_, HIER_); \ + end else begin \ + `uvm_info(ID_, $sformatf("Disabling assertions: %0s", `DV_STRINGIFY(HIER_)), UVM_LOW) \ + $assertoff(LEVELS_, HIER_); \ + end \ + end \ + end +`endif + +// Retrieves a plusarg value representing an enum literal. +// +// The plusarg is parsed as a string, which needs to be converted into the enum literal whose name +// matches the string. This functionality is provided by the UVM helper function below. +// +// ENUM_: The enum type. +// VAR_: The enum variable to which the plusarg value will be set (must be declared already). +// PLUSARG_: the name of the plusarg (as raw text). This is typically the same as the enum variable. +// CHECK_EXISTS_: Throws a fatal error if the plusarg is not set. +`ifndef DV_GET_ENUM_PLUSARG +`define DV_GET_ENUM_PLUSARG(ENUM_, VAR_, PLUSARG_ = VAR_, CHECK_EXISTS_ = 0, ID_ = `gfn) \ + begin \ + string str; \ + if ($value$plusargs("``PLUSARG_``=%0s", str)) begin \ + if (!uvm_enum_wrapper#(ENUM_)::from_name(str, VAR_)) begin \ + `uvm_fatal(ID_, $sformatf("Cannot find %s from enum ``ENUM_``", VAR_.name())) \ + end \ + end else if (CHECK_EXISTS_) begin \ + `uvm_fatal(ID_, "Please pass the plusarg +``PLUSARG_``=<``ENUM_``-literal>") \ + end \ + end +`endif + +// Enable / disable assertions at a module hierarchy identified by LABEL_. +// +// This goes in conjunction with `DV_ASSERT_CTRL() macro above, but is invoked in the entity that is +// sending the req to turn on / off the assertions. Note that that piece of code invoking this macro +// does not have the information on the actual hierarchical path to the module or the levels - this +// is 'wrapped' into the LABEL_ instead. DV user needs to uniquify the label sufficienly enough to +// reflect it. +// +// LABEL_ : Name of the assertion control resource bit (string). +// VALUE_ : Value of the control bit - 1 - enable assertions, 0 - disable assertions. +// SCOPE_ : Hierarchical string path to the testbench where this macro is invoked, example: %m. +`ifndef DV_ASSERT_CTRL_REQ +`define DV_ASSERT_CTRL_REQ(LABEL_, VALUE_, SCOPE_="") \ + begin \ + uvm_config_db#(bit)::set(null, SCOPE_, LABEL_, VALUE_); \ + end +`endif + +// Macros for logging (info, warning, error and fatal severities). +// +// These are meant to be invoked in modules and interfaces that are shared between DV and Verilator +// testbenches. We waive the lint requirement for these to be in uppercase, since they are +// UVM-adjacent. +`ifdef UVM +`ifndef dv_info + // verilog_lint: waive macro-name-style + `define dv_info(MSG_, VERBOSITY_ = uvm_pkg::UVM_LOW, ID_ = $sformatf("%m")) \ + if (uvm_pkg::uvm_report_enabled(VERBOSITY_, uvm_pkg::UVM_INFO, ID_)) begin \ + uvm_pkg::uvm_report_info(ID_, MSG_, VERBOSITY_, `uvm_file, `uvm_line, "", 1); \ + end +`endif + +`ifndef dv_warning + // verilog_lint: waive macro-name-style + `define dv_warning(MSG_, ID_ = $sformatf("%m")) \ + if (uvm_pkg::uvm_report_enabled(uvm_pkg::UVM_NONE, uvm_pkg::UVM_WARNING, ID_)) begin \ + uvm_pkg::uvm_report_warning(ID_, MSG_, uvm_pkg::UVM_NONE, `uvm_file, `uvm_line, "", 1); \ + end +`endif + +`ifndef dv_error + // verilog_lint: waive macro-name-style + `define dv_error(MSG_, ID_ = $sformatf("%m")) \ + if (uvm_pkg::uvm_report_enabled(uvm_pkg::UVM_NONE, uvm_pkg::UVM_ERROR, ID_)) begin \ + uvm_pkg::uvm_report_error(ID_, MSG_, uvm_pkg::UVM_NONE, `uvm_file, `uvm_line, "", 1); \ + end +`endif + +`ifndef dv_fatal + // verilog_lint: waive macro-name-style + `define dv_fatal(MSG_, ID_ = $sformatf("%m")) \ + if (uvm_pkg::uvm_report_enabled(uvm_pkg::UVM_NONE, uvm_pkg::UVM_FATAL, ID_)) begin \ + uvm_pkg::uvm_report_fatal(ID_, MSG_, uvm_pkg::UVM_NONE, `uvm_file, `uvm_line, "", 1); \ + end +`endif + +`else // UVM + +`ifndef dv_info + // verilog_lint: waive macro-name-style + `define dv_info(MSG_, VERBOSITY = DUMMY_, ID_ = $sformatf("%m")) \ + $display("%0t: (%0s:%0d) [%0s] %0s", $time, `__FILE__, `__LINE__, ID_, MSG_); +`endif + +`ifndef dv_warning + // verilog_lint: waive macro-name-style + `define dv_warning(MSG_, ID_ = $sformatf("%m")) \ + $warning("%0t: (%0s:%0d) [%0s] %0s", $time, `__FILE__, `__LINE__, ID_, MSG_); +`endif + +`ifndef dv_error + // verilog_lint: waive macro-name-style + `define dv_error(MSG_, ID_ = $sformatf("%m")) \ + $error("%0t: (%0s:%0d) [%0s] %0s", $time, `__FILE__, `__LINE__, ID_, MSG_); +`endif + +`ifndef dv_fatal + // verilog_lint: waive macro-name-style + `define dv_fatal(MSG_, ID_ = $sformatf("%m")) \ + $fatal("%0t: (%0s:%0d) [%0s] %0s", $time, `__FILE__, `__LINE__, ID_, MSG_); +`endif + +`endif // UVM + +// Macros for constrain clk with common frequencies +// constrain clock to run at 24Mhz - 100Mhz and use higher weights on 24, 25, 48, 50, 100 +`ifndef DV_COMMON_CLK_CONSTRAINT +`define DV_COMMON_CLK_CONSTRAINT(FREQ_) \ + FREQ_ dist { \ + [24:25] :/ 2, \ + [26:47] :/ 1, \ + [48:50] :/ 2, \ + [51:95] :/ 1, \ + 96 :/ 1, \ + [97:99] :/ 1, \ + 100 :/ 1 \ + }; +`endif diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_catcher.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_catcher.sv new file mode 100644 index 00000000..91e3337e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_catcher.sv @@ -0,0 +1,46 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// Report catcher/demoter +class dv_report_catcher extends uvm_report_catcher; + + // Stores a new severity indexed by the ID and + // the regular expression to match the message + protected uvm_severity m_changed_sev[string][string]; + + `uvm_object_utils(dv_report_catcher) + `uvm_object_new + + // Called for all report messages - defined in uvm_report_catcher + virtual function action_e catch(); + string id = get_id(); + if (m_changed_sev.exists(id)) begin + string report_msg = get_message(); + foreach (m_changed_sev[id][msg]) begin + if (uvm_re_match(msg, report_msg)) begin + set_severity(m_changed_sev[id][msg]); + end + end + end + return THROW; + endfunction + + // Change severity of a message with ID == id and message text + // matching msg which is treated as a regular expression + virtual function void add_change_sev(string id, string msg, uvm_severity sev); + m_changed_sev[id][msg] = sev; + endfunction + + // Remove a change entry + // If msg == "" then remove all changes for a given id + virtual function void remove_change_sev(string id, string msg = ""); + if (m_changed_sev.exists(id)) + if (msg == "") begin + // Delete all with id if message is blank + m_changed_sev.delete(id); + end else if (m_changed_sev[id].exists(msg)) begin + m_changed_sev[id].delete(msg); + end + endfunction + +endclass diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_server.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_server.sv new file mode 100644 index 00000000..a5d7440e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_report_server.sv @@ -0,0 +1,65 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Standardize look & feel of report phase and uvm logging messages. +class dv_report_server extends uvm_default_report_server; + + bit show_file_line = 1'b1; + // if enabled, show the relative path of the file. By default only show file name + bit show_file_path = 1'b0; + bit use_default_uvm_report_message_format = 1'b0; + + function new (string name = ""); + super.new(name); + // provide ability to override these knobs over cli + void'($value$plusargs("show_file_line=%0b", show_file_line)); + void'($value$plusargs("show_file_path=%0b", show_file_path)); + void'($value$plusargs("use_default_uvm_report_message_format=%0b", + use_default_uvm_report_message_format)); + endfunction + + function void report_summarize(UVM_FILE file = 0); + int num_uvm_warning; + int num_uvm_error; + int num_uvm_fatal; + + num_uvm_warning = get_severity_count(UVM_WARNING); + num_uvm_error = get_severity_count(UVM_ERROR); + num_uvm_fatal = get_severity_count(UVM_FATAL); + + // Print default summary report + super.report_summarize(file); + + // Print final test pass-fail - external tool can use this signature for test status + // Treat UVM_WARNINGs as a sign of test failure since it could silently result in false pass + dv_test_status_pkg::dv_test_status((num_uvm_warning + num_uvm_error + num_uvm_fatal) == 0); + endfunction + + // Override default messaging format to standard "pretty" format for all testbenches + virtual function string compose_report_message(uvm_report_message report_message, + string report_object_name = ""); + + if (use_default_uvm_report_message_format) begin + return (super.compose_report_message(report_message, report_object_name)); + end else begin + uvm_severity severity = report_message.get_severity(); + string filename = report_message.get_filename(); + int line = report_message.get_line(); + string obj_name = report_message.get_report_object().get_full_name(); + string id = report_message.get_id(); + string message = report_message.get_message(); + string file_line; + + if (show_file_line && filename != "") begin + if (!show_file_path) filename = str_utils_pkg::str_path_basename(filename); + file_line = $sformatf("(%0s:%0d) ", filename, line); + end + obj_name = {obj_name, ((obj_name != "") ? " " : "")}; + compose_report_message = $sformatf({"%0s @ %t: ", file_line, obj_name, "[%0s] %0s"}, + severity.name(), $realtime, id, message); + return compose_report_message; + end + endfunction + +endclass diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status.core new file mode 100644 index 00000000..bbec1b05 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status.core @@ -0,0 +1,17 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:dv_test_status" +description: "DV test status reporting utilities" + +filesets: + files_dv: + files: + - dv_test_status_pkg.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status_pkg.sv new file mode 100644 index 00000000..3a81ddfc --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_test_status_pkg.sv @@ -0,0 +1,31 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package dv_test_status_pkg; + + // Prints the test status signature & banner. + // + // This function takes a boolean arg indicating whether the test passed or failed and prints the + // signature along with a banner. The signature can be used by external scripts to determine if + // the test passed or failed. + function automatic void dv_test_status(bit passed); + if (passed) begin + $display("\nTEST PASSED CHECKS"); + $display(" _____ _ _ _ "); + $display("|_ _|__ ___| |_ _ __ __ _ ___ ___ ___ __| | |"); + $display(" | |/ _ \\/ __| __| | '_ \\ / _` / __/ __|/ _ \\/ _` | |"); + $display(" | | __/\\__ \\ |_ | |_) | (_| \\__ \\__ \\ __/ (_| |_|"); + $display(" |_|\\___||___/\\__| | .__/ \\__,_|___/___/\\___|\\__,_(_)"); + $display(" |_| \n"); + end else begin + $display("\nTEST FAILED CHECKS"); + $display(" _____ _ __ _ _ _ _ "); + $display("|_ _|__ ___| |_ / _| __ _(_) | ___ __| | |"); + $display(" | |/ _ \\/ __| __| | |_ / _` | | |/ _ \\/ _` | |"); + $display(" | | __/\\__ \\ |_ | _| (_| | | | __/ (_| |_|"); + $display(" |_|\\___||___/\\__| |_| \\__,_|_|_|\\___|\\__,_(_)\n"); + end + endfunction + +endpackage diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils.core new file mode 100644 index 00000000..1e405236 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils.core @@ -0,0 +1,28 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:dv_utils" +description: "DV utilities" + +filesets: + files_dv: + depend: + - lowrisc:dv:dv_macros + - lowrisc:dv:dv_fcov_macros + - lowrisc:dv:common_ifs + - lowrisc:prim:assert:0.1 + - lowrisc:cve2:bus_params_pkg + - lowrisc:dv:str_utils + - lowrisc:dv:dv_test_status + files: + - dv_utils_pkg.sv + - dv_report_catcher.sv: {is_include_file: true} + - dv_report_server.sv: {is_include_file: true} + - dv_vif_wrap.sv: {is_include_file: true} + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv new file mode 100644 index 00000000..62f3b765 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_utils_pkg.sv @@ -0,0 +1,223 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package dv_utils_pkg; + // dep packages + import uvm_pkg::*; + import bus_params_pkg::*; + + // macro includes + `include "dv_macros.svh" +`ifdef UVM + `include "uvm_macros.svh" +`endif + + // common parameters used across all benches + parameter int NUM_MAX_INTERRUPTS = 32; + typedef logic [NUM_MAX_INTERRUPTS-1:0] interrupt_t; + + parameter int NUM_MAX_ALERTS = 32; + typedef logic [NUM_MAX_ALERTS-1:0] alert_t; + + // types & variables + typedef bit [31:0] uint; + typedef bit [7:0] uint8; + typedef bit [15:0] uint16; + typedef bit [31:0] uint32; + typedef bit [63:0] uint64; + + // TODO: The above typedefs violate the name rule, which is fixed below. Cleanup the codebase to + // use the typedefs below and remove the ones above. + typedef bit [7:0] uint8_t; + typedef bit [15:0] uint16_t; + typedef bit [31:0] uint32_t; + typedef bit [63:0] uint64_t; + + // typedef parameterized pins_if for ease of implementation for interrupts and alerts + typedef virtual pins_if #(NUM_MAX_INTERRUPTS) intr_vif; + typedef virtual pins_if #(1) devmode_vif; + + // interface direction / mode - Host or Device + typedef enum bit { + Host, + Device + } if_mode_e; + + // compare operator types + typedef enum { + CompareOpEq, + CompareOpCaseEq, + CompareOpNe, + CompareOpCaseNe, + CompareOpGt, + CompareOpGe, + CompareOpLt, + CompareOpLe + } compare_op_e; + + // mem address struct + typedef struct { + uvm_reg_addr_t start_addr; + uvm_reg_addr_t end_addr; + } addr_range_t; + + // Enum representing a bus operation type - read or write. + typedef enum bit { + BusOpWrite = 1'b0, + BusOpRead = 1'b1 + } bus_op_e; + + // Enum representing a type of host requests - read only, write only or random read & write + typedef enum int { + HostReqNone = 0, + HostReqReadOnly = 1, + HostReqWriteOnly = 2, + HostReqReadWrite = 3 + } host_req_type_e; + + // Enum representing clock frequency difference on 2 clocks + typedef enum bit [1:0] { + ClkFreqDiffNone, + ClkFreqDiffSmall, + ClkFreqDiffBig, + ClkFreqDiffAny + } clk_freq_diff_e; + + string msg_id = "dv_utils_pkg"; + + // return the smaller value of 2 inputs + function automatic int min2(int a, int b); + return (a < b) ? a : b; + endfunction + + // return the bigger value of 2 inputs + function automatic int max2(int a, int b); + return (a > b) ? a : b; + endfunction + + // return the biggest value within the given queue of integers. + function automatic int max(const ref int int_q[$]); + `DV_CHECK_GT_FATAL(int_q.size(), 0, "max function cannot accept an empty queue of integers!", + msg_id) + // Assign the first value from the queue in case of negative integers. + max = int_q[0]; + foreach (int_q[i]) max = max2(max, int_q[i]); + return max; + endfunction + + // get absolute value of the input. Usage: absolute(val) or absolute(a - b) + function automatic uint absolute(int val); + return val >= 0 ? val : -val; + endfunction + + // endian swaps a 32-bit data word + function automatic logic [31:0] endian_swap(logic [31:0] data); + return {<<8{data}}; + endfunction + + // endian swaps bytes at a word granularity, while preserving overall word ordering. + // + // e.g. if `arr[] = '{'h0, 'h1, 'h2, 'h3, 'h4, 'h5, 'h6, 'h7}`, this function will produce: + // `'{'h3, 'h2, 'h1, 'h0, 'h7, 'h6, 'h5, 'h4}` + function automatic void endian_swap_byte_arr(ref bit [7:0] arr[]); + arr = {<< byte {arr}}; + arr = {<< 32 {arr}}; + endfunction + +`ifdef UVM + // Simple function to set max errors before quitting sim + function automatic void set_max_quit_count(int n); + uvm_report_server report_server = uvm_report_server::get_server(); + report_server.set_max_quit_count(n); + endfunction + + // return if uvm_fatal occurred + function automatic bit has_uvm_fatal_occurred(); + uvm_report_server report_server = uvm_report_server::get_server(); + return report_server.get_severity_count(UVM_FATAL) > 0; + endfunction + + // task that waits for the specfied timeout + task automatic wait_timeout(input uint timeout_ns, + input string error_msg_id = msg_id, + input string error_msg = "timeout occurred!", + input bit report_fatal = 1); + #(timeout_ns * 1ns); + if (report_fatal) `uvm_fatal(error_msg_id, error_msg) + else `uvm_error(error_msg_id, error_msg) + endtask : wait_timeout + + // get masked data based on provided byte mask; if csr reg handle is provided (optional) then + // masked bytes from csr's mirrored value are returned, else masked bytes are 0's + function automatic bit [bus_params_pkg::BUS_DW-1:0] + get_masked_data(bit [bus_params_pkg::BUS_DW-1:0] data, + bit [bus_params_pkg::BUS_DBW-1:0] mask, + uvm_reg csr = null); + bit [bus_params_pkg::BUS_DW-1:0] csr_data; + csr_data = (csr != null) ? csr.get_mirrored_value() : '0; + get_masked_data = data; + foreach (mask[i]) begin + if (~mask[i]) get_masked_data[i * 8 +: 8] = csr_data[i * 8 +: 8]; + end + endfunction + + // create a sequence by name and return the handle of uvm_sequence + function automatic uvm_sequence create_seq_by_name(string seq_name); + uvm_object obj; + uvm_factory factory; + uvm_sequence seq; + + factory = uvm_factory::get(); + obj = factory.create_object_by_name(seq_name, "", seq_name); + if (obj == null) begin + // print factory overrides to help debug + factory.print(1); + `uvm_fatal(msg_id, $sformatf("could not create %0s seq", seq_name)) + end + if (!$cast(seq, obj)) begin + `uvm_fatal(msg_id, $sformatf("cast failed - %0s is not a uvm_sequence", seq_name)) + end + return seq; + endfunction +`endif + + // Returns the hierarchical path to the interface / module N levels up. + // + // Meant to be invoked inside a module or interface. + // hier: String input of the interface / module, typically $sformatf("%m"). + // n_levels_up: Integer number of levels up the hierarchy to omit. + // Example: if (hier = tb.dut.foo.bar, n_levels_up = 2), then return tb.dut + function automatic string get_parent_hier(string hier, int n_levels_up = 1); + int idx; + int level; + if (n_levels_up <= 0) return hier; + for (idx = hier.len() - 1; idx >= 0; idx--) begin + if (hier[idx] == ".") level++; + if (level == n_levels_up) break; + end + return (hier.substr(0, idx - 1)); + endfunction + + // Periodically check for the existence of a magic file (dv.stop). Exit if it exists. This + // provides a mechanism to gracefully kill a simulation without direct access to the process. + task automatic poll_for_stop(uint interval_ns = 10_000, string filename = "dv.stop"); + fork + while (1) begin + #(interval_ns * 1ns); + if (!$system($sformatf("test -f %0s", filename))) begin + $system($sformatf("rm %0s", filename)); + `dv_fatal($sformatf("Found %0s file. Exiting!", filename), "poll_for_stop") + end + end + join_none + endtask : poll_for_stop + + // sources +`ifdef UVM + `include "dv_report_catcher.sv" + `include "dv_report_server.sv" + `include "dv_vif_wrap.sv" +`endif + +endpackage diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_vif_wrap.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_vif_wrap.sv new file mode 100644 index 00000000..61d99479 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e20/vendor/lowrisc_ip/dv/sv/dv_utils/dv_vif_wrap.sv @@ -0,0 +1,96 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Abstract class meant to hold arbitrary virtual interface handles. +// +// Written primarily for an interface which implements functional coverage, this could be used +// for other purposes as well. This abstract class provides utilities & macros to retrieve +// virtual interface handles that are bound to a DUT's sub-modules. These sub-module interfaces must +// self-register using the `DV_VIF_WRAP_SET_VIF()` macro (see details below). The extended class +// then implements the `get_vifs()` method using the `DV_VIF_WRAP_GET_VIF*` macros below to retrieve +// the sub-module interface handles it maintains. +virtual class dv_vif_wrap; + string hier; // Represents the hierarchy of the parent module or interface. + string name; // Name of the class instance. + + function new(string hier, string name = ""); + this.hier = hier; + this.name = name; + endfunction + + // Abstract method implemented by the extended class. It is recommended to invoke the helper + // macros below rather than manually define it. + pure virtual task get_vifs(); + +endclass + +// Helper macros. +// +// These are defined in the file itself since they are tightly coupled to the class definition +// above. These are scoped globally so that extended classes can invoke them. + +// Enable an interface to register itself (set its handle into the config db). +// +// Meant to be invoked from an interface. The macros invocation causes the interface to register +// itself into the uvm_resource_db pool. The derived class of dv_vif_wrap retrieves the handle to +// that interface handle from the uvm_resource db pool. +// +// SV LRM does not yet allow referencing the instance of an interface within itself as one +// would in case of a class using the ~this~ keyword. However, most major simulators actually +// support this in their own custom way. On VCS, a reference to self within the interface can be set +// using `interface::self()` construct. On Xcelium, this is achieved by simply referencing the +// interface name. +// +// _IF: The SV interface +// _VIF: The corresponding virtual interface handle name +// _LEVEL: # of hierarchical levels the module to which the SV interface is bound, starting at the +// top level DUT instance. +`define DV_VIF_WRAP_SET_VIF(_IF, _VIF, _LEVEL = 0) \ + import uvm_pkg::*; \ + function automatic void self_register(); \ + string path; \ + virtual _IF vif; \ + /* Initial block adds another level in the path hierarchy which needs to be split out. */ \ + /* Add one more to go one level up the interface instance. */ \ + /* Example: tb.dut.core.u_foo_if.self_register -> tb.dut.core. */ \ + path = dv_utils_pkg::get_parent_hier(.hier($sformatf("%m")), .n_levels_up(2 + _LEVEL)); \ +`ifdef VCS \ + vif = interface::self(); \ +`elsif XCELIUM \ + vif = _IF; \ +`else \ + vif = _IF; \ +`endif \ + uvm_pkg::uvm_resource_db#(virtual _IF)::set(path, `"_VIF`", vif); \ + endfunction \ + initial self_register(); + +// Enables the retrieval of individual vifs. +// +// The three macros below go together to define the _get_vifs() task in the extended class. +`define DV_VIF_WRAP_GET_VIFS_BEGIN \ + task get_vifs(); \ + fork \ + +// To avoid race condition between the instant when an interface handle is set into the config db +// and the instant when it is retrieved (in the same time step, at t = 0), the macro below invokes +// uvm_config_db#(..)::wait_modified() to ensure that the retrieval is done only after the set. +`define DV_VIF_WRAP_GET_VIF(_IF, _VIF) \ + begin \ + bit vif_found; \ + /* At most 2 retries. */ \ + repeat (2) begin \ + /* Force the evaluation at the end of the time step. */ \ + #0; \ + if (uvm_pkg::uvm_resource_db#(virtual _IF)::read_by_name(hier, `"_VIF`", _VIF)) begin \ + vif_found = 1'b1; \ + break; \ + end \ + end \ + `DV_CHECK_FATAL(vif_found, {`"_VIF`", " not found in the resource db"}, hier) \ + end + +`define DV_VIF_WRAP_GET_VIFS_END \ + join \ + endtask diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.core index f11d35c1..1d8a39f7 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.core @@ -64,3 +64,4 @@ targets: - files_rtl - ff_regfile - target_sim? (files_clk_gate) + - target_sim_sc? (files_clk_gate) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.lock.hjson index 00ea518e..fcaf1619 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.lock.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/openhwgroup/cv32e40p.git - rev: c8d65849ec060c6f7bc62325b46ba0ab7eae8805 + rev: a43277c0dc64c02be3f5d713438f315ecffde2b9 } } diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.vendor.hjson index 462a2848..9712edb0 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.vendor.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p.vendor.hjson @@ -7,7 +7,7 @@ upstream: { url: "https://github.com/openhwgroup/cv32e40p.git", - rev: "c8d65849ec060c6f7bc62325b46ba0ab7eae8805", + rev: "a43277c0dc64c02be3f5d713438f315ecffde2b9", }, patch_dir: "patches/openhwgroup_cv32e40p", diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/.gitignore b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/.gitignore index ef351b19..6c2cd791 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/.gitignore +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/.gitignore @@ -18,3 +18,11 @@ TAGS /build /Bender.lock /Bender.local +golden_reference_design +ref_design +golden.src +revised.src +cadence_conformal +synopsys_formality +questa_autocheck +reports diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_instr_trace.svh b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_instr_trace.svh index 8c4ae99f..355bc738 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_instr_trace.svh +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_instr_trace.svh @@ -1,23 +1,37 @@ -// Copyright (c) 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. // -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +// This file, and derivatives thereof are licensed under the +// Solderpad License, Version 2.0 (the "License"). // -// https://solderpad.org/licenses/ +// Use of this file means you agree to the terms and conditions +// of the license and are in full compliance with the License. +// +// You may obtain a copy of the License at: +// +// https://solderpad.org/licenses/SHL-2.0/ // // Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// and hardware implementations thereof distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +// OF ANY KIND, EITHER EXPRESSED OR IMPLIED. +// // See the License for the specific language governing permissions and // limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 -// Tracer data structures and functions -// -// Contributors: Steve Richmond, Silicon Labs -// Pascal Gouedo, Dolphin Design +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Steve Richmond - steve.richmond@silabs.com // +// // +// Design Name: cv32e40p_tracer data structures // +// Project Name: CV32E40P // +// Language: SystemVerilog // +// // +// Description: Moves the class definition for instr_trace_t out of the // +// tracer module for readability and code partitioning // +// // +// Includes various enhancements to make the instr_trace_t // +// class more comprehensive // +// // +//////////////////////////////////////////////////////////////////////////////// typedef struct { logic [5:0] addr; @@ -35,9 +49,13 @@ typedef struct { class instr_trace_t; time simtime; + time stoptime; + bit external_time; int cycles; + int stopcycles; logic [31:0] pc; logic [31:0] instr; + string ctx; //Used to add context in the trace log file (Canceled, debug, interrput,....) bit compressed; bit wb_bypass; bit misaligned; @@ -56,10 +74,15 @@ class instr_trace_t; regs_read = {}; regs_write = {}; mem_access = {}; + external_time = 0; + stoptime = 0; + stopcycles = 0; endfunction function void init(int unsigned cycles, bit [31:0] pc, bit compressed, bit [31:0] instr); - this.simtime = $time; + if(!this.external_time) begin + this.simtime = $time; + end this.cycles = cycles; this.pc = pc; this.compressed = compressed; @@ -308,7 +331,23 @@ class instr_trace_t; begin string insn_str; // Accumulate writes into a single string to enable single $fwrite - insn_str = $sformatf("%t %15d %h %h %-36s", simtime, cycles, pc, instr, str); + if(simtime < 100ns) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else if (simtime < 1us) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else if (simtime < 10us) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else if (simtime < 100us) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else if (simtime < 1ms) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else if (simtime < 10ms) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else if (simtime < 100ms) begin + insn_str = $sformatf(" %t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end else begin + insn_str = $sformatf("%t %15d %h %h %-3s %-36s", simtime, cycles, pc, instr, ctx, str); + end foreach (regs_write[i]) begin if (regs_write[i].addr != 0) @@ -330,6 +369,12 @@ class instr_trace_t; insn_str = $sformatf("%s PA:%08x", insn_str, mem_acc.addr); end + casex (instr) + INSTR_FDIV: insn_str = $sformatf("%s %15d %t", insn_str, stopcycles, stoptime); + INSTR_FSQRT:insn_str = $sformatf("%s %15d %t", insn_str, stopcycles, stoptime); + default: ; + endcase + $fwrite(f, "%s\n", insn_str); end endfunction @@ -489,7 +534,7 @@ class instr_trace_t; begin mnemonic = {compressed ? "c." : "", mnemonic}; regs_read.push_back('{rs1, rs1_value, 0}); - str = $sformatf("%-16s %s, %0d", mnemonic, regAddrToStr(rs1), $signed(imm_sb_type)); + str = $sformatf("%-16s %s, %0d, %0d", mnemonic, regAddrToStr(rs1), $signed(imm_s2_type), $signed(imm_sb_type)); end endfunction // printSBInstr @@ -587,14 +632,14 @@ class instr_trace_t; // immediate post-incremented load regs_read.push_back('{rs1, rs1_value, 0}); regs_write.push_back('{rs1, 'x, 0}); - str = $sformatf("cv.%-13s %s, %0d(x%0d!)", mnemonic, regAddrToStr(rd), $signed(imm_i_type), rs1); + str = $sformatf("cv.%-13s %s, (x%0d), %0d", mnemonic, regAddrToStr(rd), rs1, $signed(imm_i_type)); end else if (instr[6:0] == OPCODE_CUSTOM_1) begin if (instr[27] == 1'b0) begin // reg-reg post-incremented load regs_read.push_back('{rs2, rs2_value, 0}); regs_read.push_back('{rs1, rs1_value, 0}); regs_write.push_back('{rs1, 'x, 0}); - str = $sformatf("cv.%-13s %s, %s(x%0d!)", mnemonic, regAddrToStr(rd), regAddrToStr(rs2), rs1); + str = $sformatf("cv.%-13s %s, (x%0d), %s", mnemonic, regAddrToStr(rd), rs1, regAddrToStr(rs2)); end else begin // reg-reg indexed load regs_read.push_back('{rs2, rs2_value, 0}); @@ -637,7 +682,7 @@ class instr_trace_t; regs_read.push_back('{rs2, rs2_value, 0}); regs_read.push_back('{rs1, rs1_value, 0}); regs_write.push_back('{rs1, 'x, 0}); - str = $sformatf("cv.%-14s %s, %0d(x%0d!)", mnemonic, regAddrToStr(rs2), $signed(imm_s_type), rs1); + str = $sformatf("cv.%-14s %s, (x%0d), %0d", mnemonic, regAddrToStr(rs2), rs1, $signed(imm_s_type)); end else if (instr[31:28] == 4'b0010) begin if (instr[27] == 1'b0) begin // reg-reg post-incremented store @@ -645,7 +690,7 @@ class instr_trace_t; regs_read.push_back('{rs3, rs3_value, 0}); regs_read.push_back('{rs1, rs1_value, 0}); regs_write.push_back('{rs1, 'x, 0}); - str = $sformatf("cv.%-13s %s, %s(x%0d!)", mnemonic, regAddrToStr(rs2), regAddrToStr(rs3), rs1); + str = $sformatf("cv.%-13s %s, (x%0d), %s", mnemonic, regAddrToStr(rs2), rs1, regAddrToStr(rs3)); end else begin // reg-reg indexed store regs_read.push_back('{rs2, rs2_value, 0}); @@ -679,22 +724,22 @@ class instr_trace_t; // decode and print instruction case (instr[11:8]) // cv.starti, cv.endi - 4'b0000, 4'b0010: str = $sformatf("%-16s %d, 0x%0x", mnemonic, rd[0], imm_iz_type); + 4'b0000, 4'b0010: str = $sformatf("%-16s %d, 0x%0x", mnemonic, instr[7], imm_iz_type); // cv.counti - 4'b0100: str = $sformatf("%-16s %d, %d", mnemonic, rd[0], imm_iz_type); + 4'b0100: str = $sformatf("%-16s %d, %d", mnemonic, instr[7], imm_iz_type); // cv.start, cv.end, cv.count 4'b0001, 4'b0011, 4'b0101: begin regs_read.push_back('{rs1, rs1_value, 0}); - str = $sformatf("%-16s %d, %s", mnemonic, rd[0], regAddrToStr(rs1)); + str = $sformatf("%-16s %d, %s", mnemonic, instr[7], regAddrToStr(rs1)); end // cv.setupi 4'b0110: begin - str = $sformatf("%-16s %d, %d, 0x%0x", mnemonic, rd[0], imm_iz_type, rs1); + str = $sformatf("%-16s %d, %d, 0x%0x", mnemonic, instr[7], imm_iz_type, rs1); end // cv.setup 4'b0111: begin regs_read.push_back('{rs1, rs1_value, 0}); - str = $sformatf("%-16s %d, %s, 0x%0x", mnemonic, rd[0], regAddrToStr(rs1), imm_iz_type); + str = $sformatf("%-16s %d, %s, 0x%0x", mnemonic, instr[7], regAddrToStr(rs1), imm_iz_type); end endcase end @@ -757,238 +802,429 @@ class instr_trace_t; else str_hb = ".h"; // set mnemonic - case (instr[31:26]) - 6'b000000: begin + case (instr) + INSTR_CVADDH , + INSTR_CVADDSCH , + INSTR_CVADDSCIH, + INSTR_CVADDB , + INSTR_CVADDSCB , + INSTR_CVADDSCIB : begin mnemonic = "cv.add"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b000010: begin + INSTR_CVSUBH , + INSTR_CVSUBSCH , + INSTR_CVSUBSCIH, + INSTR_CVSUBB , + INSTR_CVSUBSCB , + INSTR_CVSUBSCIB : begin mnemonic = "cv.sub"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b000100: begin + INSTR_CVAVGH , + INSTR_CVAVGSCH , + INSTR_CVAVGSCIH , + INSTR_CVAVGB , + INSTR_CVAVGSCB , + INSTR_CVAVGSCIB : begin mnemonic = "cv.avg"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b000110: begin + INSTR_CVAVGUH , + INSTR_CVAVGUSCH , + INSTR_CVAVGUSCIH, + INSTR_CVAVGUB , + INSTR_CVAVGUSCB , + INSTR_CVAVGUSCIB : begin mnemonic = "cv.avgu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b001000: begin + INSTR_CVMINH , + INSTR_CVMINSCH , + INSTR_CVMINSCIH, + INSTR_CVMINB , + INSTR_CVMINSCB , + INSTR_CVMINSCIB : begin mnemonic = "cv.min"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b001010: begin + INSTR_CVMINUH , + INSTR_CVMINUSCH , + INSTR_CVMINUSCIH, + INSTR_CVMINUB , + INSTR_CVMINUSCB , + INSTR_CVMINUSCIB : begin mnemonic = "cv.minu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b001100: begin + INSTR_CVMAXH , + INSTR_CVMAXSCH , + INSTR_CVMAXSCIH , + INSTR_CVMAXB , + INSTR_CVMAXSCB , + INSTR_CVMAXSCIB : begin mnemonic = "cv.max"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b001110: begin + INSTR_CVMAXUH , + INSTR_CVMAXUSCH , + INSTR_CVMAXUSCIH , + INSTR_CVMAXUB , + INSTR_CVMAXUSCB , + INSTR_CVMAXUSCIB : begin mnemonic = "cv.maxu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b010000: begin + INSTR_CVSRLH , + INSTR_CVSRLSCH , + INSTR_CVSRLSCIH , + INSTR_CVSRLB , + INSTR_CVSRLSCB , + INSTR_CVSRLSCIB : begin mnemonic = "cv.srl"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b010010: begin + INSTR_CVSRAH , + INSTR_CVSRASCH , + INSTR_CVSRASCIH, + INSTR_CVSRAB , + INSTR_CVSRASCB , + INSTR_CVSRASCIB : begin mnemonic = "cv.sra"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b010100: begin + INSTR_CVSLLH , + INSTR_CVSLLSCH , + INSTR_CVSLLSCIH, + INSTR_CVSLLB , + INSTR_CVSLLSCB , + INSTR_CVSLLSCIB : begin mnemonic = "cv.sll"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b010110: begin + INSTR_CVORH , + INSTR_CVORSCH , + INSTR_CVORSCIH, + INSTR_CVORB , + INSTR_CVORSCB , + INSTR_CVORSCIB : begin mnemonic = "cv.or"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b011000: begin + INSTR_CVXORH , + INSTR_CVXORSCH , + INSTR_CVXORSCIH , + INSTR_CVXORB , + INSTR_CVXORSCB , + INSTR_CVXORSCIB : begin mnemonic = "cv.xor"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b011010: begin + INSTR_CVANDH , + INSTR_CVANDSCH , + INSTR_CVANDSCIH , + INSTR_CVANDB , + INSTR_CVANDSCB , + INSTR_CVANDSCIB : begin mnemonic = "cv.and"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b011100: begin + INSTR_CVABSH, + INSTR_CVABSB : begin mnemonic = "cv.abs"; str_imm = $sformatf("0x%0h", imm_vs_type); end // dot products - 6'b100000: begin + INSTR_CVDOTUPH , + INSTR_CVDOTUPSCH , + INSTR_CVDOTUPSCIH, + INSTR_CVDOTUPB , + INSTR_CVDOTUPSCB , + INSTR_CVDOTUPSCIB : begin mnemonic = "cv.dotup"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b100010: begin + INSTR_CVDOTUSPH , + INSTR_CVDOTUSPSCH , + INSTR_CVDOTUSPSCIH, + INSTR_CVDOTUSPB , + INSTR_CVDOTUSPSCB , + INSTR_CVDOTUSPSCIB : begin mnemonic = "cv.dotusp"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b100100: begin + INSTR_CVDOTSPH , + INSTR_CVDOTSPSCH , + INSTR_CVDOTSPSCIH, + INSTR_CVDOTSPB , + INSTR_CVDOTSPSCB , + INSTR_CVDOTSPSCIB : begin mnemonic = "cv.dotsp"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b100110: begin + INSTR_CVSDOTUPH , + INSTR_CVSDOTUPSCH , + INSTR_CVSDOTUPSCIH, + INSTR_CVSDOTUPB , + INSTR_CVSDOTUPSCB , + INSTR_CVSDOTUPSCIB : begin mnemonic = "cv.sdotup"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b101000: begin + INSTR_CVSDOTUSPH , + INSTR_CVSDOTUSPSCH , + INSTR_CVSDOTUSPSCIH, + INSTR_CVSDOTUSPB , + INSTR_CVSDOTUSPSCB , + INSTR_CVSDOTUSPSCIB : begin mnemonic = "cv.sdotusp"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b101010: begin + INSTR_CVSDOTSPH , + INSTR_CVSDOTSPSCH , + INSTR_CVSDOTSPSCIH, + INSTR_CVSDOTSPB , + INSTR_CVSDOTSPSCB , + INSTR_CVSDOTSPSCIB : begin mnemonic = "cv.sdotsp"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b101110: begin - case (instr[14:13]) - 2'b00 : begin - mnemonic = "cv.extract"; - str_imm = $sformatf("0x%0h", imm_vs_type); - end - 2'b01 : begin - mnemonic = "cv.extractu"; - str_imm = $sformatf("0x%0h", imm_vu_type); - end - 2'b10 : begin - mnemonic = "cv.insert"; - str_imm = $sformatf("0x%0h", imm_vs_type); - end - endcase - str_sci = ""; + INSTR_CVEXTRACTH, + INSTR_CVEXTRACTB : begin + mnemonic = "cv.extract"; + str_imm = $sformatf("0x%0h", imm_vs_type); + str_sci = ""; + end + INSTR_CVEXTRACTUH, + INSTR_CVEXTRACTUB : begin + mnemonic = "cv.extractu"; + str_imm = $sformatf("0x%0h", imm_vu_type); + str_sci = ""; end - + INSTR_CVINSERTH, + INSTR_CVINSERTB : begin + mnemonic = "cv.insert"; + str_imm = $sformatf("0x%0h", imm_vs_type); + str_sci = ""; + end + // shuffle/pack - 6'b110000: begin - if (instr[14:12] == 3'b111) begin - mnemonic = "cv.shuffleI0"; - str_imm = $sformatf("0x%8h", imm_shuffle_type); - end else begin + INSTR_CVSHUFFLEH , + INSTR_CVSHUFFLESCIH, + INSTR_CVSHUFFLEB : begin mnemonic = "cv.shuffle"; if (instr[14:12] == 3'b110) begin str_imm = $sformatf("0x%8h", imm_shuffle_type); end - end end - 6'b110010: begin + + INSTR_CVSHUFFLEL0SCIB : begin + mnemonic = "cv.shuffleI0"; + str_imm = $sformatf("0x%8h", imm_shuffle_type); + end + INSTR_CVSHUFFLEL1SCIB : begin mnemonic = "cv.shuffleI1"; str_imm = $sformatf("0x%8h", imm_shuffle_type); end - 6'b110100: begin + INSTR_CVSHUFFLEL2SCIB : begin mnemonic = "cv.shuffleI2"; str_imm = $sformatf("0x%8h", imm_shuffle_type); end - 6'b110110: begin + INSTR_CVSHUFFLEL3SCIB : begin mnemonic = "cv.shuffleI3"; str_imm = $sformatf("0x%8h", imm_shuffle_type); end - 6'b111000: begin + INSTR_CVSHUFFLE2H, + INSTR_CVSHUFFLE2B : begin mnemonic = "cv.shuffle2"; end - 6'b111100: begin + INSTR_CVPACK, + INSTR_CVPACKH : begin mnemonic = "cv.pack"; if (instr[25] == 1'b0) begin str_hb = ""; end end - 6'b111110: begin - mnemonic = instr[25] ? "cv.packhi" : "cv.packlo"; - end + INSTR_CVPACKHIB : mnemonic = "cv.packhi"; + INSTR_CVPACKLOB : mnemonic = "cv.packlo"; // comparisons - 6'b000001: begin + INSTR_CVCMPEQH , + INSTR_CVCMPEQSCH , + INSTR_CVCMPEQSCIH, + INSTR_CVCMPEQB , + INSTR_CVCMPEQSCB , + INSTR_CVCMPEQSCIB : begin mnemonic = "cv.cmpeq"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b000011: begin + INSTR_CVCMPNEH , + INSTR_CVCMPNESCH , + INSTR_CVCMPNESCIH, + INSTR_CVCMPNEB , + INSTR_CVCMPNESCB , + INSTR_CVCMPNESCIB : begin mnemonic = "cv.cmpne"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b000101: begin + INSTR_CVCMPGTH , + INSTR_CVCMPGTSCH , + INSTR_CVCMPGTSCIH, + INSTR_CVCMPGTB , + INSTR_CVCMPGTSCB , + INSTR_CVCMPGTSCIB : begin mnemonic = "cv.cmpgt"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b000111: begin + INSTR_CVCMPGEH , + INSTR_CVCMPGESCH , + INSTR_CVCMPGESCIH, + INSTR_CVCMPGEB , + INSTR_CVCMPGESCB , + INSTR_CVCMPGESCIB : begin mnemonic = "cv.cmpge"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b001001: begin + INSTR_CVCMPLTH , + INSTR_CVCMPLTSCH , + INSTR_CVCMPLTSCIH, + INSTR_CVCMPLTB , + INSTR_CVCMPLTSCB , + INSTR_CVCMPLTSCIB : begin mnemonic = "cv.cmplt"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b001011: begin + INSTR_CVCMPLEH , + INSTR_CVCMPLESCH , + INSTR_CVCMPLESCIH, + INSTR_CVCMPLEB , + INSTR_CVCMPLESCB , + INSTR_CVCMPLESCIB : begin mnemonic = "cv.cmple"; str_imm = $sformatf("0x%0h", imm_vs_type); end - 6'b001101: begin + INSTR_CVCMPGTUH , + INSTR_CVCMPGTUSCH , + INSTR_CVCMPGTUSCIH, + INSTR_CVCMPGTUB , + INSTR_CVCMPGTUSCB , + INSTR_CVCMPGTUSCIB : begin mnemonic = "cv.cmpgtu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b001111: begin + INSTR_CVCMPGEUH , + INSTR_CVCMPGEUSCH , + INSTR_CVCMPGEUSCIH, + INSTR_CVCMPGEUB , + INSTR_CVCMPGEUSCB , + INSTR_CVCMPGEUSCIB : begin mnemonic = "cv.cmpgeu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b010001: begin + INSTR_CVCMPLTUH , + INSTR_CVCMPLTUSCH , + INSTR_CVCMPLTUSCIH, + INSTR_CVCMPLTUB , + INSTR_CVCMPLTUSCB , + INSTR_CVCMPLTUSCIB : begin mnemonic = "cv.cmpltu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b010011: begin + INSTR_CVCMPLEUH , + INSTR_CVCMPLEUSCH , + INSTR_CVCMPLEUSCIH, + INSTR_CVCMPLEUB , + INSTR_CVCMPLEUSCB , + INSTR_CVCMPLEUSCIB : begin mnemonic = "cv.cmpleu"; str_imm = $sformatf("0x%0h", imm_vu_type); end - 6'b010101: begin - unique case (instr[14:13]) - 2'b00: mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r" : "cv.cplxmul.i"; - 2'b01: mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r.div2" : "cv.cplxmul.i.div2"; - 2'b10: mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r.div4" : "cv.cplxmul.i.div4"; - 2'b11: mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r.div8" : "cv.cplxmul.i.div8"; - endcase + INSTR_CVCPLXMULR, + INSTR_CVCPLXMULI : begin + mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r" : "cv.cplxmul.i"; str_sci = ""; str_hb = ""; end - - 6'b010111: begin - mnemonic = "cv.cplxconj"; - str_sci = ""; + INSTR_CVCPLXMULRDIV2, + INSTR_CVCPLXMULIDIV2 : begin + mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r.div2" : "cv.cplxmul.i.div2"; + str_sci = ""; str_hb = ""; end - - 6'b011001: begin - unique case (instr[14:13]) - 2'b00: mnemonic = "cv.subrotmj"; - 2'b01: mnemonic = "cv.subrotmj.div2"; - 2'b10: mnemonic = "cv.subrotmj.div4"; - 2'b11: mnemonic = "cv.subrotmj.div8"; - endcase + INSTR_CVCPLXMULRDIV4, + INSTR_CVCPLXMULIDIV4 : begin + mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r.div4" : "cv.cplxmul.i.div4"; str_sci = ""; str_hb = ""; end - - 6'b011011: begin - unique case (instr[14:13]) - 2'b01: mnemonic = "cv.add.div2"; - 2'b10: mnemonic = "cv.add.div4"; - 2'b11: mnemonic = "cv.add.div8"; - endcase + INSTR_CVCPLXMULRDIV8, + INSTR_CVCPLXMULIDIV8 : begin + mnemonic = instr[25] == 1'b0 ? "cv.cplxmul.r.div8" : "cv.cplxmul.i.div8"; str_sci = ""; str_hb = ""; end - 6'b011101: begin - unique case (instr[14:13]) - 2'b01: mnemonic = "cv.sub.div2"; - 2'b10: mnemonic = "cv.sub.div4"; - 2'b11: mnemonic = "cv.sub.div8"; - endcase - str_sci = ""; + INSTR_CVCPLXCONJ : begin + mnemonic = "cv.cplxconj"; + str_sci = ""; str_hb = ""; end + INSTR_CVSUBROTMJ : begin + mnemonic = "cv.subrotmj"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVSUBROTMJDIV2 : begin + mnemonic = "cv.subrotmj.div2"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVSUBROTMJDIV4 : begin + mnemonic = "cv.subrotmj.div4"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVSUBROTMJDIV8 : begin + mnemonic = "cv.subrotmj.div8"; + str_sci = ""; + str_hb = ""; + end + + INSTR_CVADDIV2 : begin + mnemonic = "cv.add.div2"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVADDIV4 : begin + mnemonic = "cv.add.div4"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVADDIV8 : begin + mnemonic = "cv.add.div8"; + str_sci = ""; + str_hb = ""; + end + + INSTR_CVSUBIV2 : begin + mnemonic = "cv.sub.div2"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVSUBIV4 : begin + mnemonic = "cv.sub.div4"; + str_sci = ""; + str_hb = ""; + end + INSTR_CVSUBIV8 : begin + mnemonic = "cv.sub.div8"; + str_sci = ""; + str_hb = ""; + end + default: begin printMnemonic("INVALID"); return; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_rvfi.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_rvfi.sv index ca158f96..99429d90 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_rvfi.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_rvfi.sv @@ -1,24 +1,28 @@ -// Copyright (c) 2020 OpenHW Group +// Copyright 2024 Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. // You may obtain a copy of the License at // -// https://solderpad.org/licenses/ +// https://solderpad.org/licenses/SHL-2.1/ // -// Unless required by applicable law or agreed to in writing, software +// Unless required by applicable law or agreed to in writing, any work // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 -// CV32E40P RVFI interface -// -// Contributors: Davide Schiavone, OpenHW Group -// Halfdan Bechmann, Silicon Labs -// Yoann Pruvost, Dolphin Design +//////////////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Davide Schiavone, OpenHW Group // +// Halfdan Bechmann, Silicon Labs // +// Yoann Pruvost, Dolphin Design // +// // +// Description: CV32E40P RVFI interface // +// // +//////////////////////////////////////////////////////////////////////////////////// `include "cv32e40p_rvfi_pkg.sv" @@ -27,7 +31,8 @@ module cv32e40p_rvfi import cv32e40p_rvfi_pkg::*; #( parameter FPU = 0, - parameter ZFINX = 0 + parameter ZFINX = 0, + parameter NUM_MHPMCOUNTERS = 1 ) ( input logic clk_i, input logic rst_ni, @@ -73,6 +78,10 @@ module cv32e40p_rvfi input logic is_compressed_id_i, input logic ebrk_insn_dec_i, + input logic ecall_insn_dec_i, + + input logic mret_insn_dec_i, + input logic mret_dec_i, input logic [5:0] csr_cause_i, @@ -126,6 +135,9 @@ module cv32e40p_rvfi input logic [31:0] data_wdata_ex_i, input logic lsu_split_q_ex_i, + input logic mult_ready_i, + input logic alu_ready_i, + //// WB probes //// input logic [31:0] pc_wb_i, input logic wb_ready_i, @@ -202,6 +214,7 @@ module cv32e40p_rvfi input logic csr_we_i, input logic [31:0] csr_wdata_int_i, + input logic csr_fregs_we_i, input logic csr_jvt_we_i, input Status_t csr_mstatus_n_i, input Status_t csr_mstatus_q_i, @@ -282,7 +295,7 @@ module cv32e40p_rvfi // performance counters // cycle, instret, hpcounter, cycleh, instreth, hpcounterh // mcycle, minstret, mhpcounter, mcycleh, minstreth, mhpcounterh - input logic [31:0][MHPMCOUNTER_WIDTH-1:0] csr_mhpmcounter_q_i, + input logic [63:0][MHPMCOUNTER_WIDTH-1:0] csr_mhpmcounter_q_i, input logic [31:0] csr_mhpmcounter_write_lower_i, input logic [31:0] csr_mhpmcounter_write_upper_i, @@ -319,6 +332,10 @@ module cv32e40p_rvfi // the convention of RISC-V Formal Interface Specification. output logic [ 0:0] rvfi_valid, output logic [63:0] rvfi_order, + output integer rvfi_start_cycle, + output time rvfi_start_time, + output integer rvfi_stop_cycle, + output time rvfi_stop_time, output logic [31:0] rvfi_insn, output rvfi_trap_t rvfi_trap, output logic [ 0:0] rvfi_halt, @@ -338,6 +355,7 @@ module cv32e40p_rvfi output logic rvfi_frd_wvalid [1:0], output logic [ 4:0] rvfi_frd_addr [1:0], output logic [31:0] rvfi_frd_wdata [1:0], + output logic rvfi_2_rd, output logic [ 4:0] rvfi_rs1_addr, output logic [ 4:0] rvfi_rs2_addr, output logic [ 4:0] rvfi_rs3_addr, @@ -358,8 +376,8 @@ module cv32e40p_rvfi output logic [31:0] rvfi_pc_wdata, output logic [31:0] rvfi_mem_addr, - output logic [ 3:0] rvfi_mem_rmask, - output logic [ 3:0] rvfi_mem_wmask, + output logic [31:0] rvfi_mem_rmask, + output logic [31:0] rvfi_mem_wmask, output logic [31:0] rvfi_mem_rdata, output logic [31:0] rvfi_mem_wdata, @@ -610,6 +628,13 @@ module cv32e40p_rvfi bit clk_i_d; assign #0.01 clk_i_d = clk_i; + integer cycles; + // cycle counter + always_ff @(posedge clk_i_d, negedge rst_ni) begin + if (rst_ni == 1'b0) cycles <= 0; + else cycles <= cycles + 1; + end + logic pc_mux_debug; logic pc_mux_dret; logic pc_mux_exception; @@ -617,6 +642,11 @@ module cv32e40p_rvfi logic pc_mux_interrupt; logic pc_mux_nmi; + localparam logic [31:0] MSTATUS_WRITE_MASK = 32'h0000_6088; + localparam logic [31:0] MCOUNTINHIBIT_WRITE_MASK = {{(29-NUM_MHPMCOUNTERS){1'b0}}, {(NUM_MHPMCOUNTERS){1'b1}}, 3'b101}; + localparam NUM_HPM_EVENTS = 16; + localparam logic [31:0] MHPMEVENT_WRITE_MASK = {{(31-NUM_HPM_EVENTS){1'b0}}, {(NUM_HPM_EVENTS){1'b1}}}; + `include "pipe_freeze_trace.sv" `include "insn_trace.sv" @@ -633,6 +663,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; logic [2:0] saved_debug_cause; integer next_send; + event e_empty_queue; function void empty_fifo(); integer i, trace_q_size; trace_q_size = wb_bypass_trace_q.size(); @@ -648,6 +679,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; new_rvfi_trace.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; rvfi_trace_q.push_back(new_rvfi_trace); next_send = next_send + 1; + ->e_empty_queue; end else begin wb_bypass_trace_q.push_back(new_rvfi_trace); end @@ -658,6 +690,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; /* * Function used to alocate a new insn and send it to the rvfi driver */ + event e_add_to_bypass; function void send_rvfi(insn_trace_t m_wb_insn); insn_trace_t new_rvfi_trace; new_rvfi_trace = new(); @@ -667,6 +700,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; next_send = next_send + 1; end else begin wb_bypass_trace_q.push_back(new_rvfi_trace); + ->e_add_to_bypass; end empty_fifo(); endfunction @@ -733,6 +767,10 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end rvfi_order = new_rvfi_trace.m_order; + rvfi_start_cycle = new_rvfi_trace.m_start_cycle; + rvfi_start_time = new_rvfi_trace.m_start_time; + rvfi_stop_cycle = new_rvfi_trace.m_stop_cycle; + rvfi_stop_time = new_rvfi_trace.m_stop_time; rvfi_pc_rdata = new_rvfi_trace.m_pc_rdata; rvfi_insn = new_rvfi_trace.m_insn; @@ -787,6 +825,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; rvfi_frd_addr[1] = '0; rvfi_frd_wdata[1] = '0; + rvfi_2_rd = new_rvfi_trace.m_2_rd_insn; if (new_rvfi_trace.m_rd_addr[0][5] == 1'b0) begin rvfi_rd_addr[0] = new_rvfi_trace.m_rd_addr[0][4:0]; rvfi_rd_wdata[0] = new_rvfi_trace.m_rd_wdata[0]; @@ -837,7 +876,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; //CSR rvfi_csr_mstatus_rmask = new_rvfi_trace.m_csr.mstatus_rmask | new_rvfi_trace.m_csr.mstatus_fs_rmask; - rvfi_csr_mstatus_wmask = new_rvfi_trace.m_csr.mstatus_wmask; + rvfi_csr_mstatus_wmask = new_rvfi_trace.m_csr.mstatus_wmask & MSTATUS_WRITE_MASK; rvfi_csr_mstatus_wmask[31] = new_rvfi_trace.m_csr.mstatus_fs_wmask[31]; rvfi_csr_mstatus_wmask[14:13] = new_rvfi_trace.m_csr.mstatus_fs_wmask[14:13]; @@ -870,7 +909,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end rvfi_csr_mstatus_wdata[30:18] = '0; // MPRV is not implemented in the target configuration, writes to it are ignored - rvfi_csr_mstatus_wdata[17] = 1'b0;//new_rvfi_trace.m_csr.mstatus_wdata.mprv; + rvfi_csr_mstatus_wdata[17] = 1'b0; //new_rvfi_trace.m_csr.mstatus_wdata.mprv; rvfi_csr_mstatus_wdata[16:15] = '0; if (FPU == 1 && ZFINX == 0) begin rvfi_csr_mstatus_wdata[14:13] = new_rvfi_trace.m_csr.mstatus_fs_wdata; @@ -882,24 +921,59 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; rvfi_csr_mstatus_wdata[7] = new_rvfi_trace.m_csr.mstatus_wdata.mpie; rvfi_csr_mstatus_wdata[6:5] = '0; // UPIE is not implemented in the target configuration, writes to it are ignored - rvfi_csr_mstatus_wdata[4] = 1'b0;//new_rvfi_trace.m_csr.mstatus_wdata.upie; + rvfi_csr_mstatus_wdata[4] = 1'b0; //new_rvfi_trace.m_csr.mstatus_wdata.upie; rvfi_csr_mstatus_wdata[3] = new_rvfi_trace.m_csr.mstatus_wdata.mie; rvfi_csr_mstatus_wdata[2:1] = '0; // UIE is not implemented in the target configuration, writes to it are ignored - rvfi_csr_mstatus_wdata[0] = 1'b0;//new_rvfi_trace.m_csr.mstatus_wdata.uie; + rvfi_csr_mstatus_wdata[0] = 1'b0; //new_rvfi_trace.m_csr.mstatus_wdata.uie; `SET_RVFI_CSR_FROM_INSN(misa) `SET_RVFI_CSR_FROM_INSN(mie) `SET_RVFI_CSR_FROM_INSN(mtvec) - `SET_RVFI_CSR_FROM_INSN(mcountinhibit) + + rvfi_csr_mcountinhibit_rdata = new_rvfi_trace.m_csr.mcountinhibit_rdata; + rvfi_csr_mcountinhibit_rmask = new_rvfi_trace.m_csr.mcountinhibit_rmask; + rvfi_csr_mcountinhibit_wdata = new_rvfi_trace.m_csr.mcountinhibit_wdata; + rvfi_csr_mcountinhibit_wmask = new_rvfi_trace.m_csr.mcountinhibit_wmask & MCOUNTINHIBIT_WRITE_MASK; + `SET_RVFI_CSR_FROM_INSN(mscratch) `SET_RVFI_CSR_FROM_INSN(mepc) `SET_RVFI_CSR_FROM_INSN(mcause) + `SET_RVFI_CSR_FROM_INSN(mcycle) `SET_RVFI_CSR_FROM_INSN(minstret) + `SET_RVFI_CSR_FROM_INSN(minstreth) + + // `SET_RVFI_CSR_FROM_INSN(cycle) + // `SET_RVFI_CSR_FROM_INSN(instret) + rvfi_csr_instret_rdata = new_rvfi_trace.m_csr.minstret_rdata; + rvfi_csr_instret_rmask = new_rvfi_trace.m_csr.minstret_rmask; + rvfi_csr_instret_wdata = new_rvfi_trace.m_csr.minstret_wdata; + rvfi_csr_instret_wmask = new_rvfi_trace.m_csr.minstret_wmask; + + for(int idx=3; idx<32; idx++) begin + rvfi_csr_mhpmcounter_rmask[idx] = new_rvfi_trace.m_csr.mhpmcounter_rmask[idx][31:0]; + rvfi_csr_mhpmcounter_wmask[idx] = new_rvfi_trace.m_csr.mhpmcounter_wmask[idx][31:0]; + rvfi_csr_mhpmcounter_rdata[idx] = new_rvfi_trace.m_csr.mhpmcounter_rdata[idx][31:0]; + rvfi_csr_mhpmcounter_wdata[idx] = new_rvfi_trace.m_csr.mhpmcounter_wdata[idx][31:0]; + + rvfi_csr_mhpmcounterh_rmask[idx] = new_rvfi_trace.m_csr.mhpmcounter_rmask[idx][63:32]; + rvfi_csr_mhpmcounterh_wmask[idx] = new_rvfi_trace.m_csr.mhpmcounter_wmask[idx][63:32]; + rvfi_csr_mhpmcounterh_rdata[idx] = new_rvfi_trace.m_csr.mhpmcounter_rdata[idx][63:32]; + rvfi_csr_mhpmcounterh_wdata[idx] = new_rvfi_trace.m_csr.mhpmcounter_wdata[idx][63:32]; + + rvfi_csr_mhpmevent_rmask[idx] = new_rvfi_trace.m_csr.mhpmevent_rmask[idx]; + rvfi_csr_mhpmevent_wmask[idx] = new_rvfi_trace.m_csr.mhpmevent_wmask[idx] & MHPMEVENT_WRITE_MASK; + rvfi_csr_mhpmevent_rdata[idx] = new_rvfi_trace.m_csr.mhpmevent_rdata[idx]; + rvfi_csr_mhpmevent_wdata[idx] = new_rvfi_trace.m_csr.mhpmevent_wdata[idx]; + end + // `SET_RVFI_CSR_FROM_INSN(instreth) + rvfi_csr_instreth_rdata = new_rvfi_trace.m_csr.minstreth_rdata; + rvfi_csr_instreth_rmask = new_rvfi_trace.m_csr.minstreth_rmask; + rvfi_csr_instreth_wdata = new_rvfi_trace.m_csr.minstreth_wdata; + rvfi_csr_instreth_wmask = new_rvfi_trace.m_csr.minstreth_wmask; + `SET_RVFI_CSR_FROM_INSN(mip) - // if(rvfi_order == 64'h00000000_00000167) begin - // rvfi_csr_mip_rdata = 32'h0010_0000; - // end + rvfi_csr_tdata_rdata[0] = 'Z; rvfi_csr_tdata_rmask[0] = '0; // Does not exist rvfi_csr_tdata_wdata[0] = 'Z; // Does not exist @@ -945,36 +1019,134 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; endfunction // set_rvfi - function void minstret_to_id(); - trace_id.m_csr.minstret_we = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2]; - trace_id.m_csr.minstret_rdata = r_pipe_freeze_trace.csr.mhpmcounter_q[2]; - trace_id.m_csr.minstret_rmask = '1; - trace_id.m_csr.minstret_wdata = r_pipe_freeze_trace.csr.mhpmcounter_q; - trace_id.m_csr.minstret_wmask = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2] ? '1 : '0; + function void sample_perf_counter_to_id(int idx); + trace_id.m_csr.mhpmcounter_rdata[idx][31:0] = r_pipe_freeze_trace.csr.mhpmcounter_q[idx][31:0]; + trace_id.m_csr.mhpmcounter_rmask[idx][31:0] = '1; + endfunction + + function void perf_counter_to_id(int idx); + if(!trace_id.m_csr.mhpmcounter_we[idx][0]) begin + trace_id.m_csr.mhpmcounter_wdata[idx][31:0] = r_pipe_freeze_trace.csr.wdata_int; + end + if(r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx]) begin + trace_id.m_csr.mhpmcounter_we[idx][0] = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx]; + trace_id.m_csr.mhpmcounter_wdata[idx][31:0] = r_pipe_freeze_trace.csr.wdata_int; + trace_id.m_csr.mhpmcounter_wmask[idx][31:0] = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx] ? '1 : '0; + end + sample_perf_counter_to_id(idx); + endfunction + + function void sample_perf_event_to_trace(int idx, insn_trace_t m_trace); + m_trace.m_csr.mhpmevent_rdata[idx] = r_pipe_freeze_trace.csr.mhpmevent_q[idx]; + m_trace.m_csr.mhpmevent_rmask[idx] = '1; endfunction - function void minstret_to_ex(); - trace_ex.m_csr.minstret_we = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2]; - trace_ex.m_csr.minstret_rdata = r_pipe_freeze_trace.csr.mhpmcounter_q[2]; - trace_ex.m_csr.minstret_rmask = '1; - trace_ex.m_csr.minstret_wdata = r_pipe_freeze_trace.csr.mhpmcounter_q; - trace_ex.m_csr.minstret_wmask = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2] ? '1 : '0; + function void perf_event_to_trace(int idx, insn_trace_t m_trace); + if(!m_trace.m_csr.mhpmevent_we[idx]) begin + m_trace.m_csr.mhpmevent_wdata[idx] = r_pipe_freeze_trace.csr.wdata_int; + end + if(r_pipe_freeze_trace.csr.mhpmevent_we[idx]) begin + m_trace.m_csr.mhpmevent_we[idx] = r_pipe_freeze_trace.csr.mhpmevent_we[idx]; + m_trace.m_csr.mhpmevent_wdata[idx] = r_pipe_freeze_trace.csr.wdata_int; + m_trace.m_csr.mhpmevent_wmask[idx] = r_pipe_freeze_trace.csr.mhpmevent_we[idx] ? '1 : '0; + end + sample_perf_event_to_trace(idx, m_trace); endfunction - function void tinfo_to_id(); - trace_id.m_csr.tinfo_we = '0; // READ ONLY csr_tinfo_we_i; - trace_id.m_csr.tinfo_rdata = r_pipe_freeze_trace.csr.tinfo_q; - trace_id.m_csr.tinfo_rmask = '1; - trace_id.m_csr.tinfo_wdata = r_pipe_freeze_trace.csr.tinfo_n; - trace_id.m_csr.tinfo_wmask = '0; + function void sample_minstret_to_trace(insn_trace_t m_trace); + m_trace.m_csr.minstret_rdata = r_pipe_freeze_trace.csr.mhpmcounter_q[2][31:0]; + m_trace.m_csr.minstret_rmask = '1; endfunction - function void tinfo_to_ex(); - trace_ex.m_csr.tinfo_we = '0; // READ ONLY csr_tinfo_we_i; - trace_ex.m_csr.tinfo_rdata = r_pipe_freeze_trace.csr.tinfo_q; - trace_ex.m_csr.tinfo_rmask = '1; - trace_ex.m_csr.tinfo_wdata = r_pipe_freeze_trace.csr.tinfo_n; - trace_ex.m_csr.tinfo_wmask = '0; + function void minstret_to_trace(insn_trace_t m_trace); + if(!m_trace.m_csr.minstret_we) begin + m_trace.m_csr.minstret_wdata = r_pipe_freeze_trace.csr.wdata_int; + end + if(r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2]) begin + m_trace.m_csr.minstret_we = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2]; + m_trace.m_csr.minstret_wdata = r_pipe_freeze_trace.csr.wdata_int; + m_trace.m_csr.minstret_wmask = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2] ? '1 : '0; + end + sample_minstret_to_trace(m_trace); + endfunction + + function void sample_perf_counter_h_to_id(int idx); + trace_id.m_csr.mhpmcounter_rdata[idx][63:32] = r_pipe_freeze_trace.csr.mhpmcounter_q[idx][63:0]; + trace_id.m_csr.mhpmcounter_rmask[idx][63:32] = '1; + endfunction + + function void perf_counter_h_to_id(int idx); + if(!trace_id.m_csr.mhpmcounter_we[idx][1]) begin + trace_id.m_csr.mhpmcounter_wdata[idx][63:32] = r_pipe_freeze_trace.csr.wdata_int; + end + if(r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx]) begin + trace_id.m_csr.mhpmcounter_we[idx][1] = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx]; + trace_id.m_csr.mhpmcounter_wdata[idx][63:32] = r_pipe_freeze_trace.csr.wdata_int; + trace_id.m_csr.mhpmcounter_wmask[idx][63:32] = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx] ? '1 : '0; + end + sample_perf_counter_h_to_id(idx); + endfunction + + function void sample_minstreth_to_trace(insn_trace_t m_trace); + m_trace.m_csr.minstreth_rdata = r_pipe_freeze_trace.csr.mhpmcounter_q[2][63:32]; + m_trace.m_csr.minstreth_rmask = '1; + endfunction + + function void sample_mcycle_to_trace(insn_trace_t m_trace); + m_trace.m_csr.mcycle_we = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[0]; + m_trace.m_csr.mcycle_rdata = r_pipe_freeze_trace.csr.mhpmcounter_q[0][31:0]; + m_trace.m_csr.mcycle_rmask = '1; + m_trace.m_csr.mcycle_wdata = r_pipe_freeze_trace.csr.mhpmcounter_q[31:0]; + m_trace.m_csr.mcycle_wmask = r_pipe_freeze_trace.csr.mhpmcounter_write_lower[0] ? '1 : '0; + endfunction + + function void minstreth_to_trace(insn_trace_t m_trace); + if(!m_trace.m_csr.minstreth_we) begin + m_trace.m_csr.minstreth_wdata = r_pipe_freeze_trace.csr.wdata_int; + end + if(r_pipe_freeze_trace.csr.mhpmcounter_write_upper[2]) begin + m_trace.m_csr.minstreth_we = r_pipe_freeze_trace.csr.mhpmcounter_write_upper[2]; + m_trace.m_csr.minstreth_wdata = r_pipe_freeze_trace.csr.wdata_int; + m_trace.m_csr.minstreth_wmask = r_pipe_freeze_trace.csr.mhpmcounter_write_upper[2] ? '1 : '0; + end + sample_minstreth_to_trace(m_trace); + endfunction + + function void sample_perf_counter_to_trace(insn_trace_t m_trace); + sample_minstret_to_trace(m_trace); + sample_minstreth_to_trace(m_trace); + sample_mcycle_to_trace(m_trace); + for(int idx=3; idx<32; idx++)begin + sample_perf_event_to_trace(idx, m_trace); //TO CHANGE + end + endfunction + + function void perf_counter_to_trace(insn_trace_t m_trace); + if(r_pipe_freeze_trace.csr.mhpmcounter_write_lower[2]) begin + minstret_to_trace(m_trace); + end + if(r_pipe_freeze_trace.csr.mhpmcounter_write_upper[2]) begin + minstreth_to_trace(m_trace); + end + for(int idx=3; idx<32; idx++) begin + if(r_pipe_freeze_trace.csr.mhpmcounter_write_lower[idx]) begin + perf_counter_to_id(idx); + end + if(r_pipe_freeze_trace.csr.mhpmcounter_write_upper[idx]) begin + perf_counter_h_to_id(idx); + end + if(r_pipe_freeze_trace.csr.mhpmevent_we[idx]) begin + perf_event_to_trace(idx, m_trace); + end + end + endfunction + + function void tinfo_to_trace(insn_trace_t m_trace); + m_trace.m_csr.tinfo_we = '0; // READ ONLY csr_tinfo_we_i; + m_trace.m_csr.tinfo_rdata = r_pipe_freeze_trace.csr.tinfo_q; + m_trace.m_csr.tinfo_rmask = '1; + m_trace.m_csr.tinfo_wdata = r_pipe_freeze_trace.csr.tinfo_n; + m_trace.m_csr.tinfo_wmask = '0; endfunction function void mtvec_to_id(); @@ -1069,8 +1241,6 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; lpcount1_to_id(); lpend1_to_id(); lpstart1_to_id(); - - endfunction bit s_was_flush; //debug exception is flagged as trap only if preceed by a flush @@ -1111,6 +1281,9 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; * The third updates the rvfi interface */ `define CSR_FROM_PIPE(TRACE_NAME, CSR_NAME) \ + if(!trace_``TRACE_NAME``.m_csr.``CSR_NAME``_we) begin \ + trace_``TRACE_NAME``.m_csr.``CSR_NAME``_wdata = r_pipe_freeze_trace.csr.``CSR_NAME``_n; \ + end\ if (r_pipe_freeze_trace.csr.``CSR_NAME``_we) begin \ trace_``TRACE_NAME``.m_csr.``CSR_NAME``_we = r_pipe_freeze_trace.csr.``CSR_NAME``_we; \ trace_``TRACE_NAME``.m_csr.``CSR_NAME``_wdata = r_pipe_freeze_trace.csr.``CSR_NAME``_n; \ @@ -1120,9 +1293,14 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_``TRACE_NAME``.m_csr.``CSR_NAME``_rmask = '1; event e_mstatus_to_id; + event e_fregs_dirty_1, e_fregs_dirty_2, e_fregs_dirty_3; function void mstatus_to_id(); `CSR_FROM_PIPE(id, mstatus) `CSR_FROM_PIPE(id, mstatus_fs) + if(r_pipe_freeze_trace.csr.fregs_we && !r_pipe_freeze_trace.csr.mstatus_fs_we && !(r_pipe_freeze_trace.csr.we && r_pipe_freeze_trace.csr.mstatus_fs_we)) begin //writes happening in ex that needs to be reported to id + trace_id.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; + ->e_fregs_dirty_2; + end ->e_mstatus_to_id; endfunction //those event are for debug purpose @@ -1133,10 +1311,11 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; e_dev_commit_rf_to_ex_3, e_dev_commit_rf_to_ex_4, e_dev_commit_rf_to_ex_5; - event e_if_2_id_1, e_if_2_id_2; + event e_if_2_id_1, e_if_2_id_2, e_if_2_id_3, e_if_2_id_4; event e_ex_to_wb_1, e_ex_to_wb_2; event e_id_to_ex_1, e_id_to_ex_2; event e_commit_dpc; + event e_csr_in_ex, e_csr_irq; event e_send_rvfi_trace_apu_resp; event @@ -1160,12 +1339,17 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; `CSR_FROM_PIPE(apu_resp, fcsr) `CSR_FROM_PIPE(apu_resp, fflags) - // `CSR_FROM_PIPE(apu_resp, mstatus) `CSR_FROM_PIPE(apu_resp, mstatus_fs) - if (r_pipe_freeze_trace.csr.mstatus_we) begin + if (r_pipe_freeze_trace.csr.mstatus_fs_we && (trace_id.m_order > trace_apu_resp.m_order)) begin + trace_id.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; + end + if (r_pipe_freeze_trace.csr.mstatus_fs_we && (trace_ex.m_order > trace_apu_resp.m_order)) begin trace_ex.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; end + if (r_pipe_freeze_trace.csr.mstatus_fs_we && (trace_wb.m_order > trace_apu_resp.m_order)) begin + trace_wb.m_csr.mstatus_fs_rdata = r_pipe_freeze_trace.csr.mstatus_fs_n; + end endfunction function void csr_to_apu_req(); @@ -1229,6 +1413,9 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end end csr_to_apu_resp(); + + trace_apu_resp.m_stop_cycle = cycles; + trace_apu_resp.m_stop_time = $time; send_rvfi(trace_apu_resp); ->e_send_rvfi_trace_apu_resp; end @@ -1243,27 +1430,48 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; bit s_is_irq_start; bit s_id_done; function void if_to_id(); + if (trace_id.m_valid) begin + `CSR_FROM_PIPE(id, misa) + `CSR_FROM_PIPE(id, tdata1) + `CSR_FROM_PIPE(id, tdata2) + tinfo_to_trace(trace_id); + `CSR_FROM_PIPE(id, mip) + send_rvfi(trace_id); + end trace_id.init(trace_if); trace_id.m_trap = ~r_pipe_freeze_trace.minstret; - trace_id.m_is_illegal = r_pipe_freeze_trace.is_illegal; + trace_id.m_is_illegal = trace_id.m_is_illegal | r_pipe_freeze_trace.is_illegal; + `CSR_FROM_PIPE(id, dpc) s_is_pc_set = 1'b0; s_is_irq_start = 1'b0; trace_if.m_valid = 1'b0; s_id_done = 1'b0; - `CSR_FROM_PIPE(id, dpc) endfunction function logic [31:0] be_to_mask(logic [3:0] be); logic [31:0] mask; - mask[7:0] = be[0] ? 8'hFF : 8'h00; - mask[15:8] = be[0] ? 8'hFF : 8'h00; - mask[23:16] = be[0] ? 8'hFF : 8'h00; - mask[31:24] = be[0] ? 8'hFF : 8'h00; + mask[7:0] = (be[0] == 1'b1) ? 8'hFF : 8'h00; + mask[15:8] = (be[1] == 1'b1) ? 8'hFF : 8'h00; + mask[23:16] = (be[2] == 1'b1) ? 8'hFF : 8'h00; + mask[31:24] = (be[3] == 1'b1) ? 8'hFF : 8'h00; be_to_mask = mask; return mask; endfunction + function void commit_rf_to_trace(insn_trace_t m_trace); + if (m_trace.m_got_ex_reg) begin + m_trace.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; + m_trace.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; + m_trace.m_2_rd_insn = 1'b1; + m_trace.m_got_first_data = 1'b1; + end else begin + m_trace.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; + m_trace.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; + m_trace.m_got_first_data = 1'b1; + end + endfunction + task compute_pipeline(); bit s_new_valid_insn; bit s_ex_valid_adjusted; @@ -1280,34 +1488,44 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; bit s_core_is_decoding; // For readability, ctrl_fsm is DECODE or DECODE_HWLOOP - trace_if = new(); - trace_id = new(); - trace_ex = new(); - trace_wb = new(); - s_new_valid_insn = 1'b0; - s_ex_valid_adjusted = 1'b0; + bit s_ex_reg_we_adjusted; //ex_reg_we + bit s_rf_we_wb_adjusted; // + + bit s_dont_override_mstatus_fs_id; + + trace_if = new(); + trace_id = new(); + trace_ex = new(); + trace_wb = new(); + s_new_valid_insn = 1'b0; + s_ex_valid_adjusted = 1'b0; + + s_id_done = 1'b0; + s_apu_wb_ok = 1'b0; + s_apu_0_cycle_reps = 1'b0; + + next_send = 1; + cnt_data_req = 0; + cnt_data_resp = 0; + cnt_apu_req = 0; + cnt_apu_resp = 0; + csr_is_irq = '0; + is_dbg_taken = '0; + s_was_flush = 1'b0; - s_id_done = 1'b0; - s_apu_wb_ok = 1'b0; - s_apu_0_cycle_reps = 1'b0; + s_is_pc_set = 1'b0; + s_is_irq_start = 1'b0; - next_send = 1; - cnt_data_req = 0; - cnt_data_resp = 0; - cnt_apu_req = 0; - cnt_apu_resp = 0; - csr_is_irq = '0; - is_dbg_taken = '0; - s_was_flush = 1'b0; + s_is_pc_set = 1'b0; + s_is_irq_start = 1'b0; + s_skip_wb = 1'b0; - s_is_pc_set = 1'b0; - s_is_irq_start = 1'b0; + s_core_is_decoding = 1'b0; - s_is_pc_set = 1'b0; - s_is_irq_start = 1'b0; - s_skip_wb = 1'b0; + s_ex_reg_we_adjusted = 1'b0; + s_rf_we_wb_adjusted = 1'b0; - s_core_is_decoding = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; forever begin wait(e_pipe_monitor_ok.triggered); // event triggered @@ -1325,23 +1543,11 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end if (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_ID && r_pipe_freeze_trace.ebrk_insn_dec) begin - if (trace_wb.m_valid) begin - send_rvfi(trace_wb); - trace_wb.m_valid = 1'b0; - ->e_send_rvfi_trace_wb_1; - end - if (trace_ex.m_valid) begin - send_rvfi(trace_ex); - trace_ex.m_valid = 1'b0; - ->e_send_rvfi_trace_ex_1; - end if (trace_id.m_valid) begin - - minstret_to_id(); `CSR_FROM_PIPE(id, misa) `CSR_FROM_PIPE(id, tdata1) `CSR_FROM_PIPE(id, tdata2) - tinfo_to_id(); + tinfo_to_trace(trace_id); `CSR_FROM_PIPE(id, mip) end end @@ -1375,7 +1581,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; if (trace_ex.m_valid & s_wb_valid_adjusted) begin // Used flopped values in case write happened before wb_valid - minstret_to_ex(); + sample_perf_counter_to_trace(trace_ex); trace_ex.m_csr.got_minstret = '1; end @@ -1387,7 +1593,9 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; s_new_valid_insn = r_pipe_freeze_trace.id_valid && r_pipe_freeze_trace.is_decoding;// && !r_pipe_freeze_trace.apu_rvalid; - s_wb_valid_adjusted = r_pipe_freeze_trace.wb_valid && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_EX));// && !r_pipe_freeze_trace.apu_rvalid;; + s_wb_valid_adjusted = r_pipe_freeze_trace.wb_valid && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_EX) || (r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_WB) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_FLUSH) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_ID) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_IF));// && !r_pipe_freeze_trace.apu_rvalid;; + s_ex_reg_we_adjusted = r_pipe_freeze_trace.ex_reg_we && r_pipe_freeze_trace.mult_ready && r_pipe_freeze_trace.alu_ready && r_pipe_freeze_trace.lsu_ready_ex && !s_apu_to_alu_port; + s_rf_we_wb_adjusted = r_pipe_freeze_trace.rf_we_wb && (~r_pipe_freeze_trace.data_misaligned_ex && r_pipe_freeze_trace.wb_ready) && (!s_apu_to_lsu_port || r_pipe_freeze_trace.wb_contention_lsu); s_fflags_we_non_apu = 1'b0; if (r_pipe_freeze_trace.csr.fflags_we) begin @@ -1418,60 +1626,55 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; s_skip_wb = 1'b1; end end - if (trace_wb.m_valid && !s_skip_wb) begin - if (r_pipe_freeze_trace.rf_we_wb) begin - if((trace_wb.m_rd_addr[0] == r_pipe_freeze_trace.rf_addr_wb) && (cnt_data_resp == trace_wb.m_mem_req_id[0]) && trace_wb.m_mem_req_id_valid[0]) begin - trace_wb.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; - trace_wb.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - trace_wb.m_mem_req_id_valid[0] = 1'b0; - end else if (trace_wb.m_2_rd_insn && (trace_wb.m_rd_addr[1] == r_pipe_freeze_trace.rf_addr_wb) && (cnt_data_resp == trace_wb.m_mem_req_id[1]) && trace_wb.m_mem_req_id_valid[1]) begin - trace_wb.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; - trace_wb.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; - trace_wb.m_mem_req_id_valid[1] = 1'b0; - end - end - if (!trace_wb.m_data_missaligned) begin - send_rvfi(trace_wb); - ->e_dev_send_wb_1; ->e_send_rvfi_trace_wb_2; - trace_wb.m_valid = 1'b0; + if (trace_wb.m_valid && !s_skip_wb && s_rf_we_wb_adjusted) begin + if (trace_wb.m_2_rd_insn) begin + trace_wb.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; + trace_wb.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; + end else if (trace_wb.m_ex_fw) begin + trace_wb.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; + trace_wb.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; + trace_wb.m_2_rd_insn = 1'b1; end else begin - if (s_wb_valid_adjusted) begin - if (r_pipe_freeze_trace.rf_we_wb) begin - if (!trace_wb.m_ex_fw) begin - trace_wb.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; - trace_wb.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - end - if (trace_wb.m_data_missaligned && !trace_wb.m_got_first_data) begin - trace_wb.m_got_first_data = 1'b1; - end else begin - send_rvfi(trace_wb); - ->e_dev_send_wb_2; ->e_send_rvfi_trace_wb_3; - trace_wb.m_valid = 1'b0; - end - end // rf_we_wb + trace_wb.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; + trace_wb.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; + end + + if (r_pipe_freeze_trace.csr.fregs_we) begin + `CSR_FROM_PIPE(wb, mstatus_fs) + trace_wb.m_csr.mstatus_fs_we = 1'b1; + trace_wb.m_csr.mstatus_fs_wmask = '1; + if(r_pipe_freeze_trace.csr.we && r_pipe_freeze_trace.csr.mstatus_fs_we) begin //In this specific case, two writes to mstatus_fs happen at the same time. We need to recreate the writes caused by fregs_we + trace_wb.m_csr.mstatus_fs_wdata = FS_DIRTY; end + ->e_fregs_dirty_1; end + + send_rvfi(trace_wb); + ->e_dev_send_wb_1; ->e_send_rvfi_trace_wb_2; + trace_wb.m_valid = 1'b0; + end if (trace_ex.m_valid) begin - - if (!trace_ex.m_csr.got_minstret) begin - minstret_to_ex(); + if(trace_ex.m_instret_smaple_trigger == 1) begin //time to sample instret + sample_perf_counter_to_trace(trace_ex); end + trace_ex.m_instret_smaple_trigger = trace_ex.m_instret_smaple_trigger + 1; + `CSR_FROM_PIPE(ex, misa) `CSR_FROM_PIPE(ex, tdata1) `CSR_FROM_PIPE(ex, tdata2) - tinfo_to_ex(); + tinfo_to_trace(trace_ex); - if (r_pipe_freeze_trace.regfile_we_lsu) begin + if (s_rf_we_wb_adjusted) begin ->e_dev_commit_rf_to_ex_4; - if ((cnt_data_resp == trace_ex.m_mem_req_id[0]) && !(trace_ex.m_got_ex_reg) && trace_ex.m_mem_req_id_valid[0]) begin + if (!(trace_ex.m_got_ex_reg) && trace_ex.m_mem_req_id_valid[0]) begin trace_ex.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; trace_ex.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; trace_ex.m_got_first_data = 1'b1; trace_ex.m_mem_req_id_valid[0] = 1'b0; - end else if ((cnt_data_resp == trace_ex.m_mem_req_id[1]) && trace_ex.m_mem_req_id_valid[1]) begin + end else if (trace_ex.m_mem_req_id_valid[1]) begin trace_ex.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; trace_ex.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; trace_ex.m_got_first_data = 1'b1; @@ -1485,66 +1688,86 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_ex.m_valid = 1'b0; ->e_send_rvfi_trace_ex_2; end else begin - if (r_pipe_freeze_trace.rf_we_wb && !s_apu_to_lsu_port) begin + + if (s_rf_we_wb_adjusted) begin ->e_dev_commit_rf_to_ex_1; - if (trace_ex.m_got_ex_reg) begin - trace_ex.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; - trace_ex.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; - trace_ex.m_2_rd_insn = 1'b1; - trace_ex.m_got_first_data = 1'b1; - end else begin - trace_ex.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; - trace_ex.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - trace_ex.m_got_first_data = 1'b1; + commit_rf_to_trace(trace_ex); + + if (r_pipe_freeze_trace.csr.fregs_we && (r_pipe_freeze_trace.rf_we_wb && r_pipe_freeze_trace.rf_addr_wb[5])) begin //Catching mstatus_fs updates caused by flw + `CSR_FROM_PIPE(ex, mstatus_fs) + trace_ex.m_csr.mstatus_fs_we = 1'b1; + trace_ex.m_csr.mstatus_fs_wmask = '1; + if(r_pipe_freeze_trace.csr.we && r_pipe_freeze_trace.csr.mstatus_fs_we) begin //In this specific case, two writes to mstatus_fs happen at the same time. We need to recreate the writes caused by fregs_we + trace_ex.m_csr.mstatus_fs_wdata = FS_DIRTY; + end else begin + trace_id.m_csr.mstatus_fs_rdata = trace_ex.m_csr.mstatus_fs_wdata; + s_dont_override_mstatus_fs_id = 1'b1; + end + ->e_fregs_dirty_3; end - end - if (!s_ex_valid_adjusted & !trace_ex.m_csr.got_minstret) begin - minstret_to_ex(); - end - if (trace_ex.m_is_load) begin // only move relevant instr in wb stage - ->e_ex_to_wb_1; - trace_wb.move_down_pipe(trace_ex); + send_rvfi(trace_ex); + trace_ex.m_valid = 1'b0; + end else begin - if (!trace_ex.m_csr.got_minstret) begin - minstret_to_ex(); + if (trace_ex.m_is_load) begin // only move relevant instr in wb stage + ->e_ex_to_wb_1; + trace_wb.move_down_pipe(trace_ex); + end else begin + send_rvfi(trace_ex); + ->e_send_rvfi_trace_ex_6; end - send_rvfi(trace_ex); - ->e_send_rvfi_trace_ex_6; + trace_ex.m_valid = 1'b0; end - trace_ex.m_valid = 1'b0; end - end else if (r_pipe_freeze_trace.rf_we_wb && !s_apu_to_lsu_port && !s_was_flush) begin + end else if (s_rf_we_wb_adjusted && !s_was_flush) begin ->e_dev_commit_rf_to_ex_2; - if (trace_ex.m_got_ex_reg) begin - trace_ex.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; - trace_ex.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; - trace_ex.m_2_rd_insn = 1'b1; - trace_ex.m_got_first_data = 1'b1; - end else begin - trace_ex.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; - trace_ex.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - trace_ex.m_got_first_data = 1'b1; - end + commit_rf_to_trace(trace_ex); end end - s_ex_valid_adjusted = (r_pipe_freeze_trace.ex_valid && r_pipe_freeze_trace.ex_ready) && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_IF)) && (!r_pipe_freeze_trace.apu_rvalid || r_pipe_freeze_trace.data_req_ex); + // If mret, we need to keep the instruction in Id during flush_ex because mstatus update happens at that time + s_ex_valid_adjusted = (r_pipe_freeze_trace.ex_valid && r_pipe_freeze_trace.ex_ready) && (s_core_is_decoding || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_IF) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_TAKEN_ID) || (r_pipe_freeze_trace.ctrl_fsm_cs == DBG_FLUSH) || ((r_pipe_freeze_trace.ctrl_fsm_cs == FLUSH_EX) && !r_pipe_freeze_trace.mret_insn_dec)); //EX_STAGE - if (trace_id.m_valid) begin - mtvec_to_id(); - `CSR_FROM_PIPE(id, mip) - `CSR_FROM_PIPE(id, misa) + if (trace_id.m_valid) begin + if(trace_id.m_instret_smaple_trigger == 1) begin //time to sample instret + sample_perf_counter_to_trace(trace_id); + for(int idx=3; idx<32; idx++) begin + sample_perf_counter_to_id(idx); + sample_perf_counter_h_to_id(idx); + sample_perf_event_to_trace(idx, trace_id); + end + end + trace_id.m_instret_smaple_trigger = trace_id.m_instret_smaple_trigger + 1; - if (!csr_is_irq && !s_is_irq_start) begin - mstatus_to_id(); + if(trace_id.m_sample_csr_write_in_ex && !csr_is_irq && !s_is_irq_start) begin //First cycle after id_ready, csr write is asserted in this cycle + `CSR_FROM_PIPE(id, mstatus) + if(!s_dont_override_mstatus_fs_id) begin + `CSR_FROM_PIPE(id, mstatus_fs) + end `CSR_FROM_PIPE(id, mepc) - if (trace_id.m_csr.mcause_we == '0) begin //for debug purpose - `CSR_FROM_PIPE(id, mcause) + `CSR_FROM_PIPE(id, mcause) + `CSR_FROM_PIPE(id, dscratch0) + `CSR_FROM_PIPE(id, dscratch1) + if(r_pipe_freeze_trace.csr.we && (r_pipe_freeze_trace.csr.addr == CSR_DPC)) begin + `CSR_FROM_PIPE(id, dpc) end + + `CSR_FROM_PIPE(id, mcountinhibit) + + perf_counter_to_trace(trace_id); + ->e_csr_in_ex; end + if(r_pipe_freeze_trace.is_decoding) begin + trace_id.m_sample_csr_write_in_ex = 1'b0; + end + mtvec_to_id(); + + `CSR_FROM_PIPE(id, mip) + `CSR_FROM_PIPE(id, misa) + `CSR_FROM_PIPE(id, mcountinhibit) `CSR_FROM_PIPE(id, mscratch) `CSR_FROM_PIPE(id, mie) @@ -1553,10 +1776,6 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; `CSR_FROM_PIPE(id, frm) `CSR_FROM_PIPE(id, fcsr) - if (r_pipe_freeze_trace.csr.we) begin - `CSR_FROM_PIPE(id, dpc) - end - if (r_pipe_freeze_trace.csr.dcsr_we) begin dcsr_to_id(); end @@ -1577,6 +1796,15 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_ex.m_csr.frm_wmask = '0; trace_ex.m_csr.fcsr_wmask = '0; + if(r_pipe_freeze_trace.ctrl_fsm_cs == XRET_JUMP) begin //xret exit pipeline + tinfo_to_trace(trace_id); + `CSR_FROM_PIPE(id, tdata1) + `CSR_FROM_PIPE(id, tdata2) + send_rvfi(trace_id); + trace_id.m_valid = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; + end + if (r_pipe_freeze_trace.apu_req && r_pipe_freeze_trace.apu_gnt) begin trace_id.m_is_apu = 1'b1; trace_id.m_apu_req_id = cnt_apu_req; @@ -1586,6 +1814,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_apu_req.set_to_apu(); apu_trace_q.push_back(trace_apu_req); trace_id.m_valid = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; if(r_pipe_freeze_trace.apu_rvalid && (cnt_apu_req == cnt_apu_resp)) begin//APU return in the same cycle apu_resp(); @@ -1603,10 +1832,10 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_rd_addr[0] = r_pipe_freeze_trace.ex_reg_addr; trace_id.m_rd_wdata[0] = r_pipe_freeze_trace.ex_reg_wdata; trace_id.m_got_ex_reg = 1'b1; - end else if (!trace_ex.m_valid & r_pipe_freeze_trace.rf_we_wb & !trace_id.m_ex_fw) begin + end else if (!trace_ex.m_valid & s_rf_we_wb_adjusted & !trace_id.m_ex_fw) begin trace_id.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; trace_id.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; - end else if (r_pipe_freeze_trace.rf_we_wb) begin + end else if (s_rf_we_wb_adjusted) begin trace_id.m_rd_addr[1] = r_pipe_freeze_trace.rf_addr_wb; trace_id.m_rd_wdata[1] = r_pipe_freeze_trace.rf_wdata_wb; trace_id.m_2_rd_insn = 1'b1; @@ -1621,19 +1850,16 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_mem.addr = r_pipe_freeze_trace.data_addr_pmp; if (r_pipe_freeze_trace.data_misaligned) begin cnt_data_req = cnt_data_req + 1; + trace_id.m_mem_req_id[0] = cnt_data_req; end + if (!r_pipe_freeze_trace.data_we_ex) begin trace_id.m_is_load = 1'b1; trace_id.m_mem.wmask = be_to_mask(r_pipe_freeze_trace.lsu_data_be); //'1; - if (r_pipe_freeze_trace.data_misaligned) begin - trace_id.m_data_missaligned = 1'b1; - trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; - trace_id.m_mem_req_id[0] = cnt_data_req; - trace_id.m_mem_req_id_valid[1] = 1'b1; - end end else begin trace_id.m_mem.rmask = be_to_mask(r_pipe_freeze_trace.lsu_data_be); //'1; end + if (trace_id.m_got_ex_reg) begin // Shift index 0 to 1 trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; trace_id.m_mem_req_id[0] = 0; @@ -1644,6 +1870,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; hwloop_to_id(); trace_ex.move_down_pipe(trace_id); // The instruction moves forward from ID to EX trace_id.m_valid = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; ->e_id_to_ex_1; end else if (r_pipe_freeze_trace.ex_reg_we && r_pipe_freeze_trace.rf_alu_we_ex) begin @@ -1667,9 +1894,6 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; if (s_new_valid_insn) begin // There is a new valid instruction if (trace_id.m_valid) begin if (trace_ex.m_valid) begin - if (!trace_ex.m_csr.got_minstret) begin - minstret_to_ex(); - end if (trace_wb.m_valid) begin send_rvfi(trace_ex); ->e_send_rvfi_trace_ex_4; @@ -1692,15 +1916,10 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_mem.addr = r_pipe_freeze_trace.data_addr_pmp; if (r_pipe_freeze_trace.data_misaligned) begin cnt_data_req = cnt_data_req + 1; + trace_id.m_mem_req_id[0] = cnt_data_req; end if (!r_pipe_freeze_trace.data_we_ex) begin trace_id.m_is_load = 1'b1; - if (r_pipe_freeze_trace.data_misaligned) begin - trace_id.m_data_missaligned = 1'b1; - trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; - trace_id.m_mem_req_id[0] = cnt_data_req; - trace_id.m_mem_req_id_valid[1] = 1'b1; - end end if (trace_id.m_got_ex_reg) begin // Shift index 0 to 1 trace_id.m_mem_req_id[1] = trace_id.m_mem_req_id[0]; @@ -1708,7 +1927,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; trace_id.m_mem_req_id_valid[0] = 1'b0; trace_id.m_mem_req_id_valid[1] = 1'b1; end - end else if (r_pipe_freeze_trace.rf_we_wb && !r_pipe_freeze_trace.ex_reg_we) begin + end else if (s_rf_we_wb_adjusted && !r_pipe_freeze_trace.ex_reg_we) begin trace_id.m_rd_addr[0] = r_pipe_freeze_trace.rf_addr_wb; trace_id.m_rd_wdata[0] = r_pipe_freeze_trace.rf_wdata_wb; end @@ -1716,6 +1935,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; hwloop_to_id(); trace_ex.move_down_pipe(trace_id); trace_id.m_valid = 1'b0; + s_dont_override_mstatus_fs_id = 1'b0; ->e_id_to_ex_2; end if_to_id(); @@ -1733,13 +1953,28 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; end //IF_STAGE - if (r_pipe_freeze_trace.if_valid && r_pipe_freeze_trace.if_ready) begin - if(trace_if.m_valid && r_pipe_freeze_trace.id_valid && r_pipe_freeze_trace.id_ready && !trace_id.m_valid && r_pipe_freeze_trace.ebrk_insn_dec) begin - if_to_id(); - trace_id.m_is_ebreak = '1; //trace_if.m_is_ebreak; - ->e_if_2_id_2; + if(trace_if.m_valid) begin + if(r_pipe_freeze_trace.is_illegal && r_pipe_freeze_trace.is_decoding) begin + trace_if.m_is_illegal = 1'b1; + end + end + + if (r_pipe_freeze_trace.if_valid && r_pipe_freeze_trace.if_ready && r_pipe_freeze_trace.instr_valid_if) begin + if (trace_if.m_valid) begin + if (r_pipe_freeze_trace.id_valid && r_pipe_freeze_trace.id_ready && !trace_id.m_valid && r_pipe_freeze_trace.ebrk_insn_dec) begin + if_to_id(); + trace_id.m_is_ebreak = '1; //trace_if.m_is_ebreak; + ->e_if_2_id_2; + end else if (trace_if.m_is_illegal) begin + if_to_id(); + ->e_if_2_id_3; + end else if (r_pipe_freeze_trace.ecall_insn_dec) begin + if_to_id(); + ->e_if_2_id_4; + end end + trace_if.m_insn = r_pipe_freeze_trace.instr_if; //Instr comes from if, buffer for one cycle trace_if.m_pc_rdata = r_pipe_freeze_trace.pc_if; trace_if.m_dbg_taken = is_dbg_taken; @@ -1754,6 +1989,7 @@ insn_trace_t trace_if, trace_id, trace_ex, trace_ex_next, trace_wb; mstatus_to_id(); `CSR_FROM_PIPE(id, mepc) `CSR_FROM_PIPE(id, mcause) + ->e_csr_irq; end if (!s_id_done && r_pipe_freeze_trace.is_decoding) begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_rvfi_trace.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_rvfi_trace.sv index 417f562a..adf85175 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_rvfi_trace.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_rvfi_trace.sv @@ -1,26 +1,31 @@ -// Copyright (c) 2020 OpenHW Group +// Copyright 2024 Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. // You may obtain a copy of the License at // -// https://solderpad.org/licenses/ +// https://solderpad.org/licenses/SHL-2.1/ // -// Unless required by applicable law or agreed to in writing, software +// Unless required by applicable law or agreed to in writing, any work // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 -// CV32E40P RVFI interface -// -// Contributors: Halfdan Bechmann, Silicon Labs -// Yoann Pruvost, Dolphin Design +//////////////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Halfdan Bechmann, Silicon Labs // +// Yoann Pruvost, Dolphin Design // +// // +// Description: CV32E40P RVFI tracer // +// // +//////////////////////////////////////////////////////////////////////////////////// module cv32e40p_rvfi_trace import cv32e40p_pkg::*; + import cv32e40p_rvfi_pkg::*; #( parameter FPU = 0, parameter ZFINX = 0 @@ -32,9 +37,14 @@ module cv32e40p_rvfi_trace input logic [31:0] imm_s3_type, - input logic rvfi_valid, - input logic [31:0] rvfi_insn, - input logic [31:0] rvfi_pc_rdata, + input logic rvfi_valid, + input logic [31:0] rvfi_insn, + input integer rvfi_start_cycle, + input time rvfi_start_time, + input integer rvfi_stop_cycle, + input time rvfi_stop_time, + input logic [31:0] rvfi_pc_rdata, + input rvfi_trap_t rvfi_trap, input logic [ 4:0] rvfi_rd_addr [1:0], input logic [31:0] rvfi_rd_wdata[1:0], @@ -42,6 +52,7 @@ module cv32e40p_rvfi_trace input logic rvfi_frd_wvalid[1:0], input logic [ 4:0] rvfi_frd_addr [1:0], input logic [31:0] rvfi_frd_wdata [1:0], + input logic rvfi_2_rd, input logic [ 4:0] rvfi_rs1_addr, input logic [ 4:0] rvfi_rs2_addr, @@ -61,8 +72,8 @@ module cv32e40p_rvfi_trace input logic [31:0] rvfi_frs3_rdata, input logic [31:0] rvfi_mem_addr, - input logic [ 3:0] rvfi_mem_rmask, - input logic [ 3:0] rvfi_mem_wmask, + input logic [31:0] rvfi_mem_rmask, + input logic [31:0] rvfi_mem_wmask, input logic [31:0] rvfi_mem_rdata, input logic [31:0] rvfi_mem_wdata ); @@ -74,7 +85,7 @@ module cv32e40p_rvfi_trace integer f; //file pointer string fn; - integer cycles; + // integer cycles; string info_tag; logic is_compressed; @@ -125,7 +136,13 @@ module cv32e40p_rvfi_trace rs3_value = rvfi_rs3_rdata; end - if (rvfi_frd_wvalid[0]) begin + if (rvfi_2_rd) begin + if (rvfi_frd_wvalid[1]) begin + rd = {1'b1, rvfi_frd_addr[1]}; + end else begin + rd = {1'b0, rvfi_rd_addr[1]}; + end + end else if (rvfi_frd_wvalid[0]) begin rd = {1'b1, rvfi_frd_addr[0]}; end else begin rd = {1'b0, rvfi_rd_addr[0]}; @@ -134,57 +151,69 @@ module cv32e40p_rvfi_trace assign rs4 = rs3; - assign imm_i_type = {{20{rvfi_insn[31]}}, rvfi_insn[31:20]}; - assign imm_iz_type = {20'b0, rvfi_insn[31:20]}; - assign imm_s_type = {{20{rvfi_insn[31]}}, rvfi_insn[31:25], rvfi_insn[11:7]}; + cv32e40p_compressed_decoder #( + .FPU(FPU) + ) rvfi_trace_decompress_i ( + .instr_i(rvfi_insn), + .instr_o(decomp_insn), + .is_compressed_o(is_compressed) + ); + + assign imm_i_type = {{20{decomp_insn[31]}}, decomp_insn[31:20]}; + assign imm_iz_type = {20'b0, decomp_insn[31:20]}; + assign imm_s_type = {{20{decomp_insn[31]}}, decomp_insn[31:25], decomp_insn[11:7]}; assign imm_sb_type = { - {19{rvfi_insn[31]}}, rvfi_insn[31], rvfi_insn[7], rvfi_insn[30:25], rvfi_insn[11:8], 1'b0 + {19{decomp_insn[31]}}, + decomp_insn[31], + decomp_insn[7], + decomp_insn[30:25], + decomp_insn[11:8], + 1'b0 }; - assign imm_u_type = {rvfi_insn[31:12], 12'b0}; + assign imm_u_type = {decomp_insn[31:12], 12'b0}; assign imm_uj_type = { - {12{rvfi_insn[31]}}, rvfi_insn[19:12], rvfi_insn[20], rvfi_insn[30:21], 1'b0 + {12{decomp_insn[31]}}, decomp_insn[19:12], decomp_insn[20], decomp_insn[30:21], 1'b0 }; - assign imm_z_type = '0; //{27'b0, rvfi_insn[REG_S1_MSB:REG_S1_LSB]}; + assign imm_z_type = '0; //{27'b0, decomp_insn[REG_S1_MSB:REG_S1_LSB]}; - assign imm_s2_type = {27'b0, rvfi_insn[24:20]}; + assign imm_s2_type = {27'b0, decomp_insn[24:20]}; assign imm_vs_type = '0; assign imm_vu_type = '0; assign imm_shuffle_type = '0; assign imm_clip_type = '0; - cv32e40p_compressed_decoder #( - .FPU(FPU) - ) rvfi_trace_decompress_i ( - .instr_i(rvfi_insn), - .instr_o(decomp_insn), - .is_compressed_o(is_compressed) - ); - `include "cv32e40p_instr_trace.svh" instr_trace_t trace_retire; function instr_trace_t trace_new_instr(); instr_trace_t trace; trace = new(); - trace.init(.cycles(cycles), .pc(rvfi_pc_rdata), .compressed(is_compressed), + trace.external_time = 1; + trace.simtime = rvfi_start_time - 1ns; + trace.stoptime = rvfi_stop_time; + trace.stopcycles = rvfi_stop_cycle; + trace.ctx = (rvfi_trap.trap) ? "(C)" : ""; + trace.init(.cycles(rvfi_start_cycle), .pc(rvfi_pc_rdata), .compressed(is_compressed), .instr(decomp_insn)); return trace; endfunction : trace_new_instr function void apply_reg_write(); foreach (trace_retire.regs_write[i]) begin - if (rvfi_frd_wvalid[0] && (trace_retire.regs_write[i].addr == {1'b1, rvfi_frd_addr[0]})) begin - trace_retire.regs_write[i].value = rvfi_frd_wdata[0]; - end else if (trace_retire.regs_write[i].addr == rvfi_rd_addr[0]) begin - trace_retire.regs_write[i].value = rvfi_rd_wdata[0]; - end if (rvfi_frd_wvalid[1] && (trace_retire.regs_write[i].addr == {1'b1, rvfi_frd_addr[1]})) begin trace_retire.regs_write[i].value = rvfi_frd_wdata[1]; end else if (trace_retire.regs_write[i].addr == rvfi_rd_addr[1]) begin trace_retire.regs_write[i].value = rvfi_rd_wdata[1]; end end + foreach (trace_retire.regs_write[i]) begin + if (rvfi_frd_wvalid[0] && (trace_retire.regs_write[i].addr == {1'b1, rvfi_frd_addr[0]})) begin + trace_retire.regs_write[i].value = rvfi_frd_wdata[0]; + end else if (trace_retire.regs_write[i].addr == rvfi_rd_addr[0]) begin + trace_retire.regs_write[i].value = rvfi_rd_wdata[0]; + end + end endfunction : apply_reg_write function void apply_mem_access(); @@ -202,11 +231,9 @@ instr_trace_t trace_retire; end endfunction : apply_mem_access - // cycle counter - always_ff @(posedge clk_i, negedge rst_ni) begin - if (rst_ni == 1'b0) cycles <= 0; - else cycles <= cycles + 1; - end + string insn_disas; + logic [31:0] insn_pc; + logic [31:0] insn_val; always @(posedge clk_i) begin if (rvfi_valid) begin @@ -214,6 +241,9 @@ instr_trace_t trace_retire; apply_reg_write(); apply_mem_access(); trace_retire.printInstrTrace(); + insn_disas = trace_retire.str; + insn_pc = trace_retire.pc; + insn_val = trace_retire.instr; end end @@ -223,7 +253,8 @@ instr_trace_t trace_retire; $sformat(info_tag, "CORE_TRACER %2d", hart_id_i); $display("[%s] Output filename is: %s", info_tag, fn); f = $fopen(fn, "w"); - $fwrite(f, "Time\tCycle\tPC\tInstr\tDecoded instruction\tRegister and memory contents\n"); + $fwrite(f, + " Time Cycle PC Instr Ctx Decoded instruction Register and memory contents Stop cycle Stop time\n"); end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_tb_wrapper.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_tb_wrapper.sv index 725ed4f0..25245407 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_tb_wrapper.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_tb_wrapper.sv @@ -1,23 +1,27 @@ -// Copyright (c) 2020 OpenHW Group +// Copyright 2024 Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. // You may obtain a copy of the License at // -// https://solderpad.org/licenses/ +// https://solderpad.org/licenses/SHL-2.1/ // -// Unless required by applicable law or agreed to in writing, software +// Unless required by applicable law or agreed to in writing, any work // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 -// Wrapper for a cv32e40p, containing cv32e40p_top, and rvfi_tracer -// -// Contributors: Davide Schiavone, OpenHW Group -// Yoann Pruvost, Dolphin Design +//////////////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Davide Schiavone, OpenHW Group // +// Yoann Pruvost, Dolphin Design // +// // +// Description: Test-bench wrapper for cv32e40p_top, tracer and and rvfi_tracer // +// // +//////////////////////////////////////////////////////////////////////////////////// `ifdef CV32E40P_ASSERT_ON `include "cv32e40p_prefetch_controller_sva.sv" @@ -234,8 +238,9 @@ module cv32e40p_tb_wrapper endgenerate cv32e40p_rvfi #( - .FPU (FPU), - .ZFINX(ZFINX) + .FPU(FPU), + .ZFINX(ZFINX), + .NUM_MHPMCOUNTERS(NUM_MHPMCOUNTERS) ) rvfi_i ( .clk_i (cv32e40p_top_i.core_i.clk_i), .rst_ni(cv32e40p_top_i.core_i.rst_ni), @@ -279,8 +284,12 @@ module cv32e40p_tb_wrapper // .instr (cv32e40p_top_i.core_i.id_stage_i.instr ), .is_compressed_id_i(cv32e40p_top_i.core_i.id_stage_i.is_compressed_i), .ebrk_insn_dec_i (cv32e40p_top_i.core_i.id_stage_i.ebrk_insn_dec), - .csr_cause_i (cv32e40p_top_i.core_i.csr_cause), - .debug_csr_save_i (cv32e40p_top_i.core_i.debug_csr_save), + .ecall_insn_dec_i (cv32e40p_top_i.core_i.id_stage_i.ecall_insn_dec), + .mret_insn_dec_i (cv32e40p_top_i.core_i.id_stage_i.mret_insn_dec), + .mret_dec_i (cv32e40p_top_i.core_i.id_stage_i.mret_dec), + + .csr_cause_i (cv32e40p_top_i.core_i.csr_cause), + .debug_csr_save_i(cv32e40p_top_i.core_i.debug_csr_save), // HWLOOP regs .hwlp_start_q_i (hwlp_start_q), @@ -305,9 +314,11 @@ module cv32e40p_tb_wrapper // .rf_addr_alu_i (cv32e40p_top_i.core_i.id_stage_i.regfile_alu_waddr_fw_i), // .rf_wdata_alu_i (cv32e40p_top_i.core_i.id_stage_i.regfile_alu_wdata_fw_i), + .mult_ready_i (cv32e40p_top_i.core_i.ex_stage_i.mult_ready), + .alu_ready_i (cv32e40p_top_i.core_i.ex_stage_i.alu_ready), //// WB probes //// - .wb_valid_i(cv32e40p_top_i.core_i.wb_valid), - + .wb_valid_i (cv32e40p_top_i.core_i.wb_valid), + .wb_ready_i (cv32e40p_top_i.core_i.lsu_ready_wb), //// LSU probes //// .data_we_ex_i (cv32e40p_top_i.core_i.data_we_ex), .data_atop_ex_i (cv32e40p_top_i.core_i.data_atop_ex), @@ -360,6 +371,8 @@ module cv32e40p_tb_wrapper .csr_we_i (cv32e40p_top_i.core_i.cs_registers_i.csr_we_int), .csr_wdata_int_i(cv32e40p_top_i.core_i.cs_registers_i.csr_wdata_int), + .csr_fregs_we_i(cv32e40p_top_i.core_i.cs_registers_i.fregs_we_i), + .csr_mstatus_n_i (cv32e40p_top_i.core_i.cs_registers_i.mstatus_n), .csr_mstatus_q_i (cv32e40p_top_i.core_i.cs_registers_i.mstatus_q), .csr_mstatus_fs_n_i(cv32e40p_top_i.core_i.cs_registers_i.mstatus_fs_n), @@ -391,6 +404,9 @@ module cv32e40p_tb_wrapper .csr_mcountinhibit_n_i (cv32e40p_top_i.core_i.cs_registers_i.mcountinhibit_n), .csr_mcountinhibit_we_i(cv32e40p_top_i.core_i.cs_registers_i.mcountinhibit_we), + .csr_mhpmevent_n_i(cv32e40p_top_i.core_i.cs_registers_i.mhpmevent_n), + .csr_mhpmevent_q_i(cv32e40p_top_i.core_i.cs_registers_i.mhpmevent_q), + .csr_mhpmevent_we_i(cv32e40p_top_i.core_i.cs_registers_i.mhpmevent_we), .csr_mscratch_q_i(cv32e40p_top_i.core_i.cs_registers_i.mscratch_q), .csr_mscratch_n_i(cv32e40p_top_i.core_i.cs_registers_i.mscratch_n), .csr_mepc_q_i(cv32e40p_top_i.core_i.cs_registers_i.mepc_q), @@ -446,12 +462,18 @@ module cv32e40p_tb_wrapper .rvfi_valid(rvfi_valid), .rvfi_insn(rvfi_insn), + .rvfi_start_cycle(rvfi_start_cycle), + .rvfi_start_time(rvfi_start_time), + .rvfi_stop_cycle(rvfi_stop_cycle), + .rvfi_stop_time(rvfi_stop_time), .rvfi_pc_rdata(rvfi_pc_rdata), + .rvfi_trap(rvfi_trap), .rvfi_rd_addr(rvfi_rd_addr), .rvfi_rd_wdata(rvfi_rd_wdata), .rvfi_frd_wvalid(rvfi_frd_wvalid), .rvfi_frd_addr(rvfi_frd_addr), .rvfi_frd_wdata(rvfi_frd_wdata), + .rvfi_2_rd(rvfi_2_rd), .rvfi_rs1_addr(rvfi_rs1_addr), .rvfi_rs2_addr(rvfi_rs2_addr), .rvfi_rs3_addr(rvfi_rs3_addr), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_tracer.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_tracer.sv index 8208f2e6..59ed6fd7 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_tracer.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/cv32e40p_tracer.sv @@ -1,24 +1,26 @@ -// Copyright (c) 2020 OpenHW Group -// -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://solderpad.org/licenses/ -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 - -// Traces the executed instructions -// -// Contributors: Andreas Traber, ETHZ -// Davide Schiavone, OpenHW Group -// Pascal Gouedo, Dolphin Design +// Copyright 2018 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Andreas Traber - atraber@iis.ee.ethz.ch // +// // +// Additional contributions by: // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// // +// Design Name: RISC-V Tracer // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Traces the executed instructions // +// // +//////////////////////////////////////////////////////////////////////////////// `ifdef CV32E40P_TRACE_EXECUTION @@ -183,7 +185,8 @@ module cv32e40p_tracer $sformat(info_tag, "CORE_TRACER %2d", hart_id_i); $display("[%s] Output filename is: %s", info_tag, fn); f = $fopen(fn, "w"); - $fwrite(f, "Time\tCycle\tPC\tInstr\tDecoded instruction\tRegister and memory contents\n"); + $fwrite(f, + " Time Cycle PC Instr Ctx Decoded instruction Register and memory contents\n"); end //initial begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/include/cv32e40p_rvfi_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/include/cv32e40p_rvfi_pkg.sv index 68879569..f4044e6e 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/include/cv32e40p_rvfi_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/include/cv32e40p_rvfi_pkg.sv @@ -1,24 +1,28 @@ -// Copyright (c) 2020 OpenHW Group +// Copyright 2024 Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. // You may obtain a copy of the License at // -// https://solderpad.org/licenses/ +// https://solderpad.org/licenses/SHL-2.1/ // -// Unless required by applicable law or agreed to in writing, software +// Unless required by applicable law or agreed to in writing, any work // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 -// Includes to print info about the RVFI output -// -// Contributors: Davide Schiavone, OpenHW Group -// Halfdan Bechmann, Silicon Labs -// Yoann Pruvost, Dolphin Design +//////////////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Davide Schiavone, OpenHW Group // +// Halfdan Bechmann, Silicon Labs // +// Yoann Pruvost, Dolphin Design // +// // +// Description: Package to print info on RVFI interface // +// // +//////////////////////////////////////////////////////////////////////////////////// package cv32e40p_rvfi_pkg; import cv32e40p_pkg::*; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/include/cv32e40p_tracer_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/include/cv32e40p_tracer_pkg.sv index c099ff4f..b9ce57df 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/include/cv32e40p_tracer_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/include/cv32e40p_tracer_pkg.sv @@ -1,23 +1,13 @@ -// Copyright (c) 2020 OpenHW Group -// -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://solderpad.org/licenses/ -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 - -// Tracer package -// -// Contributors: Steve Richmond, Silicon Labs -// Pascal Gouedo, Dolphin Design +// Copyright 2018 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + package cv32e40p_tracer_pkg; import cv32e40p_pkg::*; @@ -196,8 +186,8 @@ package cv32e40p_tracer_pkg; parameter INSTR_CVEND0 = {12'b000000000000, 5'b?, 3'b100, 4'b0011, 1'b0, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNTI0 = {12'b?, 5'b00000, 3'b100, 4'b0100, 1'b0, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNT0 = {12'b000000000000, 5'b?, 3'b100, 4'b0101, 1'b0, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUPI0 = {12'b?, 5'b00000, 3'b100, 4'b0110, 1'b0, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUP0 = {12'b?, 5'b00000, 3'b100, 4'b0111, 1'b0, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUPI0 = {17'b?, 3'b100, 4'b0110, 1'b0, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUP0 = {12'b?, 5'b?, 3'b100, 4'b0111, 1'b0, OPCODE_CUSTOM_1}; parameter INSTR_CVSTARTI1 = {12'b?, 5'b00000, 3'b100, 4'b0000, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_CVSTART1 = {12'b000000000000, 5'b?, 3'b100, 4'b0001, 1'b1, OPCODE_CUSTOM_1}; @@ -205,8 +195,8 @@ package cv32e40p_tracer_pkg; parameter INSTR_CVEND1 = {12'b000000000000, 5'b?, 3'b100, 4'b0011, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNTI1 = {12'b?, 5'b00000, 3'b100, 4'b0100, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_CVCOUNT1 = {12'b000000000000, 5'b?, 3'b100, 4'b0101, 1'b1, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUPI1 = {12'b?, 5'b00000, 3'b100, 4'b0110, 1'b1, OPCODE_CUSTOM_1}; - parameter INSTR_CVSETUP1 = {12'b?, 5'b00000, 3'b100, 4'b0111, 1'b1, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUPI1 = {17'b?, 3'b100, 4'b0110, 1'b1, OPCODE_CUSTOM_1}; + parameter INSTR_CVSETUP1 = {12'b?, 5'b?, 3'b100, 4'b0111, 1'b1, OPCODE_CUSTOM_1}; parameter INSTR_FF1 = {7'b0100001, 5'b0, 5'b?, 3'b011, 5'b?, OPCODE_CUSTOM_1}; @@ -449,8 +439,8 @@ package cv32e40p_tracer_pkg; parameter INSTR_CVSHUFFLE2H = {5'b11100, 1'b0, 1'b0, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; parameter INSTR_CVSHUFFLE2B = {5'b11100, 1'b0, 1'b0, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_CUSTOM_3}; - parameter INSTR_CVPACK = {5'b11101, 1'b0, 1'b0, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; - parameter INSTR_CVPACKH = {5'b11101, 1'b0, 1'b1, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; + parameter INSTR_CVPACK = {5'b11110, 1'b0, 1'b0, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; + parameter INSTR_CVPACKH = {5'b11110, 1'b0, 1'b1, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_CUSTOM_3}; parameter INSTR_CVPACKHIB = {5'b11111, 1'b0, 1'b1, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_CUSTOM_3}; parameter INSTR_CVPACKLOB = {5'b11111, 1'b0, 1'b0, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_CUSTOM_3}; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/insn_trace.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/insn_trace.sv index 3db2a7ee..8cdc06d9 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/insn_trace.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/insn_trace.sv @@ -1,5 +1,26 @@ -// Copyright 2022 Dolphin Design -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// Copyright 2024 OpenHW Group and Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//////////////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Yoann Pruvost, Dolphin Design // +// // +// Description: Macros and Functions to print information on RVFI interface // +// // +//////////////////////////////////////////////////////////////////////////////////// `define DEFINE_CSR(CSR_NAME) \ logic ``CSR_NAME``_we; \ @@ -23,6 +44,10 @@ class insn_trace_t; bit m_valid; logic [63:0] m_order; + integer m_start_cycle; + integer m_stop_cycle; + time m_start_time; + time m_stop_time; bit m_skip_order; //next order was used by trap; logic [31:0] m_pc_rdata; logic [31:0] m_insn; @@ -65,12 +90,15 @@ bit m_move_down_pipe; int m_instret_cnt; + int m_instret_smaple_trigger; //We need to sample minstret from csr 2 cycle after id is doen + + bit m_sample_csr_write_in_ex; struct { logic [31:0] addr ; - logic [ 3:0] rmask; + logic [31:0] rmask; logic [31:0] rdata; - logic [ 3:0] wmask; + logic [31:0] wmask; logic [31:0] wdata; } m_mem; @@ -100,9 +128,28 @@ `DEFINE_CSR(mscratch) `DEFINE_CSR(mepc) `DEFINE_CSR(mcause) + `DEFINE_CSR(mcycle) `DEFINE_CSR(minstret) bit got_minstret; - + `DEFINE_CSR(mcycleh) + `DEFINE_CSR(minstreth) + `DEFINE_CSR(cycle) + `DEFINE_CSR(instret) + // bit got_minstret; + `DEFINE_CSR(cycleh) + `DEFINE_CSR(instreth) + + logic [31:0][ 1:0] mhpmcounter_we; + logic [31:0][63:0] mhpmcounter_rdata; + logic [31:0][63:0] mhpmcounter_rmask; + logic [31:0][63:0] mhpmcounter_wdata; + logic [31:0][63:0] mhpmcounter_wmask; + + logic [31:0] mhpmevent_we; + logic [31:0][31:0] mhpmevent_rdata; + logic [31:0][31:0] mhpmevent_rmask; + logic [31:0][31:0] mhpmevent_wdata; + logic [31:0][31:0] mhpmevent_wmask; `DEFINE_CSR(mip) //mnxti //mintstatus @@ -145,32 +192,38 @@ function new(); - this.m_order = 0; - this.m_skip_order = 1'b0; - this.m_valid = 1'b0; - this.m_move_down_pipe = 1'b0; - this.m_data_missaligned = 1'b0; - this.m_got_first_data = 1'b0; - this.m_got_ex_reg = 1'b0; - this.m_intr = '0; - this.m_dbg_taken = 1'b0; - this.m_dbg_cause = '0; - this.m_is_ebreak = '0; - this.m_is_illegal = '0; - this.m_is_irq = '0; - this.m_is_memory = 1'b0; - this.m_is_load = 1'b0; - this.m_is_apu = 1'b0; - this.m_is_apu_ok = 1'b0; - this.m_apu_req_id = 0; - this.m_mem_req_id[0] = 0; - this.m_mem_req_id[1] = 0; - this.m_mem_req_id_valid = '0; - this.m_trap = 1'b0; - this.m_fflags_we_non_apu = 1'b0; - this.m_frm_we_non_apu = 1'b0; - this.m_fcsr_we_non_apu = 1'b0; - this.m_instret_cnt = 0; + this.m_order = 0; + this.m_start_cycle = 0; + this.m_stop_cycle = 0; + this.m_start_time = 0; + this.m_stop_time = 0; + this.m_skip_order = 1'b0; + this.m_valid = 1'b0; + this.m_move_down_pipe = 1'b0; + this.m_data_missaligned = 1'b0; + this.m_got_first_data = 1'b0; + this.m_got_ex_reg = 1'b0; + this.m_intr = '0; + this.m_dbg_taken = 1'b0; + this.m_dbg_cause = '0; + this.m_is_ebreak = '0; + this.m_is_illegal = '0; + this.m_is_irq = '0; + this.m_is_memory = 1'b0; + this.m_is_load = 1'b0; + this.m_is_apu = 1'b0; + this.m_is_apu_ok = 1'b0; + this.m_apu_req_id = 0; + this.m_mem_req_id[0] = 0; + this.m_mem_req_id[1] = 0; + this.m_mem_req_id_valid = '0; + this.m_trap = 1'b0; + this.m_fflags_we_non_apu = 1'b0; + this.m_frm_we_non_apu = 1'b0; + this.m_fcsr_we_non_apu = 1'b0; + this.m_instret_cnt = 0; + this.m_instret_smaple_trigger = 0; + this.m_sample_csr_write_in_ex = 1'b1; endfunction function void get_mnemonic(); @@ -610,12 +663,12 @@ INSTR_CVCMPLEB : this.m_mnemonic = "cv.cmple.b"; INSTR_CVCMPLESCB : this.m_mnemonic = "cv.cmple.sc.b"; INSTR_CVCMPLESCIB : this.m_mnemonic = "cv.cmple.sci.b"; - INSTR_CVCMPGTUH : this.m_mnemonic = "cv.cmptu.h"; - INSTR_CVCMPGTUSCH : this.m_mnemonic = "cv.cmptu.sc.h"; - INSTR_CVCMPGTUSCIH : this.m_mnemonic = "cv.cmptu.sci.h"; - INSTR_CVCMPGTUB : this.m_mnemonic = "cv.cmptu.b"; - INSTR_CVCMPGTUSCB : this.m_mnemonic = "cv.cmptu.sc.b"; - INSTR_CVCMPGTUSCIB : this.m_mnemonic = "cv.cmptu.sci.b"; + INSTR_CVCMPGTUH : this.m_mnemonic = "cv.cmpgtu.h"; + INSTR_CVCMPGTUSCH : this.m_mnemonic = "cv.cmpgtu.sc.h"; + INSTR_CVCMPGTUSCIH : this.m_mnemonic = "cv.cmpgtu.sci.h"; + INSTR_CVCMPGTUB : this.m_mnemonic = "cv.cmpgtu.b"; + INSTR_CVCMPGTUSCB : this.m_mnemonic = "cv.cmpgtu.sc.b"; + INSTR_CVCMPGTUSCIB : this.m_mnemonic = "cv.cmpgtu.sci.b"; INSTR_CVCMPGEUH : this.m_mnemonic = "cv.cmpgeu.h"; INSTR_CVCMPGEUSCH : this.m_mnemonic = "cv.cmpgeu.sc.h"; INSTR_CVCMPGEUSCIH : this.m_mnemonic = "cv.cmpgeu.sci.h"; @@ -844,7 +897,18 @@ `INIT_CSR(mscratch) `INIT_CSR(mepc) `INIT_CSR(mcause) + `INIT_CSR(mcycle) `INIT_CSR(minstret) + `INIT_CSR(mcycleh) + `INIT_CSR(minstreth) + `INIT_CSR(cycle) + `INIT_CSR(instret) + `INIT_CSR(cycleh) + `INIT_CSR(instreth) + this.m_csr.mhpmcounter_we = '0; + this.m_csr.mhpmcounter_wmask = '0; + this.m_csr.mhpmevent_we = '0; + this.m_csr.mhpmevent_wmask = '0; `INIT_CSR(mip) `INIT_CSR(tdata1) `INIT_CSR(tdata2) @@ -872,40 +936,46 @@ this.m_valid = 1'b1; this.m_stage = ID; this.m_order = this.m_order + 64'h1; + this.m_start_cycle = cycles; + this.m_stop_cycle = 0; + this.m_start_time = $time; + this.m_stop_time = 0; if(this.m_skip_order) begin this.m_order = this.m_order + 64'h1; end - this.m_skip_order = 1'b0; - this.m_pc_rdata = r_pipe_freeze_trace.pc_id; - this.m_is_illegal = 1'b0; - this.m_is_irq = 1'b0; - this.m_is_memory = 1'b0; - this.m_is_load = 1'b0; - this.m_is_apu = 1'b0; - this.m_is_apu_ok = 1'b0; - this.m_apu_req_id = 0; - this.m_mem_req_id[0] = 0; - this.m_mem_req_id[1] = 0; - this.m_mem_req_id_valid = '0; - this.m_data_missaligned = 1'b0; - this.m_got_first_data = 1'b0; - this.m_got_ex_reg = 1'b0; - this.m_got_regs_write = 1'b0; - this.m_move_down_pipe = 1'b0; - this.m_instret_cnt = 0; - this.m_rd_addr[0] = '0; - this.m_rd_addr[1] = '0; - this.m_2_rd_insn = 1'b0; - this.m_rs1_addr = '0; - this.m_rs2_addr = '0; - this.m_rs3_addr = '0; - this.m_ex_fw = '0; - this.m_csr.got_minstret = '0; - this.m_dbg_taken = '0; - this.m_trap = 1'b0; - this.m_fflags_we_non_apu = 1'b0; - this.m_frm_we_non_apu = 1'b0; - this.m_fcsr_we_non_apu = 1'b0; + this.m_skip_order = 1'b0; + this.m_pc_rdata = r_pipe_freeze_trace.pc_id; + this.m_is_illegal = 1'b0; + this.m_is_irq = 1'b0; + this.m_is_memory = 1'b0; + this.m_is_load = 1'b0; + this.m_is_apu = 1'b0; + this.m_is_apu_ok = 1'b0; + this.m_apu_req_id = 0; + this.m_mem_req_id[0] = 0; + this.m_mem_req_id[1] = 0; + this.m_mem_req_id_valid = '0; + this.m_data_missaligned = 1'b0; + this.m_got_first_data = 1'b0; + this.m_got_ex_reg = 1'b0; + this.m_got_regs_write = 1'b0; + this.m_move_down_pipe = 1'b0; + this.m_instret_cnt = 0; + this.m_instret_smaple_trigger = 0; + this.m_sample_csr_write_in_ex = 1'b1; + this.m_rd_addr[0] = '0; + this.m_rd_addr[1] = '0; + this.m_2_rd_insn = 1'b0; + this.m_rs1_addr = '0; + this.m_rs2_addr = '0; + this.m_rs3_addr = '0; + this.m_ex_fw = '0; + this.m_csr.got_minstret = '0; + this.m_dbg_taken = '0; + this.m_trap = 1'b0; + this.m_fflags_we_non_apu = 1'b0; + this.m_frm_we_non_apu = 1'b0; + this.m_fcsr_we_non_apu = 1'b0; this.m_csr.mcause_we = '0; if (is_compressed_id_i) begin this.m_insn[31:16] = '0; @@ -944,47 +1014,53 @@ endfunction function void copy_full(insn_trace_t m_source); - this.m_valid = m_source.m_valid; - this.m_stage = m_source.m_stage; - this.m_order = m_source.m_order; - this.m_pc_rdata = m_source.m_pc_rdata; - this.m_insn = m_source.m_insn; - this.m_mnemonic = m_source.m_mnemonic; - this.m_is_memory = m_source.m_is_memory; - this.m_is_load = m_source.m_is_load; - this.m_is_apu = m_source.m_is_apu; - this.m_is_apu_ok = m_source.m_is_apu_ok; - this.m_apu_req_id = m_source.m_apu_req_id; - this.m_mem_req_id = m_source.m_mem_req_id; - this.m_mem_req_id_valid = m_source.m_mem_req_id_valid; - this.m_data_missaligned = m_source.m_data_missaligned; - this.m_got_first_data = m_source.m_got_first_data; - this.m_got_ex_reg = m_source.m_got_ex_reg; - this.m_dbg_taken = m_source.m_dbg_taken; - this.m_dbg_cause = m_source.m_dbg_cause; - this.m_is_ebreak = m_source.m_is_ebreak; - this.m_is_illegal = m_source.m_is_illegal; - this.m_is_irq = m_source.m_is_irq; - this.m_instret_cnt = m_source.m_instret_cnt; - this.m_rs1_addr = m_source.m_rs1_addr; - this.m_rs2_addr = m_source.m_rs2_addr; - this.m_rs3_addr = m_source.m_rs3_addr; - this.m_rs1_rdata = m_source.m_rs1_rdata; - this.m_rs2_rdata = m_source.m_rs2_rdata; - this.m_rs3_rdata = m_source.m_rs3_rdata; - - this.m_ex_fw = m_source.m_ex_fw; - this.m_rd_addr = m_source.m_rd_addr; - this.m_2_rd_insn = m_source.m_2_rd_insn; - this.m_rd_wdata = m_source.m_rd_wdata; - - this.m_intr = m_source.m_intr; - this.m_trap = m_source.m_trap; - this.m_fflags_we_non_apu = m_source.m_fflags_we_non_apu; - this.m_frm_we_non_apu = m_source.m_frm_we_non_apu ; - this.m_fcsr_we_non_apu = m_source.m_fcsr_we_non_apu; - - this.m_mem = m_source.m_mem; + this.m_valid = m_source.m_valid; + this.m_stage = m_source.m_stage; + this.m_order = m_source.m_order; + this.m_start_cycle = m_source.m_start_cycle; + this.m_stop_cycle = m_source.m_stop_cycle; + this.m_start_time = m_source.m_start_time; + this.m_stop_time = m_source.m_stop_time; + this.m_pc_rdata = m_source.m_pc_rdata; + this.m_insn = m_source.m_insn; + this.m_mnemonic = m_source.m_mnemonic; + this.m_is_memory = m_source.m_is_memory; + this.m_is_load = m_source.m_is_load; + this.m_is_apu = m_source.m_is_apu; + this.m_is_apu_ok = m_source.m_is_apu_ok; + this.m_apu_req_id = m_source.m_apu_req_id; + this.m_mem_req_id = m_source.m_mem_req_id; + this.m_mem_req_id_valid = m_source.m_mem_req_id_valid; + this.m_data_missaligned = m_source.m_data_missaligned; + this.m_got_first_data = m_source.m_got_first_data; + this.m_got_ex_reg = m_source.m_got_ex_reg; + this.m_dbg_taken = m_source.m_dbg_taken; + this.m_dbg_cause = m_source.m_dbg_cause; + this.m_is_ebreak = m_source.m_is_ebreak; + this.m_is_illegal = m_source.m_is_illegal; + this.m_is_irq = m_source.m_is_irq; + this.m_instret_cnt = m_source.m_instret_cnt; + this.m_instret_smaple_trigger = m_source.m_instret_smaple_trigger; + this.m_sample_csr_write_in_ex = m_source.m_sample_csr_write_in_ex; + this.m_rs1_addr = m_source.m_rs1_addr; + this.m_rs2_addr = m_source.m_rs2_addr; + this.m_rs3_addr = m_source.m_rs3_addr; + this.m_rs1_rdata = m_source.m_rs1_rdata; + this.m_rs2_rdata = m_source.m_rs2_rdata; + this.m_rs3_rdata = m_source.m_rs3_rdata; + + this.m_ex_fw = m_source.m_ex_fw; + this.m_rd_addr = m_source.m_rd_addr; + this.m_2_rd_insn = m_source.m_2_rd_insn; + this.m_rd_wdata = m_source.m_rd_wdata; + + this.m_intr = m_source.m_intr; + this.m_trap = m_source.m_trap; + this.m_fflags_we_non_apu = m_source.m_fflags_we_non_apu; + this.m_frm_we_non_apu = m_source.m_frm_we_non_apu ; + this.m_fcsr_we_non_apu = m_source.m_fcsr_we_non_apu; + + this.m_mem = m_source.m_mem; //CRS `ASSIGN_CSR(mstatus) `ASSIGN_CSR(mstatus_fs) @@ -995,8 +1071,26 @@ `ASSIGN_CSR(mscratch) `ASSIGN_CSR(mepc) `ASSIGN_CSR(mcause) + `ASSIGN_CSR(mcycle) `ASSIGN_CSR(minstret) this.m_csr.got_minstret = m_source.m_csr.got_minstret; + `ASSIGN_CSR(mcycleh) + `ASSIGN_CSR(minstreth) + `ASSIGN_CSR(cycle) + `ASSIGN_CSR(instret) + // this.m_csr.got_minstret = m_source.m_csr.got_minstret; + `ASSIGN_CSR(cycleh) + `ASSIGN_CSR(instreth) + this.m_csr.mhpmcounter_we = m_source.m_csr.mhpmcounter_we; + this.m_csr.mhpmcounter_rdata = m_source.m_csr.mhpmcounter_rdata; + this.m_csr.mhpmcounter_rmask = m_source.m_csr.mhpmcounter_rmask; + this.m_csr.mhpmcounter_wdata = m_source.m_csr.mhpmcounter_wdata; + this.m_csr.mhpmcounter_wmask = m_source.m_csr.mhpmcounter_wmask; + this.m_csr.mhpmevent_we = m_source.m_csr.mhpmevent_we; + this.m_csr.mhpmevent_rdata = m_source.m_csr.mhpmevent_rdata; + this.m_csr.mhpmevent_rmask = m_source.m_csr.mhpmevent_rmask; + this.m_csr.mhpmevent_wdata = m_source.m_csr.mhpmevent_wdata; + this.m_csr.mhpmevent_wmask = m_source.m_csr.mhpmevent_wmask; `ASSIGN_CSR(mip) `ASSIGN_CSR(tdata1) `ASSIGN_CSR(tdata2) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/pipe_freeze_trace.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/pipe_freeze_trace.sv index 58051ab8..39a16fa6 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/pipe_freeze_trace.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/bhv/pipe_freeze_trace.sv @@ -1,27 +1,29 @@ -// Copyright (c) 2023 OpenHW Group +// Copyright 2024 OpenHW Group and Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // -// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. // You may obtain a copy of the License at // -// https://solderpad.org/licenses/ +// https://solderpad.org/licenses/SHL-2.1/ // -// Unless required by applicable law or agreed to in writing, software +// Unless required by applicable law or agreed to in writing, any work // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 -// CV32E40P -// -// Contributors: Yoann Pruvost, Dolphin Design +//////////////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Yoann Pruvost, Dolphin Design // +// // +// Description: Structures, Functions and Task used to store all information // +// coming from the core pipeline at every posedge. // +// Those information will then be processed by RVFI. // +// // +//////////////////////////////////////////////////////////////////////////////////// -/* - * This struct is used to store all information comming from the core at every posedge - * The information will then be processed - */ typedef struct { logic is_decoding; logic is_illegal; @@ -64,6 +66,9 @@ typedef struct { logic is_compressed_id; logic ebrk_insn_dec; + logic ecall_insn_dec; + logic mret_insn_dec; + logic mret_dec; logic [5:0] csr_cause; @@ -112,6 +117,9 @@ typedef struct { logic [31:0] data_wdata_ex; logic lsu_split_q_ex; + logic mult_ready; + logic alu_ready; + //// WB probes //// logic [31:0] pc_wb; logic wb_ready; @@ -198,6 +206,8 @@ typedef struct { logic mcause_we; logic dcsr_we; + logic fregs_we; + logic jvt_we; Status_t mstatus_n; Status_t mstatus_q; @@ -341,6 +351,7 @@ function compute_csr_we(); r_pipe_freeze_trace.csr.fflags_we = 1'b0; r_pipe_freeze_trace.csr.frm_we = 1'b0; r_pipe_freeze_trace.csr.fcsr_we = 1'b0; + r_pipe_freeze_trace.csr.mhpmevent_we = '0; r_pipe_freeze_trace.csr.dpc_we = csr_dpc_we_i; if (r_pipe_freeze_trace.csr.we) begin case (r_pipe_freeze_trace.csr.addr) @@ -348,18 +359,33 @@ function compute_csr_we(); r_pipe_freeze_trace.csr.mstatus_we = 1'b1; r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; end - CSR_MISA: r_pipe_freeze_trace.csr.misa_we = 1'b1; - CSR_MTVEC: r_pipe_freeze_trace.csr.mtvec_we = 1'b1; - CSR_MSCRATCH: r_pipe_freeze_trace.csr.mscratch_we = 1'b1; - CSR_MEPC: r_pipe_freeze_trace.csr.mepc_we = 1'b1; - CSR_MCAUSE: r_pipe_freeze_trace.csr.mcause_we = 1'b1; - CSR_DCSR: r_pipe_freeze_trace.csr.dcsr_we = 1'b1; - CSR_FFLAGS: r_pipe_freeze_trace.csr.fflags_we = 1'b1; - CSR_FRM: r_pipe_freeze_trace.csr.frm_we = 1'b1; - CSR_FCSR: r_pipe_freeze_trace.csr.fcsr_we = 1'b1; - CSR_DPC: r_pipe_freeze_trace.csr.dpc_we = 1'b1; + CSR_MISA: r_pipe_freeze_trace.csr.misa_we = 1'b1; + CSR_MTVEC: r_pipe_freeze_trace.csr.mtvec_we = 1'b1; + CSR_MSCRATCH: r_pipe_freeze_trace.csr.mscratch_we = 1'b1; + CSR_MEPC: r_pipe_freeze_trace.csr.mepc_we = 1'b1; + CSR_MCAUSE: r_pipe_freeze_trace.csr.mcause_we = 1'b1; + CSR_DCSR: r_pipe_freeze_trace.csr.dcsr_we = 1'b1; + CSR_FFLAGS: begin + r_pipe_freeze_trace.csr.fflags_we = 1'b1; + r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; + end + CSR_FRM: begin + r_pipe_freeze_trace.csr.frm_we = 1'b1; + r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; + end + CSR_FCSR: begin + r_pipe_freeze_trace.csr.fcsr_we = 1'b1; + r_pipe_freeze_trace.csr.mstatus_fs_we = 1'b1; + end + CSR_DPC: r_pipe_freeze_trace.csr.dpc_we = 1'b1; + CSR_DSCRATCH0: r_pipe_freeze_trace.csr.dscratch0_we = 1'b1; + CSR_DSCRATCH1: r_pipe_freeze_trace.csr.dscratch1_we = 1'b1; endcase end + + if (csr_mhpmevent_we_i) begin + r_pipe_freeze_trace.csr.mhpmevent_we[r_pipe_freeze_trace.csr.addr[4:0]] = 1'b1; + end // CSR_MCAUSE: r_pipe_freeze_trace.csr.mcause_we = r_pipe_freeze_trace.csr.mcause_n != r_pipe_freeze_trace.csr.mcause_q; //for debug purpose endfunction /* @@ -416,6 +442,9 @@ task monitor_pipeline(); r_pipe_freeze_trace.jump_target_id = jump_target_id_i; r_pipe_freeze_trace.is_compressed_id = is_compressed_id_i; r_pipe_freeze_trace.ebrk_insn_dec = ebrk_insn_dec_i; + r_pipe_freeze_trace.ecall_insn_dec = ecall_insn_dec_i; + r_pipe_freeze_trace.mret_insn_dec = mret_insn_dec_i; + r_pipe_freeze_trace.mret_dec = mret_dec_i; r_pipe_freeze_trace.csr_cause = csr_cause_i; r_pipe_freeze_trace.debug_csr_save = debug_csr_save_i; r_pipe_freeze_trace.minstret = minstret_i; @@ -462,6 +491,8 @@ task monitor_pipeline(); r_pipe_freeze_trace.data_wdata_ex = data_wdata_ex_i; r_pipe_freeze_trace.lsu_split_q_ex = lsu_split_q_ex_i; + r_pipe_freeze_trace.mult_ready = mult_ready_i; + r_pipe_freeze_trace.alu_ready = alu_ready_i; //// WB probes //// r_pipe_freeze_trace.pc_wb = pc_wb_i; r_pipe_freeze_trace.wb_ready = wb_ready_i; @@ -526,6 +557,8 @@ task monitor_pipeline(); r_pipe_freeze_trace.csr.we = csr_we_i; r_pipe_freeze_trace.csr.wdata_int = csr_wdata_int_i; + r_pipe_freeze_trace.csr.fregs_we = csr_fregs_we_i; + r_pipe_freeze_trace.csr.jvt_we = csr_jvt_we_i; r_pipe_freeze_trace.csr.mstatus_n = csr_mstatus_n_i; r_pipe_freeze_trace.csr.mstatus_q = csr_mstatus_q_i; @@ -550,7 +583,6 @@ task monitor_pipeline(); r_pipe_freeze_trace.csr.mcountinhibit_we = csr_mcountinhibit_we_i; r_pipe_freeze_trace.csr.mhpmevent_n = csr_mhpmevent_n_i; r_pipe_freeze_trace.csr.mhpmevent_q = csr_mhpmevent_q_i; - r_pipe_freeze_trace.csr.mhpmevent_we = csr_mhpmevent_we_i; r_pipe_freeze_trace.csr.mscratch_n = csr_mscratch_n_i; r_pipe_freeze_trace.csr.mscratch_q = csr_mscratch_q_i; r_pipe_freeze_trace.csr.mepc_n = csr_mepc_n_i; @@ -650,10 +682,6 @@ task monitor_pipeline(); if (r_pipe_freeze_trace.csr.fcsr_we) begin r_pipe_freeze_trace.csr.fflags_we = 1'b1; r_pipe_freeze_trace.csr.frm_we = 1'b1; - end else begin - if (r_pipe_freeze_trace.csr.fflags_we || r_pipe_freeze_trace.csr.frm_we) begin - r_pipe_freeze_trace.csr.fcsr_we = 1'b1; - end end if (csr_fcsr_fflags_we_i) begin diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_controller.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_controller.sv index 54980269..d1c86d6c 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_controller.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_controller.sv @@ -491,6 +491,7 @@ module cv32e40p_controller import cv32e40p_pkg::*; if ( (debug_req_pending || trigger_match_i) & ~debug_mode_q ) begin //Serving the debug + is_decoding_o = COREV_PULP ? 1'b0 : 1'b1; halt_if_o = 1'b1; halt_id_o = 1'b1; ctrl_fsm_ns = DBG_FLUSH; @@ -596,7 +597,17 @@ module cv32e40p_controller import cv32e40p_pkg::*; csr_status_i: begin halt_if_o = 1'b1; - ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE; + if (~id_ready_i) begin + ctrl_fsm_ns = DECODE; + end else begin + ctrl_fsm_ns = FLUSH_EX; + if (hwlp_end0_eq_pc) begin + hwlp_dec_cnt_o[0] = 1'b1; + end + if (hwlp_end1_eq_pc) begin + hwlp_dec_cnt_o[1] = 1'b1; + end + end end data_load_event_i: begin @@ -616,7 +627,7 @@ module cv32e40p_controller import cv32e40p_pkg::*; ctrl_fsm_ns = hwlp_end0_eq_pc_plus4 || hwlp_end1_eq_pc_plus4 ? DECODE : DECODE_HWLOOP; // we can be at the end of HWloop due to a return from interrupt or ecall or ebreak or exceptions - if(hwlp_end0_eq_pc && hwlp_counter0_gt_1) begin + if (hwlp_end0_eq_pc && hwlp_counter0_gt_1) begin pc_mux_o = PC_HWLOOP; if (~jump_done_q) begin pc_set_o = 1'b1; @@ -712,6 +723,7 @@ module cv32e40p_controller import cv32e40p_pkg::*; if ( (debug_req_pending || trigger_match_i) & ~debug_mode_q ) begin //Serving the debug + is_decoding_o = COREV_PULP ? 1'b0 : 1'b1; halt_if_o = 1'b1; halt_id_o = 1'b1; ctrl_fsm_ns = DBG_FLUSH; @@ -764,7 +776,7 @@ module cv32e40p_controller import cv32e40p_pkg::*; ebrk_insn_i: begin halt_if_o = 1'b1; - halt_id_o = 1'b1; + halt_id_o = 1'b0; if (debug_mode_q) // we got back to the park loop in the debug rom @@ -776,20 +788,30 @@ module cv32e40p_controller import cv32e40p_pkg::*; else begin // otherwise just a normal ebreak exception - ctrl_fsm_ns = FLUSH_EX; + ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE_HWLOOP; end end ecall_insn_i: begin halt_if_o = 1'b1; - halt_id_o = 1'b1; - ctrl_fsm_ns = FLUSH_EX; + halt_id_o = 1'b0; + ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE_HWLOOP; end csr_status_i: begin halt_if_o = 1'b1; - ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE_HWLOOP; + if (~id_ready_i) begin + ctrl_fsm_ns = DECODE_HWLOOP; + end else begin + ctrl_fsm_ns = FLUSH_EX; + if (hwlp_end0_eq_pc) begin + hwlp_dec_cnt_o[0] = 1'b1; + end + if (hwlp_end1_eq_pc) begin + hwlp_dec_cnt_o[1] = 1'b1; + end + end end data_load_event_i: begin @@ -1065,16 +1087,10 @@ module cv32e40p_controller import cv32e40p_pkg::*; end csr_status_i: begin - - if(hwlp_end0_eq_pc && hwlp_counter0_gt_1) begin - pc_mux_o = PC_HWLOOP; - pc_set_o = 1'b1; - hwlp_dec_cnt_o[0] = 1'b1; - end - if(hwlp_end1_eq_pc && hwlp_counter1_gt_1) begin - pc_mux_o = PC_HWLOOP; - pc_set_o = 1'b1; - hwlp_dec_cnt_o[1] = 1'b1; + if ((hwlp_end0_eq_pc && !hwlp_counter0_eq_0) || + (hwlp_end1_eq_pc && !hwlp_counter1_eq_0)) begin + pc_mux_o = PC_HWLOOP; + pc_set_o = 1'b1; end end @@ -1559,7 +1575,7 @@ endgenerate // HWLoop 0 and 1 having target address constraints property p_hwlp_same_target_address; - @(posedge clk) (hwlp_counter_i[1] > 1 && hwlp_counter_i[0] > 1) |-> ( hwlp_end_addr_i[1] - 4 >= hwlp_end_addr_i[0] - 4 + 8 ); + @(posedge clk) (hwlp_counter_i[1] > 1 && hwlp_counter_i[0] > 1 && pc_id_i >= hwlp_start_addr_i[0] && pc_id_i <= hwlp_end_addr_i[0] - 4) |-> ( hwlp_end_addr_i[1] - 4 >= hwlp_end_addr_i[0] - 4 + 8 ); endproperty a_hwlp_same_target_address : assert property(p_hwlp_same_target_address) else $warning("%t, HWLoops target address do not respect constraints", $time); diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_core.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_core.sv index e6f9f709..4275cf9c 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_core.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_core.sv @@ -70,7 +70,8 @@ module cv32e40p_core output logic [31:0] data_wdata_o, input logic [31:0] data_rdata_i, - // apu-interconnect + // CVFPU interface + output logic apu_busy_o, // handshake signals output logic apu_req_o, input logic apu_gnt_i, @@ -158,11 +159,11 @@ module cv32e40p_core logic [31:0] jump_target_id, jump_target_ex; logic branch_in_ex; logic branch_decision; + logic [ 1:0] ctrl_transfer_insn_in_dec; logic ctrl_busy; logic if_busy; logic lsu_busy; - logic apu_busy; logic [31:0] pc_ex; // PC of last executed branch or cv.elw @@ -201,6 +202,7 @@ module cv32e40p_core logic [ C_RM-1:0] frm_csr; logic [ C_FFLAG-1:0] fflags_csr; logic fflags_we; + logic fregs_we; // APU logic apu_en_ex; @@ -228,6 +230,7 @@ module cv32e40p_core logic regfile_we_ex; logic [ 5:0] regfile_waddr_fw_wb_o; // From WB to ID logic regfile_we_wb; + logic regfile_we_wb_power; logic [ 31:0] regfile_wdata; logic [ 5:0] regfile_alu_waddr_ex; @@ -235,6 +238,7 @@ module cv32e40p_core logic [ 5:0] regfile_alu_waddr_fw; logic regfile_alu_we_fw; + logic regfile_alu_we_fw_power; logic [ 31:0] regfile_alu_wdata_fw; // CSR control @@ -395,7 +399,7 @@ module cv32e40p_core .if_busy_i (if_busy), .ctrl_busy_i(ctrl_busy), .lsu_busy_i (lsu_busy), - .apu_busy_i (apu_busy), + .apu_busy_i (apu_busy_o), // PULP cluster .pulp_clock_en_i (pulp_clock_en_i), @@ -540,9 +544,10 @@ module cv32e40p_core .instr_req_o (instr_req_int), // Jumps and branches - .branch_in_ex_o (branch_in_ex), - .branch_decision_i(branch_decision), - .jump_target_o (jump_target_id), + .branch_in_ex_o (branch_in_ex), + .branch_decision_i (branch_decision), + .jump_target_o (jump_target_id), + .ctrl_transfer_insn_in_dec_o(ctrl_transfer_insn_in_dec), // IF and ID control signals .clear_instr_valid_o(clear_instr_valid), @@ -629,7 +634,7 @@ module cv32e40p_core .apu_write_regs_valid_o (apu_write_regs_valid), .apu_write_dep_i (apu_write_dep), .apu_perf_dep_o (perf_apu_dep), - .apu_busy_i (apu_busy), + .apu_busy_i (apu_busy_o), // CSR ID/EX .csr_access_ex_o (csr_access_ex), @@ -699,13 +704,15 @@ module cv32e40p_core .wake_from_sleep_o(wake_from_sleep), // Forward Signals - .regfile_waddr_wb_i(regfile_waddr_fw_wb_o), // Write address ex-wb pipeline - .regfile_we_wb_i (regfile_we_wb), // write enable for the register file - .regfile_wdata_wb_i(regfile_wdata), // write data to commit in the register file + .regfile_waddr_wb_i (regfile_waddr_fw_wb_o), // Write address ex-wb pipeline + .regfile_we_wb_i (regfile_we_wb), // write enable for the register file + .regfile_we_wb_power_i(regfile_we_wb_power), + .regfile_wdata_wb_i (regfile_wdata), // write data to commit in the register file - .regfile_alu_waddr_fw_i(regfile_alu_waddr_fw), - .regfile_alu_we_fw_i (regfile_alu_we_fw), - .regfile_alu_wdata_fw_i(regfile_alu_wdata_fw), + .regfile_alu_waddr_fw_i (regfile_alu_waddr_fw), + .regfile_alu_we_fw_i (regfile_alu_we_fw), + .regfile_alu_we_fw_power_i(regfile_alu_we_fw_power), + .regfile_alu_wdata_fw_i (regfile_alu_wdata_fw), // from ALU .mult_multicycle_i(mult_multicycle), @@ -737,6 +744,7 @@ module cv32e40p_core // // ///////////////////////////////////////////////////// cv32e40p_ex_stage #( + .COREV_PULP (COREV_PULP), .FPU (FPU), .APU_NARGS_CPU (APU_NARGS_CPU), .APU_WOP_CPU (APU_WOP_CPU), @@ -785,6 +793,8 @@ module cv32e40p_core .data_misaligned_ex_i(data_misaligned_ex), // from ID/EX pipeline .data_misaligned_i (data_misaligned), + .ctrl_transfer_insn_in_dec_i(ctrl_transfer_insn_in_dec), + // FPU .fpu_fflags_we_o(fflags_we), .fpu_fflags_o (fflags_csr), @@ -808,9 +818,9 @@ module cv32e40p_core .apu_perf_cont_o(perf_apu_cont), .apu_perf_wb_o (perf_apu_wb), .apu_ready_wb_o (apu_ready_wb), - .apu_busy_o (apu_busy), + .apu_busy_o (apu_busy_o), - // apu-interconnect + // CVFPU interface // handshake signals .apu_req_o (apu_req_o), .apu_gnt_i (apu_gnt_i), @@ -838,18 +848,20 @@ module cv32e40p_core .regfile_we_i (regfile_we_ex), // Output of ex stage pipeline - .regfile_waddr_wb_o(regfile_waddr_fw_wb_o), - .regfile_we_wb_o (regfile_we_wb), - .regfile_wdata_wb_o(regfile_wdata), + .regfile_waddr_wb_o (regfile_waddr_fw_wb_o), + .regfile_we_wb_o (regfile_we_wb), + .regfile_we_wb_power_o(regfile_we_wb_power), + .regfile_wdata_wb_o (regfile_wdata), // To IF: Jump and branch target and decision .jump_target_o (jump_target_ex), .branch_decision_o(branch_decision), // To ID stage: Forwarding signals - .regfile_alu_waddr_fw_o(regfile_alu_waddr_fw), - .regfile_alu_we_fw_o (regfile_alu_we_fw), - .regfile_alu_wdata_fw_o(regfile_alu_wdata_fw), + .regfile_alu_waddr_fw_o (regfile_alu_waddr_fw), + .regfile_alu_we_fw_o (regfile_alu_we_fw), + .regfile_alu_we_fw_power_o(regfile_alu_we_fw_power), + .regfile_alu_wdata_fw_o (regfile_alu_wdata_fw), // stall control .is_decoding_i (is_decoding), @@ -969,6 +981,7 @@ module cv32e40p_core .frm_o (frm_csr), .fflags_i (fflags_csr), .fflags_we_i(fflags_we), + .fregs_we_i (fregs_we), // Interrupt related control signals .mie_bypass_o (mie_bypass), @@ -1037,13 +1050,16 @@ module cv32e40p_core ); // CSR access - assign csr_addr = csr_addr_int; - assign csr_wdata = alu_operand_a_ex; - assign csr_op = csr_op_ex; + assign csr_addr = csr_addr_int; + assign csr_wdata = alu_operand_a_ex; + assign csr_op = csr_op_ex; assign csr_addr_int = csr_num_e'(csr_access_ex ? alu_operand_b_ex[11:0] : '0); - + // Floating-Point registers write + assign fregs_we = (FPU == 1 & ZFINX == 0) ? ((regfile_alu_we_fw && regfile_alu_waddr_fw[5]) || + (regfile_we_wb && regfile_waddr_fw_wb_o[5])) + : 1'b0; /////////////////////////// // ____ __ __ ____ // diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_cs_registers.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_cs_registers.sv index 25c777e2..920305c8 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_cs_registers.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_cs_registers.sv @@ -68,6 +68,7 @@ module cv32e40p_cs_registers output logic [ 2:0] frm_o, input logic [C_FFLAG-1:0] fflags_i, input logic fflags_we_i, + input logic fregs_we_i, // Interrupts output logic [31:0] mie_bypass_o, @@ -212,6 +213,7 @@ module cv32e40p_cs_registers logic [31:0] exception_pc; Status_t mstatus_q, mstatus_n; + logic mstatus_we_int; FS_t mstatus_fs_q, mstatus_fs_n; logic [5:0] mcause_q, mcause_n; logic [5:0] ucause_q, ucause_n; @@ -507,7 +509,7 @@ module cv32e40p_cs_registers // mimpid, Machine Implementation ID CSR_MIMPID: begin - csr_rdata_int = (FPU || COREV_PULP || COREV_CLUSTER) ? 32'h1 : 'b0; + csr_rdata_int = (FPU == 1 || COREV_PULP == 1 || COREV_CLUSTER == 1) ? 32'h1 : 'b0; end // unimplemented, read 0 CSRs @@ -897,6 +899,7 @@ module cv32e40p_cs_registers dscratch0_n = dscratch0_q; dscratch1_n = dscratch1_q; + mstatus_we_int = 1'b0; mstatus_n = mstatus_q; mcause_n = mcause_q; ucause_n = '0; // Not used if PULP_SECURE == 0 @@ -957,7 +960,8 @@ module cv32e40p_cs_registers mprv: csr_wdata_int[MSTATUS_MPRV_BIT] }; if (FPU == 1 && ZFINX == 0) begin - mstatus_fs_n = FS_t'(csr_wdata_int[MSTATUS_FS_BIT_HIGH:MSTATUS_FS_BIT_LOW]); + mstatus_we_int = 1'b1; + mstatus_fs_n = FS_t'(csr_wdata_int[MSTATUS_FS_BIT_HIGH:MSTATUS_FS_BIT_LOW]); end end // mie: machine interrupt enable @@ -1027,7 +1031,7 @@ module cv32e40p_cs_registers if (ZFINX == 0) begin // FPU Register File/Flags implicit update or modified by CSR instructions - if (fflags_we_i || fcsr_update) begin + if ((fregs_we_i && !(mstatus_we_int && mstatus_fs_n != FS_DIRTY)) || fflags_we_i || fcsr_update) begin mstatus_fs_n = FS_DIRTY; end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_decoder.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_decoder.sv index d03027ba..c1608eb4 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_decoder.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_decoder.sv @@ -1057,7 +1057,6 @@ module cv32e40p_decoder 5'b00000: begin fpu_op = cv32e40p_fpu_pkg::ADD; fp_op_group = ADDMUL; - apu_op_o = 2'b0; alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; end @@ -1066,7 +1065,6 @@ module cv32e40p_decoder fpu_op = cv32e40p_fpu_pkg::ADD; fpu_op_mod = 1'b1; fp_op_group = ADDMUL; - apu_op_o = 2'b1; alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; end @@ -1085,7 +1083,6 @@ module cv32e40p_decoder regb_used_o = 1'b0; fpu_op = cv32e40p_fpu_pkg::SQRT; fp_op_group = DIVSQRT; - apu_op_o = 1'b1; // rs2 must be zero if (instr_rdata_i[24:20] != 5'b00000) illegal_insn_o = 1'b1; end @@ -1213,7 +1210,6 @@ module cv32e40p_decoder fpu_op = cv32e40p_fpu_pkg::F2I; fp_op_group = CONV; fpu_op_mod = instr_rdata_i[20]; // signed/unsigned switch - apu_op_o = 2'b1; unique case (instr_rdata_i[26:25]) //fix for casting to different formats other than FP32 2'b00: begin @@ -1249,7 +1245,6 @@ module cv32e40p_decoder fpu_op = cv32e40p_fpu_pkg::I2F; fp_op_group = CONV; fpu_op_mod = instr_rdata_i[20]; // signed/unsigned switch - apu_op_o = 2'b0; // bits [21:20] used, other bits must be 0 if (instr_rdata_i[24:21]) illegal_insn_o = 1'b1; // in RV32, no casts to L allowed. end @@ -1323,20 +1318,20 @@ module cv32e40p_decoder // check rounding mode if (check_fprm) begin unique case (instr_rdata_i[14:12]) inside - [3'b000:3'b100]: ; //legal rounding modes + 3'b000, 3'b001, 3'b010, 3'b011, 3'b100: ; //legal rounding modes 3'b101: begin // Alternative Half-Precsision encded as fmt=10 and rm=101 if (~C_XF16ALT || fpu_dst_fmt_o != cv32e40p_fpu_pkg::FP16ALT) illegal_insn_o = 1'b1; // actual rounding mode from frm csr unique case (frm_i) inside - [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes - default : illegal_insn_o = 1'b1; + 3'b000, 3'b001, 3'b010, 3'b011, 3'b100 : fp_rnd_mode_o = frm_i; //legal rounding modes + default : illegal_insn_o = 1'b1; endcase end 3'b111: begin // rounding mode from frm csr unique case (frm_i) inside - [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes - default : illegal_insn_o = 1'b1; + 3'b000, 3'b001, 3'b010, 3'b011, 3'b100 : fp_rnd_mode_o = frm_i; //legal rounding modes + default : illegal_insn_o = 1'b1; endcase end default : illegal_insn_o = 1'b1; @@ -1364,6 +1359,7 @@ module cv32e40p_decoder NONCOMP : apu_lat_o = (FPU_OTHERS_LAT<2) ? FPU_OTHERS_LAT+1 : 2'h3; // CONV uses the same latency for all formats CONV : apu_lat_o = (FPU_OTHERS_LAT<2) ? FPU_OTHERS_LAT+1 : 2'h3; + default: ; endcase // Set FPnew OP and OPMOD as the APU op @@ -1425,25 +1421,21 @@ module cv32e40p_decoder unique case (instr_rdata_i[6:0]) // fmadd.fmt - FP Fused multiply-add OPCODE_OP_FMADD : begin - fpu_op = cv32e40p_fpu_pkg::FMADD; - apu_op_o = 2'b00; + fpu_op = cv32e40p_fpu_pkg::FMADD; end // fmsub.fmt - FP Fused multiply-subtract OPCODE_OP_FMSUB : begin - fpu_op = cv32e40p_fpu_pkg::FMADD; - fpu_op_mod = 1'b1; - apu_op_o = 2'b01; + fpu_op = cv32e40p_fpu_pkg::FMADD; + fpu_op_mod = 1'b1; end // fnmsub.fmt - FP Negated fused multiply-subtract OPCODE_OP_FNMSUB : begin - fpu_op = cv32e40p_fpu_pkg::FNMSUB; - apu_op_o = 2'b10; + fpu_op = cv32e40p_fpu_pkg::FNMSUB; end // fnmadd.fmt - FP Negated fused multiply-add OPCODE_OP_FNMADD : begin - fpu_op = cv32e40p_fpu_pkg::FNMSUB; - fpu_op_mod = 1'b1; - apu_op_o = 2'b11; + fpu_op = cv32e40p_fpu_pkg::FNMSUB; + fpu_op_mod = 1'b1; end default : ; endcase @@ -1459,19 +1451,19 @@ module cv32e40p_decoder // check rounding mode unique case (instr_rdata_i[14:12]) inside - [3'b000:3'b100]: ; //legal rounding modes + 3'b000, 3'b001, 3'b010, 3'b011, 3'b100: ; //legal rounding modes 3'b101: begin // Alternative Half-Precsision encded as fmt=10 and rm=101 if (~C_XF16ALT || fpu_dst_fmt_o != cv32e40p_fpu_pkg::FP16ALT) illegal_insn_o = 1'b1; // actual rounding mode from frm csr unique case (frm_i) inside - [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes + 3'b000, 3'b001, 3'b010, 3'b011, 3'b100 : fp_rnd_mode_o = frm_i; //legal rounding modes default : illegal_insn_o = 1'b1; endcase end 3'b111: begin // rounding mode from frm csr unique case (frm_i) inside - [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes + 3'b000, 3'b001, 3'b010, 3'b011, 3'b100 : fp_rnd_mode_o = frm_i; //legal rounding modes default : illegal_insn_o = 1'b1; endcase end @@ -1493,6 +1485,7 @@ module cv32e40p_decoder // Set FPnew OP and OPMOD as the APU op apu_op_o = {fpu_vec_op, fpu_op_mod, fpu_op}; + // No FPU or (ZFINX == 0 && MSTATUS.FS == FS_OFF) end else begin illegal_insn_o = 1'b1; @@ -1900,15 +1893,14 @@ module cv32e40p_decoder alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; unique case (instr_rdata_i[27:25]) - 3'b000: alu_operator_o = ALU_ADD; // cv.addNr - 3'b001: alu_operator_o = ALU_ADDU; // cv.adduNr - 3'b010: alu_operator_o = ALU_ADDR; // cv.addRNr - 3'b011: alu_operator_o = ALU_ADDUR; // cv.adduRNr - 3'b100: alu_operator_o = ALU_SUB; // cv.subNr - 3'b101: alu_operator_o = ALU_SUBU; // cv.subuNr - 3'b110: alu_operator_o = ALU_SUBR; // cv.subRNr - 3'b111: alu_operator_o = ALU_SUBUR; // cv.subuRNr - default: alu_operator_o = ALU_ADD; + 3'b001: alu_operator_o = ALU_ADDU; // cv.adduNr + 3'b010: alu_operator_o = ALU_ADDR; // cv.addRNr + 3'b011: alu_operator_o = ALU_ADDUR; // cv.adduRNr + 3'b100: alu_operator_o = ALU_SUB; // cv.subNr + 3'b101: alu_operator_o = ALU_SUBU; // cv.subuNr + 3'b110: alu_operator_o = ALU_SUBR; // cv.subRNr + 3'b111: alu_operator_o = ALU_SUBUR; // cv.subuRNr + default: alu_operator_o = ALU_ADD; // cv.addNr endcase end @@ -2085,7 +2077,6 @@ module cv32e40p_decoder // decide between using unsigned and rounding, and combinations unique case ({instr_rdata_i[31:30], instr_rdata_i[12]}) - {2'b00, 1'b0}: alu_operator_o = ALU_ADD; // cv.addN {2'b01, 1'b0}: alu_operator_o = ALU_ADDU; // cv.adduN {2'b10, 1'b0}: alu_operator_o = ALU_ADDR; // cv.addRN {2'b11, 1'b0}: alu_operator_o = ALU_ADDUR; // cv.adduRN @@ -2093,12 +2084,12 @@ module cv32e40p_decoder {2'b01, 1'b1}: alu_operator_o = ALU_SUBU; // cv.subuN {2'b10, 1'b1}: alu_operator_o = ALU_SUBR; // cv.subRN {2'b11, 1'b1}: alu_operator_o = ALU_SUBUR; // cv.subuRN - default : alu_operator_o = ALU_ADD; + default : alu_operator_o = ALU_ADD; // cv.addN endcase end - 2'b10, 2'b11: begin + default: begin // MUL/MAC with subword selection alu_en = 1'b0; mult_int_en = 1'b1; @@ -2126,7 +2117,6 @@ module cv32e40p_decoder mult_operator_o = MUL_I; end end - default: illegal_insn_o = 1'b1; endcase end else begin illegal_insn_o = 1'b1; @@ -2267,6 +2257,11 @@ module cv32e40p_decoder instr_rdata_i[25] != 1'b0) begin illegal_insn_o = 1'b1; end + // Imm6 restrictions + if ((instr_rdata_i[14:12] == 3'b110 && instr_rdata_i[24:23] != 2'b0) || + (instr_rdata_i[14:12] == 3'b111 && instr_rdata_i[24:22] != 3'b0)) begin + illegal_insn_o = 1'b1; + end end 6'b01001_0: begin // cv.sra alu_operator_o = ALU_SRA; @@ -2278,6 +2273,11 @@ module cv32e40p_decoder instr_rdata_i[25] != 1'b0) begin illegal_insn_o = 1'b1; end + // Imm6 restrictions + if ((instr_rdata_i[14:12] == 3'b110 && instr_rdata_i[24:23] != 2'b0) || + (instr_rdata_i[14:12] == 3'b111 && instr_rdata_i[24:22] != 3'b0)) begin + illegal_insn_o = 1'b1; + end end 6'b01010_0: begin // cv.sll alu_operator_o = ALU_SLL; @@ -2289,6 +2289,11 @@ module cv32e40p_decoder instr_rdata_i[25] != 1'b0) begin illegal_insn_o = 1'b1; end + // Imm6 restrictions + if ((instr_rdata_i[14:12] == 3'b110 && instr_rdata_i[24:23] != 2'b0) || + (instr_rdata_i[14:12] == 3'b111 && instr_rdata_i[24:22] != 3'b0)) begin + illegal_insn_o = 1'b1; + end end 6'b01011_0: begin // cv.or alu_operator_o = ALU_OR; @@ -2425,6 +2430,11 @@ module cv32e40p_decoder end default: illegal_insn_o = 1'b1; endcase + // Imm6 restrictions + if ((instr_rdata_i[12] == 1'b0 && instr_rdata_i[24:20] != 5'b0) || + (instr_rdata_i[12] == 1'b1 && instr_rdata_i[24:21] != 4'b0)) begin + illegal_insn_o = 1'b1; + end end 6'b11000_0: begin // cv.shuffle, cv.shuffleI0 alu_operator_o = ALU_SHUF; @@ -2439,6 +2449,10 @@ module cv32e40p_decoder instr_rdata_i[25] != 1'b0) begin illegal_insn_o = 1'b1; end + // Imm6 restriction + if (instr_rdata_i[14:12] == 3'b110 && instr_rdata_i[24:21] != 4'b0) begin + illegal_insn_o = 1'b1; + end end 6'b11001_0, 6'b11010_0, diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_ex_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_ex_stage.sv index c51ef7f8..488a83dc 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_ex_stage.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_ex_stage.sv @@ -33,6 +33,7 @@ module cv32e40p_ex_stage import cv32e40p_pkg::*; import cv32e40p_apu_core_pkg::*; #( + parameter COREV_PULP = 0, parameter FPU = 0, parameter APU_NARGS_CPU = 3, parameter APU_WOP_CPU = 6, @@ -81,6 +82,8 @@ module cv32e40p_ex_stage input logic data_misaligned_ex_i, input logic data_misaligned_i, + input logic [1:0] ctrl_transfer_insn_in_dec_i, + // FPU signals output logic fpu_fflags_we_o, output logic [APU_NUSFLAGS_CPU-1:0] fpu_fflags_o, @@ -138,11 +141,13 @@ module cv32e40p_ex_stage // Output of EX stage pipeline output logic [ 5:0] regfile_waddr_wb_o, output logic regfile_we_wb_o, + output logic regfile_we_wb_power_o, output logic [31:0] regfile_wdata_wb_o, // Forwarding ports : to ID stage output logic [ 5:0] regfile_alu_waddr_fw_o, output logic regfile_alu_we_fw_o, + output logic regfile_alu_we_fw_power_o, output logic [31:0] regfile_alu_wdata_fw_o, // forward to RF and ID/EX pipe, ALU & MUL // To IF: Jump and branch target and decision @@ -190,22 +195,27 @@ module cv32e40p_ex_stage // ALU write port mux always_comb begin - regfile_alu_wdata_fw_o = '0; - regfile_alu_waddr_fw_o = '0; - regfile_alu_we_fw_o = '0; - wb_contention = 1'b0; + regfile_alu_wdata_fw_o = '0; + regfile_alu_waddr_fw_o = '0; + regfile_alu_we_fw_o = 1'b0; + regfile_alu_we_fw_power_o = 1'b0; + wb_contention = 1'b0; - // APU single cycle operations, and multicycle operations (>2cycles) are written back on ALU port + // APU single cycle operations, and multicycle operations (> 2cycles) are written back on ALU port if (apu_valid & (apu_singlecycle | apu_multicycle)) begin - regfile_alu_we_fw_o = 1'b1; - regfile_alu_waddr_fw_o = apu_waddr; - regfile_alu_wdata_fw_o = apu_result; + regfile_alu_we_fw_o = 1'b1; + regfile_alu_we_fw_power_o = 1'b1; + regfile_alu_waddr_fw_o = apu_waddr; + regfile_alu_wdata_fw_o = apu_result; if (regfile_alu_we_i & ~apu_en_i) begin wb_contention = 1'b1; end end else begin - regfile_alu_we_fw_o = regfile_alu_we_i & ~apu_en_i; // private fpu incomplete? + regfile_alu_we_fw_o = regfile_alu_we_i & ~apu_en_i; + regfile_alu_we_fw_power_o = (COREV_PULP == 0) ? regfile_alu_we_i & ~apu_en_i : + regfile_alu_we_i & ~apu_en_i & + mult_ready & alu_ready & lsu_ready_ex_i; regfile_alu_waddr_fw_o = regfile_alu_waddr_i; if (alu_en_i) regfile_alu_wdata_fw_o = alu_result; if (mult_en_i) regfile_alu_wdata_fw_o = mult_result; @@ -215,21 +225,24 @@ module cv32e40p_ex_stage // LSU write port mux always_comb begin - regfile_we_wb_o = 1'b0; - regfile_waddr_wb_o = regfile_waddr_lsu; - regfile_wdata_wb_o = lsu_rdata_i; - wb_contention_lsu = 1'b0; + regfile_we_wb_o = 1'b0; + regfile_we_wb_power_o = 1'b0; + regfile_waddr_wb_o = regfile_waddr_lsu; + regfile_wdata_wb_o = lsu_rdata_i; + wb_contention_lsu = 1'b0; if (regfile_we_lsu) begin - regfile_we_wb_o = 1'b1; + regfile_we_wb_o = 1'b1; + regfile_we_wb_power_o = (COREV_PULP == 0) ? 1'b1 : ~data_misaligned_ex_i & wb_ready_i; if (apu_valid & (!apu_singlecycle & !apu_multicycle)) begin wb_contention_lsu = 1'b1; end // APU two-cycle operations are written back on LSU port end else if (apu_valid & (!apu_singlecycle & !apu_multicycle)) begin - regfile_we_wb_o = 1'b1; - regfile_waddr_wb_o = apu_waddr; - regfile_wdata_wb_o = apu_result; + regfile_we_wb_o = 1'b1; + regfile_we_wb_power_o = 1'b1; + regfile_waddr_wb_o = apu_waddr; + regfile_wdata_wb_o = apu_result; end end @@ -371,11 +384,20 @@ module cv32e40p_ex_stage apu_result_q <= 'b0; apu_flags_q <= 'b0; end else begin - if (apu_rvalid_i && apu_multicycle && (data_misaligned_i || data_misaligned_ex_i || (data_req_i && regfile_alu_we_i) || (mulh_active && (mult_operator_i == MUL_H)))) begin + if (apu_rvalid_i && apu_multicycle && + (data_misaligned_i || data_misaligned_ex_i || + ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || + (mulh_active && (mult_operator_i == MUL_H)) || + ((ctrl_transfer_insn_in_dec_i == BRANCH_JALR) && + regfile_alu_we_i && ~apu_read_dep_for_jalr_o))) begin apu_rvalid_q <= 1'b1; apu_result_q <= apu_result_i; apu_flags_q <= apu_flags_i; - end else if (apu_rvalid_q && !(data_misaligned_i || data_misaligned_ex_i || ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || (mulh_active && (mult_operator_i == MUL_H)))) begin + end else if (apu_rvalid_q && !(data_misaligned_i || data_misaligned_ex_i || + ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || + (mulh_active && (mult_operator_i == MUL_H)) || + ((ctrl_transfer_insn_in_dec_i == BRANCH_JALR) && + regfile_alu_we_i && ~apu_read_dep_for_jalr_o))) begin apu_rvalid_q <= 1'b0; end end @@ -383,7 +405,12 @@ module cv32e40p_ex_stage assign apu_req_o = apu_req; assign apu_gnt = apu_gnt_i; - assign apu_valid = (apu_multicycle && (data_misaligned_i || data_misaligned_ex_i || ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || (mulh_active && (mult_operator_i == MUL_H)))) ? 1'b0 : (apu_rvalid_i || apu_rvalid_q); + assign apu_valid = (apu_multicycle && (data_misaligned_i || data_misaligned_ex_i || + ((data_req_i || data_rvalid_i) && regfile_alu_we_i) || + (mulh_active && (mult_operator_i == MUL_H)) || + ((ctrl_transfer_insn_in_dec_i == BRANCH_JALR) && + regfile_alu_we_i && ~apu_read_dep_for_jalr_o))) + ? 1'b0 : (apu_rvalid_i || apu_rvalid_q); assign apu_operands_o = apu_operands_i; assign apu_op_o = apu_op_i; assign apu_result = apu_rvalid_q ? apu_result_q : apu_result_i; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_fp_wrapper.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_fp_wrapper.sv index 042fa0f2..839d58aa 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_fp_wrapper.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_fp_wrapper.sv @@ -14,7 +14,7 @@ module cv32e40p_fp_wrapper import cv32e40p_apu_core_pkg::*; #( - parameter FPU_ADDMUL_LAT = 0, // Floating-Point ADDition/MULtiplication computing lane pipeline registers number + parameter FPU_ADDMUL_LAT = 0, // Floating-Point ADDition/MULtiplication computing lane pipeline registers number parameter FPU_OTHERS_LAT = 0 // Floating-Point COMParison/CONVersion computing lanes pipeline registers number ) ( // Clock and Reset @@ -111,7 +111,7 @@ module cv32e40p_fp_wrapper .int_fmt_i (fpnew_pkg::int_format_e'(fpu_int_fmt)), .vectorial_op_i(fpu_vec_op), .tag_i (1'b0), - .simd_mask_i ('b0), + .simd_mask_i (1'b0), .in_valid_i (apu_req_i), .in_ready_o (apu_gnt_o), .flush_i (1'b0), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_id_stage.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_id_stage.sv index 7811eabf..f323cbe5 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_id_stage.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_id_stage.sv @@ -70,6 +70,7 @@ module cv32e40p_id_stage output logic branch_in_ex_o, input logic branch_decision_i, output logic [31:0] jump_target_o, + output logic [ 1:0] ctrl_transfer_insn_in_dec_o, // IF and ID stage signals output logic clear_instr_valid_o, @@ -225,10 +226,12 @@ module cv32e40p_id_stage // Forward Signals input logic [5:0] regfile_waddr_wb_i, input logic regfile_we_wb_i, + input logic regfile_we_wb_power_i, input logic [31:0] regfile_wdata_wb_i, // From wb_stage: selects data from data memory, ex_stage result and sp rdata input logic [ 5:0] regfile_alu_waddr_fw_i, input logic regfile_alu_we_fw_i, + input logic regfile_alu_we_fw_power_i, input logic [31:0] regfile_alu_wdata_fw_i, // from ALU @@ -809,6 +812,9 @@ module cv32e40p_id_stage if (ctrl_transfer_target_mux_sel == JT_JALR) begin apu_read_regs[0] = regfile_addr_ra_id; apu_read_regs_valid[0] = 1'b1; + end else begin + apu_read_regs[0] = regfile_addr_ra_id; + apu_read_regs_valid[0] = 1'b0; end end // OP_A_CURRPC: OP_A_REGA_OR_FWD: begin @@ -948,12 +954,12 @@ module cv32e40p_id_stage // Write port a .waddr_a_i(regfile_waddr_wb_i), .wdata_a_i(regfile_wdata_wb_i), - .we_a_i (regfile_we_wb_i), + .we_a_i (regfile_we_wb_power_i), // Write port b .waddr_b_i(regfile_alu_waddr_fw_i), .wdata_b_i(regfile_alu_wdata_fw_i), - .we_b_i (regfile_alu_we_fw_i) + .we_b_i (regfile_alu_we_fw_power_i) ); @@ -1087,7 +1093,7 @@ module cv32e40p_id_stage .debug_wfi_no_sleep_i(debug_wfi_no_sleep), // jump/branches - .ctrl_transfer_insn_in_dec_o (ctrl_transfer_insn_in_dec), + .ctrl_transfer_insn_in_dec_o (ctrl_transfer_insn_in_dec_o), .ctrl_transfer_insn_in_id_o (ctrl_transfer_insn_in_id), .ctrl_transfer_target_mux_sel_o(ctrl_transfer_target_mux_sel), @@ -1187,7 +1193,7 @@ module cv32e40p_id_stage // jump/branch control .branch_taken_ex_i (branch_taken_ex), .ctrl_transfer_insn_in_id_i (ctrl_transfer_insn_in_id), - .ctrl_transfer_insn_in_dec_i(ctrl_transfer_insn_in_dec), + .ctrl_transfer_insn_in_dec_i(ctrl_transfer_insn_in_dec_o), // Interrupt signals .irq_wu_ctrl_i (irq_wu_ctrl), @@ -1508,9 +1514,13 @@ module cv32e40p_id_stage if (id_valid_o) begin // unstall the whole pipeline alu_en_ex_o <= alu_en; if (alu_en) begin - alu_operator_ex_o <= alu_operator; - alu_operand_a_ex_o <= alu_operand_a; - alu_operand_b_ex_o <= alu_operand_b; + alu_operator_ex_o <= alu_operator; + alu_operand_a_ex_o <= alu_operand_a; + if (alu_op_b_mux_sel == OP_B_REGB_OR_FWD && (alu_operator == ALU_CLIP || alu_operator == ALU_CLIPU)) begin + alu_operand_b_ex_o <= {1'b0, alu_operand_b[30:0]}; + end else begin + alu_operand_b_ex_o <= alu_operand_b; + end alu_operand_c_ex_o <= alu_operand_c; bmask_a_ex_o <= bmask_a_id; bmask_b_ex_o <= bmask_b_id; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_load_store_unit.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_load_store_unit.sv index 7c08ffe1..f9c4db4a 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_load_store_unit.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_load_store_unit.sv @@ -121,18 +121,18 @@ module cv32e40p_load_store_unit #( 2'b00: begin // Writing a word if (misaligned_st == 1'b0) begin // non-misaligned case case (data_addr_int[1:0]) - 2'b00: data_be = 4'b1111; - 2'b01: data_be = 4'b1110; - 2'b10: data_be = 4'b1100; - 2'b11: data_be = 4'b1000; + 2'b00: data_be = 4'b1111; + 2'b01: data_be = 4'b1110; + 2'b10: data_be = 4'b1100; + default: data_be = 4'b1000; endcase ; // case (data_addr_int[1:0]) end else begin // misaligned case case (data_addr_int[1:0]) - 2'b00: data_be = 4'b0000; // this is not used, but included for completeness - 2'b01: data_be = 4'b0001; - 2'b10: data_be = 4'b0011; - 2'b11: data_be = 4'b0111; + 2'b01: data_be = 4'b0001; + 2'b10: data_be = 4'b0011; + 2'b11: data_be = 4'b0111; + default: data_be = 4'b0000; // this is not used, but included for completeness endcase ; // case (data_addr_int[1:0]) end @@ -141,10 +141,10 @@ module cv32e40p_load_store_unit #( 2'b01: begin // Writing a half word if (misaligned_st == 1'b0) begin // non-misaligned case case (data_addr_int[1:0]) - 2'b00: data_be = 4'b0011; - 2'b01: data_be = 4'b0110; - 2'b10: data_be = 4'b1100; - 2'b11: data_be = 4'b1000; + 2'b00: data_be = 4'b0011; + 2'b01: data_be = 4'b0110; + 2'b10: data_be = 4'b1100; + default: data_be = 4'b1000; endcase ; // case (data_addr_int[1:0]) end else begin // misaligned case @@ -154,10 +154,10 @@ module cv32e40p_load_store_unit #( 2'b10, 2'b11: begin // Writing a byte case (data_addr_int[1:0]) - 2'b00: data_be = 4'b0001; - 2'b01: data_be = 4'b0010; - 2'b10: data_be = 4'b0100; - 2'b11: data_be = 4'b1000; + 2'b00: data_be = 4'b0001; + 2'b01: data_be = 4'b0010; + 2'b10: data_be = 4'b0100; + default: data_be = 4'b1000; endcase ; // case (data_addr_int[1:0]) end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_register_file_latch.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_register_file_latch.sv index d8e2f4aa..57383e6a 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_register_file_latch.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_register_file_latch.sv @@ -172,8 +172,8 @@ module cv32e40p_register_file #( mem[0] = '0; for (k = 1; k < NUM_WORDS; k++) begin : w_WordIter - if (~rst_n) mem[k] = '0; - else if (mem_clocks[k] == 1'b1) mem[k] = waddr_onehot_b_q[k] ? wdata_b_q : wdata_a_q; + if (~rst_n) mem[k] <= '0; + else if (mem_clocks[k] == 1'b1) mem[k] <= waddr_onehot_b_q[k] ? wdata_b_q : wdata_a_q; end end @@ -182,9 +182,9 @@ module cv32e40p_register_file #( always_latch begin : latch_wdata_fp if (FPU == 1) begin for (l = 0; l < NUM_FP_WORDS; l++) begin : w_WordIter - if (~rst_n) mem_fp[l] = '0; + if (~rst_n) mem_fp[l] <= '0; else if (mem_clocks[l+NUM_WORDS] == 1'b1) - mem_fp[l] = waddr_onehot_b_q[l+NUM_WORDS] ? wdata_b_q : wdata_a_q; + mem_fp[l] <= waddr_onehot_b_q[l+NUM_WORDS] ? wdata_b_q : wdata_a_q; end end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_top.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_top.sv index 7ddd2d5a..43eee77b 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_top.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40p/rtl/cv32e40p_top.sv @@ -1,15 +1,27 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -// Top file instantiating a CV32E40P core and an optional FPU -// Contributor: Davide Schiavone +// Copyright 2024 Dolphin Design +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); +// you may not use this file except in compliance with the License, or, +// at your option, the Apache License version 2.0. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +///////////////////////////////////////////////////////////////////////////// +// // +// Contributors: Pascal Gouedo, Dolphin Design // +// // +// Description: Top level module of CV32E40P instantiating the Core and // +// an optional CVFPU with its clock gating cell. // +// // +///////////////////////////////////////////////////////////////////////////// module cv32e40p_top #( parameter COREV_PULP = 0, // PULP ISA Extension (incl. custom CSRs and hardware loop, excl. cv.elw) @@ -70,7 +82,7 @@ module cv32e40p_top #( import cv32e40p_apu_core_pkg::*; // Core to FPU - logic clk; + logic apu_busy; logic apu_req; logic [ APU_NARGS_CPU-1:0][31:0] apu_operands; logic [ APU_WOP_CPU-1:0] apu_op; @@ -82,6 +94,8 @@ module cv32e40p_top #( logic [ 31:0] apu_rdata; logic [APU_NUSFLAGS_CPU-1:0] apu_rflags; + logic apu_clk_en, apu_clk; + // Instantiate the Core cv32e40p_core #( .COREV_PULP (COREV_PULP), @@ -119,6 +133,7 @@ module cv32e40p_top #( .data_wdata_o (data_wdata_o), .data_rdata_i (data_rdata_i), + .apu_busy_o (apu_busy), .apu_req_o (apu_req), .apu_gnt_i (apu_gnt), .apu_operands_o(apu_operands), @@ -143,12 +158,15 @@ module cv32e40p_top #( generate if (FPU) begin : fpu_gen + + assign apu_clk_en = apu_req | apu_busy; + // FPU clock gate cv32e40p_clock_gate core_clock_gate_i ( .clk_i (clk_i), - .en_i (!core_sleep_o), + .en_i (apu_clk_en), .scan_cg_en_i(scan_cg_en_i), - .clk_o (clk) + .clk_o (apu_clk) ); // Instantiate the FPU wrapper @@ -156,7 +174,7 @@ module cv32e40p_top #( .FPU_ADDMUL_LAT(FPU_ADDMUL_LAT), .FPU_OTHERS_LAT(FPU_OTHERS_LAT) ) fp_wrapper_i ( - .clk_i (clk), + .clk_i (apu_clk), .rst_ni (rst_ni), .apu_req_i (apu_req), .apu_gnt_o (apu_gnt), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40x.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40x.core index 70a248de..7a12b181 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40x.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cv32e40x.core @@ -67,3 +67,4 @@ targets: filesets: - files_rtl - target_sim? (files_clk_gate) + - target_sim_sc? (files_clk_gate) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.lock.hjson index d1cc1ce7..fc70c877 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.lock.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.lock.hjson @@ -8,7 +8,7 @@ { upstream: { - url: https://github.com/davideschiavone/cve2.git - rev: 5039e60cdea6a76282576ca7e93a35ee9a3ff2e9 + url: https://github.com/openhwgroup/cve2.git + rev: 7f3bb9fcb28e55b227c966734d8e81ddef58b7e3 } } diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.vendor.hjson index 8c860069..28cb1df6 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.vendor.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/openhwgroup_cve2.vendor.hjson @@ -6,22 +6,43 @@ target_dir: "openhwgroup_cv32e20", upstream: { - url: "https://github.com/davideschiavone/cve2.git", - rev: "5039e60cdea6a76282576ca7e93a35ee9a3ff2e9", + url: "https://github.com/openhwgroup/cve2.git", + rev: "7f3bb9fcb28e55b227c966734d8e81ddef58b7e3", }, + patch_dir: "patches/openhwgroup_cv32e20", + exclude_from_upstream: [ "ci", "dv", "examples", "formal", ".dir-locals.el", - "cv32e40p_manifest.flist", "doc", "shared", "syn", "util", - "vendor", + "scripts", + "vendor/eembc_coremark", + "vendor/eembc_coremark.lock.hjson", + "vendor/google_riscv-dv", + "vendor/google_riscv-dv.lock.hjson", + "vendor/google_riscv-dv.vendor.hjson", + "vendor/lowrisc_ip.lock.hjson", + "vendor/lowrisc_ip.vendor.hjson", + "vendor/patches", + "vendor/lowrisc_ip/ip" + "vendor/lowrisc_ip/lint" + "vendor/lowrisc_ip/util" + "vendor/lowrisc_ip/dv/tools", + "vendor/lowrisc_ip/dv/verilator", + "vendor/lowrisc_ip/dv/sv/common_ifs", + "vendor/lowrisc_ip/dv/sv/csr_utils", + "vendor/lowrisc_ip/dv/sv/dv_base_reg", + "vendor/lowrisc_ip/dv/sv/dv_lib", + "vendor/lowrisc_ip/dv/sv/mem_bkdr_util", + "vendor/lowrisc_ip/dv/sv/mem_model", + "vendor/lowrisc_ip/dv/sv/str_utils", ".github", "azure-pipelines.yml", "check_tool_requirements.core", diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/esl_epfl_cv32e40px/0001-vendor-cv32e40px-Re-vendor.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/esl_epfl_cv32e40px/0001-vendor-cv32e40px-Re-vendor.patch deleted file mode 100644 index 28ab47b1..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/esl_epfl_cv32e40px/0001-vendor-cv32e40px-Re-vendor.patch +++ /dev/null @@ -1,44 +0,0 @@ -diff --git a/rtl/cv32e40px_cs_registers.sv b/rtl/cv32e40px_cs_registers.sv -index 1f1d56b..cdc6433 100644 ---- a/rtl/cv32e40px_cs_registers.sv -+++ b/rtl/cv32e40px_cs_registers.sv -@@ -1450,7 +1450,7 @@ module cv32e40px_cs_registers - // minstret is located at index 2 - // Programable HPM counters start at index 3 - if ((cnt_gidx == 1) || (cnt_gidx >= (NUM_MHPMCOUNTERS + 3))) begin : gen_non_implemented -- assign mhpmcounter_q[cnt_gidx] = 'b0; -+ always_ff @(posedge clk) mhpmcounter_q[cnt_gidx] <= 'b0; - end else begin : gen_implemented - always_ff @(posedge clk, negedge rst_n) - if (!rst_n) begin -@@ -1478,10 +1478,10 @@ module cv32e40px_cs_registers - for (evt_gidx = 0; evt_gidx < 32; evt_gidx++) begin : gen_mhpmevent - // programable HPM events start at index3 - if ((evt_gidx < 3) || (evt_gidx >= (NUM_MHPMCOUNTERS + 3))) begin : gen_non_implemented -- assign mhpmevent_q[evt_gidx] = 'b0; -+ always_ff @(posedge clk) mhpmevent_q[evt_gidx] <= 'b0; - end else begin : gen_implemented - if (NUM_HPM_EVENTS < 32) begin : gen_tie_off -- assign mhpmevent_q[evt_gidx][31:NUM_HPM_EVENTS] = 'b0; -+ always_ff @(posedge clk) mhpmevent_q[evt_gidx][31:NUM_HPM_EVENTS] <= 'b0; - end - always_ff @(posedge clk, negedge rst_n) - if (!rst_n) mhpmevent_q[evt_gidx][NUM_HPM_EVENTS-1:0] <= 'b0; -@@ -1499,7 +1499,7 @@ module cv32e40px_cs_registers - (en_gidx == 1) || - (en_gidx >= (NUM_MHPMCOUNTERS+3) ) ) - begin : gen_non_implemented -- assign mcounteren_q[en_gidx] = 'b0; -+ always_ff @(posedge clk) mcounteren_q[en_gidx] <= 'b0; - end else begin : gen_implemented - always_ff @(posedge clk, negedge rst_n) - if (!rst_n) mcounteren_q[en_gidx] <= 'b0; // default disable -@@ -1514,7 +1514,7 @@ module cv32e40px_cs_registers - generate - for (inh_gidx = 0; inh_gidx < 32; inh_gidx++) begin : gen_mcountinhibit - if ((inh_gidx == 1) || (inh_gidx >= (NUM_MHPMCOUNTERS + 3))) begin : gen_non_implemented -- assign mcountinhibit_q[inh_gidx] = 'b0; -+ always_ff @(posedge clk) mcountinhibit_q[inh_gidx] <= 'b0; - end else begin : gen_implemented - always_ff @(posedge clk, negedge rst_n) - if (!rst_n) mcountinhibit_q[inh_gidx] <= 'b1; // default disable diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/lowrisc_opentitan/uartdpi.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/lowrisc_opentitan/uartdpi.patch index 94b7d2b8..54c13229 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/lowrisc_opentitan/uartdpi.patch +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/lowrisc_opentitan/uartdpi.patch @@ -1,5 +1,5 @@ diff --git a/hw/dv/dpi/uartdpi/uartdpi.h b/hw/dv/dpi/uartdpi/uartdpi.h -index 29d50a5a2..2149fb115 100644 +index 29d50a5a28..2149fb1155 100644 --- a/hw/dv/dpi/uartdpi/uartdpi.h +++ b/hw/dv/dpi/uartdpi/uartdpi.h @@ -5,7 +5,9 @@ @@ -21,21 +21,23 @@ index 29d50a5a2..2149fb115 100644 +#endif #endif // OPENTITAN_HW_DV_DPI_UARTDPI_UARTDPI_H_ diff --git a/hw/dv/dpi/uartdpi/uartdpi.sv b/hw/dv/dpi/uartdpi/uartdpi.sv -index 97fae4767..07c75cf8e 100644 +index 97fae47674..2be4df54ff 100644 --- a/hw/dv/dpi/uartdpi/uartdpi.sv +++ b/hw/dv/dpi/uartdpi/uartdpi.sv -@@ -82,11 +82,14 @@ module uartdpi #( +@@ -82,11 +82,16 @@ module uartdpi #( end end - +`ifndef VCS +`ifndef MODELSIM ++`ifndef XCELIUM initial begin // Prevent falling edges of rx_i before reset causing spurious characters seen_reset = 0; end +`endif ++`endif +`endif // RX diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_assert.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_assert.patch new file mode 100644 index 00000000..4ac84c15 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_assert.patch @@ -0,0 +1,12 @@ +diff --git a/rtl/cve2_top.sv b/rtl/cve2_top.sv +index 34af60b7..00c38a4a 100644 +--- a/rtl/cve2_top.sv ++++ b/rtl/cve2_top.sv +@@ -265,7 +265,6 @@ module cve2_top import cve2_pkg::*; #( + + `ASSERT_KNOWN(IbexDataGntX, data_gnt_i) + `ASSERT_KNOWN(IbexDataRValidX, data_rvalid_i) +- `ASSERT_KNOWN_IF(IbexDataRPayloadX, {data_rdata_i, data_err_i}, data_rvalid_i) + + `ASSERT_KNOWN(IbexIrqX, {irq_software_i, irq_timer_i, irq_external_i, irq_fast_i, irq_nm_i}) + diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_core.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_core.patch new file mode 100644 index 00000000..9727dec1 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/openhwgroup_cv32e20/cv32e20_core.patch @@ -0,0 +1,12 @@ +diff --git a/cve2_top.core b/cve2_top.core +index cb4e23b4..0d9d2c5c 100644 +--- a/cve2_top.core ++++ b/cve2_top.core +@@ -75,6 +75,7 @@ targets: + - tool_veriblelint ? (files_lint_verible) + - files_rtl + - target_sim ? (files_clk_gate) ++ - target_sim_sc ? (files_clk_gate) + toplevel: cve2_top + parameters: + - tool_vivado ? (FPGA_XILINX=true) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/pulp_platform_common_cells/clk_mux_glitch_free.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/pulp_platform_common_cells/clk_mux_glitch_free.patch new file mode 100644 index 00000000..3e5ccb84 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/pulp_platform_common_cells/clk_mux_glitch_free.patch @@ -0,0 +1,13 @@ +diff --git a/src/clk_mux_glitch_free.sv b/src/clk_mux_glitch_free.sv +index e0eb5cd..5193742 100644 +--- a/src/clk_mux_glitch_free.sv ++++ b/src/clk_mux_glitch_free.sv +@@ -191,7 +191,7 @@ endmodule + + // Helper Module to generate an N-input clock OR-gate from a tree of tc_clk_or2 cells. + module clk_or_tree #( +- parameter int unsigned NUM_INPUTS ++ parameter int unsigned NUM_INPUTS = 1 + ) ( + input logic [NUM_INPUTS-1:0] clks_i, + output logic clk_o diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/pulp_platform_riscv_dbg/fix_nrharts.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/pulp_platform_riscv_dbg/fix_nrharts.patch new file mode 100644 index 00000000..ea96dec8 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/pulp_platform_riscv_dbg/fix_nrharts.patch @@ -0,0 +1,28 @@ +diff --git a/src/dm_csrs.sv b/src/dm_csrs.sv +index 59d1c90..2338028 100644 +--- a/src/dm_csrs.sv ++++ b/src/dm_csrs.sv +@@ -547,7 +547,7 @@ module dm_csrs #( + if (!dmcontrol_q.resumereq && dmcontrol_d.resumereq) begin + clear_resumeack_o = 1'b1; + end +- if (dmcontrol_q.resumereq && resumeack_i) begin ++ if (dmcontrol_q.resumereq && resumeack_i[selected_hart]) begin + dmcontrol_d.resumereq = 1'b0; + end + // static values for dcsr +diff --git a/src/dm_mem.sv b/src/dm_mem.sv +index 9ff3c86..8f97bec 100755 +--- a/src/dm_mem.sv ++++ b/src/dm_mem.sv +@@ -535,8 +535,8 @@ module dm_mem #( + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin +- halted_q <= 1'b0; +- resuming_q <= 1'b0; ++ halted_q <= '0; ++ resuming_q <= '0; + end else begin + halted_q <= SelectableHarts & halted_d; + resuming_q <= SelectableHarts & resuming_d; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/0002-spiflash_valueargs.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/0002-spiflash_valueargs.patch deleted file mode 100644 index 5b525705..00000000 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/0002-spiflash_valueargs.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/picosoc/spiflash.v b/picosoc/spiflash.v -index 22b337b..e0eef9f 100644 ---- a/picosoc/spiflash.v -+++ b/picosoc/spiflash.v -@@ -102,8 +102,14 @@ module spiflash ( - reg [7:0] memory [0:16*1024*1024-1]; - - reg [1023:0] firmware_file; -+ reg result; -+ integer i; -+ - initial begin -- if (!$value$plusargs("firmware=%s", firmware_file)) -+ for (i=0;i<=16*1024*1024;i=i+1) -+ memory[i] = '0; -+ result = $value$plusargs("firmware=%s", firmware_file); -+ if (!result) - firmware_file = "firmware.hex"; - $readmemh(firmware_file, memory); - end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/spiflash.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/spiflash.patch new file mode 100644 index 00000000..3583151d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/spiflash.patch @@ -0,0 +1,113 @@ +diff --git a/picosoc/spiflash.v b/picosoc/spiflash.v +index 22b337b..55342b5 100644 +--- a/picosoc/spiflash.v ++++ b/picosoc/spiflash.v +@@ -26,7 +26,7 @@ + // updates output signals 1ns after the SPI clock edge. + // + // Supported commands: +-// AB, B9, FF, 03, BB, EB, ED ++// AB, B9, FF, 03, BB, EB, ED, 06, 02, 32 + // + // Well written SPI flash data sheets: + // Cypress S25FL064L http://www.cypress.com/file/316661/download +@@ -61,6 +61,8 @@ module spiflash ( + reg spi_io_vld; + + reg powered_up = 0; ++ reg write_enable = 0; ++ reg write_enable_reset = 0; + + localparam [3:0] mode_spi = 1; + localparam [3:0] mode_dspi_rd = 2; +@@ -102,8 +104,14 @@ module spiflash ( + reg [7:0] memory [0:16*1024*1024-1]; + + reg [1023:0] firmware_file; ++ reg result; ++ integer i; ++ + initial begin +- if (!$value$plusargs("firmware=%s", firmware_file)) ++ for (i=0;i<=16*1024*1024;i=i+1) ++ memory[i] = 8'h00; ++ result = $value$plusargs("firmware=%s", firmware_file); ++ if (!result) + firmware_file = "firmware.hex"; + $readmemh(firmware_file, memory); + end +@@ -123,6 +131,9 @@ module spiflash ( + + if (spi_cmd == 8'h ff) + xip_cmd = 0; ++ ++ if (spi_cmd == 8'h 06) ++ write_enable = 1; + end + + if (powered_up && spi_cmd == 'h 03) begin +@@ -141,6 +152,25 @@ module spiflash ( + end + end + ++ if (powered_up && write_enable && spi_cmd == 'h 02) begin ++ if (bytecount == 1) ++ write_enable_reset = 1; ++ ++ if (bytecount == 2) ++ spi_addr[23:16] = buffer; ++ ++ if (bytecount == 3) ++ spi_addr[15:8] = buffer; ++ ++ if (bytecount == 4) ++ spi_addr[7:0] = buffer; ++ ++ if (bytecount >= 5 && bytecount <= 260) begin ++ memory[spi_addr] = buffer; ++ spi_addr = spi_addr + 1; ++ end ++ end ++ + if (powered_up && spi_cmd == 'h bb) begin + if (bytecount == 1) + mode = mode_dspi_rd; +@@ -191,6 +221,27 @@ module spiflash ( + end + end + ++ if (powered_up && write_enable && spi_cmd == 'h 32) begin ++ if (bytecount == 1) ++ write_enable_reset = 1; ++ ++ if (bytecount == 2) ++ spi_addr[23:16] = buffer; ++ ++ if (bytecount == 3) ++ spi_addr[15:8] = buffer; ++ ++ if (bytecount == 4) begin ++ spi_addr[7:0] = buffer; ++ mode = mode_qspi_rd; ++ end ++ ++ if (bytecount >= 5 && bytecount <= 260) begin ++ memory[spi_addr] = buffer; ++ spi_addr = spi_addr + 1; ++ end ++ end ++ + if (powered_up && spi_cmd == 'h ed) begin + if (bytecount == 1) + next_mode = mode_qspi_ddr_rd; +@@ -268,6 +319,10 @@ module spiflash ( + $display(""); + $fflush; + end ++ if (write_enable_reset) begin ++ write_enable = 0; ++ write_enable_reset = 0; ++ end + buffer = 0; + bitcount = 0; + bytecount = 0; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/0001-async.-lowactive-reset.patch b/hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/spimemio.patch similarity index 100% rename from hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/0001-async.-lowactive-reset.patch rename to hw/vendor/esl_epfl_x_heep/hw/vendor/patches/yosyshq_picorv32/spimemio.patch diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_common_cells/src/clk_mux_glitch_free.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_common_cells/src/clk_mux_glitch_free.sv index e0eb5cdc..51937424 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_common_cells/src/clk_mux_glitch_free.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_common_cells/src/clk_mux_glitch_free.sv @@ -191,7 +191,7 @@ endmodule // Helper Module to generate an N-input clock OR-gate from a tree of tc_clk_or2 cells. module clk_or_tree #( - parameter int unsigned NUM_INPUTS + parameter int unsigned NUM_INPUTS = 1 ) ( input logic [NUM_INPUTS-1:0] clks_i, output logic clk_o diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.lock.hjson index bc1ec555..de40549d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.lock.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/pulp-platform/fpnew.git - rev: d6e581628f3517a1fb1257507d3214e599f7859d + rev: 79e453139072df42c9ec8f697132ba485d74e23d } } diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.vendor.hjson index 7ae0d55c..1fe09cca 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.vendor.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_fpnew.vendor.hjson @@ -7,7 +7,7 @@ upstream: { url: "https://github.com/pulp-platform/fpnew.git", - rev: "d6e581628f3517a1fb1257507d3214e599f7859d", + rev: "79e453139072df42c9ec8f697132ba485d74e23d", }, exclude_from_upstream: [ diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_gpio.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_gpio.core index 630f318a..2d79c611 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_gpio.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_gpio.core @@ -39,8 +39,10 @@ targets: - rtl - "gpio-test? (testbench)" - target_sim? (clock-gate) + - target_sim_sc? (clock-gate) - target_asic_synthesis? (clock-gate) - target_asic_yosys_synthesis? (clock-gate) - target_nexys-a7-100t? (no-clock-gate) - target_pynq-z2? (no-clock-gate) - target_pynq-z2-arm-emulation? (no-clock-gate) + - target_zcu104? (no-clock-gate) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_register_interface.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_register_interface.core index b7883672..383b7eac 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_register_interface.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_register_interface.core @@ -14,6 +14,7 @@ filesets: - pulp_platform_register_interface/src/reg_intf.sv - pulp_platform_register_interface/src/periph_to_reg.sv - pulp_platform_register_interface/src/reg_demux.sv + - pulp_platform_register_interface/src/reg_mux.sv - pulp_platform_register_interface/src/reg_to_tlul.sv file_type: systemVerilogSource diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.lock.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.lock.hjson index 3f13125e..f74356a1 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.lock.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/pulp-platform/riscv-dbg.git - rev: 69be5ddc03ea1688c0eab47d6ed9d0e8725beda1 + rev: 358f90110220adf7a083f8b65d157e836d706236 } } diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.vendor.hjson b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.vendor.hjson index 2ec8e7e9..9b0fb8b9 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.vendor.hjson +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg.vendor.hjson @@ -7,9 +7,11 @@ upstream: { url: "https://github.com/pulp-platform/riscv-dbg.git", - rev: "69be5ddc03ea1688c0eab47d6ed9d0e8725beda1", + rev: "358f90110220adf7a083f8b65d157e836d706236", }, + patch_dir: "patches/pulp_platform_riscv_dbg", + exclude_from_upstream: [ "ci", "tb", diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/CHANGELOG.md b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/CHANGELOG.md index 35db8983..99dab605 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/CHANGELOG.md +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/CHANGELOG.md @@ -4,7 +4,40 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased] +## Unreleased + +## [0.8.1] - 2023-10-01 +### Changed +- debug_rom: Add rst + +## [0.8.0] - 2023-04-05 +### Fixed +- dm_csrs: Fix W1C behavior of `sberror` (#155) [@andreaskurth](https://github.com/andreaskurth) +- gen_rom.py: Port to python3 (#152) [@andreaskurth](https://github.com/andreaskurth) + +### Added +- `xprop_off` to Xprop-incompatible processes (#151) [@andreaskurth](https://github.com/andreaskurth) + +## [0.7.0] - 2022-11-02 +### Fixed +- 64-bit unaligned accesses (#145) [@creinwar](https://github.com/creinwar) +- Various minor testbench fixes (#146) + +### Changed +- Halted, Resume and Exception addresses are now aligned to 8 bytes + +## [0.6.0] - 2022-10-11 +### Fixed +- Testbench build (#141, #142) +- remote_bitbang tb build for newer GCC versions (#133) [@epsilon537](https://github.com/noytzach) +- 32-bit access to abstract data (#27) [@Silabs-ArjanB](https://github.com/Silabs-ArjanB) +- `dm_mem`: Clear state of hart upon ndmreset (#140) [@andreaskurth](https://github.com/andreaskurth) +- `dmi_jtag_tap`: Bring all state to initial value in test-logic-reset (#139) [@andreaskurth](https://github.com/andreaskurth) +- Fix DMI response when command or SBA are busy (#138) [@andreaskurth](https://github.com/andreaskurth) + +### Changed +- Add expontential backoff to read_dmi in tb (#134) [@colluca](https://github.com/colluca) + ## [0.5.1] - 2022-04-12 ### Fixed - Fixed dmi_bscane_tap top-level signals diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/Makefile b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/Makefile index b23370aa..931e2532 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/Makefile +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/Makefile @@ -5,7 +5,7 @@ debug_rom = debug_rom.sv debug_rom_one_scratch.sv GCC?=riscv64-unknown-elf-gcc OBJCOPY?=riscv64-unknown-elf-objcopy OBJDUMP?=riscv64-unknown-elf-objdump -PYTHON?=python +PYTHON?=python3 all: $(debug_rom) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.S b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.S index 2989c7e8..7126ae46 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.S +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.S @@ -6,9 +6,9 @@ // # define SND_SCRATCH 1 // These are implementation-specific addresses in the Debug Module #define HALTED 0x100 -#define GOING 0x104 -#define RESUMING 0x108 -#define EXCEPTION 0x10C +#define GOING 0x108 +#define RESUMING 0x110 +#define EXCEPTION 0x118 // Region of memory where each hart has 1 // byte to read. @@ -26,10 +26,13 @@ entry: jal zero, _entry + nop resume: jal zero, _resume + nop exception: jal zero, _exception + nop diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.h b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.h index b4f2d35a..9e1d73d2 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.h +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.h @@ -1,11 +1,14 @@ // Auto-generated code -const int reset_vec_size = 38; +const int reset_vec_size = 40; uint32_t reset_vec[reset_vec_size] = { - 0x00c0006f, - 0x07c0006f, - 0x04c0006f, + 0x0180006f, + 0x00000013, + 0x0840006f, + 0x00000013, + 0x0500006f, + 0x00000013, 0x0ff0000f, 0x7b241073, 0x7b351073, @@ -22,23 +25,22 @@ uint32_t reset_vec[reset_vec_size] = { 0x00a40433, 0x40044403, 0x00247413, - 0xfa041ce3, + 0xfa0418e3, 0xfd5ff06f, 0x00000517, 0x00c55513, 0x00c51513, - 0x10052623, + 0x10052c23, 0x7b302573, 0x7b202473, 0x00100073, - 0x10052223, + 0x10052423, 0x7b302573, 0x7b202473, - 0xa85ff06f, + 0xa79ff06f, 0xf1402473, - 0x10852423, + 0x10852823, 0x7b302573, 0x7b202473, - 0x7b200073, - 0x00000000 + 0x7b200073 }; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.sv index 0299db6b..ac10eeea 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom.sv @@ -16,41 +16,47 @@ // Auto-generated code module debug_rom ( input logic clk_i, + input logic rst_ni, input logic req_i, input logic [63:0] addr_i, output logic [63:0] rdata_o ); - localparam int unsigned RomSize = 19; + localparam int unsigned RomSize = 20; logic [RomSize-1:0][63:0] mem; assign mem = { - 64'h00000000_7b200073, + 64'h7b200073_7b202473, + 64'h7b302573_10852823, + 64'hf1402473_a79ff06f, 64'h7b202473_7b302573, - 64'h10852423_f1402473, - 64'ha85ff06f_7b202473, - 64'h7b302573_10052223, - 64'h00100073_7b202473, - 64'h7b302573_10052623, - 64'h00c51513_00c55513, - 64'h00000517_fd5ff06f, - 64'hfa041ce3_00247413, - 64'h40044403_00a40433, - 64'hf1402473_02041c63, - 64'h00147413_40044403, - 64'h00a40433_10852023, - 64'hf1402473_00c51513, + 64'h10052423_00100073, + 64'h7b202473_7b302573, + 64'h10052c23_00c51513, 64'h00c55513_00000517, - 64'h7b351073_7b241073, - 64'h0ff0000f_04c0006f, - 64'h07c0006f_00c0006f + 64'hfd5ff06f_fa0418e3, + 64'h00247413_40044403, + 64'h00a40433_f1402473, + 64'h02041c63_00147413, + 64'h40044403_00a40433, + 64'h10852023_f1402473, + 64'h00c51513_00c55513, + 64'h00000517_7b351073, + 64'h7b241073_0ff0000f, + 64'h00000013_0500006f, + 64'h00000013_0840006f, + 64'h00000013_0180006f }; - logic [$clog2(RomSize)-1:0] addr_q; + logic [$clog2(RomSize)-1:0] addr_d, addr_q; + + assign addr_d = req_i ? addr_i[$clog2(RomSize)-1+3:3] : addr_q; - always_ff @(posedge clk_i) begin - if (req_i) begin - addr_q <= addr_i[$clog2(RomSize)-1+3:3]; + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + addr_q <= '0; + end else begin + addr_q <= addr_d; end end @@ -59,7 +65,7 @@ module debug_rom ( always_comb begin : p_outmux rdata_o = '0; if (addr_q < $clog2(RomSize)'(RomSize)) begin - rdata_o = mem[addr_q]; + rdata_o = mem[addr_q]; end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.h b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.h index 625d66a0..d4539714 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.h +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.h @@ -1,11 +1,14 @@ // Auto-generated code -const int reset_vec_size = 26; +const int reset_vec_size = 28; uint32_t reset_vec[reset_vec_size] = { - 0x00c0006f, - 0x0500006f, - 0x0340006f, + 0x0180006f, + 0x00000013, + 0x0580006f, + 0x00000013, + 0x0380006f, + 0x00000013, 0x0ff0000f, 0x7b241073, 0xf1402473, @@ -16,17 +19,16 @@ uint32_t reset_vec[reset_vec_size] = { 0xf1402473, 0x40044403, 0x00247413, - 0xfc0418e3, + 0xfc0414e3, 0xfddff06f, - 0x10002623, + 0x10002c23, 0x7b202473, 0x00100073, - 0x10002223, + 0x10002423, 0x7b202473, - 0xab1ff06f, + 0xaa5ff06f, 0xf1402473, - 0x10802423, + 0x10802823, 0x7b202473, - 0x7b200073, - 0x00000000 + 0x7b200073 }; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.sv index af7e67c7..3cd2d9e2 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/debug_rom_one_scratch.sv @@ -16,35 +16,41 @@ // Auto-generated code module debug_rom_one_scratch ( input logic clk_i, + input logic rst_ni, input logic req_i, input logic [63:0] addr_i, output logic [63:0] rdata_o ); - localparam int unsigned RomSize = 13; + localparam int unsigned RomSize = 14; logic [RomSize-1:0][63:0] mem; assign mem = { - 64'h00000000_7b200073, - 64'h7b202473_10802423, - 64'hf1402473_ab1ff06f, - 64'h7b202473_10002223, - 64'h00100073_7b202473, - 64'h10002623_fddff06f, - 64'hfc0418e3_00247413, - 64'h40044403_f1402473, - 64'h02041263_00147413, - 64'h40044403_10802023, - 64'hf1402473_7b241073, - 64'h0ff0000f_0340006f, - 64'h0500006f_00c0006f + 64'h7b200073_7b202473, + 64'h10802823_f1402473, + 64'haa5ff06f_7b202473, + 64'h10002423_00100073, + 64'h7b202473_10002c23, + 64'hfddff06f_fc0414e3, + 64'h00247413_40044403, + 64'hf1402473_02041263, + 64'h00147413_40044403, + 64'h10802023_f1402473, + 64'h7b241073_0ff0000f, + 64'h00000013_0380006f, + 64'h00000013_0580006f, + 64'h00000013_0180006f }; - logic [$clog2(RomSize)-1:0] addr_q; + logic [$clog2(RomSize)-1:0] addr_d, addr_q; - always_ff @(posedge clk_i) begin - if (req_i) begin - addr_q <= addr_i[$clog2(RomSize)-1+3:3]; + assign addr_d = req_i ? addr_i[$clog2(RomSize)-1+3:3] : addr_q; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + addr_q <= '0; + end else begin + addr_q <= addr_d; end end @@ -53,7 +59,7 @@ module debug_rom_one_scratch ( always_comb begin : p_outmux rdata_o = '0; if (addr_q < $clog2(RomSize)'(RomSize)) begin - rdata_o = mem[addr_q]; + rdata_o = mem[addr_q]; end end diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/gen_rom.py b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/gen_rom.py index b8cb60bc..a34efc5d 100755 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/gen_rom.py +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/debug_rom/gen_rom.py @@ -43,6 +43,7 @@ module = """\ module $filename ( input logic clk_i, + input logic rst_ni, input logic req_i, input logic [63:0] addr_i, output logic [63:0] rdata_o @@ -55,11 +56,15 @@ $content }; - logic [$$clog2(RomSize)-1:0] addr_q; + logic [$$clog2(RomSize)-1:0] addr_d, addr_q; - always_ff @(posedge clk_i) begin - if (req_i) begin - addr_q <= addr_i[$$clog2(RomSize)-1+3:3]; + assign addr_d = req_i ? addr_i[$$clog2(RomSize)-1+3:3] : addr_q; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + addr_q <= '0; + end else begin + addr_q <= addr_d; end end @@ -68,7 +73,7 @@ always_comb begin : p_outmux rdata_o = '0; if (addr_q < $$clog2(RomSize)'(RomSize)) begin - rdata_o = mem[addr_q]; + rdata_o = mem[addr_q]; end end @@ -88,9 +93,8 @@ def read_bin(): with open(filename + ".img", 'rb') as f: - rom = binascii.hexlify(f.read()) - rom = map(''.join, zip(rom[::2], rom[1::2])) - + rom = bytes.hex(f.read()) + rom = list(map(''.join, zip(rom[::2], rom[1::2]))) # align to 64 bit align = (int((len(rom) + 7) / 8 )) * 8; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/doc/debug-system.md b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/doc/debug-system.md index 1beca7df..5fbfbe18 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/doc/debug-system.md +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/doc/debug-system.md @@ -439,9 +439,9 @@ Address | Description --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ 0x0 to 0x0ff | _unused_ 0x100 | Halted. Write to this address to acknowledge that the core is halted. -0x104 | Going. Write to this address to acknowledge that the core is executing. -0x108 | Resuming. Write to this address to acknowledge that the core is resuming non-debug operation. -0x10c | Exception. An exception was triggered while the core was in debug mode. +0x108 | Going. Write to this address to acknowledge that the core is executing. +0x110 | Resuming. Write to this address to acknowledge that the core is resuming non-debug operation. +0x118 | Exception. An exception was triggered while the core was in debug mode. 0x300 | WhereTo 0x338 to 0x35f | AbstractCmd 0x360 to 0x37f | Program Buffer (8 words) @@ -449,8 +449,8 @@ Address | Description 0x400 to 0x7ff | Flags 0x800 to 0x1000 | Debug ROM 0x800 | HaltAddress. Entry point into the Debug Module. The core must jump to this address when it was requested to halt. -0x804 | ResumeAddress. Entry point into the Debug Module. Jumping to this address instructs the debug module to bring the core out of debug mode and back into normal operation mode. -0x808 | ExceptionAddress. Entry point into the Debug Module. The core must jump to this address when it receives an exception while being in debug mode. +0x808 | ResumeAddress. Entry point into the Debug Module. Jumping to this address instructs the debug module to bring the core out of debug mode and back into normal operation mode. +0x810 | ExceptionAddress. Entry point into the Debug Module. The core must jump to this address when it receives an exception while being in debug mode. (Note: The debug memory addressing scheme is adopted from the Rocket Chip Generator.) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_csrs.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_csrs.sv index 350c6c5f..23380289 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_csrs.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_csrs.sv @@ -90,7 +90,6 @@ module dm_csrs #( logic resp_queue_empty; logic resp_queue_push; logic resp_queue_pop; - logic [31:0] resp_queue_data; localparam dm::dm_csr_e DataEnd = dm::dm_csr_e'(dm::Data0 + {4'h0, dm::DataCount} - 8'h1); localparam dm::dm_csr_e ProgBufEnd = dm::dm_csr_e'(dm::ProgBuf0 + {4'h0, dm::ProgBufSize} - 8'h1); @@ -179,8 +178,8 @@ module dm_csrs #( logic [HartSelLen-1:0] selected_hart; - // a successful response returns zero - assign dmi_resp_o.resp = dm::DTM_SUCCESS; + dm::dmi_resp_t resp_queue_inp; + assign dmi_resp_valid_o = ~resp_queue_empty; assign dmi_req_ready_o = ~resp_queue_full; assign resp_queue_push = dmi_req_valid_i & dmi_req_ready_o; @@ -223,7 +222,7 @@ module dm_csrs #( // types instead. assign autoexecdata_idx = 4'({dm_csr_addr} - {dm::Data0}); - always_comb begin : csr_read_write + always_comb (*xprop_off *) begin : csr_read_write // -------------------- // Static Values (R/O) // -------------------- @@ -279,7 +278,8 @@ module dm_csrs #( sbaddr_d = 64'(sbaddress_i); sbdata_d = sbdata_q; - resp_queue_data = 32'h0; + resp_queue_inp.data = 32'h0; + resp_queue_inp.resp = dm::DTM_SUCCESS; cmd_valid_d = 1'b0; sbaddress_write_valid_o = 1'b0; sbdata_read_valid_o = 1'b0; @@ -294,62 +294,70 @@ module dm_csrs #( if (dmi_req_ready_o && dmi_req_valid_i && dtm_op == dm::DTM_READ) begin unique case (dm_csr_addr) inside [(dm::Data0):DataEnd]: begin - resp_queue_data = data_q[$clog2(dm::DataCount)'(autoexecdata_idx)]; + resp_queue_inp.data = data_q[$clog2(dm::DataCount)'(autoexecdata_idx)]; if (!cmdbusy_i) begin // check whether we need to re-execute the command (just give a cmd_valid) cmd_valid_d = abstractauto_q.autoexecdata[autoexecdata_idx]; // An abstract command was executing while one of the data registers was read - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end - dm::DMControl: resp_queue_data = dmcontrol_q; - dm::DMStatus: resp_queue_data = dmstatus; - dm::Hartinfo: resp_queue_data = hartinfo_aligned[selected_hart]; - dm::AbstractCS: resp_queue_data = abstractcs; - dm::AbstractAuto: resp_queue_data = abstractauto_q; + dm::DMControl: resp_queue_inp.data = dmcontrol_q; + dm::DMStatus: resp_queue_inp.data = dmstatus; + dm::Hartinfo: resp_queue_inp.data = hartinfo_aligned[selected_hart]; + dm::AbstractCS: resp_queue_inp.data = abstractcs; + dm::AbstractAuto: resp_queue_inp.data = abstractauto_q; // command is read-only - dm::Command: resp_queue_data = '0; + dm::Command: resp_queue_inp.data = '0; [(dm::ProgBuf0):ProgBufEnd]: begin - resp_queue_data = progbuf_q[dmi_req_i.addr[$clog2(dm::ProgBufSize)-1:0]]; + resp_queue_inp.data = progbuf_q[dmi_req_i.addr[$clog2(dm::ProgBufSize)-1:0]]; if (!cmdbusy_i) begin // check whether we need to re-execute the command (just give a cmd_valid) // range of autoexecprogbuf is 31:16 cmd_valid_d = abstractauto_q.autoexecprogbuf[{1'b1, dmi_req_i.addr[3:0]}]; // An abstract command was executing while one of the progbuf registers was read - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end - dm::HaltSum0: resp_queue_data = haltsum0; - dm::HaltSum1: resp_queue_data = haltsum1; - dm::HaltSum2: resp_queue_data = haltsum2; - dm::HaltSum3: resp_queue_data = haltsum3; + dm::HaltSum0: resp_queue_inp.data = haltsum0; + dm::HaltSum1: resp_queue_inp.data = haltsum1; + dm::HaltSum2: resp_queue_inp.data = haltsum2; + dm::HaltSum3: resp_queue_inp.data = haltsum3; dm::SBCS: begin - resp_queue_data = sbcs_q; + resp_queue_inp.data = sbcs_q; end dm::SBAddress0: begin - resp_queue_data = sbaddr_q[31:0]; + resp_queue_inp.data = sbaddr_q[31:0]; end dm::SBAddress1: begin - resp_queue_data = sbaddr_q[63:32]; + resp_queue_inp.data = sbaddr_q[63:32]; end dm::SBData0: begin // access while the SBA was busy if (sbbusy_i || sbcs_q.sbbusyerror) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin sbdata_read_valid_o = (sbcs_q.sberror == '0); - resp_queue_data = sbdata_q[31:0]; + resp_queue_inp.data = sbdata_q[31:0]; end end dm::SBData1: begin // access while the SBA was busy if (sbbusy_i || sbcs_q.sbbusyerror) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin - resp_queue_data = sbdata_q[63:32]; + resp_queue_inp.data = sbdata_q[63:32]; end end default:; @@ -367,8 +375,11 @@ module dm_csrs #( // check whether we need to re-execute the command (just give a cmd_valid) cmd_valid_d = abstractauto_q.autoexecdata[autoexecdata_idx]; //An abstract command was executing while one of the data registers was written - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end end @@ -391,8 +402,11 @@ module dm_csrs #( // reads during abstract command execution are not allowed if (!cmdbusy_i) begin cmderr_d = dm::cmderr_e'(~a_abstractcs.cmderr & cmderr_q); - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end dm::Command: begin @@ -402,8 +416,11 @@ module dm_csrs #( command_d = dm::command_t'(dmi_req_i.data); // if there was an attempted to write during a busy execution // and the cmderror field is zero set the busy error - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end dm::AbstractAuto: begin @@ -412,8 +429,11 @@ module dm_csrs #( abstractauto_d = 32'h0; abstractauto_d.autoexecdata = 12'(dmi_req_i.data[dm::DataCount-1:0]); abstractauto_d.autoexecprogbuf = 16'(dmi_req_i.data[dm::ProgBufSize-1+16:16]); - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end [(dm::ProgBuf0):ProgBufEnd]: begin @@ -426,26 +446,31 @@ module dm_csrs #( // range of autoexecprogbuf is 31:16 cmd_valid_d = abstractauto_q.autoexecprogbuf[{1'b1, dmi_req_i.addr[3:0]}]; //An abstract command was executing while one of the progbuf registers was written - end else if (cmderr_q == dm::CmdErrNone) begin - cmderr_d = dm::CmdErrBusy; + end else begin + resp_queue_inp.resp = dm::DTM_BUSY; + if (cmderr_q == dm::CmdErrNone) begin + cmderr_d = dm::CmdErrBusy; + end end end dm::SBCS: begin // access while the SBA was busy if (sbbusy_i) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin sbcs = dm::sbcs_t'(dmi_req_i.data); sbcs_d = sbcs; // R/W1C sbcs_d.sbbusyerror = sbcs_q.sbbusyerror & (~sbcs.sbbusyerror); - sbcs_d.sberror = sbcs_q.sberror & {3{~(sbcs.sberror == 3'd1)}}; + sbcs_d.sberror = (|sbcs.sberror) ? 3'b0 : sbcs_q.sberror; end end dm::SBAddress0: begin // access while the SBA was busy if (sbbusy_i || sbcs_q.sbbusyerror) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin sbaddr_d[31:0] = dmi_req_i.data; sbaddress_write_valid_o = (sbcs_q.sberror == '0); @@ -455,6 +480,7 @@ module dm_csrs #( // access while the SBA was busy if (sbbusy_i || sbcs_q.sbbusyerror) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin sbaddr_d[63:32] = dmi_req_i.data; end @@ -463,6 +489,7 @@ module dm_csrs #( // access while the SBA was busy if (sbbusy_i || sbcs_q.sbbusyerror) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin sbdata_d[31:0] = dmi_req_i.data; sbdata_write_valid_o = (sbcs_q.sberror == '0); @@ -472,6 +499,7 @@ module dm_csrs #( // access while the SBA was busy if (sbbusy_i || sbcs_q.sbbusyerror) begin sbcs_d.sbbusyerror = 1'b1; + resp_queue_inp.resp = dm::DTM_BUSY; end else begin sbdata_d[63:32] = dmi_req_i.data; end @@ -519,7 +547,7 @@ module dm_csrs #( if (!dmcontrol_q.resumereq && dmcontrol_d.resumereq) begin clear_resumeack_o = 1'b1; end - if (dmcontrol_q.resumereq && resumeack_i) begin + if (dmcontrol_q.resumereq && resumeack_i[selected_hart]) begin dmcontrol_d.resumereq = 1'b0; end // static values for dcsr @@ -557,8 +585,8 @@ module dm_csrs #( // response FIFO fifo_v2 #( - .dtype ( logic [31:0] ), - .DEPTH ( 2 ) + .dtype ( logic [$bits(dmi_resp_o)-1:0] ), + .DEPTH ( 2 ) ) i_fifo ( .clk_i, .rst_ni, @@ -569,9 +597,9 @@ module dm_csrs #( .empty_o ( resp_queue_empty ), .alm_full_o ( ), .alm_empty_o ( ), - .data_i ( resp_queue_data ), + .data_i ( resp_queue_inp ), .push_i ( resp_queue_push ), - .data_o ( dmi_resp_o.data ), + .data_o ( dmi_resp_o ), .pop_i ( resp_queue_pop ) ); diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_mem.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_mem.sv index 178259f6..8f97bec7 100755 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_mem.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_mem.sv @@ -26,6 +26,7 @@ module dm_mem #( input logic rst_ni, // debug module reset output logic [NrHarts-1:0] debug_req_o, + input logic ndmreset_i, input logic [19:0] hartsel_i, // from Ctrl and Status register input logic [NrHarts-1:0] haltreq_i, @@ -77,9 +78,9 @@ module dm_mem #( localparam logic [DbgAddressBits-1:0] FlagsEndAddr = 'h7FF; localparam logic [DbgAddressBits-1:0] HaltedAddr = 'h100; - localparam logic [DbgAddressBits-1:0] GoingAddr = 'h104; - localparam logic [DbgAddressBits-1:0] ResumingAddr = 'h108; - localparam logic [DbgAddressBits-1:0] ExceptionAddr = 'h10C; + localparam logic [DbgAddressBits-1:0] GoingAddr = 'h108; + localparam logic [DbgAddressBits-1:0] ResumingAddr = 'h110; + localparam logic [DbgAddressBits-1:0] ExceptionAddr = 'h118; logic [dm::ProgBufSize/2-1:0][63:0] progbuf; logic [7:0][63:0] abstract_cmd; @@ -201,6 +202,13 @@ module dm_mem #( cmderror_valid_o = 1'b1; cmderror_o = dm::CmdErrorException; end + + if (ndmreset_i) begin + // Clear state of hart and its control signals when it is being reset. + state_d = Idle; + go = 1'b0; + resume = 1'b0; + end end // word mux for 32bit and 64bit buses @@ -214,14 +222,13 @@ module dm_mem #( end // read/write logic - logic [63:0] data_bits; + logic [dm::DataCount-1:0][31:0] data_bits; logic [7:0][7:0] rdata; - always_comb begin : p_rw_logic + always_comb (* xprop_off *) begin : p_rw_logic halted_d_aligned = NrHartsAligned'(halted_q); resuming_d_aligned = NrHartsAligned'(resuming_q); rdata_d = rdata_q; - // convert the data in bits representation data_bits = data_i; rdata = '0; @@ -258,9 +265,19 @@ module dm_mem #( // core can write data registers [DataBaseAddr:DataEndAddr]: begin data_valid_o = 1'b1; - for (int i = 0; i < $bits(be_i); i++) begin - if (be_i[i]) begin - data_bits[i*8+:8] = wdata_i[i*8+:8]; + for (int dc = 0; dc < dm::DataCount; dc++) begin + if ((addr_i[DbgAddressBits-1:2] - DataBaseAddr[DbgAddressBits-1:2]) == dc) begin + for (int i = 0; i < $bits(be_i); i++) begin + if (be_i[i]) begin + if (i>3) begin // for upper 32bit data write (only used for BusWidth == 64) + if ((dc+1) < dm::DataCount) begin // ensure we write to an implemented data register + data_bits[dc+1][(i-4)*8+:8] = wdata_i[i*8+:8]; + end + end else begin // for lower 32bit data write + data_bits[dc][i*8+:8] = wdata_i[i*8+:8]; + end + end + end end end end @@ -293,10 +310,8 @@ module dm_mem #( [DataBaseAddr:DataEndAddr]: begin rdata_d = { - data_i[$clog2(dm::ProgBufSize)'(addr_i[DbgAddressBits-1:3] - - DataBaseAddr[DbgAddressBits-1:3] + 1'b1)], - data_i[$clog2(dm::ProgBufSize)'(addr_i[DbgAddressBits-1:3] - - DataBaseAddr[DbgAddressBits-1:3])] + data_i[$clog2(dm::DataCount)'(((addr_i[DbgAddressBits-1:3] - DataBaseAddr[DbgAddressBits-1:3]) << 1) + 1'b1)], + data_i[$clog2(dm::DataCount)'(((addr_i[DbgAddressBits-1:3] - DataBaseAddr[DbgAddressBits-1:3]) << 1))] }; end @@ -325,6 +340,12 @@ module dm_mem #( end end + if (ndmreset_i) begin + // When harts are reset, they are neither halted nor resuming. + halted_d_aligned = '0; + resuming_d_aligned = '0; + end + data_o = data_bits; end @@ -476,6 +497,7 @@ module dm_mem #( if (HasSndScratch) begin : gen_rom_snd_scratch debug_rom i_debug_rom ( .clk_i, + .rst_ni, .req_i, .addr_i ( rom_addr ), .rdata_o ( rom_rdata ) @@ -486,6 +508,7 @@ module dm_mem #( // be saved. debug_rom_one_scratch i_debug_rom ( .clk_i, + .rst_ni, .req_i, .addr_i ( rom_addr ), .rdata_o ( rom_rdata ) @@ -512,8 +535,8 @@ module dm_mem #( always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin - halted_q <= 1'b0; - resuming_q <= 1'b0; + halted_q <= '0; + resuming_q <= '0; end else begin halted_q <= SelectableHarts & halted_d; resuming_q <= SelectableHarts & resuming_d; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_pkg.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_pkg.sv index 1c2b6195..cc2e1ebc 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_pkg.sv @@ -26,8 +26,8 @@ package dm; // address to which a hart should jump when it was requested to halt localparam logic [63:0] HaltAddress = 64'h800; - localparam logic [63:0] ResumeAddress = HaltAddress + 4; - localparam logic [63:0] ExceptionAddress = HaltAddress + 8; + localparam logic [63:0] ResumeAddress = HaltAddress + 8; + localparam logic [63:0] ExceptionAddress = HaltAddress + 16; // address where data0-15 is shadowed or if shadowed in a CSR // address of the first CSR used for shadowing the data @@ -197,6 +197,12 @@ package dm; DTM_WRITE = 2'h2 } dtm_op_e; + typedef enum logic [1:0] { + DTM_SUCCESS = 2'h0, + DTM_ERR = 2'h2, + DTM_BUSY = 2'h3 + } dtm_op_status_e; + typedef struct packed { logic [31:29] sbversion; logic [28:23] zero0; @@ -215,8 +221,6 @@ package dm; logic sbaccess8; } sbcs_t; - localparam logic [1:0] DTM_SUCCESS = 2'h0; - typedef struct packed { logic [6:0] addr; dtm_op_e op; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_top.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_top.sv index 3c9c4451..c21e58d9 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_top.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dm_top.sv @@ -86,6 +86,7 @@ module dm_top #( logic [dm::DataCount-1:0][31:0] data_csrs_mem; logic [dm::DataCount-1:0][31:0] data_mem_csrs; logic data_valid; + logic ndmreset; logic [19:0] hartsel; // System Bus Access Module logic [BusWidth-1:0] sbaddress_csrs_sba; @@ -104,6 +105,7 @@ module dm_top #( logic sberror_valid; logic [2:0] sberror; + assign ndmreset_o = ndmreset; dm_csrs #( .NrHarts(NrHarts), @@ -120,7 +122,7 @@ module dm_top #( .dmi_resp_valid_o, .dmi_resp_ready_i, .dmi_resp_o, - .ndmreset_o, + .ndmreset_o ( ndmreset ), .dmactive_o, .hartsel_o ( hartsel ), .hartinfo_i, @@ -201,6 +203,7 @@ module dm_top #( .clk_i, .rst_ni, .debug_req_o, + .ndmreset_i ( ndmreset ), .hartsel_i ( hartsel ), .haltreq_i ( haltreq ), .resumereq_i ( resumereq ), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag.sv index 0712f8c6..577c3fd0 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag.sv @@ -17,7 +17,7 @@ */ module dmi_jtag #( - parameter logic [31:0] IdcodeValue = 32'h00000001 + parameter logic [31:0] IdcodeValue = 32'h00000DB3 ) ( input logic clk_i, // DMI Clock input logic rst_ni, // Asynchronous reset active low @@ -134,9 +134,11 @@ module dmi_jtag #( assign dmi_resp_ready = 1'b1; logic error_dmi_busy; + logic error_dmi_op_failed; always_comb begin : p_fsm error_dmi_busy = 1'b0; + error_dmi_op_failed = 1'b0; // default assignments state_d = state_q; address_d = address_q; @@ -177,7 +179,22 @@ module dmi_jtag #( WaitReadValid: begin // load data into register and shift out if (dmi_resp_valid) begin - data_d = dmi_resp.data; + unique case (dmi_resp.resp) + dm::DTM_SUCCESS: begin + data_d = dmi_resp.data; + end + dm::DTM_ERR: begin + data_d = 32'hDEAD_BEEF; + error_dmi_op_failed = 1'b1; + end + dm::DTM_BUSY: begin + data_d = 32'hB051_B051; + error_dmi_busy = 1'b1; + end + default: begin + data_d = 32'hBAAD_C0DE; + end + endcase state_d = Idle; end end @@ -193,6 +210,11 @@ module dmi_jtag #( WaitWriteValid: begin // got a valid answer go back to idle if (dmi_resp_valid) begin + unique case (dmi_resp.resp) + dm::DTM_ERR: error_dmi_op_failed = 1'b1; + dm::DTM_BUSY: error_dmi_busy = 1'b1; + default: ; + endcase state_d = Idle; end end @@ -218,9 +240,14 @@ module dmi_jtag #( error_dmi_busy = 1'b1; end - if (error_dmi_busy) begin + if (error_dmi_busy && error_q == DMINoError) begin error_d = DMIBusy; end + + if (error_dmi_op_failed && error_q == DMINoError) begin + error_d = DMIOPFailed; + end + // clear sticky error flag if (update && dtmcs_q.dmireset && dtmcs_select) begin error_d = DMINoError; diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag_tap.sv b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag_tap.sv index 0c188c05..53f0fa9d 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag_tap.sv +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_riscv_dbg/src/dmi_jtag_tap.sv @@ -94,8 +94,9 @@ module dmi_jtag_tap #( jtag_ir_d = ir_reg_e'(jtag_ir_shift_q); end - // According to JTAG spec we have to reset the IR to IDCODE in test_logic_reset if (test_logic_reset) begin + // Bring all TAP state to the initial value. + jtag_ir_shift_d = '0; jtag_ir_d = IDCODE; end end @@ -135,6 +136,12 @@ module dmi_jtag_tap #( if (idcode_select) idcode_d = {td_i, 31'(idcode_q >> 1)}; if (bypass_select) bypass_d = td_i; end + + if (test_logic_reset) begin + // Bring all TAP state to the initial value. + idcode_d = IdcodeValue; + bypass_d = 1'b0; + end end // ---------------- @@ -180,12 +187,12 @@ module dmi_jtag_tap #( // ---------------- logic tck_n, tck_ni; - cluster_clock_inverter i_tck_inv ( + tc_clk_inverter i_tck_inv ( .clk_i ( tck_i ), .clk_o ( tck_ni ) ); - pulp_clock_mux2 i_dft_tck_mux ( + tc_clk_mux2 i_dft_tck_mux ( .clk0_i ( tck_ni ), .clk1_i ( tck_i ), // bypass the inverted clock for testing .clk_sel_i ( testmode_i ), diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_tech_cells_generic.core b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_tech_cells_generic.core index 6a70b8e2..02d8b12c 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_tech_cells_generic.core +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/pulp_platform_tech_cells_generic.core @@ -20,3 +20,4 @@ targets: default: filesets: - target_sim? (rtl_sim) + - target_sim_sc? (rtl_sim) diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cv32e40p.vlt b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cv32e40p.vlt index 65542b42..4be49e61 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cv32e40p.vlt +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cv32e40p.vlt @@ -114,3 +114,4 @@ lint_off -rule WIDTH -file "*/rtl/cv32e40p_decoder.sv" -match "Logical operator lint_off -rule WIDTH -file "*/rtl/cv32e40p_controller.sv" -match "Logical operator LOGAND expects 1 bit on the LHS, but LHS's VARREF 'FPU' generates 32 bits.*" lint_off -rule WIDTH -file "*/rtl/cv32e40p_cs_registers.sv" -match "Logical operator LOGOR expects 1 bit on the LHS, but LHS's VARREF 'FPU' generates 32 bits.*" lint_off -rule LATCH -file "*/rtl/cv32e40p_id_stage.sv" -match "Latch inferred for signal*apu_read_regs*" +lint_off -rule WIDTH -file "*/rtl/cv32e40p_cs_registers.sv" -match "Logical operator LOGOR expects 1 bit on the RHS, but RHS's VARREF 'COREV_PULP' generates 32 bits.*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cv32e40px.vlt b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cv32e40px.vlt index a6665860..f2eebf7b 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cv32e40px.vlt +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cv32e40px.vlt @@ -114,3 +114,6 @@ lint_off -rule WIDTH -file "*/rtl/cv32e40px_decoder.sv" -match "Logical operator lint_off -rule WIDTH -file "*/rtl/cv32e40px_controller.sv" -match "Logical operator LOGAND expects 1 bit on the LHS, but LHS's VARREF 'FPU' generates 32 bits.*" lint_off -rule WIDTH -file "*/rtl/cv32e40px_cs_registers.sv" -match "Logical operator LOGOR expects 1 bit on the LHS, but LHS's VARREF 'FPU' generates 32 bits.*" lint_off -rule LATCH -file "*/rtl/cv32e40px_id_stage.sv" -match "Latch inferred for signal*apu_read_regs*" +lint_off -rule WIDTH -file "*/rtl/cv32e40px_register_file_ff.sv" -match "Logical operator COND expects 1 bit on the Conditional Test*" +lint_off -rule WIDTH -file "*/rtl/cv32e40px_decoder.sv" -match "Logical operator LOGNOT expects 1 bit on the LHS*" +lint_off -rule WIDTH -file "*/rtl/cv32e40px_ex_stage.sv" -match "Logical operator LOGNOT expects 1 bit on the LHS*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cve2.vlt b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cve2.vlt index ac5b0076..7b3fc6bb 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cve2.vlt +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/cve2.vlt @@ -6,3 +6,6 @@ lint_off -rule DECLFILENAME -file "*bhv/cve2_sim_clock_gate.sv" -match "*Filename 'cve2_sim_clock_gate' does not match MODULE name: 'cve2_clock_gate'*" lint_off -rule UNOPTFLAT -file "*rtl/*.sv" -match "*" +lint_off -rule UNUSED -file "*rtl/cve2_core.sv" -match "Signal is not used: 'rf_ren_a'*" +lint_off -rule UNUSED -file "*rtl/cve2_core.sv" -match "Signal is not used: 'rf_ren_b'*" +lint_off -rule UNUSED -file "*rtl/cve2_wb.sv" -match "Signal is not used:*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/riscv_dbg.vlt b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/riscv_dbg.vlt index 460f3c6b..2d2888d2 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/riscv_dbg.vlt +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/waiver/lint/riscv_dbg.vlt @@ -11,3 +11,5 @@ lint_off -rule DECLFILENAME -file "*/src/cdc_reset_ctrlr.sv" -match "Filename 'c lint_off -rule DECLFILENAME -file "*/src/cdc_fifo_gray_clearable.sv" -match "Filename 'cdc_fifo_gray_clearable' does not match MODULE name: 'cdc_fifo_gray_src_clearable'*" lint_off -rule WIDTH -file "*/src/cdc_2phase_clearable.sv" -match "Logical operator GENIF expects 1 bit on the If, but If's VARREF 'CLEAR_ON_ASYNC_RESET' generates 32 bits.*" lint_off -rule UNOPTFLAT -file "*/src/cdc_4phase.sv" -match "Signal unoptimizable*" +lint_off -rule WIDTH -file "*/src/dm_mem.sv" -match "*" +lint_off -rule CMPCONST -file "*/src/dm_csrs.sv" -match "*" diff --git a/hw/vendor/esl_epfl_x_heep/hw/vendor/yosyshq_picorv32/picosoc/spiflash.v b/hw/vendor/esl_epfl_x_heep/hw/vendor/yosyshq_picorv32/picosoc/spiflash.v index e0eef9f7..55342b5f 100644 --- a/hw/vendor/esl_epfl_x_heep/hw/vendor/yosyshq_picorv32/picosoc/spiflash.v +++ b/hw/vendor/esl_epfl_x_heep/hw/vendor/yosyshq_picorv32/picosoc/spiflash.v @@ -26,7 +26,7 @@ // updates output signals 1ns after the SPI clock edge. // // Supported commands: -// AB, B9, FF, 03, BB, EB, ED +// AB, B9, FF, 03, BB, EB, ED, 06, 02, 32 // // Well written SPI flash data sheets: // Cypress S25FL064L http://www.cypress.com/file/316661/download @@ -61,6 +61,8 @@ module spiflash ( reg spi_io_vld; reg powered_up = 0; + reg write_enable = 0; + reg write_enable_reset = 0; localparam [3:0] mode_spi = 1; localparam [3:0] mode_dspi_rd = 2; @@ -107,7 +109,7 @@ module spiflash ( initial begin for (i=0;i<=16*1024*1024;i=i+1) - memory[i] = '0; + memory[i] = 8'h00; result = $value$plusargs("firmware=%s", firmware_file); if (!result) firmware_file = "firmware.hex"; @@ -129,6 +131,9 @@ module spiflash ( if (spi_cmd == 8'h ff) xip_cmd = 0; + + if (spi_cmd == 8'h 06) + write_enable = 1; end if (powered_up && spi_cmd == 'h 03) begin @@ -147,6 +152,25 @@ module spiflash ( end end + if (powered_up && write_enable && spi_cmd == 'h 02) begin + if (bytecount == 1) + write_enable_reset = 1; + + if (bytecount == 2) + spi_addr[23:16] = buffer; + + if (bytecount == 3) + spi_addr[15:8] = buffer; + + if (bytecount == 4) + spi_addr[7:0] = buffer; + + if (bytecount >= 5 && bytecount <= 260) begin + memory[spi_addr] = buffer; + spi_addr = spi_addr + 1; + end + end + if (powered_up && spi_cmd == 'h bb) begin if (bytecount == 1) mode = mode_dspi_rd; @@ -197,6 +221,27 @@ module spiflash ( end end + if (powered_up && write_enable && spi_cmd == 'h 32) begin + if (bytecount == 1) + write_enable_reset = 1; + + if (bytecount == 2) + spi_addr[23:16] = buffer; + + if (bytecount == 3) + spi_addr[15:8] = buffer; + + if (bytecount == 4) begin + spi_addr[7:0] = buffer; + mode = mode_qspi_rd; + end + + if (bytecount >= 5 && bytecount <= 260) begin + memory[spi_addr] = buffer; + spi_addr = spi_addr + 1; + end + end + if (powered_up && spi_cmd == 'h ed) begin if (bytecount == 1) next_mode = mode_qspi_ddr_rd; @@ -274,6 +319,10 @@ module spiflash ( $display(""); $fflush; end + if (write_enable_reset) begin + write_enable = 0; + write_enable_reset = 0; + end buffer = 0; bitcount = 0; bytecount = 0; diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/README.md b/hw/vendor/esl_epfl_x_heep/linux_femu/README.md deleted file mode 100644 index 45764e74..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/README.md +++ /dev/null @@ -1,171 +0,0 @@ -# Linux-FEMU - -In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the Zynq 7020 chip and Linux is run on the ARM-based processing system (PS) side of the same chip. The X-HEEP JTAG signals are driven by the PS GPIO peripheral and are used to program and debug the architecture, while the X-HEEP UART is connected to the PS UART peripheral and is used to get the stdout of the program running on the architecture. Moreover, the X-HEEP flash SPI is connected to the ARM AXI bus passing through an SPI to AXI bridge: this allows virtualising the flash memory into the on-board DDR RAM memory. In this way, the program running on the architecture can read the external virtualised flash as it was a real flash memory, i.e., this virtualisation is totally transparent to the X-HEEP code. - -Go through the following steps to build and use our Linux-FEMU version. - -## Build the platform - -Start in the x-heep main folder. - -## Generate the files - -1. Activate the conda environment with: - -``` -conda activate core-v-mini-mcu -``` - -2. Generate the hdl files by calling: - -``` -make linux-femu-gen PAD_CFG=linux_femu/pad_cfg.hjson -``` - -__NOTE__: you can customize the mcu-gen process by providing the MEMORY_BANKS - CPU - BUS parameters to the above command. - -## Flash the SD card with a Linux image - -1. Download the Linux image (version v3.0.1) using the following link: - -`http://www.pynq.io/board.html` - -2. Follow the procedure explained in the following linked page to flash the downloaded image to the SD card: - -`https://pynq.readthedocs.io/en/v2.2.1/appendix.html#writing-the-sd-card` - -3. Insert the SD into the Pynq-Z2 board and make sure the booting bridge is on the SD position. - -4. Power-on the board and wait for Linux to boot (a row of 4 leds should turn on). - -## Create the Vivado project and generate the bitstream - -1. Starting in the x-heep main folder, run the following command to create the Vivado project and generate the bitstream: - -``` -make vivado-fpga FPGA_BOARD=pynq-z2-arm-emulation -``` - -2. Open the project x-heep/build/openhwgroup.org_systems_core-v-mini-mcu_0/pynq-z2-arm-emulation-vivado/openhwgroup.org_systems_core-v-mini-mcu_0.xpr with Vivado and use the Hardware Manager to program the bitstream to the Zynq 7020 of the Pynq-Z2 board. - -## Connect to Linux running on the Pynq-Z2 board - -Connect your Linux-based PC to the Pynq-Z2 board through Ethernet and run the following command: - -``` -ssh -X xilinx@board_ip -``` - -The default password is: xilinx - -If you need additional documentation on how to connect your PC to the Pynq-Z2 board, use the following link: - -`https://pynq.readthedocs.io/en/v2.6.1/getting_started/pynq_z2_setup.html` - -## Install OpenOCD on the Pynq-Z2 board - -1. Clone the OpenOCD repository usign the following link: - -`https://github.com/openocd-org/openocd` - -2. Run the following commands from the OpneOCD main folder to install it: - -``` -sudo ./bootstrap -sudo ./configure --enable-sysfsgpio -sudo make -sudo make install -``` - -## Copy the x-heep folder to the Pynq-Z2 baord - -Copy the x-heep/linux_femu/arm/ folder from your PC to the home directory of the Pynq-Z2 board with the following command: - -``` -sudo scp -r x-heep/linux_femu/arm/ xilinx@board_ip:~ -``` - -## Enable UART1 on Linux on the Pynq-Z2 baord - -Enter the arm/uart_enable/ folder and run the following commands: - -``` -sudo su -mkdir -p /configfs -./uart_enable.sh -exit -``` - -These commands enable the UART1 on the ARM system side of the Zynq 7020 on the Pynq-Z2 board. UART1 is used to receive the stdout of the code running on the HEEP architecture implemented on the PL side of the chip. - -## Prepare the needed shells - -You need to use 5 shells (the first, second and third shells will run on the Pynq-Z2 board, while the fourth and fifth shells will run on your PC): - -1. First shell - run virtual flash app on the Pynq-Z2 board - browse to the arm/virtual_flash/ folder and execute the following commands to compile and run the required application: - -``` -sudo make clean -sudo make -sudo ./virtual_flash -``` - -This app allocates a buffer into the off-chip DDR memory of the Pynq-Z2 board and stores its physical base address to the hijacker PL peripheral. - -2. Second shell - run the following commands on the Pynq-Z2 board to get the stdout from the app running on x-heep: - -``` -sudo apt-get install screen -sudo screen /dev/ttyPS1 115200 -``` - -3. Third shell - run openocd on the Pynq-Z2 board - browse to the arm/openocd_cfg/ folder and run the following command: - -``` -sudo openocd -f ./gpio_bitbang.cfg -``` - -4. Fourth shell - compile HEEP app on your PC - browse to the x-heep/sw/ folder and run the following command: - -``` -make clean applications/example_virtual_flash/example_virtual_flash.hex TARGET=pynq-z2 -``` - -With this command you compile a sample RISC-V based application that uses the allocated DDR-based virtual memory. You may want to change this command with the name of your own application. - -5. Fifth shell - run GDB on your PC - browse to the x-heep/sw/applications/example_virtual_flash/ folder and run the following command to connect GDB: - -``` -sudo /path_to_your_riscv_toolchain/bin/riscv32-unknown-elf-gdb -``` - -Use the following GDB commands to connect to OpenOCD running on the Pynq-Z2 board and run your application: - -``` -(gdb) target remote board_ip:3333 -(gdb) load example_virtual_flash.elf -(gdb) cont -``` - -Go back to the first shell and press ENTER to end the application and dump the content of the virtual flash to a file. Then, run the following commands: - -``` -xxd dump.txt dump -nano dump -``` - -Check if your result corresponds to the following lines: - -``` -00000000: 0000 0000 0000 0001 0000 0002 0000 0003 ................ -00000010: 0000 0004 0000 0005 0000 0006 0000 0007 ................ -00000020: 0000 0008 0000 0009 0000 000a 0000 000b ................ -00000030: 0000 000c 0000 000d 0000 000e 0000 000f ................ -00000040: 0000 0010 0000 0011 0000 0012 0000 0013 ................ -00000050: 0000 0014 0000 0015 0000 0016 0000 0017 ................ -00000060: 0000 0018 0000 0019 0000 001a 0000 001b ................ -00000070: 0000 001c 0000 001d 0000 001e 0000 001f ................ -00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................ -``` - -__NOTE__: to run other applications, press the hard reset button on the Pynq-Z2 board (BTN3) and re-connect OpneOCD and GDB. diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/README.md b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/README.md deleted file mode 100644 index 38dfdbce..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/README.md +++ /dev/null @@ -1,80 +0,0 @@ -### Hardware Configurations - -On the hardware side, we must configure the ZYNQ processing system to use the EMIO and export them externally so that they can be attached to x-heep. They are then routed outwards from the wrapper to x-heep JTAG signals. - -### Software Configurations - -## Target adapter configuration __gpio_bitbang.cfg__: - -``` -# SPDX-License-Identifier: GPL-2.0-or-later - -# -# Config for using RaspberryPi's expansion header -# -# This is best used with a fast enough buffer but also -# is suitable for direct connection if the target voltage -# matches RPi's 3.3V -# -# Do not forget the GND connection, pin 6 of the expansion header. -# - -adapter driver sysfsgpio -transport select jtag - -bindto 0.0.0.0 - -set _CHIPNAME riscv -jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10001c05 - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid 0x000 -echo "Target created" - -riscv set_reset_timeout_sec 2000 -riscv set_command_timeout_sec 2000 -# riscv set_prefer_sba off - -echo "Setting preferences" - -# Each of the JTAG lines need a gpio number set: tck tms tdi tdo -# Header pin numbers: 23 22 19 21 -sysfsgpio jtag_nums 964 961 963 962 - -# Each of the SWD lines need a gpio number set: swclk swdio -# Header pin numbers: 23 22 -# sysfsgpio swd_nums 11 25 - -# If you define trst or srst, use appropriate reset_config -# Header pin numbers: TRST - 26, SRST - 18 - -sysfsgpio trst_num 960 -reset_config trst_only - -# sysfsgpio srst_num 24 -# reset_config srst_only srst_push_pull - -# or if you have both connected, -# reset_config trst_and_srst srst_push_pull - -scan_chain - -init - -echo "Init routine started" - -halt -echo "Ready for connections" -``` - -This instructs openocd to use the riscv HART and jtag module but instead of transmitting the commands over the usual FTDI usb adapter, it bitbangs the GPIOs by using the SYSFS framework. - -In order to understand the pin numbering used in the script we have to know how the JTAG has been ported to the PYNQ without using external adapters. The ZYNQ 7000 offers several banks of GPIO lines used for different purposes. The first 54 are MIO (multiplexed I/O) and are configured for different purposes but are PS-side only. After those, we have 64 EMIO (extended MIO) which are lines that can be routed to the PL). The idea is therefore to expose 5 EMIO GPIOS (5 jtag signals) and route them to the PL and to x-heep directly. Those can be controlled as normal GPIO lines and allow interfacing directly from ARM. - -Therefore, the pin numbers used in the configuration file are derived as follows: - -1. Find the GPIO starting numbers that linux uses by running ``` sudo cat /sys/kernel/debug/gpio ``` -> in this case it was __906__ - -2. Add 54 (the first 54 GPIOS are the MIOs). - -3. Add the gpio_n assigned to the specific signal (depends on the HDL connections). diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/gpio_bitbang.cfg b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/gpio_bitbang.cfg deleted file mode 100755 index 11c5519d..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/openocd_cfg/gpio_bitbang.cfg +++ /dev/null @@ -1,58 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-or-later - -# -# Config for using RaspberryPi's expansion header -# -# This is best used with a fast enough buffer but also -# is suitable for direct connection if the target voltage -# matches RPi's 3.3V -# -# Do not forget the GND connection, pin 6 of the expansion header. -# - -adapter driver sysfsgpio -transport select jtag - -bindto 0.0.0.0 - -set _CHIPNAME riscv -jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10001c05 - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid 0x000 -echo "Target created" - -riscv set_reset_timeout_sec 2000 -riscv set_command_timeout_sec 2000 -# riscv set_prefer_sba off - -echo "Setting preferences" - -# Each of the JTAG lines need a gpio number set: tck tms tdi tdo -# Header pin numbers: 23 22 19 21 -sysfsgpio jtag_nums 964 961 963 962 - -# Each of the SWD lines need a gpio number set: swclk swdio -# Header pin numbers: 23 22 -# sysfsgpio swd_nums 11 25 - -# If you define trst or srst, use appropriate reset_config -# Header pin numbers: TRST - 26, SRST - 18 - -sysfsgpio trst_num 960 -reset_config trst_only - -# sysfsgpio srst_num 24 -# reset_config srst_only srst_push_pull - -# or if you have both connected, -# reset_config trst_and_srst srst_push_pull - -scan_chain - -init - -echo "Init routine started" - -halt -echo "Ready for connections" diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/README.md b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/README.md deleted file mode 100644 index 15f4fac9..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/README.md +++ /dev/null @@ -1,57 +0,0 @@ -### Hardware Configurations - -On the hardware side, we must configure the ZYNQ processing system to enable UART1 and route tx and rx to the EMIO pins so that they can be attached to x-heep. They are then routed outwards from the wrapper to x-heep UART signals. - -__NOTE__: remembed to connect tx to rx and viceversa. - -### Software Configurations - -## Enable UART1 - -In order to ask Linux to use that as a normal serial port, we need to modify the DEVICE TREE to expose this new hardware piece. In theory, the UART1 peripheral is already defined in the tree but is disabled. Instead of rebuilding the device tree, we can add an overlay at runtime to add and change configuration properties of the tree. In particular, we need to extend the device tree with the following: - -``` -/dts-v1/; -/plugin/; - -/{ - fragment@0{ - target-path = "/aliases"; - __overlay__ { - serial1 = "/axi/serial@e0001000"; - }; - }; - - fragment@1{ - target = <&uart1>; - __overlay__ { - status = "okay"; - }; - }; -}; - -``` - -This first makes an alias to make sure that the uart1 (/axi/serial@e0001000) is called serial1, and then enables it by setting the status as "okay". Aliasing is important to avoid a problem that could arise if the kernel decides to swap the ttyPS1 and ttyPS0 (uart0 and the one used to connect to ARM through serial), because we'd have no access to the board over serial. - -1. DTSI file must be compiled into binary format as follows: - -``` -dtc -O dtb -o uart_enable.dtbo -b 0 -@ uart_enable.dtsi -``` -2. We mount the configfs, which is a RAM-based configuration file-system exposed to add overlays. - -``` -sudo mount configfs configfs /configfs -sudo mkdir configfs/device-tree/overlays/uart_enable -``` - -3. Concatenate the dtbo binary file to insert into the kernel device tree. - -``` -sudo su -cat uart_enable.dtbo >/configfs/device-tree/overlays/uart_enable/dtbo -exit -``` - -4. Make sure with dmesg that no errors were thrown and that /dev/ttySP1 has appeared -> that is x-heep's serial. diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.dtbo b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.dtbo deleted file mode 100755 index 896a0f34..00000000 Binary files a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.dtbo and /dev/null differ diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.dtsi b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.dtsi deleted file mode 100755 index 21804e30..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.dtsi +++ /dev/null @@ -1,18 +0,0 @@ -/dts-v1/; -/plugin/; - -/{ - fragment@0{ - target-path = "/aliases"; - __overlay__ { - serial1 = "/axi/serial@e0001000"; - }; - }; - - fragment@1{ - target = <&uart1>; - __overlay__ { - status = "okay"; - }; - }; -}; diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.sh b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.sh deleted file mode 100755 index ec02611c..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/uart_enable/uart_enable.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -mount -t configfs configfs /configfs -mkdir /configfs/device-tree/overlays/uart_enable -cat ./uart_enable.dtbo >/configfs/device-tree/overlays/uart_enable/dtbo diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/Makefile b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/Makefile deleted file mode 100755 index e9c11b69..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: virtual_flash - -virtual_flash: virtual_flash.cpp OverlayControl.c OverlayControl.h - g++ -O0 -g -Wall virtual_flash.cpp OverlayControl.c -o virtual_flash -lpthread -lm -lcma - -clean: - rm -f virtual_flash diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.c b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.c deleted file mode 100755 index 68f2a857..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.c +++ /dev/null @@ -1,103 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include - -// 1 --> Basic logging, 2 --> Debugging -#define LOGGING 2 - -#include "OverlayControl.h" -extern "C" { -#include -} - -static volatile uint32_t * memMapAddr = NULL; -static int memMapFileDesc = -1; -static uint32_t memMapSize = 0; - -volatile uint32_t * MapMemIO(uint32_t baseAddr, uint32_t mapSize) -{ - bool res = true; - - res = ( (memMapFileDesc = open("/dev/mem", O_RDWR | O_SYNC )) != -1); - - if (!res) { - #ifdef LOGGING - printf("Error opening file.\n"); - #endif - } - else { - #if LOGGING == 2 - printf("File opened.\n"); - #endif - memMapAddr = (volatile unsigned int *)mmap(NULL, mapSize, PROT_READ | PROT_WRITE, MAP_SHARED, memMapFileDesc, baseAddr); - res = (memMapAddr != MAP_FAILED); - if (!res) { - #ifdef LOGGING - printf("Memory mapping failed.\n"); - #endif - close(memMapFileDesc); - memMapFileDesc = -1; - memMapAddr = NULL; - } - } - - if (res) { - #ifdef LOGGING - printf("Memory mapped.\n"); - #endif - memMapSize = mapSize; - } - - return memMapAddr; -} - -bool UnmapMemIO() -{ - bool res = true; - - if ((memMapAddr != NULL) && (memMapAddr != MAP_FAILED)) { - if ( munmap((void*)memMapAddr, memMapSize) ) { - #ifdef LOGGING - printf("Memory unmapping failed.\n"); - #endif - res = false; - } - else { - #ifdef LOGGING - printf("Memory unmapped.\n"); - #endif - } - } - - if (memMapFileDesc != -1) { - close(memMapFileDesc); - memMapFileDesc = -1; - } - - return res; -} - -// Reference of functions to (de)allocate DMA memory. -// extern "C" { -// #include -// } -/* * Allocate a physically contiguos chunk of CMA memory and map it into - * virtual memory space. Return this Virtual pointer. Returns -1 on failure. -void *cma_alloc(uint32_t len, uint32_t cacheable); - * Return a physical memory address corresponding to a given Virtual address - * pointer. Returns NULL on failure. -unsigned long cma_get_phy_addr(void *buf); - * Free a previously allocated CMA memory chunk. -void cma_free(void *buf); - * Returns the number of available CMA memiry pages which can be allocated. -uint32_t cma_pages_available(); - * Extra functions in case user needs to flush or invalidate Cache. -void cma_flush_cache(void *buf, unsigned int phys_addr, int size); -void cma_invalidate_cache(void *buf, unsigned int phys_addr, int size); -*/ diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.h b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.h deleted file mode 100755 index 92807321..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/OverlayControl.h +++ /dev/null @@ -1,27 +0,0 @@ - -#ifndef OVERLAYCONTROL_H -#define OVERLAYCONTROL_H - -volatile uint32_t * MapMemIO(uint32_t baseAddr, uint32_t mapSize); -bool UnmapMemIO(); - -// Reference of functions to (de)allocate DMA memory. -// extern "C" { -// #include -// } -/* * Allocate a physically contiguos chunk of CMA memory and map it into - * virtual memory space. Return this Virtual pointer. Returns -1 on failure. -void *cma_alloc(uint32_t len, uint32_t cacheable); - * Return a physical memory address corresponding to a given Virtual address - * pointer. Returns NULL on failure. -unsigned long cma_get_phy_addr(void *buf); - * Free a previously allocated CMA memory chunk. -void cma_free(void *buf); - * Returns the number of available CMA memiry pages which can be allocated. -uint32_t cma_pages_available(); - * Extra functions in case user needs to flush or invalidate Cache. -void cma_flush_cache(void *buf, unsigned int phys_addr, int size); -void cma_invalidate_cache(void *buf, unsigned int phys_addr, int size); -*/ - -#endif // OVERLAYCONTROL_H diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/virtual_flash.cpp b/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/virtual_flash.cpp deleted file mode 100755 index 8de7bc7c..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/arm/virtual_flash/virtual_flash.cpp +++ /dev/null @@ -1,100 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include "OverlayControl.h" - -extern "C" { -#include -} - -const uint32_t MEM_IS_CACHEABLE = 0; -const uint32_t MAP_SIZE = 64*1024; -const uint32_t BASE_ADDR = 0x43C00000; -const uint32_t ALLOC_SIZE_BYTE = 64*1024*128; -const uint32_t FIXED_VALUE = 0x1c; - -uint32_t *virtual_flash_buffer, *virtual_flash_buffer_phy; - -static void stop(int) -{ - signal(SIGTERM, SIG_DFL); - signal(SIGINT, SIG_DFL); - - if(virtual_flash_buffer != NULL){ - FILE* dump = fopen("./dump.txt", "wb"); - fwrite(virtual_flash_buffer, ALLOC_SIZE_BYTE, 1, dump); - fclose(dump); - } -} - -int main(int argc, char **argv) -{ - signal(SIGTERM, stop); - signal(SIGINT, stop); - volatile uint8_t *pl_peripherals = NULL; - volatile uint32_t* hijacker = NULL; - - printf("Press ENTER to confirm that the bitstream is loaded (proceeding without it can crash the board).\n"); - getchar(); - - // Get the virtual address corresponding to the physical base address of the PL peripherals - if ((pl_peripherals = (uint8_t *) MapMemIO(BASE_ADDR, MAP_SIZE)) == NULL) { - printf("Error getting address!\n"); - return -1; - } - printf("PL peripherals mapped at 0x%08X.\n", (uint32_t)pl_peripherals); - fflush(stdout); - - // Map hijacker PL peripheral - hijacker = (uint32_t *)pl_peripherals; - printf("hijacker mapped at 0x%08X.\n", (uint32_t)hijacker); - - // Allocate DDR memory buffer to virtualize a Flash memory and get its physical address - fflush(stdout); - virtual_flash_buffer = (uint32_t *)cma_alloc(ALLOC_SIZE_BYTE, MEM_IS_CACHEABLE); - virtual_flash_buffer_phy = (uint32_t *)((uint32_t)cma_get_phy_addr(virtual_flash_buffer)); - printf("DDR memory buffer allocated.\n"); - fflush(stdout); - printf("Virtual address: 0x%.8X.\n", (uint32_t)virtual_flash_buffer); - fflush(stdout); - printf("Physical address: Phys: 0x%.8X.\n\n", (uint32_t)virtual_flash_buffer_phy); - fflush(stdout); - if (virtual_flash_buffer == NULL) { - printf("Error allocating DDR memory for %u bytes!\n", ALLOC_SIZE_BYTE); - return -1; - } - - // Initialize DDR memory buffer - for (uint32_t i = 0; i < ALLOC_SIZE_BYTE / sizeof(uint32_t); i++) - virtual_flash_buffer[0] = i; - - // Copy the physical address of the DDR memory buffer to hijacker PL peripheral - *hijacker = (uint32_t)virtual_flash_buffer_phy; - - // Press ENTER to end the application - printf("Press ENTER to end the application.\n"); - getchar(); - - printf("Virtual flash read and content stored in file dump.txt.\n\n"); - - // Read content of the DDR memory buffer and store it to a file - FILE *dump = fopen("./dump.txt", "wb"); - fwrite(virtual_flash_buffer, ALLOC_SIZE_BYTE, 1, dump); - fclose(dump); - - /////////////////////////////////////////////////////////////////////////////////////// - // DDR memory is a global variable. In this Linux version, it is allocated - // by a pl_peripherals driver provided by Xilinx. This means that it is not freed - // automatically when our process exits. We MUST free it or the board will - // run out of DMA memory!!! - /////////////////////////////////////////////////////////////////////////////////////// - if (virtual_flash_buffer != NULL) - cma_free(virtual_flash_buffer); - UnmapMemIO(); - - return 0; -} diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/constraints/constraints.xdc b/hw/vendor/esl_epfl_x_heep/linux_femu/constraints/constraints.xdc deleted file mode 100644 index ca9babe2..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/constraints/constraints.xdc +++ /dev/null @@ -1 +0,0 @@ -set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets linux_femu/pad_ring_i/pad_clk_i/xilinx_iobuf_i/O] diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/pad_cfg.hjson b/hw/vendor/esl_epfl_x_heep/linux_femu/pad_cfg.hjson deleted file mode 100644 index 235ee13f..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/pad_cfg.hjson +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 -// Derived from Occamy: https://github.com/pulp-platform/snitch/blob/master/hw/system/occamy/src/occamy_cfg.hjson -// Peripherals configuration for core-v-mini-mcu. -{ - pads: { - - clk: { - num: 1, - type: input - }, - rst: { - num: 1, - active: low, - driven_manually: True - type: input - }, - boot_select: { - num: 1, - type: input - }, - execute_from_flash: { - num: 1, - type: input - }, - jtag_tck: { - num: 1, - keep_internal: True - type: input - }, - jtag_tms: { - num: 1, - keep_internal: True - type: input - }, - jtag_trst: { - num: 1, - keep_internal: True - active: low, - type: input - }, - jtag_tdi: { - num: 1, - keep_internal: True - type: input - }, - jtag_tdo: { - num: 1, - keep_internal: True - type: output - }, - uart_rx: { - num: 1, - keep_internal: True - type: input - }, - uart_tx: { - num: 1, - keep_internal: True - type: output - }, - exit_valid: { - num: 1, - type: output - }, - gpio: { - num: 23, - num_offset: 0, #first gpio is gpio0 - type: inout - }, - spi_flash_sck: { - num: 1, - keep_internal: True - type: inout - }, - spi_flash_cs: { - num: 2, #carefull, the x-heep uses the CS from the spi pkg, change it - keep_internal: True - type: inout - }, - spi_flash_sd: { - num: 4, - keep_internal: True - type: inout - }, - spi_sck: { - num: 1, - type: inout - }, - spi_cs: { - num: 2, - type: inout - }, - spi_sd: { - num: 4, - type: inout - }, - spi2_cs_0: { - num: 1, - type: inout - mux: { - spi2_cs_0: { - type: inout - }, - gpio_23: { - type: inout - }, - } - }, - spi2_cs_1: { - num: 1, - type: inout - mux: { - spi2_cs_1: { - type: inout - }, - gpio_24: { - type: inout - }, - }, - }, - spi2_sck: { - num: 1, - type: inout - mux: { - spi2_sck: { - type: inout - }, - gpio_25: { - type: inout - }, - } - }, - spi2_sd_0: { - num: 1, - type: inout - mux: { - spi2_sd_0: { - type: inout - }, - gpio_26: { - type: inout - }, - } - }, - spi2_sd_1: { - num: 1, - type: inout - mux: { - spi2_sd_1: { - type: inout - }, - gpio_27: { - type: inout - }, - } - }, - spi2_sd_2: { - num: 1, - type: inout - mux: { - spi2_sd_2: { - type: inout - }, - gpio_28: { - type: inout - }, - } - }, - spi2_sd_3: { - num: 1, - type: inout - mux: { - spi2_sd_3: { - type: inout - }, - gpio_29: { - type: inout - }, - } - }, - i2c_scl: { - num: 1, - type: inout - mux: { - i2c_scl: { - type: inout - }, - gpio_31: { - type: inout - }, - } - }, - i2c_sda: { - num: 1, - type: inout - mux: { - i2c_sda: { - type: inout - }, - gpio_30: { - type: inout - }, - } - } - } -} diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/rtl/axi_address_hijacker.v b/hw/vendor/esl_epfl_x_heep/linux_femu/rtl/axi_address_hijacker.v deleted file mode 100644 index e99c60e8..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/rtl/axi_address_hijacker.v +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright 2022 EPFL -// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 - -module axi_address_hijacker # -( - parameter integer AXI_ADDR_WIDTH = 32, - parameter integer C_S_AXI_DATA_WIDTH = 32, - parameter integer C_S_AXI_ADDR_WIDTH = 4 -)( - input wire [AXI_ADDR_WIDTH-1:0] axi_master_awaddr_in, - input wire [AXI_ADDR_WIDTH-1:0] axi_master_araddr_in, - - output wire [AXI_ADDR_WIDTH-1:0] axi_master_araddr_out, - output wire [AXI_ADDR_WIDTH-1:0] axi_master_awaddr_out, - - ///////////////////////////////////////// - // AXI-Lite slave interface - ///////////////////////////////////////// - - // clock and reset - input wire S_AXI_ACLK, - input wire S_AXI_ARESETN, - - // write address - input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, - input wire [2 : 0] S_AXI_AWPROT, - input wire S_AXI_AWVALID, - output wire S_AXI_AWREADY, - - // write data - input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, - input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB, - input wire S_AXI_WVALID, - output wire S_AXI_WREADY, - - // write response - output wire [1 : 0] S_AXI_BRESP, - output wire S_AXI_BVALID, - input wire S_AXI_BREADY, - - // read address - input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, - input wire [2 : 0] S_AXI_ARPROT, - input wire S_AXI_ARVALID, - output wire S_AXI_ARREADY, - - // read data - output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, - output wire [1 : 0] S_AXI_RRESP, - output wire S_AXI_RVALID, - input wire S_AXI_RREADY -); - - reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr; - reg axi_awready; - reg axi_wready; - reg [1 : 0] axi_bresp; - reg axi_bvalid; - reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr; - reg axi_arready; - reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata; - reg [1 : 0] axi_rresp; - reg axi_rvalid; - - localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1; - localparam integer OPT_MEM_ADDR_BITS = 1; - - reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg0; - reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg1; - reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg2; - reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg3; - wire slv_reg_rden; - wire slv_reg_wren; - reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out; - integer byte_index; - reg aw_en; - - assign S_AXI_AWREADY = axi_awready; - assign S_AXI_WREADY = axi_wready; - assign S_AXI_BRESP = axi_bresp; - assign S_AXI_BVALID = axi_bvalid; - assign S_AXI_ARREADY = axi_arready; - assign S_AXI_RDATA = axi_rdata; - assign S_AXI_RRESP = axi_rresp; - assign S_AXI_RVALID = axi_rvalid; - - // Implement axi_awready generation - // axi_awready is asserted for one S_AXI_ACLK clock cycle when both - // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is - // de-asserted when reset is low. - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_awready <= 1'b0; - aw_en <= 1'b1; - end - else - begin - if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) - begin - axi_awready <= 1'b1; - aw_en <= 1'b0; - end - else if (S_AXI_BREADY && axi_bvalid) - begin - aw_en <= 1'b1; - axi_awready <= 1'b0; - end - else - begin - axi_awready <= 1'b0; - end - end - end - - // Implement axi_awaddr latching - // This process is used to latch the address when both - // S_AXI_AWVALID and S_AXI_WVALID are valid. - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_awaddr <= 0; - end - else - begin - if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) - begin - axi_awaddr <= S_AXI_AWADDR; - end - end - end - - // Implement axi_wready generation - // axi_wready is asserted for one S_AXI_ACLK clock cycle when both - // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is - // de-asserted when reset is low. - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_wready <= 1'b0; - end - else - begin - if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en ) - begin - axi_wready <= 1'b1; - end - else - begin - axi_wready <= 1'b0; - end - end - end - - // Implement memory mapped register select and write logic generation - // The write data is accepted and written to memory mapped registers when - // axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to - // select byte enables of slave registers while writing. - // These registers are cleared when reset (active low) is applied. - // Slave register write enable is asserted when valid address and data are available - // and the slave is ready to accept the write address and write data. - assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID; - - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - slv_reg0 <= 0; - slv_reg1 <= 0; - slv_reg2 <= 0; - slv_reg3 <= 0; - end - else begin - if (slv_reg_wren) - begin - case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] ) - 2'h0: - for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) - if ( S_AXI_WSTRB[byte_index] == 1 ) begin - slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; - end - 2'h1: - for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) - if ( S_AXI_WSTRB[byte_index] == 1 ) begin - slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; - end - 2'h2: - for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) - if ( S_AXI_WSTRB[byte_index] == 1 ) begin - slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; - end - 2'h3: - for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) - if ( S_AXI_WSTRB[byte_index] == 1 ) begin - slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; - end - default : begin - slv_reg0 <= slv_reg0; - slv_reg1 <= slv_reg1; - slv_reg2 <= slv_reg2; - slv_reg3 <= slv_reg3; - end - endcase - end - end - end - - // Implement write response logic generation - // The write response and response valid signals are asserted by the slave - // when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. - // This marks the acceptance of address and indicates the status of - // write transaction. - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_bvalid <= 0; - axi_bresp <= 2'b0; - end - else - begin - if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID) - begin - axi_bvalid <= 1'b1; - axi_bresp <= 2'b0; - end - else - begin - if (S_AXI_BREADY && axi_bvalid) - begin - axi_bvalid <= 1'b0; - end - end - end - end - - // Implement axi_arready generation - // axi_arready is asserted for one S_AXI_ACLK clock cycle when - // S_AXI_ARVALID is asserted. axi_awready is - // de-asserted when reset (active low) is asserted. - // The read address is also latched when S_AXI_ARVALID is - // asserted. axi_araddr is reset to zero on reset assertion. - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_arready <= 1'b0; - axi_araddr <= 32'b0; - end - else - begin - if (~axi_arready && S_AXI_ARVALID) - begin - axi_arready <= 1'b1; - axi_araddr <= S_AXI_ARADDR; - end - else - begin - axi_arready <= 1'b0; - end - end - end - - // Implement axi_arvalid generation - // axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both - // S_AXI_ARVALID and axi_arready are asserted. The slave registers - // data are available on the axi_rdata bus at this instance. The - // assertion of axi_rvalid marks the validity of read data on the - // bus and axi_rresp indicates the status of read transaction.axi_rvalid - // is deasserted on reset (active low). axi_rresp and axi_rdata are - // cleared to zero on reset (active low). - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_rvalid <= 0; - axi_rresp <= 0; - end - else - begin - if (axi_arready && S_AXI_ARVALID && ~axi_rvalid) - begin - axi_rvalid <= 1'b1; - axi_rresp <= 2'b0; - end - else if (axi_rvalid && S_AXI_RREADY) - begin - axi_rvalid <= 1'b0; - end - end - end - - // Implement memory mapped register select and read logic generation - // Slave register read enable is asserted when valid address is available - // and the slave is ready to accept the read address. - assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid; - always @(*) - begin - case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] ) - 2'h0 : reg_data_out <= slv_reg0; - 2'h1 : reg_data_out <= slv_reg1; - 2'h2 : reg_data_out <= slv_reg2; - 2'h3 : reg_data_out <= slv_reg3; - default : reg_data_out <= 0; - endcase - end - - // Output register or memory read data - always @( posedge S_AXI_ACLK ) - begin - if ( S_AXI_ARESETN == 1'b0 ) - begin - axi_rdata <= 0; - end - else - begin - if (slv_reg_rden) - begin - axi_rdata <= reg_data_out; - end - end - end - - assign axi_master_araddr_out = axi_master_araddr_in + slv_reg0; - assign axi_master_awaddr_out = axi_master_awaddr_in + slv_reg0; - - endmodule diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/rtl/linux_femu.sv.tpl b/hw/vendor/esl_epfl_x_heep/linux_femu/rtl/linux_femu.sv.tpl deleted file mode 100644 index ef5dad9b..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/rtl/linux_femu.sv.tpl +++ /dev/null @@ -1,533 +0,0 @@ -// Copyright 2022 EPFL -// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 - -module linux_femu - import obi_pkg::*; - import reg_pkg::*; -#( - parameter COREV_PULP = 0, - parameter FPU = 0, - parameter ZFINX = 0, - parameter EXT_XBAR_NMASTER = 0, - parameter CLK_LED_COUNT_LENGTH = 27 -) ( - inout logic clk_in, - inout logic rst_i, - - output logic rst_led, - output logic clk_led, - output logic clk_out, - - inout logic boot_select_i, - inout logic execute_from_flash_i, - - inout logic [29:0] gpio_io, - - output logic exit_value_o, - inout logic exit_valid_o, - - inout logic spi_sd_0_io, - inout logic spi_sd_1_io, - inout logic spi_sd_2_io, - inout logic spi_sd_3_io, - inout logic spi_csb_io, - inout logic spi_sck_io, - - inout logic spi2_sd_0_io, - inout logic spi2_sd_1_io, - inout logic spi2_sd_2_io, - inout logic spi2_sd_3_io, - inout logic [1:0] spi2_csb_io, - inout logic spi2_sck_io, - - inout logic i2c_scl_io, - inout logic i2c_sda_io, - - inout wire [14:0] DDR_addr, - inout wire [2:0] DDR_ba, - inout wire DDR_cas_n, - inout wire DDR_ck_n, - inout wire DDR_ck_p, - inout wire DDR_cke, - inout wire DDR_cs_n, - inout wire [3:0] DDR_dm, - inout wire [31:0] DDR_dq, - inout wire [3:0] DDR_dqs_n, - inout wire [3:0] DDR_dqs_p, - inout wire DDR_odt, - inout wire DDR_ras_n, - inout wire DDR_reset_n, - inout wire DDR_we_n, - inout wire FIXED_IO_ddr_vrn, - inout wire FIXED_IO_ddr_vrp, - inout wire [53:0] FIXED_IO_mio, - inout wire FIXED_IO_ps_clk, - inout wire FIXED_IO_ps_porb, - inout wire FIXED_IO_ps_srstb -); - - import core_v_mini_mcu_pkg::*; - - parameter AXI_ADDR_WIDTH = 32; - parameter AXI_ADDR_WIDTH_SLAVE = 4; - parameter AXI_DATA_WIDTH = 32; - - // PM signals - logic cpu_subsystem_powergate_switch; - logic cpu_subsystem_powergate_switch_ack; - logic cpu_subsystem_powergate_iso; - logic cpu_subsystem_rst_n; - logic peripheral_subsystem_powergate_switch; - logic peripheral_subsystem_powergate_switch_ack; - logic peripheral_subsystem_powergate_iso; - logic peripheral_subsystem_rst_n; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_ack; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_iso; - logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_set_retentive; - - // PS SIDE PORTS - logic AXI_HP_ACLK; - logic AXI_HP_ARESETN; - logic [AXI_ADDR_WIDTH - 1:0] AXI_HP_araddr_sig; - logic [1:0] AXI_HP_arburst_sig; - logic [3:0] AXI_HP_arcache_sig; - logic [5:0] AXI_HP_arid_sig; - logic [3:0] AXI_HP_arlen_sig; - logic [1:0] AXI_HP_arlock_sig; - logic [2:0] AXI_HP_arprot_sig; - logic [3:0] AXI_HP_arqos_sig; - logic AXI_HP_arready_sig; - logic [2:0] AXI_HP_arsize_sig; - logic AXI_HP_arvalid_sig; - logic [AXI_ADDR_WIDTH - 1:0] AXI_HP_awaddr_sig; - logic [1:0] AXI_HP_awburst_sig; - logic [3:0] AXI_HP_awcache_sig; - logic [5:0] AXI_HP_awid_sig; - logic [3:0] AXI_HP_awlen_sig; - logic [1:0] AXI_HP_awlock_sig; - logic [2:0] AXI_HP_awprot_sig; - logic [3:0] AXI_HP_awqos_sig; - logic AXI_HP_awready_sig; - logic [2:0] AXI_HP_awsize_sig; - logic AXI_HP_awvalid_sig; - logic [5:0] AXI_HP_bid_sig; - logic AXI_HP_bready_sig; - logic [1:0] AXI_HP_bresp_sig; - logic AXI_HP_bvalid_sig; - logic [AXI_DATA_WIDTH - 1:0] AXI_HP_rdata_sig; - logic [5:0] AXI_HP_rid_sig; - logic AXI_HP_rlast_sig; - logic AXI_HP_rready_sig; - logic [1:0] AXI_HP_rresp_sig; - logic AXI_HP_rvalid_sig; - logic [AXI_DATA_WIDTH - 1:0] AXI_HP_wdata_sig; - logic [5:0] AXI_HP_wid_sig; - logic AXI_HP_wlast_sig; - logic AXI_HP_wready_sig; - logic [3:0] AXI_HP_wstrb_sig; - logic AXI_HP_wvalid_sig; - - logic spi_test_clk_sig; - logic spi_test_cs_sig; - logic [3:0] spi_test_data_sig; - - // ADDRESS HIJACKER PORTS - logic [AXI_ADDR_WIDTH-1:0] axi_master_awaddr_in_sig; - logic [AXI_ADDR_WIDTH-1:0] axi_master_araddr_in_sig; - - logic [AXI_ADDR_WIDTH_SLAVE - 1 : 0] s00_axi_awaddr_sig; - logic s00_axi_awvalid_sig; - logic s00_axi_awready_sig; - logic [AXI_DATA_WIDTH - 1 : 0] s00_axi_wdata_sig; - logic s00_axi_wvalid_sig; - logic s00_axi_wready_sig; - logic s00_axi_bvalid_sig; - logic s00_axi_bready_sig; - logic [(AXI_DATA_WIDTH / 8)-1 : 0] s00_axi_wstrb_sig; - logic [2 : 0] s00_axi_arprot_sig; - logic [2 : 0] s00_axi_awprot_sig; - logic [AXI_ADDR_WIDTH_SLAVE - 1 : 0] s00_axi_araddr_sig; - logic s00_axi_arvalid_sig; - logic s00_axi_arready_sig; - logic [AXI_DATA_WIDTH - 1 : 0] s00_axi_rdata_sig; - logic s00_axi_rvalid_sig; - logic s00_axi_rready_sig; - logic [1:0] s00_axi_rresp_sig; - logic [1:0] s00_axi_bresp_sig; - - // PAD controller - reg_req_t pad_req; - reg_rsp_t pad_resp; - logic [core_v_mini_mcu_pkg::NUM_PAD-1:0][7:0] pad_attributes; - logic [core_v_mini_mcu_pkg::NUM_PAD-1:0][3:0] pad_muxes; - - logic rst_ngen; - - // input, output pins from core_v_mini_mcu -% for pad in total_pad_list: -${pad.internal_signals} -% endfor - - wire clk_gen; - logic [ 31:0] exit_value; - wire rst_n; - logic [CLK_LED_COUNT_LENGTH - 1:0] clk_count; - - // low active reset - assign rst_n = !rst_i; - - // reset LED for debugging - assign rst_led = rst_n; - - // counter to blink an LED - assign clk_led = clk_count[CLK_LED_COUNT_LENGTH-1]; - - always_ff @(posedge clk_gen or negedge rst_n) begin : clk_count_process - if (!rst_n) begin - clk_count <= '0; - end else begin - clk_count <= clk_count + 1; - end - end - - // clock output for debugging - assign clk_out = clk_gen; - - xilinx_clk_wizard_wrapper xilinx_clk_wizard_wrapper_i ( - .clk_125MHz(clk_in), - .clk_out1_0(clk_gen) - ); - - // eXtension Interface - if_xif #() ext_if (); - - logic clk_i; - assign clk_i = clk_gen; - - core_v_mini_mcu #( - .COREV_PULP(COREV_PULP), - .FPU(FPU), - .ZFINX(ZFINX), - .EXT_XBAR_NMASTER(EXT_XBAR_NMASTER) - ) core_v_mini_mcu_i ( - - .rst_ni(rst_ngen), -% for pad in pad_list: -${pad.core_v_mini_mcu_bonding} -% endfor - .intr_vector_ext_i('0), - .xif_compressed_if(ext_if), - .xif_issue_if(ext_if), - .xif_commit_if(ext_if), - .xif_mem_if(ext_if), - .xif_mem_result_if(ext_if), - .xif_result_if(ext_if), - .ext_xbar_master_req_i('0), - .ext_xbar_master_resp_o(), - .ext_core_instr_req_o(), - .ext_core_instr_resp_i('0), - .ext_core_data_req_o(), - .ext_core_data_resp_i('0), - .ext_debug_master_req_o(), - .ext_debug_master_resp_i('0), - .ext_dma_read_ch0_req_o(), - .ext_dma_read_ch0_resp_i('0), - .ext_dma_write_ch0_req_o(), - .ext_dma_write_ch0_resp_i('0), - .ext_dma_addr_ch0_req_o(), - .ext_dma_addr_ch0_resp_i('0), - .ext_peripheral_slave_req_o(), - .ext_peripheral_slave_resp_i('0), - .external_subsystem_powergate_switch_o(), - .external_subsystem_powergate_switch_ack_i(), - .external_subsystem_powergate_iso_o(), - .external_subsystem_rst_no(), - .external_ram_banks_set_retentive_o(), - .exit_value_o(exit_value), - .pad_req_o(pad_req), - .pad_resp_i(pad_resp), - .cpu_subsystem_powergate_switch_o(cpu_subsystem_powergate_switch), - .cpu_subsystem_powergate_switch_ack_i(cpu_subsystem_powergate_switch_ack), - .peripheral_subsystem_powergate_switch_o(peripheral_subsystem_powergate_switch), - .peripheral_subsystem_powergate_switch_ack_i(peripheral_subsystem_powergate_switch_ack), - .memory_subsystem_banks_powergate_switch_o(memory_subsystem_banks_powergate_switch), - .memory_subsystem_banks_powergate_switch_ack_i(memory_subsystem_banks_powergate_switch_ack) - ); - - logic gpio_0_io; - logic gpio_1_io; - logic gpio_2_io; - logic gpio_3_io; - logic gpio_4_io; - logic gpio_5_io; - logic gpio_6_io; - logic gpio_7_io; - logic gpio_8_io; - logic gpio_9_io; - logic gpio_10_io; - logic gpio_11_io; - logic gpio_12_io; - logic gpio_13_io; - logic gpio_14_io; - logic gpio_15_io; - logic gpio_16_io; - logic gpio_17_io; - logic gpio_18_io; - logic gpio_19_io; - logic gpio_20_io; - logic gpio_21_io; - logic gpio_22_io; - - assign spi_flash_sck_o_sig = spi_flash_sck_out_x; - assign spi_flash_csb_o_sig = spi_flash_cs_0_out_x; - assign spi_sdi1_sig = spi_flash_sd_1_in_x; - assign spi_sdo0_sig = spi_flash_sd_0_out_x; - assign spi_sdo2_sig = spi_sd_2_out_x; - assign spi_sdo3_sig = spi_sd_3_out_x; - - assign spi2_csb_io[0] = spi2_cs_0_io; - assign spi2_csb_io[1] = spi2_cs_1_io; - - assign gpio_io[0] = gpio_0_io; - assign gpio_io[1] = gpio_1_io; - assign gpio_io[2] = gpio_2_io; - assign gpio_io[3] = gpio_3_io; - assign gpio_io[4] = gpio_4_io; - assign gpio_io[5] = gpio_5_io; - assign gpio_io[6] = gpio_6_io; - assign gpio_io[7] = gpio_7_io; - assign gpio_io[8] = gpio_8_io; - assign gpio_io[9] = gpio_9_io; - assign gpio_io[10] = gpio_10_io; - assign gpio_io[11] = gpio_11_io; - assign gpio_io[12] = gpio_12_io; - assign gpio_io[13] = gpio_13_io; - assign gpio_io[14] = gpio_14_io; - assign gpio_io[15] = gpio_15_io; - assign gpio_io[16] = gpio_16_io; - assign gpio_io[17] = gpio_17_io; - assign gpio_io[18] = gpio_18_io; - assign gpio_io[19] = gpio_19_io; - assign gpio_io[20] = gpio_20_io; - assign gpio_io[21] = gpio_21_io; - assign gpio_io[22] = gpio_22_io; - - processing_system_wrapper processing_system_wrapper_i ( - .DDR_addr(DDR_addr), - .DDR_ba(DDR_ba), - .DDR_cas_n(DDR_cas_n), - .DDR_ck_n(DDR_ck_n), - .DDR_ck_p(DDR_ck_p), - .DDR_cke(DDR_cke), - .DDR_cs_n(DDR_cs_n), - .DDR_dm(DDR_dm), - .DDR_dq(DDR_dq), - .DDR_dqs_n(DDR_dqs_n), - .DDR_dqs_p(DDR_dqs_p), - .DDR_odt(DDR_odt), - .DDR_ras_n(DDR_ras_n), - .DDR_reset_n(DDR_reset_n), - .DDR_we_n(DDR_we_n), - .FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn), - .FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp), - .FIXED_IO_mio(FIXED_IO_mio), - .FIXED_IO_ps_clk(FIXED_IO_ps_clk), - .FIXED_IO_ps_porb(FIXED_IO_ps_porb), - .FIXED_IO_ps_srstb(FIXED_IO_ps_srstb), - .UART_rxd(uart_tx_out_x), - .UART_txd(uart_rx_in_x), - .gpio_jtag_tck_i(jtag_tck_in_x), - .gpio_jtag_tms_i(jtag_tms_in_x), - .gpio_jtag_trst_ni(jtag_trst_nin_x), - .gpio_jtag_tdi_i(jtag_tdi_in_x), - .gpio_jtag_tdo_o(jtag_tdo_out_x), - .AXI_HP_ACLK(AXI_HP_ACLK), - .AXI_HP_ARESETN(AXI_HP_ARESETN), - .AXI_HP_araddr(AXI_HP_araddr_sig), - .AXI_HP_arburst(AXI_HP_arburst_sig), - .AXI_HP_arcache(AXI_HP_arcache_sig), - .AXI_HP_arlen(AXI_HP_arlen_sig), - .AXI_HP_arlock(AXI_HP_arlock_sig), - .AXI_HP_arprot(AXI_HP_arprot_sig), - .AXI_HP_arqos(AXI_HP_arqos_sig), - .AXI_HP_arready(AXI_HP_arready_sig), - .AXI_HP_arsize(AXI_HP_arsize_sig), - .AXI_HP_arvalid(AXI_HP_arvalid_sig), - .AXI_HP_awaddr(AXI_HP_awaddr_sig), - .AXI_HP_awburst(AXI_HP_awburst_sig), - .AXI_HP_awcache(AXI_HP_awcache_sig), - .AXI_HP_awlen(AXI_HP_awlen_sig), - .AXI_HP_awlock(AXI_HP_awlock_sig), - .AXI_HP_awprot(AXI_HP_awprot_sig), - .AXI_HP_awqos(AXI_HP_awqos_sig), - .AXI_HP_awready(AXI_HP_awready_sig), - .AXI_HP_awsize(AXI_HP_awsize_sig), - .AXI_HP_awvalid(AXI_HP_awvalid_sig), - .AXI_HP_bready(AXI_HP_bready_sig), - .AXI_HP_bresp(AXI_HP_bresp_sig), - .AXI_HP_bvalid(AXI_HP_bvalid_sig), - .AXI_HP_rdata(AXI_HP_rdata_sig), - .AXI_HP_rlast(AXI_HP_rlast_sig), - .AXI_HP_rready(AXI_HP_rready_sig), - .AXI_HP_rresp(AXI_HP_rresp_sig), - .AXI_HP_rvalid(AXI_HP_rvalid_sig), - .AXI_HP_wdata(AXI_HP_wdata_sig), - .AXI_HP_wlast(AXI_HP_wlast_sig), - .AXI_HP_wready(AXI_HP_wready_sig), - .AXI_HP_wstrb(AXI_HP_wstrb_sig), - .AXI_HP_wvalid(AXI_HP_wvalid_sig), - .M_AXI_araddr(s00_axi_araddr_sig), - .M_AXI_arready(s00_axi_arready_sig), - .M_AXI_arvalid(s00_axi_arvalid_sig), - .M_AXI_awaddr(s00_axi_awaddr_sig), - .M_AXI_awready(s00_axi_awready_sig), - .M_AXI_awvalid(s00_axi_awvalid_sig), - .M_AXI_bready(s00_axi_bready_sig), - .M_AXI_bresp(s00_axi_bresp_sig), - .M_AXI_bvalid(s00_axi_bvalid_sig), - .M_AXI_rdata(s00_axi_rdata_sig), - .M_AXI_rready(s00_axi_rready_sig), - .M_AXI_rresp(s00_axi_rresp_sig), - .M_AXI_rvalid(s00_axi_rvalid_sig), - .M_AXI_wdata(s00_axi_wdata_sig), - .M_AXI_wready(s00_axi_wready_sig), - .M_AXI_wvalid(s00_axi_wvalid_sig), - .M_AXI_awprot(s00_axi_awprot_sig), - .M_AXI_arprot(s00_axi_arprot_sig), - .M_AXI_wstrb(s00_axi_wstrb_sig) - ); - - axi_address_hijacker #( - .AXI_ADDR_WIDTH(AXI_ADDR_WIDTH), - .C_S_AXI_DATA_WIDTH(AXI_DATA_WIDTH) - ) add_hij ( - .axi_master_awaddr_in(axi_master_awaddr_in_sig), - .axi_master_araddr_in(axi_master_araddr_in_sig), - - // output write and read address by adding fixed offset - .axi_master_araddr_out(AXI_HP_araddr_sig), - .axi_master_awaddr_out(AXI_HP_awaddr_sig), - - .S_AXI_ACLK(AXI_HP_ACLK), - .S_AXI_ARESETN(AXI_HP_ARESETN), - - .S_AXI_AWADDR (s00_axi_awaddr_sig), - .S_AXI_AWPROT (s00_axi_awprot_sig), - .S_AXI_AWVALID(s00_axi_awvalid_sig), - .S_AXI_AWREADY(s00_axi_awready_sig), - .S_AXI_WDATA (s00_axi_wdata_sig), - .S_AXI_WSTRB (s00_axi_wstrb_sig), - .S_AXI_WVALID (s00_axi_wvalid_sig), - .S_AXI_WREADY (s00_axi_wready_sig), - .S_AXI_BRESP (s00_axi_bresp_sig), - .S_AXI_BVALID (s00_axi_bvalid_sig), - .S_AXI_BREADY (s00_axi_bready_sig), - .S_AXI_ARADDR (s00_axi_araddr_sig), - .S_AXI_ARPROT (s00_axi_arprot_sig), - .S_AXI_ARVALID(s00_axi_arvalid_sig), - .S_AXI_ARREADY(s00_axi_arready_sig), - .S_AXI_RDATA (s00_axi_rdata_sig), - .S_AXI_RRESP (s00_axi_rresp_sig), - .S_AXI_RVALID (s00_axi_rvalid_sig), - .S_AXI_RREADY (s00_axi_rready_sig) - ); - - axi_spi_slave #( - .AXI_DATA_WIDTH(AXI_DATA_WIDTH) - ) fake_flash ( - .axi_aclk(AXI_HP_ACLK), - .axi_aresetn(AXI_HP_ARESETN), - - .test_mode('0), - - .axi_master_aw_valid(AXI_HP_awvalid_sig), - .axi_master_aw_id(AXI_HP_awid_sig), - .axi_master_aw_prot(AXI_HP_awprot_sig), - .axi_master_aw_qos(AXI_HP_awqos_sig), - .axi_master_aw_cache(AXI_HP_awcache_sig), - .axi_master_aw_lock(AXI_HP_awlock_sig), - .axi_master_aw_burst(AXI_HP_awburst_sig), - .axi_master_aw_size(AXI_HP_awsize_sig), - .axi_master_aw_len(AXI_HP_awlen_sig), - .axi_master_aw_addr(axi_master_awaddr_in_sig), - .axi_master_aw_ready(AXI_HP_awready_sig), - - .axi_master_w_valid(AXI_HP_wvalid_sig), - .axi_master_w_data (AXI_HP_wdata_sig), - .axi_master_w_strb (AXI_HP_wstrb_sig), - .axi_master_w_last (AXI_HP_wlast_sig), - .axi_master_w_ready(AXI_HP_wready_sig), - - .axi_master_b_valid(AXI_HP_bvalid_sig), - .axi_master_b_id(AXI_HP_bid_sig), - .axi_master_b_resp(AXI_HP_bresp_sig), - .axi_master_b_ready(AXI_HP_bready_sig), - - .axi_master_ar_valid(AXI_HP_arvalid_sig), - .axi_master_ar_id(AXI_HP_arid_sig), - .axi_master_ar_prot(AXI_HP_arprot_sig), - .axi_master_ar_qos(AXI_HP_arqos_sig), - .axi_master_ar_cache(AXI_HP_arcache_sig), - .axi_master_ar_lock(AXI_HP_arlock_sig), - .axi_master_ar_burst(AXI_HP_arburst_sig), - .axi_master_ar_size(AXI_HP_arsize_sig), - .axi_master_ar_len(AXI_HP_arlen_sig), - .axi_master_ar_addr(axi_master_araddr_in_sig), - .axi_master_ar_ready(AXI_HP_arready_sig), - - .axi_master_r_valid(AXI_HP_rvalid_sig), - .axi_master_r_id(AXI_HP_rid_sig), - .axi_master_r_data(AXI_HP_rdata_sig), - .axi_master_r_resp(AXI_HP_rresp_sig), - .axi_master_r_last(AXI_HP_rlast_sig), - .axi_master_r_ready(AXI_HP_rready_sig), - - .spi_sclk(spi_flash_sck_o_sig), - .spi_cs (spi_flash_csb_o_sig), - .spi_sdo1(spi_sdi1_sig), - .spi_sdi0(spi_sdo0_sig), - .spi_sdi2(spi_sdo2_sig), - .spi_sdi3(spi_sdo3_sig) - ); - - // TESTING PURPOSES -> THEY WILL BE INPUT TO PS AND READ BY SYSTEM ILA - assign spi_test_clk_sig = spi_flash_sck_o_sig; - assign spi_test_cs_sig = spi_flash_csb_o_sig; - assign spi_test_data_sig = {spi_sdo0_sig, spi_sdi1_sig, spi_sdo2_sig, spi_sdo3_sig}; - - pad_ring pad_ring_i ( -% for pad in total_pad_list: -${pad.pad_ring_bonding_bonding} -% endfor - .pad_attributes_i(pad_attributes) - ); - -${pad_constant_driver_assign} - -${pad_mux_process} - - pad_control #( - .reg_req_t(reg_pkg::reg_req_t), - .reg_rsp_t(reg_pkg::reg_rsp_t), - .NUM_PAD (core_v_mini_mcu_pkg::NUM_PAD) - ) pad_control_i ( - .clk_i(clk_in_x), - .rst_ni(rst_ngen), - .reg_req_i(pad_req), - .reg_rsp_o(pad_resp), - .pad_attributes_o(pad_attributes), - .pad_muxes_o(pad_muxes) - ); - - rstgen rstgen_i ( - .clk_i(clk_in_x), - .rst_ni(rst_n), - .test_mode_i(1'b0), - .rst_no(rst_ngen), - .init_no() - ); - - assign exit_value_o = exit_value[0]; -endmodule diff --git a/hw/vendor/esl_epfl_x_heep/linux_femu/scripts/xilinx_generate_processing_system.tcl b/hw/vendor/esl_epfl_x_heep/linux_femu/scripts/xilinx_generate_processing_system.tcl deleted file mode 100644 index a4628c5b..00000000 --- a/hw/vendor/esl_epfl_x_heep/linux_femu/scripts/xilinx_generate_processing_system.tcl +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright 2022 EPFL -# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. -# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -# Define design macros - -# Select board -set_property board_part tul.com.tw:pynq-z2:part0:1.0 [current_project] - -# Create block design -create_bd_design "processing_system" - -# Add Zynq Processing System -create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 processing_system7_0 -apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 -config {make_external "FIXED_IO, DDR" apply_board_preset "1" Master "Disable" Slave "Disable" } [get_bd_cells processing_system7_0] -set_property -dict [list CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {20} CONFIG.PCW_USE_S_AXI_HP0 {1} CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {0} CONFIG.PCW_SD0_PERIPHERAL_ENABLE {0} CONFIG.PCW_UART0_PERIPHERAL_ENABLE {0} CONFIG.PCW_UART1_PERIPHERAL_ENABLE {1} CONFIG.PCW_UART1_UART1_IO {EMIO} CONFIG.PCW_USB0_PERIPHERAL_ENABLE {0} CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {0} CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {1} CONFIG.PCW_GPIO_EMIO_GPIO_IO {5}] [get_bd_cells processing_system7_0] - -# Add AXI Interconnect -create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_interconnect_0 -set_property -dict [list CONFIG.NUM_SI {2} CONFIG.NUM_MI {2}] [get_bd_cells axi_interconnect_0] - -# Add Constant -create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_0 -set_property -dict [list CONFIG.CONST_WIDTH {2} CONFIG.CONST_VAL {0b11}] [get_bd_cells xlconstant_0] - -# Add Concatenation -create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 -set_property -dict [list CONFIG.IN0_WIDTH.VALUE_SRC USER CONFIG.IN1_WIDTH.VALUE_SRC USER CONFIG.IN2_WIDTH.VALUE_SRC USER] [get_bd_cells xlconcat_0] -set_property -dict [list CONFIG.NUM_PORTS {3} CONFIG.IN0_WIDTH {2} CONFIG.IN2_WIDTH {2}] [get_bd_cells xlconcat_0] - -# Add Slices -create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_0 -create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_1 -create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_2 -create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_3 -set_property -dict [list CONFIG.DIN_TO {3} CONFIG.DIN_FROM {3} CONFIG.DIN_WIDTH {5} CONFIG.DOUT_WIDTH {1}] [get_bd_cells xlslice_0] -set_property -dict [list CONFIG.DIN_TO {4} CONFIG.DIN_FROM {4} CONFIG.DIN_WIDTH {5} CONFIG.DOUT_WIDTH {1}] [get_bd_cells xlslice_1] -set_property -dict [list CONFIG.DIN_TO {1} CONFIG.DIN_FROM {1} CONFIG.DIN_WIDTH {5} CONFIG.DOUT_WIDTH {1}] [get_bd_cells xlslice_2] -set_property -dict [list CONFIG.DIN_TO {0} CONFIG.DIN_FROM {0} CONFIG.DIN_WIDTH {5} CONFIG.DOUT_WIDTH {1}] [get_bd_cells xlslice_3] - -# Create port AXI_HP -make_bd_intf_pins_external [get_bd_intf_pins axi_interconnect_0/S00_AXI] -set_property name AXI_HP [get_bd_intf_ports S00_AXI_0] -set_property -dict [list CONFIG.FREQ_HZ {20000000}] [get_bd_intf_ports AXI_HP] - -# Create port M_AXI -make_bd_intf_pins_external [get_bd_intf_pins axi_interconnect_0/M01_AXI] -set_property name M_AXI [get_bd_intf_ports M01_AXI_0] -set_property -dict [list CONFIG.FREQ_HZ {20000000}] [get_bd_intf_ports M_AXI] - -# Connect AXI Interconnect and Zynq Processing System -connect_bd_intf_net -boundary_type upper [get_bd_intf_pins axi_interconnect_0/M00_AXI] [get_bd_intf_pins processing_system7_0/S_AXI_HP0] -connect_bd_intf_net [get_bd_intf_pins processing_system7_0/M_AXI_GP0] -boundary_type upper [get_bd_intf_pins axi_interconnect_0/S01_AXI] -apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/processing_system7_0/FCLK_CLK0 (20 MHz)} Freq {100} Ref_Clk0 {} Ref_Clk1 {} Ref_Clk2 {}} [get_bd_pins axi_interconnect_0/ACLK] -apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/processing_system7_0/FCLK_CLK0 (20 MHz)} Freq {100} Ref_Clk0 {} Ref_Clk1 {} Ref_Clk2 {}} [get_bd_pins axi_interconnect_0/M00_ACLK] -apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/processing_system7_0/FCLK_CLK0 (20 MHz)} Freq {100} Ref_Clk0 {} Ref_Clk1 {} Ref_Clk2 {}} [get_bd_pins axi_interconnect_0/M01_ACLK] -apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/processing_system7_0/FCLK_CLK0 (20 MHz)} Freq {100} Ref_Clk0 {} Ref_Clk1 {} Ref_Clk2 {}} [get_bd_pins axi_interconnect_0/S00_ACLK] -apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/processing_system7_0/FCLK_CLK0 (20 MHz)} Freq {100} Ref_Clk0 {} Ref_Clk1 {} Ref_Clk2 {}} [get_bd_pins axi_interconnect_0/S01_ACLK] - -# Create port AXI_HP_ACLK -create_bd_port -dir O -type clk AXI_HP_ACLK - -# Create port AXI_HP_ARESETN -create_bd_port -dir O -type rst AXI_HP_ARESETN - -# Connect AXI_HP_ACLK and AXI_HP_ARESETN -connect_bd_net [get_bd_ports AXI_HP_ACLK] [get_bd_pins processing_system7_0/FCLK_CLK0] -connect_bd_net [get_bd_ports AXI_HP_ARESETN] [get_bd_pins rst_ps7_0_20M/peripheral_aresetn] - -# Create port gpio_jtag_tdo_o -make_bd_pins_external [get_bd_pins xlconcat_0/In1] -set_property name gpio_jtag_tdo_o [get_bd_ports In1_0] - -# Connect Constant and Concatenation -connect_bd_net [get_bd_pins xlconstant_0/dout] [get_bd_pins xlconcat_0/In0] -connect_bd_net [get_bd_pins xlconcat_0/In2] [get_bd_pins xlconstant_0/dout] -connect_bd_net [get_bd_pins xlconcat_0/dout] [get_bd_pins processing_system7_0/GPIO_I] - -# Create port gpio_jtag_tdi_i -make_bd_pins_external [get_bd_pins xlslice_0/Dout] -set_property name gpio_jtag_tdi_i [get_bd_ports Dout_0] - -# Create port gpio_jtag_tck_i -make_bd_pins_external [get_bd_pins xlslice_1/Dout] -set_property name gpio_jtag_tck_i [get_bd_ports Dout_0] - -# Create port gpio_jtag_tms_i -make_bd_pins_external [get_bd_pins xlslice_2/Dout] -set_property name gpio_jtag_tms_i [get_bd_ports Dout_0] - -# Create port gpio_jtag_trst_ni -make_bd_pins_external [get_bd_pins xlslice_3/Dout] -set_property name gpio_jtag_trst_ni [get_bd_ports Dout_0] - -# Connect Slices -connect_bd_net [get_bd_pins xlslice_0/Din] [get_bd_pins processing_system7_0/GPIO_O] -connect_bd_net [get_bd_pins xlslice_1/Din] [get_bd_pins processing_system7_0/GPIO_O] -connect_bd_net [get_bd_pins xlslice_2/Din] [get_bd_pins processing_system7_0/GPIO_O] -connect_bd_net [get_bd_pins xlslice_3/Din] [get_bd_pins processing_system7_0/GPIO_O] - -# Create port UART -make_bd_intf_pins_external [get_bd_intf_pins processing_system7_0/UART_1] -set_property name UART [get_bd_intf_ports UART_1_0] - -# Assign addresses -assign_bd_address - -# Validate design -validate_bd_design - -# Save design -save_bd_design - -# Close design -close_bd_design [get_bd_designs processing_system] - -# Make wrapper -set wrapper_path [ make_wrapper -fileset sources_1 -files [ get_files -norecurse processing_system.bd ] -top ] -add_files -norecurse -fileset sources_1 $wrapper_path diff --git a/hw/vendor/esl_epfl_x_heep/logo/x-heep.png b/hw/vendor/esl_epfl_x_heep/logo/x-heep.png deleted file mode 100644 index 76814a07..00000000 Binary files a/hw/vendor/esl_epfl_x_heep/logo/x-heep.png and /dev/null differ diff --git a/hw/vendor/esl_epfl_x_heep/mcu_cfg.hjson b/hw/vendor/esl_epfl_x_heep/mcu_cfg.hjson index 4bc1e1df..316750e1 100644 --- a/hw/vendor/esl_epfl_x_heep/mcu_cfg.hjson +++ b/hw/vendor/esl_epfl_x_heep/mcu_cfg.hjson @@ -7,26 +7,9 @@ cpu_type: cv32e20 - bus_type: onetoM - - ram: { - address: 0x00000000, #only tried with 0, cannot be changed for now - numbanks: 2, #each bank is 32kB, cannot be changed for now - numbanks_interleaved: 0, - }, - linker_script: { - #value used for the on-chip linker script, the on-flash linker script is generated using FLASH values and the whole RAM values - onchip_ls: { - code: { - address: 0x00000000, - lenght: 0x00000C800, #minimum size for freeRTOS and clang - } - data: { - address: 0x00000C800, - lenght: whatisleft, #keyword used to calculate the size as: ram.length - code.lenght - } - }, + stack_size: 0x800, + heap_size: 0x800, } debug: { @@ -54,10 +37,14 @@ offset: 0x00028000, length: 0x00008000, }, - spi_host: { + dma: { offset: 0x00030000, length: 0x00010000, - path: "./hw/vendor/lowrisc_opentitan_spi_host/data/spi_host.hjson" + ch_length: 0x100, + num_channels: 0x1, + num_master_ports: 0x1, + num_channels_per_master_port: 0x1, + path: "./hw/ip/dma/data/dma.hjson" }, power_manager: { offset: 0x00040000, @@ -68,30 +55,25 @@ offset: 0x00050000, length: 0x00010000, }, - dma: { - offset: 0x00060000, - length: 0x00010000, - path: "./hw/ip/dma/data/dma.hjson" - }, fast_intr_ctrl: { - offset: 0x00070000, + offset: 0x00060000, length: 0x00010000, path: "./hw/ip/fast_intr_ctrl/data/fast_intr_ctrl.hjson" }, ext_peripheral: { - offset: 0x00080000, + offset: 0x00070000, length: 0x00010000, }, pad_control: { - offset: 0x00090000, + offset: 0x00080000, length: 0x00010000, }, gpio_ao: { - offset: 0x000A0000, + offset: 0x00090000, length: 0x00010000, }, uart: { - offset: 0x000B0000, + offset: 0x000A0000, length: 0x00010000, path: "./hw/vendor/lowrisc_opentitan/hw/ip/uart/data/uart.hjson" }, @@ -106,6 +88,12 @@ is_included: "yes", path: "./hw/vendor/lowrisc_opentitan/hw/ip/rv_plic/data/rv_plic.hjson" }, + spi_host: { + offset: 0x00010000, + length: 0x00010000, + is_included: "yes", + path: "./hw/vendor/lowrisc_opentitan_spi_host/data/spi_host.hjson" + }, gpio: { offset: 0x00020000, length: 0x00010000, @@ -141,6 +129,7 @@ is_included: "yes", path: "./hw/ip/i2s/data/i2s.hjson" }, + }, flash_mem: { diff --git a/hw/vendor/esl_epfl_x_heep/mcu_cfg_minimal.hjson b/hw/vendor/esl_epfl_x_heep/mcu_cfg_minimal.hjson index 98440522..d496c274 100644 --- a/hw/vendor/esl_epfl_x_heep/mcu_cfg_minimal.hjson +++ b/hw/vendor/esl_epfl_x_heep/mcu_cfg_minimal.hjson @@ -7,26 +7,9 @@ cpu_type: cv32e20 - bus_type: onetoM - - ram: { - address: 0x00000000, #only tried with 0, cannot be changed for now - numbanks: 2, #each bank is 32kB, cannot be changed for now - numbanks_interleaved: 0, - }, - linker_script: { - #value used for the on-chip linker script, the on-flash linker script is generated using FLASH values and the whole RAM values - onchip_ls: { - code: { - address: 0x00000000, - lenght: 0x00000C800, #minimum size for freeRTOS and clang - } - data: { - address: 0x00000C800, - lenght: whatisleft, #keyword used to calculate the size as: ram.length - code.lenght - } - }, + stack_size: 0x800, + heap_size: 0x800, } debug: { @@ -54,10 +37,14 @@ offset: 0x00028000, length: 0x00008000, }, - spi_host: { + dma: { offset: 0x00030000, length: 0x00010000, - path: "./hw/vendor/lowrisc_opentitan_spi_host/data/spi_host.hjson" + ch_length: 0x100, + num_channels: 0x1, + num_master_ports: 0x1, + num_channels_per_master_port: 0x1, + path: "./hw/ip/dma/data/dma.hjson" }, power_manager: { offset: 0x00040000, @@ -68,30 +55,25 @@ offset: 0x00050000, length: 0x00010000, }, - dma: { - offset: 0x00060000, - length: 0x00010000, - path: "./hw/ip/dma/data/dma.hjson" - }, fast_intr_ctrl: { - offset: 0x00070000, + offset: 0x00060000, length: 0x00010000, path: "./hw/ip/fast_intr_ctrl/data/fast_intr_ctrl.hjson" }, ext_peripheral: { - offset: 0x00080000, + offset: 0x00070000, length: 0x00010000, }, pad_control: { - offset: 0x00090000, + offset: 0x00080000, length: 0x00010000, }, gpio_ao: { - offset: 0x000A0000, + offset: 0x00090000, length: 0x00010000, }, uart: { - offset: 0x000B0000, + offset: 0x000A0000, length: 0x00010000, path: "./hw/vendor/lowrisc_opentitan/hw/ip/uart/data/uart.hjson" }, @@ -106,6 +88,12 @@ is_included: "no", path: "./hw/vendor/lowrisc_opentitan/hw/ip/rv_plic/data/rv_plic.hjson" }, + spi_host: { + offset: 0x00010000, + length: 0x00010000, + is_included: "no", + path: "./hw/vendor/lowrisc_opentitan_spi_host/data/spi_host.hjson" + }, gpio: { offset: 0x00020000, length: 0x00010000, diff --git a/hw/vendor/esl_epfl_x_heep/pad_cfg.hjson b/hw/vendor/esl_epfl_x_heep/pad_cfg.hjson index cc7303a1..b0720c2e 100644 --- a/hw/vendor/esl_epfl_x_heep/pad_cfg.hjson +++ b/hw/vendor/esl_epfl_x_heep/pad_cfg.hjson @@ -2,11 +2,31 @@ // Solderpad Hardware License, Version 0.51, see LICENSE for details. // SPDX-License-Identifier: SHL-0.51 // Derived from Occamy: https://github.com/pulp-platform/snitch/blob/master/hw/system/occamy/src/occamy_cfg.hjson -// Peripherals configuration for core-v-mini-mcu. - +// +// Pads configuration for core-v-mini-mcu. Read by mcu_gen.py. +// +// The pads contains the list of all the pads available in the design. +// Each pad is defined by its name and can have the following attributes: +// num: (mandatory) - the number of pads of this type +// type: (mandatory) - the type of the pad +// num_offset: (optional) - the offset to the first pad of this type (default 0) +// mapping: (optional) - the mapping of the pad in the design. Useful for ASICs (default top) +// active: (optional) - the active level of the pad (default high) +// driven_manually: (optional) - the pad is driven manually (default False) +// mux: (optional) - the muxing options for the pad +// skip_declaration: (optional) - skip the declaration of the pad in the top level (default False) +// keep_internal: (optional) - keep the pad internal to the design (default False) +// layout_attributes: (optional) - collection of attributes related to the physical (ASIC) layout of the pads +// index: (mandatory) index of the pad on its side of the I/O ring +// orient: (optional) - orientation of the pad +// cell: (mandatory for type "supply") - specific cell to use if not a default pad cell (ex. for VDD/VSS pads) +// offset: (optional) - offset from edge (in um) +// skip: (optional) - distance from neighboring pad (in um) +// // Add this field at the same level of pads (not inside) if you want to define PADs attributes // attributes: { // bits: 7:0 +// resval: 0x3 // }, { diff --git a/hw/vendor/esl_epfl_x_heep/scripts/synthesis/dc_shell/dc_script.tcl b/hw/vendor/esl_epfl_x_heep/scripts/synthesis/dc_shell/dc_script.tcl index 8edeb7f9..3a246ab8 100644 --- a/hw/vendor/esl_epfl_x_heep/scripts/synthesis/dc_shell/dc_script.tcl +++ b/hw/vendor/esl_epfl_x_heep/scripts/synthesis/dc_shell/dc_script.tcl @@ -10,11 +10,15 @@ remove_design -all source ${SET_LIBS} +define_design_lib WORK -path ./work + source ${READ_SOURCES}.tcl elaborate ${TOP_MODULE} link +load_upf ../../../core-v-mini-mcu.dc.upf + write -f ddc -hierarchy -output ${REPORT_DIR}/precompiled.ddc source ${CONSTRAINTS} diff --git a/hw/vendor/esl_epfl_x_heep/scripts/verification/examples/im2col_spc_verification.py b/hw/vendor/esl_epfl_x_heep/scripts/verification/examples/im2col_spc_verification.py new file mode 100644 index 00000000..93fe9d6b --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/scripts/verification/examples/im2col_spc_verification.py @@ -0,0 +1,317 @@ +# +# Copyright EPFL contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +# +# Author: Tommaso Terzano +# +# +# Info: This is a usecase of the VerifHeep tool. It generates a dataset for the im2col function +# and the golden result, then it runs the test on the PYNQ-Z2 board and stores the results +# in a file. The data can be then read and plotted using the plotter.py script. +# +# In order to be run, these steps has to be followed: +# 0. Set the X-Heep configuration to have 4 channels, +# while there are no limits on the number of master ports +# 1. Run this command to include Verifheep: +# export PYTHONPATH="$PYTHONPATH://scripts/verification" +# 2. Perform the synthesis with Vivado and to program the FPGA with the bitstream +# 3. Connect the board using GDB by running X-Heep script "make openOCD_bscan". Close Vivado to avoid conflicts +# + +import re +import time +import verifheep +from tqdm import tqdm +import curses +import torch +import torch.nn.functional as F +import numpy as np + +# Define the USB port to which the board is connected. Useful because the port may change +USBport = 2 + +# Define the parameters for the test + +datatype = "uint8_t" +range_max = 255 + +num_masters = 4 # Number of DMA CH +num_slaves = 2 # Number of BUS master ports +max_masters_per_slave = 2 # Maximum number of DMA CH per BUS master port + +batch_max = 4 +batch_min = 1 + +channels_max = 4 +channels_min = 1 + +im_h_max = 11 +im_h_min = 10 + +im_w_max = 11 +im_w_min = 10 + +ker_h_max = 5 +ker_h_min = 3 + +ker_w_max = 5 +ker_w_min = 3 + +pad_top_max = 2 +pad_top_min = 1 +pad_bottom_max = 2 +pad_bottom_min = 1 +pad_left_max = 2 +pad_left_min = 1 +pad_right_max = 2 +pad_right_min = 1 + +stride_d1_max = 2 +stride_d1_min = 1 +stride_d2_max = 2 +stride_d2_min = 1 + +# Calculate the total number of iterations +total_iterations = ((stride_d2_max - stride_d2_min) * (stride_d1_max - stride_d1_min) * + (pad_right_max - pad_right_min) * (pad_left_max - pad_left_min) * + (pad_bottom_max - pad_bottom_min) * (pad_top_max - pad_top_min) * + (ker_w_max - ker_w_min) * (ker_h_max - ker_h_min) * + (im_w_max - im_w_min) * (im_h_max - im_h_min) * + (channels_max - channels_min) * (batch_max - batch_min)) + +# Define the patterns to be used for modifying the im2col_lib.h file +spc_mask_pattern = re.compile(r'#define SPC_CH_MASK 0b\d+') +start_id_pattern = re.compile(r'#define START_ID \d+') +test_en_pattern = re.compile(r'#define TEST_EN \d+') + +# Define the arrays to store the data +im2col_cpu_array = [] +im2col_dma_2d_C_array = [] +im2col_spc_array = [] + +# Function to generate the input dataset for the im2col test to be passed to the VerifHeep tool +def im2col_function(input_array, parameters): + + # Extract parameters + batch_size = parameters['BATCH'] + channels = parameters['CH'] + image_height = parameters['IH'] + image_width = parameters['IW'] + top_pad = parameters['TOP_PAD'] + bottom_pad = parameters['BOTTOM_PAD'] + left_pad = parameters['LEFT_PAD'] + right_pad = parameters['RIGHT_PAD'] + stride_d1 = parameters['STRIDE_D1'] + stride_d2 = parameters['STRIDE_D2'] + (filter_height, filter_width) = (parameters['FH'], parameters['FW']) + kernel_size = (filter_height, filter_width) + + # Convert the input array into a PyTorch tensor with the correct shape + input_tensor = torch.tensor(input_array).view(batch_size, channels, image_height, image_width) + + dilation = 1 + # Ensure kernel_size, stride, padding, and dilation are tuples + if isinstance(kernel_size, int): + kernel_size = (kernel_size, kernel_size) + if isinstance(dilation, int): + dilation = (dilation, dilation) + + # Adjust padding format for F.pad (expects pad_left, pad_right, pad_top, pad_bottom) + padding_format = (left_pad, right_pad, top_pad, bottom_pad) + + # Apply zero padding + padded_input = F.pad(input_tensor, padding_format, "constant", 0) + + # Unfold the padded input tensor + unfolded = padded_input.unfold(2, kernel_size[0], stride_d2).unfold(3, kernel_size[1], stride_d1) + unfolded = unfolded.permute(0, 2, 3, 1, 4, 5) + + # Reshape to get the 2D tensor where each row is a flattened receptive field + channel_dim = padded_input.size(1) + unfolded_tensor = unfolded.contiguous().view(-1, channel_dim * kernel_size[0] * kernel_size[1]).t() + + # Convert the PyTorch tensor to a NumPy array and then to a list (simple array) + unfolded_array = unfolded_tensor.numpy().flatten().tolist() + + return unfolded_array, "" + + +# Initialize the VerifHeep tool +im2colVer = verifheep.VerifHeep("pynq-z2", "../../../") + +# Connect to the pynq-z2 board +print("Connecting to the board...") +serial_status = im2colVer.serialBegin(f"/dev/ttyUSB{USBport}", 9600) +if not serial_status: + print("Error connecting to the board") + exit(1) +else: + print("Connected!\n") + time.sleep(1) + +# Set up the debug interface +im2colVer.setUpDeb() + +def main(stdscr): + + # Initialize the progress bar + progress_bar = tqdm(total=total_iterations, desc="Overall Progress", ncols=100, unit=" iter", + bar_format='{desc}: {percentage:.2f}%|{bar}| {n_fmt}/{total_fmt}') + + iteration = 1 + started = False + counter = 10 + + # Set CH0 to be the SPC channel + mask = "0001" + im2colVer.modifyFile("../../../sw/applications/example_im2col/im2col_lib.h", spc_mask_pattern, f'#define SPC_CH_MASK 0b{mask}') + + # Set the correct output format by setting the TEST_EN define + im2colVer.modifyFile("../../../sw/applications/example_im2col/im2col_lib.h", test_en_pattern, f'#define TEST_EN 1') + + curses.curs_set(0) + for j in range(batch_min, batch_max): + im2col_cpu = [] + im2col_dma_2d_C = [] + im2col_spc = [] + for k in range(channels_min, channels_max): + + for l in range(im_h_min, im_h_max): + + for m in range(im_w_min, im_w_max): + + for n in range(ker_h_min, ker_h_max): + + for o in range(ker_w_min, ker_w_max): + + for p in range(pad_top_min, pad_top_max): + + for q in range(pad_bottom_min, pad_bottom_max): + + for r in range(pad_left_min, pad_left_max): + + for s in range(pad_right_min, pad_right_max): + + for t in range(stride_d1_min, stride_d1_max): + + for u in range(stride_d2_min, stride_d2_max): + + # Start the chrono + if started and counter == 0: + im2colVer.stopDeb() + im2colVer.setUpDeb() + counter = 10 + elif not started: + im2colVer.setUpDeb() + started = True + counter -= 1 + else: + counter -= 1 + + im2colVer.chronoStart() + + # Generate the input dataset and the golden result + n_patches_h = (l + p + q - n) // u + 1 + n_patches_w = (m + s + r - o) // t + 1 + OH = o * n * k * j # Number of rows in a column -> size of a column + OW = n_patches_h * n_patches_w # Numver of columns in a row -> size of a row + input_size = k * l * m * j + golden_size = OH * OW + + parameters = { + 'IH': l, + 'IW': m, + 'CH': k, + 'BATCH': j, + 'FH': n, + 'FW': o, + 'TOP_PAD': p, + 'BOTTOM_PAD': q, + 'LEFT_PAD': r, + 'RIGHT_PAD': s, + 'STRIDE_D1': t, + 'STRIDE_D2': u + } + + im2colVer.genInputDataset(input_size, row_size=m, range_max=range_max, dataset_dir_c="../../../sw/applications/example_im2col/im2col_input.c", + dataset_dir="../../../sw/applications/example_im2col/im2col_input.h", parameters=parameters, dataset_name="input_image_nchw", + datatype=datatype) + + im2colVer.genGoldenResult(im2col_function, golden_size, parameters, row_size=OW, golden_dir="../../../sw/applications/example_im2col/im2col_golden.h", + golden_dir_c="../../../sw/applications/example_im2col/im2col_golden.c", input_dataset_dir="../../../sw/applications/example_im2col/im2col_input.c", + golden_name="golden_im2col_nchw", + output_datatype=datatype) + + im2colVer.modifyFile("../../../sw/applications/example_im2col/im2col_lib.h", start_id_pattern, f'#define START_ID 0') + + # Launch the test + im2colVer.launchTest("example_im2col", input_size=j*k*l*m) + + # Format the parameters of the current run and store them for plots + for test in im2colVer.results: + string = f'CH_SPC: 1, B: {j}, C: {k}, H: {l}, W: {m}, FH: {n}, FW: {o}, PT: {p}, PB: {q}, PL: {r}, PR: {s}, S1: {t}, S2: {u}, cycles: {test["Cycles"]}' + + if int(test["ID"]) == 0: + im2col_cpu.append(string) + elif int(test["ID"]) == 1: + im2col_dma_2d_C.append(string) + elif int(test["ID"]) == 2: + im2col_spc.append(string) + + # Stop the chrono and calculate the remaining time of the verification + im2colVer.clearResults() + im2colVer.chronoStop() + time_rem = im2colVer.chronoExecutionEst(((stride_d2_max - stride_d2_min) * (stride_d1_max - stride_d1_min) * (pad_right_max - pad_right_min) * (pad_left_max - pad_left_min) * (pad_bottom_max - pad_bottom_min) * (pad_top_max - pad_top_min) * (ker_w_max - ker_w_min) * (ker_h_max - ker_h_min) * (im_w_max - im_w_min) * (im_h_max - im_h_min) * (channels_max - channels_min) * (batch_max - batch_min))) + + # Update the progress bar + message = ( + f"Batch size: {j:>5}\n" + f"Input channels:{k:>5}\n" + f"Image height: {l:>5}\n" + f"Image width: {m:>5}\n" + f"Kernel height: {n:>5}\n" + f"Kernel width: {o:>5}\n" + f"Pad top: {p:>5}\n" + f"Pad bottom: {q:>5}\n" + f"Pad left: {r:>5}\n" + f"Pad right: {s:>5}\n" + f"Stride d1: {t:>5}\n" + f"Stride d2: {u:>5}\n" + f"Remaining time:{time_rem['hours']:>2}h:{time_rem['minutes']:>2}m:{time_rem['seconds']:.2f}s\n" + ) + + iteration += 1 + progress_bar.update(1) + + stdscr.addstr(1, 0, message) + stdscr.refresh() + + im2col_cpu_array.append(im2col_cpu) + im2col_dma_2d_C_array.append(im2col_dma_2d_C) + im2col_spc_array.append(im2col_spc) + + # Stop the debug interface and close the progress bar + im2colVer.stopDeb() + progress_bar.close() + + # Write the data to a file + with open('im2col_data.txt', 'w') as file: + file.write("im2col_cpu:\n") + for value in im2col_cpu_array: + file.write(f"{value}\n") + file.write("\n") + + file.write("im2col_dma_2d_C:\n") + for value in im2col_dma_2d_C_array: + file.write(f"{value}\n") + file.write("\n") + + file.write("im2col_spc:\n") + for value in im2col_spc_array: + file.write(f"{value}\n") + file.write("\n") + + print("Data acquired!\n") + +curses.wrapper(main) \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/scripts/verification/examples/plotter.py b/hw/vendor/esl_epfl_x_heep/scripts/verification/examples/plotter.py new file mode 100644 index 00000000..3a012aa6 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/scripts/verification/examples/plotter.py @@ -0,0 +1,123 @@ +# +# Copyright EPFL contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +# +# Author: Tommaso Terzano +# +# +# Info: Plotter script for im2col spc verification data. +# + +import matplotlib.pyplot as plt +import pandas as pd +import ast +import numpy as np + +# Function to parse data from string to dictionary +def parse_data(data): + results = [] + for item in data: + # Split each item by ', ' to get key-value pairs + pairs = item.split(', ') + # Create a dictionary from the pairs + result_dict = {} + for pair in pairs: + key, value = pair.split(': ') + # Convert value to integer + result_dict[key] = int(value) + results.append(result_dict) + return results + +# Function to add loop_size field +def add_loop_size(data): + for entry in data: + # Calculate the number of patches, i.e. the number the filter can fit along one dimension during convolution + n_patches_h = int((entry['H'] - entry['FH'] + entry['PT'] + entry['PB']) / entry['S2']) + 1 + n_patches_w = int((entry['W'] - entry['FW'] + entry['PR'] + entry['PL']) / entry['S1']) + 1 + # Calculate the dimensions of the output matrix + OH = entry['FW'] * entry['FH'] * entry['C'] * entry['B'] # Number of rows in a column -> size of a column + OW = n_patches_h * n_patches_w # Number of columns in a row -> size of a row + entry['loop_size'] = OH*OW + return data + +# Read and parse data from file +def read_data(file_path): + with open(file_path, 'r') as file: + lines = file.readlines() + + im2col_cpu = [] + im2col_dma_2d_C = [] + im2col_spc = [] + + current_section = None + for line in lines: + line = line.strip() + if line.startswith("im2col_cpu:"): + current_section = im2col_cpu + elif line.startswith("im2col_dma_2d_C:"): + current_section = im2col_dma_2d_C + elif line.startswith("im2col_spc:"): + current_section = im2col_spc + elif line: + if current_section is not None: + current_section.append(line.strip("[]'")) + + return im2col_cpu, im2col_dma_2d_C, im2col_spc + +# Path to the file containing the data +file_path = 'im2col_data.txt' + +# Read data from the file +im2col_cpu_array, im2col_dma_2d_C_array, im2col_spc_array = read_data(file_path) + +# Elaborate the data +parsed_1ch_CPU = parse_data(ast.literal_eval("'"+im2col_cpu_array[0]+"'")) +parsed_1ch_DMA = parse_data(ast.literal_eval("'"+im2col_dma_2d_C_array[0]+"'")) +parsed_1ch_spc = parse_data(ast.literal_eval("'"+im2col_spc_array[0]+"'")) + +add_loop_size(parsed_1ch_CPU) +add_loop_size(parsed_1ch_DMA) +add_loop_size(parsed_1ch_spc) + +df_1ch_CPU = pd.DataFrame(parsed_1ch_CPU) +df_1ch_DMA = pd.DataFrame(parsed_1ch_DMA) +df_1ch_spc = pd.DataFrame(parsed_1ch_spc) + +# Plot the data +plt.figure(0, figsize=(12, 8)) + +# Scatter plots +plt.scatter(df_1ch_CPU['loop_size'], df_1ch_CPU['cycles'], color='blue', label='1ch CPU', alpha=1) +plt.scatter(df_1ch_DMA['loop_size'], df_1ch_DMA['cycles'], color='red', label='1ch DMA', alpha=1) +plt.scatter(df_1ch_spc['loop_size'], df_1ch_spc['cycles'], color='green', label='1ch SPC', alpha=1) + +# Trendline plots +p_cpu = np.polyfit(df_1ch_CPU['loop_size'],df_1ch_CPU['cycles'], 1) +trendline_cpu = np.polyval(p_cpu, df_1ch_CPU['loop_size']) + +p_dma = np.polyfit(df_1ch_DMA['loop_size'], df_1ch_DMA['cycles'], 1) +trendline_dma = np.polyval(p_dma, df_1ch_DMA['loop_size']) + +p_spc = np.polyfit(df_1ch_spc['loop_size'], df_1ch_spc['cycles'], 1) +trendline_spc = np.polyval(p_spc, df_1ch_spc['loop_size']) + +plt.plot(df_1ch_CPU['loop_size'], trendline_cpu, color='blue', linestyle='-', alpha=0.6) +plt.plot(df_1ch_DMA['loop_size'], trendline_dma, color='red', linestyle='-', alpha=0.6) +plt.plot(df_1ch_spc['loop_size'], trendline_spc, color='green', linestyle='-', alpha=0.6) + + +# Title and labels +plt.title('Loop Size vs Cycles') +plt.xlabel('Loop Size') +plt.ylabel('Cycles') +plt.grid(True) + +# Legend +plt.legend() + +# Save plot +plt.savefig('plot.png') + +# Show plot +plt.show() diff --git a/hw/vendor/esl_epfl_x_heep/scripts/verification/verifheep.py b/hw/vendor/esl_epfl_x_heep/scripts/verification/verifheep.py new file mode 100644 index 00000000..8cf07ebd --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/scripts/verification/verifheep.py @@ -0,0 +1,498 @@ +# +# Copyright EPFL contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +# +# Author: Tommaso Terzano +# +# +# Info: This library can be used to implement a software-based verification of X-Heep on a variety of targets, +# including Verilator, QuestaSim and FPGA (pynq-z2), using gdb and OpenOCD. +# Some useful information: +# +# 1) In order to enable the elaboration of the outcome of a test, the SW testbench should produce data using +# the following format: +# - 1st line to n line: "::" +# - last line: "&" +# Of course it is not mandatory to count the cycles, or to provide an outcome, or even to use different IDs. +# The crucial thing is to use the format, even if only one of its fields is relevant for your usecase. +# +# 2) The library provides methods to generate a random input dataset + a golden output dataset +# using a provided function. +# This is particularly useful for data-processing applications and accelerators, but could be used to test other +# units with some workarounds. +# If the function returns a dictionary of parameters that might be useful for the application (if not, return None), +# they will be written in the same header file as the golden output. +# The application has to be written in order to use an external output, defined in a header file, +# and to compare it against a golden output, also defined in a header. +# Both the name and directories of these datasets can be provided as arguments. +# It is also possible to generate a golden result starting from a custom input dataset, provided that it was produced +# using the same structure.# +# +# 3) The library provides methods to estimate the remaining time of the execution of a loop, based on the average duration +# of the iterations that have already been executed. +# This is useful to estimate the remaining time of the execution of a multi-iteration test. +# + +import subprocess +import re +import time +import serial +import pexpect +import threading +import queue +import random +import os + +# Set this to True to enable debugging prints +DEBUG_MODE = False + +def PRINT_DEB(*args, **kwargs): + if DEBUG_MODE: + print(*args, **kwargs) + +class VerifHeep: + def __init__(self, target, xheep_dir, opt_en=False): + self.target = target + if target not in ['verilator', 'questasim', 'pynq-z2']: + raise Exception(f'Target {target} not supported. Choose one among:\n- verilator\n- questasim (with optional optimization)\n- pynq-z2\n') + if (target != 'pynq-z2' and opt_en) or (target != 'verilator' and opt_en): + raise Exception(f'Target {target} not supported with {opt_en}. Choose one among:\n- verilator\n- questasim (with optional optimization)\n- pynq-z2\n') + + self.opt_en = opt_en + self.xheep_dir = xheep_dir + self.results = [] + self.it_times = [] + + def resetAll(self): + self.results = [] + self.it_times = [] + if self.ser.is_open: + self.ser.close() + self.ser = None + self.serial_queue = None + self.serial_thread = None + self.gdb = None + self.xheep_dir = None + + def clearResults(self): + self.results = [] + + # Synthesis & Simulation methods + + def compileModel(self, mem_banks=6, cpu="cv32e40px", bus="1toN"): + mcu_gen_cmd = f"cd {self.xheep_dir} ; make mcu-gen MEMORY_BANKS={mem_banks} CPU={cpu} BUS={bus}" + subprocess.run(mcu_gen_cmd, shell=True, capture_output=True, text=True) + if ("ERROR" in mcu_gen_cmd.stderr) or ("error" in mcu_gen_cmd.stderr): + print(mcu_gen_cmd.stderr) + exit(1) + + def buildModel(self): + if self.target == 'verilator': + cmd = f'cd {self.xheep_dir} ; make verilator-sim FUSESOC_PARAM=--JTAG_DPI=1' + elif self.target == 'questasim' and self.opt_en: + cmd = f'cd {self.xheep_dir} ; make questasim-sim-opt FUSESOC_PARAM=--JTAG_DPI=1' + elif self.target == 'questasim' and not self.opt_en: + cmd = f'cd {self.xheep_dir} ; make questasim-sim' + elif self.target == 'pynq-z2': + cmd = f"cd {self.xheep_dir} ; make vivado-fpga FPGA_BOARD={self.target} FUSESOC_FLAGS=--flag=use_bscane_xilinx" + result_synth = subprocess.run(cmd, shell=True, capture_output=True, text=True, executable="/bin/bash") + if ("ERROR" in result_synth.stderr) or ("error" in result_synth.stderr): + print(result_synth.stderr) + exit(1) + + # FPGA programming & debugging methods + + def serialBegin(self, port, baudrate): + try: + self.ser = serial.Serial(port, baudrate, timeout=1) + self.serial_queue = queue.Queue() + + if self.ser.is_open: + print("Connection successful") + return True + else: + print("Failed to open the connection") + return False + except serial.SerialException as e: + print(f"Serial exception: {e}") + return False + except Exception as e: + print(f"An error occurred: {e}") + return False + + def setUpDeb(self): + gdb_cmd = f""" + cd {self.xheep_dir} + $RISCV/bin/riscv32-unknown-elf-gdb ./sw/build/main.elf + """ + self.gdb = pexpect.spawn(f"/bin/bash -c '{gdb_cmd}'") + self.gdb.expect('(gdb)') + self.gdb.sendline('set remotetimeout 2000') + self.gdb.expect('(gdb)') + self.gdb.sendline('target remote localhost:3333') + self.gdb.expect('(gdb)') + + if self.gdb.isalive(): + PRINT_DEB("GDB process is still running.") + else: + PRINT_DEB("GDB process has terminated.") + if self.gdb.exitstatus is not None: + print(f"GDB exit status: {self.gdb.exitstatus}") + if self.gdb.signalstatus is not None: + print(f"GDB terminated by signal: {self.gdb.signalstatus}") + exit(1) + + def stopDeb(self): + self.gdb.sendcontrol('c') + self.gdb.terminate() + + def launchTest(self, example_name, input_size=0, pattern=r'(\d+):(\d+):(\d+)', en_timeout_term=False): + PRINT_DEB(f"Running test {example_name} with input size {input_size}...") + + # Check that the serial connection is still open + if not self.ser.is_open: + print("Error: Serial port is not open!") + exit(1) + + # Set up the serial communication thread and attach it the serial queue + self.serial_thread = threading.Thread(target=SerialReceiver, args=(self.ser, self.serial_queue,)) + + # Start the serial thread + self.serial_thread.start() + + # Compile the application + if self.target == 'verilator' or self.target == 'questasim': + app_compile_run_com = f"cd {self.xheep_dir} ; make app PROJECT={example_name}" + else: + app_compile_run_com = f"cd {self.xheep_dir} ; make app PROJECT={example_name} TARGET={self.target}" + + result_compilation = subprocess.run(app_compile_run_com, shell=True, capture_output=True, text=True) + + if ("Error" in result_compilation.stderr) or ("error" in result_compilation.stderr): + print(result_compilation.stderr) + return + else: + PRINT_DEB("Compilation successful!") + + # Run the testbench with gdb + self.gdb.sendline('load') + self.gdb.expect('(gdb)') + + try: + output = self.gdb.read_nonblocking(size=100, timeout=1) + PRINT_DEB("Current gdb output:", output) + except pexpect.TIMEOUT: + PRINT_DEB("No new output from GDB.") + + # Set a breakpoint at the exit and wait for it + self.gdb.sendline('b _exit') + self.gdb.expect('(gdb)') + self.gdb.sendline('continue') + try: + self.gdb.expect('Breakpoint', timeout=600) + except pexpect.TIMEOUT: + print("Timeout! Program didn't answer in time, exiting...") + self.gdb.terminate() + if en_timeout_term: + exit(1) + return + + # Wait for serial to finish + self.serial_thread.join() + + # Recover the lines + lines = [] + while not self.serial_queue.empty(): + lines.append(self.serial_queue.get()) + + # Analyse the results + pattern = re.compile(pattern) + test_id = None + for line in lines: + match = pattern.search(line) + if match: + test_id = match.group(1) + cycle_count = match.group(2) + outcome = match.group(3) + self.results.append({ "ID" : test_id, "Cycles": cycle_count, "Outcome": outcome, "Input size": input_size }) + + def dumpResults(self, filename="results.txt"): + with open(filename, 'w') as f: + for result in self.results: + f.write(result + '\n') + + # Performance estimation methods + + def chronoStart(self): + self.start_time = time.time() + + def chronoStop(self): + self.end_time = time.time() + self.it_times.append(self.end_time - self.start_time) + return self.end_time - self.start_time + + def chronoExecutionEst(self, loop_size): + avg_duration = sum(self.it_times) / len(self.it_times) + remaining_it = loop_size - len(self.it_times) + remaining_time_raw = remaining_it * avg_duration + remaining_time = {} + remaining_time["hours"], remainder = divmod(remaining_time_raw, 3600) + remaining_time["minutes"], remaining_time["seconds"] = divmod(remainder, 60) + return remaining_time + + # Data generation methods + + def genInputDataset(self, dataset_size, parameters="", row_size=0, range_min=0, range_max=1, dataset_dir="input_dataset.h", dataset_dir_c="", dataset_name="input_dataset", datatype="uint32_t"): + + if dataset_dir_c == "": + with open(dataset_dir, 'w') as f: + # Add license + f.write(f"#ifndef {dataset_name.upper()}_H\n") + f.write(f"#define {dataset_name.upper()}_H\n\n") + license = "/*\n\tCopyright EPFL contributors.\n\tLicensed under the Apache License, Version 2.0, see LICENSE for details.\n\tSPDX-License-Identifier: Apache-2.0\n*/\n\n" + f.write(license) + f.write(f"#include \n\n") + + # Write the parameters, if there are any + if parameters: + for key, value in parameters.items(): + f.write(f"#define {key} {value}\n") + + # Vector declaration + f.write(f"const {datatype} {dataset_name}[{dataset_size}] = " + "{\n") + + # Generate the random vector + for i in range(dataset_size): + if 'float' in datatype: + value = random.uniform(range_min, range_max) # float + elif 'uint' in datatype: + if ('8' in datatype or '16' in datatype or '32' in datatype) and range_min >= 0 and range_max > 0: + value = random.randint(range_min, range_max) + else: + print("Error: invalid datatype. Choose one among:\n- float\n- u/int8_t\n- u/int16_t\n- u/int32_t\n") + exit(1) + elif 'int' in datatype: + if ('8' in datatype or '16' in datatype or '32' in datatype): + value = random.randint(range_min, range_max) + else: + print("Error: invalid datatype. Choose one among:\n- float\n- u/int8_t\n- u/int16_t\n- u/int32_t\n") + exit(1) + else: + print("Error: invalid datatype. Choose one among:\n- float\n- u/int8_t\n- u/int16_t\n- u/int32_t\n") + exit(1) + + if i < dataset_size - 1: + f.write(f" {value},") + else: + f.write(f" {value}") + + if row_size > 0 and (i + 1) % row_size == 0: + f.write("\n") + + # Close the file + f.write("};\n\n") + f.write(f"#endif // {dataset_name.upper()}_H\n") + else: + with open(dataset_dir_c, 'w') as f: + # Add license + license = "/*\n\tCopyright EPFL contributors.\n\tLicensed under the Apache License, Version 2.0, see LICENSE for details.\n\tSPDX-License-Identifier: Apache-2.0\n*/\n\n" + f.write(license) + f.write(f'#include "{os.path.basename(dataset_dir)}"\n\n') + + # Vector declaration + f.write(f"const {datatype} {dataset_name}[{dataset_size}] = " + "{\n") + + # Generate the random vector + for i in range(dataset_size): + if 'float' in datatype: + value = random.uniform(range_min, range_max) # float + elif 'uint' in datatype: + if ('8' in datatype or '16' in datatype or '32' in datatype) and range_min >= 0 and range_max > 0: + value = random.randint(range_min, range_max) + else: + print("Error: invalid datatype. Choose one among:\n- float\n- u/int8_t\n- u/int16_t\n- u/int32_t\n") + exit(1) + elif 'int' in datatype: + if ('8' in datatype or '16' in datatype or '32' in datatype): + value = random.randint(range_min, range_max) + else: + print("Error: invalid datatype. Choose one among:\n- float\n- u/int8_t\n- u/int16_t\n- u/int32_t\n") + exit(1) + else: + print("Error: invalid datatype. Choose one among:\n- float\n- u/int8_t\n- u/int16_t\n- u/int32_t\n") + exit(1) + + if i < dataset_size - 1: + f.write(f" {value},") + else: + f.write(f" {value}") + + if row_size > 0 and (i + 1) % row_size == 0: + f.write("\n") + + # Close the file + f.write("};\n\n") + + with open(dataset_dir, 'w') as f: + # Add license + f.write(f"#ifndef {dataset_name.upper()}_H\n") + f.write(f"#define {dataset_name.upper()}_H\n\n") + license = "/*\n\tCopyright EPFL contributors.\n\tLicensed under the Apache License, Version 2.0, see LICENSE for details.\n\tSPDX-License-Identifier: Apache-2.0\n*/\n\n" + f.write(license) + f.write(f"#include \n\n") + + # Write the parameters, if there are any + if parameters: + for key, value in parameters.items(): + f.write(f"#define {key} {value}\n") + + f.write("\n") + + # Vector declaration + f.write(f"extern const {datatype} {dataset_name}[{dataset_size}];\n\n") + + # Close the file + f.write(f"#endif // {dataset_name.upper()}_H\n") + + def genGoldenResult(self, function, golden_size, parameters, row_size=0, output_datatype="uint32_t", input_dataset_dir="input_dataset.h", golden_dir_c="", golden_dir="golden_output.h", golden_name = "golden_output"): + + # Recover the input dataset + with open(input_dataset_dir, 'r') as f: + content = f.read() + + # Use regular expressions to find the array data + pattern = re.compile(r"{(.*?)}", re.DOTALL) + match = pattern.search(content) + + if not match: + raise ValueError("No array data found in the file.") + + array_data = match.group(1) + # Remove extra whitespace and split the string into individual values + array_data = array_data.replace('\n', '').replace(' ', '') + values = array_data.split(',') + + # Convert values to the appropriate type + if "float" in content: + values = [float(value) for value in values] + elif "uint8_t" in content or "uint16_t" in content or "uint32_t" in content: + values = [int(value) for value in values] + elif "int8_t" in content or "int16_t" in content or "int32_t" in content: + values = [int(value) for value in values] + + # Generate the golden result + (golden_values, output_parameters) = function(values, parameters) + + if golden_dir_c == "": + with open(golden_dir, 'w') as f: + # Write the golden result to a file + f.write(f"#ifndef {golden_name.upper()}_H\n") + f.write(f"#define {golden_name.upper()}_H\n\n") + license = "/*\n\tCopyright EPFL contributors.\n\tLicensed under the Apache License, Version 2.0, see LICENSE for details.\n\tSPDX-License-Identifier: Apache-2.0\n*/\n\n" + f.write(license) + f.write(f"#include \n\n") + + # Write the parameters that could have been returned from the function + if output_parameters: + for key, value in output_parameters.items(): + f.write(f"#define {key} {value}\n") + + f.write("\n") + + # Vector declaration + f.write(f"const {output_datatype} {golden_name}[{golden_size}] = " + "{\n") + + for i in range(golden_size): + if i < golden_size - 1: + f.write(f" {golden_values[i]},") + else: + f.write(f" {golden_values[i]}") + + if row_size > 0 and (i + 1) % row_size == 0: + f.write("\n") + + # Close the file + f.write("};\n\n") + f.write(f"#endif // {golden_name.upper()}_H\n") + else: + with open(golden_dir_c, 'w') as f: + # Write the golden result to a file + license = "/*\n\tCopyright EPFL contributors.\n\tLicensed under the Apache License, Version 2.0, see LICENSE for details.\n\tSPDX-License-Identifier: Apache-2.0\n*/\n\n" + f.write(license) + f.write(f'#include "{os.path.basename(golden_dir)}"\n\n') + + # Vector declaration + f.write(f"const {output_datatype} {golden_name}[{golden_size}] = " + "{\n") + + for i in range(golden_size): + if i < golden_size - 1: + f.write(f" {golden_values[i]},") + else: + f.write(f" {golden_values[i]}") + + if row_size > 0 and (i + 1) % row_size == 0: + f.write("\n") + + # Close the file + f.write("};\n\n") + + with open(golden_dir, 'w') as f: + # Write the golden result to a file + f.write(f"#ifndef {golden_name.upper()}_H\n") + f.write(f"#define {golden_name.upper()}_H\n\n") + license = "/*\n\tCopyright EPFL contributors.\n\tLicensed under the Apache License, Version 2.0, see LICENSE for details.\n\tSPDX-License-Identifier: Apache-2.0\n*/\n\n" + f.write(license) + f.write(f"#include \n\n") + + # Write the parameters that could have been returned from the function + if output_parameters: + for key, value in output_parameters.items(): + f.write(f"#define {key} {value}\n") + + # Vector declaration + f.write(f"extern const {output_datatype} {golden_name}[{golden_size}];\n\n") + + # Close the file + f.write(f"#endif // {golden_name.upper()}_H\n") + + def modifyFile(self, file_dir, pattern, replacement): + + with open(file_dir, 'r') as f: + content = f.read() + + # Replace the pattern with the replacement + new_content = re.sub(pattern, replacement, content) + + with open(file_dir, 'w') as f: + f.write(new_content) + +# Serial communication thread + +def SerialReceiver(ser, serial_queue, endword="&"): + try: + if not ser.is_open: + raise serial.SerialException("Serial port not open") + + received = False + while not received: + # Read the data from the serial port + line = ser.readline().decode('utf-8').rstrip() + serial_queue.put(line) + PRINT_DEB(f">: {line}") + if line: + if endword in line: + received = True + PRINT_DEB(f"Received {endword}: end of serial transmission thread") + return + elif "ERROR" in line: + print("FAILED VERIFICATION!") + exit(1) + except serial.SerialException as e: + print(f"Serial exception: {e}") + except Exception as e: + print(f"An error occurred: {e}") + except KeyboardInterrupt: + print("Keyboard interruption") + finally: + pass \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/CMakeLists.txt b/hw/vendor/esl_epfl_x_heep/sw/CMakeLists.txt index d857d792..cdb2a8f7 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/CMakeLists.txt +++ b/hw/vendor/esl_epfl_x_heep/sw/CMakeLists.txt @@ -42,7 +42,7 @@ if(NOT WIN32) endif() # set the project name -project(${PROJECT} ASM C) +project(${PROJECT} ASM C CXX) # set the required CMake standard set(CMAKE_CXX_STANDARD 14) @@ -63,19 +63,19 @@ FILE(GLOB_RECURSE new_list FOLLOW_SYMLINKS ${SOURCE_PATH}*.h) SET(dir_list_str "") FOREACH(file_path ${new_list}) SET(add 0) # This variable is set to 1 if the file_pth needs to be added to the list - if(${file_path} MATCHES "/device/") - if(${file_path} MATCHES "/target/") # Add it if its not in target, or if its in target/${TARGET} - if(${file_path} MATCHES ${TARGET}) + if(${file_path} MATCHES "${SOURCE_PATH}device/") + if(${file_path} MATCHES "${SOURCE_PATH}device/target/") # Add it if its not in target, or if its in target/${TARGET} + if(${file_path} MATCHES "${SOURCE_PATH}device/target/${TARGET}") SET(add 1) endif() else() SET(add 1) endif() - elseif(${file_path} MATCHES ${PROJECT}) + elseif(${file_path} MATCHES ${SOURCE_PATH}applications/${PROJECT}/) SET(add 1) - elseif( ( ${file_path} MATCHES "/freertos/" ) AND ( ${PROJECT} MATCHES "freertos" ) ) + elseif( ( ${file_path} MATCHES "${SOURCE_PATH}freertos/" ) AND ( ${PROJECT} MATCHES "freertos" ) ) SET(add 1) - elseif( ${file_path} MATCHES "/external/" ) + elseif( ${file_path} MATCHES "${SOURCE_PATH}external/" ) SET(add 1) endif() @@ -89,17 +89,18 @@ FOREACH(file_path ${new_list}) # Add it to the string format list SET(dir_list_str ${dir_list_str} "-I ${dir_path} \ ") - string(REPLACE ";" "" dir_list_str ${dir_list_str}) - + # Add it to the header list SET(h_dir_list_ ${h_dir_list_} "${dir_path}") endif() ENDFOREACH() -LIST(REMOVE_DUPLICATES dir_list_str) +LIST(REMOVE_DUPLICATES dir_list_str) +string(REPLACE ";" "" dir_list_str ${dir_list_str}) #This has been moved here to avoid multiple includes of the same path, see: https://github.com/esl-epfl/x-heep/issues/470 LIST(REMOVE_DUPLICATES h_dir_list_) + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Add list to the directories to be included @@ -108,8 +109,7 @@ SET(INCLUDE_FOLDERS "-I ${RISCV}/${COMPILER_PREFIX}elf/include \ -I ${RISCV}/${COMPILER_PREFIX}elf/include/ \ -I ${ROOT_PROJECT} \ -I ${SOURCE_PATH} \ - ${dir_list_str}") - + ${dir_list_str}") ####################################################################### # FIND SOURCE FILES TO BE INCLUDED @@ -118,23 +118,33 @@ SET(INCLUDE_FOLDERS "-I ${RISCV}/${COMPILER_PREFIX}elf/include \ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Preliminary list of source files inside the source path -# Make a list of the source files that need to be linked -FILE(GLOB_RECURSE new_list FOLLOW_SYMLINKS ${SOURCE_PATH}*.c) +# Make a list of the .c source files that need to be linked +FILE(GLOB_RECURSE c_files FOLLOW_SYMLINKS ${SOURCE_PATH}*.c) +# Make a list of the .s source files that need to be linked +FILE(GLOB_RECURSE s_files FOLLOW_SYMLINKS ${SOURCE_PATH}*.s) +# Make a list of the .S source files that need to be linked +FILE(GLOB_RECURSE S_files FOLLOW_SYMLINKS ${SOURCE_PATH}*.S) +# Make a list of the .cpp source files that need to be linked +FILE(GLOB_RECURSE cpp_files FOLLOW_SYMLINKS ${SOURCE_PATH}*.cpp) +SET(new_list ${c_files} ${s_files} ${S_files} ${cpp_files}) + SET( c_dir_list "" ) SET( app_found 0 ) FOREACH(file_path IN LISTS new_list) SET(add 0) # This variable is set to 1 if the file_pth needs to be added to the list - if(${file_path} MATCHES "/device/") - SET(add 1) - elseif( ${file_path} MATCHES "/external/" ) - SET(add 1) - elseif( ( ${file_path} MATCHES "/${PROJECT}/" ) AND ( NOT ${file_path} MATCHES ${MAINFILE} ) ) + if(${file_path} MATCHES "${SOURCE_PATH}device/") + if(NOT ${file_path} MATCHES ".*/crt/.*") + SET(add 1) + endif() + elseif( (${file_path} MATCHES "${SOURCE_PATH}external/") AND ( NOT ${file_path} MATCHES "exclude" ) ) SET(add 1) - elseif( ( ${file_path} MATCHES "/${PROJECT}/" ) AND ( ${file_path} MATCHES ${MAINFILE} ) ) + elseif( ${file_path} MATCHES "${SOURCE_PATH}applications/${PROJECT}/.*${MAINFILE}\." ) # look for main.* SET(app_found 1) + elseif( ${file_path} MATCHES "${SOURCE_PATH}applications/${PROJECT}/" ) # other sources + SET(add 1) endif() - if( add EQUAL 1 ) # If the file path mathced one of the criterion, add it to the list + if( add EQUAL 1 ) # If the file path matched one of the criteria, add it to the list SET(c_dir_list ${c_dir_list} "${file_path}\ ") string(REPLACE ";" "" c_dir_list ${c_dir_list}) @@ -148,28 +158,39 @@ ENDFOREACH() if( app_found EQUAL 0 ) SET(SOURCE_PATH ${ROOT_PROJECT}) - # Make a list of the source files that need to be linked - FILE(GLOB_RECURSE new_list FOLLOW_SYMLINKS ${SOURCE_PATH}*.c) + # Make a list of the .c source files that need to be linked + FILE(GLOB_RECURSE c_files FOLLOW_SYMLINKS ${SOURCE_PATH}*.c) + # Make a list of the .s source files that need to be linked + FILE(GLOB_RECURSE s_files FOLLOW_SYMLINKS ${SOURCE_PATH}*.s) + # Make a list of the .S source files that need to be linked + FILE(GLOB_RECURSE S_files FOLLOW_SYMLINKS ${SOURCE_PATH}*.S) + # Make a list of the .cpp source files that need to be linked + FILE(GLOB_RECURSE cpp_files FOLLOW_SYMLINKS ${SOURCE_PATH}*.cpp) + SET(new_list ${c_files} ${s_files} ${S_files} ${cpp_files}) + SET(c_dir_list "") FOREACH(file_path IN LISTS new_list) SET(add 0) # This variable is set to 1 if the file_pth needs to be added to the list - if(${file_path} MATCHES "/device/") - SET(add 1) - elseif( ( ${file_path} MATCHES "/${PROJECT}/" ) AND ( NOT ${file_path} MATCHES ${MAINFILE} ) ) + if(${file_path} MATCHES "${ROOT_PROJECT}device/") + if(NOT ${file_path} MATCHES ".*/crt/.*") + SET(add 1) + endif() + elseif( ( ${file_path} MATCHES "${ROOT_PROJECT}applications/${PROJECT}/" ) AND ( NOT ${file_path} MATCHES "${ROOT_PROJECT}applications/${PROJECT}/.*${MAINFILE}\." ) AND ( NOT ${file_path} MATCHES "exclude" ) ) SET(add 1) endif() - if( add EQUAL 1 ) # If the file path mathced one of the criterion, add it to the list + if( add EQUAL 1 ) # If the file path matched one of the criteria, add it to the list SET(c_dir_list ${c_dir_list} "${file_path}\ ") string(REPLACE ";" "" c_dir_list ${c_dir_list}) endif() ENDFOREACH() -endif() - + endif() + LIST(REMOVE_DUPLICATES c_dir_list) + ####################################################################### # DETERMINE IF APP IS EXTERNAL ####################################################################### @@ -266,7 +287,7 @@ message( "${Magenta}Target: ${TARGET}${ColourReset}") SET(LINKED_FILES "${LIB_CRT_P} \ ${LIB_VCTR_P} \ ${LIB_CRT_EXT_P} \ - ${c_dir_list}") + ${c_dir_list}") message( "${Magenta}Linked files: ${LINKED_FILES}${ColourReset}") @@ -303,19 +324,32 @@ endif() # Set CMAKE flags # specify the C standard -set(COMPILER_LINKER_FLAGS "\ - -march=${CMAKE_SYSTEM_PROCESSOR} \ - -w -Os -g -nostdlib \ - -DHOST_BUILD \ - -D${CRT_TYPE} \ - -D${CRTO} \ - -DportasmHANDLE_INTERRUPT=vSystemIrqHandler\ -") +if(NOT ${PROJECT} MATCHES "coremark") + set(COMPILER_LINKER_FLAGS "\ + -march=${CMAKE_SYSTEM_PROCESSOR} \ + -w -O2 -g -nostdlib \ + -ffunction-sections \ + -DHOST_BUILD \ + -D${CRT_TYPE} \ + -D${CRTO} \ + -DportasmHANDLE_INTERRUPT=vSystemIrqHandler\ + ") +else() + set(COMPILER_LINKER_FLAGS "\ + -march=${CMAKE_SYSTEM_PROCESSOR} \ + -w -O3 -g -nostdlib -falign-functions=16 -funroll-all-loops -falign-jumps=4 -finline-functions -Wall -static -pedantic -DPERFORMANCE_RUN=1 -DITERATIONS=1 -DHAS_STDIO=1 -DHAS_PRINTF=1 \ + -ffunction-sections \ + -DHOST_BUILD \ + -D${CRT_TYPE} \ + -D${CRTO} \ + -DportasmHANDLE_INTERRUPT=vSystemIrqHandler\ + ") +endif() set(CMAKE_C_FLAGS ${COMPILER_LINKER_FLAGS}) +set(CMAKE_CXX_FLAGS ${COMPILER_LINKER_FLAGS}) if (${COMPILER} MATCHES "clang") set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=riscv32 \ - -mabi=ilp32 \ --gcc-toolchain=${RISCV} \ --sysroot=${RISCV}/${COMPILER_PREFIX}elf \ -static \ @@ -334,8 +368,18 @@ endif() ####################################################################### # SET TARGETS ####################################################################### - -set(SOURCES ${SOURCE_PATH}applications/${PROJECT}/${MAINFILE}.c) +if (${COMPILER} MATCHES "gcc") + set(SOURCES ${SOURCE_PATH}applications/${PROJECT}/${MAINFILE}.c) + if(NOT EXISTS ${SOURCES}) + # If main.c does not exist, set the source file to main.cpp + set(SOURCES ${SOURCE_PATH}applications/${PROJECT}/${MAINFILE}.cpp) + message("${Red}cpp SOURCES set") + endif() +elseif(${COMPILER} MATCHES "clang") + set(SOURCES ${SOURCE_PATH}applications/${PROJECT}/${MAINFILE}.c) +elseif(${COMPILER} MATCHES "g\\+\\+.*$") + set(SOURCES ${SOURCE_PATH}applications/${PROJECT}/${MAINFILE}.cpp) +endif() # add the executable add_executable(${MAINFILE}.elf ${SOURCES}) @@ -365,6 +409,7 @@ SET(CMAKE_EXE_LINKER_FLAGS "-T ${LINKER_SCRIPT} \ -Wl,-Map=${MAINFILE}.map \ -L ${RISCV}/${COMPILER_PREFIX}elf/lib \ -lc -lm -lgcc -flto \ + -fpermissive -fno-rtti -fno-exceptions -fno-threadsafe-statics \ -ffunction-sections -fdata-sections -specs=nano.specs") message( "${Magenta}Lib Folder RISCV-GCC: ${RISCV}/${COMPILER_PREFIX}elf/lib${ColourReset}") @@ -401,7 +446,7 @@ endif() # Post processing command to create a disassembly file add_custom_command(TARGET ${MAINFILE}.elf POST_BUILD - COMMAND ${CMAKE_OBJDUMP} -S ${MAINFILE}.elf > ${MAINFILE}.disasm + COMMAND ${CMAKE_OBJDUMP} -S ${MAINFILE}.elf > ${MAINFILE}.S COMMENT "Invoking: Disassemble") # Post processing command to create a hex file @@ -420,12 +465,31 @@ add_custom_command(TARGET ${MAINFILE}.elf POST_BUILD COMMENT "Invoking: Hexdump") # Pre-processing command to create disassembly for each source file -foreach (SRC_MODULE ${MAINFILE} ) +if ((${COMPILER} MATCHES "gcc") OR (${COMPILER} MATCHES "clang")) + if(EXISTS ${SOURCE_PATH}applications/${PROJECT}/${MAINFILE}.c) + foreach (SRC_MODULE ${MAINFILE} ) + add_custom_command(TARGET ${MAINFILE}.elf + PRE_LINK + COMMAND ${CMAKE_OBJDUMP} -S ${ROOT_PROJECT}build/CMakeFiles/${MAINFILE}.elf.dir/${OBJ_PATH}applications/${PROJECT}/${SRC_MODULE}.c.obj > ${SRC_MODULE}.s + COMMENT "Invoking: GCC C Disassemble ( CMakeFiles/${MAINFILE}.dir/${SRC_MODULE}.c.obj)") + endforeach() + else() #main.cpp targets + foreach (SRC_MODULE ${MAINFILE} ) + add_custom_command(TARGET ${MAINFILE}.elf + PRE_LINK + COMMAND ${CMAKE_OBJDUMP} -S ${ROOT_PROJECT}build/CMakeFiles/${MAINFILE}.elf.dir/${OBJ_PATH}applications/${PROJECT}/${SRC_MODULE}.cpp.obj > ${SRC_MODULE}.s + COMMENT "Invoking: GCC CPP Disassemble ( CMakeFiles/${MAINFILE}.dir/${SRC_MODULE}.cpp.obj)") + endforeach() + endif() +elseif(${COMPILER} MATCHES "g\\+\\+.*$") + foreach (SRC_MODULE ${MAINFILE} ) add_custom_command(TARGET ${MAINFILE}.elf PRE_LINK - COMMAND ${CMAKE_OBJDUMP} -S ${ROOT_PROJECT}build/CMakeFiles/${MAINFILE}.elf.dir/${OBJ_PATH}applications/${PROJECT}/${SRC_MODULE}.c.obj > ${SRC_MODULE}.s - COMMENT "Invoking: Disassemble ( CMakeFiles/${MAINFILE}.dir/${SRC_MODULE}.c.obj)") -endforeach() + COMMAND ${CMAKE_OBJDUMP} -S ${ROOT_PROJECT}build/CMakeFiles/${MAINFILE}.elf.dir/${OBJ_PATH}applications/${PROJECT}/${SRC_MODULE}.cpp.obj > ${SRC_MODULE}.s + COMMENT "Invoking: G++ Disassemble ( CMakeFiles/${MAINFILE}.dir/${SRC_MODULE}.cpp.obj)") + endforeach() +endif() + # Adding gdb command - TBD #add_custom_target(gdb DEPENDS ${MAINFILE}.elf) diff --git a/hw/vendor/esl_epfl_x_heep/sw/Makefile b/hw/vendor/esl_epfl_x_heep/sw/Makefile index 3582fb25..e327138b 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/Makefile +++ b/hw/vendor/esl_epfl_x_heep/sw/Makefile @@ -25,7 +25,7 @@ PROJECT ?= hello_world # Linker options are 'on_chip' (default),'flash_load','flash_exec' LINKER ?= on_chip -# Target options are 'sim' (default) and 'pynq-z2' +# Target options are 'sim' (default), 'pynq-z2', and 'nexys-a7-100t' TARGET ?= sim # Compiler options are 'gcc' (default) and 'clang' @@ -38,7 +38,7 @@ COMPILER_PREFIX ?= riscv32-unknown- ARCH ?= rv32imc # Path relative from the location of sw/Makefile from which to fetch source files. The directory of that file is the default value. -SOURCE ?= "." +SOURCE ?= $(".") # riscv toolchain install path RISCV ?= ~/.riscv @@ -56,10 +56,10 @@ source_path := $(realpath $(mkfile_path)/$(SOURCE)) $(info $$You are fetching sources from $(source_path) ) -SOURCE_PATH = $(source_path)/ +SOURCE_PATH = $(source_path)/ ROOT_PROJECT = $(mkfile_path)/ INC_FOLDERS = $(mkfile_path)/device/target/$(TARGET)/ -LINK_FOLDER = $(mkfile_path)/linker +LINK_FOLDER ?= $(mkfile_path)/linker # CMake keyword CMAKE_DIR=cmake @@ -70,6 +70,9 @@ else CMAKE=cmake3 endif +# Export variables to sub-makefiles +export + # Let's CMake! include cmake/targets.mak diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_list_join.c b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_list_join.c new file mode 100644 index 00000000..64527aa5 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_list_join.c @@ -0,0 +1,612 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +#include "coremark.h" +/* +Topic: Description + Benchmark using a linked list. + + Linked list is a common data structure used in many applications. + + For our purposes, this will excercise the memory units of the processor. + In particular, usage of the list pointers to find and alter data. + + We are not using Malloc since some platforms do not support this +library. + + Instead, the memory block being passed in is used to create a list, + and the benchmark takes care not to add more items then can be + accomodated by the memory block. The porting layer will make sure + that we have a valid memory block. + + All operations are done in place, without using any extra memory. + + The list itself contains list pointers and pointers to data items. + Data items contain the following: + + idx - An index that captures the initial order of the list. + data - Variable data initialized based on the input parameters. The 16b +are divided as follows: o Upper 8b are backup of original data. o Bit 7 +indicates if the lower 7 bits are to be used as is or calculated. o Bits 0-2 +indicate type of operation to perform to get a 7b value. o Bits 3-6 provide +input for the operation. + +*/ + +/* local functions */ + +list_head *core_list_find(list_head *list, list_data *info); +list_head *core_list_reverse(list_head *list); +list_head *core_list_remove(list_head *item); +list_head *core_list_undo_remove(list_head *item_removed, + list_head *item_modified); +list_head *core_list_insert_new(list_head * insert_point, + list_data * info, + list_head **memblock, + list_data **datablock, + list_head * memblock_end, + list_data * datablock_end); +typedef ee_s32 (*list_cmp)(list_data *a, list_data *b, core_results *res); +list_head *core_list_mergesort(list_head * list, + list_cmp cmp, + core_results *res); + +ee_s16 +calc_func(ee_s16 *pdata, core_results *res) +{ + ee_s16 data = *pdata; + ee_s16 retval; + ee_u8 optype + = (data >> 7) + & 1; /* bit 7 indicates if the function result has been cached */ + if (optype) /* if cached, use cache */ + return (data & 0x007f); + else + { /* otherwise calculate and cache the result */ + ee_s16 flag = data & 0x7; /* bits 0-2 is type of function to perform */ + ee_s16 dtype + = ((data >> 3) + & 0xf); /* bits 3-6 is specific data for the operation */ + dtype |= dtype << 4; /* replicate the lower 4 bits to get an 8b value */ + switch (flag) + { + case 0: + if (dtype < 0x22) /* set min period for bit corruption */ + dtype = 0x22; + retval = core_bench_state(res->size, + res->memblock[3], + res->seed1, + res->seed2, + dtype, + res->crc); + if (res->crcstate == 0) + res->crcstate = retval; + break; + case 1: + retval = core_bench_matrix(&(res->mat), dtype, res->crc); + if (res->crcmatrix == 0) + res->crcmatrix = retval; + break; + default: + retval = data; + break; + } + res->crc = crcu16(retval, res->crc); + retval &= 0x007f; + *pdata = (data & 0xff00) | 0x0080 | retval; /* cache the result */ + return retval; + } +} +/* Function: cmp_complex + Compare the data item in a list cell. + + Can be used by mergesort. +*/ +ee_s32 +cmp_complex(list_data *a, list_data *b, core_results *res) +{ + ee_s16 val1 = calc_func(&(a->data16), res); + ee_s16 val2 = calc_func(&(b->data16), res); + return val1 - val2; +} + +/* Function: cmp_idx + Compare the idx item in a list cell, and regen the data. + + Can be used by mergesort. +*/ +ee_s32 +cmp_idx(list_data *a, list_data *b, core_results *res) +{ + if (res == NULL) + { + a->data16 = (a->data16 & 0xff00) | (0x00ff & (a->data16 >> 8)); + b->data16 = (b->data16 & 0xff00) | (0x00ff & (b->data16 >> 8)); + } + return a->idx - b->idx; +} + +void +copy_info(list_data *to, list_data *from) +{ + to->data16 = from->data16; + to->idx = from->idx; +} + +/* Benchmark for linked list: + - Try to find multiple data items. + - List sort + - Operate on data from list (crc) + - Single remove/reinsert + * At the end of this function, the list is back to original state +*/ +ee_u16 +core_bench_list(core_results *res, ee_s16 finder_idx) +{ + ee_u16 retval = 0; + ee_u16 found = 0, missed = 0; + list_head *list = res->list; + ee_s16 find_num = res->seed3; + list_head *this_find; + list_head *finder, *remover; + list_data info; + ee_s16 i; + + info.idx = finder_idx; + /* find values in the list, and change the list each time + * (reverse and cache if value found) */ + for (i = 0; i < find_num; i++) + { + info.data16 = (i & 0xff); + this_find = core_list_find(list, &info); + list = core_list_reverse(list); + if (this_find == NULL) + { + missed++; + retval += (list->next->info->data16 >> 8) & 1; + } + else + { + found++; + if (this_find->info->data16 & 0x1) /* use found value */ + retval += (this_find->info->data16 >> 9) & 1; + /* and cache next item at the head of the list (if any) */ + if (this_find->next != NULL) + { + finder = this_find->next; + this_find->next = finder->next; + finder->next = list->next; + list->next = finder; + } + } + if (info.idx >= 0) + info.idx++; +#if CORE_DEBUG + ee_printf("List find %d: [%d,%d,%d]\n", i, retval, missed, found); +#endif + } + retval += found * 4 - missed; + /* sort the list by data content and remove one item*/ + if (finder_idx > 0) + list = core_list_mergesort(list, cmp_complex, res); + remover = core_list_remove(list->next); + /* CRC data content of list from location of index N forward, and then undo + * remove */ + finder = core_list_find(list, &info); + if (!finder) + finder = list->next; + while (finder) + { + retval = crc16(list->info->data16, retval); + finder = finder->next; + } +#if CORE_DEBUG + ee_printf("List sort 1: %04x\n", retval); +#endif + remover = core_list_undo_remove(remover, list->next); + /* sort the list by index, in effect returning the list to original state */ + list = core_list_mergesort(list, cmp_idx, NULL); + /* CRC data content of list */ + finder = list->next; + while (finder) + { + retval = crc16(list->info->data16, retval); + finder = finder->next; + } +#if CORE_DEBUG + ee_printf("List sort 2: %04x\n", retval); +#endif + return retval; +} +/* Function: core_list_init + Initialize list with data. + + Parameters: + blksize - Size of memory to be initialized. + memblock - Pointer to memory block. + seed - Actual values chosen depend on the seed parameter. + The seed parameter MUST be supplied from a source that cannot be + determined at compile time + + Returns: + Pointer to the head of the list. + +*/ +list_head * +core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed) +{ + /* calculated pointers for the list */ + ee_u32 per_item = 16 + sizeof(struct list_data_s); + ee_u32 size = (blksize / per_item) + - 2; /* to accomodate systems with 64b pointers, and make sure + same code is executed, set max list elements */ + list_head *memblock_end = memblock + size; + list_data *datablock = (list_data *)(memblock_end); + list_data *datablock_end = datablock + size; + /* some useful variables */ + ee_u32 i; + list_head *finder, *list = memblock; + list_data info; + + /* create a fake items for the list head and tail */ + list->next = NULL; + list->info = datablock; + list->info->idx = 0x0000; + list->info->data16 = (ee_s16)0x8080; + memblock++; + datablock++; + info.idx = 0x7fff; + info.data16 = (ee_s16)0xffff; + core_list_insert_new( + list, &info, &memblock, &datablock, memblock_end, datablock_end); + + /* then insert size items */ + for (i = 0; i < size; i++) + { + ee_u16 datpat = ((ee_u16)(seed ^ i) & 0xf); + ee_u16 dat + = (datpat << 3) | (i & 0x7); /* alternate between algorithms */ + info.data16 = (dat << 8) | dat; /* fill the data with actual data and + upper bits with rebuild value */ + core_list_insert_new( + list, &info, &memblock, &datablock, memblock_end, datablock_end); + } + /* and now index the list so we know initial seed order of the list */ + finder = list->next; + i = 1; + while (finder->next != NULL) + { + if (i < size / 5) /* first 20% of the list in order */ + finder->info->idx = i++; + else + { + ee_u16 pat = (ee_u16)(i++ ^ seed); /* get a pseudo random number */ + finder->info->idx = 0x3fff + & (((i & 0x07) << 8) + | pat); /* make sure the mixed items end up + after the ones in sequence */ + } + finder = finder->next; + } + list = core_list_mergesort(list, cmp_idx, NULL); +#if CORE_DEBUG + ee_printf("Initialized list:\n"); + finder = list; + while (finder) + { + ee_printf( + "[%04x,%04x]", finder->info->idx, (ee_u16)finder->info->data16); + finder = finder->next; + } + ee_printf("\n"); +#endif + return list; +} + +/* Function: core_list_insert + Insert an item to the list + + Parameters: + insert_point - where to insert the item. + info - data for the cell. + memblock - pointer for the list header + datablock - pointer for the list data + memblock_end - end of region for list headers + datablock_end - end of region for list data + + Returns: + Pointer to new item. +*/ +list_head * +core_list_insert_new(list_head * insert_point, + list_data * info, + list_head **memblock, + list_data **datablock, + list_head * memblock_end, + list_data * datablock_end) +{ + list_head *newitem; + + if ((*memblock + 1) >= memblock_end) + return NULL; + if ((*datablock + 1) >= datablock_end) + return NULL; + + newitem = *memblock; + (*memblock)++; + newitem->next = insert_point->next; + insert_point->next = newitem; + + newitem->info = *datablock; + (*datablock)++; + copy_info(newitem->info, info); + + return newitem; +} + +/* Function: core_list_remove + Remove an item from the list. + + Operation: + For a singly linked list, remove by copying the data from the next item + over to the current cell, and unlinking the next item. + + Note: + since there is always a fake item at the end of the list, no need to + check for NULL. + + Returns: + Removed item. +*/ +list_head * +core_list_remove(list_head *item) +{ + list_data *tmp; + list_head *ret = item->next; + /* swap data pointers */ + tmp = item->info; + item->info = ret->info; + ret->info = tmp; + /* and eliminate item */ + item->next = item->next->next; + ret->next = NULL; + return ret; +} + +/* Function: core_list_undo_remove + Undo a remove operation. + + Operation: + Since we want each iteration of the benchmark to be exactly the same, + we need to be able to undo a remove. + Link the removed item back into the list, and switch the info items. + + Parameters: + item_removed - Return value from the + item_modified - List item that was modified during + + Returns: + The item that was linked back to the list. + +*/ +list_head * +core_list_undo_remove(list_head *item_removed, list_head *item_modified) +{ + list_data *tmp; + /* swap data pointers */ + tmp = item_removed->info; + item_removed->info = item_modified->info; + item_modified->info = tmp; + /* and insert item */ + item_removed->next = item_modified->next; + item_modified->next = item_removed; + return item_removed; +} + +/* Function: core_list_find + Find an item in the list + + Operation: + Find an item by idx (if not 0) or specific data value + + Parameters: + list - list head + info - idx or data to find + + Returns: + Found item, or NULL if not found. +*/ +list_head * +core_list_find(list_head *list, list_data *info) +{ + if (info->idx >= 0) + { + while (list && (list->info->idx != info->idx)) + list = list->next; + return list; + } + else + { + while (list && ((list->info->data16 & 0xff) != info->data16)) + list = list->next; + return list; + } +} +/* Function: core_list_reverse + Reverse a list + + Operation: + Rearrange the pointers so the list is reversed. + + Parameters: + list - list head + info - idx or data to find + + Returns: + Found item, or NULL if not found. +*/ + +list_head * +core_list_reverse(list_head *list) +{ + list_head *next = NULL, *tmp; + while (list) + { + tmp = list->next; + list->next = next; + next = list; + list = tmp; + } + return next; +} +/* Function: core_list_mergesort + Sort the list in place without recursion. + + Description: + Use mergesort, as for linked list this is a realistic solution. + Also, since this is aimed at embedded, care was taken to use iterative + rather then recursive algorithm. The sort can either return the list to + original order (by idx) , or use the data item to invoke other other + algorithms and change the order of the list. + + Parameters: + list - list to be sorted. + cmp - cmp function to use + + Returns: + New head of the list. + + Note: + We have a special header for the list that will always be first, + but the algorithm could theoretically modify where the list starts. + + */ +list_head * +core_list_mergesort(list_head *list, list_cmp cmp, core_results *res) +{ + list_head *p, *q, *e, *tail; + ee_s32 insize, nmerges, psize, qsize, i; + + insize = 1; + + while (1) + { + p = list; + list = NULL; + tail = NULL; + + nmerges = 0; /* count number of merges we do in this pass */ + + while (p) + { + nmerges++; /* there exists a merge to be done */ + /* step `insize' places along from p */ + q = p; + psize = 0; + for (i = 0; i < insize; i++) + { + psize++; + q = q->next; + if (!q) + break; + } + + /* if q hasn't fallen off end, we have two lists to merge */ + qsize = insize; + + /* now we have two lists; merge them */ + while (psize > 0 || (qsize > 0 && q)) + { + + /* decide whether next element of merge comes from p or q */ + if (psize == 0) + { + /* p is empty; e must come from q. */ + e = q; + q = q->next; + qsize--; + } + else if (qsize == 0 || !q) + { + /* q is empty; e must come from p. */ + e = p; + p = p->next; + psize--; + } + else if (cmp(p->info, q->info, res) <= 0) + { + /* First element of p is lower (or same); e must come from + * p. */ + e = p; + p = p->next; + psize--; + } + else + { + /* First element of q is lower; e must come from q. */ + e = q; + q = q->next; + qsize--; + } + + /* add the next element to the merged list */ + if (tail) + { + tail->next = e; + } + else + { + list = e; + } + tail = e; + } + + /* now p has stepped `insize' places along, and q has too */ + p = q; + } + + tail->next = NULL; + + /* If we have done only one merge, we're finished. */ + if (nmerges <= 1) /* allow for nmerges==0, the empty list case */ + return list; + + /* Otherwise repeat, merging lists twice the size */ + insize *= 2; + } +#if COMPILER_REQUIRES_SORT_RETURN + return list; +#endif +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_matrix.c b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_matrix.c new file mode 100644 index 00000000..9c7901c3 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_matrix.c @@ -0,0 +1,376 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +#include "coremark.h" +/* +Topic: Description + Matrix manipulation benchmark + + This very simple algorithm forms the basis of many more complex +algorithms. + + The tight inner loop is the focus of many optimizations (compiler as +well as hardware based) and is thus relevant for embedded processing. + + The total available data space will be divided to 3 parts: + NxN Matrix A - initialized with small values (upper 3/4 of the bits all +zero). NxN Matrix B - initialized with medium values (upper half of the bits all +zero). NxN Matrix C - used for the result. + + The actual values for A and B must be derived based on input that is not +available at compile time. +*/ +ee_s16 matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val); +ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval); +void matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val); +void matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B); +void matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B); +void matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B); +void matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val); + +#define matrix_test_next(x) (x + 1) +#define matrix_clip(x, y) ((y) ? (x)&0x0ff : (x)&0x0ffff) +#define matrix_big(x) (0xf000 | (x)) +#define bit_extract(x, from, to) (((x) >> (from)) & (~(0xffffffff << (to)))) + +#if CORE_DEBUG +void +printmat(MATDAT *A, ee_u32 N, char *name) +{ + ee_u32 i, j; + ee_printf("Matrix %s [%dx%d]:\n", name, N, N); + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + if (j != 0) + ee_printf(","); + ee_printf("%d", A[i * N + j]); + } + ee_printf("\n"); + } +} +void +printmatC(MATRES *C, ee_u32 N, char *name) +{ + ee_u32 i, j; + ee_printf("Matrix %s [%dx%d]:\n", name, N, N); + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + if (j != 0) + ee_printf(","); + ee_printf("%d", C[i * N + j]); + } + ee_printf("\n"); + } +} +#endif +/* Function: core_bench_matrix + Benchmark function + + Iterate N times, + changing the matrix values slightly by a constant amount each time. +*/ +ee_u16 +core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc) +{ + ee_u32 N = p->N; + MATRES *C = p->C; + MATDAT *A = p->A; + MATDAT *B = p->B; + MATDAT val = (MATDAT)seed; + + crc = crc16(matrix_test(N, C, A, B, val), crc); + + return crc; +} + +/* Function: matrix_test + Perform matrix manipulation. + + Parameters: + N - Dimensions of the matrix. + C - memory for result matrix. + A - input matrix + B - operator matrix (not changed during operations) + + Returns: + A CRC value that captures all results calculated in the function. + In particular, crc of the value calculated on the result matrix + after each step by . + + Operation: + + 1 - Add a constant value to all elements of a matrix. + 2 - Multiply a matrix by a constant. + 3 - Multiply a matrix by a vector. + 4 - Multiply a matrix by a matrix. + 5 - Add a constant value to all elements of a matrix. + + After the last step, matrix A is back to original contents. +*/ +ee_s16 +matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val) +{ + ee_u16 crc = 0; + MATDAT clipval = matrix_big(val); + + matrix_add_const(N, A, val); /* make sure data changes */ +#if CORE_DEBUG + printmat(A, N, "matrix_add_const"); +#endif + matrix_mul_const(N, C, A, val); + crc = crc16(matrix_sum(N, C, clipval), crc); +#if CORE_DEBUG + printmatC(C, N, "matrix_mul_const"); +#endif + matrix_mul_vect(N, C, A, B); + crc = crc16(matrix_sum(N, C, clipval), crc); +#if CORE_DEBUG + printmatC(C, N, "matrix_mul_vect"); +#endif + matrix_mul_matrix(N, C, A, B); + crc = crc16(matrix_sum(N, C, clipval), crc); +#if CORE_DEBUG + printmatC(C, N, "matrix_mul_matrix"); +#endif + matrix_mul_matrix_bitextract(N, C, A, B); + crc = crc16(matrix_sum(N, C, clipval), crc); +#if CORE_DEBUG + printmatC(C, N, "matrix_mul_matrix_bitextract"); +#endif + + matrix_add_const(N, A, -val); /* return matrix to initial value */ + return crc; +} + +/* Function : matrix_init + Initialize the memory block for matrix benchmarking. + + Parameters: + blksize - Size of memory to be initialized. + memblk - Pointer to memory block. + seed - Actual values chosen depend on the seed parameter. + p - pointers to containing initialized matrixes. + + Returns: + Matrix dimensions. + + Note: + The seed parameter MUST be supplied from a source that cannot be + determined at compile time +*/ +ee_u32 +core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p) +{ + ee_u32 N = 0; + MATDAT *A; + MATDAT *B; + ee_s32 order = 1; + MATDAT val; + ee_u32 i = 0, j = 0; + if (seed == 0) + seed = 1; + while (j < blksize) + { + i++; + j = i * i * 2 * 4; + } + N = i - 1; + A = (MATDAT *)align_mem(memblk); + B = A + N * N; + + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + seed = ((order * seed) % 65536); + val = (seed + order); + val = matrix_clip(val, 0); + B[i * N + j] = val; + val = (val + order); + val = matrix_clip(val, 1); + A[i * N + j] = val; + order++; + } + } + + p->A = A; + p->B = B; + p->C = (MATRES *)align_mem(B + N * N); + p->N = N; +#if CORE_DEBUG + printmat(A, N, "A"); + printmat(B, N, "B"); +#endif + return N; +} + +/* Function: matrix_sum + Calculate a function that depends on the values of elements in the + matrix. + + For each element, accumulate into a temporary variable. + + As long as this value is under the parameter clipval, + add 1 to the result if the element is bigger then the previous. + + Otherwise, reset the accumulator and add 10 to the result. +*/ +ee_s16 +matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval) +{ + MATRES tmp = 0, prev = 0, cur = 0; + ee_s16 ret = 0; + ee_u32 i, j; + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + cur = C[i * N + j]; + tmp += cur; + if (tmp > clipval) + { + ret += 10; + tmp = 0; + } + else + { + ret += (cur > prev) ? 1 : 0; + } + prev = cur; + } + } + return ret; +} + +/* Function: matrix_mul_const + Multiply a matrix by a constant. + This could be used as a scaler for instance. +*/ +void +matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val) +{ + ee_u32 i, j; + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + C[i * N + j] = (MATRES)A[i * N + j] * (MATRES)val; + } + } +} + +/* Function: matrix_add_const + Add a constant value to all elements of a matrix. +*/ +void +matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val) +{ + ee_u32 i, j; + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + A[i * N + j] += val; + } + } +} + +/* Function: matrix_mul_vect + Multiply a matrix by a vector. + This is common in many simple filters (e.g. fir where a vector of + coefficients is applied to the matrix.) +*/ +void +matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) +{ + ee_u32 i, j; + for (i = 0; i < N; i++) + { + C[i] = 0; + for (j = 0; j < N; j++) + { + C[i] += (MATRES)A[i * N + j] * (MATRES)B[j]; + } + } +} + +/* Function: matrix_mul_matrix + Multiply a matrix by a matrix. + Basic code is used in many algorithms, mostly with minor changes such as + scaling. +*/ +void +matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) +{ + ee_u32 i, j, k; + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + C[i * N + j] = 0; + for (k = 0; k < N; k++) + { + C[i * N + j] += (MATRES)A[i * N + k] * (MATRES)B[k * N + j]; + } + } + } +} + +/* Function: matrix_mul_matrix_bitextract + Multiply a matrix by a matrix, and extract some bits from the result. + Basic code is used in many algorithms, mostly with minor changes such as + scaling. +*/ +void +matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) +{ + ee_u32 i, j, k; + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + C[i * N + j] = 0; + for (k = 0; k < N; k++) + { + MATRES tmp = (MATRES)A[i * N + k] * (MATRES)B[k * N + j]; + C[i * N + j] += bit_extract(tmp, 2, 4) * bit_extract(tmp, 5, 7); + } + } + } +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.c b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.c new file mode 100644 index 00000000..3b40763c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.c @@ -0,0 +1,104 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +#include "csr.h" +#include "x-heep.h" + +#include "coremark.h" + +ee_u32 default_num_contexts = 1; + +static CORETIMETYPE start_time_val, stop_time_val; + +#if VALIDATION_RUN +volatile ee_s32 seed1_volatile = 0x3415; +volatile ee_s32 seed2_volatile = 0x3415; +volatile ee_s32 seed3_volatile = 0x66; +#endif +#if PERFORMANCE_RUN +volatile ee_s32 seed1_volatile = 0x0; +volatile ee_s32 seed2_volatile = 0x0; +volatile ee_s32 seed3_volatile = 0x66; +#endif +#if PROFILE_RUN +volatile ee_s32 seed1_volatile = 0x8; +volatile ee_s32 seed2_volatile = 0x8; +volatile ee_s32 seed3_volatile = 0x8; +#endif +volatile ee_s32 seed4_volatile = ITERATIONS; +volatile ee_s32 seed5_volatile = 0; + +void +portable_init(core_portable *p, int *argc, char *argv[]) +{ + // Don't need to do anything here atm. + (void)p; + (void)argc; + (void)argv; +} + +void +portable_fini(core_portable *p) +{ + // Don't need to do anything here atm. + (void)p; +} + +void +start_time(void) +{ + // Enable mcycle counter and read value + CSR_CLEAR_BITS(CSR_REG_MCOUNTINHIBIT, 0x1); + + CSR_READ(CSR_REG_MCYCLE, &start_time_val); +} + +void +stop_time(void) +{ + CSR_READ(CSR_REG_MCYCLE, &stop_time_val); +} + +CORE_TICKS +get_time(void) +{ + return (stop_time_val - start_time_val); +} + +secs_ret +time_in_secs(CORE_TICKS ticks) +{ + return ticks*1E-6; // Normalized to 1 MHz clock period +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.h b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.h new file mode 100644 index 00000000..5a15066a --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_portme.h @@ -0,0 +1,93 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +#include +#include + +typedef signed short ee_s16; +typedef unsigned short ee_u16; +typedef signed int ee_s32; +typedef double ee_f32; +typedef unsigned char ee_u8; +typedef unsigned int ee_u32; +typedef ee_u32 ee_ptr_int; +typedef size_t ee_size_t; + +typedef ee_u32 CORE_TICKS; + +typedef struct CORE_PORTABLE_S +{ + ee_u8 portable_id; +} core_portable; + +#ifndef MULTITHREAD +#define MULTITHREAD 1 // 1 means single-core +#define USE_PTHREAD 0 +#define USE_FORK 0 +#define USE_SOCKET 0 +#endif + +#ifndef COMPILER_VERSION +#ifdef __GNUC__ +#define COMPILER_VERSION "GCC"__VERSION__ +#else +#define COMPILER_VERSION "Undefined non-gcc compiler used" +#endif +#endif + +#ifndef COMPILER_FLAGS +#define COMPILER_FLAGS FLAGS_STR +#endif + +#ifndef MEM_LOCATION +#define MEM_LOCATION "" +#endif + +#ifndef SEED_METHOD +#define SEED_METHOD SEED_VOLATILE +#endif + +#ifndef HAS_PRINTF +#define HAS_PRINTF 1 +#endif + +#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x)-1) & ~3)) + +#define CORETIMETYPE ee_u32 + +extern ee_u32 default_num_contexts; + +void portable_init(core_portable *p, int *argc, char *argv[]); +void portable_fini(core_portable *p); diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_state.c b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_state.c new file mode 100644 index 00000000..b5c3d461 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_state.c @@ -0,0 +1,347 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +#include "coremark.h" +/* local functions */ +enum CORE_STATE core_state_transition(ee_u8 **instr, ee_u32 *transition_count); + +/* +Topic: Description + Simple state machines like this one are used in many embedded products. + + For more complex state machines, sometimes a state transition table +implementation is used instead, trading speed of direct coding for ease of +maintenance. + + Since the main goal of using a state machine in CoreMark is to excercise +the switch/if behaviour, we are using a small moore machine. + + In particular, this machine tests type of string input, + trying to determine whether the input is a number or something else. + (see core_state.png). +*/ + +/* Function: core_bench_state + Benchmark function + + Go over the input twice, once direct, and once after introducing some + corruption. +*/ +ee_u16 +core_bench_state(ee_u32 blksize, + ee_u8 *memblock, + ee_s16 seed1, + ee_s16 seed2, + ee_s16 step, + ee_u16 crc) +{ + ee_u32 final_counts[NUM_CORE_STATES]; + ee_u32 track_counts[NUM_CORE_STATES]; + ee_u8 *p = memblock; + ee_u32 i; + +#if CORE_DEBUG + ee_printf("State Bench: %d,%d,%d,%04x\n", seed1, seed2, step, crc); +#endif + for (i = 0; i < NUM_CORE_STATES; i++) + { + final_counts[i] = track_counts[i] = 0; + } + /* run the state machine over the input */ + while (*p != 0) + { + enum CORE_STATE fstate = core_state_transition(&p, track_counts); + final_counts[fstate]++; +#if CORE_DEBUG + ee_printf("%d,", fstate); + } + ee_printf("\n"); +#else + } +#endif + p = memblock; + while (p < (memblock + blksize)) + { /* insert some corruption */ + if (*p != ',') + *p ^= (ee_u8)seed1; + p += step; + } + p = memblock; + /* run the state machine over the input again */ + while (*p != 0) + { + enum CORE_STATE fstate = core_state_transition(&p, track_counts); + final_counts[fstate]++; +#if CORE_DEBUG + ee_printf("%d,", fstate); + } + ee_printf("\n"); +#else + } +#endif + p = memblock; + while (p < (memblock + blksize)) + { /* undo corruption is seed1 and seed2 are equal */ + if (*p != ',') + *p ^= (ee_u8)seed2; + p += step; + } + /* end timing */ + for (i = 0; i < NUM_CORE_STATES; i++) + { + crc = crcu32(final_counts[i], crc); + crc = crcu32(track_counts[i], crc); + } + return crc; +} + +/* Default initialization patterns */ +static ee_u8 *intpat[4] + = { (ee_u8 *)"5012", (ee_u8 *)"1234", (ee_u8 *)"-874", (ee_u8 *)"+122" }; +static ee_u8 *floatpat[4] = { (ee_u8 *)"35.54400", + (ee_u8 *)".1234500", + (ee_u8 *)"-110.700", + (ee_u8 *)"+0.64400" }; +static ee_u8 *scipat[4] = { (ee_u8 *)"5.500e+3", + (ee_u8 *)"-.123e-2", + (ee_u8 *)"-87e+832", + (ee_u8 *)"+0.6e-12" }; +static ee_u8 *errpat[4] = { (ee_u8 *)"T0.3e-1F", + (ee_u8 *)"-T.T++Tq", + (ee_u8 *)"1T3.4e4z", + (ee_u8 *)"34.0e-T^" }; + +/* Function: core_init_state + Initialize the input data for the state machine. + + Populate the input with several predetermined strings, interspersed. + Actual patterns chosen depend on the seed parameter. + + Note: + The seed parameter MUST be supplied from a source that cannot be + determined at compile time +*/ +void +core_init_state(ee_u32 size, ee_s16 seed, ee_u8 *p) +{ + ee_u32 total = 0, next = 0, i; + ee_u8 *buf = 0; +#if CORE_DEBUG + ee_u8 *start = p; + ee_printf("State: %d,%d\n", size, seed); +#endif + size--; + next = 0; + while ((total + next + 1) < size) + { + if (next > 0) + { + for (i = 0; i < next; i++) + *(p + total + i) = buf[i]; + *(p + total + i) = ','; + total += next + 1; + } + seed++; + switch (seed & 0x7) + { + case 0: /* int */ + case 1: /* int */ + case 2: /* int */ + buf = intpat[(seed >> 3) & 0x3]; + next = 4; + break; + case 3: /* float */ + case 4: /* float */ + buf = floatpat[(seed >> 3) & 0x3]; + next = 8; + break; + case 5: /* scientific */ + case 6: /* scientific */ + buf = scipat[(seed >> 3) & 0x3]; + next = 8; + break; + case 7: /* invalid */ + buf = errpat[(seed >> 3) & 0x3]; + next = 8; + break; + default: /* Never happen, just to make some compilers happy */ + break; + } + } + size++; + while (total < size) + { /* fill the rest with 0 */ + *(p + total) = 0; + total++; + } +#if CORE_DEBUG + ee_printf("State Input: %s\n", start); +#endif +} + +static ee_u8 +ee_isdigit(ee_u8 c) +{ + ee_u8 retval; + retval = ((c >= '0') & (c <= '9')) ? 1 : 0; + return retval; +} + +/* Function: core_state_transition + Actual state machine. + + The state machine will continue scanning until either: + 1 - an invalid input is detcted. + 2 - a valid number has been detected. + + The input pointer is updated to point to the end of the token, and the + end state is returned (either specific format determined or invalid). +*/ + +enum CORE_STATE +core_state_transition(ee_u8 **instr, ee_u32 *transition_count) +{ + ee_u8 * str = *instr; + ee_u8 NEXT_SYMBOL; + enum CORE_STATE state = CORE_START; + for (; *str && state != CORE_INVALID; str++) + { + NEXT_SYMBOL = *str; + if (NEXT_SYMBOL == ',') /* end of this input */ + { + str++; + break; + } + switch (state) + { + case CORE_START: + if (ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INT; + } + else if (NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-') + { + state = CORE_S1; + } + else if (NEXT_SYMBOL == '.') + { + state = CORE_FLOAT; + } + else + { + state = CORE_INVALID; + transition_count[CORE_INVALID]++; + } + transition_count[CORE_START]++; + break; + case CORE_S1: + if (ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INT; + transition_count[CORE_S1]++; + } + else if (NEXT_SYMBOL == '.') + { + state = CORE_FLOAT; + transition_count[CORE_S1]++; + } + else + { + state = CORE_INVALID; + transition_count[CORE_S1]++; + } + break; + case CORE_INT: + if (NEXT_SYMBOL == '.') + { + state = CORE_FLOAT; + transition_count[CORE_INT]++; + } + else if (!ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INVALID; + transition_count[CORE_INT]++; + } + break; + case CORE_FLOAT: + if (NEXT_SYMBOL == 'E' || NEXT_SYMBOL == 'e') + { + state = CORE_S2; + transition_count[CORE_FLOAT]++; + } + else if (!ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INVALID; + transition_count[CORE_FLOAT]++; + } + break; + case CORE_S2: + if (NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-') + { + state = CORE_EXPONENT; + transition_count[CORE_S2]++; + } + else + { + state = CORE_INVALID; + transition_count[CORE_S2]++; + } + break; + case CORE_EXPONENT: + if (ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_SCIENTIFIC; + transition_count[CORE_EXPONENT]++; + } + else + { + state = CORE_INVALID; + transition_count[CORE_EXPONENT]++; + } + break; + case CORE_SCIENTIFIC: + if (!ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INVALID; + transition_count[CORE_INVALID]++; + } + break; + default: + break; + } + } + *instr = str; + return state; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_util.c b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_util.c new file mode 100644 index 00000000..0544e621 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/core_util.c @@ -0,0 +1,266 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +#include "coremark.h" +/* Function: get_seed + Get a values that cannot be determined at compile time. + + Since different embedded systems and compilers are used, 3 different + methods are provided: 1 - Using a volatile variable. This method is only + valid if the compiler is forced to generate code that reads the value of a + volatile variable from memory at run time. Please note, if using this method, + you would need to modify core_portme.c to generate training profile. 2 - + Command line arguments. This is the preferred method if command line + arguments are supported. 3 - System function. If none of the first 2 methods + is available on the platform, a system function which is not a stub can be + used. + + e.g. read the value on GPIO pins connected to switches, or invoke + special simulator functions. +*/ +#if (SEED_METHOD == SEED_VOLATILE) +extern volatile ee_s32 seed1_volatile; +extern volatile ee_s32 seed2_volatile; +extern volatile ee_s32 seed3_volatile; +extern volatile ee_s32 seed4_volatile; +extern volatile ee_s32 seed5_volatile; +ee_s32 +get_seed_32(int i) +{ + ee_s32 retval; + switch (i) + { + case 1: + retval = seed1_volatile; + break; + case 2: + retval = seed2_volatile; + break; + case 3: + retval = seed3_volatile; + break; + case 4: + retval = seed4_volatile; + break; + case 5: + retval = seed5_volatile; + break; + default: + retval = 0; + break; + } + return retval; +} +#elif (SEED_METHOD == SEED_ARG) +ee_s32 +parseval(char *valstring) +{ + ee_s32 retval = 0; + ee_s32 neg = 1; + int hexmode = 0; + if (*valstring == '-') + { + neg = -1; + valstring++; + } + if ((valstring[0] == '0') && (valstring[1] == 'x')) + { + hexmode = 1; + valstring += 2; + } + /* first look for digits */ + if (hexmode) + { + while (((*valstring >= '0') && (*valstring <= '9')) + || ((*valstring >= 'a') && (*valstring <= 'f'))) + { + ee_s32 digit = *valstring - '0'; + if (digit > 9) + digit = 10 + *valstring - 'a'; + retval *= 16; + retval += digit; + valstring++; + } + } + else + { + while ((*valstring >= '0') && (*valstring <= '9')) + { + ee_s32 digit = *valstring - '0'; + retval *= 10; + retval += digit; + valstring++; + } + } + /* now add qualifiers */ + if (*valstring == 'K') + retval *= 1024; + if (*valstring == 'M') + retval *= 1024 * 1024; + + retval *= neg; + return retval; +} + +ee_s32 +get_seed_args(int i, int argc, char *argv[]) +{ + if (argc > i) + return parseval(argv[i]); + return 0; +} + +#elif (SEED_METHOD == SEED_FUNC) +/* If using OS based function, you must define and implement the functions below + * in core_portme.h and core_portme.c ! */ +ee_s32 +get_seed_32(int i) +{ + ee_s32 retval; + switch (i) + { + case 1: + retval = portme_sys1(); + break; + case 2: + retval = portme_sys2(); + break; + case 3: + retval = portme_sys3(); + break; + case 4: + retval = portme_sys4(); + break; + case 5: + retval = portme_sys5(); + break; + default: + retval = 0; + break; + } + return retval; +} +#endif + +/* Function: crc* + Service functions to calculate 16b CRC code. + +*/ +ee_u16 +crcu8(ee_u8 data, ee_u16 crc) +{ + ee_u8 i = 0, x16 = 0, carry = 0; + + for (i = 0; i < 8; i++) + { + x16 = (ee_u8)((data & 1) ^ ((ee_u8)crc & 1)); + data >>= 1; + + if (x16 == 1) + { + crc ^= 0x4002; + carry = 1; + } + else + carry = 0; + crc >>= 1; + if (carry) + crc |= 0x8000; + else + crc &= 0x7fff; + } + return crc; +} +ee_u16 +crcu16(ee_u16 newval, ee_u16 crc) +{ + crc = crcu8((ee_u8)(newval), crc); + crc = crcu8((ee_u8)((newval) >> 8), crc); + return crc; +} +ee_u16 +crcu32(ee_u32 newval, ee_u16 crc) +{ + crc = crc16((ee_s16)newval, crc); + crc = crc16((ee_s16)(newval >> 16), crc); + return crc; +} +ee_u16 +crc16(ee_s16 newval, ee_u16 crc) +{ + return crcu16((ee_u16)newval, crc); +} + +ee_u8 +check_data_types() +{ + ee_u8 retval = 0; + if (sizeof(ee_u8) != 1) + { + ee_printf("ERROR: ee_u8 is not an 8b datatype!\n"); + retval++; + } + if (sizeof(ee_u16) != 2) + { + ee_printf("ERROR: ee_u16 is not a 16b datatype!\n"); + retval++; + } + if (sizeof(ee_s16) != 2) + { + ee_printf("ERROR: ee_s16 is not a 16b datatype!\n"); + retval++; + } + if (sizeof(ee_s32) != 4) + { + ee_printf("ERROR: ee_s32 is not a 32b datatype!\n"); + retval++; + } + if (sizeof(ee_u32) != 4) + { + ee_printf("ERROR: ee_u32 is not a 32b datatype!\n"); + retval++; + } + if (sizeof(ee_ptr_int) != sizeof(int *)) + { + ee_printf( + "ERROR: ee_ptr_int is not a datatype that holds an int pointer!\n"); + retval++; + } + if (retval > 0) + { + ee_printf("ERROR: Please modify the datatypes in core_portme.h!\n"); + } + return retval; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/coremark.h b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/coremark.h new file mode 100644 index 00000000..4f2b074d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/coremark.h @@ -0,0 +1,211 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +/* Topic: Description + This file contains declarations of the various benchmark functions. +*/ + +/* Configuration: TOTAL_DATA_SIZE + Define total size for data algorithms will operate on +*/ +#ifndef TOTAL_DATA_SIZE +#define TOTAL_DATA_SIZE 2 * 1000 +#endif + +#define SEED_ARG 0 +#define SEED_FUNC 1 +#define SEED_VOLATILE 2 + +#define MEM_STATIC 0 +#define MEM_MALLOC 1 +#define MEM_STACK 2 + +#include "core_portme.h" + +#if HAS_STDIO +#include +#endif +#if HAS_PRINTF +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define ee_printf(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define ee_printf(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define ee_printf printf +#endif + +#endif + +/* Actual benchmark execution in iterate */ +void *iterate(void *pres); + +/* Typedef: secs_ret + For machines that have floating point support, get number of seconds as + a double. Otherwise an unsigned int. +*/ +#if HAS_FLOAT +typedef double secs_ret; +#else +typedef ee_u32 secs_ret; +#endif + +#if MAIN_HAS_NORETURN +#define MAIN_RETURN_VAL +#define MAIN_RETURN_TYPE void +#else +#define MAIN_RETURN_VAL 0 +#define MAIN_RETURN_TYPE int +#endif + +void start_time(void); +void stop_time(void); +CORE_TICKS get_time(void); +secs_ret time_in_secs(CORE_TICKS ticks); + +/* Misc useful functions */ +ee_u16 crcu8(ee_u8 data, ee_u16 crc); +ee_u16 crc16(ee_s16 newval, ee_u16 crc); +ee_u16 crcu16(ee_u16 newval, ee_u16 crc); +ee_u16 crcu32(ee_u32 newval, ee_u16 crc); +ee_u8 check_data_types(void); +void * portable_malloc(ee_size_t size); +void portable_free(void *p); +ee_s32 parseval(char *valstring); + +/* Algorithm IDS */ +#define ID_LIST (1 << 0) +#define ID_MATRIX (1 << 1) +#define ID_STATE (1 << 2) +#define ALL_ALGORITHMS_MASK (ID_LIST | ID_MATRIX | ID_STATE) +#define NUM_ALGORITHMS 3 + +/* list data structures */ +typedef struct list_data_s +{ + ee_s16 data16; + ee_s16 idx; +} list_data; + +typedef struct list_head_s +{ + struct list_head_s *next; + struct list_data_s *info; +} list_head; + +/*matrix benchmark related stuff */ +#define MATDAT_INT 1 +#if MATDAT_INT +typedef ee_s16 MATDAT; +typedef ee_s32 MATRES; +#else +typedef ee_f16 MATDAT; +typedef ee_f32 MATRES; +#endif + +typedef struct MAT_PARAMS_S +{ + int N; + MATDAT *A; + MATDAT *B; + MATRES *C; +} mat_params; + +/* state machine related stuff */ +/* List of all the possible states for the FSM */ +typedef enum CORE_STATE +{ + CORE_START = 0, + CORE_INVALID, + CORE_S1, + CORE_S2, + CORE_INT, + CORE_FLOAT, + CORE_EXPONENT, + CORE_SCIENTIFIC, + NUM_CORE_STATES +} core_state_e; + +/* Helper structure to hold results */ +typedef struct RESULTS_S +{ + /* inputs */ + ee_s16 seed1; /* Initializing seed */ + ee_s16 seed2; /* Initializing seed */ + ee_s16 seed3; /* Initializing seed */ + void * memblock[4]; /* Pointer to safe memory location */ + ee_u32 size; /* Size of the data */ + ee_u32 iterations; /* Number of iterations to execute */ + ee_u32 execs; /* Bitmask of operations to execute */ + struct list_head_s *list; + mat_params mat; + /* outputs */ + ee_u16 crc; + ee_u16 crclist; + ee_u16 crcmatrix; + ee_u16 crcstate; + ee_s16 err; + /* ultithread specific */ + core_portable port; +} core_results; + +/* Multicore execution handling */ +#if (MULTITHREAD > 1) +ee_u8 core_start_parallel(core_results *res); +ee_u8 core_stop_parallel(core_results *res); +#endif + +/* list benchmark functions */ +list_head *core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed); +ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx); + +/* state benchmark functions */ +void core_init_state(ee_u32 size, ee_s16 seed, ee_u8 *p); +ee_u16 core_bench_state(ee_u32 blksize, + ee_u8 *memblock, + ee_s16 seed1, + ee_s16 seed2, + ee_s16 step, + ee_u16 crc); + +/* matrix benchmark functions */ +ee_u32 core_init_matrix(ee_u32 blksize, + void * memblk, + ee_s32 seed, + mat_params *p); +ee_u16 core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc); diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/main.c new file mode 100644 index 00000000..12136ada --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/coremark/main.c @@ -0,0 +1,459 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +// Copyright 2020 OpenHW Group +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0 + +/* File: core_main.c + This file contains the framework to acquire a block of memory, seed + initial parameters, tun t he benchmark and report the results. +*/ +#include "coremark.h" + +/* Function: iterate + Run the benchmark for a specified number of iterations. + + Operation: + For each type of benchmarked algorithm: + a - Initialize the data block for the algorithm. + b - Execute the algorithm N times. + + Returns: + NULL. +*/ +static ee_u16 list_known_crc[] = { (ee_u16)0xd4b0, + (ee_u16)0x3340, + (ee_u16)0x6a79, + (ee_u16)0xe714, + (ee_u16)0xe3c1 }; +static ee_u16 matrix_known_crc[] = { (ee_u16)0xbe52, + (ee_u16)0x1199, + (ee_u16)0x5608, + (ee_u16)0x1fd7, + (ee_u16)0x0747 }; +static ee_u16 state_known_crc[] = { (ee_u16)0x5e47, + (ee_u16)0x39bf, + (ee_u16)0xe5a4, + (ee_u16)0x8e3a, + (ee_u16)0x8d84 }; +void * +iterate(void *pres) +{ + ee_u32 i; + ee_u16 crc; + core_results *res = (core_results *)pres; + ee_u32 iterations = res->iterations; + res->crc = 0; + res->crclist = 0; + res->crcmatrix = 0; + res->crcstate = 0; + + for (i = 0; i < iterations; i++) + { + crc = core_bench_list(res, 1); + res->crc = crcu16(crc, res->crc); + crc = core_bench_list(res, -1); + res->crc = crcu16(crc, res->crc); + if (i == 0) + res->crclist = res->crc; + } + return NULL; +} + +#if (SEED_METHOD == SEED_ARG) +ee_s32 get_seed_args(int i, int argc, char *argv[]); +#define get_seed(x) (ee_s16) get_seed_args(x, argc, argv) +#define get_seed_32(x) get_seed_args(x, argc, argv) +#else /* via function or volatile */ +ee_s32 get_seed_32(int i); +#define get_seed(x) (ee_s16) get_seed_32(x) +#endif + +#if (MEM_METHOD == MEM_STATIC) +ee_u8 static_memblk[TOTAL_DATA_SIZE]; +#endif +char *mem_name[3] = { "Static", "Heap", "Stack" }; +/* Function: main + Main entry routine for the benchmark. + This function is responsible for the following steps: + + 1 - Initialize input seeds from a source that cannot be determined at + compile time. 2 - Initialize memory block for use. 3 - Run and time the + benchmark. 4 - Report results, testing the validity of the output if the + seeds are known. + + Arguments: + 1 - first seed : Any value + 2 - second seed : Must be identical to first for iterations to be + identical 3 - third seed : Any value, should be at least an order of + magnitude less then the input size, but bigger then 32. 4 - Iterations : + Special, if set to 0, iterations will be automatically determined such that + the benchmark will run between 10 to 100 secs + +*/ + +#if MAIN_HAS_NOARGC +MAIN_RETURN_TYPE +main(void) +{ + int argc = 0; + char *argv[1]; +#else +MAIN_RETURN_TYPE +main(int argc, char *argv[]) +{ +#endif + ee_u16 i, j = 0, num_algorithms = 0; + ee_s16 known_id = -1, total_errors = 0; + ee_u16 seedcrc = 0; + CORE_TICKS total_time; + core_results results[MULTITHREAD]; +#if (MEM_METHOD == MEM_STACK) + ee_u8 stack_memblock[TOTAL_DATA_SIZE * MULTITHREAD]; +#endif + /* first call any initializations needed */ + portable_init(&(results[0].port), &argc, argv); + /* First some checks to make sure benchmark will run ok */ + if (sizeof(struct list_head_s) > 128) + { + ee_printf("list_head structure too big for comparable data!\n"); + return MAIN_RETURN_VAL; + } + results[0].seed1 = get_seed(1); + results[0].seed2 = get_seed(2); + results[0].seed3 = get_seed(3); + results[0].iterations = get_seed_32(4); +#if CORE_DEBUG + results[0].iterations = 1; +#endif + results[0].execs = get_seed_32(5); + if (results[0].execs == 0) + { /* if not supplied, execute all algorithms */ + results[0].execs = ALL_ALGORITHMS_MASK; + } + /* put in some default values based on one seed only for easy testing */ + if ((results[0].seed1 == 0) && (results[0].seed2 == 0) + && (results[0].seed3 == 0)) + { /* perfromance run */ + results[0].seed1 = 0; + results[0].seed2 = 0; + results[0].seed3 = 0x66; + } + if ((results[0].seed1 == 1) && (results[0].seed2 == 0) + && (results[0].seed3 == 0)) + { /* validation run */ + results[0].seed1 = 0x3415; + results[0].seed2 = 0x3415; + results[0].seed3 = 0x66; + } +#if (MEM_METHOD == MEM_STATIC) + results[0].memblock[0] = (void *)static_memblk; + results[0].size = TOTAL_DATA_SIZE; + results[0].err = 0; +#if (MULTITHREAD > 1) +#error "Cannot use a static data area with multiple contexts!" +#endif +#elif (MEM_METHOD == MEM_MALLOC) + for (i = 0; i < MULTITHREAD; i++) + { + ee_s32 malloc_override = get_seed(7); + if (malloc_override != 0) + results[i].size = malloc_override; + else + results[i].size = TOTAL_DATA_SIZE; + results[i].memblock[0] = portable_malloc(results[i].size); + results[i].seed1 = results[0].seed1; + results[i].seed2 = results[0].seed2; + results[i].seed3 = results[0].seed3; + results[i].err = 0; + results[i].execs = results[0].execs; + } +#elif (MEM_METHOD == MEM_STACK) +for (i = 0; i < MULTITHREAD; i++) +{ + results[i].memblock[0] = stack_memblock + i * TOTAL_DATA_SIZE; + results[i].size = TOTAL_DATA_SIZE; + results[i].seed1 = results[0].seed1; + results[i].seed2 = results[0].seed2; + results[i].seed3 = results[0].seed3; + results[i].err = 0; + results[i].execs = results[0].execs; +} +#else +#error "Please define a way to initialize a memory block." +#endif + /* Data init */ + /* Find out how space much we have based on number of algorithms */ + for (i = 0; i < NUM_ALGORITHMS; i++) + { + if ((1 << (ee_u32)i) & results[0].execs) + num_algorithms++; + } + for (i = 0; i < MULTITHREAD; i++) + results[i].size = results[i].size / num_algorithms; + /* Assign pointers */ + for (i = 0; i < NUM_ALGORITHMS; i++) + { + ee_u32 ctx; + if ((1 << (ee_u32)i) & results[0].execs) + { + for (ctx = 0; ctx < MULTITHREAD; ctx++) + results[ctx].memblock[i + 1] + = (char *)(results[ctx].memblock[0]) + results[0].size * j; + j++; + } + } + /* call inits */ + for (i = 0; i < MULTITHREAD; i++) + { + if (results[i].execs & ID_LIST) + { + results[i].list = core_list_init( + results[0].size, results[i].memblock[1], results[i].seed1); + } + if (results[i].execs & ID_MATRIX) + { + core_init_matrix(results[0].size, + results[i].memblock[2], + (ee_s32)results[i].seed1 + | (((ee_s32)results[i].seed2) << 16), + &(results[i].mat)); + } + if (results[i].execs & ID_STATE) + { + core_init_state( + results[0].size, results[i].seed1, results[i].memblock[3]); + } + } + + /* automatically determine number of iterations if not set */ + if (results[0].iterations == 0) + { + secs_ret secs_passed = 0; + ee_u32 divisor; + results[0].iterations = 1; + while (secs_passed < (secs_ret)1) + { + results[0].iterations *= 10; + start_time(); + iterate(&results[0]); + stop_time(); + secs_passed = time_in_secs(get_time()); + } + /* now we know it executes for at least 1 sec, set actual run time at + * about 10 secs */ + divisor = (ee_u32)secs_passed; + if (divisor == 0) /* some machines cast float to int as 0 since this + conversion is not defined by ANSI, but we know at + least one second passed */ + divisor = 1; + results[0].iterations *= 1 + 10 / divisor; + } + /* perform actual benchmark */ + start_time(); +#if (MULTITHREAD > 1) + if (default_num_contexts > MULTITHREAD) + { + default_num_contexts = MULTITHREAD; + } + for (i = 0; i < default_num_contexts; i++) + { + results[i].iterations = results[0].iterations; + results[i].execs = results[0].execs; + core_start_parallel(&results[i]); + } + for (i = 0; i < default_num_contexts; i++) + { + core_stop_parallel(&results[i]); + } +#else + iterate(&results[0]); +#endif + stop_time(); + total_time = get_time(); + /* get a function of the input to report */ + seedcrc = crc16(results[0].seed1, seedcrc); + seedcrc = crc16(results[0].seed2, seedcrc); + seedcrc = crc16(results[0].seed3, seedcrc); + seedcrc = crc16(results[0].size, seedcrc); + + switch (seedcrc) + { /* test known output for common seeds */ + case 0x8a02: /* seed1=0, seed2=0, seed3=0x66, size 2000 per algorithm */ + known_id = 0; + ee_printf("6k performance run parameters for coremark.\n"); + break; + case 0x7b05: /* seed1=0x3415, seed2=0x3415, seed3=0x66, size 2000 per + algorithm */ + known_id = 1; + ee_printf("6k validation run parameters for coremark.\n"); + break; + case 0x4eaf: /* seed1=0x8, seed2=0x8, seed3=0x8, size 400 per algorithm + */ + known_id = 2; + ee_printf("Profile generation run parameters for coremark.\n"); + break; + case 0xe9f5: /* seed1=0, seed2=0, seed3=0x66, size 666 per algorithm */ + known_id = 3; + ee_printf("2K performance run parameters for coremark.\n"); + break; + case 0x18f2: /* seed1=0x3415, seed2=0x3415, seed3=0x66, size 666 per + algorithm */ + known_id = 4; + ee_printf("2K validation run parameters for coremark.\n"); + break; + default: + total_errors = -1; + break; + } + if (known_id >= 0) + { + for (i = 0; i < default_num_contexts; i++) + { + results[i].err = 0; + if ((results[i].execs & ID_LIST) + && (results[i].crclist != list_known_crc[known_id])) + { + ee_printf("[%u]ERROR! list crc 0x%04x - should be 0x%04x\n", + i, + results[i].crclist, + list_known_crc[known_id]); + results[i].err++; + } + if ((results[i].execs & ID_MATRIX) + && (results[i].crcmatrix != matrix_known_crc[known_id])) + { + ee_printf("[%u]ERROR! matrix crc 0x%04x - should be 0x%04x\n", + i, + results[i].crcmatrix, + matrix_known_crc[known_id]); + results[i].err++; + } + if ((results[i].execs & ID_STATE) + && (results[i].crcstate != state_known_crc[known_id])) + { + ee_printf("[%u]ERROR! state crc 0x%04x - should be 0x%04x\n", + i, + results[i].crcstate, + state_known_crc[known_id]); + results[i].err++; + } + total_errors += results[i].err; + } + } + total_errors += check_data_types(); + /* and report results */ + ee_printf("CoreMark Size : %lu\n", (long unsigned)results[0].size); + ee_printf("Total ticks : %lu\n", (long unsigned)total_time); +#if HAS_FLOAT + ee_printf("Total time (secs): %f\n", time_in_secs(total_time)); + if (time_in_secs(total_time) > 0) + ee_printf("Iterations/Sec : %f\n", + default_num_contexts * results[0].iterations + / time_in_secs(total_time)); +#else + ee_printf("Total time (secs): %d\n", time_in_secs(total_time)); + if (time_in_secs(total_time) > 0) + ee_printf("Iterations/Sec : %d\n", + default_num_contexts * results[0].iterations + / time_in_secs(total_time)); +#endif +/* if (time_in_secs(total_time) < 10) + { + ee_printf( + "ERROR! Must execute for at least 10 secs for a valid result!\n"); + total_errors++; + } +*/ + + ee_printf("Iterations : %lu\n", + (long unsigned)default_num_contexts * results[0].iterations); +#if (MULTITHREAD > 1) + ee_printf("Parallel %s : %d\n", PARALLEL_METHOD, default_num_contexts); +#endif + ee_printf("Memory location : %s\n", MEM_LOCATION); + /* output for verification */ + ee_printf("seedcrc : 0x%04x\n", seedcrc); + if (results[0].execs & ID_LIST) + for (i = 0; i < default_num_contexts; i++) + ee_printf("[%d]crclist : 0x%04x\n", i, results[i].crclist); + if (results[0].execs & ID_MATRIX) + for (i = 0; i < default_num_contexts; i++) + ee_printf("[%d]crcmatrix : 0x%04x\n", i, results[i].crcmatrix); + if (results[0].execs & ID_STATE) + for (i = 0; i < default_num_contexts; i++) + ee_printf("[%d]crcstate : 0x%04x\n", i, results[i].crcstate); + for (i = 0; i < default_num_contexts; i++) + ee_printf("[%d]crcfinal : 0x%04x\n", i, results[i].crc); + if (total_errors == 0) + { + ee_printf( + "Correct operation validated. See README.md for run and reporting " + "rules.\n"); +#if HAS_FLOAT + if (known_id == 3) + { + ee_printf("CoreMark 1.0 : %f / %s", + default_num_contexts * results[0].iterations + / time_in_secs(total_time), + COMPILER_VERSION); +// COMPILER_VERSION, +// COMPILER_FLAGS); +#if defined(MEM_LOCATION) && !defined(MEM_LOCATION_UNSPEC) + ee_printf(" / %s", MEM_LOCATION); +#else + ee_printf(" / %s", mem_name[MEM_METHOD]); +#endif + +#if (MULTITHREAD > 1) + ee_printf(" / %d:%s", default_num_contexts, PARALLEL_METHOD); +#endif + ee_printf("\n"); + } +#endif + } + if (total_errors > 0) + ee_printf("Errors detected\n"); + if (total_errors < 0) + ee_printf( + "Cannot validate operation for these seed values, please compare " + "with results on a known platform.\n"); + +#if (MEM_METHOD == MEM_MALLOC) + for (i = 0; i < MULTITHREAD; i++) + portable_free(results[i].memblock[0]); +#endif + /* And last call any target specific code for finalizing */ + portable_fini(&(results[0].port)); + + return MAIN_RETURN_VAL; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_ams_peripheral/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_ams_peripheral/main.c index accf4c4d..817cbff6 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_ams_peripheral/main.c +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_ams_peripheral/main.c @@ -10,7 +10,7 @@ #include "ams_regs.h" #include "mmio.h" -#ifdef TARGET_PYNQ_Z2 +#ifdef TARGET_IS_FPGA #error ( "This app does NOT work on the FPGA as it relies on the simulator testbench" ) #endif diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_asm/add.s b/hw/vendor/esl_epfl_x_heep/sw/applications/example_asm/add.s new file mode 100644 index 00000000..2e61b29a --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_asm/add.s @@ -0,0 +1,6 @@ + .section .text + .globl add_asm_function + +add_asm_function: + add a0, a0, a1 # Add the values in a0 and a1, store the result in a0 + ret # Return from the function \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_asm/constants.h b/hw/vendor/esl_epfl_x_heep/sw/applications/example_asm/constants.h new file mode 100644 index 00000000..58834c58 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_asm/constants.h @@ -0,0 +1 @@ +#define MULTIPLY_CONSTANT 2 \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_asm/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_asm/main.c new file mode 100644 index 00000000..48ca9c9e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_asm/main.c @@ -0,0 +1,31 @@ +#include +#include +#include "constants.h" +#include "x-heep.h" + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +extern int add_asm_function(int a, int b); +extern int mul_by_const_asm_function( int a); + +int main() { + int num1 = 10; + int num2 = 20; + int sum = add_asm_function(num1, num2); + int mul = mul_by_const_asm_function(num2); + + PRINTF("%d+%d=%d\n", num1, num2, sum); + PRINTF("%d*%d=%d\n", num2, MULTIPLY_CONSTANT, mul ); + + return (sum == num1+num2) && (mul == num2*MULTIPLY_CONSTANT) ? EXIT_SUCCESS : EXIT_FAILURE; +} \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_asm/multiply.S b/hw/vendor/esl_epfl_x_heep/sw/applications/example_asm/multiply.S new file mode 100644 index 00000000..7130f488 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_asm/multiply.S @@ -0,0 +1,9 @@ +#include "constants.h" + + .section .text + .globl mul_by_const_asm_function + +mul_by_const_asm_function: + li t0, MULTIPLY_CONSTANT # Load the constant into temporary register t0 + mul a0, a0, t0 # Multiply the value in a0 by the constant in t0 + ret # Return from the function \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_clock_gating/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_clock_gating/main.c deleted file mode 100644 index 958e0492..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_clock_gating/main.c +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright EPFL contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "core_v_mini_mcu.h" -#include "power_manager.h" -#include "x-heep.h" - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -static power_manager_t power_manager; - -int main(int argc, char *argv[]) -{ - // Setup power_manager - mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); - power_manager.base_addr = power_manager_reg; - - // Clock-gating the peripheral subsystem - mmio_region_write32(power_manager.base_addr, (ptrdiff_t)(POWER_MANAGER_PERIPH_CLK_GATE_REG_OFFSET), 0x1); - - // Clock-gating ram-banks - // We probably should not clockgate the bank where our RAM resides - for(uint32_t i = 2; i < MEMORY_BANKS; ++i) - mmio_region_write32(power_manager.base_addr, (ptrdiff_t)(power_manager_ram_map[i].clk_gate), 0x1); - - // Clock-gating external subsystems - for(uint32_t i = 0; i < EXTERNAL_DOMAINS; ++i) - mmio_region_write32(power_manager.base_addr, (ptrdiff_t)(power_manager_external_map[i].clk_gate), 0x1); - - // Wait some time - for (int i=0; i<100; i++) asm volatile("nop;"); - - // Enabling the peripheral subsystem - mmio_region_write32(power_manager.base_addr, (ptrdiff_t)(POWER_MANAGER_PERIPH_CLK_GATE_REG_OFFSET), 0x0); - - // Enabling ram-banks - for(uint32_t i = 2; i < MEMORY_BANKS; ++i) - mmio_region_write32(power_manager.base_addr, (ptrdiff_t)(power_manager_ram_map[i].clk_gate), 0x0); - - // Enabling external subsystems - for(uint32_t i = 0; i < EXTERNAL_DOMAINS; ++i) - mmio_region_write32(power_manager.base_addr, (ptrdiff_t)(power_manager_external_map[i].clk_gate), 0x0); - - /* write something to stdout */ - PRINTF("Success.\n\r"); - return EXIT_SUCCESS; -} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/MyClass.cpp b/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/MyClass.cpp new file mode 100644 index 00000000..00d1b576 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/MyClass.cpp @@ -0,0 +1,21 @@ + +extern "C" { + #include + #include +} + +#include "MyClass.hpp" + +MyClass::MyClass(int initialValue) : value(initialValue) {} + +void MyClass::setValue(int newValue) { + value = newValue; +} + +int MyClass::getValue() { + return value*5; +} + +void MyClass::printValue() { + printf("Value: %d\n\r", value); +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/MyClass.hpp b/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/MyClass.hpp new file mode 100644 index 00000000..82922878 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/MyClass.hpp @@ -0,0 +1,15 @@ +#ifndef MYCLASS_HPP +#define MYCLASS_HPP + +class MyClass { +public: + MyClass(int initialValue); // Constructor + void setValue(int newValue); // Setter + int getValue(); // Getter + void printValue(); // Method to print the value + +private: + int value; +}; + +#endif // MYCLASS_HPP diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/main.c deleted file mode 100644 index bbe2f071..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/main.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2020 ETH Zurich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Author: Robert Balas - */ - -#include -#include - -int main(int argc, char *argv[]) -{ - /* write something to stdout */ - printf("hello world!\n"); - return EXIT_SUCCESS; -} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/main.cpp b/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/main.cpp new file mode 100644 index 00000000..b314a2b8 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/main.cpp @@ -0,0 +1,50 @@ +/* + * Copyright 2024 EPFL + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Juan Sapriza + */ + + + +extern "C" { + #include + #include +} + +#include "MyClass.hpp" +#include "core_v_mini_mcu.h" +#include "x-heep.h" + +#if TARGET_SIM && PRINTF_IN_SIM +#define PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM +#define PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +int main() +{ + MyClass myObject(10); // Create an object with initial value 10 + myObject.printValue(); // Print the initial value + + myObject.setValue(20); // Change the value to 20 + myObject.printValue(); // Print the updated value + + int value = myObject.getValue(); // Get the value + PRINTF("Retrieved Value: %d\n\r" ,value); // Print the retrieved value + + return value == 20*5 ? EXIT_SUCCESS : EXIT_FAILURE; +} \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/test_cpp.cpp b/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/test_cpp.cpp deleted file mode 100644 index 53d08e36..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/test_cpp.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2022 ESL EPFL - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Author: Jose Miranda - */ - -extern "C" { - #include - #include - #include "test_cpp.h" -} - -#define LOOPS 5 -template -T mySum(T x, T y) -{ - return x+y; -} - -int test_numbers(void) -{ - int i = 0, a = 3, b = 7; - - while (i < LOOPS) - { - printf("Integer sum %d\n", mySum(a, b)); - i = i + 1; - } - - return 0; -} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/test_cpp.h b/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/test_cpp.h deleted file mode 100644 index 31121435..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_cpp/test_cpp.h +++ /dev/null @@ -1,4 +0,0 @@ -/// @brief -/// @param -/// @return -int test_numbers(void); \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_data_processing_from_flash/gen_stimuly.py b/hw/vendor/esl_epfl_x_heep/sw/applications/example_data_processing_from_flash/gen_stimuly.py new file mode 100644 index 00000000..4486daad --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_data_processing_from_flash/gen_stimuly.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +## Copyright 2024 EPFL +## Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +## SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +# type " python gen_stimuly.py " in the terminal to generate the matrices.h file + +import sys +import random +import numpy as np + +def write_arr(f, name, arr, ctype, size): + f.write("const " + ctype + " " + name + "[] = {\n") + + for row in arr: + for elem in row[:-1]: + f.write('%d,' % (elem)) + f.write('%d,\n' % (row[-1])) + + f.write('};\n\n') + return + +def write_arr_flash_only(f, name, arr, ctype, size): + f.write( ctype + " __attribute__((section(\".xheep_data_flash_only\"))) __attribute__ ((aligned (16)))" + name + "[] = {\n") + + for row in arr: + for elem in row[:-1]: + f.write('%d,' % (elem)) + f.write('%d,\n' % (row[-1])) + + f.write('};\n\n') + return + + +################################################################################ +f = open('matrices.h', 'w') +f.write('#ifndef MATRICES_H_\n') +f.write('#define MATRICES_H_\n') +f.write('// This file is automatically generated\n') +f.write('#ifdef FLASH_LOAD\n') + +SIZE = 32 +RANGE = 10 + +m_a = [] +m_b = [] +m_exp = [] + +# Generate random 8 bit integers from -RANGE to RANGE for A and B +A = np.random.randint(0, RANGE, size=(SIZE, SIZE), dtype=np.int32) +B = np.random.randint(0, RANGE, size=(SIZE, SIZE), dtype=np.int32) +C = np.zeros((SIZE, SIZE), dtype=np.int32) + +# Test the function with A and B +C = np.matmul(A,B) + +write_arr_flash_only(f, 'A', A, 'int32_t', SIZE) +write_arr(f, 'B', B, 'int32_t', SIZE) +write_arr(f, 'C', C, 'int32_t', SIZE) + +f.write('#endif\n') +f.write('#define MATRIX_SIZE %d\n' % SIZE) + + +f.write('#endif') diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_data_processing_from_flash/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_data_processing_from_flash/main.c new file mode 100644 index 00000000..8785dcef --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_data_processing_from_flash/main.c @@ -0,0 +1,93 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// File: sw/applications/example_data_processing_from_flash/main.c +// Author: Francesco Poluzzi +// Date: 29/07/2024 + +/** + * @file main.c + * @brief Example of data processing (matrix multiplication) reading data from flash memory + * + * Simple example that read a matrix from flash memory in many step and performs + * matrix multiplication. This is useful for applications where the + * data size does not fit in the available SRAM memory, so some data needs to be + * stored as "flash_only" and read trough the spi interface. This usually requires + * filling a buffer and tiling the data processing. +*/ + +#include +#include +#include + +#include "x-heep.h" +#include "w25q128jw.h" +#include "main.h" +#include "dma_sdk.h" + +#define TILING_ROWS 2 + + /* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +int32_t buffer_data[MATRIX_SIZE*TILING_ROWS] = {0}; +int32_t output_matrix[MATRIX_SIZE*MATRIX_SIZE] = {0}; + +int main(int argc, char *argv[]) { +#ifndef FLASH_LOAD + PRINTF("This application is meant to run with the FLASH_LOAD linker script\n"); + return EXIT_SUCCESS; +#else + + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + + #ifdef TARGET_SIM + PRINTF("This application is meant to run on FPGA only\n"); + return EXIT_SUCCESS; + #endif + + if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) { + PRINTF("This application cannot work with the memory mapped SPI FLASH" + "module - do not use the FLASH_EXEC linker script for this application\n"); + return EXIT_SUCCESS; + } + + // Pick the correct spi device based on simulation type + spi_host_t* spi = spi_flash; + + // Init SPI host and SPI<->Flash bridge parameters + if (w25q128jw_init(spi) != FLASH_OK){ + PRINTF("Error initializing SPI flash\n"); + return EXIT_FAILURE; + } + + for (int i = 0; i < MATRIX_SIZE; i+=TILING_ROWS) { + // read first half matrix A from flash and perform matmul + if(fill_buffer(&A[i*MATRIX_SIZE], buffer_data, MATRIX_SIZE*TILING_ROWS)!=FLASH_OK){ + PRINTF("Error reading from flash\n"); + return EXIT_FAILURE; + } + matmul(buffer_data, B, &output_matrix[i*MATRIX_SIZE], TILING_ROWS, MATRIX_SIZE, MATRIX_SIZE); + } + + for(int i = 0; i < MATRIX_SIZE*MATRIX_SIZE; i++){ + if (output_matrix[i] != C[i]){ + PRINTF("Result[%d][%d]:golden model %d : %d\n", (i/MATRIX_SIZE), (i % MATRIX_SIZE), output_matrix[i], C[i]); + return EXIT_FAILURE; + } + } + PRINTF("All tests passed!\n"); + return EXIT_SUCCESS; + +#endif +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_data_processing_from_flash/main.h b/hw/vendor/esl_epfl_x_heep/sw/applications/example_data_processing_from_flash/main.h new file mode 100644 index 00000000..0e588e78 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_data_processing_from_flash/main.h @@ -0,0 +1,42 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// File: sw/applications/example_data_processing_from_flash/main.h +// Author: Francesco Poluzzi +// Date: 29/07/2024 + +#ifndef MAIN_H_ +#define MAIN_H_ + +#include +#include +#include + +#include "x-heep.h" +#include "w25q128jw.h" +#include "matrices.h" + +w25q_error_codes_t fill_buffer(uint32_t *source, uint32_t *buffer, uint32_t len); +void matmul(int32_t *A, int32_t *B, int32_t *res, int rowsA, int colsA, int colsB); + +w25q_error_codes_t fill_buffer(uint32_t *source, uint32_t *buffer, uint32_t len){ + uint32_t *source_flash = heep_get_flash_address_offset(source); + w25q_error_codes_t status = w25q128jw_read_standard(source_flash, buffer, len*4); + return status; +} + +void matmul(int32_t *A, int32_t *B, int32_t *res, int rowsA, int colsA, int colsB) { + for (int i = 0; i < rowsA; i++) { + for (int j = 0; j < colsB; j++) { + int32_t sum = 0; + for (int k = 0; k < colsA; k++) { + sum += A[i*colsA + k] * B[k*colsB + j]; + } + res[i*colsB + j] = sum; + } + } +} + + +#endif // DATA_H_ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_data_processing_from_flash/matrices.h b/hw/vendor/esl_epfl_x_heep/sw/applications/example_data_processing_from_flash/matrices.h new file mode 100644 index 00000000..59dc4443 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_data_processing_from_flash/matrices.h @@ -0,0 +1,112 @@ +#ifndef MATRICES_H_ +#define MATRICES_H_ +// This file is automatically generated +#ifdef FLASH_LOAD +int32_t __attribute__((section(".xheep_data_flash_only"))) __attribute__ ((aligned (16)))A[] = { +9,2,4,0,5,0,6,4,3,9,7,8,0,8,9,0,3,2,4,0,5,8,3,4,0,4,9,8,3,6,4,7, +5,7,3,4,1,8,5,7,7,3,1,0,5,8,5,5,4,1,8,0,1,6,7,8,4,1,1,6,2,1,2,6, +0,7,7,6,4,7,2,9,9,1,2,9,7,6,1,8,1,1,6,5,0,6,3,3,7,6,6,4,2,7,2,6, +7,6,3,7,3,3,5,0,2,8,2,1,8,7,1,4,5,5,9,4,0,9,9,1,9,9,0,9,0,9,1,9, +1,1,5,0,3,4,0,2,5,4,2,3,2,8,0,4,3,8,1,2,0,2,2,7,2,7,4,6,8,1,4,7, +0,8,7,7,4,2,5,3,0,7,0,3,9,1,9,3,9,2,4,8,0,7,2,0,6,2,9,7,8,5,0,8, +3,9,3,0,1,1,7,8,2,7,9,4,2,6,9,2,4,1,8,3,9,8,3,4,5,4,8,0,2,4,9,0, +2,0,6,7,4,3,3,1,8,4,6,7,5,3,9,9,6,1,8,4,4,2,5,6,7,6,2,6,4,2,1,5, +7,3,0,8,6,6,2,8,6,9,6,8,4,0,0,5,5,5,0,4,4,0,9,8,9,9,8,2,2,0,1,0, +5,6,2,7,4,9,2,8,8,2,2,4,0,9,0,9,7,2,6,6,7,3,7,8,3,7,1,0,0,0,6,1, +5,4,8,7,5,3,3,1,2,5,6,0,3,9,6,4,7,3,1,2,0,8,6,2,4,5,1,9,5,0,8,8, +6,9,0,7,0,3,8,6,6,8,4,3,1,7,8,2,4,4,2,3,3,8,3,9,5,4,3,9,4,5,9,6, +7,0,0,7,0,8,6,7,1,1,3,9,7,7,0,7,0,9,8,3,6,4,9,1,3,9,0,3,6,0,1,0, +6,9,9,6,3,5,9,4,1,3,8,2,9,6,5,9,1,3,1,4,1,8,7,6,3,2,9,1,1,5,0,2, +5,2,8,5,3,4,7,8,6,7,0,1,0,4,7,5,6,0,8,6,9,9,5,9,7,3,2,8,5,3,6,5, +1,4,4,1,6,7,0,8,6,8,6,7,8,2,3,6,6,1,0,1,2,0,6,4,5,1,2,2,3,7,7,3, +0,3,6,7,5,4,1,2,8,1,9,3,6,5,5,3,7,5,4,1,3,2,3,0,8,5,5,2,6,9,1,7, +8,6,9,3,9,4,1,9,1,4,8,7,5,2,5,0,7,7,9,5,2,9,8,9,5,7,6,5,1,6,1,0, +2,8,6,6,7,3,0,9,3,5,5,9,2,0,2,3,9,9,3,0,0,4,5,1,2,6,5,0,6,0,6,3, +9,8,1,1,0,2,2,4,3,7,4,8,9,8,5,0,8,4,6,6,7,4,5,4,1,9,1,9,1,3,5,2, +0,8,2,2,5,3,0,2,2,4,5,3,4,1,2,3,7,7,0,2,6,8,5,7,5,1,6,5,8,2,8,4, +9,8,4,3,3,7,9,8,3,5,9,8,6,1,5,3,2,8,8,2,3,0,1,4,4,1,7,3,1,0,6,1, +6,6,1,4,4,3,1,7,9,3,6,8,2,4,4,7,6,6,0,8,6,7,6,0,0,2,9,7,4,7,2,1, +2,3,7,1,3,2,4,7,8,8,9,2,0,1,7,9,4,5,9,4,5,6,2,3,6,0,7,9,4,5,8,2, +9,2,8,2,2,5,3,6,1,2,4,3,2,3,7,6,7,9,2,4,4,3,7,1,1,0,9,2,6,3,4,9, +1,9,7,1,7,2,2,1,0,3,0,2,3,0,9,6,4,0,4,9,5,3,9,0,5,3,0,7,9,5,8,4, +1,7,6,5,4,4,6,0,7,7,4,7,8,3,8,1,6,4,2,0,6,5,6,4,7,3,6,9,8,2,5,0, +3,4,3,8,0,4,2,8,9,8,9,9,1,8,3,1,8,0,9,7,8,3,3,1,3,0,3,2,7,4,0,7, +8,6,3,2,3,9,7,5,3,2,0,2,7,2,8,8,4,3,6,9,7,7,6,6,3,1,2,7,6,5,9,0, +4,1,2,9,4,5,5,2,8,1,6,7,7,0,4,0,4,4,0,8,0,5,8,5,5,5,0,9,3,3,1,7, +9,7,0,5,1,4,6,0,2,7,5,8,5,6,5,4,8,2,4,2,9,2,2,4,6,0,2,0,3,0,6,8, +7,3,4,2,4,1,3,7,1,9,8,0,6,0,1,4,8,9,0,6,8,2,2,7,8,5,6,5,2,8,7,7, +}; + +const int32_t B[] = { +1,2,5,3,4,3,8,1,6,3,8,5,5,9,8,5,2,6,0,2,1,4,0,0,5,8,8,6,0,8,5,9, +9,6,7,8,4,9,6,2,9,4,8,6,1,2,1,4,7,8,7,5,8,2,8,8,0,9,1,6,8,7,0,1, +3,5,5,0,0,0,6,4,1,1,9,6,6,5,2,7,4,2,0,6,8,4,2,9,1,0,5,9,5,2,8,3, +2,6,0,3,6,4,3,4,5,7,8,3,1,5,0,6,3,8,9,2,8,2,8,8,8,8,0,6,6,1,9,3, +8,9,3,8,7,7,5,2,2,7,0,4,0,1,1,4,1,2,7,1,8,9,5,7,9,6,3,1,0,8,1,4, +6,6,6,6,7,7,4,7,8,8,8,0,7,8,1,2,8,7,0,4,1,7,1,6,1,5,8,9,1,0,7,5, +3,7,2,3,7,6,5,8,7,5,6,5,3,3,3,3,8,4,7,3,0,2,0,0,0,5,9,9,3,2,4,8, +5,2,9,1,0,8,4,4,7,4,9,3,9,3,5,0,4,4,5,9,9,5,7,7,7,7,0,1,8,7,7,3, +8,0,4,2,1,7,3,0,4,8,0,2,6,1,4,9,1,0,2,4,2,8,6,1,5,0,4,0,5,6,2,3, +5,6,8,5,0,5,4,2,8,6,0,5,4,1,3,9,5,0,6,7,1,4,8,2,5,3,4,5,4,0,7,7, +1,2,9,1,9,2,2,0,8,4,3,9,2,7,3,2,7,7,5,1,1,7,3,9,8,8,9,1,5,1,7,3, +4,7,8,2,3,8,2,3,7,4,0,5,0,1,4,1,3,8,8,6,6,3,8,9,0,0,5,9,0,1,1,5, +2,9,2,2,0,1,9,4,6,1,7,5,0,1,1,3,9,6,1,4,4,9,2,8,1,3,0,4,0,6,9,6, +6,2,2,1,2,4,3,0,6,7,8,4,0,7,3,7,1,1,7,6,8,1,7,5,7,7,7,7,9,3,9,5, +8,0,9,5,9,2,4,5,6,7,8,5,9,3,2,7,4,8,0,7,1,4,4,1,4,0,4,5,7,4,0,1, +1,9,4,6,3,6,0,8,2,0,4,0,9,5,6,3,4,9,0,0,5,3,2,8,3,2,4,5,9,6,9,7, +1,9,9,4,4,6,0,1,2,6,3,0,2,0,1,4,0,0,8,4,1,3,4,6,7,5,3,6,2,0,2,9, +7,9,6,5,4,4,4,0,5,8,6,5,9,6,0,6,6,9,9,9,2,7,6,1,7,0,2,0,7,8,8,4, +3,1,9,6,2,5,0,5,4,3,8,3,3,9,2,7,8,7,1,3,6,7,1,6,5,3,0,6,9,4,1,3, +8,5,0,0,4,3,2,2,4,5,8,0,9,1,5,3,5,9,5,6,7,6,7,5,6,1,1,6,4,8,2,5, +9,6,3,7,2,6,0,1,0,9,0,2,7,2,6,1,8,0,0,3,3,5,5,1,6,4,0,8,7,9,0,2, +6,7,9,2,5,1,2,5,3,8,0,1,4,4,9,4,2,6,6,6,2,7,5,2,8,6,2,1,5,5,4,9, +5,4,9,8,7,7,8,0,0,7,9,5,4,8,6,6,1,3,7,8,2,9,0,5,2,6,0,1,8,9,4,2, +5,7,0,6,8,0,4,2,8,7,4,2,5,4,8,2,7,7,7,8,1,6,6,8,4,5,6,3,2,7,5,4, +9,4,1,7,6,0,1,3,3,7,2,3,6,7,5,4,3,2,3,5,7,2,3,1,8,1,7,2,3,6,6,8, +5,8,8,4,8,5,1,5,8,4,6,4,6,0,6,5,7,7,1,1,7,7,4,5,8,4,0,7,2,3,6,9, +2,3,9,0,0,6,2,8,1,4,0,8,5,5,6,2,1,0,2,1,7,3,1,9,7,6,8,8,0,3,1,4, +1,3,9,6,2,6,3,7,3,4,1,8,5,0,3,1,0,3,5,5,7,4,2,5,1,4,3,5,4,8,5,5, +2,9,0,3,0,8,1,0,0,7,3,9,1,7,9,8,0,2,7,0,8,2,0,9,9,3,7,9,7,9,0,8, +2,8,9,6,9,4,7,8,3,0,4,8,0,0,1,1,3,0,9,0,3,6,6,3,2,2,5,8,0,3,4,2, +8,9,0,2,3,4,7,5,0,8,1,1,3,5,5,6,8,0,7,5,7,0,8,3,4,7,4,2,2,6,6,0, +4,8,8,4,0,9,2,5,9,0,6,9,6,9,7,0,3,2,4,2,0,7,6,9,5,8,0,2,7,7,1,6, +}; + +const int32_t C[] = { +626,710,934,522,553,696,511,517,688,718,560,731,575,571,626,583,521,524,662,600,565,671,612,693,694,657,622,732,588,660,550,698, +616,645,731,564,502,644,490,470,667,680,719,509,583,616,528,565,548,587,556,617,536,654,521,680,566,627,474,602,672,664,614,628, +701,813,830,551,536,751,510,601,719,675,721,610,631,579,569,570,606,679,645,612,779,749,676,890,664,603,515,742,656,698,698,702, +673,881,915,687,647,702,579,576,754,709,789,684,600,648,575,664,622,678,731,631,648,805,630,737,716,692,479,726,688,747,760,836, +493,654,551,399,352,537,342,336,499,559,464,494,484,465,473,479,398,425,518,466,503,526,468,623,559,434,430,509,488,560,520,562, +625,851,830,548,496,693,490,583,639,664,687,682,589,513,521,598,531,611,675,586,688,664,594,830,679,582,483,784,622,671,557,745, +746,716,855,542,589,661,488,508,667,781,628,601,617,576,599,603,697,587,635,644,637,632,648,686,710,667,571,720,680,664,567,624, +640,762,784,595,601,662,430,512,653,719,658,591,652,581,566,638,583,671,577,578,624,729,578,793,695,523,528,718,668,672,634,713, +673,794,767,596,609,711,493,433,701,789,613,562,653,555,595,576,587,654,660,624,637,731,617,769,749,629,545,652,535,687,691,736, +725,758,687,581,580,722,448,434,655,794,716,400,654,595,574,595,619,651,617,624,656,676,654,739,697,662,473,674,683,690,671,654, +623,787,751,530,549,631,508,464,616,730,669,617,566,619,556,646,501,562,667,593,626,632,586,740,705,677,522,637,662,670,687,706, +778,843,849,634,661,755,579,564,805,872,708,678,679,622,661,669,659,670,813,728,653,681,758,730,743,754,617,740,724,781,696,749, +571,742,688,522,524,667,442,434,628,696,726,505,585,625,541,546,612,723,571,568,605,671,483,670,627,552,442,688,640,666,691,696, +624,809,802,541,632,630,606,573,716,672,792,657,615,638,569,581,653,730,637,609,630,718,556,832,627,687,621,756,645,678,746,708, +795,847,844,662,612,741,523,592,679,882,736,601,790,659,722,695,658,630,689,739,705,754,678,760,788,677,578,801,778,836,680,792, +594,745,710,520,483,639,508,428,582,620,532,523,502,455,453,498,533,472,594,551,550,639,581,720,547,521,487,571,488,582,605,559, +602,751,765,526,559,641,439,453,596,658,614,648,522,559,457,576,513,523,618,477,607,692,566,760,714,541,517,650,594,603,599,633, +764,888,1043,671,739,725,630,545,781,841,819,716,705,662,639,668,693,796,778,776,759,907,690,911,826,722,595,773,667,813,734,792, +601,788,781,490,467,699,444,383,587,678,580,550,519,506,463,565,505,581,679,575,642,614,608,775,671,576,420,579,569,591,559,603, +680,776,863,573,549,696,541,441,736,739,698,607,582,499,563,602,649,657,655,676,626,709,659,704,642,641,465,747,612,721,628,718, +637,807,668,542,482,616,431,388,504,725,456,543,515,500,541,507,510,499,667,556,560,600,569,699,649,579,459,550,550,694,504,590, +645,722,796,531,548,686,546,505,745,707,698,621,624,625,495,560,716,709,601,627,602,658,568,732,605,629,610,706,580,649,643,637, +666,766,882,533,548,773,492,482,608,752,593,617,650,506,588,561,497,627,698,601,657,718,652,751,711,610,534,700,635,749,583,672, +698,754,897,585,547,703,473,574,610,766,590,644,741,610,603,652,624,597,637,642,671,707,625,745,737,581,607,685,730,741,654,670, +575,751,808,490,472,680,495,468,562,651,700,625,677,663,568,547,503,569,575,575,542,647,501,728,656,590,536,676,629,698,575,648, +662,763,664,590,513,643,476,457,452,639,616,548,557,477,511,562,506,532,572,527,648,593,514,676,552,499,392,658,616,741,443,555, +721,837,803,621,577,710,547,501,634,844,592,683,576,537,555,684,602,586,701,658,667,691,607,761,668,585,597,771,623,716,619,709, +652,692,831,503,477,770,400,407,698,752,659,621,574,604,561,613,554,570,686,599,636,679,684,801,749,628,522,755,730,626,561,674, +756,877,768,653,637,725,601,597,644,823,769,555,732,625,645,631,709,729,645,679,665,740,595,728,652,645,575,802,676,855,659,728, +591,730,693,507,594,617,491,434,649,686,622,574,556,495,510,511,502,640,653,571,524,724,555,692,606,543,451,577,510,663,588,662, +627,749,660,541,495,651,442,399,662,695,583,533,512,588,532,539,598,559,592,538,485,554,589,647,607,624,528,691,574,609,532,664, +683,909,809,598,581,661,541,501,678,728,621,660,702,562,606,543,666,567,704,625,603,735,670,734,776,657,553,664,576,775,709,741, +}; + +#endif +#define MATRIX_SIZE 32 +#endif \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma/main.c index bbab3698..6ee5797b 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma/main.c +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma/main.c @@ -5,57 +5,217 @@ #include #include - #include "dma.h" #include "core_v_mini_mcu.h" #include "x-heep.h" #include "csr.h" #include "rv_plic.h" -#define TEST_SINGULAR_MODE +// TEST DEFINES AND CONFIGURATION + +#define TEST_SINGLE_MODE +#define TEST_ADDRESS_MODE #define TEST_PENDING_TRANSACTION #define TEST_WINDOW -#define TEST_ADDRESS_MODE #define TEST_ADDRESS_MODE_EXTERNAL_DEVICE -#define TEST_DATA_SIZE 16 -#define TEST_DATA_LARGE 1024 -#define TRANSACTIONS_N 3 // Only possible to perform transaction at a time, others should be blocked -#define TEST_WINDOW_SIZE_DU 1024 // if put at <=71 the isr is too slow to react to the interrupt +#define TEST_DATA_SIZE 16 +#define TEST_DATA_LARGE 256 +#define TRANSACTIONS_N 3 // Only possible to perform one transaction at a time, others should be blocked +#define TEST_WINDOW_SIZE_DU 256 // if put at <=71 the isr is too slow to react to the interrupt - - -#if TEST_DATA_LARGE < 2* TEST_DATA_SIZE - #errors("TEST_DATA_LARGE must be at least 2*TEST_DATA_SIZE") +#if TEST_DATA_LARGE < 2 * TEST_DATA_SIZE +#errors("TEST_DATA_LARGE must be at least 2*TEST_DATA_SIZE") #endif /* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 #if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#define PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM +#define PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__) #else - #define PRINTF(...) +#define PRINTF(...) #endif +// UTILITIES + +#define type2name(dma_type) \ + dma_type == DMA_DATA_TYPE_BYTE ? "8-bit" : dma_type == DMA_DATA_TYPE_HALF_WORD ? "16-bit" \ + : dma_type == DMA_DATA_TYPE_WORD ? "32-bit" \ + : "TYPE NOT VALID" + +dma_data_type_t C_type_2_dma_type(int C_type) +{ + switch (C_type) + { + case 1: + return DMA_DATA_TYPE_BYTE; + case 2: + return DMA_DATA_TYPE_HALF_WORD; + case 4: + return DMA_DATA_TYPE_WORD; + default: + return DMA_DATA_TYPE_WORD; + } +} + +#define WAIT_DMA \ + while (!dma_is_ready(0)) \ + { \ + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); \ + if (dma_is_ready(0) == 0) \ + { \ + wait_for_interrupt(); \ + } \ + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); \ + } + +#define RUN_DMA \ + trans.flags = 0x0; \ + res = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); \ + PRINTF("tran: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); \ + res = dma_load_transaction(&trans); \ + PRINTF("load: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); \ + res = dma_launch(&trans); \ + PRINTF("laun: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); + +// TEST MACROS + +#define PRINT_TEST(signed, data_size, dma_src_type, dma_dst_type) \ + PRINTF("TEST:\n\r"); \ + PRINTF("Data size: %d\n\r", data_size); \ + PRINTF("Signed: %d\n\r", signed); \ + PRINTF("Source type size: %s\n\r", type2name(dma_src_type)); \ + PRINTF("Destination type size: %s\n\r", type2name(dma_dst_type)); + +#define DEFINE_DATA(data_size, C_src_type, C_dst_type, signed) \ + C_src_type src[data_size] __attribute__((aligned(4))); \ + C_dst_type dst[data_size] __attribute__((aligned(4))); \ + if (data_size <= TEST_DATA_SIZE) \ + for (int i = 0; i < data_size; i++) \ + if (signed && (i % 2) == 0) \ + src[i] = (C_src_type)(-test_data_4B[i]); \ + else \ + src[i] = (C_src_type)test_data_4B[i]; + +#define CHECK_RESULTS(data_size) \ + for (int i = 0; i < data_size; i++) \ + { \ + if (src[i] != dst[i]) \ + { \ + PRINTF("[%d] Expected: %x Got : %x\n\r", i, src[i], dst[i]); \ + errors++; \ + } \ + } \ + if (errors != 0) \ + { \ + PRINTF("DMA failure: %d errors out of %d elements checked\n\r", errors, trans.size_d1_du); \ + return EXIT_FAILURE; \ + } + +#define INIT_TEST(signed, data_size, dma_src_type, dma_dst_type) \ + tgt_src.ptr = (uint8_t *)src; \ + tgt_src.inc_d1_du = 1; \ + tgt_src.inc_d2_du = 0; \ + tgt_src.trig = DMA_TRIG_MEMORY; \ + tgt_src.type = dma_src_type; \ + tgt_src.env = NULL; \ + tgt_dst.ptr = (uint8_t *)dst; \ + tgt_dst.inc_d1_du = 1; \ + tgt_dst.inc_d2_du = 0; \ + tgt_dst.trig = DMA_TRIG_MEMORY; \ + tgt_dst.type = dma_dst_type; \ + tgt_dst.env = NULL; \ + trans.src = &tgt_src; \ + trans.dst = &tgt_dst; \ + trans.src_addr = &tgt_addr; \ + trans.src_type = dma_src_type; \ + trans.dst_type = dma_dst_type; \ + trans.size_d1_du = data_size; \ + trans.mode = DMA_TRANS_MODE_SINGLE; \ + trans.win_du = 0; \ + trans.sign_ext = signed; \ + trans.end = DMA_TRANS_END_INTR; \ + trans.dim = DMA_DIM_CONF_1D; \ + +#define TEST(C_src_type, C_dst_type, test_size, sign_extend) \ + PRINT_TEST(sign_extend, test_size, C_type_2_dma_type(sizeof(C_src_type)), C_type_2_dma_type(sizeof(C_dst_type))) \ + DEFINE_DATA(test_size, C_src_type, C_dst_type, sign_extend) \ + INIT_TEST(sign_extend, test_size, C_type_2_dma_type(sizeof(C_src_type)), C_type_2_dma_type(sizeof(C_dst_type))) \ + RUN_DMA \ + WAIT_DMA \ + CHECK_RESULTS(test_size) \ + PRINTF("\n\r") + +#define TEST_SINGLE \ + { \ + TEST(uint8_t, uint8_t, TEST_DATA_SIZE, 0); \ + errors += errors; \ + } \ + { \ + TEST(uint8_t, uint16_t, TEST_DATA_SIZE, 0); \ + errors += errors; \ + } \ + { \ + TEST(uint8_t, uint32_t, TEST_DATA_SIZE, 0); \ + errors += errors; \ + } \ + { \ + TEST(int8_t, int8_t, TEST_DATA_SIZE, 1); \ + errors += errors; \ + } \ + { \ + TEST(int8_t, int16_t, TEST_DATA_SIZE, 1); \ + errors += errors; \ + } \ + { \ + TEST(int8_t, int32_t, TEST_DATA_SIZE, 1); \ + errors += errors; \ + } \ + { \ + TEST(uint16_t, uint16_t, TEST_DATA_SIZE, 0); \ + errors += errors; \ + } \ + { \ + TEST(uint16_t, uint32_t, TEST_DATA_SIZE, 0); \ + errors += errors; \ + } \ + { \ + TEST(int16_t, int16_t, TEST_DATA_SIZE, 1); \ + errors += errors; \ + } \ + { \ + TEST(int16_t, int32_t, TEST_DATA_SIZE, 1); \ + errors += errors; \ + } \ + { \ + TEST(uint32_t, uint32_t, TEST_DATA_SIZE, 0); \ + errors += errors; \ + } \ + { \ + TEST(int32_t, int32_t, TEST_DATA_SIZE, 1); \ + errors += errors; \ + } + +// GLOBAL VARIABLES int32_t errors = 0; int8_t cycles = 0; -void dma_intr_handler_trans_done() +// INTERRUPT HANDLERS +void dma_intr_handler_trans_done(uint8_t channel) { cycles++; } - #ifdef TEST_WINDOW int32_t window_intr_flag; -void dma_intr_handler_window_done(void) { +void dma_intr_handler_window_done(uint8_t channel) { window_intr_flag ++; } @@ -66,94 +226,62 @@ uint8_t dma_window_ratio_warning_threshold() #endif // TEST_WINDOW +dma_trans_t trans; int main(int argc, char *argv[]) { - static uint32_t test_data_4B[TEST_DATA_SIZE] __attribute__ ((aligned (4))) = { - 0x76543210, 0xfedcba98, 0x579a6f90, 0x657d5bee, 0x758ee41f, 0x01234567, 0xfedbca98, 0x89abcdef, 0x679852fe, 0xff8252bb, 0x763b4521, 0x6875adaa, 0x09ac65bb, 0x666ba334, 0x55446677, 0x65ffba98}; - static uint32_t copied_data_4B[TEST_DATA_LARGE] __attribute__ ((aligned (4))) = { 0 }; - static uint32_t test_data_large[TEST_DATA_LARGE] __attribute__ ((aligned (4))) = { 0 }; - // this array will contain the even address of copied_data_4B - uint32_t* test_addr_4B_PTR = &test_data_large[0]; + static uint32_t test_data_4B[TEST_DATA_SIZE] __attribute__((aligned(4))) = { + 0x76543210, 0xfedcba98, 0x579a6f90, 0x657d5bee, 0x758ee41f, 0x01234567, 0xfedbca98, 0x89abcdef, 0x679852fe, 0xff8252bb, 0x763b4521, 0x6875adaa, 0x09ac65bb, 0x666ba334, 0x55446677, 0x65ffba98}; + static uint32_t copied_data_4B[TEST_DATA_LARGE] __attribute__((aligned(4))) = {0}; + static uint32_t test_data_large[TEST_DATA_LARGE] __attribute__((aligned(4))) = {0}; + + // this array will contain the even address of copied_data_4B + uint32_t *test_addr_4B_PTR = &test_data_large[0]; // The DMA is initialized (i.e. Any current transaction is cleaned.) dma_init(NULL); - dma_config_flags_t res; - - dma_target_t tgt_src = { - .ptr = test_data_4B, - .inc_du = 1, - .size_du = TEST_DATA_SIZE, - .trig = DMA_TRIG_MEMORY, - .type = DMA_DATA_TYPE_WORD, - }; - dma_target_t tgt_dst = { - .ptr = copied_data_4B, - .inc_du = 1, - .size_du = TEST_DATA_SIZE, - .trig = DMA_TRIG_MEMORY, - }; - + dma_target_t tgt_src; + dma_target_t tgt_dst; dma_target_t tgt_addr = { - .ptr = test_addr_4B_PTR, - .inc_du = 1, - .size_du = TEST_DATA_SIZE, - .trig = DMA_TRIG_MEMORY, - }; - - dma_trans_t trans = { - .src = &tgt_src, - .dst = &tgt_dst, - .src_addr = &tgt_addr, - .mode = DMA_TRANS_MODE_SINGLE, - .win_du = 0, - .end = DMA_TRANS_END_INTR, - }; - // Create a target pointing at the buffer to be copied. Whole WORDs, no skippings, in memory, no environment. - -#ifdef TEST_SINGULAR_MODE + .ptr = (uint8_t *)test_addr_4B_PTR, + .inc_d1_du = 1, + .trig = DMA_TRIG_MEMORY, + }; + +#ifdef TEST_SINGLE_MODE PRINTF("\n\n\r===================================\n\n\r"); PRINTF(" TESTING SINGLE MODE "); PRINTF("\n\n\r===================================\n\n\r"); - res = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); - PRINTF("tran: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); - res = dma_load_transaction(&trans); - PRINTF("load: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); - res = dma_launch(&trans); - PRINTF("laun: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); - - while( ! dma_is_ready()) { - // disable_interrupts - // this does not prevent waking up the core as this is controlled by the MIP register - CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); - if ( dma_is_ready() == 0 ) { - wait_for_interrupt(); - //from here we wake up even if we did not jump to the ISR - } - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - } - PRINTF(">> Finished transaction. \n\r"); + TEST_SINGLE - for(uint32_t i = 0; i < trans.size_b; i++ ) { - if ( ((uint8_t*)copied_data_4B)[i] != ((uint8_t*)test_data_4B)[i] ) { - PRINTF("ERROR [%d]: %04x != %04x\n\r", i, ((uint8_t*)copied_data_4B)[i], ((uint8_t*)test_data_4B)[i]); - errors++; - } - } +#endif // TEST_SINGLE_MODE - if (errors == 0) { - PRINTF("DMA single mode success.\n\r"); - } else { - PRINTF("DMA single mode failure: %d errors out of %d bytes checked\n\r", errors, trans.size_b ); - return EXIT_FAILURE; - } + // Initialize the DMA for the next tests + tgt_src.ptr = (uint8_t *)test_data_4B; + tgt_src.inc_d1_du = 1; + tgt_src.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE_WORD; + + tgt_dst.ptr = (uint8_t *)copied_data_4B; + tgt_dst.inc_d1_du = 1; + tgt_dst.trig = DMA_TRIG_MEMORY; + tgt_dst.type = DMA_DATA_TYPE_WORD; -#endif // TEST_SINGULAR_MODE + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.src_addr = &tgt_addr; + trans.size_d1_du = TEST_DATA_SIZE; + trans.src_type = DMA_DATA_TYPE_WORD; + trans.dst_type = DMA_DATA_TYPE_WORD; + trans.mode = DMA_TRANS_MODE_SINGLE; + trans.win_du = 0; + trans.sign_ext = 0; + trans.end = DMA_TRANS_END_INTR; #ifdef TEST_ADDRESS_MODE @@ -162,66 +290,54 @@ int main(int argc, char *argv[]) PRINTF("\n\n\r===================================\n\n\r"); // Prepare the data - for (int i = 0; i < TEST_DATA_SIZE; i++) { - test_addr_4B_PTR[i] = &copied_data_4B[i*2]; + for (int i = 0; i < TEST_DATA_SIZE; i++) + { + test_addr_4B_PTR[i] = (uint32_t)&copied_data_4B[i * 2]; } trans.mode = DMA_TRANS_MODE_ADDRESS; - res = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); - PRINTF("tran: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); - res = dma_load_transaction(&trans); - PRINTF("load: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); - res = dma_launch(&trans); - PRINTF("laun: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); - - while( ! dma_is_ready()) { - // disable_interrupts - // this does not prevent waking up the core as this is controlled by the MIP register - CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); - if ( dma_is_ready() == 0 ) { - wait_for_interrupt(); - //from here we wake up even if we did not jump to the ISR - } - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - } + RUN_DMA + WAIT_DMA PRINTF(">> Finished transaction. \n\r"); - for(uint32_t i = 0; i < trans.size_b >> 2; i++ ) { - if ( copied_data_4B[i*2] != test_data_4B[i] ) { - PRINTF("ERROR [%d]: %04x != %04x\n\r", i, copied_data_4B[i*2], test_data_4B[i]); + for (uint32_t i = 0; i < trans.size_d1_du; i++) + { + if (copied_data_4B[i * 2] != test_data_4B[i]) + { + PRINTF("ERROR [%d]: %04x != %04x\n\r", i, copied_data_4B[i * 2], test_data_4B[i]); errors++; } } - if (errors == 0) { + if (errors == 0) + { PRINTF("DMA address mode success.\n\r"); - } else { - PRINTF("DMA address mode failure: %d errors out of %d bytes checked\n\r", errors, trans.size_b ); + } + else + { + PRINTF("DMA address mode failure: %d errors out of %d elements checked\n\r", errors, trans.size_d1_du); return EXIT_FAILURE; } - trans.mode = DMA_TRANS_MODE_SINGLE; - #endif // TEST_ADDRESS_MODE -#ifndef TARGET_PYNQ_Z2 +#if defined(TARGET_SIM) || defined(TARGET_SYSTEMC) #ifdef TEST_ADDRESS_MODE_EXTERNAL_DEVICE -#pragma message ( "this application should not be ran in a system integrating x-heep as in the external \ - slave can be plugged something else than a slow memory as in our testbench" ) - - uint32_t* ext_test_addr_4B_PTR = EXT_SLAVE_START_ADDRESS; - uint32_t* ext_copied_data_4B; +#pragma message("this application should not be ran in a system integrating x-heep as in the external \ + slave can be plugged something else than a slow memory as in our testbench") - ext_copied_data_4B = &ext_test_addr_4B_PTR[TEST_DATA_SIZE+1]; + uint32_t *ext_test_addr_4B_PTR = (uint32_t *)EXT_SLAVE_START_ADDRESS; + uint32_t *ext_copied_data_4B; + ext_copied_data_4B = &ext_test_addr_4B_PTR[TEST_DATA_SIZE + 1]; - tgt_addr.ptr = ext_test_addr_4B_PTR; + tgt_addr.ptr = (uint8_t *) ext_test_addr_4B_PTR; trans.src_addr = &tgt_addr; PRINTF("\n\n\r=====================================\n\n\r"); @@ -229,53 +345,44 @@ int main(int argc, char *argv[]) PRINTF("\n\n\r=====================================\n\n\r"); // Prepare the data - for (int i = 0; i < TEST_DATA_SIZE; i++) { - ext_test_addr_4B_PTR[i] = &ext_copied_data_4B[i*2]; + for (int i = 0; i < TEST_DATA_SIZE; i++) + { + ext_test_addr_4B_PTR[i] = (uint32_t) &ext_copied_data_4B[i * 2]; } trans.mode = DMA_TRANS_MODE_ADDRESS; - res = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); - PRINTF("tran: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); - res = dma_load_transaction(&trans); - PRINTF("load: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); - res = dma_launch(&trans); - PRINTF("laun: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); - - while( ! dma_is_ready()) { - // disable_interrupts - // this does not prevent waking up the core as this is controlled by the MIP register - CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); - if ( dma_is_ready() == 0 ) { - wait_for_interrupt(); - //from here we wake up even if we did not jump to the ISR - } - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - } + RUN_DMA + WAIT_DMA PRINTF(">> Finished transaction. \n\r"); - for(uint32_t i = 0; i < trans.size_b >> 2; i++ ) { - if ( ext_copied_data_4B[i*2] != test_data_4B[i] ) { + for (uint32_t i = 0; i < trans.size_d1_du; i++) + { + if (ext_copied_data_4B[i * 2] != test_data_4B[i]) + { PRINTF("ERROR [%d]: %04x != %04x\n\r", i, ext_copied_data_4B[i], test_data_4B[i]); errors++; } } - if (errors == 0) { + if (errors == 0) + { PRINTF("DMA address mode in external memory success.\n\r"); - } else { - PRINTF("DMA address mode in external memory failure: %d errors out of %d bytes checked\n\r", errors, trans.size_b ); + } + else + { + PRINTF("DMA address mode in external memory failure: %d errors out of %d elements checked\n\r", errors, trans.size_d1_du); return EXIT_FAILURE; } trans.mode = DMA_TRANS_MODE_SINGLE; -#endif //TEST_ADDRESS_MODE_EXTERNAL_DEVICE +#endif // TEST_ADDRESS_MODE_EXTERNAL_DEVICE #else - #pragma message( "TEST_ADDRESS_MODE_EXTERNAL_DEVICE is not executed on PYNQ Z2" ) +#pragma message("TEST_ADDRESS_MODE_EXTERNAL_DEVICE is not executed on target different than TARGET_SIM") #endif #ifdef TEST_PENDING_TRANSACTION @@ -283,61 +390,68 @@ int main(int argc, char *argv[]) PRINTF(" TESTING MULTIPLE TRANSACTIONS "); PRINTF("\n\n\r===================================\n\n\r"); - for (uint32_t i = 0; i < TEST_DATA_LARGE; i++) { + for (uint32_t i = 0; i < TEST_DATA_LARGE; i++) + { test_data_large[i] = i; } + tgt_src.ptr = (uint8_t *)test_data_large; + trans.size_d1_du = TEST_DATA_LARGE; + trans.mode = DMA_TRANS_MODE_SINGLE; - tgt_src.ptr = test_data_large; - tgt_src.size_du = TEST_DATA_LARGE; - - // trans.end = DMA_TRANS_END_INTR_WAIT; // This option makes no sense, because the launch is blocking the program until the trans finishes. trans.end = DMA_TRANS_END_INTR; - // trans.end = DMA_TRANS_END_POLLING; - - res = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); - PRINTF("tran: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); + res = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + PRINTF("tran: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); cycles = 0; uint8_t consecutive_trans = 0; - for( uint8_t i = 0; i < TRANSACTIONS_N; i++ ){ - res = dma_load_transaction(&trans); + for (uint8_t i = 0; i < TRANSACTIONS_N; i++) + { + res = dma_load_transaction(&trans); res |= dma_launch(&trans); - if( res == DMA_CONFIG_OK ) consecutive_trans++; + if (res == DMA_CONFIG_OK) + consecutive_trans++; } - if( trans.end == DMA_TRANS_END_POLLING ){ - while( cycles < consecutive_trans ){ - while( ! dma_is_ready() ); + if (trans.end == DMA_TRANS_END_POLLING) + { + while (cycles < consecutive_trans) + { + while (!dma_is_ready(0)); cycles++; } - } else { - while( cycles < consecutive_trans ){ + } + else + { + while (cycles < consecutive_trans) + { wait_for_interrupt(); } } PRINTF(">> Finished %d transactions. That is %s.\n\r", consecutive_trans, consecutive_trans > 1 ? "bad" : "good"); - - - for(int i=0; i + * + * + * Info: Example application of matrix manipulation by exploiting the 2D DMA. + * In this code, there are some optional features: + * - Verification of several matrix operations carried out by the 2D DMA + * - Performance comparison between the DMA and the CPU, obtained by performing similar matrix operations + * and monitoring the performance counter. + */ + +#include +#include +#include "dma.h" +#include "core_v_mini_mcu.h" +#include "x-heep.h" +#include "csr.h" +#include "rv_plic.h" +#include "test_data.h" + +/* + * This code contains four different tests that can be run by defining the corresponding TEST_ID_* macro. + * - Extract a NxM matrix, perform optional padding and copy it to a AxB matrix, using HALs + * - Extract a NxM matrix and copy its transposed version to AxB matrix, using HALs + * - Extract a 1xN matrix (array), perform optional padding and copy it to an array, using HALs + * - Extract a NxM matrix, perform optional padding and copy it to a AxB matrix, using direct register operations + */ + +#define TEST_ID_0 +#define TEST_ID_1 +#define TEST_ID_2 +#define TEST_ID_3 + +/* Enable performance analysis */ +#define EN_PERF 1 + +/* Enable verification */ +#define EN_VERIF 1 + +/* Parameters */ + +/* Size of the extracted matrix (including strides on the input, excluding strides on the outputs) */ +#define SIZE_EXTR_D1 3 +#define SIZE_EXTR_D2 3 + +/* Set strides of the input ad output matrix */ +#define STRIDE_IN_D1 1 +#define STRIDE_IN_D2 1 +#define STRIDE_OUT_D1 1 +#define STRIDE_OUT_D2 1 + +/* Set the padding parameters */ +#define TOP_PAD 1 +#define BOTTOM_PAD 1 +#define LEFT_PAD 1 +#define RIGHT_PAD 1 + +/* Macros for dimensions computation */ +#define OUT_D1_PAD ( SIZE_EXTR_D1 + LEFT_PAD + RIGHT_PAD ) +#define OUT_D2_PAD ( SIZE_EXTR_D2 + TOP_PAD + BOTTOM_PAD ) +#define OUT_D1_PAD_STRIDE ( (OUT_D1_PAD * STRIDE_OUT_D1) - (STRIDE_OUT_D1 - 1) ) +#define OUT_D2_PAD_STRIDE ( (OUT_D2_PAD * STRIDE_OUT_D2) - (STRIDE_OUT_D2 - 1) ) +#define OUT_DIM_1D ( OUT_D1_PAD_STRIDE ) +#define OUT_DIM_2D ( OUT_D1_PAD_STRIDE * OUT_D2_PAD_STRIDE ) + +/* Mask for the direct register operations example */ +#define DMA_CSR_REG_MIE_MASK (( 1 << 19 ) | (1 << 11 )) + +/* Transposition example def */ +#define TRANSPOSITION_EN 1 + +/* Enables test format */ +#define TEST_EN 0 + +/* Define the input datatype */ +typedef uint32_t dma_input_data_type; + +/* Pointer increments computation */ +#define SRC_INC_D1 STRIDE_IN_D1 +#define DST_INC_D1 STRIDE_OUT_D1 +#define SRC_INC_D2 (STRIDE_IN_D2 * SIZE_IN_D1 - (SIZE_EXTR_D1 - 1 + (STRIDE_IN_D1 - 1) * (SIZE_EXTR_D1 - 1))) +#define DST_INC_D2 ((STRIDE_OUT_D2 - 1) * OUT_DIM_1D + 1) +#define SRC_INC_TRSP_D1 SRC_INC_D1 +#define SRC_INC_TRSP_D2 (STRIDE_IN_D2 * SIZE_IN_D1) + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +dma_input_data_type copied_data_2D_DMA[OUT_DIM_2D]; +dma_input_data_type copied_data_1D_DMA[OUT_DIM_1D]; +dma_input_data_type copied_data_2D_CPU[OUT_DIM_2D]; +dma_input_data_type copied_data_1D_CPU[OUT_DIM_2D]; + +dma_config_flags_t res_valid, res_load, res_launch; + +dma *peri = dma_peri(0); + +dma_target_t tgt_src; +dma_target_t tgt_dst; +dma_trans_t trans; + +uint32_t dst_ptr = 0, src_ptr = 0; +uint32_t cycles_dma, cycles_cpu; +uint32_t size_dst_trans_d1; +uint32_t dst_stride_d1; +uint32_t dst_stride_d2; +uint32_t size_src_trans_d1; +uint32_t src_stride_d1; +uint32_t src_stride_d2; +uint32_t i_in; +uint32_t j_in; +uint32_t i_in_last; +uint16_t left_pad_cnt = 0; +uint16_t top_pad_cnt = 0; +uint8_t stride_1d_cnt = 0; +uint8_t stride_2d_cnt = 0; +char passed = 1; + +int main() +{ + #ifdef TEST_ID_0 + + /* Testing copy and padding of a NxM matrix using HALs */ + + #if EN_PERF + + /* Reset the counter to evaluate the performance of the DMA */ + timer_cycles_init(); + + #endif + + tgt_src.ptr = (uint8_t *) test_data; + tgt_src.inc_d1_du = SRC_INC_D1; + tgt_src.inc_d2_du = SRC_INC_D2; + tgt_src.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE; + + tgt_dst.ptr = (uint8_t *) copied_data_2D_DMA; + tgt_dst.inc_d1_du = DST_INC_D1; + tgt_dst.inc_d2_du = DST_INC_D2; + tgt_dst.trig = DMA_TRIG_MEMORY; + tgt_dst.type = DMA_DATA_TYPE; + + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.mode = DMA_TRANS_MODE_SINGLE; + trans.dim = DMA_DIM_CONF_2D; + trans.pad_top_du = TOP_PAD, + trans.pad_bottom_du = BOTTOM_PAD, + trans.pad_left_du = LEFT_PAD, + trans.pad_right_du = RIGHT_PAD, + trans.size_d1_du = SIZE_EXTR_D1; + trans.size_d2_du = SIZE_EXTR_D2; + trans.win_du = 0, + trans.end = DMA_TRANS_END_INTR; + + dma_init(NULL); + + timer_start(); + + #if EN_PERF + + res_valid = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + res_load = dma_load_transaction(&trans); + res_launch = dma_launch(&trans); + + #else + + res_valid = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + PRINTF("tran: %u \t%s\n\r", res_valid, res_valid == DMA_CONFIG_OK ? "Ok!" : "Error!"); + res_load = dma_load_transaction(&trans); + PRINTF("load: %u \t%s\n\r", res_load, res_load == DMA_CONFIG_OK ? "Ok!" : "Error!"); + res_launch = dma_launch(&trans); + PRINTF("laun: %u \t%s\n\r", res_launch, res_launch == DMA_CONFIG_OK ? "Ok!" : "Error!"); + #endif + + while( ! dma_is_ready(0)) { + /* Disable_interrupts */ + /* This does not prevent waking up the core as this is controlled by the MIP register */ + + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if ( dma_is_ready(0) == 0 ) { + wait_for_interrupt(); + /* From here the core wakes up even if we did not jump to the ISR */ + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + } + + #if EN_PERF + + /* Read the cycles count after the DMA run */ + cycles_dma = timer_stop(); + + /* Reset the performance counter to evaluate the CPU performance */ + timer_cycles_init(); + timer_start(); + #endif + + #if EN_VERIF + + /* Run the same computation on the CPU */ + for (int i=0; i < OUT_D2_PAD_STRIDE; i++) + { + stride_1d_cnt = 0; + j_in = 0; + + for (int j=0; j < OUT_D1_PAD_STRIDE; j++) + { + dst_ptr = i * OUT_D1_PAD_STRIDE + j; + src_ptr = (i_in - top_pad_cnt ) * STRIDE_IN_D2 * SIZE_IN_D1 + (j_in - left_pad_cnt) * STRIDE_IN_D1; + if (i_in < TOP_PAD || i_in >= SIZE_EXTR_D2 + TOP_PAD || j_in < LEFT_PAD || j_in >= SIZE_EXTR_D1 + LEFT_PAD || + stride_1d_cnt != 0 || stride_2d_cnt != 0) + { + copied_data_2D_CPU[dst_ptr] = 0; + } + else + { + copied_data_2D_CPU[dst_ptr] = test_data[src_ptr]; + } + + if (j_in < LEFT_PAD && i_in >= TOP_PAD && stride_1d_cnt == 0 && stride_2d_cnt == 0) + { + left_pad_cnt++; + } + + if (stride_1d_cnt == STRIDE_OUT_D1 - 1) + { + stride_1d_cnt = 0; + j_in++; + } + else + { + stride_1d_cnt++; + } + + } + + if (i_in < TOP_PAD && stride_2d_cnt == 0) + { + top_pad_cnt++; + } + + if (stride_2d_cnt == STRIDE_OUT_D2 - 1) + { + stride_2d_cnt = 0; + i_in++; + } + else + { + stride_2d_cnt++; + } + + left_pad_cnt = 0; + } + #endif + + #if EN_PERF + + /* Read the cycles count after the CPU run */ + cycles_cpu = timer_stop(); + + #if TEST_EN == 0 + PRINTF("Total number of cycles CPU: [%d]\n\r", cycles_cpu); + PRINTF("Total number of cycles DMA: [%d]\n\r", cycles_dma); + #endif + + #endif + + #if EN_VERIF + + /* Verify that the DMA and the CPU outputs are the same */ + for (int i = 0; i < OUT_D2_PAD_STRIDE; i++) { + for (int j = 0; j < OUT_D1_PAD_STRIDE; j++) { + if (copied_data_2D_DMA[i * OUT_D1_PAD_STRIDE + j] != copied_data_2D_CPU[i * OUT_D1_PAD_STRIDE + j]) { + passed = 0; + } + } + } + + if (passed) { + #if TEST_EN == 0 + PRINTF("TEST 0 PASSED!\n\r\n\r"); + #else + PRINTF("0a:%d:0\n\r", cycles_cpu); + PRINTF("0b:%d:0\n\r", cycles_dma); + #endif + } + else + { + #if TEST_EN == 0 + PRINTF("TEST 0 FAILED\n\r"); + #else + PRINTF("0a:%d:1\n\r", cycles_cpu); + PRINTF("0b:%d:1\n\r", cycles_dma); + #endif + return EXIT_FAILURE; + } + #endif + + #endif + + /* Reset for second test */ + passed = 1; + i_in = 0; + j_in = 0; + left_pad_cnt = 0; + top_pad_cnt = 0; + stride_1d_cnt = 0; + stride_2d_cnt = 0; + + for (int i = 0; i < OUT_DIM_2D; i++) { + copied_data_2D_DMA[i] = 0; + copied_data_2D_CPU[i] = 0; + } + + #ifdef TEST_ID_1 + + /* Testing transposition and copy of a NxM matrix using HALs */ + + #if EN_PERF + + /* Reset the counter to evaluate the performance of the DMA */ + timer_cycles_init(); + #endif + + tgt_src.ptr = (uint8_t *) test_data; + tgt_src.inc_d1_du = SRC_INC_TRSP_D1; + tgt_src.inc_d2_du = SRC_INC_TRSP_D2; + tgt_src.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE; + + tgt_dst.ptr = (uint8_t *) copied_data_2D_DMA; + tgt_dst.inc_d1_du = DST_INC_D1; + tgt_dst.inc_d2_du = DST_INC_D2; + tgt_dst.trig = DMA_TRIG_MEMORY; + + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.mode = DMA_TRANS_MODE_SINGLE; + trans.dim = DMA_DIM_CONF_2D; + trans.pad_top_du = TOP_PAD; + trans.pad_bottom_du = BOTTOM_PAD; + trans.pad_left_du = LEFT_PAD; + trans.pad_right_du = RIGHT_PAD; + trans.dim_inv = TRANSPOSITION_EN; + trans.size_d1_du = SIZE_EXTR_D1; + trans.size_d2_du = SIZE_EXTR_D2; + trans.win_du = 0, + trans.end = DMA_TRANS_END_INTR; + + dma_init(NULL); + + timer_start(); + + #if EN_PERF + + res_valid = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + res_load = dma_load_transaction(&trans); + res_launch = dma_launch(&trans); + + #else + + res_valid = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + PRINTF("tran: %u \t%s\n\r", res_valid, res_valid == DMA_CONFIG_OK ? "Ok!" : "Error!"); + res_load = dma_load_transaction(&trans); + PRINTF("load: %u \t%s\n\r", res_load, res_load == DMA_CONFIG_OK ? "Ok!" : "Error!"); + res_launch = dma_launch(&trans); + PRINTF("laun: %u \t%s\n\r", res_launch, res_launch == DMA_CONFIG_OK ? "Ok!" : "Error!"); + #endif + + while( ! dma_is_ready(0)) { + /* Disable_interrupts */ + /* This does not prevent waking up the core as this is controlled by the MIP register */ + + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if ( dma_is_ready(0) == 0 ) { + wait_for_interrupt(); + /* From here the core wakes up even if we did not jump to the ISR */ + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + } + + #if EN_PERF + + /* Read the cycles count after the DMA run */ + cycles_dma = timer_stop(); + + /* Reset the performance counter to evaluate the CPU performance */ + timer_cycles_init(); + timer_start(); + #endif + + #if EN_VERIF + + /* Run the same computation on the CPU */ + for (int i=0; i < OUT_D2_PAD_STRIDE; i++) + { + stride_1d_cnt = 0; + j_in = 0; + + for (int j=0; j < OUT_D1_PAD_STRIDE; j++) + { + dst_ptr = i * OUT_D1_PAD_STRIDE + j; + src_ptr = (j_in - left_pad_cnt) * STRIDE_IN_D2 * SIZE_IN_D1 + (i_in - top_pad_cnt ) * STRIDE_IN_D1; + if (i_in < TOP_PAD || i_in >= SIZE_EXTR_D2 + TOP_PAD || j_in < LEFT_PAD || j_in >= SIZE_EXTR_D1 + LEFT_PAD || + stride_1d_cnt != 0 || stride_2d_cnt != 0) + { + copied_data_2D_CPU[dst_ptr] = 0; + } + else + { + copied_data_2D_CPU[dst_ptr] = test_data[src_ptr]; + } + + if (j_in < LEFT_PAD && i_in >= TOP_PAD && stride_1d_cnt == 0 && stride_2d_cnt == 0) + { + left_pad_cnt++; + } + + if (stride_1d_cnt == STRIDE_OUT_D1 - 1) + { + stride_1d_cnt = 0; + j_in++; + } + else + { + stride_1d_cnt++; + } + + } + + if (i_in < TOP_PAD && stride_2d_cnt == 0) + { + top_pad_cnt++; + } + + if (stride_2d_cnt == STRIDE_OUT_D2 - 1) + { + stride_2d_cnt = 0; + i_in++; + } + else + { + stride_2d_cnt++; + } + + left_pad_cnt = 0; + } + #endif + + #if EN_PERF + + /* Read the cycles count after the CPU run */ + cycles_cpu = timer_stop(); + #if TEST_EN == 0 + PRINTF("Total number of cycles CPU: [%d]\n\r", cycles_cpu); + PRINTF("Total number of cycles DMA: [%d]\n\r", cycles_dma); + #endif + + #endif + + #if EN_VERIF + + /* Verify that the DMA and the CPU outputs are the same */ + for (int i = 0; i < OUT_D2_PAD_STRIDE; i++) { + for (int j = 0; j < OUT_D1_PAD_STRIDE; j++) { + if (copied_data_2D_DMA[i * OUT_D1_PAD_STRIDE + j] != copied_data_2D_CPU[i * OUT_D1_PAD_STRIDE + j]) { + passed = 0; + } + } + } + + if (passed) { + #if TEST_EN == 0 + PRINTF("TEST 1 PASSED!\n\r\n\r"); + #else + PRINTF("1a:%d:0\n\r", cycles_cpu); + PRINTF("1b:%d:0\n\r", cycles_dma); + #endif + } + else + { + #if TEST_EN == 0 + PRINTF("TEST 1 FAILED\n\r"); + #else + PRINTF("1a:%d:1\n\r", cycles_cpu); + PRINTF("1b:%d:1\n\r", cycles_dma); + #endif + return EXIT_FAILURE; + } + #endif + + #endif + + /* Reset for third test */ + passed = 1; + i_in = 0; + j_in = 0; + left_pad_cnt = 0; + top_pad_cnt = 0; + stride_1d_cnt = 0; + stride_2d_cnt = 0; + + #ifdef TEST_ID_2 + + /* Testing copy and padding of a 1xN matrix (an array) */ + + #if EN_PERF + + /* Reset the counter to evaluate the performance of the DMA */ + timer_cycles_init(); + #endif + + tgt_src.ptr = (uint8_t *) test_data; + tgt_src.inc_d1_du = SRC_INC_D1; + tgt_src.inc_d2_du = 0; + tgt_src.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE; + + tgt_dst.ptr = (uint8_t *) copied_data_1D_DMA; + tgt_dst.inc_d1_du = DST_INC_D1; + tgt_dst.inc_d2_du = 0; + tgt_dst.trig = DMA_TRIG_MEMORY; + + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.mode = DMA_TRANS_MODE_SINGLE; + trans.dim = DMA_DIM_CONF_1D; + trans.pad_top_du = 0; + trans.pad_bottom_du = 0; + trans.pad_left_du = LEFT_PAD; + trans.pad_right_du = RIGHT_PAD; + trans.dim_inv = 0; + trans.win_du = 0; + trans.size_d1_du = SIZE_EXTR_D1; + trans.size_d2_du = 0; + trans.end = DMA_TRANS_END_INTR; + + dma_init(NULL); + + timer_start(); + + #if EN_PERF + + res_valid = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + res_load = dma_load_transaction(&trans); + res_launch = dma_launch(&trans); + + #else + + res_valid = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + PRINTF("tran: %u \t%s\n\r", res_valid, res_valid == DMA_CONFIG_OK ? "Ok!" : "Error!"); + res_load = dma_load_transaction(&trans); + PRINTF("load: %u \t%s\n\r", res_load, res_load == DMA_CONFIG_OK ? "Ok!" : "Error!"); + res_launch = dma_launch(&trans); + PRINTF("laun: %u \t%s\n\r", res_launch, res_launch == DMA_CONFIG_OK ? "Ok!" : "Error!"); + #endif + + while( ! dma_is_ready(0)) { + /* Disable_interrupts */ + + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if ( dma_is_ready(0) == 0 ) { + wait_for_interrupt(); + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + } + + #if EN_PERF + + /* Read the cycles count after the DMA run */ + cycles_dma = timer_stop(); + + /* Reset the performance counter to evaluate the CPU performance */ + timer_cycles_init(); + timer_start(); + #endif + + #if EN_VERIF + + /* Run the same computation on the CPU */ + for (int j=0; j < OUT_D1_PAD_STRIDE; j++) + { + dst_ptr = j; + src_ptr = (j_in - left_pad_cnt) * STRIDE_IN_D1; + + if (j_in < LEFT_PAD || j_in >= SIZE_EXTR_D1 + LEFT_PAD || + stride_1d_cnt != 0) + { + copied_data_1D_CPU[dst_ptr] = 0; + } + else + { + copied_data_1D_CPU[dst_ptr] = test_data[src_ptr]; + } + + if (j_in < LEFT_PAD && stride_1d_cnt == 0) + { + left_pad_cnt++; + } + + if (stride_1d_cnt == STRIDE_OUT_D1 - 1) + { + stride_1d_cnt = 0; + j_in++; + } + else + { + stride_1d_cnt++; + } + } + + #endif + + #if EN_PERF + + /* Read the cycles count after the CPU run */ + cycles_cpu = timer_stop(); + #if TEST_EN == 0 + PRINTF("Total number of cycles CPU: [%d]\n\r", cycles_cpu); + PRINTF("Total number of cycles DMA: [%d]\n\r", cycles_dma); + #endif + + #endif + + #if EN_VERIF + + /* Verify that the DMA and the CPU outputs are the same */ + for (int i = 0; i < OUT_D1_PAD_STRIDE; i++) { + if (copied_data_1D_DMA[i] != copied_data_1D_CPU[i]) { + passed = 0; + } + } + + if (passed) { + #if TEST_EN == 0 + PRINTF("TEST 2 PASSED!\n\r\n\r"); + #else + PRINTF("2a:%d:0\n\r", cycles_cpu); + PRINTF("2b:%d:0\n\r", cycles_dma); + #endif + } + else + { + #if TEST_EN == 0 + PRINTF("TEST 2 FAILED\n\r"); + #else + PRINTF("2a:%d:1\n\r", cycles_cpu); + PRINTF("2b:%d:1\n\r", cycles_dma); + #endif + return EXIT_FAILURE; + } + #endif + + #endif + + /* Reset for fourth test */ + passed = 1; + i_in = 0; + j_in = 0; + left_pad_cnt = 0; + top_pad_cnt = 0; + stride_1d_cnt = 0; + stride_2d_cnt = 0; + for (int i = 0; i < OUT_DIM_2D; i++) { + copied_data_2D_DMA[i] = 0; + copied_data_2D_CPU[i] = 0; + } + + #ifdef TEST_ID_3 + + /* Testing copy and padding of a NxM matrix using direct register operations. + * This strategy allows for maximum performance but doesn't perform any checks on the data integrity. + */ + + #if EN_PERF + + /* Reset the counter to evaluate the performance of the DMA */ + timer_cycles_init(); + #endif + + /* The DMA is initialized (i.e. Any current transaction is cleaned.) */ + dma_init(NULL); + + timer_start(); + + /* Enable the DMA interrupt logic */ + write_register( 0x1, + DMA_INTERRUPT_EN_REG_OFFSET, + 0xffff, + DMA_INTERRUPT_EN_TRANSACTION_DONE_BIT, + peri ); + + /* Enable global interrupts */ + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + + /* Enable fast interrupts */ + CSR_SET_BITS(CSR_REG_MIE, DMA_CSR_REG_MIE_MASK); + + /* Pointer set up */ + peri->SRC_PTR = (uint32_t) (test_data); + peri->DST_PTR = (uint32_t) (copied_data_2D_DMA); + + /* Dimensionality configuration */ + write_register( 0x1, + DMA_DIM_CONFIG_REG_OFFSET, + 0xffff, + DMA_DIM_CONFIG_DMA_DIM_BIT, + peri ); + + /* Operation mode configuration */ + write_register( DMA_TRANS_MODE_SINGLE, + DMA_MODE_REG_OFFSET, + DMA_MODE_MODE_MASK, + DMA_MODE_MODE_OFFSET, + peri ); + + /* Data type configuration */ + write_register( DMA_DATA_TYPE, + DMA_DST_DATA_TYPE_REG_OFFSET, + DMA_DST_DATA_TYPE_DATA_TYPE_MASK, + DMA_DST_DATA_TYPE_DATA_TYPE_OFFSET, + peri ); + write_register( DMA_DATA_TYPE, + DMA_SRC_DATA_TYPE_REG_OFFSET, + DMA_SRC_DATA_TYPE_DATA_TYPE_MASK, + DMA_SRC_DATA_TYPE_DATA_TYPE_OFFSET, + peri ); + + /* Set the source strides */ + write_register( SRC_INC_D1 * DMA_DATA_TYPE_2_SIZE(DMA_DATA_TYPE), + DMA_SRC_PTR_INC_D1_REG_OFFSET, + DMA_SRC_PTR_INC_D1_INC_MASK, + DMA_SRC_PTR_INC_D1_INC_OFFSET, + peri ); + + write_register( SRC_INC_D2 * DMA_DATA_TYPE_2_SIZE(DMA_DATA_TYPE), + DMA_SRC_PTR_INC_D2_REG_OFFSET, + DMA_SRC_PTR_INC_D2_INC_MASK, + DMA_SRC_PTR_INC_D2_INC_OFFSET, + peri ); + + write_register( DST_INC_D1 * DMA_DATA_TYPE_2_SIZE( DMA_DATA_TYPE), + DMA_DST_PTR_INC_D1_REG_OFFSET, + DMA_DST_PTR_INC_D1_INC_MASK, + DMA_DST_PTR_INC_D1_INC_OFFSET, + peri ); + + write_register( DST_INC_D2 * DMA_DATA_TYPE_2_SIZE( DMA_DATA_TYPE), + DMA_DST_PTR_INC_D2_REG_OFFSET, + DMA_DST_PTR_INC_D2_INC_MASK, + DMA_DST_PTR_INC_D2_INC_OFFSET, + peri ); + + /* Padding configuration */ + write_register( TOP_PAD, + DMA_PAD_TOP_REG_OFFSET, + DMA_PAD_TOP_PAD_MASK, + DMA_PAD_TOP_PAD_OFFSET, + peri ); + + write_register( RIGHT_PAD, + DMA_PAD_RIGHT_REG_OFFSET, + DMA_PAD_RIGHT_PAD_MASK, + DMA_PAD_RIGHT_PAD_OFFSET, + peri ); + + write_register( LEFT_PAD, + DMA_PAD_LEFT_REG_OFFSET, + DMA_PAD_LEFT_PAD_MASK, + DMA_PAD_LEFT_PAD_OFFSET, + peri ); + + write_register( BOTTOM_PAD, + DMA_PAD_BOTTOM_REG_OFFSET, + DMA_PAD_BOTTOM_PAD_MASK, + DMA_PAD_BOTTOM_PAD_OFFSET, + peri ); + + /* Set the sizes */ + + write_register( SIZE_EXTR_D2, + DMA_SIZE_D2_REG_OFFSET, + DMA_SIZE_D2_SIZE_MASK, + DMA_SIZE_D2_SIZE_OFFSET, + peri ); + + write_register( SIZE_EXTR_D1, + DMA_SIZE_D1_REG_OFFSET, + DMA_SIZE_D1_SIZE_MASK, + DMA_SIZE_D1_SIZE_OFFSET, + peri ); + + while( ! dma_is_ready(0)) { + /* Disable_interrupts */ + /* This does not prevent waking up the core as this is controlled by the MIP register */ + + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if ( dma_is_ready(0) == 0 ) { + wait_for_interrupt(); + /* From here the core wakes up even if we did not jump to the ISR */ + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + } + + #if EN_PERF + + /* Read the cycles count after the DMA run */ + cycles_dma = timer_stop(); + + /* Reset the performance counter to evaluate the CPU performance */ + timer_cycles_init(); + timer_start(); + #endif + + #if EN_VERIF + + /* Run the same computation on the CPU */ + for (int i=0; i < OUT_D2_PAD_STRIDE; i++) + { + stride_1d_cnt = 0; + j_in = 0; + + for (int j=0; j < OUT_D1_PAD_STRIDE; j++) + { + dst_ptr = i * OUT_D1_PAD_STRIDE + j; + src_ptr = (i_in - top_pad_cnt ) * STRIDE_IN_D2 * SIZE_IN_D1 + (j_in - left_pad_cnt) * STRIDE_IN_D1; + if (i_in < TOP_PAD || i_in >= SIZE_EXTR_D2 + TOP_PAD || j_in < LEFT_PAD || j_in >= SIZE_EXTR_D1 + LEFT_PAD || + stride_1d_cnt != 0 || stride_2d_cnt != 0) + { + copied_data_2D_CPU[dst_ptr] = 0; + } + else + { + copied_data_2D_CPU[dst_ptr] = test_data[src_ptr]; + } + + if (j_in < LEFT_PAD && i_in >= TOP_PAD && stride_1d_cnt == 0 && stride_2d_cnt == 0) + { + left_pad_cnt++; + } + + if (stride_1d_cnt == STRIDE_OUT_D1 - 1) + { + stride_1d_cnt = 0; + j_in++; + } + else + { + stride_1d_cnt++; + } + + } + + if (i_in < TOP_PAD && stride_2d_cnt == 0) + { + top_pad_cnt++; + } + + if (stride_2d_cnt == STRIDE_OUT_D2 - 1) + { + stride_2d_cnt = 0; + i_in++; + } + else + { + stride_2d_cnt++; + } + + left_pad_cnt = 0; + } + + #endif + + #if EN_PERF + + /* Read the cycles count after the CPU run */ + cycles_cpu = timer_stop(); + #if TEST_EN == 0 + PRINTF("Total number of cycles CPU: [%d]\n\r", cycles_cpu); + PRINTF("Total number of cycles DMA: [%d]\n\r", cycles_dma); + #endif + + #endif + + #if EN_VERIF + + /* Verify that the DMA and the CPU outputs are the same */ + if (passed) { + #if TEST_EN == 0 + PRINTF("TEST 3 PASSED!\n\r\n\r"); + #else + PRINTF("3a:%d:0\n\r", cycles_cpu); + PRINTF("3b:%d:0\n\r", cycles_dma); + #endif + } + else + { + #if TEST_EN == 0 + PRINTF("TEST 3 FAILED\n\r"); + #else + PRINTF("3a:%d:1\n\r", cycles_cpu); + PRINTF("3b:%d:1\n\r", cycles_dma); + #endif + return EXIT_FAILURE; + } + #endif + + #endif + + #if TEST_EN + PRINTF("&\n\r"); + #endif + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_2d/test_data.h b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_2d/test_data.h new file mode 100644 index 00000000..66dcc52a --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_2d/test_data.h @@ -0,0 +1,35 @@ +#ifndef __TEST_DATA_H__ +#define __TEST_DATA_H__ + +#define SIZE_IN_D1 25 +#define SIZE_IN_D2 25 +#define DMA_DATA_TYPE DMA_DATA_TYPE_WORD + +uint32_t test_data[SIZE_IN_D1 * SIZE_IN_D2] = { + 93 ,178 ,28 ,23 ,5 ,231 ,211 ,236 ,45 ,196 ,55 ,124 ,113 ,188 ,36 ,43 ,147 ,111 ,254 ,126 ,145 ,83 ,77 ,7 ,126, + 92 ,179 ,157 ,41 ,64 ,7 ,105 ,93 ,176 ,196 ,171 ,42 ,251 ,175 ,120 ,63 ,134 ,56 ,233 ,0 ,189 ,133 ,71 ,226 ,9, + 252 ,214 ,243 ,177 ,205 ,75 ,100 ,165 ,160 ,42 ,112 ,71 ,238 ,208 ,62 ,1 ,113 ,87 ,116 ,212 ,107 ,165 ,214 ,239 ,151, + 215 ,3 ,80 ,243 ,0 ,18 ,30 ,149 ,237 ,35 ,81 ,149 ,227 ,23 ,240 ,13 ,117 ,122 ,158 ,253 ,120 ,175 ,203 ,30 ,204, + 45 ,18 ,176 ,241 ,38 ,232 ,189 ,208 ,50 ,120 ,4 ,47 ,136 ,141 ,154 ,207 ,180 ,160 ,46 ,191 ,48 ,29 ,122 ,30 ,45, + 56 ,8 ,137 ,197 ,185 ,210 ,103 ,123 ,116 ,25 ,57 ,126 ,41 ,213 ,165 ,17 ,111 ,151 ,39 ,115 ,21 ,59 ,220 ,165 ,142, + 175 ,169 ,150 ,41 ,68 ,241 ,228 ,121 ,125 ,163 ,16 ,244 ,157 ,8 ,205 ,148 ,194 ,115 ,7 ,59 ,164 ,127 ,88 ,184 ,215, + 13 ,6 ,102 ,204 ,29 ,15 ,182 ,125 ,141 ,251 ,172 ,13 ,159 ,196 ,93 ,200 ,211 ,42 ,10 ,154 ,105 ,82 ,109 ,175 ,117, + 115 ,109 ,201 ,196 ,242 ,139 ,178 ,191 ,190 ,181 ,140 ,197 ,233 ,34 ,69 ,20 ,193 ,35 ,243 ,11 ,41 ,131 ,196 ,8 ,133, + 70 ,234 ,210 ,171 ,107 ,57 ,133 ,162 ,114 ,168 ,118 ,250 ,12 ,30 ,223 ,95 ,246 ,122 ,73 ,220 ,247 ,6 ,102 ,214 ,108, + 48 ,55 ,22 ,243 ,241 ,45 ,147 ,32 ,105 ,25 ,185 ,22 ,41 ,2 ,5 ,82 ,221 ,237 ,223 ,162 ,77 ,95 ,62 ,198 ,97, + 206 ,210 ,61 ,7 ,163 ,142 ,20 ,215 ,35 ,92 ,232 ,88 ,52 ,207 ,137 ,234 ,123 ,251 ,214 ,221 ,23 ,19 ,51 ,245 ,188, + 251 ,139 ,176 ,240 ,126 ,29 ,247 ,228 ,248 ,164 ,14 ,198 ,143 ,15 ,178 ,72 ,238 ,220 ,145 ,7 ,253 ,233 ,245 ,32 ,95, + 142 ,30 ,227 ,66 ,67 ,177 ,47 ,2 ,87 ,155 ,74 ,255 ,1 ,69 ,157 ,181 ,73 ,57 ,60 ,39 ,64 ,93 ,146 ,4 ,220, + 129 ,219 ,109 ,159 ,65 ,112 ,162 ,145 ,241 ,59 ,55 ,21 ,12 ,196 ,239 ,239 ,31 ,58 ,148 ,215 ,241 ,109 ,72 ,108 ,61, + 178 ,205 ,116 ,33 ,240 ,137 ,150 ,150 ,148 ,80 ,211 ,87 ,46 ,160 ,64 ,9 ,179 ,221 ,91 ,113 ,87 ,132 ,141 ,70 ,95, + 104 ,62 ,121 ,12 ,149 ,108 ,197 ,154 ,51 ,247 ,78 ,121 ,186 ,124 ,140 ,138 ,155 ,117 ,221 ,55 ,233 ,1 ,61 ,190 ,220, + 123 ,200 ,239 ,89 ,200 ,167 ,191 ,121 ,24 ,249 ,145 ,189 ,15 ,249 ,235 ,165 ,243 ,239 ,102 ,41 ,62 ,159 ,45 ,248 ,28, + 128 ,200 ,95 ,240 ,148 ,118 ,168 ,156 ,62 ,88 ,102 ,14 ,197 ,252 ,135 ,54 ,170 ,249 ,133 ,250 ,172 ,67 ,60 ,35 ,246, + 7 ,9 ,7 ,181 ,49 ,60 ,239 ,70 ,33 ,29 ,132 ,112 ,37 ,28 ,34 ,233 ,37 ,178 ,40 ,20 ,189 ,43 ,45 ,65 ,194, + 104 ,43 ,31 ,59 ,49 ,157 ,15 ,198 ,205 ,47 ,201 ,88 ,49 ,199 ,55 ,223 ,43 ,13 ,118 ,225 ,175 ,94 ,222 ,236 ,10, + 157 ,75 ,239 ,221 ,34 ,14 ,26 ,232 ,18 ,240 ,198 ,3 ,23 ,226 ,110 ,118 ,172 ,0 ,17 ,210 ,136 ,226 ,223 ,162 ,169, + 4 ,35 ,179 ,115 ,9 ,54 ,89 ,178 ,2 ,108 ,123 ,178 ,61 ,107 ,228 ,73 ,70 ,46 ,236 ,102 ,179 ,182 ,49 ,130 ,229, + 72 ,159 ,179 ,125 ,24 ,152 ,13 ,104 ,186 ,2 ,174 ,204 ,191 ,241 ,158 ,84 ,96 ,184 ,19 ,171 ,135 ,101 ,27 ,218 ,217, + 211 ,180 ,172 ,64 ,213 ,56 ,76 ,16 ,82 ,205 ,105 ,165 ,185 ,61 ,19 ,158 ,252 ,192 ,135 ,110 ,246 ,84 ,2 ,18 ,72}; + +#endif \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_external/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_external/main.c index a4fa35a7..24d8429c 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_external/main.c +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_external/main.c @@ -20,7 +20,7 @@ #if TARGET_SIM && PRINTF_IN_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA +#elif PRINTF_IN_FPGA && !TARGET_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) #else #define PRINTF(...) @@ -29,7 +29,7 @@ int32_t errors = 0; -void dma_intr_handler_trans_done() +void dma_intr_handler_trans_done(uint8_t channel) { PRINTF("D"); } @@ -51,20 +51,19 @@ int main(int argc, char *argv[]) static dma_target_t tgt_src = { .ptr = test_data, - .inc_du = 1, - .size_du = TEST_DATA_SIZE, + .inc_d1_du = 1, .trig = DMA_TRIG_MEMORY, .type = DMA_DATA_TYPE_WORD, }; static dma_target_t tgt_dst = { .ptr = copied_data, - .inc_du = 1, - .size_du = TEST_DATA_SIZE, + .inc_d1_du = 1, .trig = DMA_TRIG_MEMORY, }; static dma_trans_t trans = { .src = &tgt_src, .dst = &tgt_dst, + .size_d1_du = TEST_DATA_SIZE, .mode = DMA_TRANS_MODE_SINGLE, .win_du = 0, .end = DMA_TRANS_END_INTR, @@ -82,11 +81,11 @@ int main(int argc, char *argv[]) res = dma_launch(&trans); PRINTF("laun: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); - while( ! dma_is_ready() ){ + while( ! dma_is_ready(0) ){ // disable_interrupts // this does not prevent waking up the core as this is controlled by the MIP register CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); - if ( dma_is_ready() == 0 ) { + if ( dma_is_ready(0) == 0 ) { wait_for_interrupt(); //from here we wake up even if we did not jump to the ISR } @@ -94,7 +93,7 @@ int main(int argc, char *argv[]) } PRINTF(">> Finished transaction. \n\r"); - for(uint32_t i = 0; i < trans.size_b; i++ ) { + for(uint32_t i = 0; i < trans.size_d1_du; i++ ) { if ( ((uint8_t*)copied_data)[i] != ((uint8_t*)test_data)[i] ) { PRINTF("ERROR [%d]: %04x != %04x\n\r", i, ((uint8_t*)copied_data)[i], ((uint8_t*)test_data)[i]); errors++; @@ -105,7 +104,7 @@ int main(int argc, char *argv[]) PRINTF("External DMA success\n\r"); return EXIT_SUCCESS; } else { - PRINTF("External DMA failure: %d errors out of %d bytes checked\n\r", errors, trans.size_b ); + PRINTF("External DMA failure: %d errors out of %d elements checked\n\r", errors, trans.size_d1_du ); return EXIT_FAILURE; } diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_multichannel/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_multichannel/main.c new file mode 100644 index 00000000..8bff88ba --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_multichannel/main.c @@ -0,0 +1,1262 @@ +/* + * Copyright EPFL contributors. + * Licensed under the Apache License, Version 2.0, see LICENSE for details. + * SPDX-License-Identifier: Apache-2.0 + * + * Author: Tommaso Terzano + * + * + * Info: Example application of matrix manipulation by exploiting the multichannel feature of the DMA subsystem. + * This code is capable of testing the following features: + * - Verification of matrix operations carried out by the DMA subsystem + * - Performance comparison between the DMA multichannel and the CPU, obtained by performing similar matrix operations + * and monitoring the performance counter. + * The performance of the DMA is compared against sequential CPU loops for each operation performed by a single channel. + * A typical case in which the DMA could be used to improve the performance is a series of matrix operations, + * like extracting 3 matrices from a larger one. + * By exploiting the DMA, these three separate calls can be performed in parallel. + */ + +#include +#include +#include "dma.h" +#include "core_v_mini_mcu.h" +#include "x-heep.h" +#include "csr.h" +#include "rv_plic.h" +#include "test_data.h" +#include "w25q128jw.h" + +/* + * The following code is designed to test the DMA subsystem multichannel feature. In order to do so, several + * tests are available, which are run using some or all of the DMA channels available. + * + * DISCLAIMER: + * When using the default memory configuration (64kB), pay attention to the dimensions of the output matrices. + * When executing TEST_ID_3 on QuestaSim, make sure to enable the SPI FLASH. + * + * Enable one or more of the following tests by defining the correct TEST_ID_* macro: + * + * 0: Extract a NxM matrix, perform optional padding and copy the result to two separate + * AxB matrices using N channels at the same time and using direct register writes. + * Additionally, each DMA channel is set with a window of M size. For each window interrupt, + * the correct window flag is set. + * + * 1: Extract a NxM matrix, perform optional padding and copy the result to two separate + * AxB matrices using N channels at the same time and using HALs. For each transaction interrupt, + * the correct transaction flag is set. + * + * 2: Each DMA channel performs, alternatively, one of the following operations: + * - Extract a NxM matrix, perform optional padding and copy the result + * - Extract a NxM matrix, perform optional padding, transpose it and copy the result + * + * 3: Extract a NxM matrix, perform optional padding and copy the result to a location using one channel (with HALs), + * while at the same time read a buffer from SPI and copy it to another location using another channel (with HALs). + * This test can only be performed on FPGA boards or using QuestaSim, by setting the correct macro (SIM_QUESTASIM). + * When executing on QuestaSim, make sure to compile in the correct way: + * - Include LINKER=flash_load in "make app ..." + * - Add boot_sel and execute_from_flash: + * 'make run PLUSARGS="c firmware=../../../sw/build/main.hex boot_sel=1 execute_from_flash=0" ' + * + */ + +#define TEST_ID_0 +#define TEST_ID_1 +#define TEST_ID_2 +#define TEST_ID_3 + +/* Enable performance analysis */ +#define EN_PERF 1 + +/* Enable verification */ +#define EN_VERIF 1 + +/* Parameters */ + +/* Size of the extracted matrix (including strides on the input, excluding strides on the outputs) */ +#define SIZE_EXTR_D1 10 +#define SIZE_EXTR_D2 10 + +/* Set strides of the input ad output matrix */ +#define STRIDE_IN_D1 1 +#define STRIDE_IN_D2 1 +#define STRIDE_OUT_D1 1 +#define STRIDE_OUT_D2 1 + +/* Set the padding parameters */ +#define TOP_PAD 0 +#define BOTTOM_PAD 0 +#define LEFT_PAD 0 +#define RIGHT_PAD 0 + +/* Macros for dimensions computation */ +#define OUT_D1_PAD ( SIZE_EXTR_D1 + LEFT_PAD + RIGHT_PAD ) +#define OUT_D2_PAD ( SIZE_EXTR_D2 + TOP_PAD + BOTTOM_PAD ) +#define OUT_D1_PAD_STRIDE ( (OUT_D1_PAD * STRIDE_OUT_D1) - (STRIDE_OUT_D1 - 1) ) +#define OUT_D2_PAD_STRIDE ( (OUT_D2_PAD * STRIDE_OUT_D2) - (STRIDE_OUT_D2 - 1) ) +#define OUT_DIM_1D ( OUT_D1_PAD_STRIDE ) +#define OUT_DIM_2D ( OUT_D1_PAD_STRIDE * OUT_D2_PAD_STRIDE ) + +/* + * Window size for the DMA. Since it has to be > 71 for the ISR to have the time to react, + * the OUT_DIM_2D has to be big enough. DMA_WINDOW_SIZE is by default set to 80 for good measure. + */ + +#define DMA_WINDOW_SIZE 80 + +#if defined(TEST_ID_0) && ((OUT_DIM_2D < DMA_WINDOW_SIZE) || (DMA_WINDOW_SIZE < 72)) + #error "In order to correctly execute TEST_ID_0, the matrix output dimension has to be bigger than 72 and bigger than the window dimension.\nCheck these parameters and recompile.\n" +#endif + +/* Defines for DMA channels */ +#define DMA_CH0_IDX 0 +#define DMA_CH1_IDX 1 +#define DMA_CH2_IDX 2 +#define DMA_CH3_IDX 3 + +/* Assigning a pointer to a define writes the pointed array in the flash */ +#define TEST_DATA_FLASH_PTR test_data_flash + +/* Mask for direct register operations example */ +#define DMA_CSR_REG_MIE_MASK (( 1 << 19 ) | (1 << 11 )) + +/* Transposition example def */ +#define TRANSPOSITION_EN 1 + +/* Pointer increments computation */ +#define SRC_INC_D1 STRIDE_IN_D1 +#define DST_INC_D1 STRIDE_OUT_D1 +#define SRC_INC_D2 (STRIDE_IN_D2 * SIZE_IN_D1 - (SIZE_EXTR_D1 - 1 + (STRIDE_IN_D1 - 1) * (SIZE_EXTR_D1 - 1))) +#define DST_INC_D2 ((STRIDE_OUT_D2 - 1) * OUT_DIM_1D + 1) +#define SRC_INC_TRSP_D1 SRC_INC_D1 +#define SRC_INC_TRSP_D2 (STRIDE_IN_D2 * SIZE_IN_D1) + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +/* FPGA SPI board selection */ +#if !TARGET_SIM + #define USE_SPI_FLASH +#endif + +/* QuestaSim macro to enable test 4, by default is disabled */ +//#define SIM_QUESTASIM + +/* Size of FLASH buffer */ +#define TEST_DATA_FLASH_SIZE 32 + +/* Memory allocation for examples */ +uint32_t copied_test_data_flash[TEST_DATA_FLASH_SIZE]; +dma_input_data_type copied_data_2D_DMA[DMA_CH_NUM][OUT_DIM_2D]; +dma_input_data_type copied_data_2D_CPU[DMA_CH_NUM][OUT_DIM_2D]; + +#if (TARGET_SIM == 0 || defined(TARGET_QUESTASIM)) +/* Data for TEST_ID_3 to be stored in the FLASH */ +uint32_t __attribute__((section(".xheep_data_flash_only"))) __attribute__ ((aligned (16))) test_data_flash[TEST_DATA_FLASH_SIZE] = { + 105 ,82 ,221 ,172 ,77 ,62, + 81 ,185 ,33 ,213 ,249 ,117, + 69 ,212 ,99 ,137 ,9 ,233, + 107 ,105 ,166 ,141 ,53 ,207, + 53 ,21 ,221 ,102 ,84 ,108, + 43 ,99 ,123 ,71 ,30 ,179 + }; + +/* Data for TEST_ID_3 to compare the copied data from the FLASH */ +uint32_t test_data_flash_golden[TEST_DATA_FLASH_SIZE] = { + 105 ,82 ,221 ,172 ,77 ,62, + 81 ,185 ,33 ,213 ,249 ,117, + 69 ,212 ,99 ,137 ,9 ,233, + 107 ,105 ,166 ,141 ,53 ,207, + 53 ,21 ,221 ,102 ,84 ,108, + 43 ,99 ,123 ,71 ,30 ,179 + }; +#endif + +/* DMA source, destination and transaction */ +dma_target_t tgt_src; +dma_target_t tgt_src_trsp; +dma_target_t tgt_dst[DMA_CH_NUM]; +dma_trans_t trans[DMA_CH_NUM]; + +dma_config_flags_t res_valid, res_load, res_launch; + +/* CPU computation variables */ +uint32_t dst_ptr = 0, src_ptr = 0; +uint32_t cycles_dma, cycles_cpu; +uint32_t size_dst_trans_d1; +uint32_t dst_stride_d1; +uint32_t dst_stride_d2; +uint32_t size_src_trans_d1; +uint32_t src_stride_d1; +uint32_t src_stride_d2; +uint32_t i_in; +uint32_t j_in; +uint32_t i_in_last; +uint32_t j_in_last; +uint16_t left_pad_cnt = 0; +uint16_t top_pad_cnt = 0; +uint8_t stride_1d_cnt = 0; +uint8_t stride_2d_cnt = 0; +uint8_t transaction_flag[DMA_CH_NUM]; +uint8_t window_flag[DMA_CH_NUM]; +char passed = 1; +char flag = 0; + +/* Strong transaction ISR implementation */ +void dma_intr_handler_trans_done(uint8_t channel) +{ + transaction_flag[channel] = 1; + return; +} + +/* Strong window ISR implementation */ +void dma_intr_handler_window_done(uint8_t channel) +{ + window_flag[channel] = 1; + return; +} + +int main() +{ + + #ifdef TEST_ID_0 + + /* + * Testing copy and padding of a NxM matrix using direct register operations. + * This strategy allows for maximum performance but doesn't perform any checks on the data integrity. + * The data is copied using N channels to N different memory locations. + */ + + #if EN_PERF + + /* Reset the counter to evaluate the performance of the DMA */ + CSR_CLEAR_BITS(CSR_REG_MCOUNTINHIBIT, 0x1); + CSR_WRITE(CSR_REG_MCYCLE, 0); + #endif + + /* The DMA channels are initialized (i.e. Any current transaction is cleaned.) */ + dma_init(NULL); + + plic_Init(); + plic_irq_set_priority( DMA_WINDOW_INTR, 1); + plic_irq_set_enabled( DMA_WINDOW_INTR, kPlicToggleEnabled); + + /* Enable global interrupts */ + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + + /* Enable fast interrupts */ + CSR_SET_BITS(CSR_REG_MIE, DMA_CSR_REG_MIE_MASK); + + + for (int i=0; iSRC_PTR = &test_data[0]; + dma_peri(i)->DST_PTR = copied_data_2D_DMA[i]; + + /* Dimensionality configuration */ + write_register( 0x1, + DMA_DIM_CONFIG_REG_OFFSET, + 0x1, + DMA_DIM_CONFIG_DMA_DIM_BIT, + dma_peri(i) ); + + /* Operation mode configuration */ + write_register( DMA_TRANS_MODE_SINGLE, + DMA_MODE_REG_OFFSET, + DMA_MODE_MODE_MASK, + DMA_MODE_MODE_OFFSET, + dma_peri(i) ); + + /* Data type configuration */ + write_register( DMA_DATA_TYPE, + DMA_DST_DATA_TYPE_REG_OFFSET, + DMA_DST_DATA_TYPE_DATA_TYPE_MASK, + DMA_DST_DATA_TYPE_DATA_TYPE_OFFSET, + dma_peri(i) ); + + write_register( DMA_DATA_TYPE, + DMA_SRC_DATA_TYPE_REG_OFFSET, + DMA_SRC_DATA_TYPE_DATA_TYPE_MASK, + DMA_SRC_DATA_TYPE_DATA_TYPE_OFFSET, + dma_peri(i) ); + + /* Set the source strides */ + write_register( SRC_INC_D1 * DMA_DATA_TYPE_2_SIZE(DMA_DATA_TYPE), + DMA_SRC_PTR_INC_D1_REG_OFFSET, + DMA_SRC_PTR_INC_D1_INC_MASK, + DMA_SRC_PTR_INC_D1_INC_OFFSET, + dma_peri(i) ); + + write_register( SRC_INC_D2 * DMA_DATA_TYPE_2_SIZE(DMA_DATA_TYPE), + DMA_SRC_PTR_INC_D2_REG_OFFSET, + DMA_SRC_PTR_INC_D2_INC_MASK, + DMA_SRC_PTR_INC_D2_INC_OFFSET, + dma_peri(i) ); + + write_register( DST_INC_D1 * DMA_DATA_TYPE_2_SIZE( DMA_DATA_TYPE), + DMA_DST_PTR_INC_D1_REG_OFFSET, + DMA_DST_PTR_INC_D1_INC_MASK, + DMA_DST_PTR_INC_D1_INC_OFFSET, + dma_peri(i) ); + + write_register( DST_INC_D2 * DMA_DATA_TYPE_2_SIZE( DMA_DATA_TYPE), + DMA_DST_PTR_INC_D2_REG_OFFSET, + DMA_DST_PTR_INC_D2_INC_MASK, + DMA_DST_PTR_INC_D2_INC_OFFSET, + dma_peri(i) ); + + /* Padding configuration */ + write_register( TOP_PAD, + DMA_PAD_TOP_REG_OFFSET, + DMA_PAD_TOP_PAD_MASK, + DMA_PAD_TOP_PAD_OFFSET, + dma_peri(i) ); + + write_register( RIGHT_PAD, + DMA_PAD_RIGHT_REG_OFFSET, + DMA_PAD_RIGHT_PAD_MASK, + DMA_PAD_RIGHT_PAD_OFFSET, + dma_peri(i) ); + + write_register( LEFT_PAD, + DMA_PAD_LEFT_REG_OFFSET, + DMA_PAD_LEFT_PAD_MASK, + DMA_PAD_LEFT_PAD_OFFSET, + dma_peri(i) ); + + write_register( BOTTOM_PAD, + DMA_PAD_BOTTOM_REG_OFFSET, + DMA_PAD_BOTTOM_PAD_MASK, + DMA_PAD_BOTTOM_PAD_OFFSET, + dma_peri(i) ); + + /* Set the window size */ + write_register( DMA_WINDOW_SIZE, + DMA_WINDOW_SIZE_REG_OFFSET, + DMA_WINDOW_SIZE_WINDOW_SIZE_MASK, + DMA_WINDOW_SIZE_WINDOW_SIZE_OFFSET, + dma_peri(i) ); + } + + for (int i=0; i= SIZE_EXTR_D2 + TOP_PAD || j_in < LEFT_PAD || j_in >= SIZE_EXTR_D1 + LEFT_PAD || + stride_1d_cnt != 0 || stride_2d_cnt != 0) + { + copied_data_2D_CPU[c][dst_ptr] = 0; + } + else + { + copied_data_2D_CPU[c][dst_ptr] = test_data[src_ptr]; + } + + if (j_in < LEFT_PAD && i_in >= TOP_PAD && stride_1d_cnt == 0 && stride_2d_cnt == 0) + { + left_pad_cnt++; + } + + if (stride_1d_cnt == STRIDE_OUT_D1 - 1) + { + stride_1d_cnt = 0; + j_in++; + } + else + { + stride_1d_cnt++; + } + + } + + if (i_in < TOP_PAD && stride_2d_cnt == 0) + { + top_pad_cnt++; + } + + if (stride_2d_cnt == STRIDE_OUT_D2 - 1) + { + stride_2d_cnt = 0; + i_in++; + } + else + { + stride_2d_cnt++; + } + + left_pad_cnt = 0; + } + } + + #endif + + #if EN_PERF + + /* Read the cycles count after the CPU run */ + CSR_READ(CSR_REG_MCYCLE, &cycles_cpu); + + PRINTF("DMA cycles: %d\n\r", cycles_dma); + PRINTF("CPU cycles: %d \n\r", cycles_cpu); + #endif + + #if EN_VERIF + + /* Verify that the DMA and the CPU outputs are the same */ + for (int c=0; c= SIZE_EXTR_D2 + TOP_PAD || j_in < LEFT_PAD || j_in >= SIZE_EXTR_D1 + LEFT_PAD || + stride_1d_cnt != 0 || stride_2d_cnt != 0) + { + copied_data_2D_CPU[c][dst_ptr] = 0; + } + else + { + copied_data_2D_CPU[c][dst_ptr] = test_data[src_ptr]; + } + + if (j_in < LEFT_PAD && i_in >= TOP_PAD && stride_1d_cnt == 0 && stride_2d_cnt == 0) + { + left_pad_cnt++; + } + + if (stride_1d_cnt == STRIDE_OUT_D1 - 1) + { + stride_1d_cnt = 0; + j_in++; + } + else + { + stride_1d_cnt++; + } + + } + + if (i_in < TOP_PAD && stride_2d_cnt == 0) + { + top_pad_cnt++; + } + + if (stride_2d_cnt == STRIDE_OUT_D2 - 1) + { + stride_2d_cnt = 0; + i_in++; + } + else + { + stride_2d_cnt++; + } + + left_pad_cnt = 0; + } + } + #endif + + #if EN_PERF + + /* Read the cycles count after the CPU run */ + CSR_READ(CSR_REG_MCYCLE, &cycles_cpu); + PRINTF("DMA cycles: %d\n\r", cycles_dma); + PRINTF("CPU cycles: %d \n\r", cycles_cpu); + + #endif + + #if EN_VERIF + + /* Verify that the DMA and the CPU outputs are the same */ + for (int c=0; c= SIZE_EXTR_D2 + TOP_PAD || j_in < LEFT_PAD || j_in >= SIZE_EXTR_D1 + LEFT_PAD || + stride_1d_cnt != 0 || stride_2d_cnt != 0) + { + copied_data_2D_CPU[c][dst_ptr] = 0; + } + else + { + copied_data_2D_CPU[c][dst_ptr] = test_data[src_ptr]; + } + + if (j_in < LEFT_PAD && i_in >= TOP_PAD && stride_1d_cnt == 0 && stride_2d_cnt == 0) + { + left_pad_cnt++; + } + + if (stride_1d_cnt == STRIDE_OUT_D1 - 1) + { + stride_1d_cnt = 0; + j_in++; + } + else + { + stride_1d_cnt++; + } + + } + + if (i_in < TOP_PAD && stride_2d_cnt == 0) + { + top_pad_cnt++; + } + + if (stride_2d_cnt == STRIDE_OUT_D2 - 1) + { + stride_2d_cnt = 0; + i_in++; + } + else + { + stride_2d_cnt++; + } + + left_pad_cnt = 0; + } + flag = 1; + } + else + { + for (int i=0; i < OUT_D2_PAD_STRIDE; i++) + { + stride_1d_cnt = 0; + j_in = 0; + + for (int j=0; j < OUT_D1_PAD_STRIDE; j++) + { + dst_ptr = i * OUT_D1_PAD_STRIDE + j; + src_ptr = (j_in - left_pad_cnt) * STRIDE_IN_D2 * SIZE_IN_D1 + (i_in - top_pad_cnt ) * STRIDE_IN_D1; + if (i_in < TOP_PAD || i_in >= SIZE_EXTR_D2 + TOP_PAD || j_in < LEFT_PAD || j_in >= SIZE_EXTR_D1 + LEFT_PAD || + stride_1d_cnt != 0 || stride_2d_cnt != 0) + { + copied_data_2D_CPU[c][dst_ptr] = 0; + } + else + { + copied_data_2D_CPU[c][dst_ptr] = test_data[src_ptr]; + } + + if (j_in < LEFT_PAD && i_in >= TOP_PAD && stride_1d_cnt == 0 && stride_2d_cnt == 0) + { + left_pad_cnt++; + } + + if (stride_1d_cnt == STRIDE_OUT_D1 - 1) + { + stride_1d_cnt = 0; + j_in++; + } + else + { + stride_1d_cnt++; + } + + } + + if (i_in < TOP_PAD && stride_2d_cnt == 0) + { + top_pad_cnt++; + } + + if (stride_2d_cnt == STRIDE_OUT_D2 - 1) + { + stride_2d_cnt = 0; + i_in++; + } + else + { + stride_2d_cnt++; + } + + left_pad_cnt = 0; + } + flag = 0; + } + } + + #endif + + #if EN_PERF + + /* Read the cycles count after the CPU run */ + CSR_READ(CSR_REG_MCYCLE, &cycles_cpu); + PRINTF("DMA cycles: %d\n\r", cycles_dma); + PRINTF("CPU cycles: %d \n\r", cycles_cpu); + + #endif + + #if EN_VERIF + + /* Verify that the DMA and the CPU outputs are the same */ + for (int c=0; c 1 + + /* Testing SPI2RAM & RAM2RAM operations on 2 channels */ + + /* Reset for fourth test */ + passed = 1; + i_in = 0; + j_in = 0; + left_pad_cnt = 0; + top_pad_cnt = 0; + stride_1d_cnt = 0; + stride_2d_cnt = 0; + for (int i = 0; i < OUT_DIM_2D; i++) { + copied_data_2D_DMA[1][i] = 0; + copied_data_2D_CPU[1][i] = 0; + } + + #if EN_PERF + + /* Reset the counter to evaluate the performance of the DMA */ + CSR_CLEAR_BITS(CSR_REG_MCOUNTINHIBIT, 0x1); + CSR_WRITE(CSR_REG_MCYCLE, 0); + #endif + + dma_init(NULL); + + tgt_src.ptr = (uint8_t *) test_data; + tgt_src.inc_d1_du = SRC_INC_D1; + tgt_src.inc_d2_du = SRC_INC_D2; + tgt_src.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE; + + tgt_dst[1].ptr = (uint8_t *) copied_data_2D_DMA[1]; + tgt_dst[1].inc_d1_du = DST_INC_D1; + tgt_dst[1].inc_d2_du = DST_INC_D2; + tgt_dst[1].trig = DMA_TRIG_MEMORY; + + trans[1].src = &tgt_src; + trans[1].dst = &tgt_dst[1]; + trans[1].size_d1_du = SIZE_EXTR_D1; + trans[1].size_d2_du = SIZE_EXTR_D2; + trans[1].mode = DMA_TRANS_MODE_SINGLE; + trans[1].dim = DMA_DIM_CONF_2D; + trans[1].pad_top_du = TOP_PAD; + trans[1].pad_bottom_du = BOTTOM_PAD; + trans[1].pad_left_du = LEFT_PAD; + trans[1].pad_right_du = RIGHT_PAD; + trans[1].win_du = 0; + trans[1].end = DMA_TRANS_END_INTR; + trans[1].channel = DMA_CH1_IDX; + + /* Initialize the SPI */ + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + + if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) { + PRINTF("This application cannot work with the memory mapped SPI FLASH" + "module - do not use the FLASH_EXEC linker script for this application\n"); + return EXIT_SUCCESS; + } + + /* Pick the correct spi device based on simulation type */ + spi_host_t *spi; + #ifndef USE_SPI_FLASH + spi = spi_host1; + #else + spi = spi_flash; + #endif + + /* Init SPI host and SPI<->Flash bridge parameters */ + if (w25q128jw_init(spi) != FLASH_OK) + { + PRINTF("Error initializing the flash SPI\n\r"); + return EXIT_FAILURE; + } + + /* Start the reading process from the SPI, avoiding both sanity checks and waiting for the DMA to finish */ + w25q_error_codes_t status = w25q128jw_read_standard_dma(TEST_DATA_FLASH_PTR, copied_test_data_flash, TEST_DATA_FLASH_SIZE*4, 1, 1); + if (status != FLASH_OK) + { + PRINTF("Error reading from flash\n\r"); + return EXIT_FAILURE; + } + + #if EN_PERF + + dma_validate_transaction(&trans[1], DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + dma_load_transaction(&trans[1]); + dma_launch(&trans[1]); + + #else + + res_valid = dma_validate_transaction(&trans_ch1, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + PRINTF("tran: %u \t%s\n\r", res_valid, res_valid == DMA_CONFIG_OK ? "Ok!" : "Error!"); + res_load = dma_load_transaction(&trans_ch1); + PRINTF("load: %u \t%s\n\r", res_load, res_load == DMA_CONFIG_OK ? "Ok!" : "Error!"); + res_launch = dma_launch(&trans_ch1); + PRINTF("laun: %u \t%s\n\r", res_launch, res_launch == DMA_CONFIG_OK ? "Ok!" : "Error!"); + #endif + + /* Wait for CH0 to end, since the SPI will be slower than the DMA */ + while(!dma_is_ready(0)) { + #if !EN_PERF + /* Disable_interrupts */ + /* This does not prevent waking up the core as this is controlled by the MIP register */ + + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if ( dma_is_ready(0) == 0 ) { + wait_for_interrupt(); + /* From here the core wakes up even if we did not jump to the ISR */ + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + #endif + } + + #if EN_PERF + + /* Read the cycles count after the DMA run */ + CSR_READ(CSR_REG_MCYCLE, &cycles_dma); + + /* Reset the performance counter to evaluate the CPU performance */ + CSR_SET_BITS(CSR_REG_MCOUNTINHIBIT, 0x1); + CSR_WRITE(CSR_REG_MCYCLE, 0); + CSR_CLEAR_BITS(CSR_REG_MCOUNTINHIBIT, 0x1); + #endif + + #if EN_VERIF + + /* Run the same computation on the CPU */ + for (int i=0; i < OUT_D2_PAD_STRIDE; i++) + { + stride_1d_cnt = 0; + j_in = 0; + + for (int j=0; j < OUT_D1_PAD_STRIDE; j++) + { + dst_ptr = i * OUT_D1_PAD_STRIDE + j; + src_ptr = (i_in - top_pad_cnt ) * STRIDE_IN_D2 * SIZE_IN_D1 + (j_in - left_pad_cnt) * STRIDE_IN_D1; + if (i_in < TOP_PAD || i_in >= SIZE_EXTR_D2 + TOP_PAD || j_in < LEFT_PAD || j_in >= SIZE_EXTR_D1 + LEFT_PAD || + stride_1d_cnt != 0 || stride_2d_cnt != 0) + { + copied_data_2D_CPU[1][dst_ptr] = 0; + } + else + { + copied_data_2D_CPU[1][dst_ptr] = test_data[src_ptr]; + } + + if (j_in < LEFT_PAD && i_in >= TOP_PAD && stride_1d_cnt == 0 && stride_2d_cnt == 0) + { + left_pad_cnt++; + } + + if (stride_1d_cnt == STRIDE_OUT_D1 - 1) + { + stride_1d_cnt = 0; + j_in++; + } + else + { + stride_1d_cnt++; + } + + } + + if (i_in < TOP_PAD && stride_2d_cnt == 0) + { + top_pad_cnt++; + } + + if (stride_2d_cnt == STRIDE_OUT_D2 - 1) + { + stride_2d_cnt = 0; + i_in++; + } + else + { + stride_2d_cnt++; + } + + left_pad_cnt = 0; + } + #endif + + #if EN_PERF + + /* Read the cycles count after the CPU run */ + CSR_READ(CSR_REG_MCYCLE, &cycles_cpu); + PRINTF("DMA cycles: %d\n\r", cycles_dma); + PRINTF("CPU cycles: %d \n\r", cycles_cpu); + + #endif + + #if EN_VERIF + + /* Verify that the DMA and the CPU outputs are the same */ + for (int i = 0; i < OUT_D2_PAD_STRIDE; i++) { + for (int j = 0; j < OUT_D1_PAD_STRIDE; j++) { + if ((copied_data_2D_DMA[1][i * OUT_D1_PAD_STRIDE + j] != copied_data_2D_CPU[1][i * OUT_D1_PAD_STRIDE + j])) + { + passed = 0; + } + } + } + + /* Verify that the SPI copy was successful */ + for (int i=0; i < TEST_DATA_FLASH_SIZE; i++) + { + if (copied_test_data_flash[i] != test_data_flash_golden[i]) + { + passed = 0; + } + } + + if (passed) { + PRINTF("Success test 3\n\r"); + } + else + { + PRINTF("Fail test 3\n\r"); + return EXIT_FAILURE; + } + #endif + + #endif + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_multichannel/test_data.h b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_multichannel/test_data.h new file mode 100644 index 00000000..c582490e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_multichannel/test_data.h @@ -0,0 +1,34 @@ +#ifndef __TEST_DATA_H__ +#define __TEST_DATA_H__ + +#define SIZE_IN_D1 15 +#define SIZE_IN_D2 15 +#define DMA_DATA_TYPE DMA_DATA_TYPE_WORD + +/* + * Change the input datatype depending on the DMA_DATA_TYPE. + * The test data has been generated using byte as datatype, so it's possible to use both uint8_t, uint16_t and uint32_t. + * NOTE: To fully evaluate the performance gains of the DMA it's recommended to increase the number of memory banks and + * the size of the data to be copied up ot at least 50x50. + */ +typedef uint32_t dma_input_data_type; + +dma_input_data_type test_data[SIZE_IN_D1 * SIZE_IN_D2] = { + 236 ,19 ,35 ,109 ,59 ,58 ,216 ,210 ,72 ,169 ,123 ,74 ,132 ,27 ,208, + 43 ,93 ,216 ,145 ,94 ,235 ,80 ,25 ,146 ,127 ,115 ,9 ,45 ,61 ,60, + 78 ,218 ,28 ,230 ,140 ,236 ,152 ,242 ,98 ,173 ,20 ,206 ,176 ,157 ,219, + 225 ,182 ,118 ,22 ,153 ,196 ,7 ,9 ,87 ,99 ,173 ,11 ,103 ,173 ,49, + 122 ,185 ,128 ,93 ,243 ,29 ,172 ,32 ,207 ,64 ,184 ,40 ,165 ,87 ,157, + 182 ,196 ,160 ,93 ,182 ,91 ,20 ,82 ,156 ,45 ,109 ,132 ,168 ,234 ,85, + 121 ,39 ,188 ,109 ,190 ,127 ,192 ,124 ,149 ,90 ,247 ,68 ,26 ,82 ,57, + 189 ,249 ,91 ,193 ,23 ,210 ,167 ,79 ,175 ,31 ,212 ,131 ,102 ,43 ,4, + 192 ,184 ,234 ,9 ,81 ,4 ,221 ,12 ,181 ,76 ,64 ,131 ,59 ,26 ,83, + 86 ,140 ,176 ,18 ,120 ,115 ,153 ,50 ,41 ,83 ,110 ,157 ,173 ,145 ,81, + 9 ,120 ,250 ,3 ,27 ,119 ,64 ,195 ,48 ,245 ,160 ,78 ,177 ,246 ,59, + 156 ,114 ,97 ,7 ,11 ,224 ,75 ,154 ,223 ,221 ,90 ,77 ,254 ,181 ,198, + 193 ,254 ,161 ,177 ,201 ,3 ,182 ,18 ,36 ,23 ,67 ,46 ,116 ,229 ,166, + 90 ,158 ,248 ,194 ,224 ,218 ,245 ,34 ,60 ,126 ,68 ,248 ,143 ,232 ,226, + 58 ,202 ,172 ,209 ,229 ,89 ,246 ,184 ,215 ,7 ,163 ,204 ,43 ,116 ,33}; +; + +#endif \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_sdk/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_sdk/main.c new file mode 100644 index 00000000..22b3ce65 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_dma_sdk/main.c @@ -0,0 +1,112 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// File: example_dma_sdk.c +// Author: Juan Sapriza +// Date: 13/06/2024 +// Description: Example application to test the DMA SDK. Will copy +// a constant value in a buffer and then copy the content +// of the buffer into another. Will check that both transactions +// are performed correctly. + +#include +#include // For compatibility with OH Group compiler +#include +#include "dma_sdk.h" +#include "dma.h" // For compatibility with OH Group compiler +#include "core_v_mini_mcu.h" +#include "x-heep.h" +#include "csr.h" // For compatibility with OH Group compiler + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM +#define PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM +#define PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#define SOURCE_BUFFER_SIZE_32b 5 +#define SOURCE_BUFFER_SIZE_16b 5 +#define SOURCE_BUFFER_SIZE_8b 5 +#define CONST_VALUE_32B 123 +#define CONST_NEG_VALUE_32B -123 +#define CONST_VALUE_16B 123 +#define CONST_NEG_VALUE_16B -123 +#define CONST_VALUE_8B 123 +#define CONST_NEG_VALUE_8B -123 + +static uint32_t source_32b[SOURCE_BUFFER_SIZE_32b]; +static uint32_t destin_32b[SOURCE_BUFFER_SIZE_32b]; + +static uint16_t destin_16b[SOURCE_BUFFER_SIZE_16b]; +static uint16_t source_16b[SOURCE_BUFFER_SIZE_16b]; + +static uint8_t destin_8b[SOURCE_BUFFER_SIZE_8b]; +static uint8_t source_8b[SOURCE_BUFFER_SIZE_8b]; + +static int32_t neg_source_32b[SOURCE_BUFFER_SIZE_32b]; +static int32_t neg_destin_32b[SOURCE_BUFFER_SIZE_32b]; + +static int16_t neg_destin_16b[SOURCE_BUFFER_SIZE_16b]; +static int16_t neg_source_16b[SOURCE_BUFFER_SIZE_16b]; + +static int8_t neg_destin_8b[SOURCE_BUFFER_SIZE_8b]; +static int8_t neg_source_8b[SOURCE_BUFFER_SIZE_8b]; + +static uint32_t value_32b = CONST_VALUE_32B; +static uint16_t value_16b = CONST_VALUE_16B; +static uint8_t value_8b = CONST_VALUE_8B; + +static int32_t neg_value_32b = CONST_NEG_VALUE_32B; +static int16_t neg_value_16b = CONST_NEG_VALUE_16B; +static int8_t neg_value_8b = CONST_NEG_VALUE_8B; + +uint32_t i; +uint32_t errors = 0; + +int main() +{ + dma_sdk_init(); + + dma_fill((uint32_t)source_32b, (uint32_t)&value_32b, SOURCE_BUFFER_SIZE_32b, 0, DMA_DATA_TYPE_WORD, DMA_DATA_TYPE_WORD, 0); + dma_copy((uint32_t)destin_32b, (uint32_t)source_32b, SOURCE_BUFFER_SIZE_32b, 0, DMA_DATA_TYPE_WORD, DMA_DATA_TYPE_WORD, 0); + + for (i = 0; i < SOURCE_BUFFER_SIZE_32b; i++) + { + errors += destin_32b[i] != CONST_VALUE_32B; + } + + dma_fill((uint32_t)source_16b, (uint32_t)&value_16b, SOURCE_BUFFER_SIZE_16b, 0, DMA_DATA_TYPE_HALF_WORD, DMA_DATA_TYPE_HALF_WORD, 0); + dma_copy((uint32_t)destin_16b, (uint32_t)source_16b, SOURCE_BUFFER_SIZE_16b, 0, DMA_DATA_TYPE_HALF_WORD, DMA_DATA_TYPE_HALF_WORD, 0); + + for (i = 0; i < SOURCE_BUFFER_SIZE_16b; i++) + { + errors += destin_16b[i] != CONST_VALUE_16B; + } + + dma_fill((uint32_t)source_8b, (uint32_t)&value_8b, SOURCE_BUFFER_SIZE_8b, 0, DMA_DATA_TYPE_BYTE, DMA_DATA_TYPE_BYTE, 0); + dma_copy((uint32_t)destin_8b, (uint32_t)source_8b, SOURCE_BUFFER_SIZE_8b, 0, DMA_DATA_TYPE_BYTE, DMA_DATA_TYPE_BYTE, 0); + + for (i = 0; i < SOURCE_BUFFER_SIZE_8b; i++) + { + errors += destin_8b[i] != CONST_VALUE_8B; + } + + dma_fill((uint32_t)neg_source_16b, (uint32_t)&neg_value_8b, SOURCE_BUFFER_SIZE_32b, 0, DMA_DATA_TYPE_BYTE, DMA_DATA_TYPE_HALF_WORD, 1); + dma_copy((uint32_t)neg_destin_32b, (uint32_t)neg_source_16b, SOURCE_BUFFER_SIZE_32b, 0, DMA_DATA_TYPE_HALF_WORD, DMA_DATA_TYPE_WORD, 1); + + for (i = 0; i < SOURCE_BUFFER_SIZE_32b; i++) + { + errors += destin_32b[i] != CONST_VALUE_32B; + } + + PRINTF("Errors:%d\n\r", errors); + + return errors ? EXIT_FAILURE : EXIT_SUCCESS; +} \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_ext_memory/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_ext_memory/main.c new file mode 100644 index 00000000..8af03ad4 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_ext_memory/main.c @@ -0,0 +1,128 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include "core_v_mini_mcu.h" +#include "x-heep.h" + +#define BUFF_LEN 100 + +uint32_t buffer_rnd_index[BUFF_LEN]; + +#ifdef TARGET_SYSTEMC +//make app PROJECT=example_ext_memory TARGET=systemc +#define CACHE_FLUSH 1 +#define CACHE_BYPASS 2 +#define CACHE_SIZE 4*1024 +#endif + +#define MEMORY_SIZE 32*1024 +#define MEMORY_ADDR_MASK 0x7FFF +#define MEMORY_MAX_WORD_INDEX (MEMORY_SIZE/4) + +int is_in_array(uint32_t number, uint32_t* array, int N ) { + + for (int i=0;i str: + # Ensure the matrix is int16 (signed 16-bit integer) + if matrix.dtype != np.int16: + raise ValueError("Input matrix must be of dtype int16") + + num_bits = matrix.dtype.itemsize * 8 + array_ctype = "int16_t" + + # Convert each element to its 2's complement hexadecimal representation + rows = [] + for row in matrix: + row = np.atleast_1d(row) # Ensure row is array-like for iteration + # Format each element as a 16-bit signed integer in hex format + hex_values = [f"{element if element >= 0 else (1 << num_bits) + element:#06x}" for element in row] + rows.append(hex_values) + + # Format the matrix into a C-style array + matrix_contents = f"{array_ctype} {name}[{matrix.size}] = {{\n" + if len(rows) > 1: + matrix_contents += ',\n'.join([f" {', '.join(row)}" for row in rows]) + else: + matrix_contents += f" {', '.join(rows[0])}" + matrix_contents += '\n};\n\n' + + return matrix_contents + + +def generate_fft_twiddle_factors_radix2(N): + # Number of twiddle factors is N + num_twiddle_factors = N + + # Generate the angles for the twiddle factors + angles = np.linspace(0, -2 * np.pi, num_twiddle_factors, endpoint=False) + + # Compute the real and imaginary parts + real_parts = np.cos(angles) + imaginary_parts = np.sin(angles) + + # Concatenate real and imaginary parts + twiddle_factors = np.empty(2 * num_twiddle_factors) + twiddle_factors[0::2] = real_parts + twiddle_factors[1::2] = imaginary_parts + + return twiddle_factors + +import numpy as np + +def generate_fft_twiddle_factors_radix4(N): + # Ensure N is divisible by 4 for Radix-4 FFT + if N % 4 != 0: + raise ValueError("N must be a multiple of 4 for Radix-4 FFT") + + num_twiddle_groups = N // 4 + angles_k1 = np.linspace(0, -2 * np.pi / N, num_twiddle_groups, endpoint=False) + angles_k2 = 2 * angles_k1 # Corresponds to W_N^{2k} + angles_k3 = 3 * angles_k1 # Corresponds to W_N^{3k} + real_parts_k1 = np.cos(angles_k1) + imag_parts_k1 = np.sin(angles_k1) + real_parts_k2 = np.cos(angles_k2) + imag_parts_k2 = np.sin(angles_k2) + real_parts_k3 = np.cos(angles_k3) + imag_parts_k3 = np.sin(angles_k3) + twiddle_factors = np.empty(6 * num_twiddle_groups) + twiddle_factors[0::6] = real_parts_k1 + twiddle_factors[1::6] = imag_parts_k1 + twiddle_factors[2::6] = real_parts_k2 + twiddle_factors[3::6] = imag_parts_k2 + twiddle_factors[4::6] = real_parts_k3 + twiddle_factors[5::6] = imag_parts_k3 + + return twiddle_factors + + +def write_arr(f, name, arr, ctype, size): + f.write("const " + ctype + " " + name + "[2*FFT_LEN] = {\n") + + for row in arr: + for elem in row[:-1]: + f.write('%d,' % (elem)) + f.write('%d,\n' % (row[-1])) + + f.write('};\n\n') + return + +def generate_random_matrix(num_channels, length, decimal_bits): + """ + Generate a random matrix with num_channels rows and length columns. + """ + + real_part = np.random.uniform(-0.01, 0.01, (num_channels, length)) #* (2**(-decimal_bits)) + imag_part = np.random.uniform(-0.01, 0.01, (num_channels, length)) #* (2**(-decimal_bits)) + + matrix = real_part + 1j * imag_part + + return matrix + +def perform_fft(matrix): + """ + Perform FFT on each row of the matrix and return the result matrix. + """ + return np.fft.fft(matrix, axis=1) + +def convert_to_fixed_point(matrix, decimal_places=8): + """ + Convert the matrix to fixed-point format with a specified number of decimal bits. + Each element in the output matrix is of type 'int16'. + """ + # Scaling factor for conversion + scaling_factor = 1 << decimal_places # 2^decimal_bits (256 for Q1.8 format) + + # Convert to fixed-point representation + real_part = np.real(matrix) * scaling_factor + imag_part = np.imag(matrix) * scaling_factor + + # Clip values to ensure they fit within the range of int16 + real_part = np.clip(real_part, -32768, 32767) + imag_part = np.clip(imag_part, -32768, 32767) + + # Convert to int16 + real_part = real_part.astype(np.int16) + imag_part = imag_part.astype(np.int16) + + # Combine real and imaginary parts into a single matrix + fixed_point_matrix = np.empty((matrix.shape[0], matrix.shape[1] * 2), dtype=np.int16) + fixed_point_matrix[:, 0::2] = real_part + fixed_point_matrix[:, 1::2] = imag_part + + return fixed_point_matrix + +def convert_to_fixed_point_twiddles(array, decimal_bits=8): + # The input 'array' is a 1D array with interleaved real and imaginary parts + fixed_point_array = np.empty_like(array, dtype=np.int16) + + # Scale and convert to fixed-point for real and imaginary parts + scale_factor = 1 << decimal_bits + fixed_point_array = np.round(array * scale_factor).astype(np.int16) + + return fixed_point_array + +################################################################################ +f = open('data.h', 'w') +f.write('// This file is automatically generated\n// Type " python datagen.py " in the terminal to generate the data.h file. Configuration parameters can be changed in the datagen.py file.\n') +f.write('\n#ifndef DATA_H_\n') +f.write('#define DATA_H_\n\n') + +np.random.seed(seed) + +# Generate random input +input = generate_random_matrix(1, SIZE, decimal_bits) + +# Perform FFT +fft_output = perform_fft(input) + +# Comput twiddles +twiddles_radix2 = generate_fft_twiddle_factors_radix2(SIZE) +twiddles_radix4 = generate_fft_twiddle_factors_radix4(SIZE) + +# Convert FFT result to fixed-point format +R = convert_to_fixed_point(fft_output, decimal_bits) +A = convert_to_fixed_point(input, decimal_bits) +W_radix2 = convert_to_fixed_point_twiddles(twiddles_radix2, decimal_bits) +W_radix4 = convert_to_fixed_point_twiddles(twiddles_radix4, decimal_bits) + +print("Input:") +print(input) +print("A (fixed point) :") +print(A*2**-decimal_bits) +print("FFT output:") +print(fft_output) +print("R (fixed point):") +print(R*2**-decimal_bits) +print("Twiddles Radix-2 (fixed point):") +print([hex(x) for x in W_radix2.flatten()]) # Print in hexadecimal format +print("Twiddles Radix-4 (fixed point):") +print([hex(x) for x in W_radix4.flatten()]) # Print in hexadecimal format + +f.write('#define FFT_LEN %d\n' % SIZE) +f.write('#define DECIMAL_BITS %d\n\n' % decimal_bits) + +f.write(format_matrix( A, 'A')) +f.write(format_matrix( R, 'R')) +f.write(format_matrix( W_radix2, 'W_radix2')) +f.write(format_matrix( W_radix4, 'W_radix4')) + +f.write('#endif') \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_fft/fft.h b/hw/vendor/esl_epfl_x_heep/sw/applications/example_fft/fft.h new file mode 100644 index 00000000..6d079bda --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_fft/fft.h @@ -0,0 +1,331 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// File: fft.h +// Author: Francesco Poluzzi +// Date: 04/09/2024 +// Description: FFT-related functions for X-Heep + +#ifndef FFT_H +#define FFT_H + +#include +#include +#include +#include "data.h" + +#define PI 3.14159265358979323846 + +uint8_t log_floor(uint16_t N, uint8_t base) { + if (N == 0) { + return 0; // Log of 0 is undefined, return 0 for safety + } + uint8_t log_val = 0; + + if (base == 2) { + while (N >>= 1) { // Right shift by 1 bit (equivalent to dividing by 2) + log_val++; + } + } else if (base == 4) { + while (N >= 4) { // Right shift by 2 bits (equivalent to dividing by 4) + N >>= 2; + log_val++; + } + } + return log_val; +} + +bool is_power_of(uint16_t N, uint8_t base) { + if (N == 0) { + return false; + } + if (base == 2) { + return (N & (N - 1)) == 0; + } else if (base == 4) { + return (N & (N - 1)) == 0 && (N & 0x5555) != 0; + } + return false; +} + +// Function to perform bit reversal based on radix (base) +uint16_t bit_reversal(uint16_t n, uint8_t num_bits, uint8_t base) { + uint16_t result = 0; + + // Calculate the number of bits to shift based on the base + uint8_t shiftamt = (base == 2) ? 1 : 2; // Shift by 1 for Radix-2, by 2 for Radix-4 + uint16_t mask = base - 1; // Mask is 1 for Radix-2, 3 for Radix-4 + + // Perform the bit reversal by repeatedly shifting and applying the mask + for (uint8_t i = 0; i < num_bits; i++) { + result <<= shiftamt; // Shift result to the left by `shiftamt` bits + result |= n & mask; // Add the masked bits from `n` to `result` + n >>= shiftamt; // Shift `n` to the right by `shiftamt` bits + } + + return result; +} + +// Function to generate bit-reversed sequence +void get_bit_reversed_seq(uint16_t *seq, uint16_t N, uint8_t num_bits, uint8_t base) { + for (uint16_t i = 0; i < N; i++) { + seq[i] = bit_reversal(i, num_bits, base); + } +} + +void compute_twiddle_factors_radix2(int16_t* twiddle_factors, uint32_t N, uint8_t decimal_bits) { + for (uint16_t j = 0; j < N / 2; j++) { + float angle = -2.0 * PI * j / N; + twiddle_factors[2 * j] = (int16_t)(cos(angle) * (1 << decimal_bits)); // Real part in Q1.8 format + twiddle_factors[2 * j + 1] = (int16_t)(sin(angle) * (1 << decimal_bits)); // Imaginary part in Q1.8 format + } +} + +void compute_twiddle_factors_radix4(int16_t *twiddle_factors, uint16_t N, int16_t decimal_bits) { + // Twiddle factor for radix-4 FFT + // N is the FFT size, which must be a power of 4 + // twiddle_factors is the output array where real and imaginary parts are interleaved + uint16_t twiddle_count = N / 4; // Radix-4 FFT needs twiddles for N/4 size + + for (uint16_t k = 0; k < twiddle_count; k++) { + // Compute the real and imaginary parts of W_N^k = e^(-2*pi*i*k/N) + double angle = -2.0 * PI * k / N; + double real_part = cos(angle); + double imag_part = sin(angle); + + // Convert to fixed-point with the specified number of decimal bits + int16_t real_fixed = (int16_t)(real_part * (1 << decimal_bits)); + int16_t imag_fixed = (int16_t)(imag_part * (1 << decimal_bits)); + + // Store the values in the interleaved array + twiddle_factors[2 * k] = real_fixed; // Real part + twiddle_factors[2 * k + 1] = imag_fixed; // Imaginary part + } +} + +void __attribute__((noinline, aligned(4))) iterative_FFT_radix2(int16_t *x, int16_t *X, uint16_t N, int16_t *twiddle_factors, int16_t decimal_bits, + int16_t *w_real_fixed, int16_t *w_imag_fixed, int16_t *xrev, int16_t *bit_reversed_seq) { + + // Perform bit reversal on the input array + uint8_t num_bits = log_floor(N, 2); + + for (uint16_t i = 0; i < N; i++) { + // Access real and imaginary parts independently + xrev[2 * i] = x[2 * bit_reversed_seq[i]]; // Real part + xrev[2 * i + 1] = x[2 * bit_reversed_seq[i] + 1]; // Imaginary part + } + + // Stage 0 unrolled: simple additions and subtractions + for (uint16_t i = 0; i < N; i += 2) { + // Access real and imaginary parts for two points independently + int16_t a_real = xrev[2 * i]; + int16_t a_imag = xrev[2 * i + 1]; + int16_t b_real = xrev[2 * (i + 1)]; + int16_t b_imag = xrev[2 * (i + 1) + 1]; + + // No twiddle factor for the first stage (equivalent to multiplying by 1 + 0j) + xrev[2 * i] = a_real + b_real; + xrev[2 * i + 1] = a_imag + b_imag; + xrev[2 * (i + 1)] = a_real - b_real; + xrev[2 * (i + 1) + 1] = a_imag - b_imag; + } + + // FFT processing for remaining stages + uint16_t stage_count = num_bits; + uint16_t twiddle_step = N/2; + + for (uint16_t stage = 1, step = 4; stage < stage_count; stage++, step *= 2) { + uint16_t halfstep = step / 2; + twiddle_step /= 2; + + for (uint16_t j = 0; j < halfstep; j++) { + // Access precomputed twiddle factors from the interleaved array + w_real_fixed[j] = twiddle_factors[2 * (j * twiddle_step)]; + w_imag_fixed[j] = twiddle_factors[2 * (j * twiddle_step) + 1]; + } + + // Modify the outer loop to increment from 0 to N, increasing by step + for (uint16_t i = 0; i < N; i += step) { + // Calculate the starting index for this iteration + uint16_t idx = i; + for (uint16_t j = 0; j < halfstep; j++) { + // Butterfly operations - Access real and imag parts independently + int16_t a_real = xrev[2 * (idx + j)]; + int16_t a_imag = xrev[2 * (idx + j) + 1]; + int16_t b_real = xrev[2 * (idx + j + halfstep)]; + int16_t b_imag = xrev[2 * (idx + j + halfstep) + 1]; + + // Complex multiplication (b * w) using 32-bit intermediate values + int32_t temp_real = ((int32_t)b_real * w_real_fixed[j] - (int32_t)b_imag * w_imag_fixed[j]) >> decimal_bits; + int32_t temp_imag = ((int32_t)b_real * w_imag_fixed[j] + (int32_t)b_imag * w_real_fixed[j]) >> decimal_bits; + + // Store the results directly in the array, independently for real and imag parts + xrev[2 * (idx + j)] = a_real + temp_real; + xrev[2 * (idx + j) + 1] = a_imag + temp_imag; + xrev[2 * (idx + j + halfstep)] = a_real - temp_real; + xrev[2 * (idx + j + halfstep) + 1] = a_imag - temp_imag; + } + } + } + + // Copy the result to output array X + for (uint16_t i = 0; i < 2 * N; i++) { + X[i] = xrev[i]; + } +} + +// Radix-4 FFT +void __attribute__((noinline, aligned(4))) iterative_FFT_radix4(int16_t *x, int16_t *X, uint16_t N, int16_t *twiddle_factors, int16_t *w_real_fixed, int16_t * w_imag_fixed, int16_t *xrev, int8_t decimal_bits, int16_t * bit_reversed_seq) { + + uint16_t stage_count = log_floor(N, 4); // Radix-4 halves the number of stages + uint16_t twiddle_step = N; + + for (uint16_t i = 0; i < N; i++) { + xrev[2 * i] = x[2 * bit_reversed_seq[i]]; // Real part + xrev[2 * i + 1] = x[2 * bit_reversed_seq[i] + 1]; // Imaginary part + } + + // Unroll the first stage: radix-4 butterfly (4 points per butterfly) + uint16_t quarterstep = 1; + for (uint16_t i = 0; i < N; i += 4) { + uint16_t idx = i; + // Load the real and imaginary parts for the 4 input points + int16_t a_real = xrev[2 * idx]; + int16_t a_imag = xrev[2 * idx + 1]; + int16_t b_real = xrev[2 * (idx + quarterstep)]; + int16_t b_imag = xrev[2 * (idx + quarterstep) + 1]; + int16_t c_real = xrev[2 * (idx + 2 * quarterstep)]; + int16_t c_imag = xrev[2 * (idx + 2 * quarterstep) + 1]; + int16_t d_real = xrev[2 * (idx + 3 * quarterstep)]; + int16_t d_imag = xrev[2 * (idx + 3 * quarterstep) + 1]; + + // Radix-4 butterfly calculations (without twiddle factors) + int16_t t0_real = a_real + c_real; + int16_t t0_imag = a_imag + c_imag; + int16_t t1_real = b_real + d_real; + int16_t t1_imag = b_imag + d_imag; + + int16_t t2_real = a_real - c_real; + int16_t t2_imag = a_imag - c_imag; + int16_t t3_real = b_real - d_real; + int16_t t3_imag = b_imag - d_imag; + + // Output without twiddle factors + xrev[2 * idx] = t0_real + t1_real; // Result 1 real part + xrev[2 * idx + 1] = t0_imag + t1_imag; // Result 1 imag part + + xrev[2 * (idx + quarterstep)] = t2_real - t3_imag; // Result 2 real part + xrev[2 * (idx + quarterstep) + 1] = t2_imag + t3_real; // Result 2 imag part + + xrev[2 * (idx + 2 * quarterstep)] = t0_real - t1_real; // Result 3 real part + xrev[2 * (idx + 2 * quarterstep) + 1] = t0_imag - t1_imag; // Result 3 imag part + + xrev[2 * (idx + 3 * quarterstep)] = t2_real + t3_imag; // Result 4 real part + xrev[2 * (idx + 3 * quarterstep) + 1] = t2_imag - t3_real; // Result 4 imag part + } + + // Perform the remaining stages + for (uint16_t stage = 1, step = 16; stage < stage_count; stage++, step *= 4) { + uint16_t quarterstep = step / 4; + twiddle_step /= 4; + + // Precompute the twiddle factors for this stage + for (uint16_t j = 0; j < quarterstep; j++) { + w_real_fixed[j] = twiddle_factors[2 * (j * twiddle_step)]; + w_imag_fixed[j] = twiddle_factors[2 * (j * twiddle_step) + 1]; + } + + // Loop over groups of 4 points per butterfly + for (uint16_t i = 0; i < N; i += step) { + uint16_t idx = i; + + // Perform load, butterfly, and store operations in a single loop + for (uint16_t j = 0; j < quarterstep; j++) { + // Load the data for the 4 points + int16_t a_real = xrev[2 * (idx + j)]; + int16_t a_imag = xrev[2 * (idx + j) + 1]; + int16_t b_real = xrev[2 * (idx + j + quarterstep)]; + int16_t b_imag = xrev[2 * (idx + j + quarterstep) + 1]; + int16_t c_real = xrev[2 * (idx + j + 2 * quarterstep)]; + int16_t c_imag = xrev[2 * (idx + j + 2 * quarterstep) + 1]; + int16_t d_real = xrev[2 * (idx + j + 3 * quarterstep)]; + int16_t d_imag = xrev[2 * (idx + j + 3 * quarterstep) + 1]; + + // Apply twiddle factors to b + int16_t tw_b_real = ((int32_t)b_real * w_real_fixed[j] - (int32_t)b_imag * w_imag_fixed[j]) >> decimal_bits; + int16_t tw_b_imag = ((int32_t)b_real * w_imag_fixed[j] + (int32_t)b_imag * w_real_fixed[j]) >> decimal_bits; + + int16_t res1_real = a_real + tw_b_real; // a + Tw(b) + int16_t res1_imag = a_imag + tw_b_imag; + + int16_t res2_real = a_real - tw_b_real; // a - Tw(b) + int16_t res2_imag = a_imag - tw_b_imag; + + // Apply twiddle factors to c + int16_t tw_c_real = ((int32_t)c_real * w_real_fixed[2 * j] - (int32_t)c_imag * w_imag_fixed[2 * j]) >> decimal_bits; + int16_t tw_c_imag = ((int32_t)c_real * w_imag_fixed[2 * j] + (int32_t)c_imag * w_real_fixed[2 * j]) >> decimal_bits; + + int16_t res3_real = a_real + tw_c_real; // a + Tw(c) + int16_t res3_imag = a_imag + tw_c_imag; + + int16_t res4_real = a_real - tw_c_real; // a - Tw(c) + int16_t res4_imag = a_imag - tw_c_imag; + + // Apply twiddle factors to d + int16_t tw_d_real = ((int32_t)d_real * w_real_fixed[3 * j] - (int32_t)d_imag * w_imag_fixed[3 * j]) >> decimal_bits; + int16_t tw_d_imag = ((int32_t)d_real * w_imag_fixed[3 * j] + (int32_t)d_imag * w_real_fixed[3 * j]) >> decimal_bits; + + // Store the results + xrev[2 * (idx + j)] = res1_real; + xrev[2 * (idx + j) + 1] = res1_imag; + xrev[2 * (idx + j + quarterstep)] = res2_real; + xrev[2 * (idx + j + quarterstep) + 1] = res2_imag; + xrev[2 * (idx + j + 2 * quarterstep)] = res3_real; + xrev[2 * (idx + j + 2 * quarterstep) + 1] = res3_imag; + xrev[2 * (idx + j + 3 * quarterstep)] = res4_real; + xrev[2 * (idx + j + 3 * quarterstep) + 1] = res4_imag; + } + } + } + + // Copy the result to output array X + for (uint16_t i = 0; i < 2 * N; i++) { + X[i] = xrev[i]; + } +} + +#define FIXED_POINT_SCALE (1 << DECIMAL_BITS) + +// Helper function to print the FFT result +void print_complex_array(int16_t *array, uint16_t N) { + for (uint16_t i = 0; i < N; i++) { + // Convert fixed-point to decimal by dividing by FIXED_POINT_SCALE + int16_t real_part = array[2 * i]; + int16_t imag_part = array[2 * i + 1]; + + // Calculate integer and fractional parts + int16_t real_int = real_part / FIXED_POINT_SCALE; + int16_t imag_int = imag_part / FIXED_POINT_SCALE; + + // Fractional part needs to be scaled and displayed with leading zeros if necessary + int16_t real_frac = (real_part % FIXED_POINT_SCALE) * 1000 / FIXED_POINT_SCALE; + int16_t imag_frac = (imag_part % FIXED_POINT_SCALE) * 1000 / FIXED_POINT_SCALE; + + // Adjust the fractional part for negative values, and ensure fractional part is positive + if (real_part < 0 && real_frac > 0) { + real_frac = 1000 - real_frac; + } + if (imag_part < 0 && imag_frac > 0) { + imag_frac = 1000 - imag_frac; + } + + // Print the complex number in the correct format + // Use separate handling for real and imaginary signs + printf("X[%d] = %c%d.%03d %c %d.%03dj\n", + i, + (real_part < 0) ? '-' : '+', abs(real_int), abs(real_frac), // Real part + (imag_part < 0) ? '-' : '+', abs(imag_int), abs(imag_frac)); // Imaginary part + } +} + +#endif // FFT_ITERATIVE_RADIX_2_H \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_fft/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_fft/main.c new file mode 100644 index 00000000..2f5ebb2a --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_fft/main.c @@ -0,0 +1,112 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// File: main.c +// Author: Francesco Poluzzi +// Date: 04/09/2024 +// Description: FFT example for X-Heep +// Functions for the FFT computation are in fft.h +// Parameters as FFT_LEN and DECIMAL_BITS can be changed in data.h. To also automate the input and +// golden model generation with different parameters, the script datagen.py can be used. + +#include +#include +#include + +#include "data.h" +#include "x-heep.h" +#include "timer_sdk.h" +#include "fft.h" + +/* By default, PRINTs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 1 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +// Tolerance for the comparison of the results in fixed point (needs to be adjusted based on the number of decimal bits). +// The error is due to shifts and roundings in the fixed-point computation. +#define TOLERANCE 0x000000f + +int16_t __attribute__((aligned(4))) R_radix_2[2 * FFT_LEN] ; +int16_t __attribute__((aligned(4))) R_radix_4[2 * FFT_LEN] ; +int16_t __attribute__((aligned(4))) twiddle_factors_radix2[FFT_LEN]; +int16_t __attribute__((aligned(4))) twiddle_factors_radix4[FFT_LEN]; +int16_t __attribute__((aligned(4))) w_real_fixed[FFT_LEN / 2]; +int16_t __attribute__((aligned(4))) w_imag_fixed[FFT_LEN / 2]; +int32_t __attribute__((aligned(4))) xrev_32[ FFT_LEN]; +int16_t __attribute__((aligned(4))) xrev[2* FFT_LEN]; +int16_t __attribute__((aligned(4))) bit_reversed_seq_radix2[FFT_LEN]; +int16_t __attribute__((aligned(4))) bit_reversed_seq_radix4[FFT_LEN]; + +int main(void) +{ + uint32_t radix2_cycles, radix4_cycles; + + if(!is_power_of(FFT_LEN, 2)){ + PRINTF("FFT_LEN must be a power of 2, FFT radix 2 cannot be performed.\n"); + return EXIT_FAILURE; + } + + PRINTF("Starting radix 2 FFT\n"); + + // precompute twiddle factors for radix-2 FFT + compute_twiddle_factors_radix2(twiddle_factors_radix2, FFT_LEN, DECIMAL_BITS); + + // precompute bit reversed sequence + get_bit_reversed_seq(bit_reversed_seq_radix2, FFT_LEN, log_floor(FFT_LEN, 2), 2); + + timer_cycles_init(); + timer_start(); + + iterative_FFT_radix2(A, R_radix_2, FFT_LEN, twiddle_factors_radix2, DECIMAL_BITS, w_real_fixed, w_imag_fixed, xrev, bit_reversed_seq_radix2); + + radix2_cycles = timer_stop(); + + for(int i = 0; i < 2 * FFT_LEN; i++){ + if(abs(R_radix_2[i] - R[i] > TOLERANCE)){ + PRINTF("Error: R_gold[%d] = %x, R_radix_2[%d] = %x\n", i, R[i], i, R_radix_2[i]); + return 1; + } + } + + PRINTF("Radix-2 FFT took %d cycles\n", radix2_cycles); + + if(!is_power_of(FFT_LEN, 4)){ + PRINTF("FFT_LEN must be a power of 4, FFT radix 4 cannot be performed.\n"); + return EXIT_FAILURE; + } + + PRINTF("Starting radix 4 FFT\n"); + + // precompute twiddle factors for radix-4 FFT + compute_twiddle_factors_radix4(twiddle_factors_radix4, FFT_LEN, DECIMAL_BITS); + + // precompute bit reversed sequence + get_bit_reversed_seq(bit_reversed_seq_radix4, FFT_LEN, log_floor(FFT_LEN, 4), 4); + + timer_cycles_init(); + timer_start(); + + iterative_FFT_radix4(A, R_radix_4, FFT_LEN, twiddle_factors_radix4, w_real_fixed, w_imag_fixed, xrev, DECIMAL_BITS, bit_reversed_seq_radix4); + + radix4_cycles = timer_stop(); + + for(int i = 0; i < 2 * FFT_LEN; i++){ + if(abs(R_radix_2[i] - R[i] > TOLERANCE)){ + PRINTF("Error: R_gold[%d] = %x, R_radix_4[%d] = %x\n", i, R[i], i, R_radix_4[i]); + return 1; + } + } + + PRINTF("Radix-4 FFT took %d cycles\n", radix4_cycles); + + return EXIT_SUCCESS; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_freertos_blinky/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_freertos_blinky/main.c index fbb9941f..77c0c461 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_freertos_blinky/main.c +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_freertos_blinky/main.c @@ -116,7 +116,7 @@ /* The rate at which data is sent to the queue. The 200ms value is converted to ticks using the pdMS_TO_TICKS() macro. */ -#ifdef TARGET_PYNQ_Z2 +#ifdef TARGET_IS_FPGA #define mainQUEUE_SEND_FREQUENCY_MS pdMS_TO_TICKS( 200 ) #else #define mainQUEUE_SEND_FREQUENCY_MS pdMS_TO_TICKS( 3 ) @@ -148,7 +148,7 @@ or 0 to run the more comprehensive test and demo application. */ #endif /* #if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 */ -#ifdef TARGET_PYNQ_Z2 +#ifdef TARGET_IS_FPGA #define GPIO_LD5_R 15 #define GPIO_LD5_B 16 #define GPIO_LD5_G 17 diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_gpio_intr/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_gpio_intr/main.c index acad473a..bbdb9bc5 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_gpio_intr/main.c +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_gpio_intr/main.c @@ -29,7 +29,7 @@ #if TARGET_SIM && PRINTF_IN_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA +#elif PRINTF_IN_FPGA && !TARGET_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) #else #define PRINTF(...) @@ -41,7 +41,7 @@ #endif -#ifdef TARGET_PYNQ_Z2 +#ifdef TARGET_IS_FPGA #define GPIO_TB_OUT 8 #define GPIO_TB_IN 9 #define GPIO_INTR GPIO_INTR_9 @@ -150,6 +150,7 @@ int main(int argc, char *argv[]) // wait_for_interrupt(); CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); } + gpio_res = gpio_write(GPIO_TB_OUT, false); gpio_assign_irq_handler( GPIO_INTR, &handler_2 ); gpio_intr_flag = 0; diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_gpio_toggle/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_gpio_toggle/main.c index 9f920281..426de0f1 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_gpio_toggle/main.c +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_gpio_toggle/main.c @@ -16,7 +16,7 @@ #if TARGET_SIM && PRINTF_IN_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA +#elif PRINTF_IN_FPGA && !TARGET_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) #else #define PRINTF(...) diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_i2s/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_i2s/main.c index dc8a5c1d..cef21ff5 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_i2s/main.c +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_i2s/main.c @@ -34,7 +34,7 @@ #include "i2s_structs.h" -#ifdef TARGET_PYNQ_Z2 +#ifdef TARGET_IS_FPGA #define I2S_TEST_BATCH_SIZE 128 #define I2S_TEST_BATCHES 16 #define I2S_CLK_DIV 8 @@ -72,7 +72,7 @@ #if TARGET_SIM && PRINTF_IN_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA +#elif PRINTF_IN_FPGA && !TARGET_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) #else #define PRINTF(...) @@ -104,7 +104,7 @@ void handler_irq_i2s(uint32_t id) { } #ifdef USE_DMA -void dma_intr_handler_trans_done(void) +void dma_intr_handler_trans_done(uint8_t channel) { dma_intr_flag = 1; } @@ -128,18 +128,18 @@ void setup() // -- DMA CONFIGURATION -- tgt_src.ptr = I2S_RX_DATA_ADDRESS; - tgt_src.inc_du = 0; + tgt_src.inc_d1_du = 0; tgt_src.trig = DMA_TRIG_SLOT_I2S; tgt_src.type = DMA_DATA_TYPE_WORD; - tgt_src.size_du = AUDIO_DATA_NUM; tgt_dst.ptr = audio_data_0; - tgt_dst.inc_du = 1; + tgt_dst.inc_d1_du = 1; tgt_dst.trig = DMA_TRIG_MEMORY; tgt_dst.type = DMA_DATA_TYPE_WORD; trans.src = &tgt_src; trans.dst = &tgt_dst; + trans.size_d1_du = AUDIO_DATA_NUM; trans.end = DMA_TRANS_END_INTR; dma_config_flags_t res; @@ -173,7 +173,7 @@ void setup() int main(int argc, char *argv[]) { bool success = true; -#ifdef TARGET_PYNQ_Z2 +#ifdef TARGET_IS_FPGA for (uint32_t i = 0; i < 0x10000; i++) asm volatile("nop"); #endif PRINTF("I2S DEMO\r\n\r"); @@ -182,7 +182,7 @@ int main(int argc, char *argv[]) { //PRINTF("Setup done!\r\n\r"); -#ifdef TARGET_PYNQ_Z2 +#ifdef TARGET_IS_FPGA for (uint32_t i = 0; i < I2S_WAIT_CYCLES; i++) asm volatile("nop"); @@ -301,22 +301,47 @@ int main(int argc, char *argv[]) { PRINTF("B%x\r\n\r", batch); int32_t* data = audio_data_0; - for (int i = 0; i < AUDIO_DATA_NUM; i+=2) { - PRINTF("0x%x 0x%x\r\n\r", data[i], data[i+1]); + int32_t data_even = 0; + int32_t data_odd = 0; + for (int i = 0; i < AUDIO_DATA_NUM; i++) { + PRINTF("0x%x\r\n\r", data[i]); if (data[i] != 0) { mic_connected = true; // the microphone testbench is connected - if (data[i] != 0x8765431) { - PRINTF("ERROR left sample %d (B%d) = 0x%08x != 0x8765431\r\n\r", i, batch, data[i]); - success = false; + } else { + if(i == 0) { + //check what is the first data to expect, left or right + //the testbench alternatively sends these 2 data, catching which one is first for each BATCH + if ( (data[0] == 0x8765431) || (data[0] == 0xfedcba9) ) { + if (data[0] == 0x8765431) { + data_even = 0x8765431; + data_odd = 0xfedcba9; + } else { + data_odd = 0x8765431; + data_even = 0xfedcba9; + } + } else { + PRINTF("ERROR sample %d (B%d) = 0x%08x != 0x8765431 or 0xfedcba9\r\n\r", i, batch, data[0]); + success = false; + } + + } else { + //check whether even or odd + if (i & 0x1) { + //odd + if (data[i] != data_odd) { + PRINTF("ERROR left sample %d (B%d) = 0x%08x != 0x%08x\r\n\r", i, batch, data[i], data_odd); + success = false; + } + } + else { + //even + if (data[i] != data_even) { + PRINTF("ERROR left sample %d (B%d) = 0x%08x != 0x%08x\r\n\r", i, batch, data[i], data_even); + success = false; + } + } } - } - if (data[i+1] != 0) { - mic_connected = true; // the microphone testbench is connected - if (data[i+1] != 0xfedcba9) { - PRINTF("ERROR left sample data[%d] = 0x%08x != 0xfedcba9\r\n\r", i+1, batch, data[i+1]); - success = false; - } - } + } } } diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_iffifo/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_iffifo/main.c new file mode 100644 index 00000000..1afe2e6b --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_iffifo/main.c @@ -0,0 +1,206 @@ +/* + * Copyright EPFL contributors. + * Licensed under the Apache License, Version 2.0, see LICENSE for details. + * SPDX-License-Identifier: Apache-2.0 + * + * Author: Pierre Guillod + */ + +#include +#include + +#include "core_v_mini_mcu.h" + +#include "x-heep.h" +#include "iffifo_regs.h" + +#include "mmio.h" +#include "handler.h" +#include "csr.h" +#include "hart.h" + +#include "rv_plic.h" + +#include "dma.h" +#include "dma_regs.h" +#include "fast_intr_ctrl.h" + + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +unsigned int IFFIFO_START_ADDRESS = EXT_PERIPHERAL_START_ADDRESS + 0x2000; + +int32_t to_fifo [6] __attribute__ ((aligned (4))) = { 1, 2, 3, 4, 5, 6 }; +int32_t from_fifo[4] __attribute__ ((aligned (4))) = { 0, 0, 0, 0 }; + +int8_t dma_intr_flag = 0; +void dma_intr_handler_trans_done(uint8_t channel) +{ + dma_intr_flag = 1; +} + +void protected_wait_for_dma_interrupt(void) +{ + while(!dma_is_ready(0)) { + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if (!dma_is_ready(0)) { + wait_for_interrupt(); + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + } +} + +iffifo_intr_flag = 0; +static void handler_irq_iffifo( uint32_t int_id ) +{ + mmio_region_t iffifo_base_addr = mmio_region_from_addr((uintptr_t)IFFIFO_START_ADDRESS); + mmio_region_write32(iffifo_base_addr, IFFIFO_INTERRUPTS_REG_OFFSET, 0b0); + iffifo_intr_flag = 1; + PRINTF(" ** REACH intr. fired.\n"); +} + +static dma_target_t tgt_src; +static dma_target_t tgt_dst; +static dma_trans_t trans; + +int compare_print_fifo_array(void) { + int errors = 0; + PRINTF("from_fifo = {"); + for (int i = 0; i < 4; i+=1) { + PRINTF("%d",from_fifo[i]); + if(i != 4-1) {PRINTF(", ");}; + if (to_fifo[i]+1 != from_fifo[i]) {++errors;} + } + PRINTF("}\n"); + return errors; +} + +void print_status_register(void) +{ + mmio_region_t iffifo_base_addr = mmio_region_from_addr((uintptr_t)IFFIFO_START_ADDRESS); + int32_t status = mmio_region_read32(iffifo_base_addr, IFFIFO_STATUS_REG_OFFSET); + PRINTF("STATUS = "); + PRINTF(status & (1 << IFFIFO_STATUS_EMPTY_BIT) ? "E" : "-"); // FIFO empty + PRINTF(status & (1 << IFFIFO_STATUS_AVAILABLE_BIT) ? "A" : "-"); // Data available in FIFO + PRINTF(status & (1 << IFFIFO_STATUS_REACHED_BIT) ? "R" : "-"); // Watermark reached + PRINTF(status & (1 << IFFIFO_STATUS_FULL_BIT) ? "F" : "-"); // FIFO full + PRINTF("\n"); +} + +int is_iffifo_full(void) +{ + mmio_region_t iffifo_base_addr = mmio_region_from_addr((uintptr_t)IFFIFO_START_ADDRESS); + int32_t status = mmio_region_read32(iffifo_base_addr, IFFIFO_STATUS_REG_OFFSET); + return status & (1 << IFFIFO_STATUS_FULL_BIT); +} + +int main(int argc, char *argv[]) { + + mmio_region_t iffifo_base_addr = mmio_region_from_addr((uintptr_t)IFFIFO_START_ADDRESS); + + // Enable interrupt on processor side + // Enable global interrupt for machine-level interrupts + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + // Set mie.MEIE bit to one to enable machine-level external interrupts + const uint32_t mask = 1 << 11; + CSR_SET_BITS(CSR_REG_MIE, mask); + + if(plic_Init()) {return EXIT_FAILURE;}; + if(plic_irq_set_priority(EXT_INTR_1, 1)) {return EXIT_FAILURE;}; + if(plic_irq_set_enabled(EXT_INTR_1, kPlicToggleEnabled)) {return EXIT_FAILURE;}; + + plic_assign_external_irq_handler(EXT_INTR_1, &handler_irq_iffifo); + + mmio_region_write32(iffifo_base_addr, IFFIFO_WATERMARK_REG_OFFSET, 2); + mmio_region_write32(iffifo_base_addr, IFFIFO_INTERRUPTS_REG_OFFSET, 0b1); + + dma_config_flags_t ret; + + // -- DMA CONFIGURATION -- + + dma_init(NULL); + tgt_src.ptr = to_fifo; + tgt_src.inc_d1_du = 1; + tgt_src.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE_WORD; + + tgt_dst.ptr = IFFIFO_START_ADDRESS + IFFIFO_FIFO_IN_REG_OFFSET; + tgt_dst.inc_d1_du = 0; + tgt_dst.trig = DMA_TRIG_SLOT_EXT_TX; + tgt_dst.type = DMA_DATA_TYPE_WORD; + + trans.size_d1_du = 6; + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.end = DMA_TRANS_END_INTR; + + ret = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); + if (ret != 0) {return EXIT_FAILURE;} + ret = dma_load_transaction(&trans); + if (ret != 0) {return EXIT_FAILURE;} + + if (compare_print_fifo_array() != 4) {return EXIT_FAILURE;} + + print_status_register(); + + PRINTF("Launch MM -> Stream DMA\n"); + // Launch a 6-word TX DMA transaction to a 4-word FIFO. The FIFO will be full. + dma_launch( &trans ); + + // To terminate the DMA transaction, 2 words must be manually popped from the FIFO. + while(!is_iffifo_full()); + int32_t read0 = mmio_region_read32(iffifo_base_addr, IFFIFO_FIFO_OUT_REG_OFFSET); + while(!is_iffifo_full()); + int32_t read1 = mmio_region_read32(iffifo_base_addr, IFFIFO_FIFO_OUT_REG_OFFSET); + + print_status_register(); + + PRINTF("Manual readings: {%d, %d}\n", read0, read1); + + protected_wait_for_dma_interrupt(); + + dma_init(NULL); + tgt_src.ptr = IFFIFO_START_ADDRESS + IFFIFO_FIFO_OUT_REG_OFFSET; + tgt_src.inc_d1_du = 0; + tgt_src.trig = DMA_TRIG_SLOT_EXT_RX; + tgt_src.type = DMA_DATA_TYPE_WORD; + + tgt_dst.ptr = from_fifo; + tgt_dst.inc_d1_du = 1; + tgt_dst.trig = DMA_TRIG_MEMORY; + tgt_dst.type = DMA_DATA_TYPE_WORD; + + trans.size_d1_du = 4; + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.end = DMA_TRANS_END_INTR; + + ret = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); + if (ret != 0) {return EXIT_FAILURE;} + ret = dma_load_transaction(&trans); + if (ret != 0) {return EXIT_FAILURE;} + PRINTF("Launch Stream -> MM DMA\n"); + dma_launch( &trans ); + + protected_wait_for_dma_interrupt(); + + print_status_register(); + + if (compare_print_fifo_array() == 0) {return EXIT_FAILURE;}; + + if (!iffifo_intr_flag) {return EXIT_FAILURE;}; + + return EXIT_SUCCESS; + +} + diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_golden.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_golden.c new file mode 100644 index 00000000..c6716359 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_golden.c @@ -0,0 +1,20 @@ +/* + Copyright EPFL contributors. + Licensed under the Apache License, Version 2.0, see LICENSE for details. + SPDX-License-Identifier: Apache-2.0 +*/ + +#include "im2col_golden.h" + +const uint32_t golden_im2col_nchw[225] = { + 0, 0, 0, 0, 0, 0, 45280, 44040, 39555, 48322, 0, 46986, 61580, 31407, 53015, 0, 48311, 52851, 12647, 34880, 0, 1708, 38684, 39145, 34646, + 0, 0, 0, 0, 0, 45280, 44040, 39555, 48322, 43761, 46986, 61580, 31407, 53015, 50099, 48311, 52851, 12647, 34880, 26310, 1708, 38684, 39145, 34646, 20833, + 0, 0, 0, 0, 0, 44040, 39555, 48322, 43761, 0, 61580, 31407, 53015, 50099, 0, 52851, 12647, 34880, 26310, 0, 38684, 39145, 34646, 20833, 0, + 0, 45280, 44040, 39555, 48322, 0, 46986, 61580, 31407, 53015, 0, 48311, 52851, 12647, 34880, 0, 1708, 38684, 39145, 34646, 0, 38991, 55892, 20081, 22175, + 45280, 44040, 39555, 48322, 43761, 46986, 61580, 31407, 53015, 50099, 48311, 52851, 12647, 34880, 26310, 1708, 38684, 39145, 34646, 20833, 38991, 55892, 20081, 22175, 48554, + 44040, 39555, 48322, 43761, 0, 61580, 31407, 53015, 50099, 0, 52851, 12647, 34880, 26310, 0, 38684, 39145, 34646, 20833, 0, 55892, 20081, 22175, 48554, 0, + 0, 46986, 61580, 31407, 53015, 0, 48311, 52851, 12647, 34880, 0, 1708, 38684, 39145, 34646, 0, 38991, 55892, 20081, 22175, 0, 0, 0, 0, 0, + 46986, 61580, 31407, 53015, 50099, 48311, 52851, 12647, 34880, 26310, 1708, 38684, 39145, 34646, 20833, 38991, 55892, 20081, 22175, 48554, 0, 0, 0, 0, 0, + 61580, 31407, 53015, 50099, 0, 52851, 12647, 34880, 26310, 0, 38684, 39145, 34646, 20833, 0, 55892, 20081, 22175, 48554, 0, 0, 0, 0, 0, 0 +}; + diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_golden.h b/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_golden.h new file mode 100644 index 00000000..8ef7092c --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_golden.h @@ -0,0 +1,14 @@ +#ifndef GOLDEN_IM2COL_NCHW_H +#define GOLDEN_IM2COL_NCHW_H + +/* + Copyright EPFL contributors. + Licensed under the Apache License, Version 2.0, see LICENSE for details. + SPDX-License-Identifier: Apache-2.0 +*/ + +#include + +extern const uint32_t golden_im2col_nchw[225]; + +#endif // GOLDEN_IM2COL_NCHW_H diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_input.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_input.c new file mode 100644 index 00000000..7def5007 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_input.c @@ -0,0 +1,16 @@ +/* + Copyright EPFL contributors. + Licensed under the Apache License, Version 2.0, see LICENSE for details. + SPDX-License-Identifier: Apache-2.0 +*/ + +#include "im2col_input.h" + +const uint32_t input_image_nchw[25] = { + 45280, 44040, 39555, 48322, 43761, + 46986, 61580, 31407, 53015, 50099, + 48311, 52851, 12647, 34880, 26310, + 1708, 38684, 39145, 34646, 20833, + 38991, 55892, 20081, 22175, 48554 +}; + diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_input.h b/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_input.h new file mode 100644 index 00000000..b1ec30ce --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_input.h @@ -0,0 +1,27 @@ +#ifndef INPUT_IMAGE_NCHW_H +#define INPUT_IMAGE_NCHW_H + +/* + Copyright EPFL contributors. + Licensed under the Apache License, Version 2.0, see LICENSE for details. + SPDX-License-Identifier: Apache-2.0 +*/ + +#include + +#define IH 5 +#define IW 5 +#define CH 1 +#define BATCH 1 +#define FH 3 +#define FW 3 +#define TOP_PAD 1 +#define BOTTOM_PAD 1 +#define LEFT_PAD 1 +#define RIGHT_PAD 1 +#define STRIDE_D1 1 +#define STRIDE_D2 1 + +extern const uint32_t input_image_nchw[25]; + +#endif // INPUT_IMAGE_NCHW_H diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_lib.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_lib.c new file mode 100644 index 00000000..6670cc0f --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/im2col_lib.c @@ -0,0 +1,489 @@ +/* + Copyright EPFL contributors. + Licensed under the Apache License, Version 2.0, see LICENSE for details. + SPDX-License-Identifier: Apache-2.0 + + Author: Tommaso Terzano + + + Info: im2col_lib.c describes functions used to calculate im2col and verify it using + the golden result in im2colGolden.c. + + Notes: im2col_nchw_int32() algorithm is inspired from the library SHL, developed by T-HEAD Semi. + For reference, check out the following link: + https:/*github.com/T-head-Semi/csi-nn2/blob/main/source/reference/im2col.c +*/ + +#include "im2col_lib.h" + +#if INPUT_DATATYPE == 2 + typedef uint8_t data_t; +#elif INPUT_DATATYPE == 1 + typedef uint16_t data_t; +#elif INPUT_DATATYPE == 0 + typedef uint32_t data_t; +#endif + +data_t output_data[OH_NCHW*OW_NCHW]; +data_t* input_image_ptr = &input_image_nchw[0]; +data_t* output_data_ptr = &output_data[0]; + +char im2col_done = 0; +int ifr_status; + +void handler_irq_im2col_spc( void ) +{ + im2col_done = 1; + + /* Read the IFR to lower the interrupt flag */ + ifr_status = * (volatile uint32_t * )(EXT_PERIPHERAL_START_ADDRESS + IM2COL_PER_OFFSET + IM2COL_SPC_SPC_IFR_REG_OFFSET); + return; +} + +/* Used to wait for the SPC interrupt handler to end */ +__attribute__ ((optimize("O0"))) void waiting_for_spc_irq( void ) +{ + while (im2col_done == 0) + { + asm volatile ("wfi"); + } +} + +int im2col_nchw_int32(uint8_t test_id, unsigned int *cycles) +{ + int size_transfer = 0; + int size_transfer_d2 = 0; + int counter = 0; + int n_zeros_left = 0; + int n_zeros_right = 0; + int n_zeros_top = 0; + int n_zeros_bottom = 0; + int im_row = 0; + int im_col = 0; + int im_c = 0; + int w_offset = 0; + int h_offset = 0; + int col_index = 0; + int minimum = 0; + int start_max = 0; + int start_min = 0; + int stray_elements = 0; + int last_position = 0; + int tmp_pad = 0; + int w_offset_pad = 0; + int h_offset_pad = 0; + int fw_minus_w_offset = 0; + int fh_minus_h_offset = 0; + unsigned int cycles_A = 0; + unsigned int cycles_B = 0; + unsigned int avg_first_zeros; + unsigned int avg_last_zeros; + unsigned int avg_patch = 0; + int src_inc_d2 = 0; + int w_offset_counter = 0; + int h_offset_counter = 0; + int h_offset_tmp_counter = 0; + int im_c_counter = 0; + int w_offset_vs_PAD = 0; + int h_offset_vs_PAD = 0; + int fw_minus_w_offset_vs_PAD = 0; + int fh_minus_h_offset_vs_PAD = 0; + int h_offset_tmp = 0; + int n_zeros_top_counter = 0; + int n_zeros_top_cond = 0; + int pad_min_w_offset = 0; + + for (int i=0; i= IH || im_col >= IW) { + output_data[col_index] = 0; + PRINTF_DEB("Padding with 0\n\r"); + } else { + output_data[col_index] = input_image_nchw[get_index(CH, IH, IW, b, im_c, im_row, im_col)]; + PRINTF_DEB("Value: %d\n\r", input_image_nchw[get_index(CH, IH, IW, b, im_c, im_row, im_col)]); + } + } + } + } + } + + #if TIMING + *cycles = timer_stop(); + #endif + } + + /* Implementation of the nchw im2col algorithm using the DMA 2D feature */ + else if (test_id == 1) + { + + data_t* input_image_ptr = &input_image_nchw[0]; + data_t* output_data_ptr = &output_data[0]; + /* Iterate over each row of the output matrix. */ + + dma_config_flags_t res; + + static dma_target_t tgt_src = { + .ptr = input_image_nchw, + .inc_d1_du = STRIDE_D1, + .type = INPUT_DATATYPE + }; + + static dma_target_t tgt_dst = { + .inc_d1_du = 1, + .inc_d2_du = 1, + .type = INPUT_DATATYPE + }; + + static dma_trans_t trans = { + .src = &tgt_src, + .dst = &tgt_dst, + .mode = DMA_TRANS_MODE_SINGLE, + .dim = DMA_DIM_CONF_2D, + .end = DMA_TRANS_END_INTR, + .channel = 0 + }; + + #if TIMING + timer_start(); + #endif + + /* The DMA is initialized (i.e. Any current transaction is cleaned.) */ + dma_init(NULL); + + w_offset = 0; + h_offset = 0; + pad_min_w_offset = LEFT_PAD; + + for (int c = 0; c < CH_COL; ++c) { + + /* Iterate over each patch on the IW of the input matrix. */ + fw_minus_w_offset = FW - 1 - w_offset; + fh_minus_h_offset = FH - 1 - h_offset; + + /* Calculate offsets within the kernel window. */ + + /* Iterate over each BATCH. */ + for (int32_t b = 0; b < BATCH; ++b) { + + im_row = h_offset - TOP_PAD; + im_col = w_offset - LEFT_PAD; + + PRINTF_DEB("\n\rim_row: %d, im_col: %d", im_row, im_col); + PRINTF_DEB("\n\rw_offset: %d, h_offset: %d\n\r", w_offset, h_offset); + + /* Computing the number of zeros on the left */ + + /* In the offset of the element in the filter is bigger than P, then no zeros are needed */ + if ( w_offset >= LEFT_PAD) + { + n_zeros_left = 0; + } + else if ( (LEFT_PAD - w_offset) % STRIDE_D1 == 0 ) + { + n_zeros_left = (LEFT_PAD - w_offset) / STRIDE_D1; + } + else + { + n_zeros_left = (LEFT_PAD - w_offset) / STRIDE_D1 + 1; + } + + /* Computing the number of zeros on the top */ + + /* In the offset of the element in the filter is bigger than P, then no zeros are needed */ + if ( h_offset >= TOP_PAD) + { + n_zeros_top = 0; + } + else if ( (TOP_PAD - h_offset) % STRIDE_D2 == 0 ) + { + n_zeros_top = (TOP_PAD - h_offset) / STRIDE_D2; + } + else + { + n_zeros_top = (TOP_PAD - h_offset) / STRIDE_D2 + 1; + } + + /* Computing the number of zeros on the right */ + + /* To adapt the final case to the formulas used to the first padded region, let's compute an "adapted" padded region, + /* by removing the elements of the row uncovered by the sliding filter */ + + if (fw_minus_w_offset >= RIGHT_PAD || ADPT_PAD_RIGHT == 0) + { + n_zeros_right = 0; + } + else if ( (ADPT_PAD_RIGHT - (fw_minus_w_offset)) % STRIDE_D1 == 0 ) + { + n_zeros_right = (ADPT_PAD_RIGHT - (fw_minus_w_offset)) / STRIDE_D1; + } + else + { + n_zeros_right = (ADPT_PAD_RIGHT - (fw_minus_w_offset)) / STRIDE_D1 + 1; + } + + /* Computing the number of zeros on the bottom */ + + /* To adapt the final case to the formulas used to the first padded region, let's compute an "adapted" padded region, + /* by removing the elements of the row uncovered by the sliding filter */ + + if (fh_minus_h_offset >= BOTTOM_PAD || ADPT_PAD_BOTTOM == 0) + { + n_zeros_bottom = 0; + } + else if ( (ADPT_PAD_BOTTOM - (fh_minus_h_offset)) % STRIDE_D2 == 0) + { + n_zeros_bottom = (ADPT_PAD_BOTTOM - (fh_minus_h_offset)) / STRIDE_D2; + } + else + { + n_zeros_bottom = (ADPT_PAD_BOTTOM - (fh_minus_h_offset)) / STRIDE_D2 + 1; + } + + /* Compute the number of elements to transfer */ + size_transfer = N_PATCHES_W - n_zeros_left - n_zeros_right; + size_transfer_d2 = N_PATCHES_H - n_zeros_top - n_zeros_bottom; + + PRINTF_DEB("\n\rn_zeros_left: %d, n_zeros_right: %d, n_zeros_top: %d, n_zeros_bottom: %d", n_zeros_left, n_zeros_right, n_zeros_top, n_zeros_bottom); + PRINTF_DEB("\n\rsize_transfer: %d, size_transfer_d2: %d\n\r", size_transfer, size_transfer_d2); + + /* DMA setup and transaction run */ + int index = get_index(CH, IH, IW, b, im_c, im_row + n_zeros_top*STRIDE_D2, im_col + n_zeros_left*STRIDE_D1); + src_inc_d2 = (STRIDE_D2 * IW - (size_transfer - 1 + (STRIDE_D1 - 1) * (size_transfer - 1))); + + PRINTF_DEB("\n\rindex: %d, src_inc_d2: %d", index, src_inc_d2); + + input_image_ptr = &input_image_nchw[0] + index; + PRINTF_DEB("\n\rsrc_ptr: %x dst_ptr: %x\n\r", input_image_ptr, output_data_ptr); + + tgt_src.ptr = input_image_ptr; + tgt_src.inc_d2_du = src_inc_d2; + + tgt_dst.ptr = output_data_ptr; + + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.size_d1_du = size_transfer; + trans.size_d2_du = size_transfer_d2; + trans.pad_top_du = n_zeros_top; + trans.pad_left_du = n_zeros_left; + trans.pad_right_du = n_zeros_right; + trans.pad_bottom_du = n_zeros_bottom; + + dma_run(&trans); + + output_data_ptr += OW_NCHW; + + PRINTF_DEB("\n\r"); + + #ifndef DEBUG + PRINTF_DEB("\n\rCurrent output matrix: \n\r"); + for (int i=0; i + * + + Info: Header file of im2col_lib.c, containing the function prototypes, parameters macros and the configuration of prints and performance analysis. +*/ + +#ifndef _IM2COL_ +#define _IM2COL_ + +#include +#include +#include +#include "im2col_golden.h" +#include "im2col_input.h" +#include "im2col.h" +#include "dma.h" +#include "im2col_spc_regs.h" +#include "core_v_mini_mcu.h" +#include "x-heep.h" +#include "rv_plic.h" +#include "csr.h" +#include + +#include "mmio.h" +#include "handler.h" +#include "hart.h" +#include "fast_intr_ctrl.h" +#include "timer_sdk.h" + +/* + Choose between several HW configurations: + - 0: Only CPU + - 1: Exploit standard DMA + - 2: Exploit 2D DMA + - 3: Exploit Smart Peripheral Controller (SPC) +*/ +#define HW_CONFIG_CPU +#define HW_CONFIG_DMA_2D +#define HW_CONFIG_SPC + +/* Defines which DMA channels are available to the SPC, depending on HW specifications */ +#define SPC_CH_MASK 0b0001 + +/* Defines the datatype of the input */ +#define INPUT_DATATYPE 0 + +/* Defines the offset of the im2col SPC in the system (0x4000 in testharness.sv) */ +#define IM2COL_PER_OFFSET 0x4000 + +/* By default, printfs are activated for FPGA and for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +/* Set to 1 to enable debug prints */ +#define DEBUG 0 +/* Set to 1 to enable timing measurements */ +#define TIMING 1 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) + #if DEBUG + #define PRINTF_DEB(fmt, ...) printf(fmt, ## __VA_ARGS__) + #else + #define PRINTF_DEB(...) + #endif + #if TIMING + #define PRINTF_TIM(fmt, ...) printf(fmt, ## __VA_ARGS__) + #else + #define PRINTF_TIM(...) + #endif +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) + #if DEBUG + #define PRINTF_DEB(fmt, ...) printf(fmt, ## __VA_ARGS__) + #else + #define PRINTF_DEB(...) + #endif + #if TIMING + #define PRINTF_TIM(fmt, ...) printf(fmt, ## __VA_ARGS__) + #else + #define PRINTF_TIM(...) + #endif +#else + #define PRINTF(...) + #define PRINTF_DEB(...) + #define PRINTF_TIM(...) +#endif + +// Define the dimensions of the input tensor and the kernel + +#define N_PATCHES_H ((IH + (TOP_PAD + BOTTOM_PAD) - FH)/ STRIDE_D2 + 1) +#define N_PATCHES_W ((IW + (RIGHT_PAD + LEFT_PAD) - FW)/ STRIDE_D1 + 1) + +#define ADPT_PAD_BOTTOM (STRIDE_D2 * (N_PATCHES_H - 1) + FH - (TOP_PAD + IH)) +#define ADPT_PAD_RIGHT (STRIDE_D1 * (N_PATCHES_W - 1) + FW - (LEFT_PAD + IW)) + +#define CH_COL (CH * FH * FW) + +#define OH_NCHW (CH * FH * FW * BATCH) +#define OW_NCHW (N_PATCHES_H) * (N_PATCHES_W) + +#define START_ID 0 + +#define TEST_EN 0 + +// Computations for 2D DMA +#define SRC_INC_D2 (STRIDE_D2 * IW - (FW - 1 + (STRIDE_D1 - 1) * (FW - 1))) + +int im2col_nchw_int32(uint8_t test_id, unsigned int *cycles); + +__attribute__((weak, optimize("O0"))) void handler_irq_im2col_spc(void); + +int get_index(int dim1, int dim2, int dim3, int index0, int index1, int index2, int index3); + +int verify(void); + +#endif diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/main.c new file mode 100644 index 00000000..23c71e67 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_im2col/main.c @@ -0,0 +1,59 @@ +/* + Copyright EPFL contributors. + Licensed under the Apache License, Version 2.0, see LICENSE for details. + SPDX-License-Identifier: Apache-2.0 + + Author: Tommaso Terzano + + + Info: Example application of im2col algorithm with configurable format, verification and performance analysis. +*/ + +#include +#include +#include +#include "x-heep.h" +#include "im2col_lib.h" + +/* Test variables */ +int errors; +unsigned int cycles; + +int main() +{ + for (int i=START_ID; i<3; i++) + { + im2col_nchw_int32(i, &cycles); + + #if TEST_EN == 0 + PRINTF("im2col NCHW test %d executed\n\r", i); + PRINTF_TIM("Total number of cycles: [%d]\n\r", cycles); + #endif + + errors = verify(); + + if (errors != 0) + { + #if TEST_EN == 0 + PRINTF("TEST %d FAILED: %d errors\n\r", i, errors); + return EXIT_FAILURE; + #else + PRINTF_TIM("%d:%d:1\n\r", i, cycles); + #endif + + } + else + { + #if TEST_EN == 0 + PRINTF("TEST PASSED!\n\r\n\r"); + #else + PRINTF_TIM("%d:%d:0\n\r", i, cycles); + #endif + } + } + + /* Print the end word for verification */ + PRINTF("&\n\r"); + + return EXIT_SUCCESS; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd/main.c index 80fdb655..7c35229c 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd/main.c +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd/main.c @@ -14,7 +14,7 @@ #if TARGET_SIM && PRINTF_IN_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA +#elif PRINTF_IN_FPGA && !TARGET_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) #else #define PRINTF(...) diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/main.c new file mode 100644 index 00000000..058aadbe --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/main.c @@ -0,0 +1,84 @@ +// Copyright 2022 OpenHW Group +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#include +#include +#include "csr.h" +#include "matrixAdd32.h" +#include "x-heep.h" +#include "core_v_mini_mcu.h" + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +void __attribute__ ((noinline)) matrixAdd(int32_t * A, int32_t * B, int32_t * C, int N, int M); +uint32_t check_results(int32_t * C, int N, int M); + +int32_t __attribute__((section(".xheep_data_interleaved"))) m_c[16*16]; + + +int main() +{ + +#ifndef HAS_MEMORY_BANKS_IL + PRINTF("This application is only meant to be tested when there are interleaved memory banks\n"); + return EXIT_SUCCESS; +#endif + + + int N = WIDTH; + int M = HEIGHT; + uint32_t errors = 0; + unsigned int instr, cycles, ldstall, jrstall, imstall; + + CSR_WRITE(CSR_REG_MCYCLE, 0); + + //execute the kernel + matrixAdd(m_a, m_b, m_c, N, M); + + CSR_READ(CSR_REG_MCYCLE, &cycles) ; + + //stop the HW counter used for monitoring + + errors = check_results(m_c, N, M); + + PRINTF("program finished with %d errors and %d cycles\n\r", errors, cycles); + return errors; +} + +void __attribute__ ((noinline)) matrixAdd(int32_t * A, int32_t * B, int32_t * C, int N, int M) +{ + for(int i = 0; i < N; i++) { + for(int j = 0; j < M; j++) { + C[i*N+j] = A[i*WIDTH+j] + B[i*WIDTH+j]; + } + } +} + +uint32_t check_results(int32_t * C, int N, int M) +{ + // check + int i, j; + uint32_t err = 0; + + for(i = 0; i < N; i++) { + for(j = 0; j < M; j++) { + if(C[i*N+j] != m_exp[i*WIDTH+j]) { + err++; + PRINTF("Error at index %d, %d, expected %d, got %d\n\r", i, j, m_exp[i*WIDTH+j], C[i*N+j]); + } + } + } + + return err; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/matrixAdd32.h b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/matrixAdd32.h new file mode 100644 index 00000000..8b9bace3 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matadd_interleaved/matrixAdd32.h @@ -0,0 +1,64 @@ +#ifndef MatrixAdd32_H_ +#define MatrixAdd32_H_ + +int32_t __attribute__((section(".xheep_data_interleaved"))) m_a[16*16] = { +-267220638, -815694637, -357240193, 52586566, 471263969, -752743258, -54811671, -330483534, -895389047, 476606065, -261687046, -301494394, 101299356, 1064594637, 876939884, 673598893, +510087407, 21095419, -66273695, 200819447, 230905645, -522677817, 466985617, -42864608, 925345137, -985253526, 963426323, 34126990, -894741205, -944572242, -62503253, -88084923, +-40863508, 775424478, -977993934, -563294903, 240810335, -950840151, 841082377, 814816122, 1010825869, 626595210, -30466653, 32965586, -1009681585, -398274647, 209852250, -680997577, +831825297, 371554642, 209565266, -173321792, 130553499, -846489230, -837855833, -291296547, -656131005, -1008649794, -644660179, -559832327, -957317256, 414035806, 238077607, -417354312, +691270381, 167236288, -370338394, 264811381, -740211299, -502137446, -216028919, -576761164, -1005576983, -300300576, -51567714, 742968985, -713639053, 81381137, -254911471, -456085969, +-657637814, 212880558, 164912940, 975706502, -558175870, -522438623, 219649600, -149341108, -761491992, -324770181, -905679666, -1066241764, 852450941, -105770862, -706293797, 965826475, +605386582, 397282251, -510180840, 322039481, 906789344, 577829424, -244909961, -6565162, -10463653, -275962613, 1045813592, 287658995, 202626085, -913131320, -953473425, 7501200, +44568419, 631042458, -962343731, 389765403, 510986448, 615528098, 854389577, 873031590, 291656555, 717742724, 139337062, 1014134612, 37179482, 156110030, 549532436, -211305424, +146967397, -910154681, 306466943, 809719463, 990862734, -321035009, -503247368, -434011427, -184327001, -460285290, -695885128, 745541667, 549735829, 972687164, 81845219, 626415449, +-869892524, 7650305, -668932203, 612640394, -533618868, -767284692, 263874653, -505082478, -333082894, -170998598, 351985173, 539903843, 161284779, -223326011, -386924128, -894616525, +-205913216, 983230715, 184759813, 3745004, -421392253, 311771810, 809133901, 541639735, 1029270115, 390582486, 1059667793, -308077038, -345200733, 661937983, -69729012, -313649214, +-457079064, 660862401, -419895058, -352985806, 748622990, 789128492, 57857836, 123409871, 367565501, 714681971, 90478156, 401194382, -25590123, 808922190, 231668089, 365978441, +-168791957, 500701111, 966566283, -619646012, 410934777, -567381204, 405170082, -954683259, -176892010, 205925886, 1035377376, 91289957, 478111519, 220727997, -859802080, -155168848, +723982461, -833318195, -445511314, -903460885, 167471780, 423323222, -640855013, 480396600, -268314639, -850542572, 257027787, -315635254, 560711756, -717798753, -372060287, -544448897, +-103077323, -640041517, 577573751, 1039664378, -546538923, 739571966, 680289428, 412799378, 987282320, -378880850, 588647906, -965191092, -829907433, 739600408, -33720223, 56361300, +-1068334620, -399957948, -960664907, -540542510, 280786542, -752129362, -10289650, 1029788294, -636639267, 1029706817, -892387611, 191199904, -965464658, -1048403025, -734580512, 872029387, +}; + +int32_t __attribute__((section(".xheep_data_interleaved"))) m_b[16*16] = { +-451882475, -777460700, 909169980, -96074001, -300818508, 814405880, -568048006, -83472456, 402440048, 810240641, -180564453, 216877888, -140613462, 620727378, -909318526, 765805622, +-231722067, -336894715, -1073684733, -121460761, -23888211, 438175722, -904262018, 145258576, -356787314, 372900212, -358591099, 140421444, -928238022, -99914115, 968352616, -71902672, +-7354035, -831973999, 233305822, -392287490, -729923194, -828467700, -323283176, -788941348, -111739211, -199056442, -476803416, 465916744, 443852965, -376815395, 148885406, 124331090, +-998134941, -490161461, 607731285, 887008149, 683830004, -186741406, -241303958, 456378716, 536730595, 967225269, 1037796891, -802215107, 382626188, 791688228, 538691527, -19673298, +251682349, 598278365, 984763713, 698038628, 821027888, -495782484, -798473539, -424505599, 310436971, 361824506, -130460722, -847926918, 926418138, 637997507, 565305015, 901041052, +236841072, 748341019, 851219634, 437917539, 979456559, 834327011, -191800443, 415161968, -687346999, -41616108, 226338567, 671381489, -248505365, -991524242, 465050274, 673573191, +-432551530, 1057245412, 714468280, -650829182, -850172935, 408331778, 846612827, 884618062, -1025138869, 389044228, 241552082, 1038961376, -425996140, -770151901, -59811946, 433319347, +420324744, -41895865, -626338369, -617719112, -398763632, 40560785, 608712418, 270292226, 276772130, 713936878, -39616963, 852564869, 651061789, -1069752389, 942487510, -212496210, +-884568730, -614540093, 940597970, 963278316, 500604546, -89930534, -362276438, 800923761, 799305363, 67728257, -935053727, -507421158, 453168328, -270267180, 767962559, 540805, +-178905319, 755067965, -132287841, -8637376, 608185815, 427835026, 103464976, -203264205, 80225884, 539643001, -362743073, -487778248, 792077066, 697184933, 827496823, 790812604, +249285726, 359686773, 419021969, 454726313, 124358246, 47824230, -619837186, -913155286, -381944316, 783327309, 572077053, -225060553, 787746239, 671339856, 730167112, 870184696, +319311551, 932192632, -376845525, -288051918, 713264893, -102198441, -315559203, -635483087, -76253988, -427900440, -508626018, -847322511, -717023663, 649773356, -751674700, -363502823, +896873064, -967112426, -607994984, 346538028, -403535863, -456242519, -865446025, -238823125, 568667781, -1008745310, -517236588, -90482335, -769550983, -553756781, -473911347, -317302102, +308779302, 610106502, -99323447, -610238668, 176302035, 320291710, 22124485, 927846370, -961507070, 1046393978, 623269088, -385024596, -636139940, -661255126, -1024580190, -710776275, +874358552, -978379641, 484825057, -177908522, -643611415, -197553591, 406358020, 460342548, 408235584, -809119385, 1047128507, -592130753, -50891763, 786819419, 314046385, 461621105, +-328939806, 375494681, 558517164, 640788713, -419567316, -499867631, 629778826, 201608525, 1006046604, 259505742, 994398852, 338082134, -444011788, 128878595, -672831452, 18560178, +}; + +int32_t m_exp[16*16] = { +-719103113, -1593155337, 551929787, -43487435, 170445461, 61662622, -622859677, -413955990, -492948999, 1286846706, -442251499, -84616506, -39314106, 1685322015, -32378642, 1439404515, +278365340, -315799296, -1139958428, 79358686, 207017434, -84502095, -437276401, 102393968, 568557823, -612353314, 604835224, 174548434, -1822979227, -1044486357, 905849363, -159987595, +-48217543, -56549521, -744688112, -955582393, -489112859, -1779307851, 517799201, 25874774, 899086658, 427538768, -507270069, 498882330, -565828620, -775090042, 358737656, -556666487, +-166309644, -118606819, 817296551, 713686357, 814383503, -1033230636, -1079159791, 165082169, -119400410, -41424525, 393136712, -1362047434, -574691068, 1205724034, 776769134, -437027610, +942952730, 765514653, 614425319, 962850009, 80816589, -997919930, -1014502458, -1001266763, -695140012, 61523930, -182028436, -104957933, 212779085, 719378644, 310393544, 444955083, +-420796742, 961221577, 1016132574, 1413624041, 421280689, 311888388, 27849157, 265820860, -1448838991, -366386289, -679341099, -394860275, 603945576, -1097295104, -241243523, 1639399666, +172835052, 1454527663, 204287440, -328789701, 56616409, 986161202, 601702866, 878052900, -1035602522, 113081615, 1287365674, 1326620371, -223370055, -1683283221, -1013285371, 440820547, +464893163, 589146593, -1588682100, -227953709, 112222816, 656088883, 1463101995, 1143323816, 568428685, 1431679602, 99720099, 1866699481, 688241271, -913642359, 1492019946, -423801634, +-737601333, -1524694774, 1247064913, 1772997779, 1491467280, -410965543, -865523806, 366912334, 614978362, -392557033, -1630938855, 238120509, 1002904157, 702419984, 849807778, 626956254, +-1048797843, 762718270, -801220044, 604003018, 74566947, -339449666, 367339629, -708346683, -252857010, 368644403, -10757900, 52125595, 953361845, 473858922, 440572695, -103803921, +43372510, 1342917488, 603781782, 458471317, -297034007, 359596040, 189296715, -371515551, 647325799, 1173909795, 1631744846, -533137591, 442545506, 1333277839, 660438100, 556535482, +-137767513, 1593055033, -796740583, -641037724, 1461887883, 686930051, -257701367, -512073216, 291311513, 286781531, -418147862, -446128129, -742613786, 1458695546, -520006611, 2475618, +728081107, -466411315, 358571299, -273107984, 7398914, -1023623723, -460275943, -1193506384, 391775771, -802819424, 518140788, 807622, -291439464, -333028784, -1333713427, -472470950, +1032761763, -223211693, -544834761, -1513699553, 343773815, 743614932, -618730528, 1408242970, -1229821709, 195851406, 880296875, -700659850, -75428184, -1379053879, -1396640477, -1255225172, +771281229, -1618421158, 1062398808, 861755856, -1190150338, 542018375, 1086647448, 873141926, 1395517904, -1188000235, 1635776413, -1557321845, -880799196, 1526419827, 280326162, 517982405, +-1397274426, -24463267, -402147743, 100246203, -138780774, -1251996993, 619489176, 1231396819, 369407337, 1289212559, 102011241, 529282038, -1409476446, -919524430, -1407411964, 890589565, +}; + +#define WIDTH 16 +#define HEIGHT 16 + +#endif // MatrixAdd32_H_ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matfadd/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matfadd/main.c index ab2191bd..59dc2bef 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matfadd/main.c +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matfadd/main.c @@ -17,7 +17,7 @@ #if TARGET_SIM && PRINTF_IN_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA +#elif PRINTF_IN_FPGA && !TARGET_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) #else #define PRINTF(...) @@ -28,11 +28,24 @@ uint32_t check_results(float * C, int N, int M); float m_c[HEIGHT*WIDTH]; -void swap(char *a, char *b) +void putlong(long i) { - char temp = *a; - *a = *b; - *b = temp; + char int_str[20]; // An array to store the digits + int len = 0; // The length of the string + do + { + // Get the last digit and store it in the array + int_str[len] = '0' + i % 10; + len++; + // Remove the last digit from i + i /= 10; + } while (i > 0); + + // Print the reversed string of digits + for (int j = len - 1; j >= 0; j--) + { + putchar(int_str[j]); + } } // A function to print a floating point number using putchar @@ -47,57 +60,68 @@ void putfloat(float x, int p) x = -x; } - // Convert the integer part of x into a string of digits - long i = (long)x; // Get the integer part - char int_str[20]; // An array to store the digits - int len = 0; // The length of the string - do - { - // Get the last digit and store it in the array - int_str[len] = '0' + i % 10; - len++; - // Remove the last digit from i - i /= 10; - } while (i > 0); + float f = x - (long)x; // Get the fractional part of x - // Reverse the string of digits - for (int j = 0; j < len / 2; j++) + // Get the p most significant digits of the fractional part as the + // integer part of f. + // Count the number of initial zeros. + int initial_zeros = 0; + // Check if the fraction will overflow to the integer part when + // rounding up (i.e. if the fraction is 0.999...) + int fraction_overflow = 1; + for (int j = 0; j < p; j++) { - // Swap the elements at both ends - swap(&int_str[j], &int_str[len - 1 - j]); + f *= 10; + if (f < 1) + { + // exclude the last digit with round up + if (!(j == p - 1 && f >= 0.5f)) + initial_zeros++; + } + if (fraction_overflow && (long)f % 10 < 9) + { + fraction_overflow = 0; + } } - // Print the string of digits - for (int j = 0; j < len; j++) + // Round up if necessary + if ((f - (long)f) >= 0.5f) { - putchar(int_str[j]); + // If the rounding causes a digit to overflow in the fractional + // part, then we need to print one less zero + if (fraction_overflow == 0) + { + f += 1; + if (f >= 10 && initial_zeros > 0) + { + initial_zeros--; + } + } + // If the overflow is in the integer part, then we need to print + // one more digit in the integer part, and none in the fractional + else + { + f = 0; + x += 1; + initial_zeros = p - 1; + } } + // Convert the integer part of x into a string of digits + putlong((long)x); + // Print a decimal point putchar('.'); - // Convert the fractional part of x into a string of digits - float f = x - (long)x; // Get the fractional part - char frac_str[20]; // An array to store the digits - len = 0; // The length of the string - while (p--) + // Print the initial zeros + while (initial_zeros--) { - // Get the first digit after the decimal point and store it in the array - f = (f - (long)f) * 10; - frac_str[len] = '0' + (long)f; - len++; - // Round up if necessary - if (fabs(f - (long)f) >= 0.5f) - { - frac_str[len - 1]++; - } + putchar('0'); } - // Print the string of digits - for (int j = 0; j < len; j++) - { - putchar(frac_str[j]); - } + // Convert the fractional part of x into a string of digits + if (f > 1) + putlong((long)f); } void __attribute__ ((noinline)) printMatrix(float * C, int N, int M) diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/gen_stimuly.py b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/gen_stimuly.py new file mode 100644 index 00000000..cdf55503 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/gen_stimuly.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +## Copyright 2024 EPFL +## Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +## SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +import sys +import random +import numpy as np + +def write_arr(f, name, arr, ctype, size): + f.write("const " + ctype + " " + name + "[] = {\n") + + for row in arr: + for elem in row[:-1]: + f.write('%d,' % (elem)) + f.write('%d,\n' % (row[-1])) + + f.write('};\n\n') + return + + +################################################################################ +f = open('matrixMul8.h', 'w') +f.write('#ifndef _MATMUL8_\n') +f.write('#define _MATMUL8_\n') +f.write('// This file is automatically generated\n') + + +SIZE = 16 +RANGE = 4 + +m_a = [] +m_b = [] +m_exp = [] + +# Generate random 8 bit integers from -RANGE to RANGE for A and B +m_a = np.random.randint(-RANGE, RANGE, size=(SIZE, SIZE), dtype=np.int32) +m_b = np.random.randint(-RANGE, RANGE, size=(SIZE, SIZE), dtype=np.int32) +m_exp = np.zeros((SIZE, SIZE), dtype=np.int32) + +# Test the function with A and B +m_exp = np.matmul(m_a,m_b) + +write_arr(f, 'm_a', m_a, 'int8_t', SIZE) +write_arr(f, 'm_b', m_b, 'int8_t', SIZE) +write_arr(f, 'm_exp', m_exp, 'int32_t', SIZE) + +f.write('#define SIZE %d\n' % SIZE) + + +f.write('#endif') diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/main.c new file mode 100644 index 00000000..69d1750b --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/main.c @@ -0,0 +1,126 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#include +#include +#include "csr.h" +#include "matrixMul8.h" +#include "x-heep.h" + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +void __attribute__ ((noinline)) matrixMul8_blocksize(int8_t * A, int8_t * B, int32_t * C, int N); + +void __attribute__ ((noinline)) matrixMul8_tiled(int8_t * A, int8_t * B, int32_t * C, int N); + +uint32_t check_results(int32_t * C, int N); + +int32_t m_c[SIZE*SIZE]; + +#define BLOCK_SIZE 4 + +// Define a macro for accessing matrix elements +#define A(i,j) &A[i*SIZE+j] +#define B(i,j) &B[i*SIZE+j] +#define C(i,j) &C[i*SIZE+j] + +#define HIGHEST_PERF + +int main() +{ + + uint32_t errors = 0; + unsigned int instr, cycles; + + for(int i =0;i> 1; // Half the size + // Multiply the blocks and add them to the corresponding blocks of C + matrixMul8_tiled(A(0, 0), B(0, 0), C(0, 0), N); // C_00 += A_00 * B_00 + matrixMul8_tiled(A(0, N), B(N, 0), C(0, 0), N); // C_00 += A_01 * B_10 + matrixMul8_tiled(A(0, 0), B(0, N), C(0, N), N); // C_01 += A_00 * B_01 + matrixMul8_tiled(A(0, N), B(N, N), C(0, N), N); // C_01 += A_01 * B_11 + matrixMul8_tiled(A(N, 0), B(0, 0), C(N, 0), N); // C_10 += A_10 * B_00 + matrixMul8_tiled(A(N, N), B(N, 0), C(N, 0), N); // C_10 += A_11 * B_10 + matrixMul8_tiled(A(N, 0), B(0, N), C(N, N), N); // C_11 += A_10 * B_01 + matrixMul8_tiled(A(N, N), B(N, N), C(N, N), N); // C_11 += A_11 * B_11 + } +} + + +uint32_t check_results(int32_t * C, int N) +{ + // check + int i, j; + uint32_t err = 0; + + for(i = 0; i < N; i++) { + for(j = 0; j < N; j++) { + if(C[i*N+j] != m_exp[i*N+j]) { + err++; + PRINTF("Error at index %d, %d, expected %d, got %d\n\r", i, j, m_exp[i*N+j], C[i*N+j]); + } + } + } + + return err; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/matrixMul8.h b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/matrixMul8.h new file mode 100644 index 00000000..bc2be3e0 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_matmul/matrixMul8.h @@ -0,0 +1,62 @@ +#ifndef _MATMUL8_ +#define _MATMUL8_ +// This file is automatically generated +const int8_t m_a[] = { +-4,-2,-3,3,3,-1,-4,-3,1,-2,-2,2,-2,-4,-2,-1, +0,2,0,-2,-3,3,-2,3,-1,3,0,2,3,1,-3,-2, +0,2,2,3,-2,-2,-3,-2,0,-3,0,-4,2,-3,-3,1, +3,-4,1,1,-1,0,-3,0,1,3,-1,-2,2,3,-4,0, +3,-1,2,-4,-1,-2,0,-3,-3,0,-2,-4,-2,1,0,-2, +-3,0,-2,2,-1,2,2,2,3,1,0,-2,-1,-4,3,-3, +1,3,2,-3,-4,-3,-2,-1,-2,3,1,-3,2,-4,0,0, +-2,0,3,-1,3,-4,0,-2,2,3,-2,-2,-1,-4,-3,1, +-4,-2,-4,-1,-2,-4,-4,-2,-4,-4,-3,0,-2,-4,2,-4, +1,-1,-3,-2,-1,-2,-4,0,2,3,1,-3,-3,1,3,1, +-3,0,1,3,-3,1,3,2,0,-2,1,-4,-3,0,1,-4, +3,0,-1,-3,2,-1,-1,1,-1,3,2,-4,2,2,0,-2, +-4,2,2,-2,2,-4,-3,-3,-3,-3,-2,-3,3,0,3,0, +2,3,-2,0,3,1,1,-3,3,0,1,-4,-4,-1,0,1, +0,0,1,3,-3,3,3,1,-3,1,1,2,1,-2,-2,2, +-1,2,-2,1,0,-2,-3,-1,0,0,2,0,3,3,-4,-4, +}; + +const int8_t m_b[] = { +2,1,2,1,0,3,-1,-1,3,3,3,-2,0,-3,-1,3, +-3,0,-3,0,2,-2,3,0,-2,-1,2,-3,2,-2,0,-2, +-4,0,1,3,-3,-3,-2,2,3,0,-1,2,3,2,-2,-4, +3,3,-2,3,2,2,-2,-1,-3,-3,-1,-3,3,-2,2,-2, +0,1,0,-3,-1,-3,-1,0,-1,3,3,1,-1,-1,2,2, +-2,-4,-1,-1,1,1,2,-1,2,3,0,3,2,0,-4,3, +-1,-1,-3,2,-4,3,3,-1,3,1,-3,-2,1,1,2,3, +0,2,0,1,1,-3,-4,-4,2,-2,1,0,3,2,0,-1, +0,1,1,-1,2,-1,0,2,-1,-3,3,0,-2,-4,2,3, +1,-4,2,-4,0,1,3,-4,-2,-3,-2,-2,-1,3,-2,-3, +1,0,2,3,0,1,1,-1,-3,-1,3,-3,-3,-2,1,-4, +-3,2,-4,1,3,2,3,-2,1,1,3,0,-2,-2,-1,-1, +1,-3,-1,1,-2,2,-1,-4,3,0,-3,-4,-3,1,-1,2, +-1,-2,3,-4,0,1,1,1,-2,1,-4,3,0,1,2,1, +1,3,-1,-4,2,0,-1,-1,-4,-3,-2,-4,-1,-4,3,2, +0,1,0,1,3,-4,-1,2,1,-1,3,-2,-2,-2,-1,-1, +}; + +const int32_t m_exp[] = { +15,30,-21,1,25,-11,-8,24,-29,-1,32,23,-10,-15,9,-4, +-20,-44,1,-1,3,12,19,-41,25,4,-10,11,7,36,-44,-17, +13,10,3,50,-5,-17,-31,28,5,-12,9,-14,14,-3,-8,-28, +23,-31,50,-6,-12,14,-20,-5,19,6,-17,24,-4,29,-22,-1, +0,-17,35,-16,-40,5,-2,28,15,29,-28,27,10,27,-7,8, +15,8,-21,-5,6,6,0,-18,-23,-38,-11,-19,16,-8,16,14, +3,-18,14,16,-15,-9,1,-8,6,-23,-5,-36,-6,20,-27,-43, +-4,-1,9,3,-23,-39,-5,24,5,-13,15,6,-4,21,-3,-26, +20,35,-18,-6,6,3,-17,18,-28,-4,-14,16,-2,8,15,-4, +31,7,45,-49,28,-14,-8,10,-49,-31,11,-6,-24,-17,14,-3, +3,8,-5,21,-19,8,-10,8,-17,-23,-39,10,49,16,22,-9, +21,-30,44,-32,-25,5,-5,-22,-5,10,-12,-8,-15,19,1,8, +-7,8,-2,-18,-18,-38,-23,28,-20,-3,-29,-4,-9,9,17,-11, +10,4,11,-18,8,-13,16,34,-29,6,36,-5,0,-37,18,22, +-7,-13,-29,48,-2,22,13,-26,31,1,-8,-18,20,16,-30,-23, +8,-20,13,0,-5,20,10,-10,-22,2,-9,4,-12,14,6,-18, +}; + +#define SIZE 16 +#endif \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_pdm2pcm/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_pdm2pcm/main.c index b4f9c3b3..72551c21 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_pdm2pcm/main.c +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_pdm2pcm/main.c @@ -35,7 +35,7 @@ #if TARGET_SIM && PRINTF_IN_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA +#elif PRINTF_IN_FPGA && !TARGET_SIM #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) #else #define PRINTF(...) diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_gating_core/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_gating_core/main.c deleted file mode 100644 index da7d8448..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_gating_core/main.c +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright EPFL contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "core_v_mini_mcu.h" -#include "rv_timer.h" -#include "power_manager.h" -#include "soc_ctrl.h" -#include "rv_plic.h" -#include "rv_plic_regs.h" -#include "gpio.h" -#include "pad_control.h" -#include "pad_control_regs.h" -#include "x-heep.h" - - -#ifndef RV_PLIC_IS_INCLUDED - #error ( "This app does NOT work as the RV_PLIC peripheral is not included" ) -#endif - - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -static rv_timer_t timer_0_1; -static rv_timer_t timer_2_3; -static const uint64_t kTickFreqHz = 1000 * 1000; // 1 MHz -static power_manager_t power_manager; - -#ifndef TARGET_PYNQ_Z2 - #define GPIO_TB_OUT 30 - #define GPIO_TB_IN 31 - #define GPIO_INTR GPIO_INTR_31 -#endif - -int main(int argc, char *argv[]) -{ - - // Setup power_manager - mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); - power_manager.base_addr = power_manager_reg; - power_manager_counters_t power_manager_cpu_counters; - //counters - uint32_t reset_off, reset_on, switch_off, switch_on, iso_off, iso_on; - - // Setup pads -#ifndef TARGET_PYNQ_Z2 - pad_control_t pad_control; - pad_control.base_addr = mmio_region_from_addr((uintptr_t)PAD_CONTROL_START_ADDRESS); - pad_control_set_mux(&pad_control, (ptrdiff_t)(PAD_CONTROL_PAD_MUX_I2C_SCL_REG_OFFSET), 1); - pad_control_set_mux(&pad_control, (ptrdiff_t)(PAD_CONTROL_PAD_MUX_I2C_SDA_REG_OFFSET), 1); -#endif - - // Setup plic - plic_Init(); - - // Get current Frequency - soc_ctrl_t soc_ctrl; - soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - uint32_t freq_hz = soc_ctrl_get_frequency(&soc_ctrl); - - // Setup rv_timer_0_1 - mmio_region_t timer_0_1_reg = mmio_region_from_addr(RV_TIMER_AO_START_ADDRESS); - rv_timer_init(timer_0_1_reg, (rv_timer_config_t){.hart_count = 2, .comparator_count = 1}, &timer_0_1); - rv_timer_tick_params_t tick_params; - rv_timer_approximate_tick_params(freq_hz, kTickFreqHz, &tick_params); - - // Setup rv_timer_2_3 - mmio_region_t timer_2_3_reg = mmio_region_from_addr(RV_TIMER_START_ADDRESS); - rv_timer_init(timer_2_3_reg, (rv_timer_config_t){.hart_count = 2, .comparator_count = 1}, &timer_2_3); - - // Init cpu_subsystem's counters - - //Turn off: first, isolate the CPU outputs, then I reset it, then I switch it off (reset and switch off order does not really matter) - iso_off = 10; - reset_off = iso_off + 5; - switch_off = reset_off + 5; - //Turn on: first, give back power by switching on, then deassert the reset, the unisolate the CPU outputs - switch_on = 10; - reset_on = switch_on + 20; //give 20 cycles to emulate the turn on time, this number depends on technology and here it is just a random number - iso_on = reset_on + 5; - - if (power_gate_counters_init(&power_manager_cpu_counters, reset_off, reset_on, switch_off, switch_on, iso_off, iso_on, 0, 0) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail. Check the reset and powergate counters value\n\r"); - return EXIT_FAILURE; - } - - // Power-gate and wake-up due to timer_0 - rv_timer_set_tick_params(&timer_0_1, 0, tick_params); - rv_timer_irq_enable(&timer_0_1, 0, 0, kRvTimerEnabled); - rv_timer_arm(&timer_0_1, 0, 0, 1024); - rv_timer_counter_set_enabled(&timer_0_1, 0, kRvTimerEnabled); - - CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); - if (power_gate_core(&power_manager, kTimer_0_pm_e, &power_manager_cpu_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - - // Power-gate and wake-up due to timer_1 - rv_timer_set_tick_params(&timer_0_1, 1, tick_params); - rv_timer_irq_enable(&timer_0_1, 1, 0, kRvTimerEnabled); - rv_timer_arm(&timer_0_1, 1, 0, 1024); - rv_timer_counter_set_enabled(&timer_0_1, 1, kRvTimerEnabled); - - CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); - if (power_gate_core(&power_manager, kTimer_1_pm_e, &power_manager_cpu_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - - // Power-gate and wake-up due to timer_2 - rv_timer_set_tick_params(&timer_2_3, 0, tick_params); - rv_timer_irq_enable(&timer_2_3, 0, 0, kRvTimerEnabled); - rv_timer_arm(&timer_2_3, 0, 0, 1024); - rv_timer_counter_set_enabled(&timer_2_3, 0, kRvTimerEnabled); - - CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); - if (power_gate_core(&power_manager, kTimer_2_pm_e, &power_manager_cpu_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - - // Power-gate and wake-up due to timer_3 - rv_timer_set_tick_params(&timer_2_3, 1, tick_params); - rv_timer_irq_enable(&timer_2_3, 1, 0, kRvTimerEnabled); - rv_timer_arm(&timer_2_3, 1, 0, 1024); - rv_timer_counter_set_enabled(&timer_2_3, 1, kRvTimerEnabled); - - CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); - if (power_gate_core(&power_manager, kTimer_3_pm_e, &power_manager_cpu_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - -#ifndef TARGET_PYNQ_Z2 - // Power-gate and wake-up due to plic - bool state = false; - plic_irq_set_priority(GPIO_INTR_31, 1); - plic_irq_set_enabled(GPIO_INTR_31, kPlicToggleEnabled); - - gpio_cfg_t pin2_cfg = {.pin = GPIO_TB_IN, .mode = GpioModeIn,.en_input_sampling = true, - .en_intr = true, .intr_type = GpioIntrEdgeRising}; - gpio_config (pin2_cfg); - - gpio_cfg_t pin1_cfg = {.pin = GPIO_TB_OUT, .mode = GpioModeOutPushPull}; - gpio_config (pin1_cfg); - gpio_write(GPIO_TB_OUT, true); - - CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); - if (power_gate_core(&power_manager, kPlic_pm_e, &power_manager_cpu_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - - uint32_t intr_num; - plic_irq_complete(&intr_num); -#endif - - /* write something to stdout */ - PRINTF("Success.\n\r"); - return EXIT_SUCCESS; - -} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_gating_external/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_gating_external/main.c deleted file mode 100644 index 1ffc90c4..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_gating_external/main.c +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright EPFL contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "core_v_mini_mcu.h" -#include "power_manager.h" -#include "x-heep.h" - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -static power_manager_t power_manager; - -int main(int argc, char *argv[]) -{ - // Setup power_manager - mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); - power_manager.base_addr = power_manager_reg; - - power_manager_counters_t power_manager_external_counters; - - // Init ram block 2's counters - if (power_gate_counters_init(&power_manager_external_counters, 30, 30, 30, 30, 30, 30, 0, 0) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail. Check the reset and powergate counters value\n\r"); - return EXIT_FAILURE; - } - - // Power off external domain - if (power_gate_external(&power_manager, 0, kOff_e, &power_manager_external_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - - // Check that the external domain is actually OFF - while(!external_power_domain_is_off(&power_manager, 0)); - - // Wait some time - for (int i=0; i<100; i++) asm volatile("nop"); - - // Power on external domain - if (power_gate_external(&power_manager, 0, kOn_e, &power_manager_external_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - - /* write something to stdout */ - PRINTF("Success.\n\r"); - return EXIT_SUCCESS; - - return EXIT_FAILURE; -} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_gating_periph/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_gating_periph/main.c deleted file mode 100644 index fb51e1c7..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_gating_periph/main.c +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright EPFL contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "core_v_mini_mcu.h" -#include "power_manager.h" -#include "x-heep.h" - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -static power_manager_t power_manager; - -int main(int argc, char *argv[]) -{ - // Setup power_manager - mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); - power_manager.base_addr = power_manager_reg; - - power_manager_counters_t power_manager_periph_counters; - - // Init peripheral_subsystem's counters - if (power_gate_counters_init(&power_manager_periph_counters, 30, 30, 30, 30, 30, 30, 0, 0) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail. Check the reset and powergate counters value\n\r"); - return EXIT_FAILURE; - } - - // Power off peripheral_subsystem domain - if (power_gate_periph(&power_manager, kOff_e, &power_manager_periph_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - - // Check that the peripheral_subsystem domain is actually OFF - while(!periph_power_domain_is_off(&power_manager)); - - // Wait some time - for (int i=0; i<100; i++) asm volatile("nop;"); - - // Power on peripheral_subsystem domain - if (power_gate_periph(&power_manager, kOn_e, &power_manager_periph_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - - /* write something to stdout */ - PRINTF("Success.\n\r"); - return EXIT_SUCCESS; -} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_gating_ram_blocks/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_gating_ram_blocks/main.c deleted file mode 100644 index fe673403..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_gating_ram_blocks/main.c +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright EPFL contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "core_v_mini_mcu.h" -#include "power_manager.h" -#include "x-heep.h" - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -static power_manager_t power_manager; - -int main(int argc, char *argv[]) -{ - -#if MEMORY_BANKS > 2 - // Setup power_manager - mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); - power_manager.base_addr = power_manager_reg; - - power_manager_counters_t power_manager_ram_blocks_counters; - - // Init ram block 2's counters - if (power_gate_counters_init(&power_manager_ram_blocks_counters, 30, 30, 30, 30, 30, 30, 0, 0) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail. Check the reset and powergate counters value\n\r"); - return EXIT_FAILURE; - } - - // Power off ram block 2 domain - if (power_gate_ram_block(&power_manager, 2, kOff_e, &power_manager_ram_blocks_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - - // Check that the ram block 2 domain is actually OFF - while(!ram_block_power_domain_is_off(&power_manager, 2)); - - // Wait some time - for (int i=0; i<100; i++) asm volatile("nop"); - - // Power on ram block 2 domain - if (power_gate_ram_block(&power_manager, 2, kOn_e, &power_manager_ram_blocks_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - - /* write something to stdout */ - PRINTF("Success.\n\r"); - return EXIT_SUCCESS; - -#else - #pragma message ( "this application can run only when MEMORY_BANKS > 2" ) - return EXIT_SUCCESS; -#endif - -} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_manager/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_manager/main.c new file mode 100644 index 00000000..e1fe60e9 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_power_manager/main.c @@ -0,0 +1,463 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include "csr.h" +#include "hart.h" +#include "handler.h" +#include "core_v_mini_mcu.h" +#include "rv_timer.h" +#include "power_manager.h" +#include "soc_ctrl.h" +#include "rv_plic.h" +#include "rv_plic_regs.h" +#include "gpio.h" +#include "pad_control.h" +#include "pad_control_regs.h" +#include "x-heep.h" +#include "dma.h" + +#ifndef RV_PLIC_IS_INCLUDED + #error ( "This app does NOT work as the RV_PLIC peripheral is not included" ) +#endif + + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +static rv_timer_t timer_0_1; +static rv_timer_t timer_2_3; +static const uint64_t kTickFreqHz = 1000 * 1000; // 1 MHz +static power_manager_t power_manager; + +#ifndef TARGET_IS_FPGA + #define GPIO_TB_OUT 30 + #define GPIO_TB_IN 31 + #define GPIO_INTR GPIO_INTR_31 +#endif + +#define TEST_WORD +//this data has to be big to allow the CPU to power gate +#define TEST_DATA_SIZE 450 + +// Source and destination addresses have to be aligned on a 4 bytes address +uint32_t test_data_4B[TEST_DATA_SIZE] __attribute__ ((aligned (4))) = { 0 }; +uint32_t copied_data_4B[TEST_DATA_SIZE] __attribute__ ((aligned (4))) = { 0 }; + +uint8_t gpio_intr_flag = 0; + +void gpio_handler_in() +{ + gpio_intr_flag = 1; +} + +int main(int argc, char *argv[]) +{ + + // Setup power_manager + mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); + power_manager.base_addr = power_manager_reg; + power_manager_counters_t power_manager_counters; + //counters + uint32_t reset_off, reset_on, switch_off, switch_on, iso_off, iso_on; + + // Setup pads +#ifndef TARGET_IS_FPGA + pad_control_t pad_control; + pad_control.base_addr = mmio_region_from_addr((uintptr_t)PAD_CONTROL_START_ADDRESS); + pad_control_set_mux(&pad_control, (ptrdiff_t)(PAD_CONTROL_PAD_MUX_I2C_SCL_REG_OFFSET), 1); + pad_control_set_mux(&pad_control, (ptrdiff_t)(PAD_CONTROL_PAD_MUX_I2C_SDA_REG_OFFSET), 1); +#endif + + // Setup plic + plic_Init(); + + // Get current Frequency + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + uint32_t freq_hz = soc_ctrl_get_frequency(&soc_ctrl); + + // Setup rv_timer_0_1 + mmio_region_t timer_0_1_reg = mmio_region_from_addr(RV_TIMER_AO_START_ADDRESS); + rv_timer_init(timer_0_1_reg, (rv_timer_config_t){.hart_count = 2, .comparator_count = 1}, &timer_0_1); + rv_timer_tick_params_t tick_params; + rv_timer_approximate_tick_params(freq_hz, kTickFreqHz, &tick_params); + + // Setup rv_timer_2_3 + mmio_region_t timer_2_3_reg = mmio_region_from_addr(RV_TIMER_START_ADDRESS); + rv_timer_init(timer_2_3_reg, (rv_timer_config_t){.hart_count = 2, .comparator_count = 1}, &timer_2_3); + + // Init cpu_subsystem's counters + + //Turn off: first, isolate the CPU outputs, then I reset it, then I switch it off (reset and switch off order does not really matter) + iso_off = 10; + reset_off = iso_off + 5; + switch_off = reset_off + 5; + //Turn on: first, give back power by switching on, then deassert the reset, the unisolate the CPU outputs + switch_on = 10; + reset_on = switch_on + 20; //give 20 cycles to emulate the turn on time, this number depends on technology and here it is just a random number + iso_on = reset_on + 5; + + if (power_gate_counters_init(&power_manager_counters, reset_off, reset_on, switch_off, switch_on, iso_off, iso_on, 0, 0) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail. Check the reset and powergate counters value\n\r"); + return EXIT_FAILURE; + } + + // Power-gate and wake-up due to timer_0 + rv_timer_set_tick_params(&timer_0_1, 0, tick_params); + rv_timer_irq_enable(&timer_0_1, 0, 0, kRvTimerEnabled); + rv_timer_arm(&timer_0_1, 0, 0, 1024); + rv_timer_counter_set_enabled(&timer_0_1, 0, kRvTimerEnabled); + + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if (power_gate_core(&power_manager, kTimer_0_pm_e, &power_manager_counters) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail.\n\r"); + return EXIT_FAILURE; + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + + // Power-gate and wake-up due to timer_1 + rv_timer_set_tick_params(&timer_0_1, 1, tick_params); + rv_timer_irq_enable(&timer_0_1, 1, 0, kRvTimerEnabled); + rv_timer_arm(&timer_0_1, 1, 0, 1024); + rv_timer_counter_set_enabled(&timer_0_1, 1, kRvTimerEnabled); + + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if (power_gate_core(&power_manager, kTimer_1_pm_e, &power_manager_counters) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail.\n\r"); + return EXIT_FAILURE; + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + + // Power-gate and wake-up due to timer_2 + rv_timer_set_tick_params(&timer_2_3, 0, tick_params); + rv_timer_irq_enable(&timer_2_3, 0, 0, kRvTimerEnabled); + rv_timer_arm(&timer_2_3, 0, 0, 1024); + rv_timer_counter_set_enabled(&timer_2_3, 0, kRvTimerEnabled); + + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if (power_gate_core(&power_manager, kTimer_2_pm_e, &power_manager_counters) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail.\n\r"); + return EXIT_FAILURE; + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + + // Power-gate and wake-up due to timer_3 + rv_timer_set_tick_params(&timer_2_3, 1, tick_params); + rv_timer_irq_enable(&timer_2_3, 1, 0, kRvTimerEnabled); + rv_timer_arm(&timer_2_3, 1, 0, 1024); + rv_timer_counter_set_enabled(&timer_2_3, 1, kRvTimerEnabled); + + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if (power_gate_core(&power_manager, kTimer_3_pm_e, &power_manager_counters) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail.\n\r"); + return EXIT_FAILURE; + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + + // Power-gate and wake-up due to DMA + + //prepare data + for(int i=0; i 2 + // ------------ MEMORY SUBSYSTEM ------------ + PRINTF("Testing Memory Subsystem...\n\r"); + + // ------------ clock gating ------------ + // do not clock gate instruction and data memory (usually first 2 banks) + for(uint32_t i = 2; i < MEMORY_BANKS; ++i) + mmio_region_write32(power_manager.base_addr, (ptrdiff_t)(power_manager_ram_map[i].clk_gate), 0x1); + // Wait some time + for (int i=0; i<100; i++) asm volatile("nop;"); + // Enabling ram-banks + for(uint32_t i = 2; i < MEMORY_BANKS; ++i) + mmio_region_write32(power_manager.base_addr, (ptrdiff_t)(power_manager_ram_map[i].clk_gate), 0x0); + + PRINTF("Memory Clock Gating Test Successefull\n\r"); + + // ------------ power gating ------------ + if (power_gate_counters_init(&power_manager_counters, 30, 30, 30, 30, 30, 30, 0, 0) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail. Check the reset and powergate counters value\n\r"); + return EXIT_FAILURE; + } + // Power off ram block 2 domain + if (power_gate_ram_block(&power_manager, 2, kOff_e, &power_manager_counters) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail.\n\r"); + return EXIT_FAILURE; + } + // Check that the ram block 2 domain is actually OFF + while(!ram_block_power_domain_is_off(&power_manager, 2)); + + // Wait some time + for (int i=0; i<100; i++) asm volatile("nop"); + // Power on ram block 2 domain + if (power_gate_ram_block(&power_manager, 2, kOn_e, &power_manager_counters) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail.\n\r"); + return EXIT_FAILURE; + } + + PRINTF("Memory Power Gating Test Successefull\n\r"); + + // ------------ set retentive ------------ + if (power_gate_counters_init(&power_manager_counters, 0, 0, 0, 0, 0, 0, 30, 30) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail. Check the reset and powergate counters value\n\r"); + return EXIT_FAILURE; + } + // Set retention mode on for ram block 2 domain + if (power_gate_ram_block(&power_manager, 2, kRetOn_e, &power_manager_counters) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail.\n\r"); + return EXIT_FAILURE; + } + // Wait some time + for (int i=0; i<100; i++) asm volatile("nop"); + // Set retention mode off for ram block 2 domain + if (power_gate_ram_block(&power_manager, 2, kRetOff_e, &power_manager_counters) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail.\n\r"); + return EXIT_FAILURE; + } + + PRINTF("Memory Set Retentive Test Successefull\n\r"); + + +#else + #pragma message ( "the memory test can only run if MEMORY_BANKS > 2" ) +#endif + +#if EXTERNAL_DOMAINS > 0 + + // ------------ External SUBSYSTEM ------------ + PRINTF("Testing External Domain Subsystems...\n\r"); + + // ------------ clock gating ------------ + for(uint32_t i = 0; i < EXTERNAL_DOMAINS; ++i) + mmio_region_write32(power_manager.base_addr, (ptrdiff_t)(power_manager_external_map[i].clk_gate), 0x1); + // Wait some time + for (int i=0; i<100; i++) asm volatile("nop;"); + // Enabling external subsystems + for(uint32_t i = 0; i < EXTERNAL_DOMAINS; ++i) + mmio_region_write32(power_manager.base_addr, (ptrdiff_t)(power_manager_external_map[i].clk_gate), 0x0); + + PRINTF("External Clock Gating Test Successefull\n\r"); + + // ------------ power gating domain 0 ------------ + if (power_gate_counters_init(&power_manager_counters, 30, 30, 30, 30, 30, 30, 0, 0) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail. Check the reset and powergate counters value\n\r"); + return EXIT_FAILURE; + } + // Power off external domain + if (power_gate_external(&power_manager, 0, kOff_e, &power_manager_counters) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail.\n\r"); + return EXIT_FAILURE; + } + // Check that the external domain is actually OFF + while(!external_power_domain_is_off(&power_manager, 0)); + // Wait some time + for (int i=0; i<100; i++) asm volatile("nop"); + // Power on external domain + if (power_gate_external(&power_manager, 0, kOn_e, &power_manager_counters) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail.\n\r"); + return EXIT_FAILURE; + } + + PRINTF("External Power Gating Test Successefull\n\r"); + + // ------------ set retentive domain 0------------ + if (power_gate_counters_init(&power_manager_counters, 0, 0, 0, 0, 0, 0, 30, 30) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail. Check the reset and powergate counters value\n\r"); + return EXIT_FAILURE; + } + // Set retention mode on for external domain block 0 + if (power_gate_external(&power_manager, 0, kRetOn_e, &power_manager_counters) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail.\n\r"); + return EXIT_FAILURE; + } + // Wait some time + for (int i=0; i<100; i++) asm volatile("nop"); + // Set retention mode off for external domain block 0 + if (power_gate_external(&power_manager, 0, kRetOff_e, &power_manager_counters) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail.\n\r"); + return EXIT_FAILURE; + } + + PRINTF("External Set Retentive Test Successefull\n\r"); +#else + #pragma message ( "the external domain test can only run if EXTERNAL_DOMAINS > 0" ) +#endif + return EXIT_SUCCESS; + +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_sdk_spi_flash/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_sdk_spi_flash/main.c new file mode 100644 index 00000000..226a2a02 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_sdk_spi_flash/main.c @@ -0,0 +1,353 @@ +/** + * @file main.c + * @brief Simple spi communication example using SDK + * + * Simple example that reads a sector (4096 Bytes) from flash, overwrites the + * specified location range with new data, erases that sector from flash, writes + * the modified sector back to the flash and finally reads the modified location + * range directly from the flash to verify the operation has succeeded. + * + * The flash device being used is the w25q128jw + * +*/ + +#include +#include +#include +#include + +#include "x-heep.h" +#include "core_v_mini_mcu.h" +#include "spi_sdk.h" + +#include "fast_intr_ctrl.h" +#include "csr.h" +#include "csr_registers.h" + +/* By default, PRINTFs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif TARGET_IS_FPGA && PRINTF_IN_FPGA + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +#ifdef TARGET_IS_FPGA + #define USE_SPI_FLASH +#endif + +// =========================== VARS & DEFS ================================== + +// 1 to print the modified data at the end of program 0 to disable +#define PRINT_DATA 1 + +// Flash w25q128jw SPI commands +#define FC_WE 0x06 /** Write Enable */ +#define FC_RD 0x03 /** Read Data */ +#define FC_PP 0x02 /** Page Program */ +#define FC_SE 0x20 /** Sector Erase 4kb */ +#define FC_RSR1 0x05 /** Read Status Register 1 */ + +#define READ_WRITE_LEN 16 // Amount words to read/write +#define START_ADDRESS ((FLASH_MEM_SIZE / 2) + 256) // Flash address where read/write +#define SECT_ADDRESS (START_ADDRESS & 0xfffff000) // Start sector address +#define SECT_LEN 4096 // Length bytes of a sector +#define PAGE_LEN 256 // Length bytes of a page +#define FLASH_MAX_FREQ (133*1000*1000) // Device max spi frequency +#define FIC_FLASH_MEIE 21 // SPI Flash fast interrupt bit enable +#define CSR_INTR_EN 0x08 // CPU Global interrupt enable + +// Hold sector data +uint8_t sect_data[SECT_LEN]; + +// Data to write +uint32_t flash_original_1024B[PAGE_LEN] = { + 0x76543211, 0xfedcba99, 0x579a6f91, 0x657d5bef, 0x758ee420, 0x01234568, 0xfedbca97, 0x89abde00, + 0x76543212, 0xfedcba9a, 0x579a6f92, 0x657d5bf0, 0x758ee421, 0x01234569, 0xfedbca98, 0x89abde01, + 0x76543213, 0xfedcba9b, 0x579a6f93, 0x657d5bf1, 0x758ee422, 0x0123456a, 0xfedbca99, 0x89abde02, + 0x76543214, 0xfedcba9c, 0x579a6f94, 0x657d5bf2, 0x758ee423, 0x0123456b, 0xfedbca9a, 0x89abde03, + 0x76543215, 0xfedcba9d, 0x579a6f95, 0x657d5bf3, 0x758ee424, 0x0123456c, 0xfedbca9b, 0x89abde04, + 0x76543216, 0xfedcba9e, 0x579a6f96, 0x657d5bf4, 0x758ee425, 0x0123456d, 0xfedbca9c, 0x89abde05, + 0x76543217, 0xfedcba9f, 0x579a6f97, 0x657d5bf5, 0x758ee426, 0x0123456e, 0xfedbca9d, 0x89abde06, + 0x76543218, 0xfedcbaa0, 0x579a6f98, 0x657d5bf6, 0x758ee427, 0x0123456f, 0xfedbca9e, 0x89abde07, + 0x76543219, 0xfedcbaa1, 0x579a6f99, 0x657d5bf7, 0x758ee428, 0x01234570, 0xfedbca9f, 0x89abde08, + 0x7654321a, 0xfedcbaa2, 0x579a6f9a, 0x657d5bf8, 0x758ee429, 0x01234571, 0xfedbcaa0, 0x89abde09, + 0x7654321b, 0xfedcbaa3, 0x579a6f9b, 0x657d5bf9, 0x758ee42a, 0x01234572, 0xfedbcaa1, 0x89abde0a, + 0x7654321c, 0xfedcbaa4, 0x579a6f9c, 0x657d5bfa, 0x758ee42b, 0x01234573, 0xfedbcaa2, 0x89abde0b, + 0x7654321d, 0xfedcbaa5, 0x579a6f9d, 0x657d5bfb, 0x758ee42c, 0x01234574, 0xfedbcaa3, 0x89abde0c, + 0x7654321e, 0xfedcbaa6, 0x579a6f9e, 0x657d5bfc, 0x758ee42d, 0x01234575, 0xfedbcaa4, 0x89abde0d, + 0x7654321f, 0xfedcbaa7, 0x579a6f9f, 0x657d5bfd, 0x758ee42e, 0x01234576, 0xfedbcaa5, 0x89abde0e, + 0x76543220, 0xfedcbaa8, 0x579a6fa0, 0x657d5bfe, 0x758ee42f, 0x01234577, 0xfedbcaa6, 0x89abde0f, + 0x76543221, 0xfedcbaa9, 0x579a6fa1, 0x657d5bff, 0x758ee430, 0x01234578, 0xfadbcaa7, 0x89abde10, + 0x76543222, 0xfedcbaaa, 0x579a6fa2, 0x657d5c00, 0x758ee431, 0x01234579, 0xfadbcaa8, 0x89abde11, + 0x76543223, 0xfedcbaab, 0x579a6fa3, 0x657d5c01, 0x758ee432, 0x0123457a, 0xfadbcaa9, 0x89abde12, + 0x76543224, 0xfedcbaac, 0x579a6fa4, 0x657d5c02, 0x758ee433, 0x0123457b, 0xfadbcaaa, 0x89abde13, + 0x76543225, 0xfedcbaad, 0x579a6fa5, 0x657d5c03, 0x758ee434, 0x0123457c, 0xfadbcaab, 0x89abde14, + 0x76543226, 0xfedcbaae, 0x579a6fa6, 0x657d5c04, 0x758ee435, 0x0123457d, 0xfadbcaac, 0x89abde15, + 0x76543227, 0xfedcbaaf, 0x579a6fa7, 0x657d5c05, 0x758ee436, 0x0123457e, 0xfadbcaad, 0x89abde16, + 0x76543228, 0xfedcbab0, 0x579a6fa8, 0x657d5c06, 0x758ee437, 0x0123457f, 0xfadbcaae, 0x89abde17, + 0x76543220, 0xfedcbaa8, 0x579a6fa0, 0x657d5bfe, 0x758ee42f, 0x01234577, 0xfedbcaa6, 0x89abde0f, + 0x76543221, 0xfedcbaa9, 0x579a6fa1, 0x657d5bff, 0x758ee430, 0x01234578, 0xfadbcaa7, 0x89abde10, + 0x76543222, 0xfedcbaaa, 0x579a6fa2, 0x657d5c00, 0x758ee431, 0x01234579, 0xfadbcaa8, 0x89abde11, + 0x76543223, 0xfedcbaab, 0x579a6fa3, 0x657d5c01, 0x758ee432, 0x0123457a, 0xfadbcaa9, 0x89abde12, + 0x76543224, 0xfedcbaac, 0x579a6fa4, 0x657d5c02, 0x758ee433, 0x0123457b, 0xfadbcaaa, 0x89abde13, + 0x76543225, 0xfedcbaad, 0x579a6fa5, 0x657d5c03, 0x758ee434, 0x0123457c, 0xfadbcaab, 0x89abde14, + 0x76543226, 0xfedcbaae, 0x579a6fa6, 0x657d5c04, 0x758ee435, 0x0123457d, 0xfadbcaac, 0x89abde15, + 0x76543227, 0xfedcbaaf, 0x579a6fa7, 0x657d5c05, 0x758ee436, 0x0123457e, 0xfadbcaad, 0x89abde16, + 0x76543228, 0xfedcbab0, 0x579a6fa8, 0x657d5c06, 0x758ee437, 0x0123457f, 0xfadbcaae, 0x89abde17 +}; + +// ====================== PROTOTYPES ====================== + +bool flash_read(spi_t* spi, uint32_t addr, uint32_t* dest_buff, uint32_t len); +bool flash_read_non_blocking(spi_t* spi, uint32_t addr, uint32_t* dest_buff, uint32_t len); +bool flash_write_enable(spi_t* spi); +bool flash_erase_sector(spi_t* spi, uint32_t addr); +bool flash_write_sector(spi_t* spi, uint32_t addr, uint32_t* src_buff); +void flash_wait(spi_t* spi); + +void done_cb(const uint32_t* txbuff, uint32_t txlen, uint32_t* rxbuff, uint32_t rxlen); +void rxwm_cb(const uint32_t* txbuff, uint32_t txlen, uint32_t* rxbuff, uint32_t rxlen); + +// ========================= MAIN ========================= + +int main(int argc, char *argv[]) { + // Create our slave (flash device) with its specifications + spi_slave_t slave = SPI_SLAVE(0, FLASH_MAX_FREQ); + + // Initialize the spi device that is CONNECTED to the flash with our slave + #ifdef USE_SPI_FLASH + spi_t spi = spi_init(SPI_IDX_FLASH, slave); + #else + spi_t spi = spi_init(SPI_IDX_HOST, slave); + #endif + + // Check if initialization succeeded + if (!spi.init) { + PRINTF("\nFailed to initialize spi\n"); + return EXIT_FAILURE; + } + + PRINTF("\nSPI initialized\n"); + + // Enable global interrupt for machine-level interrupts + CSR_SET_BITS(CSR_REG_MSTATUS, CSR_INTR_EN); + // Set mie.MEIE bit to one to enable machine-level fast spi_flash interrupt + const uint32_t mask = 1 << FIC_FLASH_MEIE; + CSR_SET_BITS(CSR_REG_MIE, mask); + + // Buffer to hold data for final comparison + uint32_t rxbuffer[READ_WRITE_LEN] = {0}; + + // Read whole sector containing the desired START_ADDRESS + if (!flash_read_non_blocking(&spi, SECT_ADDRESS, sect_data, SECT_LEN)) + return EXIT_FAILURE; + + // No need to erase if on simulation + #ifdef USE_SPI_FLASH + // Erase that sector + if (!flash_erase_sector(&spi, START_ADDRESS)) return EXIT_FAILURE; + #endif + + // Copy the data to overwrite + memcpy(§_data[START_ADDRESS - SECT_ADDRESS], flash_original_1024B, READ_WRITE_LEN * 4); + // Write the whole sector with the new data back to flash + if (!flash_write_sector(&spi, START_ADDRESS, sect_data)) return EXIT_FAILURE; + // Read the modified part + if (!flash_read(&spi, START_ADDRESS, rxbuffer, 4*READ_WRITE_LEN)) return EXIT_FAILURE; + + // Compare the modified part with the data used to modify + if (memcmp(rxbuffer, flash_original_1024B, 4*READ_WRITE_LEN)) + PRINTF("\nMISMATCH\n\n"); + else PRINTF("\nSUCCESS\n\n"); + + // If wanted display the data + #if PRINT_DATA + PRINTF(" address original on flash\n"); + PRINTF("-------------------------------\n"); + for (int i = 0; i < READ_WRITE_LEN; i++) + { + PRINTF("0x%08X: %08X %08X\n", START_ADDRESS+4*i, flash_original_1024B[i], rxbuffer[i]); + } + #endif + + PRINTF("\n==================================================\n\n"); + + + return EXIT_SUCCESS; +} + +// ========================= FUNCTIONS ========================= + +bool flash_read(spi_t* spi, uint32_t addr, uint32_t* dest_buff, uint32_t len) { + // Transaction segments + spi_segment_t segments[2] = { SPI_SEG_TX(4), SPI_SEG_RX(len) }; + + // TX SPI command to send to flash for read + // Flash uses Big Endian, CPU Little Endian, hence swap bytes + uint32_t read_byte_cmd = ((bitfield_byteswap32(addr & 0x00ffffff)) | FC_RD); + + PRINTF("Blocking Reading %4i Bytes at 0x%08X\n", len, addr); + + // Start transaction + spi_codes_e error = spi_execute(spi, segments, 2, &read_byte_cmd, dest_buff); + if (error) { + PRINTF("FAILED! Error Code: %i\n", error); + return false; + } + return true; +} + +bool flash_read_non_blocking(spi_t* spi, uint32_t addr, uint32_t* dest_buff, uint32_t len) { + // Transaction segments + spi_segment_t segments[2] = { SPI_SEG_TX(4), SPI_SEG_RX(len) }; + + // TX SPI command to send to flash for read + // Flash uses Big Endian, CPU Little Endian, hence swap bytes + uint32_t read_byte_cmd = ((bitfield_byteswap32(addr & 0x00ffffff)) | FC_RD); + + PRINTF("\nNon-Blocking Reading %4i Bytes at 0x%08X\n", len, addr); + PRINTF("Counter set to 0.\n"); + + uint32_t counter = 0; + spi_callbacks_t callbacks = { + .done_cb = &done_cb, + .error_cb = NULL,//&done_cb, + .rxwm_cb = &rxwm_cb, + .txwm_cb = NULL + }; + + // Save previous watermark to reset it after transaction completes + uint8_t watermark; + spi_get_rxwm(spi, &watermark); + spi_set_rxwm(spi, 12); // Arbitrarily chosen watermark + + // Start transaction + spi_codes_e error = spi_execute_nb(spi, segments, 2, &read_byte_cmd, dest_buff, callbacks); + if (error) { + PRINTF("FAILED! Error Code: %i\n", error); + return false; + } + + while(spi_get_state(spi) == SPI_STATE_BUSY) counter++; + // Check if the communication ended because of an error + if (spi_get_state(spi) == SPI_STATE_ERROR) { + PRINTF("FAILED! Hardware ERROR !\n"); + return false; + } + + // Reset the watermark to its previous value + spi_set_rxwm(spi, watermark); + + PRINTF("Counter reached %4i. => Non Blocking\n\n", counter); + + return true; +} + +bool flash_erase_sector(spi_t* spi, uint32_t addr) { + // Sector start address + const uint32_t sect_start = addr & 0xfffff000; + // Sector erase command + // Flash uses Big Endian, CPU Little Endian, hence swap bytes + const uint32_t cmd = ((bitfield_byteswap32(sect_start & 0x00ffffff)) | FC_SE); + + PRINTF("Blocking Erasing 4096 Bytes at 0x%08X\n", sect_start); + + // Enable write before erase + if (!flash_write_enable(spi)) return false; + + // Start TX Only transaction + spi_codes_e error = spi_transmit(spi, &cmd, 4); + if (error) { + PRINTF("FAILED! Error Code: %i\n", error); + return false; + } + + // Wait flash finished processing + flash_wait(spi); + + return true; +} + +bool flash_write_sector(spi_t* spi, uint32_t addr, uint32_t* src_buff) { + // Sector start address + uint32_t sect = addr & 0xfffff000; + // Current page (256 bytes) address (can't write more than one page at a time...) + uint32_t curr_addr = sect; + + for (int i = 0; i < SECT_LEN / PAGE_LEN; i++) + { + // Our TX Buffer + uint32_t wbuff[PAGE_LEN/4 + 1] = {0}; + // Our segments for the SPI transaction + spi_segment_t segments[2] = { SPI_SEG_TX(4), SPI_SEG_TX(PAGE_LEN) }; + + // Flash uses Big Endian, CPU Little Endian, hence swap bytes + wbuff[0] = ((bitfield_byteswap32(curr_addr & 0x00ffffff)) | FC_PP); + memcpy(&wbuff[1], &src_buff[i * (PAGE_LEN/4)], PAGE_LEN); + + if (!flash_write_enable(spi)) return false; + + // Start transaction + // Note that since segments are only TX we could have used spi_transmit + // instead of spi_execute, but both work perfectly fine + spi_codes_e error = spi_execute(spi, segments, 2, wbuff, NULL); + if (error) { + PRINTF("FAILED! Error Code: %i\n", error); + return false; + } + curr_addr += PAGE_LEN; + + PRINTF("\rBlocking Written %4i/4096 Bytes at 0x%08X", (i+1) * PAGE_LEN, sect); + + // Wait flash finished processing + flash_wait(spi); + } + + PRINTF("\n"); + + return true; +} + +bool flash_write_enable(spi_t* spi) { + // SPI Flash command + const uint32_t cmd = FC_WE; + // Start TX Only transaction + spi_codes_e error = spi_transmit(spi, &cmd, 1); + if (error) { + PRINTF("FAILED! Error Code: %i\n", error); + return false; + } + return true; +} + +void flash_wait(spi_t* spi) { + // Response buffer + uint32_t resp; + // SPI Flash command + uint32_t cmd = FC_RSR1; + // Here we have to use segments and execute since our transaction is composed + // of a TX Only part and thereafter a RX Only + spi_segment_t segments[2] = {SPI_SEG_TX(1), SPI_SEG_RX(2)}; + // Flash busy flag + bool busy = true; + while (busy) + { + spi_execute(spi, segments, 2, &cmd, &resp); + busy = resp & 0x01; + } +} + +void done_cb(const uint32_t* txbuff, uint32_t txlen, uint32_t* rxbuff, uint32_t rxlen) { + PRINTF("\x1b[33mTXN DONE CALLBACK with txlen: %i, rxlen: %i\x1b[m\n", txlen, rxlen); +} + +void rxwm_cb(const uint32_t* txbuff, uint32_t txlen, uint32_t* rxbuff, uint32_t rxlen) { + PRINTF("\x1b[36mTXN RXWM CALLBACK with txlen: %i, rxlen: %i\x1b[m\n", txlen, rxlen); +} + +// ========================= THE END ========================= \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_set_retentive_ram_blocks/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_set_retentive_ram_blocks/main.c deleted file mode 100644 index cde898ad..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_set_retentive_ram_blocks/main.c +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright EPFL contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "core_v_mini_mcu.h" -#include "power_manager.h" -#include "x-heep.h" - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -static power_manager_t power_manager; - -int main(int argc, char *argv[]) -{ -#if MEMORY_BANKS > 2 - // Setup power_manager - mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); - power_manager.base_addr = power_manager_reg; - - power_manager_counters_t power_manager_ram_blocks_counters; - - // Init ram block 2's counters - if (power_gate_counters_init(&power_manager_ram_blocks_counters, 0, 0, 0, 0, 0, 0, 30, 30) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail. Check the reset and powergate counters value\n\r"); - return EXIT_FAILURE; - } - - // Set retention mode on for ram block 2 domain - if (power_gate_ram_block(&power_manager, 2, kRetOn_e, &power_manager_ram_blocks_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - - // Wait some time - for (int i=0; i<100; i++) asm volatile("nop"); - - // Set retention mode off for ram block 2 domain - if (power_gate_ram_block(&power_manager, 2, kRetOff_e, &power_manager_ram_blocks_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - - /* write something to stdout */ - PRINTF("Success.\n\r"); - return EXIT_SUCCESS; - -#else - #pragma message ( "this application can run only when MEMORY_BANKS > 2" ) - return EXIT_SUCCESS; -#endif - -} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_set_retentive_ram_blocks_external/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_set_retentive_ram_blocks_external/main.c deleted file mode 100644 index 7b455591..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_set_retentive_ram_blocks_external/main.c +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright EPFL contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "core_v_mini_mcu.h" -#include "power_manager.h" -#include "x-heep.h" - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -static power_manager_t power_manager; - -int main(int argc, char *argv[]) -{ - // Setup power_manager - mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); - power_manager.base_addr = power_manager_reg; - - power_manager_counters_t power_manager_external_ram_blocks_counters; - - // Init external ram block 0's counters - if (power_gate_counters_init(&power_manager_external_ram_blocks_counters, 0, 0, 0, 0, 0, 0, 30, 30) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail. Check the reset and powergate counters value\n\r"); - return EXIT_FAILURE; - } - - // Set retention mode on for external ram block 0 - if (power_gate_external(&power_manager, 0, kRetOn_e, &power_manager_external_ram_blocks_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - - // Wait some time - for (int i=0; i<100; i++) asm volatile("nop"); - - // Set retention mode off for external ram block 0 - if (power_gate_external(&power_manager, 0, kRetOff_e, &power_manager_external_ram_blocks_counters) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail.\n\r"); - return EXIT_FAILURE; - } - - /* write something to stdout */ - PRINTF("Success.\n\r"); - return EXIT_SUCCESS; -} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_simple_accelerator/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_simple_accelerator/main.c new file mode 100644 index 00000000..53fb896b --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_simple_accelerator/main.c @@ -0,0 +1,85 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include + +#include "core_v_mini_mcu.h" +#include "x-heep.h" + +#define TEST_DATA_SIZE 16 + +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + + +int32_t errors = 0; + +//defined in the testharness_pkg.sv +#define SIMPLE_ACC_START_ADDRESS EXT_PERIPHERAL_START_ADDRESS + 0x3000; + +// Simple accelerator Decoder (address for bytes) +//0 READ ADDRESS +#define SIMPLE_ACC_READ_OFFSET 0 +//4 WRITE ADDRESS +#define SIMPLE_ACC_WRITE_OFFSET 1 +//8 THRESHOLD +#define SIMPLE_ACC_THRESHOLD_OFFSET 2 +//C READY +#define SIMPLE_ACC_READY_OFFSET 3 +//10 SIZE +#define SIMPLE_ACC_SIZE_OFFSET 4 +//14 START +#define SIMPLE_ACC_START_OFFSET 5 + + + +int main(int argc, char *argv[]) +{ + + static uint32_t source_data[TEST_DATA_SIZE] __attribute__ ((aligned (4))); + static uint32_t copied_data[TEST_DATA_SIZE] __attribute__ ((aligned (4))); + uint32_t threshold_value = 20; + volatile static uint32_t *simple_acc = SIMPLE_ACC_START_ADDRESS; + + + for(int i=0;i threshold_value ? source_data[i] : threshold_value; + if(copied_data[i] != expected_data){ + errors++; + PRINTF("copied_data[%d] is %d, expected %d\n\r",i,copied_data[i], expected_data); + } + } + + if (errors == 0) { + PRINTF("Simple Accelerator Successful\n\r"); + return EXIT_SUCCESS; + } else { + PRINTF("Simple Accelerator failure: %d errors out of %d data checked\n\r", errors, TEST_DATA_SIZE ); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_flash_write/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_flash_write/main.c deleted file mode 100644 index a3d273e7..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_flash_write/main.c +++ /dev/null @@ -1,490 +0,0 @@ -// Copyright EPFL contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include - -#include "core_v_mini_mcu.h" -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "rv_plic.h" -#include "rv_plic_regs.h" -#include "soc_ctrl.h" -#include "spi_host.h" -#include "dma.h" -#include "fast_intr_ctrl.h" -#include "fast_intr_ctrl_regs.h" -#include "x-heep.h" - - -#ifdef TARGET_PYNQ_Z2 - #define USE_SPI_FLASH -#endif -/* Test Configurations */ -#define TEST_CIRCULAR -#define TEST_MEM_2_SPI -#define TEST_SPI_2_MEM - -// These defines are used only to easily change the data types. -// If not needed, the proper way is using the dma_data_type_t enum. -#define TEST_DATA_TYPE DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD - -#if TEST_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD -#define DATA_TYPE uint8_t -#elif TEST_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_16BIT_WORD -#define DATA_TYPE uint16_t -#else -#define DATA_TYPE uint32_t -#endif - - -#ifdef TEST_CIRCULAR -// WARNING: When using circular mode the amount of WORDS of each cycle needs to be 32 <= x <= 128 - #define CIRCULAR_CYCLES 4 - #define COPY_DATA_UNITS 256 - #define COPY_DATA_PER_CYCLE ( COPY_DATA_UNITS / CIRCULAR_CYCLES )// Flash page size = 256 Bytes -#else - #define COPY_DATA_UNITS 64 - #define COPY_DATA_PER_CYCLE COPY_DATA_UNITS -#endif //TEST_CIRCULAR - -#define REVERT_24b_ADDR(addr) ((((uint32_t)addr & 0xff0000) >> 16) | ((uint32_t)addr & 0xff00) | (((uint32_t)addr & 0xff) << 16)) - -#define FLASH_ADDR 0x00008500 // 256B data alignment - -#define FLASH_CLK_MAX_HZ (133*1000*1000) // In Hz (133 MHz for the flash w25q128jvsim used in the EPFL Programmer) - - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -int8_t spi_intr_flag; -spi_host_t spi_host; -int8_t cycles; - -// Reserve memory array -DATA_TYPE flash_data[COPY_DATA_UNITS] __attribute__ ((aligned (DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE)))) = { 0 }; -DATA_TYPE copy_data [COPY_DATA_UNITS] __attribute__ ((aligned (DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE)))) = { 0 }; - -DATA_TYPE *fifo_ptr_tx; -DATA_TYPE *fifo_ptr_rx; - -#ifndef USE_SPI_FLASH -void fic_irq_spi(void) -{ - // Disable SPI interrupts - spi_enable_evt_intr(&spi_host, false); - spi_enable_rxwm_intr(&spi_host, false); - spi_intr_flag = 1; -} -#else -void fic_irq_spi_flash(void) -{ - // Disable SPI interrupts - // PRINTF("&"); - spi_enable_evt_intr(&spi_host, false); - spi_enable_rxwm_intr(&spi_host, false); - spi_intr_flag = 1; -} -#endif //USE_SPI_FLASH - -#ifdef TEST_CIRCULAR -void dma_intr_handler_trans_done(void) -{ - PRINTF("#"); - cycles++; - if( cycles >= CIRCULAR_CYCLES -1 ) dma_stop_circular(); -} -#else -void dma_intr_handler_trans_done(void) -{ - PRINTF("#"); -} -#endif - -static inline __attribute__((always_inline)) void spi_config() -{ - -/* -* SPI CONFIGURATIONS -*/ -#ifndef USE_SPI_FLASH - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); -#else - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_FLASH_START_ADDRESS); -#endif //USE_SPI_FLASH - - soc_ctrl_t soc_ctrl; - soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - uint32_t core_clk = soc_ctrl_get_frequency(&soc_ctrl); - - // Enable interrupt on processor side - // Enable global interrupt for machine-level interrupts - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - // Set mie.MEIE bit to one to enable machine-level fast spi interrupt - - -#ifndef USE_SPI_FLASH - const uint32_t mask = 1 << 20; -#else - const uint32_t mask = 1 << 21; -#endif - CSR_SET_BITS(CSR_REG_MIE, mask); - spi_intr_flag = 0; - -#ifdef USE_SPI_FLASH - // Select SPI host as SPI output - soc_ctrl_select_spi_host(&soc_ctrl); -#endif // USE_SPI_FLASH - - - CSR_SET_BITS(CSR_REG_MIE, mask); - - // Enable SPI host device - spi_set_enable(&spi_host, true); - // Enable SPI output - spi_output_enable(&spi_host, true); - - // SPI and SPI_FLASH are the same IP so same register map - fifo_ptr_tx = spi_host.base_addr.base + SPI_HOST_TXDATA_REG_OFFSET; - fifo_ptr_rx = spi_host.base_addr.base + SPI_HOST_RXDATA_REG_OFFSET; - - // Configure SPI clock - // SPI clk freq = 1/2 core clk freq when clk_div = 0 - // SPI_CLK = CORE_CLK/(2 + 2 * CLK_DIV) <= CLK_MAX => CLK_DIV > (CORE_CLK/CLK_MAX - 2)/2 - uint16_t clk_div = 0; - if(FLASH_CLK_MAX_HZ < core_clk/2){ - clk_div = (core_clk/(FLASH_CLK_MAX_HZ) - 2)/2; // The value is truncated - if (core_clk/(2 + 2 * clk_div) > FLASH_CLK_MAX_HZ) clk_div += 1; // Adjust if the truncation was not 0 - } - // SPI Configuration - // Configure chip 0 (flash memory) - const uint32_t chip_cfg = spi_create_configopts((spi_configopts_t){ - .clkdiv = clk_div, - .csnidle = 0xF, - .csntrail = 0xF, - .csnlead = 0xF, - .fullcyc = false, - .cpha = 0, - .cpol = 0 - }); - spi_set_configopts(&spi_host, 0, chip_cfg); - spi_set_csid(&spi_host, 0); - - // Reset - const uint32_t reset_cmd = 0xFFFFFFFF; - spi_write_word(&spi_host, reset_cmd); - const uint32_t cmd_reset = spi_create_command((spi_command_t){ - .len = 3, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_reset); - spi_wait_for_ready(&spi_host); - spi_set_rx_watermark(&spi_host,1); - - // Power up flash - const uint32_t powerup_byte_cmd = 0xab; - spi_write_word(&spi_host, powerup_byte_cmd); - const uint32_t cmd_powerup = spi_create_command((spi_command_t){ - .len = 0, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_powerup); - spi_wait_for_ready(&spi_host); - - // Write enable - const uint32_t write_enable_cmd = 0x06; - spi_write_word(&spi_host, write_enable_cmd); - const uint32_t cmd_write_en = spi_create_command((spi_command_t){ - .len = 0, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_write_en); - spi_wait_for_ready(&spi_host); - - // Write command - const uint32_t write_byte_cmd = ((FLASH_ADDR << 8) | 0x02); // Program Page + addr - spi_write_word(&spi_host, write_byte_cmd); - const uint32_t cmd_write = spi_create_command((spi_command_t){ - .len = 3, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_write); - spi_wait_for_ready(&spi_host); - -} - - -static inline __attribute__((always_inline)) void spi_wait_4_resp() -{ - // Check status register status waiting for ready - bool flash_busy = true; - uint8_t flash_resp[4] = {0xff,0xff,0xff,0xff}; - while(flash_busy){ - uint32_t flash_cmd = 0x00000005; // [CMD] Read status register - spi_write_word(&spi_host, flash_cmd); // Push TX buffer - uint32_t spi_status_cmd = spi_create_command((spi_command_t){ - .len = 0, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - uint32_t spi_status_read_cmd = spi_create_command((spi_command_t){ - .len = 0, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirRxOnly - }); - spi_set_command(&spi_host, spi_status_cmd); - spi_wait_for_ready(&spi_host); - spi_set_command(&spi_host, spi_status_read_cmd); - spi_wait_for_ready(&spi_host); - spi_wait_for_rx_watermark(&spi_host); - spi_read_word(&spi_host, &flash_resp[0]); - if ((flash_resp[0] & 0x01) == 0) flash_busy = false; - } -} - -int main(int argc, char *argv[]) -{ - -#ifdef TARGET_SIM - #pragma message("This app does not allow Flash write operations in simulation!") - PRINTF("Flash writes are not permitted during Simulation, only on FPGA\n"); - return EXIT_SUCCESS; -#endif - - soc_ctrl_t soc_ctrl; - soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - -#ifdef USE_SPI_FLASH - if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) - { - PRINTF("This application cannot work with the memory mapped SPI FLASH module - do not use the FLASH_EXEC linker script for this application\n"); - return EXIT_SUCCESS; - } -#endif - spi_config(); - dma_init(NULL); - - dma_config_flags_t res; - - for( DATA_TYPE i = 0; i < COPY_DATA_PER_CYCLE; i ++ ) - { - ((DATA_TYPE*)flash_data)[i] = (DATA_TYPE) i; - } - -#ifdef TEST_MEM_2_SPI - - PRINTF("\n\n\r======================================\n\n\r"); - PRINTF(" MEM -> -> DMA -> -> SPI -> -> FLASH "); - PRINTF("\n\n\r======================================\n\n\r"); - -#ifndef USE_SPI_FLASH - const uint8_t slot = DMA_TRIG_SLOT_SPI_TX; // The DMA will wait for the SPI TX FIFO ready signal -#else - const uint8_t slot = DMA_TRIG_SLOT_SPI_FLASH_TX; // The DMA will wait for the SPI FLASH TX FIFO ready signal -#endif //USE_SPI_FLASH - - static dma_target_t tgt1= { - .ptr = flash_data, - .inc_du = 1, - .size_du = COPY_DATA_PER_CYCLE, - .trig = DMA_TRIG_MEMORY, - .type = TEST_DATA_TYPE, - }; - - static dma_target_t tgt2= { - .inc_du = 0, - .size_du = COPY_DATA_PER_CYCLE, - .trig = slot, - .type = TEST_DATA_TYPE, - }; - - tgt2.ptr = fifo_ptr_tx; // This is necessary because fifo_ptr_tx is not a constant, and therefore cannot be used as initializer element. - - static dma_trans_t trans = { - .src = &tgt1, - .dst = &tgt2, - .mode = DMA_TRANS_MODE_SINGLE, - .win_du = 0, - .end = DMA_TRANS_END_INTR, - }; - -#ifdef TEST_CIRCULAR - trans.mode = DMA_TRANS_MODE_CIRCULAR; - cycles = 0; -#endif // TEST_CIRCULAR - - res = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); - PRINTF("tran: %u \n\r", res); - - res = dma_load_transaction(&trans); - PRINTF("load: %u \n\r", res); - - res = dma_launch(&trans); - - spi_intr_flag = 0; - // Wait for the first data to arrive to the TX FIFO before enabling interrupt - spi_wait_for_tx_not_empty(&spi_host); - // Enable event interrupt - spi_enable_evt_intr(&spi_host, true); - // Enable TX empty interrupt - spi_enable_txempty_intr(&spi_host, true); - - const uint32_t cmd_write_tx = spi_create_command((spi_command_t){ - .len = COPY_DATA_UNITS*DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE) - 1, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_write_tx); - spi_wait_for_ready(&spi_host); - - // Wait for SPI interrupt - while(spi_intr_flag == 0) { - wait_for_interrupt(); - } - PRINTF("triggered\n\r"); - - spi_wait_4_resp(); - - PRINTF("%d Bytes written in Flash at @ 0x%08x \n\r", COPY_DATA_UNITS*DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE), FLASH_ADDR); - - -#endif //TEST_SPI_2_MEM - -#ifdef TEST_SPI_2_MEM - - PRINTF("\n\n\r======================================\n\n\r"); - PRINTF(" MEM <- <- DMA <- <- SPI <- <- FLASH "); - PRINTF("\n\n\r======================================\n\n\r"); - -#ifndef USE_SPI_FLASH - const uint8_t slot2 = DMA_TRIG_SLOT_SPI_RX; // The DMA will wait for the SPI TX FIFO ready signal -#else - const uint8_t slot2 = DMA_TRIG_SLOT_SPI_FLASH_RX; // The DMA will wait for the SPI FLASH TX FIFO ready signal - #endif - - static dma_target_t tgt3= { - .ptr = copy_data, - .inc_du = 1, - // Because the data type needs to be WORD the size needs to be normalized. - .size_du = COPY_DATA_PER_CYCLE*DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE)/DMA_DATA_TYPE_2_SIZE(DMA_DATA_TYPE_WORD), - .trig = DMA_TRIG_MEMORY, - .type = DMA_DATA_TYPE_WORD, // Only possible to read word-wise from SPI - }; - - static dma_target_t tgt4= { - .inc_du = 0, - // Because the data type needs to be WORD the size needs to be normalized. - .size_du = COPY_DATA_PER_CYCLE*DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE)/DMA_DATA_TYPE_2_SIZE(DMA_DATA_TYPE_WORD), - .trig = slot2, - .type = DMA_DATA_TYPE_WORD, - }; - tgt4.ptr = fifo_ptr_rx; - - static dma_trans_t trans2 = { - .src = &tgt4, - .dst = &tgt3, - .end = DMA_TRANS_END_INTR, - }; - - res = dma_validate_transaction( &trans2, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); - PRINTF("tran: %u \n\r", res); - - res = dma_load_transaction(&trans2); - PRINTF("load: %u \n\r", res); - - // The address bytes sent through the SPI to the Flash are in reverse order - const int32_t read_byte_cmd = ((REVERT_24b_ADDR(FLASH_ADDR) << 8) | 0x03); - - // Fill TX FIFO with TX data (read command + 3B address) - spi_write_word(&spi_host, read_byte_cmd); - // Wait for readiness to process commands - spi_wait_for_ready(&spi_host); - - // Load command FIFO with read command (1 Byte at single speed) - const uint32_t cmd_read = spi_create_command((spi_command_t){ - .len = 3, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_read); - spi_wait_for_ready(&spi_host); - - const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ - .len = COPY_DATA_UNITS*DMA_DATA_TYPE_2_SIZE(TEST_DATA_TYPE) - 1, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirRxOnly - }); - spi_set_command(&spi_host, cmd_read_rx); - spi_wait_for_ready(&spi_host); - - res = dma_launch(&trans2); - - while( ! dma_is_ready() ){ - /* wait_for_interrupt(); For small buffer sizes the interrupt arrives before going to wfi(); */ - }; - - PRINTF("triggered!\n\r"); - - // Power down flash - const uint32_t powerdown_byte_cmd = 0xb9; - spi_write_word(&spi_host, powerdown_byte_cmd); - const uint32_t cmd_powerdown = spi_create_command((spi_command_t){ - .len = 0, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_powerdown); - spi_wait_for_ready(&spi_host); - - // The data is already in memory -- Check results - PRINTF("ram vs flash...\n\r"); - - int i; - uint32_t errors = 0; - uint32_t count = 0; - for (i = 0; i -#include -#include - -#include "core_v_mini_mcu.h" -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "soc_ctrl.h" -#include "spi_host.h" -#include "fast_intr_ctrl.h" -#include "fast_intr_ctrl_regs.h" -#include "x-heep.h" - -#ifdef TARGET_PYNQ_Z2 - #define USE_SPI_FLASH -#endif - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -// Simple example to check the SPI host peripheral is working. It checks the ram and flash have the same content -#define REVERT_24b_ADDR(addr) ((((uint32_t)(addr) & 0xff0000) >> 16) | ((uint32_t)(addr) & 0xff00) | (((uint32_t)(addr) & 0xff) << 16)) - -#define FLASH_CLK_MAX_HZ (133*1000*1000) // In Hz (133 MHz for the flash w25q128jvsim used in the EPFL Programmer) - -volatile int8_t spi_intr_flag; -spi_host_t spi_host; -uint32_t flash_data[8]; -uint32_t flash_original[8] = {1}; - -#ifndef USE_SPI_FLASH -void fic_irq_spi(void) -{ - // Disable SPI interrupts - spi_enable_evt_intr(&spi_host, false); - spi_enable_rxwm_intr(&spi_host, false); - spi_intr_flag = 1; -} -#else -void fic_irq_spi_flash(void) -{ - // Disable SPI interrupts - spi_enable_evt_intr(&spi_host, false); - spi_enable_rxwm_intr(&spi_host, false); - spi_intr_flag = 1; -} -#endif - -int main(int argc, char *argv[]) -{ - - soc_ctrl_t soc_ctrl; - soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - uint32_t read_byte_cmd = ((REVERT_24b_ADDR(flash_original) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order - - if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) - { -#ifdef USE_SPI_FLASH - PRINTF("This application cannot work with the memory mapped SPI FLASH module - do not use the FLASH_EXEC linker script for this application\n"); - return EXIT_SUCCESS; -#else - /* - if we are using in SIMULATION the SPIMMIO from Yosys, then the flash_original data is different - as the compilation is done differently, so we will store there the first WORDs of code mapped at the beginning of the FLASH - */ - uint32_t* ptr_flash = (uint32_t*)FLASH_MEM_START_ADDRESS; - for(int i =0; i < 8 ; i++){ - flash_original[i] = ptr_flash[i]; - } - // we read the data from the FLASH address 0x0, which corresponds to FLASH_MEM_START_ADDRESS - read_byte_cmd = ((REVERT_24b_ADDR(0x0) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order - -#endif - - } - - - // spi_host_t spi_host; - #ifndef USE_SPI_FLASH - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); - #else - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_FLASH_START_ADDRESS); - #endif - - uint32_t core_clk = soc_ctrl_get_frequency(&soc_ctrl); - - // Enable interrupt on processor side - // Enable global interrupt for machine-level interrupts - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - // Set mie.MEIE bit to one to enable machine-level fast spi interrupt - #ifndef USE_SPI_FLASH - const uint32_t mask = 1 << 20; - #else - const uint32_t mask = 1 << 21; - #endif - CSR_SET_BITS(CSR_REG_MIE, mask); - spi_intr_flag = 0; - - #ifdef USE_SPI_FLASH - // Select SPI host as SPI output - soc_ctrl_select_spi_host(&soc_ctrl); - #endif - - // Enable SPI host device - spi_set_enable(&spi_host, true); - - // Enable event interrupt - spi_enable_evt_intr(&spi_host, true); - // Enable RX watermark interrupt - spi_enable_rxwm_intr(&spi_host, true); - // Enable SPI output - spi_output_enable(&spi_host, true); - - // Configure SPI clock - // SPI clk freq = 1/2 core clk freq when clk_div = 0 - // SPI_CLK = CORE_CLK/(2 + 2 * CLK_DIV) <= CLK_MAX => CLK_DIV > (CORE_CLK/CLK_MAX - 2)/2 - uint16_t clk_div = 0; - if(FLASH_CLK_MAX_HZ < core_clk/2){ - clk_div = (core_clk/(FLASH_CLK_MAX_HZ) - 2)/2; // The value is truncated - if (core_clk/(2 + 2 * clk_div) > FLASH_CLK_MAX_HZ) clk_div += 1; // Adjust if the truncation was not 0 - } - // SPI Configuration - // Configure chip 0 (flash memory) - const uint32_t chip_cfg = spi_create_configopts((spi_configopts_t){ - .clkdiv = clk_div, - .csnidle = 0xF, - .csntrail = 0xF, - .csnlead = 0xF, - .fullcyc = false, - .cpha = 0, - .cpol = 0 - }); - spi_set_configopts(&spi_host, 0, chip_cfg); - spi_set_csid(&spi_host, 0); - - // Set RX watermark to 8 word - spi_set_rx_watermark(&spi_host, 8); - - uint32_t *flash_data_ptr = flash_data[0]; - - // Power up flash - const uint32_t powerup_byte_cmd = 0xab; - spi_write_word(&spi_host, powerup_byte_cmd); - // Load command FIFO with command (1 Byte at single speed) - const uint32_t cmd_powerup = spi_create_command((spi_command_t){ - .len = 3, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_powerup); - spi_wait_for_ready(&spi_host); - - volatile uint32_t data_addr = flash_original; - - - // Fill TX FIFO with TX data (read command + 3B address) - spi_write_word(&spi_host, read_byte_cmd); - // Wait for readiness to process commands - spi_wait_for_ready(&spi_host); - - //////////////////////////////////////////////////////////////// - - // // Load command FIFO with read command (1 Byte at single speed) - // const uint32_t cmd_read = spi_create_command((spi_command_t){ - // .len = 0, - // .csaat = true, - // .speed = kSpiSpeedStandard, - // .direction = kSpiDirTxOnly - // }); - // spi_set_command(&spi_host, cmd_read); - // spi_wait_for_ready(&spi_host); - // // Load command FIFO with read address (3 Byte at single speed) - // const uint32_t cmd_addr = spi_create_command((spi_command_t){ - // .len = 2, - // .csaat = true, - // .speed = kSpiSpeedStandard, - // .direction = kSpiDirTxOnly - // }); - // spi_set_command(&spi_host, cmd_addr); - // spi_wait_for_ready(&spi_host); - - // OR - - // Load command FIFO with read command (1 Byte at single speed) - const uint32_t cmd_read = spi_create_command((spi_command_t){ - .len = 3, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_read); - spi_wait_for_ready(&spi_host); - - //////////////////////////////////////////////////////////////// - - const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ - .len = 31, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirRxOnly - }); - spi_set_command(&spi_host, cmd_read_rx); - spi_wait_for_ready(&spi_host); - - // Wait transaction is finished (polling register) - // spi_wait_for_rx_watermark(&spi_host); - // or wait for SPI interrupt - PRINTF("Waiting for SPI...\n\r"); - - while( spi_intr_flag == 0 ) { - CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); - - if( spi_intr_flag == 0 ) - wait_for_interrupt(); - - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - } - - // Enable event interrupt - spi_enable_evt_intr(&spi_host, true); - // Enable RX watermark interrupt - spi_enable_rxwm_intr(&spi_host, true); - - // Read data from SPI RX FIFO - for (int i=0; i<8; i++) { - spi_read_word(&spi_host, &flash_data[i]); - } - - PRINTF("flash vs ram...\n\r"); - - uint32_t errors = 0; - uint32_t* ram_ptr = flash_original; - for (int i=0; i<8; i++) { - if(flash_data[i] != *ram_ptr) { - PRINTF("@%x : %x != %x\n\r", ram_ptr, flash_data[i], *ram_ptr); - errors++; - } - ram_ptr++; - } - - if (errors == 0) { - PRINTF("success!\n\r"); - } else { - PRINTF("failure, %d errors!\n\r", errors); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - -} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_host_dma/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_host_dma/main.c deleted file mode 100644 index de6ab165..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_host_dma/main.c +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright EPFL contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include - -#include "core_v_mini_mcu.h" -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "soc_ctrl.h" -#include "spi_host.h" -#include "dma.h" -#include "fast_intr_ctrl.h" -#include "fast_intr_ctrl_regs.h" -#include "x-heep.h" - -#ifdef TARGET_PYNQ_Z2 - #define USE_SPI_FLASH -#endif - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -// Type of data frome the SPI. For types different than words the SPI data is requested in separate transactions -// word(0), half-word(1), byte(2,3) -#define SPI_DATA_TYPE DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD - -// Number of elements to copy -#define COPY_DATA_NUM 16 - -#define FLASH_CLK_MAX_HZ (133*1000*1000) // In Hz (133 MHz for the flash w25q128jvsim used in the EPFL Programmer) - -#define REVERT_24b_ADDR(addr) ((((uint32_t)(addr) & 0xff0000) >> 16) | ((uint32_t)(addr) & 0xff00) | (((uint32_t)(addr) & 0xff) << 16)) - -volatile int8_t dma_intr_flag; -spi_host_t spi_host; - -void dma_intr_handler_trans_done(void) -{ - PRINTF("Non-weak implementation of a DMA interrupt\n\r"); - dma_intr_flag = 1; -} - -// Reserve memory array -uint32_t flash_data[COPY_DATA_NUM] __attribute__ ((aligned (4))) = {0x76543210,0xfedcba98,0x579a6f90,0x657d5bee,0x758ee41f,0x01234567,0xfedbca98,0x89abcdef,0x679852fe,0xff8252bb,0x763b4521,0x6875adaa,0x09ac65bb,0x666ba334,0x44556677,0x0000ba98}; -uint32_t copy_data[COPY_DATA_NUM] __attribute__ ((aligned (4))) = { 0 }; - -#if SPI_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD - #define DATA_TYPE uint32_t -#elif SPI_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_16BIT_WORD - #define DATA_TYPE uint16_t -#else - #define DATA_TYPE uint8_t -#endif - -#define COPY_DATA_TYPE (COPY_DATA_NUM/(sizeof(uint32_t)/sizeof(DATA_TYPE))) - - -int main(int argc, char *argv[]) -{ - - soc_ctrl_t soc_ctrl; - soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - uint32_t read_byte_cmd; - - if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) - { -#ifdef USE_SPI_FLASH - PRINTF("This application cannot work with the memory mapped SPI FLASH module - do not use the FLASH_EXEC linker script for this application\n"); - return EXIT_SUCCESS; -#else - /* - if we are using in SIMULATION the SPIMMIO from Yosys, then the flash_original data is different - as the compilation is done differently, so we will store there the first WORDs of code mapped at the beginning of the FLASH - */ - uint32_t* ptr_flash = (uint32_t*)FLASH_MEM_START_ADDRESS; - for(int i =0; i < COPY_DATA_NUM ; i++){ - flash_data[i] = ptr_flash[i]; - } -#endif - - } - - - #ifndef USE_SPI_FLASH - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); - #else - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_FLASH_START_ADDRESS); - #endif - - uint32_t core_clk = soc_ctrl_get_frequency(&soc_ctrl); - - // Enable interrupt on processor side - // Enable global interrupt for machine-level interrupts - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - - #ifdef USE_SPI_FLASH - // Select SPI host as SPI output - soc_ctrl_select_spi_host(&soc_ctrl); - #endif - - // Enable SPI host device - spi_set_enable(&spi_host, true); - // Enable SPI output - spi_output_enable(&spi_host, true); - - // SPI and SPI_FLASH are the same IP so same register map - uint32_t *fifo_ptr_rx = spi_host.base_addr.base + SPI_HOST_RXDATA_REG_OFFSET; - - - // DMA CONFIGURATION - PRINTF("---- TEST ---- \n\r"); - dma_init(NULL); - - - #ifndef USE_SPI_FLASH - uint8_t slot = DMA_TRIG_SLOT_SPI_RX; // The DMA will wait for the SPI RX FIFO valid signal - #else - uint8_t slot = DMA_TRIG_SLOT_SPI_FLASH_RX; // The DMA will wait for the SPI FLASH RX FIFO valid signal - #endif - - static dma_target_t tgt_src = { - .inc_du = 0, - .size_du = COPY_DATA_NUM, - .type = SPI_DATA_TYPE, - }; - tgt_src.ptr = fifo_ptr_rx; // Necessary outside 'cause its not a const. - tgt_src.trig = slot;// Necessary outside 'cause its not a const. - - static dma_target_t tgt_dst = { - .ptr = copy_data, - .inc_du = 1, - .type = SPI_DATA_TYPE, - .trig = DMA_TRIG_MEMORY, - }; - static dma_trans_t trans = { - .src = &tgt_src, - .dst = &tgt_dst, - .end = DMA_TRANS_END_INTR, - }; - - dma_config_flags_t res; - - res = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); - PRINTF("Result - tgt trans: %u\n\r", res ); - res = dma_load_transaction(&trans); - PRINTF("Result - tgt load: %u\n\r", res ); - - // Configure SPI clock - // SPI clk freq = 1/2 core clk freq when clk_div = 0 - // SPI_CLK = CORE_CLK/(2 + 2 * CLK_DIV) <= CLK_MAX => CLK_DIV > (CORE_CLK/CLK_MAX - 2)/2 - uint16_t clk_div = 0; - if(FLASH_CLK_MAX_HZ < core_clk/2){ - clk_div = (core_clk/(FLASH_CLK_MAX_HZ) - 2)/2; // The value is truncated - if (core_clk/(2 + 2 * clk_div) > FLASH_CLK_MAX_HZ) clk_div += 1; // Adjust if the truncation was not 0 - } - // SPI Configuration - // Configure chip 0 (flash memory) - const uint32_t chip_cfg = spi_create_configopts((spi_configopts_t){ - .clkdiv = clk_div, - .csnidle = 0xF, - .csntrail = 0xF, - .csnlead = 0xF, - .fullcyc = false, - .cpha = 0, - .cpol = 0 - }); - spi_set_configopts(&spi_host, 0, chip_cfg); - spi_set_csid(&spi_host, 0); - - // Reset - const uint32_t reset_cmd = 0xFFFFFFFF; - spi_write_word(&spi_host, reset_cmd); - const uint32_t cmd_reset = spi_create_command((spi_command_t){ - .len = 3, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_reset); - spi_wait_for_ready(&spi_host); - - // Power up flash - const uint32_t powerup_byte_cmd = 0xab; - spi_write_word(&spi_host, powerup_byte_cmd); - const uint32_t cmd_powerup = spi_create_command((spi_command_t){ - .len = 0, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_powerup); - spi_wait_for_ready(&spi_host); - - // Load command FIFO with read command (1 Byte at single speed) - const uint32_t cmd_read = spi_create_command((spi_command_t){ - .len = 3, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - - dma_intr_flag = 0; - res = dma_launch(&trans); - PRINTF("launched!\n\r"); - - #if SPI_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD - - if(get_spi_flash_mode(&soc_ctrl) != SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO) - read_byte_cmd = ((REVERT_24b_ADDR(flash_data) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order - else - // we read the data from the FLASH address 0x0, which corresponds to FLASH_MEM_START_ADDRESS - read_byte_cmd = ((REVERT_24b_ADDR(0x0) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order - - const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ // Single transaction - .len = COPY_DATA_NUM*sizeof(DATA_TYPE) - 1, // In bytes - 1 - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirRxOnly - }); - spi_write_word(&spi_host, read_byte_cmd); // Fill TX FIFO with TX data (read command + 3B address) - spi_wait_for_ready(&spi_host); // Wait for readiness to process commands - spi_set_command(&spi_host, cmd_read); // Send read command to the external device through SPI - spi_wait_for_ready(&spi_host); - spi_set_command(&spi_host, cmd_read_rx); // Receive data in RX - spi_wait_for_ready(&spi_host); - #else - const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ // Multiple transactions of the data type - .len = (sizeof(DATA_TYPE) - 1), - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirRxOnly - }); - DATA_TYPE* flash_ptr = (DATA_TYPE *)flash_data; - for (int i = 0; i -#include -#include - -#include "core_v_mini_mcu.h" -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "soc_ctrl.h" -#include "spi_host.h" -#include "dma.h" -#include "fast_intr_ctrl.h" -#include "power_manager.h" -#include "x-heep.h" - -#ifdef TARGET_PYNQ_Z2 - #define USE_SPI_FLASH -#endif - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -// Type of data frome the SPI. For types different than words the SPI data is requested in separate transactions -// word(0), half-word(1), byte(2,3) -#define SPI_DATA_TYPE DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD - -// Number of elements to copy -#define COPY_DATA_NUM 16 - -#define FLASH_CLK_MAX_HZ (133*1000*1000) // In Hz (133 MHz for the flash w25q128jvsim used in the EPFL Programmer) - -#define REVERT_24b_ADDR(addr) ((((uint32_t)(addr) & 0xff0000) >> 16) | ((uint32_t)(addr) & 0xff00) | (((uint32_t)(addr) & 0xff) << 16)) - -volatile int8_t dma_intr_flag; -int8_t core_sleep_flag; -spi_host_t spi_host; - -static power_manager_t power_manager; - -void dma_intr_handler_trans_done(void) -{ - PRINTF("Non-weak implementation of a DMA interrupt\n\r"); - dma_intr_flag = 1; -} - -// Reserve memory array -uint32_t flash_data[COPY_DATA_NUM] __attribute__ ((aligned (4))) = {0x76543210,0xfedcba98,0x579a6f90,0x657d5bee,0x758ee41f,0x01234567,0xfedbca98,0x89abcdef,0x679852fe,0xff8252bb,0x763b4521,0x6875adaa,0x09ac65bb,0x666ba334,0x44556677,0x0000ba98}; -uint32_t copy_data[COPY_DATA_NUM] __attribute__ ((aligned (4))) = { 0 }; - -#if SPI_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD - #define DATA_TYPE uint32_t -#elif SPI_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_16BIT_WORD - #define DATA_TYPE uint16_t -#else - #define DATA_TYPE uint8_t -#endif - -#define COPY_DATA_TYPE (COPY_DATA_NUM/(sizeof(uint32_t)/sizeof(DATA_TYPE))) - - -int main(int argc, char *argv[]) -{ - - soc_ctrl_t soc_ctrl; - soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - uint32_t read_byte_cmd; - - if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) - { -#ifdef USE_SPI_FLASH - PRINTF("This application cannot work with the memory mapped SPI FLASH module - do not use the FLASH_EXEC linker script for this application\n"); - return EXIT_SUCCESS; -#else - /* - if we are using in SIMULATION the SPIMMIO from Yosys, then the flash_original data is different - as the compilation is done differently, so we will store there the first WORDs of code mapped at the beginning of the FLASH - */ - uint32_t* ptr_flash = (uint32_t*)FLASH_MEM_START_ADDRESS; - for(int i =0; i < COPY_DATA_NUM ; i++){ - flash_data[i] = ptr_flash[i]; - } -#endif - } - - #ifndef USE_SPI_FLASH - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); - #else - spi_host.base_addr = mmio_region_from_addr((uintptr_t)SPI_FLASH_START_ADDRESS); - #endif - - // Setup power_manager - mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); - power_manager.base_addr = power_manager_reg; - power_manager_counters_t power_manager_cpu_counters; - // Init cpu_subsystem's counters - if (power_gate_counters_init(&power_manager_cpu_counters, 300, 300, 300, 300, 300, 300, 0, 0) != kPowerManagerOk_e) - { - PRINTF("Error: power manager fail. Check the reset and powergate counters value\n\r"); - return EXIT_FAILURE; - } - - uint32_t core_clk = soc_ctrl_get_frequency(&soc_ctrl); - - // Enable interrupt on processor side - // Enable global interrupt for machine-level interrupts - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - - // Set mie.MEIE bit to one to enable machine-level fast dma interrupt - const uint32_t mask = 1 << 19; - CSR_SET_BITS(CSR_REG_MIE, mask); - - #ifdef USE_SPI_FLASH - // Select SPI host as SPI output - soc_ctrl_select_spi_host(&soc_ctrl); - #endif - - // Enable SPI host device - spi_set_enable(&spi_host, true); - // Enable SPI output - spi_output_enable(&spi_host, true); - - // SPI and SPI_FLASH are the same IP so same register map - uint32_t *fifo_ptr_rx = spi_host.base_addr.base + SPI_HOST_RXDATA_REG_OFFSET; - - core_sleep_flag = 0; - - // -- DMA CONFIGURATION -- - - dma_init(NULL); - - #ifndef USE_SPI_FLASH - uint8_t slot = DMA_TRIG_SLOT_SPI_RX ; // The DMA will wait for the SPI RX FIFO valid signal - #else - uint8_t slot = DMA_TRIG_SLOT_SPI_FLASH_RX ; // The DMA will wait for the SPI FLASH RX FIFO valid signal - #endif - - static dma_target_t tgt_src = { - .size_du = COPY_DATA_NUM, - .inc_du = 0, - .type = SPI_DATA_TYPE, - }; - tgt_src.ptr = fifo_ptr_rx; - tgt_src.trig = slot; - - static dma_target_t tgt_dst = { - .ptr = copy_data, - .inc_du = 1, - .type = SPI_DATA_TYPE, - .trig = DMA_TRIG_MEMORY, - }; - - static dma_trans_t trans = { - .src = &tgt_src, - .dst = &tgt_dst, - .end = DMA_TRANS_END_INTR, - }; - - dma_config_flags_t res; - - res = dma_validate_transaction(&trans ,DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); - PRINTF("trans: %u \n\r", res ); - res = dma_load_transaction(&trans); - PRINTF(" load: %u \n\r", res ); - - - - // Configure SPI clock - // SPI clk freq = 1/2 core clk freq when clk_div = 0 - // SPI_CLK = CORE_CLK/(2 + 2 * CLK_DIV) <= CLK_MAX => CLK_DIV > (CORE_CLK/CLK_MAX - 2)/2 - uint16_t clk_div = 0; - if(FLASH_CLK_MAX_HZ < core_clk/2){ - clk_div = (core_clk/(FLASH_CLK_MAX_HZ) - 2)/2; // The value is truncated - if (core_clk/(2 + 2 * clk_div) > FLASH_CLK_MAX_HZ) clk_div += 1; // Adjust if the truncation was not 0 - } - // SPI Configuration - // Configure chip 0 (flash memory) - const uint32_t chip_cfg = spi_create_configopts((spi_configopts_t){ - .clkdiv = clk_div, - .csnidle = 0xF, - .csntrail = 0xF, - .csnlead = 0xF, - .fullcyc = false, - .cpha = 0, - .cpol = 0 - }); - spi_set_configopts(&spi_host, 0, chip_cfg); - spi_set_csid(&spi_host, 0); - - // Reset - const uint32_t reset_cmd = 0xFFFFFFFF; - spi_write_word(&spi_host, reset_cmd); - const uint32_t cmd_reset = spi_create_command((spi_command_t){ - .len = 3, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_reset); - spi_wait_for_ready(&spi_host); - - // Power up flash - const uint32_t powerup_byte_cmd = 0xab; - spi_write_word(&spi_host, powerup_byte_cmd); - const uint32_t cmd_powerup = spi_create_command((spi_command_t){ - .len = 0, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host, cmd_powerup); - spi_wait_for_ready(&spi_host); - - // Load command FIFO with read command (1 Byte at single speed) - const uint32_t cmd_read = spi_create_command((spi_command_t){ - .len = 3, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - - dma_intr_flag = 0; - dma_launch(&trans); - PRINTF("Launched\n\r"); - - #if SPI_DATA_TYPE == DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD - if(get_spi_flash_mode(&soc_ctrl) != SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO) - read_byte_cmd = ((REVERT_24b_ADDR(flash_data) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order - else - // we read the data from the FLASH address 0x0, which corresponds to FLASH_MEM_START_ADDRESS - read_byte_cmd = ((REVERT_24b_ADDR(0x0) << 8) | 0x03); // The address bytes sent through the SPI to the Flash are in reverse order - const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ // Single transaction - .len = COPY_DATA_NUM*sizeof(DATA_TYPE) - 1, // In bytes - 1 - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirRxOnly - }); - spi_write_word(&spi_host, read_byte_cmd); // Fill TX FIFO with TX data (read command + 3B address) - spi_wait_for_ready(&spi_host); // Wait for readiness to process commands - spi_set_command(&spi_host, cmd_read); // Send read command to the external device through SPI - spi_wait_for_ready(&spi_host); - spi_set_command(&spi_host, cmd_read_rx); // Receive data in RX - spi_wait_for_ready(&spi_host); - #else - const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ // Multiple transactions of the data type - .len = (sizeof(DATA_TYPE) - 1), - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirRxOnly - }); - DATA_TYPE* flash_ptr = (DATA_TYPE *)flash_data; - for (int i = 0; i +#include +#include + +#include "x-heep.h" +#include "w25q128jw.h" + +/* By default, PRINTFs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +#if defined(TARGET_PYNQ_Z2) || defined(TARGET_ZCU104) || defined(TARGET_NEXYS_A7_100T) + #define USE_SPI_FLASH +#endif + + +// Start buffers (the original data) +#include "buffer.h" +// End buffer (where what is read is stored) +uint32_t flash_data[256]; + +/* + * Assign the test buffer to the buffer to write to flash. + * The buffer is defined in the file buffer.h. As multiple buffers can + * be defined, this is userful to pick the right one. + * Also the length is specified, to test different length cases. In any case + * length <= test_buffer length. +*/ +#define TEST_BUFFER flash_original_1024B +#define LENGTH 1024 + +#ifndef ON_CHIP +#define FLASH_ONLY_WORDS 32 +#define FLASH_ONLY_BYTES (FLASH_ONLY_WORDS*4) + +int32_t __attribute__((section(".xheep_data_flash_only"))) __attribute__ ((aligned (16))) flash_only_buffer[FLASH_ONLY_WORDS] = { + 0xABCDEF00, + 0xABCDEF01, + 0xABCDEF02, + 0xABCDEF03, + 0xABCDEF04, + 0xABCDEF05, + 0xABCDEF06, + 0xABCDEF07, + 0xABCDEF08, + 0xABCDEF09, + 0xABCDEF0A, + 0xABCDEF0B, + 0xABCDEF0C, + 0xABCDEF0D, + 0xABCDEF0E, + 0xABCDEF0F, + 0xABCDEF10, + 0xABCDEF11, + 0xABCDEF12, + 0xABCDEF13, + 0xABCDEF14, + 0xABCDEF15, + 0xABCDEF16, + 0xABCDEF17, + 0xABCDEF18, + 0xABCDEF19, + 0xABCDEF1A, + 0xABCDEF1B, + 0xABCDEF1C, + 0xABCDEF1D, + 0xABCDEF1E, + 0xABCDEF1F, +}; + +int32_t __attribute__ ((aligned (16))) flash_only_buffer_golden_value[FLASH_ONLY_WORDS] = { + 0xABCDEF00, + 0xABCDEF01, + 0xABCDEF02, + 0xABCDEF03, + 0xABCDEF04, + 0xABCDEF05, + 0xABCDEF06, + 0xABCDEF07, + 0xABCDEF08, + 0xABCDEF09, + 0xABCDEF0A, + 0xABCDEF0B, + 0xABCDEF0C, + 0xABCDEF0D, + 0xABCDEF0E, + 0xABCDEF0F, + 0xABCDEF10, + 0xABCDEF11, + 0xABCDEF12, + 0xABCDEF13, + 0xABCDEF14, + 0xABCDEF15, + 0xABCDEF16, + 0xABCDEF17, + 0xABCDEF18, + 0xABCDEF19, + 0xABCDEF1A, + 0xABCDEF1B, + 0xABCDEF1C, + 0xABCDEF1D, + 0xABCDEF1E, + 0xABCDEF1F, +}; +#endif + +// Test functions +uint32_t test_read(uint32_t *test_buffer, uint32_t len); +uint32_t test_read_flash_only(uint32_t *test_buffer, uint32_t len); +uint32_t test_read_dma(uint32_t *test_buffer, uint32_t len); +uint32_t test_read_quad(uint32_t *test_buffer, uint32_t len); +uint32_t test_read_quad_dma(uint32_t *test_buffer, uint32_t len); + +// Check function +uint32_t check_result(uint8_t *test_buffer, uint32_t len); + +// Define global status variable +w25q_error_codes_t global_status; + +int main(int argc, char *argv[]) { + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + + if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) { + PRINTF("This application cannot work with the memory mapped SPI FLASH" + "module - do not use the FLASH_EXEC linker script for this application\n"); + return EXIT_SUCCESS; + } + + PRINTF("BSP read test\n", LENGTH); + + // Pick the correct spi device based on simulation type + spi_host_t* spi; + #ifndef USE_SPI_FLASH + spi = spi_host1; + #else + spi = spi_flash; + #endif + + // Define status variable + int32_t errors = 0; + + // Init SPI host and SPI<->Flash bridge parameters + if (w25q128jw_init(spi) != FLASH_OK) return EXIT_FAILURE; + + // Test simple read + PRINTF("Testing simple read...\n"); + errors += test_read(TEST_BUFFER, LENGTH); + +#ifndef ON_CHIP + PRINTF("Testing simple read on flash only data...\n"); + errors += test_read_flash_only(flash_only_buffer, FLASH_ONLY_BYTES); +#endif + + // Test simple read with DMA + PRINTF("Testing simple read with DMA...\n"); + errors += test_read_dma(TEST_BUFFER, LENGTH); + + // Test quad read + PRINTF("Testing quad read...\n"); + errors += test_read_quad(TEST_BUFFER, LENGTH); + + // Test quad read with DMA + PRINTF("Testing quad read with DMA...\n"); + errors += test_read_quad_dma(TEST_BUFFER, LENGTH); + + PRINTF("\n--------TEST FINISHED--------\n"); + if (errors == 0) { + PRINTF("All tests passed!\n"); + return EXIT_SUCCESS; + } else { + PRINTF("Some tests failed!\n"); + return EXIT_FAILURE; + } + +} + +uint32_t test_read(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = test_buffer; + + // Read from flash memory at the same address + w25q_error_codes_t status = w25q128jw_read_standard(test_buffer_flash, flash_data, len); + if (status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_data == test_buffer) + uint32_t res = check_result(test_buffer, len); + + // Reset the flash data buffer + memset(flash_data, 0, len * sizeof(uint8_t)); + + return res; +} +#ifndef ON_CHIP +uint32_t test_read_flash_only(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = heep_get_flash_address_offset(test_buffer); + + // Read from flash memory at the same address + w25q_error_codes_t status = w25q128jw_read_standard(test_buffer_flash, flash_data, len); + if (status != FLASH_OK) exit(EXIT_FAILURE); + + printf("Checking Results \n"); + + // Check if what we read is correct (i.e. flash_data == test_buffer) + uint32_t res = check_result(flash_only_buffer_golden_value, len); + + // Reset the flash data buffer + memset(flash_data, 0, len * sizeof(uint8_t)); + + return res; +} +#endif +uint32_t test_read_dma(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = test_buffer; + + // Read from flash memory at the same address + w25q_error_codes_t status = w25q128jw_read_standard_dma(test_buffer_flash, flash_data, len, 0, 0); + if (status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_data == test_buffer) + uint32_t res = check_result(test_buffer, len); + + // Reset the flash data buffer + memset(flash_data, 0, len * sizeof(uint8_t)); + + return res; +} + +uint32_t test_read_quad(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = test_buffer; + + // Read from flash memory at the same address + w25q_error_codes_t status = w25q128jw_read_quad(test_buffer_flash, flash_data, len); + if (status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_data == test_buffer) + uint32_t res = check_result(test_buffer, len); + + // Reset the flash data buffer + memset(flash_data, 0, len * sizeof(uint8_t)); + + return res; +} + +uint32_t test_read_quad_dma(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = test_buffer; + + // Read from flash memory at the same address + w25q_error_codes_t status = w25q128jw_read_quad_dma(test_buffer_flash, flash_data, len); + if (status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_data == test_buffer) + uint32_t res = check_result(test_buffer, len); + + // Reset the flash data buffer + memset(flash_data, 0, len * sizeof(uint8_t)); + + return res; +} + +uint32_t check_result(uint8_t *test_buffer, uint32_t len) { + uint32_t errors = 0; + uint8_t *flash_data_char = (uint8_t *)flash_data; + + for (uint32_t i = 0; i < len; i++) { + if (test_buffer[i] != flash_data_char[i]) { + PRINTF("Error at position %d: expected %x, got %x\n", i, test_buffer[i], flash_data_char[i]); + errors++; + } + } + + if (errors == 0) { + PRINTF("success!\n"); + } else { + PRINTF("failure, %d errors!\n", errors); + } + + return errors; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_write/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_write/main.c new file mode 100644 index 00000000..b95fcad0 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_spi_write/main.c @@ -0,0 +1,354 @@ +/** + * @file main.c + * @brief Simple spi write example using BSP + * + * Simple example that writes a 1kB buffer to flash memory at a specific address + * and then read it back to check if the data was written correctly. + * For buffers bigger than 4kB (or even smaller buffers that are not aligned to 4kB), + * the erase operation must be tweeked to erase all the sectors that contain the + * buffer. + * + * @note The application assume the correct functioning of the read operation. + * +*/ + +#include +#include +#include + +#include "x-heep.h" +#include "w25q128jw.h" + +/* By default, PRINTFs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +#if defined(TARGET_PYNQ_Z2) || defined(TARGET_ZCU104) || defined(TARGET_NEXYS_A7_100T) + #define USE_SPI_FLASH +#endif + + +// what to write in flash +uint32_t flash_original_1024B[256] = { + 0x76543211, 0xfedcba99, 0x579a6f91, 0x657d5bef, 0x758ee420, 0x01234568, 0xfedbca97, 0x89abde00, + 0x76543212, 0xfedcba9a, 0x579a6f92, 0x657d5bf0, 0x758ee421, 0x01234569, 0xfedbca98, 0x89abde01, + 0x76543213, 0xfedcba9b, 0x579a6f93, 0x657d5bf1, 0x758ee422, 0x0123456a, 0xfedbca99, 0x89abde02, + 0x76543214, 0xfedcba9c, 0x579a6f94, 0x657d5bf2, 0x758ee423, 0x0123456b, 0xfedbca9a, 0x89abde03, + 0x76543215, 0xfedcba9d, 0x579a6f95, 0x657d5bf3, 0x758ee424, 0x0123456c, 0xfedbca9b, 0x89abde04, + 0x76543216, 0xfedcba9e, 0x579a6f96, 0x657d5bf4, 0x758ee425, 0x0123456d, 0xfedbca9c, 0x89abde05, + 0x76543217, 0xfedcba9f, 0x579a6f97, 0x657d5bf5, 0x758ee426, 0x0123456e, 0xfedbca9d, 0x89abde06, + 0x76543218, 0xfedcbaa0, 0x579a6f98, 0x657d5bf6, 0x758ee427, 0x0123456f, 0xfedbca9e, 0x89abde07, + 0x76543219, 0xfedcbaa1, 0x579a6f99, 0x657d5bf7, 0x758ee428, 0x01234570, 0xfedbca9f, 0x89abde08, + 0x7654321a, 0xfedcbaa2, 0x579a6f9a, 0x657d5bf8, 0x758ee429, 0x01234571, 0xfedbcaa0, 0x89abde09, + 0x7654321b, 0xfedcbaa3, 0x579a6f9b, 0x657d5bf9, 0x758ee42a, 0x01234572, 0xfedbcaa1, 0x89abde0a, + 0x7654321c, 0xfedcbaa4, 0x579a6f9c, 0x657d5bfa, 0x758ee42b, 0x01234573, 0xfedbcaa2, 0x89abde0b, + 0x7654321d, 0xfedcbaa5, 0x579a6f9d, 0x657d5bfb, 0x758ee42c, 0x01234574, 0xfedbcaa3, 0x89abde0c, + 0x7654321e, 0xfedcbaa6, 0x579a6f9e, 0x657d5bfc, 0x758ee42d, 0x01234575, 0xfedbcaa4, 0x89abde0d, + 0x7654321f, 0xfedcbaa7, 0x579a6f9f, 0x657d5bfd, 0x758ee42e, 0x01234576, 0xfedbcaa5, 0x89abde0e, + 0x76543220, 0xfedcbaa8, 0x579a6fa0, 0x657d5bfe, 0x758ee42f, 0x01234577, 0xfedbcaa6, 0x89abde0f, + 0x76543221, 0xfedcbaa9, 0x579a6fa1, 0x657d5bff, 0x758ee430, 0x01234578, 0xfadbcaa7, 0x89abde10, + 0x76543222, 0xfedcbaaa, 0x579a6fa2, 0x657d5c00, 0x758ee431, 0x01234579, 0xfadbcaa8, 0x89abde11, + 0x76543223, 0xfedcbaab, 0x579a6fa3, 0x657d5c01, 0x758ee432, 0x0123457a, 0xfadbcaa9, 0x89abde12, + 0x76543224, 0xfedcbaac, 0x579a6fa4, 0x657d5c02, 0x758ee433, 0x0123457b, 0xfadbcaaa, 0x89abde13, + 0x76543225, 0xfedcbaad, 0x579a6fa5, 0x657d5c03, 0x758ee434, 0x0123457c, 0xfadbcaab, 0x89abde14, + 0x76543226, 0xfedcbaae, 0x579a6fa6, 0x657d5c04, 0x758ee435, 0x0123457d, 0xfadbcaac, 0x89abde15, + 0x76543227, 0xfedcbaaf, 0x579a6fa7, 0x657d5c05, 0x758ee436, 0x0123457e, 0xfadbcaad, 0x89abde16, + 0x76543228, 0xfedcbab0, 0x579a6fa8, 0x657d5c06, 0x758ee437, 0x0123457f, 0xfadbcaae, 0x89abde17, + 0x76543220, 0xfedcbaa8, 0x579a6fa0, 0x657d5bfe, 0x758ee42f, 0x01234577, 0xfedbcaa6, 0x89abde0f, + 0x76543221, 0xfedcbaa9, 0x579a6fa1, 0x657d5bff, 0x758ee430, 0x01234578, 0xfadbcaa7, 0x89abde10, + 0x76543222, 0xfedcbaaa, 0x579a6fa2, 0x657d5c00, 0x758ee431, 0x01234579, 0xfadbcaa8, 0x89abde11, + 0x76543223, 0xfedcbaab, 0x579a6fa3, 0x657d5c01, 0x758ee432, 0x0123457a, 0xfadbcaa9, 0x89abde12, + 0x76543224, 0xfedcbaac, 0x579a6fa4, 0x657d5c02, 0x758ee433, 0x0123457b, 0xfadbcaaa, 0x89abde13, + 0x76543225, 0xfedcbaad, 0x579a6fa5, 0x657d5c03, 0x758ee434, 0x0123457c, 0xfadbcaab, 0x89abde14, + 0x76543226, 0xfedcbaae, 0x579a6fa6, 0x657d5c04, 0x758ee435, 0x0123457d, 0xfadbcaac, 0x89abde15, + 0x76543227, 0xfedcbaaf, 0x579a6fa7, 0x657d5c05, 0x758ee436, 0x0123457e, 0xfadbcaad, 0x89abde16, + 0x76543228, 0xfedcbab0, 0x579a6fa8, 0x657d5c06, 0x758ee437, 0x0123457f, 0xfadbcaae, 0x89abde17 +}; + +// End buffer (where what is read is stored) +uint32_t flash_read_data[256]; + +#define BYTES_TO_WRITE 533 //in bytes, must be less than 256*4=1024 + +// address to which we write in FLASH, we do not initiliaze it to 0 as we do not want into the BSS +// otherwise the compilers/linker won't allocate this to the .data section, thus not written in flash +// If not written in flash, after erasing the block this array would be all '0xFF', and this would loose +// generality of the testing as without erasing, the write operation in flash can bring 1->0 but not viceversa +// by initializing to another number, we are sure it goes to .data section and written in flash +uint32_t __attribute__ ((aligned (16))) flash_write_buffer[256] = { + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA +}; + +#ifndef ON_CHIP +int32_t __attribute__((section(".xheep_data_flash_only"))) __attribute__ ((aligned (16))) flash_only_write_buffer[256]; +#endif + +// Test functions +uint32_t test_write(uint32_t *test_buffer, uint32_t len); +uint32_t test_write_dma(uint32_t *test_buffer, uint32_t len); +uint32_t test_write_quad(uint32_t *test_buffer, uint32_t len); +uint32_t test_write_quad_dma(uint32_t *test_buffer, uint32_t len); +uint32_t test_write_flash_only(uint32_t *test_buffer, uint32_t len); + +// Check function +uint32_t check_result(uint8_t *test_buffer, uint32_t len); + +// Erase memory function +void erase_memory(uint32_t addr); + +// Define global status variable +w25q_error_codes_t global_status; + +int main(int argc, char *argv[]) { + // Initialize the DMA + dma_init(NULL); + + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + + if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) { + PRINTF("This application cannot work with the memory mapped SPI FLASH" + "module - do not use the FLASH_EXEC linker script for this application\n"); + return EXIT_SUCCESS; + } + + PRINTF("BSP write test\n"); + + // Pick the correct spi device based on simulation type + spi_host_t* spi; + #ifndef USE_SPI_FLASH + spi = spi_host1; + #else + spi = spi_flash; + #endif + + // Define status variable + int32_t errors = 0; + + // Init SPI host and SPI<->Flash bridge parameters + if (w25q128jw_init(spi) != FLASH_OK) return EXIT_FAILURE; + + // Test simple write + PRINTF("Testing simple write...\n"); + errors += test_write(flash_original_1024B, BYTES_TO_WRITE); + +#ifndef ON_CHIP + // Test simple write on flash_only data + PRINTF("Testing simple write. on flash only data..\n"); + errors += test_write_flash_only(flash_original_1024B, BYTES_TO_WRITE); +#endif + + + // Test simple write with DMA + PRINTF("Testing simple write with DMA...\n"); + errors += test_write_dma(flash_original_1024B, BYTES_TO_WRITE); + + // Test quad write + PRINTF("Testing quad write...\n"); + errors += test_write_quad(flash_original_1024B, BYTES_TO_WRITE); + + // Test quad write with DMA + PRINTF("Testing quad write with DMA...\n"); + errors += test_write_quad_dma(flash_original_1024B, BYTES_TO_WRITE); + + PRINTF("\n--------TEST FINISHED--------\n"); + if (errors == 0) { + PRINTF("All tests passed!\n"); + return EXIT_SUCCESS; + } else { + PRINTF("Some tests failed!\n"); + return EXIT_FAILURE; + } +} + + +uint32_t test_write(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = flash_write_buffer; + + // Write to flash memory at specific address + global_status = w25q128jw_erase_and_write_standard(test_buffer_flash, test_buffer, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Read from flash memory at the same address + global_status = w25q128jw_read(test_buffer_flash, flash_read_data, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_original == flash_read_data) + int32_t result = check_result(test_buffer, len); + + // Clean memory for next test + erase_memory(test_buffer_flash); + + // Reset the flash data buffer + memset(flash_read_data, 0, len * sizeof(uint8_t)); + + return result; +} + +uint32_t test_write_dma(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = flash_write_buffer; + + // Write to flash memory at specific address + global_status = w25q128jw_erase_and_write_standard_dma(test_buffer_flash, test_buffer, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Read from flash memory at the same address + global_status = w25q128jw_read(test_buffer_flash, flash_read_data, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_original == flash_read_data) + int32_t result = check_result(test_buffer, len); + + // Clean memory for next test + erase_memory(test_buffer_flash); + + // Reset the flash data buffer + memset(flash_read_data, 0, len * sizeof(uint8_t)); + + return result; +} + +uint32_t test_write_quad(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = flash_write_buffer; + + // Write to flash memory at specific address + global_status = w25q128jw_erase_and_write_quad(test_buffer_flash, test_buffer, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Read from flash memory at the same address + global_status = w25q128jw_read(test_buffer_flash, flash_read_data, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_original == flash_read_data) + int32_t result = check_result(test_buffer, len); + + // Clean memory for next test + erase_memory(test_buffer_flash); + + // Reset the flash data buffer + memset(flash_read_data, 0, len * sizeof(uint8_t)); + + return result; +} + +uint32_t test_write_quad_dma(uint32_t *test_buffer, uint32_t len) { + + uint32_t *test_buffer_flash = flash_write_buffer; + + // Write to flash memory at specific address + global_status = w25q128jw_erase_and_write_quad_dma(test_buffer_flash, test_buffer, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Read from flash memory at the same address + global_status = w25q128jw_read(test_buffer_flash, flash_read_data, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_original == flash_read_data) + int32_t result = check_result(test_buffer, len); + + // Clean memory for next test + erase_memory(test_buffer_flash); + + // Reset the flash data buffer + memset(flash_read_data, 0, len * sizeof(uint8_t)); + + return result; +} +#ifndef ON_CHIP +uint32_t test_write_flash_only(uint32_t *test_buffer, uint32_t len) { + + //remove FLASH offset as required by the BSP, flash_only_write_buffer is only mapped to the LMA + uint32_t *test_buffer_flash = heep_get_flash_address_offset(flash_only_write_buffer); + + // Clean memory + erase_memory(test_buffer_flash); + + // Write to flash memory at specific address + global_status = w25q128jw_erase_and_write_standard(test_buffer_flash, test_buffer, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Read from flash memory at the same address + global_status = w25q128jw_read(test_buffer_flash, flash_read_data, len); + if (global_status != FLASH_OK) exit(EXIT_FAILURE); + + // Check if what we read is correct (i.e. flash_original == flash_read_data) + int32_t result = check_result(test_buffer, len); + + // Clean memory for next test + erase_memory(test_buffer_flash); + + // Reset the flash data buffer + memset(flash_read_data, 0, len * sizeof(uint8_t)); + + return result; +} +#endif +uint32_t check_result(uint8_t *test_buffer, uint32_t len) { + uint32_t errors = 0; + uint8_t *flash_read_data_char = (uint8_t *)flash_read_data; + + for (uint32_t i = 0; i < len; i++) { + if (test_buffer[i] != flash_read_data_char[i]) { + PRINTF("Error at position %d: expected %x, got %x\n", i, test_buffer[i], flash_read_data_char[i]); + errors++; + } + } + + if (errors == 0) { + PRINTF("success!\n"); + } else { + PRINTF("failure, %d errors!\n", errors); + } + + return errors; +} + +// Erase the memory only if FPGA is used +void erase_memory(uint32_t addr) { + #ifdef USE_SPI_FLASH + w25q128jw_4k_erase(addr); + #endif +} \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_spidma_powergate/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_spidma_powergate/main.c new file mode 100644 index 00000000..6e197adf --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_spidma_powergate/main.c @@ -0,0 +1,192 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include + +#include "x-heep.h" +#include "w25q128jw.h" +#include "csr.h" +#include "core_v_mini_mcu.h" +#include "power_manager.h" + +/* By default, PRINTFs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +#if defined(TARGET_PYNQ_Z2) || defined(TARGET_ZCU104) || defined(TARGET_NEXYS_A7_100T) + #define USE_SPI_FLASH +#endif + +#define FLASH_ONLY_WORDS 32 +#define FLASH_ONLY_BYTES (FLASH_ONLY_WORDS*4) + +uint32_t on_chip_buffer[FLASH_ONLY_WORDS]; + +int32_t __attribute__((section(".xheep_data_flash_only"))) __attribute__ ((aligned (16))) flash_only_buffer[FLASH_ONLY_WORDS] = { + 0xABCDEF00, + 0xABCDEF01, + 0xABCDEF02, + 0xABCDEF03, + 0xABCDEF04, + 0xABCDEF05, + 0xABCDEF06, + 0xABCDEF07, + 0xABCDEF08, + 0xABCDEF09, + 0xABCDEF0A, + 0xABCDEF0B, + 0xABCDEF0C, + 0xABCDEF0D, + 0xABCDEF0E, + 0xABCDEF0F, + 0xABCDEF10, + 0xABCDEF11, + 0xABCDEF12, + 0xABCDEF13, + 0xABCDEF14, + 0xABCDEF15, + 0xABCDEF16, + 0xABCDEF17, + 0xABCDEF18, + 0xABCDEF19, + 0xABCDEF1A, + 0xABCDEF1B, + 0xABCDEF1C, + 0xABCDEF1D, + 0xABCDEF1E, + 0xABCDEF1F, +}; + +int32_t __attribute__ ((aligned (16))) flash_only_buffer_golden_value[FLASH_ONLY_WORDS] = { + 0xABCDEF00, + 0xABCDEF01, + 0xABCDEF02, + 0xABCDEF03, + 0xABCDEF04, + 0xABCDEF05, + 0xABCDEF06, + 0xABCDEF07, + 0xABCDEF08, + 0xABCDEF09, + 0xABCDEF0A, + 0xABCDEF0B, + 0xABCDEF0C, + 0xABCDEF0D, + 0xABCDEF0E, + 0xABCDEF0F, + 0xABCDEF10, + 0xABCDEF11, + 0xABCDEF12, + 0xABCDEF13, + 0xABCDEF14, + 0xABCDEF15, + 0xABCDEF16, + 0xABCDEF17, + 0xABCDEF18, + 0xABCDEF19, + 0xABCDEF1A, + 0xABCDEF1B, + 0xABCDEF1C, + 0xABCDEF1D, + 0xABCDEF1E, + 0xABCDEF1F, +}; + + +int main(int argc, char *argv[]) +{ + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + + if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) { + PRINTF("This application cannot work with the memory mapped SPI FLASH" + "module - do not use the FLASH_EXEC linker script for this application\n"); + return EXIT_SUCCESS; + } + + // Pick the correct spi device based on simulation type + spi_host_t* spi; + #ifndef USE_SPI_FLASH + spi = spi_host1; + #else + spi = spi_flash; + #endif + + // Setup power_manager + power_manager_t power_manager; + mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); + power_manager.base_addr = power_manager_reg; + power_manager_counters_t power_manager_counters; + //counters + uint32_t reset_off, reset_on, switch_off, switch_on, iso_off, iso_on; + + //Turn off: first, isolate the CPU outputs, then I reset it, then I switch it off (reset and switch off order does not really matter) + iso_off = 10; + reset_off = iso_off + 5; + switch_off = reset_off + 5; + //Turn on: first, give back power by switching on, then deassert the reset, the unisolate the CPU outputs + switch_on = 10; + reset_on = switch_on + 20; //give 20 cycles to emulate the turn on time, this number depends on technology and here it is just a random number + iso_on = reset_on + 5; + + if (power_gate_counters_init(&power_manager_counters, reset_off, reset_on, switch_off, switch_on, iso_off, iso_on, 0, 0) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail. Check the reset and powergate counters value\n\r"); + return EXIT_FAILURE; + } + + // Define status variable + int32_t errors = 0; + + // Init SPI host and SPI<->Flash bridge parameters + if (w25q128jw_init(spi) != FLASH_OK) return EXIT_FAILURE; + + uint32_t *test_buffer_flash = heep_get_flash_address_offset(flash_only_buffer); + // Read from flash memory at the same address + w25q_error_codes_t status = w25q128jw_read_standard_dma_async(test_buffer_flash, on_chip_buffer, FLASH_ONLY_BYTES); + if (status != FLASH_OK) exit(EXIT_FAILURE); + + //wait for the DMA to finish in DEEP SLEEP mode + while (!dma_is_ready(0)) + { + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if (dma_is_ready(0) == 0) + { + PRINTF("Going to sleep...\r\n"); + if (power_gate_core(&power_manager, kDma_pm_e, &power_manager_counters) != kPowerManagerOk_e) + { + PRINTF("Error: power manager fail.\n\r"); + return EXIT_FAILURE; + } + PRINTF("Woken up...\r\n"); + + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + } + + + PRINTF("Check results...\r\n"); + + // Check if what we read is correct (i.e. on_chip_buffer == flash_only_buffer_golden_value) + for(int i = 0; i < FLASH_ONLY_WORDS; i++) { + if (on_chip_buffer[i] != flash_only_buffer_golden_value[i]) { + errors++; + PRINTF("Error: on_chip_buffer[%d] = 0x%08x, flash_only_buffer_golden_value[%d] = 0x%08x\n", i, on_chip_buffer[i], i, flash_only_buffer_golden_value[i]); + } + } + + if(errors==0) PRINTF("TEST RUN SUCCEFFULLY\r\n"); + + return errors; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_tensor_format_conv/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_tensor_format_conv/main.c new file mode 100644 index 00000000..575b8dee --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_tensor_format_conv/main.c @@ -0,0 +1,288 @@ +/* + * Copyright EPFL contributors. + * Licensed under the Apache License, Version 2.0, see LICENSE for details. + * SPDX-License-Identifier: Apache-2.0 + * + * Author: Tommaso Terzano + * + * + * Info: This application converts a HWC tensor to a CHW tensor and viceversa, leveraging the DMA subsytem. + * + * This is a simple example of a HWC tensor with 3 channels, 2 rows and 2 columns: + * (1, 2, 3) (4, 5, 6) + * (7, 8, 9) (10, 11, 12) + * (1, 2, 3) are the values of the first "pixel" of the tensor across different channels, 1 for CH0, 2 for CH1 and 3 for CH2. + * + * On the other hand, this is the same tensor represented with the CHW format: + * + * (1) (4) + * (7) (10) + * (2) (5) + * (8) (11) + * (3) (6) + * (9) (12) + * + * (1) is the first pixel of CH0, which is composed of the values 1, 4, 7, 10, and so on. + * + * The conversion hwc -> chw is performed in this manner: + * - Copy the first element (1) + * - Skip #channels elements + * - Copy the element (4) + * And so on. + * + * To speed the conversion up, the application makes use of the DMA. + * Its transposition function is used in an unconventional way: the d1 increment is set to #channels, while the d2 increment + * is set to 1. + * In this way, the DMA will copy H*W elements with a C stride, then start the next copy from the first element + 1, + * and repeat until completion. + * This behaviour is similar to a 3D copy, because it performs a copy of a matrix (H*W) with a stride (C), even if + * using just 2 counters. + * + * The conversion chw -> hwc is performed in a similar way, but it needs H loops, making it a lot slower than the other type + * of conversion. + */ + +#include +#include +#include "dma.h" +#include "core_v_mini_mcu.h" +#include "x-heep.h" +#include "csr.h" +#include "rv_plic.h" + +/* Uncomment to disable performance analysis */ +#define EN_PERF + +#define C 3 +#define H 4 +#define W 3 + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +/* CHW example array */ +int chw_array[36] = { + // Channel 1 + 7, 8, 5, // Row 1 + 9, 3, 6, // Row 2 + 2, 4, 1, // Row 3 + 8, 10, 12, // Row 4 + + // Channel 2 + 15, 16, 13, // Row 1 + 19, 11, 14, // Row 2 + 10, 18, 17, // Row 3 + 20, 22, 21, // Row 4 + + // Channel 3 + 23, 25, 24, // Row 1 + 28, 26, 27, // Row 2 + 29, 31, 30, // Row 3 + 32, 34, 33 // Row 4 +}; + +/* HWC example array */ +int hwc_array[36] = { + // Row 1 + 7, 15, 23, // W1C1, W1C2, W1C3 + 8, 16, 25, // W2C1, W2C2, W2C3 + 5, 13, 24, // W3C1, W3C2, W3C3 + + // Row 2 + 9, 19, 28, // W1C1, W1C2, W1C3 + 3, 11, 26, // W2C1, W2C2, W2C3 + 6, 14, 27, // W3C1, W3C2, W3C3 + + // Row 3 + 2, 10, 29, // W1C1, W1C2, W1C3 + 4, 18, 31, // W2C1, W2C2, W2C3 + 1, 17, 30, // W3C1, W3C2, W3C3 + + // Row 4 + 8, 20, 32, // W1C1, W1C2, W1C3 + 10, 22, 34, // W2C1, W2C2, W2C3 + 12, 21, 33 // W3C1, W3C2, W3C3 +}; + +int convert_hwc_to_chw_int32(int *src, int *dst) +{ + #ifdef EN_PERF + + /* Reset the counter to evaluate the performance of the DMA */ + CSR_CLEAR_BITS(CSR_REG_MCOUNTINHIBIT, 0x1); + CSR_WRITE(CSR_REG_MCYCLE, 0); + #endif + + static dma_target_t tgt_src; + static dma_target_t tgt_dst; + static dma_trans_t trans; + int res_valid, res_load, res_launch, cycles_dma; + + /* Initialize the targets */ + tgt_src.ptr = (uint8_t *) src; + tgt_src.inc_d1_du = 1; + tgt_src.inc_d2_du = C; + tgt_src.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE_WORD; + + tgt_dst.ptr = (uint8_t *) dst; + tgt_dst.inc_d1_du = 1; + tgt_dst.inc_d2_du = 1; + tgt_dst.trig = DMA_TRIG_MEMORY; + tgt_dst.type = DMA_DATA_TYPE_WORD; + + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.mode = DMA_TRANS_MODE_SINGLE; + trans.dim = DMA_DIM_CONF_2D; + trans.dim_inv = 1; // Enable transposition function + trans.size_d1_du = H * W; + trans.size_d2_du = C; + trans.win_du = 0, + trans.end = DMA_TRANS_END_INTR_WAIT; + + dma_init(NULL); + + res_valid = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + res_load = dma_load_transaction(&trans); + res_launch = dma_launch(&trans); + if (res_launch | res_load | res_valid) { + PRINTF("Error in the DMA transaction! %d - %d - %d\n", res_valid, res_load, res_launch); + exit(1); + } + + #ifdef EN_PERF + + /* Read the cycles count after the DMA run */ + CSR_READ(CSR_REG_MCYCLE, &cycles_dma); + return cycles_dma; + #endif + + return 0; +} + +int convert_chw_to_hwc_int32(int *src, int *dst) +{ + static dma_target_t tgt_src; + static dma_target_t tgt_dst; + static dma_trans_t trans; + int res_valid, res_load, res_launch, cycles_dma; + int * src_ptr = src; + int * dst_ptr = dst; + + #ifdef EN_PERF + + /* Reset the counter to evaluate the performance of the DMA */ + CSR_CLEAR_BITS(CSR_REG_MCOUNTINHIBIT, 0x1); + CSR_WRITE(CSR_REG_MCYCLE, 0); + #endif + + dma_init(NULL); + + for (int i=0; i < H; i++) { + + /* Initialize the targets */ + tgt_src.ptr = (uint8_t *) src_ptr; + tgt_src.inc_d1_du = 1; + tgt_src.inc_d2_du = H * W; + tgt_src.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE_WORD; + + tgt_dst.ptr = (uint8_t *) dst_ptr; + tgt_dst.inc_d1_du = 1; + tgt_dst.inc_d2_du = 1; + tgt_dst.trig = DMA_TRIG_MEMORY; + tgt_dst.type = DMA_DATA_TYPE_WORD; + + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.mode = DMA_TRANS_MODE_SINGLE; + trans.dim = DMA_DIM_CONF_2D; + trans.dim_inv = 1; // Enable transposition function + trans.size_d1_du = C; + trans.size_d2_du = W; + trans.win_du = 0, + trans.end = DMA_TRANS_END_INTR_WAIT; + + res_valid = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY); + res_load = dma_load_transaction(&trans); + res_launch = dma_launch(&trans); + if (res_launch | res_load | res_valid) { + PRINTF("Error in the DMA transaction! %d - %d - %d\n", res_valid, res_load, res_launch); + exit(1); + } + + src_ptr += W; + dst_ptr += W * C; + } + + #ifdef EN_PERF + + /* Read the cycles count after the DMA run */ + CSR_READ(CSR_REG_MCYCLE, &cycles_dma); + return cycles_dma; + #endif + + return 0; +} + +int main() +{ + int cycles_dma; + int dst_array[36]; + int passed_chw = 1; + int passed_hwc = 1; + + /* Convert HWC to CHW */ + cycles_dma = convert_hwc_to_chw_int32(hwc_array, dst_array); + + #ifdef EN_PERF + PRINTF("DMA cycles HWC -> CHW: %d\n\n\r", cycles_dma); + #endif + + /* Verify that the computed and the expected outputs are the same */ + for (int i = 0; i < H * W * C; i++) { + if (chw_array[i] != dst_array[i]) { + passed_chw = 0; + } + } + + /* Convert CHW to HWC */ + cycles_dma = convert_chw_to_hwc_int32(chw_array, dst_array); + + #ifdef EN_PERF + PRINTF("DMA cycles CHW -> HWC: %d\n\n\r", cycles_dma); + #endif + + /* Verify that the computed and the expected outputs are the same */ + for (int i = 0; i < H * W * C; i++) { + if (hwc_array[i] != dst_array[i]) { + passed_hwc = 0; + } + } + + if (passed_hwc && passed_chw) { + PRINTF("Success\n\n\r"); + } + else + { + if (!passed_hwc) { + PRINTF("Fail HWC -> CHW\n\r"); + } + if (!passed_chw) { + PRINTF("Fail CHW -> HWC\n\r"); + } + return EXIT_FAILURE; + } + + return 0; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_timer_sdk/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_timer_sdk/main.c new file mode 100644 index 00000000..cb5bb5ae --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/example_timer_sdk/main.c @@ -0,0 +1,126 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// File: example_timer_sdk.c +// Author: Juan Sapriza, Francesco Poluzzi +// Date: 23/07/2024 +// Description: Example application to test the Timer SDK. Will count the time to execute a few short tasks. + +#include +#include +#include +#include "core_v_mini_mcu.h" +#include "timer_sdk.h" +#include "x-heep.h" +#include "soc_ctrl.h" + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +/* Error tolerances for the tests. */ +#define CYCLE_TOLERANCE 2 // cycles tolerance for simple timer reads +#define INTERRUPT_TOLERANCE 70 // cycles tolerance for timer interrupt +#define TIMER_WAIT_TOLERANCE 20 // milliseconds tolerance for timer wait + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +void __attribute__((aligned(4), interrupt)) handler_irq_timer(void) { + timer_arm_stop(); + timer_irq_clear(); + return; +} + +int main(){ + uint32_t i = 0; + uint32_t timer_cycles; + uint32_t nop_cycles[4]; + + // Get current Frequency + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + uint32_t freq_hz = soc_ctrl_get_frequency(&soc_ctrl); + + timer_cycles_init(); // Init the timer SDK for clock cycles + timer_start(); // Start counting the time + nop_cycles[0] = timer_stop(); // Stop counting the time + PRINTF("0 NOPs:\t%d cc\n\r", nop_cycles[0] ); + + timer_start(); + asm volatile ("nop"); + nop_cycles[1] = timer_stop(); + PRINTF("1 NOP:\t%d cc\n\r", nop_cycles[1] ); + + timer_start(); + asm volatile ("nop"); + asm volatile ("nop"); + nop_cycles[2] = timer_stop(); + PRINTF("2 NOPs:\t%d cc\n\r", nop_cycles[2] ); + + timer_start(); + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); + nop_cycles[3] = timer_stop(); + PRINTF("3 NOPs:\t%d cc\n\r", nop_cycles[3] ); + + if( abs(nop_cycles[1] - nop_cycles[0])>CYCLE_TOLERANCE || abs(nop_cycles[2] - nop_cycles[1])>CYCLE_TOLERANCE || abs(nop_cycles[3] - nop_cycles[2])>CYCLE_TOLERANCE){ + PRINTF("Clock count failed\n\r"); + return EXIT_FAILURE; + } + + enable_timer_interrupt(); // Enable the timer machine-level interrupt + + timer_cycles_init(); + timer_irq_enable(); + timer_arm_start(1000); + asm volatile ("wfi"); // Wait for interrupt + timer_cycles = timer_stop(); + if(abs(timer_cycles-1000) < INTERRUPT_TOLERANCE){ + PRINTF("Timer threshold interrupt working\n" ); + } else { + PRINTF("Timer threshold interrupt failed\n\r"); + return EXIT_FAILURE; + } + + timer_cycles_init(); // Init the timer SDK for microseconds + timer_start(); + for(i = 0; i < 1000; i++){ + asm volatile ("nop"); + } + timer_cycles = timer_stop(); + PRINTF("Microseconds for 1000 NOPs:\t%d μs\n\r", (uint32_t)get_time_from_cycles(timer_cycles) ); + + #ifdef TARGET_IS_FPGA + PRINTF("Wait 5 second\n\r"); + timer_wait_us(5000000); // Wait for 5 seconds + timer_cycles = timer_stop(); + PRINTF("Done\n\r"); + + if(abs(timer_cycles-(5*freq_hz)) > TIMER_WAIT_TOLERANCE){ + PRINTF("Timer wait failed\n\r"); + return EXIT_FAILURE; + } + #endif + #ifdef TARGET_SIM // Reduced time for simulation for faster testing + PRINTF("Wait 0.001 second\n\r"); + timer_wait_us(1000); // Wait for 1 millisecond + timer_cycles = timer_stop(); + PRINTF("Done\n\r"); + + if(abs(timer_cycles-(0.001*freq_hz)) > TIMER_WAIT_TOLERANCE){ + PRINTF("Timer wait failed\n\r"); + return EXIT_FAILURE; + } + #endif + + PRINTF("All tests passed\n\r"); + return EXIT_SUCCESS; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/example_virtual_flash/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/example_virtual_flash/main.c deleted file mode 100644 index e1e16f56..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/example_virtual_flash/main.c +++ /dev/null @@ -1,222 +0,0 @@ - -#include -#include -#include "csr.h" -#include "hart.h" -#include "handler.h" -#include "core_v_mini_mcu.h" -#include "rv_timer.h" -#include "rv_timer_regs.h" -#include "soc_ctrl.h" -#include "rv_plic.h" -#include "rv_plic_regs.h" -#include "spi_host.h" -#include "spi_host_regs.h" -#include "dma.h" -#include "fast_intr_ctrl.h" -#include "gpio.h" -#include "fast_intr_ctrl_regs.h" -#include "x-heep.h" - -#define REVERT_24b_ADDR(addr) ((((uint32_t)addr & 0xff0000) >> 16) | ((uint32_t)addr & 0xff00) | (((uint32_t)addr & 0xff) << 16)) -#define FLASH_ADDR 0x00000000 -#define FLASH_SIZE 64 * 1024 * 1024 -#define FLASH_CLK_MAX_HZ (133 * 1000 * 1000) - - -/* By default, printfs are activated for FPGA and disabled for simulation. */ -#define PRINTF_IN_FPGA 1 -#define PRINTF_IN_SIM 0 - -#if TARGET_SIM && PRINTF_IN_SIM - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA - #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else - #define PRINTF(...) -#endif - -// Interrupt controller variables -plic_result_t plic_res; -uint32_t intr_num; - -//volatile int8_t timer_flag; -volatile int8_t spi_intr_flag; - -spi_host_t spi_host_flash; - -void dma_intr_handler_trans_done(){ - PRINTF("#\n\r"); -} - -void fic_irq_spi_flash(){ - // Disable SPI interrupts - spi_enable_evt_intr(&spi_host_flash, false); - spi_enable_rxwm_intr(&spi_host_flash, false); - spi_intr_flag = 1; - PRINTF("@\n\r"); -} - - -void write_to_flash(spi_host_t *SPI, uint16_t *data, uint32_t byte_count, uint32_t addr) -{ - uint32_t write_to_mem = 0x02; - spi_write_word(SPI, write_to_mem); - uint32_t cmd_write_to_mem = spi_create_command((spi_command_t){ - .len = 0, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(SPI, cmd_write_to_mem); - spi_wait_for_ready(SPI); - - uint32_t addr_cmd = __builtin_bswap32(addr); - spi_write_word(SPI, addr_cmd); - uint32_t cmd_address = spi_create_command((spi_command_t){ - .len = 3, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(SPI, cmd_address); - spi_wait_for_ready(SPI); - - uint32_t *fifo_ptr_tx = SPI->base_addr.base + SPI_HOST_TXDATA_REG_OFFSET; - - // -- DMA CONFIGURATION -- - dma_init(NULL); - - dma_target_t tgt_src = { - .ptr = data, - .inc_du = 1, - .size_du = 64, - .type = DMA_DATA_TYPE_HALF_WORD, - .trig = DMA_TRIG_MEMORY, - }; - dma_target_t tgt_dst = { - .ptr = fifo_ptr_tx, - .inc_du = 0, - .size_du = 0, - .type = DMA_DATA_TYPE_HALF_WORD, - .trig = DMA_TRIG_SLOT_SPI_FLASH_TX, - }; - dma_trans_t trans = { - .src = &tgt_src, - .dst = &tgt_dst, - .end = DMA_TRANS_END_INTR, - }; - - dma_config_flags_t res; - - spi_intr_flag = 0; - - res = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); - PRINTF("trans: %u\n\r", res ); - res = dma_load_transaction(&trans); - PRINTF("load: %u\n\r", res ); - res = dma_launch(&trans); - - // Wait for the first data to arrive to the TX FIFO before enabling interrupt - spi_wait_for_tx_not_empty(SPI); - // Enable event interrupt - spi_enable_evt_intr(SPI, true); - // Enable TX empty interrupt - spi_enable_txempty_intr(SPI, true); - - const uint32_t cmd_write_tx = spi_create_command((spi_command_t){ - .len = byte_count - 1, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(SPI, cmd_write_tx); - spi_wait_for_ready(SPI); - - // Wait for SPI interrupt - while(spi_intr_flag == 0) { - wait_for_interrupt(); - } - - PRINTF("%d words written to flash.\n\n\r", byte_count/4); -} - -int main(int argc, char *argv[]) -{ - // Get current Frequency - soc_ctrl_t soc_ctrl; - soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - soc_ctrl_select_spi_host(&soc_ctrl); - - uint32_t core_clk = soc_ctrl_get_frequency(&soc_ctrl); - - // Enable interrupt on processor side - // Enable global interrupt for machine-level interrupts - CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - uint32_t mask = 1 << 21; - CSR_SET_BITS(CSR_REG_MIE, mask); - spi_intr_flag = 0; - // Set mie.MEIE bit to one to enable timer interrupt - mask = 1 << 7; - CSR_SET_BITS(CSR_REG_MIE, mask); - - spi_host_flash.base_addr = mmio_region_from_addr((uintptr_t)SPI_HOST_START_ADDRESS); - spi_set_enable(&spi_host_flash, true); - spi_output_enable(&spi_host_flash, true); - - uint16_t clk_div = 0; - if (FLASH_CLK_MAX_HZ < core_clk / 2) - { - clk_div = (core_clk / (FLASH_CLK_MAX_HZ)-2) / 2; // The value is truncated - if (core_clk / (2 + 2 * clk_div) > FLASH_CLK_MAX_HZ) - clk_div += 1; // Adjust if the truncation was not 0 - } - - // SPI Configuration - // Configure chip 0 (flash memory) - const uint32_t chip_cfg_flash = spi_create_configopts((spi_configopts_t){ - .clkdiv = clk_div, - .csnidle = 0xF, - .csntrail = 0xF, - .csnlead = 0xF, - .fullcyc = false, - .cpha = 0, - .cpol = 0}); - spi_set_configopts(&spi_host_flash, 0, chip_cfg_flash); - spi_set_csid(&spi_host_flash, 0); - - // To set the number of dummy cycles we have to send command 0x11 and then a 1B value - const uint32_t reset_cmd = 0x11; - spi_write_word(&spi_host_flash, reset_cmd); - const uint32_t cmd_reset = spi_create_command((spi_command_t){ - .len = 0, - .csaat = true, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - spi_set_command(&spi_host_flash, cmd_reset); - spi_wait_for_ready(&spi_host_flash); - - const uint32_t set_dummy_cycle = 0x07; - spi_write_word(&spi_host_flash, set_dummy_cycle); - const uint32_t cmd_set_dummy = spi_create_command((spi_command_t){ - .len = 0, - .csaat = false, - .speed = kSpiSpeedStandard, - .direction = kSpiDirTxOnly - }); - - spi_set_command(&spi_host_flash, cmd_set_dummy); - spi_wait_for_ready(&spi_host_flash); - - uint32_t results[32]; - for(uint32_t i = 0; i < 32; i++){ - results[i] = i; - } - - write_to_flash(&spi_host_flash, results, sizeof(*results) * 32, FLASH_ADDR); - - PRINTF("Success.\n\r"); - - return EXIT_SUCCESS; -} diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/hello_world/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/hello_world/main.c index e6133973..bbe2f071 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/applications/hello_world/main.c +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/hello_world/main.c @@ -25,4 +25,3 @@ int main(int argc, char *argv[]) printf("hello world!\n"); return EXIT_SUCCESS; } - diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/arch.cfg b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/arch.cfg new file mode 100644 index 00000000..0583bdfe --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/arch.cfg @@ -0,0 +1,67 @@ +############################################################################### +# +# Copyright 2020 OpenHW Group +# +# Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://solderpad.org/licenses/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +# +############################################################################### + +# This is a python setting of parameters for the architecture. The following +# parameters may be set (other keys are silently ignored). Defaults are shown +# in brackets +# - cc ('cc') +# - ld (same value as for cc) +# - cflags ([]) +# - ldflags ([]) +# - cc_define_pattern ('-D{0}') +# - cc_incdir_pattern ('-I{0}') +# - cc_input_pattern ('{0}') +# - cc_output_pattern ('-o {0}') +# - ld_input_pattern ('{0}') +# - ld_output_pattern ('-o {0}') +# - user_libs ([]) +# - dummy_libs ([]) +# - cpu_mhz (1) +# - warmup_heat (1) + +# The "flags" and "libs" parameters (cflags, ldflags, user_libs, dummy_libs) +# should be lists of arguments to be passed to the compile or link line as +# appropriate. Patterns are Python format patterns used to create arguments. +# Thus for GCC or Clang/LLVM defined constants can be passed using the prefix +# '-D', and the pattern '-D{0}' would be appropriate (which happens to be the +# default). + +# "user_libs" may be absolute file names or arguments to the linker. In the +# latter case corresponding arguments in ldflags may be needed. For example +# with GCC or Clang/LLVM is "-l" flags are used in "user_libs", the "-L" flags +# may be needed in "ldflags". + +# Dummy libs have their source in the "support" subdirectory. Thus if 'crt0' +# is specified, there should be a source file 'dummy-crt0.c' in the support +# directory. + +# There is no need to set an unused parameter, and this file may be empty to +# set no flags. + +# Parameter values which are duplicated in architecture, board, chip or +# command line are used in the following order of priority +# - default value +# - architecture specific value +# - chip specific value +# - board specific value +# - command line value + +# For flags, this priority is applied to individual flags, not the complete +# list of flags. diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.c new file mode 100644 index 00000000..5e55329f --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.c @@ -0,0 +1,177 @@ +/* BEEBS local library variants + + Copyright (C) 2019 Embecosm Limited. + + Contributor Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later */ + +/* These are very simple local versions of library routines, to ensure the + code is compiled with the flags used for the benchmark. Not all library + routines are here, just ones that cause a lot of unecessary load, or where + there is variation between platforms and architectures. */ + +#include +#include +#include "beebsc.h" + +/* Seed for the random number generator */ + +static long int seed = 0; + +/* Heap records and sane initial values */ + +static void *heap_ptr = NULL; +static void *heap_end = NULL; +static size_t heap_requested = 0; + + +/* Yield a sequence of random numbers in the range [0, 2^15-1]. + + long int is guaranteed to be at least 32 bits. The seed only ever uses 31 + bits (so is positive). + + For BEEBS this gets round different operating systems using different + multipliers and offsets and RAND_MAX variations. */ + +int +rand_beebs (void) +{ + seed = (seed * 1103515245L + 12345) & ((1UL << 31) - 1); + return (int) (seed >> 16); +} + + +/* Initialize the random number generator */ + +void +srand_beebs (unsigned int new_seed) +{ + seed = (long int) new_seed; +} + + +/* Initialize the BEEBS heap pointers. Note that the actual memory block is + in the caller code. */ + +void +init_heap_beebs (void *heap, size_t heap_size) +{ + heap_ptr = (void *) heap; + heap_end = (void *) ((char *) heap_ptr + heap_size); + heap_requested = 0; +} + + +/* Report if malloc ever failed. + + Return non-zero (TRUE) if malloc did not reqest more than was available + since the last call to init_heap_beebs, zero (FALSE) otherwise. */ + +int +check_heap_beebs (void *heap) +{ + return ((void *) ((char *) heap + heap_requested) <= heap_end); +} + + +/* BEEBS version of malloc. + + This is primarily to reduce library and OS dependencies. Malloc is + generally not used in embedded code, or if it is, only in well defined + contexts to pre-allocate a fixed amount of memory. So this simplistic + implementation is just fine. + + Note in particular the assumption that memory will never be freed! */ + +void * +malloc_beebs (size_t size) +{ + void *new_ptr = heap_ptr; + + heap_requested += size; + + if (((void *) ((char *) heap_ptr + size) > heap_end) || (0 == size)) + return NULL; + else + { + heap_ptr = (void *) ((char *) heap_ptr + size); + return new_ptr; + } +} + + +/* BEEBS version of calloc. + + Implement as wrapper for malloc */ + +void * +calloc_beebs (size_t nmemb, size_t size) +{ + void *new_ptr = malloc_beebs (nmemb * size); + + /* Calloc is defined to zero the memory. OK to use a function here, because + it will be handled specially by the compiler anyway. */ + + if (NULL != new_ptr) + memset (new_ptr, 0, nmemb * size); + + return new_ptr; +} + + +/* BEEBS version of realloc. + + This is primarily to reduce library and OS dependencies. We just have to + allocate new memory and copy stuff across. */ + +void * +realloc_beebs (void *ptr, size_t size) +{ + void *new_ptr = heap_ptr; + + heap_requested += size; + + if (((void *) ((char *) heap_ptr + size) > heap_end) || (0 == size)) + return NULL; + else + { + heap_ptr = (void *) ((char *) heap_ptr + size); + + /* This is clunky, since we don't know the size of the original + pointer. However it is a read only action and we know it must + be big enough if we right off the end, or we couldn't have + allocated here. If the size is smaller, it doesn't matter. */ + + if (NULL != ptr) + { + size_t i; + + for (i = 0; i < size; i++) + ((char *) new_ptr)[i] = ((char *) ptr)[i]; + } + + return new_ptr; + } +} + + +/* BEEBS version of free. + + For our simplified version of memory handling, free can just do nothing. */ + +void +free_beebs (void *ptr __attribute__ ((unused))) +{ +} + + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.h b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.h new file mode 100644 index 00000000..4a108959 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/beebsc.h @@ -0,0 +1,65 @@ +/* BEEBS local library variants header + + Copyright (C) 2019 Embecosm Limited. + + Contributor Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later */ + +#ifndef BEEBSC_H +#define BEEBSC_H + +#include + +/* BEEBS fixes RAND_MAX to its lowest permitted value, 2^15-1 */ + +#ifdef RAND_MAX +#undef RAND_MAX +#endif +#define RAND_MAX ((1U << 15) - 1) + +/* Common understanding of a "small value" (epsilon) for floating point + comparisons. */ + +#define VERIFY_DOUBLE_EPS 1.0e-13 +#define VERIFY_FLOAT_EPS 1.0e-5 + +/* Simplified assert. + + The full complexity of assert is not needed for a benchmark. See the + discussion at: + + https://lists.librecores.org/pipermail/embench/2019-August/000007.html + + This function just*/ + +#define assert_beebs(expr) { if (!(expr)) exit (1); } + +#define float_eq_beebs(exp, actual) (fabsf(exp - actual) < VERIFY_FLOAT_EPS) +#define float_neq_beebs(exp, actual) !float_eq_beebs(exp, actual) +#define double_eq_beebs(exp, actual) (fabs(exp - actual) < VERIFY_DOUBLE_EPS) +#define double_neq_beebs(exp, actual) !double_eq_beebs(exp, actual) + +/* Local simplified versions of library functions */ + +int rand_beebs (void); +void srand_beebs (unsigned int new_seed); + +void init_heap_beebs (void *heap, const size_t heap_size); +int check_heap_beebs (void *heap); +void *malloc_beebs (size_t size); +void *calloc_beebs (size_t nmemb, size_t size); +void *realloc_beebs (void *ptr, size_t size); +void free_beebs (void *ptr); +#endif /* BEEBSC_H */ + + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/board.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/board.c new file mode 100644 index 00000000..db8fafa8 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/board.c @@ -0,0 +1,22 @@ +/* Common board.c for the benchmarks + + Copyright (C) 2018-2019 Embecosm Limited + + Contributor: Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later */ + +/* This is just a wrapper for the board specific support file. */ + +#include "boardsupport.c" + + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.c new file mode 100644 index 00000000..f2e674de --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.c @@ -0,0 +1,21 @@ +/* +** +** Copyright 2020 OpenHW Group +** +** Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** https://solderpad.org/licenses/ +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +******************************************************************************* +*/ + +#include "boardsupport.h" + diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.h b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.h new file mode 100644 index 00000000..6223cd68 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/boardsupport.h @@ -0,0 +1,21 @@ +/* +** +** Copyright 2020 OpenHW Group +** +** Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** https://solderpad.org/licenses/ +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +******************************************************************************* +*/ + + + diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chip.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chip.c new file mode 100644 index 00000000..37ac28fe --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chip.c @@ -0,0 +1,32 @@ +/* Common board.c for the benchmarks + + Copyright (C) 2018-2019 Embecosm Limited + + Contributor: Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later */ + +/* This is just a wrapper for the chip specific support file if there is one. */ + +/*#include "config.h"*/ + +#ifdef HAVE_CHIPSUPPORT_H +#include "chipsupport.c" +#endif + +/* Standard C does not permit empty translation units, so provide one. */ + +static void +empty_func () +{ +} + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.c new file mode 100644 index 00000000..181a3dd9 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.c @@ -0,0 +1,73 @@ +/* +** +** Copyright 2020 OpenHW Group +** +** Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** https://solderpad.org/licenses/ +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +******************************************************************************* +*/ + +#include +#include +#include +#include "chipsupport.h" + +#include "csr.h" +#include "x-heep.h" + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +#define FS_INITIAL 0x01 + +void +initialise_board () +{ + PRINTF("Initialize board corev32 \n"); + + //enable FP operations + CSR_SET_BITS(CSR_REG_MSTATUS, (FS_INITIAL << 13)); + +} + +void __attribute__ ((noinline)) __attribute__ ((externally_visible)) +start_trigger () +{ + PRINTF("start of test \n"); + + // Enable mcycle counter and read value + CSR_CLEAR_BITS(CSR_REG_MCOUNTINHIBIT, 0x1); + CSR_WRITE(CSR_REG_MCYCLE, 0); + +} + +void __attribute__ ((noinline)) __attribute__ ((externally_visible)) +stop_trigger () +{ + uint32_t cycle_cnt; + CSR_READ(CSR_REG_MCYCLE, &cycle_cnt); + PRINTF("end of test \n"); + PRINTF("Result is given in CPU cycles \n"); + PRINTF("RES: %d \n", cycle_cnt); + +} + diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.h b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.h new file mode 100644 index 00000000..bd174c31 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/chipsupport.h @@ -0,0 +1,25 @@ +/* +** +** Copyright 2020 OpenHW Group +** +** Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** https://solderpad.org/licenses/ +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +******************************************************************************* +*/ + +#ifndef CHIPSUPPORT_H +#define CHIPSUPPORT_H + +#define CPU_MHZ 1 + +#endif diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/libminver.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/libminver.c new file mode 100644 index 00000000..0cabd55b --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/libminver.c @@ -0,0 +1,292 @@ +/* BEEBS minver benchmark + + This version, copyright (C) 2014-2019 Embecosm Limited and University of + Bristol + + Contributor Pierre Langlois + Contributor Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later + + ************************************************************************* + * * + * SNU-RT Benchmark Suite for Worst Case Timing Analysis * + * ===================================================== * + * Collected and Modified by S.-S. Lim * + * sslim@archi.snu.ac.kr * + * Real-Time Research Group * + * Seoul National University * + * * + * * + * < Features > - restrictions for our experimental environment * + * * + * 1. Completely structured. * + * - There are no unconditional jumps. * + * - There are no exit from loop bodies. * + * (There are no 'break' or 'return' in loop bodies) * + * 2. No 'switch' statements. * + * 3. No 'do..while' statements. * + * 4. Expressions are restricted. * + * - There are no multiple expressions joined by 'or', * + * 'and' operations. * + * 5. No library calls. * + * - All the functions needed are implemented in the * + * source file. * + * * + * * + ************************************************************************* + * * + * FILE: minver.c * + * SOURCE : Turbo C Programming for Engineering by Hyun Soo Ahn * + * * + * DESCRIPTION : * + * * + * Matrix inversion for 3x3 floating point matrix. * + * * + * REMARK : * + * * + * EXECUTION TIME : * + * * + * * + ************************************************************************* + +*/ + +#include +#include +#include "support.h" + +/* This scale factor will be changed to equalise the runtime of the + benchmarks. */ +#define LOCAL_SCALE_FACTOR 555 + +int minver (int row, int col, float eps); +int mmul (int row_a, int col_a, int row_b, int col_b); + +static float a_ref[3][3] = { + {3.0, -6.0, 7.0}, + {9.0, 0.0, -5.0}, + {5.0, -8.0, 6.0}, +}; + +static float b[3][3] = { + {-3.0, 0.0, 2.0}, + {3.0, -2.0, 0.0}, + {0.0, 2.0, -3.0}, +}; + +static float a[3][3], c[3][3], d[3][3], det; + +static float +minver_fabs (float n) +{ + float f; + + if (n >= 0) + f = n; + else + f = -n; + return f; +} + +int +mmul (int row_a, int col_a, int row_b, int col_b) +{ + int i, j, k, row_c, col_c; + float w; + + row_c = row_a; + col_c = col_b; + + if (row_c < 1 || row_b < 1 || col_c < 1 || col_a != row_b) + return (999); + for (i = 0; i < row_c; i++) + { + for (j = 0; j < col_c; j++) + { + w = 0.0; + for (k = 0; k < row_b; k++) + w += a[i][k] * b[k][j]; + c[i][j] = w; + } + } + + return (0); +} + + +int +minver (int row, int col, float eps) +{ + int work[500], i, j, k, r, iw, u, v; + float w, wmax, pivot, api, w1; + + r = w = 0; + if (row < 2 || row > 500 || eps <= 0.0) + return (999); + w1 = 1.0; + for (i = 0; i < row; i++) + work[i] = i; + for (k = 0; k < row; k++) + { + wmax = 0.0; + for (i = k; i < row; i++) + { + w = minver_fabs (a[i][k]); + if (w > wmax) + { + wmax = w; + r = i; + } + } + pivot = a[r][k]; + api = minver_fabs (pivot); + if (api <= eps) + { + det = w1; + return (1); + } + w1 *= pivot; + u = k * col; + v = r * col; + if (r != k) + { + w1 = -w; + iw = work[k]; + work[k] = work[r]; + work[r] = iw; + for (j = 0; j < row; j++) + { + w = a[k][j]; + a[k][j] = a[r][j]; + a[r][j] = w; + } + } + for (i = 0; i < row; i++) + a[k][i] /= pivot; + for (i = 0; i < row; i++) + { + if (i != k) + { + v = i * col; + w = a[i][k]; + if (w != 0.0) + { + for (j = 0; j < row; j++) + if (j != k) + a[i][j] -= w * a[k][j]; + a[i][k] = -w / pivot; + } + } + } + a[k][k] = 1.0 / pivot; + } + + for (i = 0; i < row; i++) + { + while (1) + { + k = work[i]; + if (k == i) + break; + iw = work[k]; + work[k] = work[i]; + work[i] = iw; + for (j = 0; j < row; j++) + { + u = j * col; + w = a[k][i]; + a[k][i] = a[k][k]; + a[k][k] = w; + } + } + } + + det = w1; + + return (0); +} + + +int +verify_benchmark (int res __attribute ((unused))) +{ + int i, j; + float eps = 1.0e-6; + + static float c_exp[3][3] = { + {-27.0, 26.0, -15.0}, + {-27.0, -10.0, 33.0}, + {-39.0, 28.0, -8.0} + }; + + static float d_exp[3][3] = { + {0.133333325, -0.199999958, 0.2666665910}, + {-0.519999862, 0.113333330, 0.5266665220}, + {0.479999840, -0.359999895, 0.0399999917} + }; + + /* Allow small errors in floating point */ + + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + if (float_neq_beebs(c[i][j], c_exp[i][j]) || float_neq_beebs(d[i][j], d_exp[i][j])) + return 0; + + return float_eq_beebs(det, -16.6666718); +} + + +void +initialise_benchmark (void) +{ +} + + +static int benchmark_body (int rpt); + +void +warm_caches (int heat) +{ + int res = benchmark_body (heat); + + return; +} + + +int +benchmark (void) +{ + return benchmark_body (LOCAL_SCALE_FACTOR * 1); +} + + +static int __attribute__ ((noinline)) +benchmark_body (int rpt) +{ + int i; + + for (i = 0; i < rpt; i++) + { + float eps = 1.0e-6; + + memcpy (a, a_ref, 3 * 3 * sizeof (a[0][0])); + minver (3, 3, eps); + memcpy (d, a, 3 * 3 * sizeof (a[0][0])); + memcpy (a, a_ref, 3 * 3 * sizeof (a[0][0])); + mmul (3, 3, 3, 3); + } + + return 0; +} + + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/main.c b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/main.c new file mode 100644 index 00000000..64566101 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/main.c @@ -0,0 +1,50 @@ +/* Common main.c for the benchmarks + + Copyright (C) 2014 Embecosm Limited and University of Bristol + Copyright (C) 2018-2019 Embecosm Limited + + Contributor: James Pallister + Contributor: Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later */ + +#include "csr.h" +#include "x-heep.h" + +#include "support.h" + + +int __attribute__ ((used)) +main (int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + int i; + volatile int result; + int correct; + + initialise_board (); + initialise_benchmark (); + warm_caches (1); + + start_trigger (); + result = benchmark (); + stop_trigger (); + + /* bmarks that use arrays will check a global array rather than int result */ + + correct = verify_benchmark (result); + + return (!correct); + +} /* main () */ + + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/applications/minver/support.h b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/support.h new file mode 100644 index 00000000..b68b81e6 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/applications/minver/support.h @@ -0,0 +1,72 @@ +/* Support header for BEEBS. + + Copyright (C) 2014 Embecosm Limited and the University of Bristol + Copyright (C) 2019 Embecosm Limited + + Contributor James Pallister + + Contributor Jeremy Bennett + + This file is part of Embench and was formerly part of the Bristol/Embecosm + Embedded Benchmark Suite. + + SPDX-License-Identifier: GPL-3.0-or-later */ + +#ifndef SUPPORT_H +#define SUPPORT_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Include board support header if we have one */ + +#ifdef HAVE_BOARDSUPPORT_H +#include "boardsupport.h" +#endif + +/* Benchmarks must implement verify_benchmark, which must return -1 if no + verification is done. */ + +int verify_benchmark (int result); + +/* Standard functions implemented for each board */ + +void initialise_board (void); +void start_trigger (void); +void stop_trigger (void); + +/* Every benchmark implements this for one-off data initialization. This is + only used for initialization that is independent of how often benchmark () + is called. */ + +void initialise_benchmark (void); + +/* Every benchmark implements this for cache warm up, typically calling + benchmark several times. The argument controls how much warming up is + done, with 0 meaning no warming. */ + +void warm_caches (int temperature); + +/* Every benchmark implements this as its entry point. Don't allow it to be + inlined! */ + +int benchmark (void) __attribute__ ((noinline)); + +/* Every benchmark must implement this to validate the result of the + benchmark. */ + +int verify_benchmark (int res); + +/* Local simplified versions of library functions */ + +#include "beebsc.h" + +#endif /* SUPPORT_H */ + +/* + Local Variables: + mode: C + c-file-style: "gnu" + End: +*/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/cmake/riscv.cmake b/hw/vendor/esl_epfl_x_heep/sw/cmake/riscv.cmake index 5c9d070d..972710f5 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/cmake/riscv.cmake +++ b/hw/vendor/esl_epfl_x_heep/sw/cmake/riscv.cmake @@ -43,7 +43,7 @@ get_filename_component(RISCV_TOOLCHAIN_BIN_EXT ${RISCV_GCC_COMPILER} EXT) #message( "RISC-V GCC Path: ${RISCV_TOOLCHAIN_BIN_PATH}" ) -STRING(REGEX REPLACE "\-gcc" "-" GCC_CROSS_COMPILE ${RISCV_GCC_COMPILER}) +STRING(REGEX REPLACE "\-gcc$" "-" GCC_CROSS_COMPILE ${RISCV_GCC_COMPILER}) if ($ENV{COMPILER} MATCHES "clang") STRING(REGEX REPLACE "clang" "" CLANG_CROSS_COMPILE ${RISCV_CLANG_COMPILER}) endif() diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q.c b/hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q.c new file mode 100644 index 00000000..f6a3ac99 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q.c @@ -0,0 +1,1562 @@ +/* + ******************* +******************************* C SOURCE FILE ***************************** +** ******************* +** +** project : X-HEEP +** filename : w25q.c +** version : 1 +** date : 1/11/2023 +** +*************************************************************************** +** +** Copyright (c) EPFL contributors. +** All rights reserved. +** +*************************************************************************** +*/ + +/***************************************************************************/ +/***************************************************************************/ +/** +* @file w25q.c +* @date 1/11/2023 +* @brief Source file of the W25Q-family flash memory driver. +*/ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/****************************************************************************/ +/** **/ +/* MODULES USED */ +/** **/ +/****************************************************************************/ +#include "string.h" + +#include "w25q128jw.h" + +/* To manage addresses. */ +#include "mmio.h" + +/* To manage interrupts. */ +#include "fast_intr_ctrl.h" +#include "csr.h" +#include "stdasm.h" + +/* To manage DMA. */ +#include "dma.h" + +/* To get TX and RX FIFO depth */ +#include "spi_host_regs.h" +/* To get SPI functions */ +#include "spi_host.h" + +/* To get the target of the compilation (sim or pynq) */ +#include "x-heep.h" + +/* To get the soc_ctrl base address */ +#include "soc_ctrl_structs.h" + +/* For word swap operations*/ +#include "bitfield.h" + +/****************************************************************************/ +/** **/ +/* DEFINITIONS AND MACROS */ +/** **/ +/****************************************************************************/ + +/** + * The flash is expecting the address in Big endian format, so a swap is needed + * in order to provide the MSB first. + * Shift is needed as the byteswap is performed on 32-bit words. +*/ +#define REVERT_24b_ADDR(addr) (bitfield_byteswap32(addr) >> 8) + +/** + * @bref If the target is the FPGA, use the SPI FLASH. +*/ +#ifndef TARGET_SIM +#define USE_SPI_FLASH +#endif + +/****************************************************************************/ +/** **/ +/* PROTOTYPES OF LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + +/** + * @brief Power up the flash. +*/ +static void flash_power_up(void); + +/** + * @brief Set the QE bit in the flash status register. + * + * @return FLASH_OK if the QE bit is set, @ref error_codes otherwise. +*/ +static w25q_error_codes_t set_QE_bit(void); + +/** + * @brief Configure the SPI<->Flash connection paramethers. +*/ +static void configure_spi(void); + +/** + * @brief Wait for the flash to be ready. + * + * It pools the BUSY bit in the flash status register. + * It is not checking the SUS bit status. +*/ +static void flash_wait(void); + +/** + * @brief Reset the flash. +*/ +static void flash_reset(void); + +/** + * @brief Erase the flash and write the data. + * + * It read 4k (a sector) at a time, erase it and write the data back. + * Befor writing the data back, it modifies the buffer in order to + * add the new data without modifing the other bytes. All the bytes + * that are not going to be modified will be copied back as is. + * + * @param addr 24-bit address to write to. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +static w25q_error_codes_t erase_and_write(uint32_t addr, uint8_t *data ,uint32_t length); + +/** + * @brief Wrapper for page write. + * + * It performs the sanity checks and calls the page_write function with + * the correct speed paramether. A wrapper is necessary as it is not possible + * to program more than a page (256 bytes) at a time. So multiple calls + * to page_write can be needed. + * + * @param addr 24-bit address to write to. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @param quad if 1, the write is performed at quad speed. + * @param dma if 1, the write is performed using DMA. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +static w25q_error_codes_t page_write_wrapper(uint32_t addr, uint8_t *data, uint32_t length, uint8_t quad, uint8_t dma); + +/** + * @brief Write (up to) a page to the flash. + * + * @param addr 24-bit address to write to. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @param quad if 1, the write is performed at quad speed. + * @param dma if 1, the write is performed using DMA. +*/ +static w25q_error_codes_t page_write(uint32_t addr, uint8_t *data, uint32_t length, uint8_t quad, uint8_t dma); + +/** + * @brief Copy length bytes from data to the SPI TX FIFO, using DMA. + * + * @param data pointer to the data buffer. + * @param length number of bytes to copy. + + * @return FLASH_OK if the operation is successful, @ref error_codes otherwise. +*/ +static w25q_error_codes_t dma_send_toflash(uint8_t *data, uint32_t length); + +/** + * @brief Enable flash write. + * + * It sets the WEL bit in the flash status register. + * Every action that require the WEL to be set is goig to automatically + * clear it. +*/ +static void flash_write_enable(void); + +/** + * @brief Performs sanity checks on the input parameters. + * + * Checks if the address is valid, the data pointer is not NULL + * and the length is not 0. + * + * @param addr 24-bit address. + * @param data pointer to the data buffer. + * @param length number of bytes to read/write. + * @return FLASH_OK if the sanity checks are passed, @ref error_codes otherwise. +*/ +static w25q_error_codes_t w25q128jw_sanity_checks(uint32_t addr, uint8_t *data, uint32_t length); + +/** + * @brief Return the minimum between two numbers. + * + * The function uses signed integers in order to handle also negative numbers. + * + * @param a first number. + * @param b second number. + * @return the minimum between a and b. +*/ +static int32_t MIN(int32_t a, int32_t b) { + return (a < b) ? a : b; +} + + +/****************************************************************************/ +/** **/ +/* GLOBAL VARIABLES */ +/** **/ +/****************************************************************************/ + +/** + * @brief SPI structure. +*/ +spi_host_t* __attribute__((section(".xheep_init_data_crt0"))) spi; //this variable is also used by the crt0, thus keep it in this section + +/** + * @brief Static vector used in the erase_and_write function. + * + * It is used to store the data of a sector (4k) of the flash. Given the dimensions + * of the vector, is not possible to allocate it dinamically as it would cause a stack + * or heap overflow. +*/ +uint8_t sector_data[FLASH_SECTOR_SIZE]; + + +/****************************************************************************/ +/** **/ +/* EXPORTED FUNCTIONS */ +/** **/ +/****************************************************************************/ + + +void w25q128jw_init_crt0() { + //make sure spi variable is into the xheep_init_data_crt0 section + spi = spi_flash; + return; +} + +w25q_error_codes_t w25q128jw_init(spi_host_t* spi_host) { + /* + * Check if memory mapped SPI is enabled. Current version of the bsp + * does not support memory mapped SPI. + */ + if (soc_ctrl_peri->USE_SPIMEMIO == 1) { + return FLASH_ERROR; // Error + } + + // Set the global spi variable to the one passed as argument. + spi = spi_host; + + #ifdef USE_SPI_FLASH + // Select SPI host as SPI output + soc_ctrl_select_spi_host((soc_ctrl_t*)soc_ctrl_peri); + #endif // USE_SPI_FLASH + + // Enable SPI host device + spi_set_enable(spi, true); + + // Enable SPI output + spi_output_enable(spi, true); + + // Configure SPI<->Flash connection on CSID 0 + configure_spi(); + + // Set CSID + spi_set_csid(spi, 0); + + // Power up flash + flash_power_up(); + + // Set QE bit (only FPGA, simulation do not support status registers at all) + #ifndef TARGET_SIM + if (set_QE_bit() == FLASH_ERROR) return FLASH_ERROR; // Error occurred while setting QE bit + #endif // TARGET_SIM + + return FLASH_OK; // Success +} + +w25q_error_codes_t w25q128jw_read(uint32_t addr, void *data, uint32_t length) { + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + // Define the status variable + w25q_error_codes_t status; + + if (length < RX_DMA_THRESHOLD) { + status = w25q128jw_read_quad(addr, data, length); + if (status != FLASH_OK) return status; + } else { + // Wait DMA to be free + while(!dma_is_ready(0)); + status = w25q128jw_read_quad_dma(addr, data, length); + if (status != FLASH_OK) return status; + } + + return FLASH_OK; +} + +w25q_error_codes_t w25q128jw_write(uint32_t addr, void *data, uint32_t length, uint8_t erase_before_write) { + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + // Define the status variable + w25q_error_codes_t status = FLASH_OK; + + if (erase_before_write == 1) { + status = erase_and_write(addr, data, length); + } else { + // Wait DMA to be free + while(!dma_is_ready(0)); + status = w25q128jw_write_quad_dma(addr, data, length); + } + + return status; +} + +w25q_error_codes_t w25q128jw_read_standard(uint32_t addr, void* data, uint32_t length) { + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + // Address + Read command + uint32_t read_byte_cmd = ((REVERT_24b_ADDR(addr & 0x00ffffff) << 8) | FC_RD); + // Load command to TX FIFO + spi_write_word(spi, read_byte_cmd); + spi_wait_for_ready(spi); + + // Set up segment parameters -> send command and address + const uint32_t cmd_read_1 = spi_create_command((spi_command_t){ + .len = 3, // 4 Bytes + .csaat = true, // Command not finished + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + // Load segment parameters to COMMAND register + spi_set_command(spi, cmd_read_1); + spi_wait_for_ready(spi); + + // Set up segment parameters -> read length bytes + const uint32_t cmd_read_2 = spi_create_command((spi_command_t){ + .len = length-1, // len bytes + .csaat = false, // End command + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_RX_ONLY // Read only + }); + spi_set_command(spi, cmd_read_2); + spi_wait_for_ready(spi); + + /* + * Set RX watermark to length. The watermark is in words. + * If the length is not a multiple of 4, the RX watermark is set to length/4+1 + * to take into account the extra bytes. + * If the length is higher then the RX FIFO depth, the RX watermark is set to + * RX FIFO depth. In this case the flag is not set to 0, so the loop will + * continue until all the data is read. + */ + int flag = 1; + int to_read = 0; + int i_start = 0; + int length_original = length; + uint32_t *data_32bit = (uint32_t *)data; + while (flag) { + if (length >= SPI_HOST_PARAM_RX_DEPTH) { + spi_set_rx_watermark(spi, SPI_HOST_PARAM_RX_DEPTH>>2); + length -= SPI_HOST_PARAM_RX_DEPTH; + to_read += SPI_HOST_PARAM_RX_DEPTH; + } + else { + spi_set_rx_watermark(spi, (length%4==0 ? length>>2 : (length>>2)+1)); + to_read += length; + flag = 0; + } + // Wait till SPI RX FIFO is full (or I read all the data) + spi_wait_for_rx_watermark(spi); + // Read data from SPI RX FIFO + for (int i = i_start; i < to_read>>2; i++) { + spi_read_word(spi, &data_32bit[i]); // Writes a full word + } + // Update the starting index + i_start += SPI_HOST_PARAM_RX_DEPTH>>2; + } + // Take into account the extra bytes (if any) + if (length_original % 4 != 0) { + uint32_t last_word = 0; + spi_read_word(spi, &last_word); + memcpy(&data_32bit[length_original>>2], &last_word, length%4); + } + + return FLASH_OK; // Success +} + +w25q_error_codes_t w25q128jw_write_standard(uint32_t addr, void* data, uint32_t length) { + // Call the wrapper with quad = 0, dma = 0 + return page_write_wrapper(addr, data, length, 0, 0); +} + + +w25q_error_codes_t w25q128jw_erase_and_write_standard(uint32_t addr, void* data, uint32_t length){ + + uint32_t remaining_length = length; + uint32_t current_addr = addr; + uint8_t *current_data = data; + + w25q_error_codes_t status; + + while (remaining_length > 0) { + // Start address of the sector to erase, 4kB aligned + uint32_t sector_start_addr = current_addr & 0xfffff000; + + // Read the full sector and save it into RAM + status = w25q128jw_read_standard(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Erase the sector (no need to do so in simulation) + #ifndef TARGET_SIM + w25q128jw_4k_erase(sector_start_addr); + #endif // TARGET_SIM + + // Calculate the length of data to write in this sector + uint32_t write_length = MIN(FLASH_SECTOR_SIZE - (current_addr - sector_start_addr), remaining_length); + + // Modify the data in RAM to include the new data + memcpy(§or_data[current_addr - sector_start_addr], current_data, write_length); + + // Write the modified data back to the flash + status = w25q128jw_write_standard(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Update the remaining length, address and data pointer + remaining_length -= write_length; + current_addr += write_length; + current_data += write_length; + } + + return FLASH_OK; + +} + + +w25q_error_codes_t w25q128jw_read_standard_dma(uint32_t addr, void *data, uint32_t length, uint8_t no_wait_init_dma, uint8_t no_sanity_checks) { + + // Sanity checks + if (!no_sanity_checks) if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + /* + * SET UP DMA + */ + // SPI and SPI_FLASH are the same IP so same register map + uint32_t *fifo_ptr_rx = (uint32_t *)((uintptr_t)spi + SPI_HOST_RXDATA_REG_OFFSET); + + // Init DMA, the integrated DMA is used (peri == NULL) + if(!no_wait_init_dma) dma_init(NULL); + + // The DMA will wait for the SPI HOST/FLASH RX FIFO valid signal + #ifndef USE_SPI_FLASH + uint8_t slot = DMA_TRIG_SLOT_SPI_RX; + #else + uint8_t slot = DMA_TRIG_SLOT_SPI_FLASH_RX; + #endif + + // Set up DMA source target + static dma_target_t tgt_src = { + .inc_d1_du = 0, // Target is peripheral, no increment + .type = DMA_DATA_TYPE_WORD, // Data type is word + }; + // Target is SPI RX FIFO + tgt_src.ptr = (uint8_t*)fifo_ptr_rx; + // Trigger to control the data flow + tgt_src.trig = slot; + + // Set up DMA destination target + static dma_target_t tgt_dst = { + .inc_d1_du = 1, // Increment by 1 data unit (word) + .type = DMA_DATA_TYPE_WORD, // Data type is byte + .trig = DMA_TRIG_MEMORY, // Read-write operation to memory + }; + tgt_dst.ptr = (uint8_t*)data; // Target is the data buffer + + // Set up DMA transaction + static dma_trans_t trans = { + .src = &tgt_src, + .dst = &tgt_dst, + .end = DMA_TRANS_END_POLLING, + }; + // Size is in data units (words in this case) + trans.size_d1_du = length>>2; + + // Validate, load and launch DMA transaction + + dma_config_flags_t res; + res = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); + res = dma_load_transaction(&trans); + res = dma_launch(&trans); + + // Address + Read command + uint32_t read_byte_cmd = ((REVERT_24b_ADDR(addr & 0x00ffffff) << 8) | FC_RD); + // Load command to TX FIFO + spi_write_word(spi, read_byte_cmd); + spi_wait_for_ready(spi); + + // Set up segment parameters -> send command and address + const uint32_t cmd_read_1 = spi_create_command((spi_command_t){ + .len = 3, // 4 Bytes + .csaat = true, // Command not finished + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + // Load segment parameters to COMMAND register + spi_set_command(spi, cmd_read_1); + spi_wait_for_ready(spi); + + // Set up segment parameters -> read length bytes + const uint32_t cmd_read_2 = spi_create_command((spi_command_t){ + .len = length-1, // len bytes + .csaat = false, // End command + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_RX_ONLY // Read only + }); + spi_set_command(spi, cmd_read_2); + spi_wait_for_ready(spi); + + // Wait for DMA to finish transaction + if(!no_wait_init_dma) while(!dma_is_ready(0)); + + // Take into account the extra bytes (if any) + if (length % 4 != 0) { + uint32_t last_word = 0; + + spi_read_word((spi_host_t *)spi, &last_word); + #ifdef __cplusplus + memcpy(static_cast(data) + length - (length % 4), &last_word, length % 4); + #else + memcpy(&data[length - length%4], &last_word, length%4); + #endif + } + + return FLASH_OK; +} +w25q_error_codes_t w25q128jw_read_standard_dma_async(uint32_t addr, void *data, uint32_t length) { + + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + // Take into account the extra bytes (if any) + if (length % 4 != 0) { + //only multiple of 4 bytes are supported in this function + return FLASH_ERROR; + } + + /* + * SET UP DMA + */ + // SPI and SPI_FLASH are the same IP so same register map + uint32_t *fifo_ptr_rx = (uint32_t *)((uintptr_t)spi + SPI_HOST_RXDATA_REG_OFFSET); + + // Init DMA, the integrated DMA is used (peri == NULL) + dma_init(NULL); + + // The DMA will wait for the SPI HOST/FLASH RX FIFO valid signal + #ifndef USE_SPI_FLASH + uint8_t slot = DMA_TRIG_SLOT_SPI_RX; + #else + uint8_t slot = DMA_TRIG_SLOT_SPI_FLASH_RX; + #endif + + // Set up DMA source target + static dma_target_t tgt_src = { + .inc_d1_du = 0, // Target is peripheral, no increment + .type = DMA_DATA_TYPE_WORD, // Data type is word + }; + // Target is SPI RX FIFO + tgt_src.ptr = (uint8_t*)fifo_ptr_rx; + // Trigger to control the data flow + tgt_src.trig = slot; + + // Set up DMA destination target + static dma_target_t tgt_dst = { + .inc_d1_du = 1, // Increment by 1 data unit (word) + .type = DMA_DATA_TYPE_WORD, // Data type is byte + .trig = DMA_TRIG_MEMORY, // Read-write operation to memory + }; + tgt_dst.ptr = (uint8_t*)data; // Target is the data buffer + + // Set up DMA transaction + static dma_trans_t trans = { + .src = &tgt_src, + .dst = &tgt_dst, + .end = DMA_TRANS_END_INTR, //so that you can wait for interrupt + }; + // Size is in data units (words in this case) + trans.size_d1_du = length>>2; + // Validate, load and launch DMA transaction + dma_config_flags_t res; + res = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); + res = dma_load_transaction(&trans); + res = dma_launch(&trans); + + // Address + Read command + uint32_t read_byte_cmd = ((REVERT_24b_ADDR(addr & 0x00ffffff) << 8) | FC_RD); + // Load command to TX FIFO + spi_write_word(spi, read_byte_cmd); + spi_wait_for_ready(spi); + + // Set up segment parameters -> send command and address + const uint32_t cmd_read_1 = spi_create_command((spi_command_t){ + .len = 3, // 4 Bytes + .csaat = true, // Command not finished + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + // Load segment parameters to COMMAND register + spi_set_command(spi, cmd_read_1); + spi_wait_for_ready(spi); + + // Set up segment parameters -> read length bytes + const uint32_t cmd_read_2 = spi_create_command((spi_command_t){ + .len = length-1, // len bytes + .csaat = false, // End command + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_RX_ONLY // Read only + }); + spi_set_command(spi, cmd_read_2); + spi_wait_for_ready(spi); + + // Wait for DMA to finish transaction outside this function, the DMA generates also an interrupt + // However, you need to enable the interrupt in the INT controllers, and CPU + + return FLASH_OK; +} + + +w25q_error_codes_t w25q128jw_write_standard_dma(uint32_t addr, void *data, uint32_t length) { + // Call the wrapper with quad = 0, dma = 1 + return page_write_wrapper(addr, data, length, 0, 1); +} + +w25q_error_codes_t w25q128jw_erase_and_write_standard_dma(uint32_t addr, void* data, uint32_t length){ + + uint32_t remaining_length = length; + uint32_t current_addr = addr; + uint8_t *current_data = data; + + w25q_error_codes_t status; + + while (remaining_length > 0) { + // Start address of the sector to erase, 4kB aligned + uint32_t sector_start_addr = current_addr & 0xfffff000; + + // Read the full sector and save it into RAM + status = w25q128jw_read_standard_dma(sector_start_addr, sector_data, FLASH_SECTOR_SIZE, 0, 0); + if (status != FLASH_OK) return FLASH_ERROR; + + // Erase the sector (no need to do so in simulation) + #ifndef TARGET_SIM + w25q128jw_4k_erase(sector_start_addr); + #endif // TARGET_SIM + + // Calculate the length of data to write in this sector + uint32_t write_length = MIN(FLASH_SECTOR_SIZE - (current_addr - sector_start_addr), remaining_length); + + // Modify the data in RAM to include the new data + memcpy(§or_data[current_addr - sector_start_addr], current_data, write_length); + + // Write the modified data back to the flash + status = w25q128jw_write_standard_dma(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Update the remaining length, address and data pointer + remaining_length -= write_length; + current_addr += write_length; + current_data += write_length; + } + + return FLASH_OK; + +} + + +w25q_error_codes_t w25q128jw_read_quad(uint32_t addr, void *data, uint32_t length) { + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + // Send quad read command at standard speed + uint32_t cmd_read_quadIO = FC_RDQIO; + spi_write_word(spi, cmd_read_quadIO); + const uint32_t cmd_read = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = true, // Command not finished + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, cmd_read); + spi_wait_for_ready(spi); + + /* + * Send address at quad speed. + * Last byte is Fxh (here FFh) required by W25Q128JW + */ + uint32_t read_byte_cmd = (REVERT_24b_ADDR(addr) | (0xFF << 24)); + spi_write_word(spi, read_byte_cmd); + const uint32_t cmd_address = spi_create_command((spi_command_t){ + .len = 3, // 3 Byte + .csaat = true, // Command not finished + .speed = SPI_SPEED_QUAD, // Quad speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, cmd_address); + spi_wait_for_ready(spi); + + // Quad read requires dummy clocks + const uint32_t dummy_clocks_cmd = spi_create_command((spi_command_t){ + #ifndef TARGET_SIM + .len = DUMMY_CLOCKS_FAST_READ_QUAD_IO-1, + #else + .len = DUMMY_CLOCKS_SIM-1, + #endif + .csaat = true, // Command not finished + .speed = SPI_SPEED_QUAD, // Quad speed + .direction = SPI_DIR_DUMMY // Dummy + }); + spi_set_command(spi, dummy_clocks_cmd); + spi_wait_for_ready(spi); + + // Read back the requested data at quad speed + const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ + .len = length-1, // 32 Byte + .csaat = false, // End command + .speed = SPI_SPEED_QUAD, // Quad speed + .direction = SPI_DIR_RX_ONLY // Read only + }); + spi_set_command(spi, cmd_read_rx); + spi_wait_for_ready(spi); + + /* COMMAND FINISHED */ + + /* + * Set RX watermark to length. The watermark is in words. + * If the length is not a multiple of 4, the RX watermark is set to length/4+1 + * to take into account the extra bytes. + * If the length is higher then the RX FIFO depth, the RX watermark is set to + * RX FIFO depth. In this case the flag is not set to 0, so the loop will + * continue until all the data is read. + */ + int flag = 1; + int to_read = 0; + int i_start = 0; + int length_original = length; + uint32_t *data_32bit = (uint32_t *)data; + while (flag) { + if (length >= SPI_HOST_PARAM_RX_DEPTH) { + spi_set_rx_watermark(spi, SPI_HOST_PARAM_RX_DEPTH>>2); + length -= SPI_HOST_PARAM_RX_DEPTH; + to_read += SPI_HOST_PARAM_RX_DEPTH; + } + else { + spi_set_rx_watermark(spi, (length%4==0 ? length>>2 : (length>>2)+1)); + to_read += length; + flag = 0; + } + // Wait till SPI RX FIFO is full (or I read all the data) + spi_wait_for_rx_watermark(spi); + // Read data from SPI RX FIFO + for (int i = i_start; i < to_read>>2; i++) { + spi_read_word(spi, &data_32bit[i]); // Writes a full word + } + // Update the starting index + i_start += SPI_HOST_PARAM_RX_DEPTH>>2; + } + // Take into account the extra bytes (if any) + if (length_original%4 != 0) { + uint32_t last_word = 0; + spi_read_word(spi, &last_word); + memcpy(&data_32bit[length_original>>2], &last_word, length%4); + } + + return FLASH_OK; // Success +} + +w25q_error_codes_t w25q128jw_write_quad(uint32_t addr, void *data, uint32_t length) { + // Call the wrapper with quad = 1, dma = 0 + return page_write_wrapper(addr, data, length, 1, 0); +} + + +w25q_error_codes_t w25q128jw_erase_and_write_quad(uint32_t addr, void *data, uint32_t length) { + + uint32_t remaining_length = length; + uint32_t current_addr = addr; + uint8_t *current_data = data; + + w25q_error_codes_t status; + + while (remaining_length > 0) { + // Start address of the sector to erase, 4kB aligned + uint32_t sector_start_addr = current_addr & 0xfffff000; + + // Read the full sector and save it into RAM + status = w25q128jw_read_quad(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Erase the sector (no need to do so in simulation) + #ifndef TARGET_SIM + w25q128jw_4k_erase(sector_start_addr); + #endif // TARGET_SIM + + // Calculate the length of data to write in this sector + uint32_t write_length = MIN(FLASH_SECTOR_SIZE - (current_addr - sector_start_addr), remaining_length); + + // Modify the data in RAM to include the new data + memcpy(§or_data[current_addr - sector_start_addr], current_data, write_length); + + // Write the modified data back to the flash + status = w25q128jw_write_quad(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Update the remaining length, address and data pointer + remaining_length -= write_length; + current_addr += write_length; + current_data += write_length; + } + + return FLASH_OK; + +} + + +w25q_error_codes_t w25q128jw_read_quad_dma(uint32_t addr, void *data, uint32_t length) { + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + // Send quad read command at standard speed + uint32_t cmd_read_quadIO = FC_RDQIO; + spi_write_word(spi, cmd_read_quadIO); + const uint32_t cmd_read = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = true, // Command not finished + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, cmd_read); + spi_wait_for_ready(spi); + + /* + * Send address at quad speed. + * Last byte is Fxh (here FFh) required by W25Q128JW + */ + uint32_t read_byte_cmd = (REVERT_24b_ADDR(addr) | (0xFF << 24)); + spi_write_word(spi, read_byte_cmd); + const uint32_t cmd_address = spi_create_command((spi_command_t){ + .len = 3, // 3 Byte + .csaat = true, // Command not finished + .speed = SPI_SPEED_QUAD, // Quad speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, cmd_address); + spi_wait_for_ready(spi); + + // Quad read requires dummy clocks + const uint32_t dummy_clocks_cmd = spi_create_command((spi_command_t){ + #ifndef TARGET_SIM + .len = DUMMY_CLOCKS_FAST_READ_QUAD_IO-1, // W25Q128JW flash needs 4 dummy cycles + #else + .len = DUMMY_CLOCKS_SIM-1, // SPI flash simulation model needs 8 dummy cycles + #endif + .csaat = true, // Command not finished + .speed = SPI_SPEED_QUAD, // Quad speed + .direction = SPI_DIR_DUMMY // Dummy + }); + spi_set_command(spi, dummy_clocks_cmd); + spi_wait_for_ready(spi); + + // Read back the requested data at quad speed + const uint32_t cmd_read_rx = spi_create_command((spi_command_t){ + .len = length-1, // length bytes + .csaat = false, // End command + .speed = SPI_SPEED_QUAD, // Quad speed + .direction = SPI_DIR_RX_ONLY // Read only + }); + spi_set_command(spi, cmd_read_rx); + spi_wait_for_ready(spi); + + /* COMMAND FINISHED */ + + /* + * SET UP DMA + */ + // SPI and SPI_FLASH are the same IP so same register map + uint32_t *fifo_ptr_rx = (uint32_t *)((uintptr_t)spi + SPI_HOST_RXDATA_REG_OFFSET); + + // Init DMA, the integrated DMA is used (peri == NULL) + dma_init(NULL); + + // The DMA will wait for the SPI HOST/FLASH RX FIFO valid signal + #ifndef USE_SPI_FLASH + uint8_t slot = DMA_TRIG_SLOT_SPI_RX; + #else + uint8_t slot = DMA_TRIG_SLOT_SPI_FLASH_RX; + #endif + + // Set up DMA source target + static dma_target_t tgt_src = { + .inc_d1_du = 0, // Target is peripheral, no increment + .type = DMA_DATA_TYPE_WORD, // Data type is byte + }; + // Target is SPI RX FIFO + tgt_src.ptr = (uint8_t*)fifo_ptr_rx; + // Trigger to control the data flow + tgt_src.trig = slot; + + // Set up DMA destination target + static dma_target_t tgt_dst = { + .inc_d1_du = 1, // Increment by 1 data unit (word) + .type = DMA_DATA_TYPE_WORD, // Data type is byte + .trig = DMA_TRIG_MEMORY, // Read-write operation to memory + }; + tgt_dst.ptr = (uint8_t*)data; // Target is the data buffer + + // Set up DMA transaction + static dma_trans_t trans = { + .src = &tgt_src, + .dst = &tgt_dst, + .end = DMA_TRANS_END_POLLING, + }; + // Size is in data units (words in this case) + trans.size_d1_du = length>>2; + + // Validate, load and launch DMA transaction + dma_config_flags_t res; + res = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); + res = dma_load_transaction(&trans); + res = dma_launch(&trans); + + // Wait for DMA to finish transaction + while(!dma_is_ready(0)); + + // Take into account the extra bytes (if any) + if (length % 4 != 0) { + uint32_t last_word = 0; + + spi_read_word((spi_host_t *)spi, &last_word); + + #ifdef __cplusplus + memcpy(static_cast(data) + length - (length % 4), &last_word, length % 4); + #else + memcpy(&data[length - length%4], &last_word, length%4); + #endif + + } + + return FLASH_OK; +} + +w25q_error_codes_t w25q128jw_write_quad_dma(uint32_t addr, void *data, uint32_t length) { + // Call the wrapper with quad = 1, dma = 1 + return page_write_wrapper(addr, (uint8_t *)data, length, 1, 1); +} + +w25q_error_codes_t w25q128jw_erase_and_write_quad_dma(uint32_t addr, void *data, uint32_t length) { + + uint32_t remaining_length = length; + uint32_t current_addr = addr; + uint8_t *current_data = (uint8_t *)data; + + w25q_error_codes_t status; + + while (remaining_length > 0) { + // Start address of the sector to erase, 4kB aligned + uint32_t sector_start_addr = current_addr & 0xfffff000; + + // Read the full sector and save it into RAM + status = w25q128jw_read_quad_dma(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Erase the sector (no need to do so in simulation) + #ifndef TARGET_SIM + w25q128jw_4k_erase(sector_start_addr); + #endif // TARGET_SIM + + // Calculate the length of data to write in this sector + uint32_t write_length = MIN(FLASH_SECTOR_SIZE - (current_addr - sector_start_addr), remaining_length); + + // Modify the data in RAM to include the new data + memcpy(§or_data[current_addr - sector_start_addr], current_data, write_length); + + // Write the modified data back to the flash + status = w25q128jw_write_quad_dma(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Update the remaining length, address and data pointer + remaining_length -= write_length; + current_addr += write_length; + current_data += write_length; + } + + return FLASH_OK; + +} + +w25q_error_codes_t w25q128jw_4k_erase(uint32_t addr) { + // Sanity checks + if (addr > MAX_FLASH_ADDR || addr < 0) return FLASH_ERROR; + + // Wait any other operation to finish + flash_wait(); + + // Enable flash write in order to erase + flash_write_enable(); + + // Build and send erase command + uint32_t erase_4k_cmd = ((REVERT_24b_ADDR(addr & 0x00ffffff) << 8) | FC_SE); + spi_write_word(spi, erase_4k_cmd); + spi_wait_for_ready(spi); + const uint32_t cmd_erase = spi_create_command((spi_command_t){ + .len = 3, // 4 Bytes + .csaat = false, // End command + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, cmd_erase); + spi_wait_for_ready(spi); + + // Wait for the erase operation to be finished + flash_wait(); +} + +w25q_error_codes_t w25q128jw_32k_erase(uint32_t addr) { + // Sanity checks + if (addr > 0x00ffffff || addr < 0) return FLASH_ERROR; + + // Wait any other operation to finish + flash_wait(); + + // Enable flash write in order to erase + flash_write_enable(); + + // Build and send erase command + uint32_t erase_32k_cmd = ((REVERT_24b_ADDR(addr & 0x00ffffff) << 8) | FC_BE32); + spi_write_word(spi, erase_32k_cmd); + spi_wait_for_ready(spi); + const uint32_t cmd_erase = spi_create_command((spi_command_t){ + .len = 3, // 4 Bytes + .csaat = false, // End command + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, cmd_erase); + spi_wait_for_ready(spi); + + // Wait for the erase operation to be finished + flash_wait(); +} + +w25q_error_codes_t w25q128jw_64k_erase(uint32_t addr) { + // Sanity checks + if (addr > 0x00ffffff || addr < 0) return FLASH_ERROR; + + // Wait any other operation to finish + flash_wait(); + + // Enable flash write in order to erase + flash_write_enable(); + + // Build and send erase command + uint32_t erase_64k_cmd = ((REVERT_24b_ADDR(addr & 0x00ffffff) << 8) | FC_BE64); + spi_write_word(spi, erase_64k_cmd); + spi_wait_for_ready(spi); + const uint32_t cmd_erase = spi_create_command((spi_command_t){ + .len = 3, // 4 Bytes + .csaat = false, // End command + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, cmd_erase); + spi_wait_for_ready(spi); + + // Wait for the erase operation to be finished + flash_wait(); +} + +void w25q128jw_chip_erase(void) { + // Wait any other operation to finish + flash_wait(); + + // Enable flash write in order to erase + flash_write_enable(); + + // Build and send erase command + spi_write_word(spi, FC_CE); + spi_wait_for_ready(spi); + const uint32_t cmd_erase = spi_create_command((spi_command_t){ + .len = 0, // 1 Bytes + .csaat = false, // End command + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, cmd_erase); + spi_wait_for_ready(spi); + + // Wait for the erase operation to be finished + flash_wait(); +} + +void w25q128jw_reset(void) { + // Wait for ongoing operation to finish (if any) + flash_wait(); + + // Build and send reset command + flash_reset(); + + // Wait for the reset operation to be finished + flash_wait(); +} + +void w25q128jw_reset_force(void) { + // Build and send reset command without waiting for ongoing operation + flash_reset(); + + // Wait for the reset operation to be finished + flash_wait(); +} + +void w25q128jw_power_down(void) { + // Build and send power down command + spi_write_word(spi, FC_PD); + const uint32_t cmd_power_down = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = false, // End command + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, cmd_power_down); + spi_wait_for_ready(spi); +} + + +/****************************************************************************/ +/** **/ +/* LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + +static void flash_power_up(void) { + spi_write_word(spi, FC_RPD); + spi_wait_for_ready(spi); + const uint32_t cmd_powerup = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = false, // End command + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, cmd_powerup); + spi_wait_for_ready(spi); +} + +static w25q_error_codes_t set_QE_bit(void) { + spi_set_rx_watermark(spi,1); + + // Read Status Register 2 + const uint32_t reg2_read_cmd = FC_RSR2; + spi_write_word(spi, reg2_read_cmd); + + const uint32_t reg2_read_1 = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = true, // Command not finished + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, reg2_read_1); + spi_wait_for_ready(spi); + + const uint32_t reg2_read_2 = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = false, // End command + .speed = SPI_SPEED_STANDARD, // Standard speed + .direction = SPI_DIR_RX_ONLY // Read only + }); + spi_set_command(spi, reg2_read_2); + spi_wait_for_ready(spi); + spi_wait_for_rx_watermark(spi); + + /* + * the partial word will be zero-padded and inserted into the RX FIFO once the segment is completed + * The actual register is 8 bit, but the SPI host gives a full word + */ + uint32_t reg2_data; + spi_read_word(spi, ®2_data); + + // Set bit in position 1 (QE bit), leaving the others unchanged + reg2_data |= 0x2; + + // Enable write operation + flash_write_enable(); + + // Write Status Register 2 (set QE bit) + const uint32_t reg2_write_cmd = FC_WSR2; + spi_write_word(spi, reg2_write_cmd); + + const uint32_t reg2_write_1 = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = true, // Command not finished + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, reg2_write_1); + spi_wait_for_ready(spi); + + // Load data to TX FIFO + spi_write_word(spi, reg2_data); + + // Create command segment + const uint32_t reg2_write_2 = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = false, // End command + .speed = SPI_SPEED_STANDARD, // Standard speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, reg2_write_2); + spi_wait_for_ready(spi); + + // Wait flash to complete write routine + flash_wait(); + + // Read back Status Register 2 + spi_write_word(spi, reg2_read_cmd); + spi_set_command(spi, reg2_read_1); + spi_wait_for_ready(spi); + spi_set_command(spi, reg2_read_2); + spi_wait_for_ready(spi); + spi_wait_for_rx_watermark(spi); + uint32_t reg2_data_check = 0x00; + spi_read_word(spi, ®2_data_check); + + // Check if the QE bit is set + if ((reg2_data_check & 0x2) == 0) return FLASH_ERROR; + else return FLASH_OK; +} + +static void configure_spi(void) { + // Configure SPI clock + uint32_t core_clk = soc_ctrl_peri->SYSTEM_FREQUENCY_HZ; + uint16_t clk_div = 0; + if(FLASH_CLK_MAX_HZ < core_clk/2){ + clk_div = (core_clk/(FLASH_CLK_MAX_HZ) - 2)/2; // The value is truncated + if (core_clk/(2 + 2 * clk_div) > FLASH_CLK_MAX_HZ) clk_div += 1; // Adjust if the truncation was not 0 + } + // SPI Configuration + // Configure chip 0 (flash memory) + const uint32_t chip_cfg = spi_create_configopts((spi_configopts_t){ + .clkdiv = clk_div, + .csnidle = 0xF, + .csntrail = 0xF, + .csnlead = 0xF, + .fullcyc = false, + .cpha = 0, + .cpol = 0 + }); + spi_set_configopts(spi, 0, chip_cfg); +} + +static void flash_wait(void) { + spi_set_rx_watermark(spi,1); + bool flash_busy = true; + uint8_t flash_resp[4] = {0xff,0xff,0xff,0xff}; + + while(flash_busy){ + uint32_t flash_cmd = FC_RSR1; // [CMD] Read status register 1 + spi_write_word(spi, flash_cmd); // Push TX buffer + uint32_t spi_status_cmd = spi_create_command((spi_command_t){ + .len = 0, + .csaat = true, + .speed = SPI_SPEED_STANDARD, + .direction = SPI_DIR_TX_ONLY + }); + uint32_t spi_status_read_cmd = spi_create_command((spi_command_t){ + .len = 0, + .csaat = false, + .speed = SPI_SPEED_STANDARD, + .direction = SPI_DIR_RX_ONLY + }); + spi_set_command(spi, spi_status_cmd); + spi_wait_for_ready(spi); + spi_set_command(spi, spi_status_read_cmd); + spi_wait_for_ready(spi); + spi_wait_for_rx_watermark(spi); + spi_read_word(spi, (uint32_t *)flash_resp); + if ((flash_resp[0] & 0x01) == 0) flash_busy = false; + } +} + +static void flash_reset(void) { + spi_write_word(spi, FC_ERESET); + spi_write_word(spi, FC_RESET); + spi_wait_for_ready(spi); + + const uint32_t cmd_reset_enable = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = false, // End command + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, cmd_reset_enable); + spi_wait_for_ready(spi); + const uint32_t cmd_reset = spi_create_command((spi_command_t){ + .len = 0, // 1 Byte + .csaat = false, // End command + .speed = SPI_SPEED_STANDARD, // Single speed + .direction = SPI_DIR_TX_ONLY // Write only + }); + spi_set_command(spi, cmd_reset); + spi_wait_for_ready(spi); +} + +w25q_error_codes_t erase_and_write(uint32_t addr, uint8_t *data, uint32_t length) { + + uint32_t remaining_length = length; + uint32_t current_addr = addr; + uint8_t *current_data = data; + + w25q_error_codes_t status; + + while (remaining_length > 0) { + // Start address of the sector to erase, 4kB aligned + uint32_t sector_start_addr = current_addr & 0xfffff000; + + // Read the full sector and save it into RAM + status = w25q128jw_read(sector_start_addr, sector_data, FLASH_SECTOR_SIZE); + if (status != FLASH_OK) return FLASH_ERROR; + + // Erase the sector (no need to do so in simulation) + #ifndef TARGET_SIM + w25q128jw_4k_erase(sector_start_addr); + #endif // TARGET_SIM + + // Calculate the length of data to write in this sector + uint32_t write_length = MIN(FLASH_SECTOR_SIZE - (current_addr - sector_start_addr), remaining_length); + + // Modify the data in RAM to include the new data + memcpy(§or_data[current_addr - sector_start_addr], current_data, write_length); + + // Write the modified data back to the flash (without erasing this time) + status = w25q128jw_write(sector_start_addr, sector_data, FLASH_SECTOR_SIZE, 0); + if (status != FLASH_OK) return FLASH_ERROR; + + // Update the remaining length, address and data pointer + remaining_length -= write_length; + current_addr += write_length; + current_data += write_length; + } + + return FLASH_OK; +} + +static w25q_error_codes_t page_write_wrapper(uint32_t addr, uint8_t *data, uint32_t length, uint8_t quad, uint8_t dma) { + // Sanity checks + if (w25q128jw_sanity_checks(addr, data, length) != FLASH_OK) return FLASH_ERROR; + + // Pointer arithmetics is not allowed on void pointers + uint8_t *data_8bit = (uint8_t *)data; + + /* + * Set speed and DMA flags. + * Robust implementation: no need to perform safety checks on the flags. + */ + uint8_t speed = quad==1 ? 1 : 0; + uint8_t dma_flag = dma==1 ? 1 : 0; + + /* + * Taking care of misalligned start address. + * If the start address is not aligned to a 256 bytes boundary, + * the first page is written with the first 256 - (addr % 256) bytes. + */ + if (addr % FLASH_PAGE_SIZE != 0) { + uint8_t tmp_len = FLASH_PAGE_SIZE - (addr % FLASH_PAGE_SIZE); + tmp_len = MIN(tmp_len, length); + page_write(addr, data_8bit, tmp_len, speed, dma_flag); + addr += tmp_len; + data_8bit += tmp_len; + length -= tmp_len; + } + + // Check if we already finished + if (length == 0) return FLASH_OK; + + // I cannot program more than a page (256 Bytes) at a time. + int flag = 1; + while (flag) { + if (length > FLASH_PAGE_SIZE) { + page_write(addr, data_8bit, FLASH_PAGE_SIZE, speed, dma_flag); + addr += FLASH_PAGE_SIZE; + data_8bit += FLASH_PAGE_SIZE; + length -= FLASH_PAGE_SIZE; + } else { + page_write(addr, data_8bit, length, speed, dma_flag); + flag = 0; + } + } + return FLASH_OK; +} + +static w25q_error_codes_t page_write(uint32_t addr, uint8_t *data, uint32_t length, uint8_t quad, uint8_t dma) { + // Required every time before issuing a write command + flash_write_enable(); + + /* + * Build and send write command (24bit address + command). + * The command is picked based on the quad flag. + */ + const uint32_t write_byte_cmd = ((REVERT_24b_ADDR(addr & 0x00ffffff) << 8) | (quad ? FC_PPQ : FC_PP)); + spi_write_word(spi, write_byte_cmd); + const uint32_t cmd_write = spi_create_command((spi_command_t){ + .len = 3, + .csaat = true, + .speed = SPI_SPEED_STANDARD, + .direction = SPI_DIR_TX_ONLY + }); + spi_set_command(spi, cmd_write); + spi_wait_for_ready(spi); + + /* + * Place data in TX FIFO + * In simulation it do not wait for the flash to be ready, so we must check + * if the FIFO is full before writing. + */ + if (dma) { + dma_send_toflash(data, length); + } else { + uint32_t *data_32bit = (uint32_t *)data; + for (int i = 0; i < length>>2; i++) { + spi_wait_for_tx_not_full(spi); + spi_write_word(spi, data_32bit[i]); + } + if (length % 4 != 0) { + uint32_t last_word = 0; + memcpy(&last_word, &data[length - length % 4], length % 4); + spi_wait_for_tx_not_full(spi); + spi_write_word(spi, last_word); + } + } + + /* + * Set up segment parameters -> send data. + * Speed is quad if quad flag is set, standard otherwise. + */ + const uint32_t cmd_write_2 = spi_create_command((spi_command_t){ + .len = length-1, + .csaat = false, + .speed = quad ? SPI_SPEED_QUAD : SPI_SPEED_STANDARD, + .direction = SPI_DIR_TX_ONLY + }); + spi_set_command(spi, cmd_write_2); + spi_wait_for_ready(spi); + + // Wait for flash to be ready again (FPGA only) + #ifndef TARGET_SIM + flash_wait(); + #endif // TARGET_SIM +} + +static w25q_error_codes_t dma_send_toflash(uint8_t *data, uint32_t length) { + // SPI and SPI_FLASH are the same IP so same register map + uint32_t *fifo_ptr_tx = (uint32_t *)((uintptr_t)spi + SPI_HOST_TXDATA_REG_OFFSET); + + // Init DMA, the integrated DMA is used (peri == NULL) + dma_init(NULL); + + // The DMA will wait for the SPI HOST/FLASH TX FIFO valid signal + #ifndef USE_SPI_FLASH + uint8_t slot = DMA_TRIG_SLOT_SPI_TX; + #else + uint8_t slot = DMA_TRIG_SLOT_SPI_FLASH_TX; + #endif + + // Set up DMA source target + static dma_target_t tgt_src = { + .inc_d1_du = 1, // Increment by 1 data unit (word) + .type = DMA_DATA_TYPE_WORD, // Data type is word + }; + // Target is data buffer + tgt_src.ptr = data; + // Reads from memory + tgt_src.trig = DMA_TRIG_MEMORY; + + // Set up DMA destination target + static dma_target_t tgt_dst = { + .inc_d1_du = 0, // It's a peripheral, no increment + .type = DMA_DATA_TYPE_WORD, // Data type is word + }; + tgt_dst.trig = slot; + tgt_dst.ptr = (uint8_t*)fifo_ptr_tx; // Target is SPI TX FIFO + + // Set up DMA transaction + static dma_trans_t trans = { + .src = &tgt_src, + .dst = &tgt_dst, + .mode = DMA_TRANS_MODE_SINGLE, + .win_du = 0, + .end = DMA_TRANS_END_POLLING, + }; + // Size is in data units (words in this case) + trans.size_d1_du = length>>2; + + // Validate, load and launch DMA transaction + dma_config_flags_t res; + res = dma_validate_transaction(&trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); + if (res != DMA_CONFIG_OK) return FLASH_ERROR_DMA; + res = dma_load_transaction(&trans); + if (res != DMA_CONFIG_OK) return FLASH_ERROR_DMA; + res = dma_launch(&trans); + if (res != DMA_CONFIG_OK) return FLASH_ERROR_DMA; + + // Wait for DMA to finish transaction + while(!dma_is_ready(0)); + + // Take into account the extra bytes (if any) + if (length % 4 != 0) { + uint32_t last_word = 0; + memcpy(&last_word, &data[length - length % 4], length % 4); + spi_wait_for_tx_not_full(spi); + spi_write_word(spi, last_word); + } + return FLASH_OK; +} + +static void flash_write_enable(void) { + spi_write_word(spi, FC_WE); + const uint32_t cmd_write_en = spi_create_command((spi_command_t){ + .len = 0, + .csaat = false, + .speed = SPI_SPEED_STANDARD, + .direction = SPI_DIR_TX_ONLY + }); + spi_set_command(spi, cmd_write_en); + spi_wait_for_ready(spi); +} + +static w25q_error_codes_t w25q128jw_sanity_checks(uint32_t addr, uint8_t *data, uint32_t length) { + // Check if address is out of range + if (addr > MAX_FLASH_ADDR || addr < 0) return FLASH_ERROR; + + // Check if data pointer is NULL + if (data == NULL) return FLASH_ERROR; + + // Check if length is 0 + if (length <= 0) return FLASH_ERROR; + + // Check if current address + length is out of range + if (addr + length > MAX_FLASH_ADDR) return FLASH_ERROR; + + return FLASH_OK; // Success +} +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus +/****************************************************************************/ +/** **/ +/* EOF */ +/** **/ +/****************************************************************************/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q128jw.h b/hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q128jw.h new file mode 100644 index 00000000..501f69c6 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/bsp/w25q/w25q128jw.h @@ -0,0 +1,443 @@ +/* + ******************* +******************************* H HEADER FILE ***************************** +** ******************* +** +** project : X-HEEP +** filename : w25q128jw.h +** version : 1 +** date : 1/11/2023 +** +*************************************************************************** +** +** Copyright (c) EPFL contributors. +** All rights reserved. +** +*************************************************************************** +*/ + +/***************************************************************************/ +/***************************************************************************/ + +/** +* @file w25q128jw.h +* @date 13/02/23 +* @brief Header file for the W25Q128JW flash memory. +*/ + +#ifndef W25Q128JW_H +#define W25Q128JW_H + +/****************************************************************************/ +/** **/ +/** MODULES USED **/ +/** **/ +/****************************************************************************/ + +#include "spi_host.h" +#include "soc_ctrl.h" +#include "core_v_mini_mcu.h" + +/****************************************************************************/ +/** **/ +/** DEFINITIONS AND MACROS **/ +/** **/ +/****************************************************************************/ + +/** + * In Hz (133 MHz for the flash w25q128jvsim used in the EPFL Programmer) +*/ +#define FLASH_CLK_MAX_HZ (133*1000*1000) + + +/** + * @defgroup flash_commands Flash commands + * @{ + */ +#define FC_WE 0x06 /** Write Enable */ +#define FC_SRWE 0x50 /** Volatile SR Write Enable */ +#define FC_WD 0x04 /** Write Disable */ +#define FC_RPD 0xAB /** Release Power-Down, returns Device ID */ +#define FC_MFGID 0x90 /** Read Manufacturer/Device ID */ +#define FC_JEDECID 0x9F /** Read JEDEC ID */ +#define FC_UID 0x4B /** Read Unique ID */ +#define FC_RD 0x03 /** Read Data */ +#define FC_FR 0x0B /** Fast Read */ +#define FC_RDQIO 0xEB /** Fast Read Quad I/O */ +#define FC_PP 0x02 /** Page Program */ +#define FC_PPQ 0x32 /** Quad Input Page Program */ +#define FC_SE 0x20 /** Sector Erase 4kb */ +#define FC_BE32 0x52 /** Block Erase 32kb */ +#define FC_BE64 0xD8 /** Block Erase 64kb */ +#define FC_CE 0xC7 /** Chip Erase */ +#define FC_RSR1 0x05 /** Read Status Register 1 */ +#define FC_WSR1 0x01 /** Write Status Register 1 */ +#define FC_RSR2 0x35 /** Read Status Register 2 */ +#define FC_WSR2 0x31 /** Write Status Register 2 */ +#define FC_RSR3 0x15 /** Read Status Register 3 */ +#define FC_WSR3 0x11 /** Write Status Register 3 */ +#define FC_RSFDP 0x5A /** Read SFDP Register */ +#define FC_ESR 0x44 /** Erase Security Register */ +#define FC_PSR 0x42 /** Program Security Register */ +#define FC_RSR 0x48 /** Read Security Register */ +#define FC_GBL 0x7E /** Global Block Lock */ +#define FC_GBU 0x98 /** Global Block Unlock */ +#define FC_RBL 0x3D /** Read Block Lock */ +#define FC_RPR 0x3C /** Read Sector Protection Registers (adesto) */ +#define FC_IBL 0x36 /** Individual Block Lock */ +#define FC_IBU 0x39 /** Individual Block Unlock */ +#define FC_EPS 0x75 /** Erase / Program Suspend */ +#define FC_EPR 0x7A /** Erase / Program Resume */ +#define FC_PD 0xB9 /** Power-down */ +#define FC_QPI 0x38 /** Enter QPI mode */ +#define FC_ERESET 0x66 /** Enable Reset */ +#define FC_RESET 0x99 /** Reset Device */ +/** @} */ + +/** + * @defgroup error_codes Error codes + * @{ +*/ +#define FLASH_OK 0 /** No error @hideinitializer*/ +#define FLASH_ERROR 1 /** Generic error @hideinitializer*/ +#define FLASH_ERROR_DMA 2 /** DMA error @hideinitializer*/ +/** @} */ + +/** +/** + * @brief Threshold value for switching to DMA in read mode. + * If the number of bytes to be read exceeds this threshold, + * DMA is the more efficient data transfer. + */ +#define RX_DMA_THRESHOLD 75 + +/** + * @brief Threshold value for switching to DMA in write mode. + * If the number of bytes to be wrote exceeds this threshold, + * DMA is the more efficient data transfer. + */ +#define TX_DMA_THRESHOLD 0 + +/** + * @brief Dimension of a flash page, in bytes. +*/ +#define FLASH_PAGE_SIZE 256 + +/** + * @brief Dimension of a flash sector, in bytes. +*/ +#define FLASH_SECTOR_SIZE 4096 + +/** + * @brief Number of dummy clocks cycles required by the simulation model. +*/ +#define DUMMY_CLOCKS_SIM 8 + +/** + * @brief Number of dummy clocks cycles required by the flash during + * fast read quad I/O operations (command code: EBh). +*/ +#define DUMMY_CLOCKS_FAST_READ_QUAD_IO 4 + +/** + * @brief Upper bound for the flash address. +*/ +#define MAX_FLASH_ADDR 0x00ffffff + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************/ +/** **/ +/** TYPEDEFS AND STRUCTURES **/ +/** **/ +/****************************************************************************/ + +/** + * @brief Return status type. +*/ +typedef uint8_t w25q_error_codes_t; + +/****************************************************************************/ +/** **/ +/** EXPORTED VARIABLES **/ +/** **/ +/****************************************************************************/ + +/****************************************************************************/ +/** **/ +/** EXPORTED FUNCTIONS **/ +/** **/ +/****************************************************************************/ + +/** + * @brief Initialize data structure used by crt0 flash_load. + * +*/ +void w25q128jw_init_crt0(); + +/** + * @brief Power up and itialize the flash. + * + * Enable the SPI interface. + * Power up the flash and set the SPI configuration specific to the flash. + * It also set the QE bit in order to accept Quad I/O commands. + * By default both error and event interrupts are disabled. + * + * @param spi_host SPI host to use. + * + * @note The flash uses CSID 0. If the CSID register value is changed, it must be + * restored back to 0 before using the flash again. + * + * @return FLASH_OK if the flash is correctly initialized, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_init(spi_host_t* spi_host); + +/** + * @brief Read from flash. + * + * The function automatically uses the best parameters based on + * the current state of the system and the length of the data to read. + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer to be filled. + * @param length number of bytes to read. + * @return FLASH_OK if the read is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_read(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Write to flash. + * + * The function automatically uses the best parameters based on + * the current state of the system and the length of the data to write. + * If erase_before_write is set, the function will take care of erasing + * the correct sectors before writing. All the bytes not written will be + * copied back in their current state before the write operation. + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @param erase_before_write if set to 1, the function will take care of erasing + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_write(uint32_t addr, void* data, uint32_t length, uint8_t erase_before_write); + +/** + * @brief Read from flash at standard speed. + * + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer to be filled. + * @param length number of bytes to read. + * @retval FLASH_OK if the read is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_read_standard(uint32_t addr, void* data, uint32_t length); + + +/** + * @brief Write to flash at standard speed. Use this function only to write to unitialized data + * + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_write_standard(uint32_t addr, void* data, uint32_t length); + + +/** + * @brief Erase and Write to flash at standard speed. + * + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_erase_and_write_standard(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Read from flash at standard speed using DMA + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to read. + * @return FLASH_OK if the read is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_read_standard_dma(uint32_t addr, void *data, uint32_t length, uint8_t no_wait_init_dma, uint8_t no_sanity_checks); + +/** + * @brief Read from flash at standard speed using DMA but wait for DMA in the application + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to read, must be multiple of 4 + * @return FLASH_OK if the read is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_read_standard_dma_async(uint32_t addr, void *data, uint32_t length); + +/** + * @brief Write to flash at standard speed using DMA. Use this function only to write to unitialized data + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_write_standard_dma(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Erase and Write to flash at standard speed using DMA + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_erase_and_write_standard_dma(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Read from flash at quad speed. + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_read_quad(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Write to flash at quad speed. Use this function only to write to unitialized data + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_write_quad(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Erase and Write to flash at quad speed. + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_erase_and_write_quad(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Read from flash at quad speed using DMA. + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_read_quad_dma(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Write to flash at quad speed using DMA. Use this function only to write to unitialized data + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_write_quad_dma(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Erase and Write to flash at quad speed using DMA. Use this function only to write to unitialized data + * + * @param addr 24-bit flash address to read from. + * @param data pointer to the data buffer. + * @param length number of bytes to write. + * @return FLASH_OK if the write is successful, @ref error_codes otherwise. +*/ +w25q_error_codes_t w25q128jw_erase_and_write_quad_dma(uint32_t addr, void* data, uint32_t length); + +/** + * @brief Erase a 4kb sector. + * + * Sets all memory within a 4kb sector to the erased state of all 1s (FFh). + * After the erase is issued, waits for the flash to be ready. + * + * @param addr 24-bit address of the sector to erase. +*/ +w25q_error_codes_t w25q128jw_4k_erase(uint32_t addr); + +/** + * @brief Erase a 32kb block. + * + * Sets all memory within a 32kb block to the erased state of all 1s (FFh). + * After the erase is issued, waits for the flash to be ready. + * + * @param addr 24-bit address of the block to erase. +*/ +w25q_error_codes_t w25q128jw_32k_erase(uint32_t addr); + +/** + * @brief Erase a 64kb block. + * + * Sets all memory within a 64kb block to the erased state of all 1s (FFh). + * After the erase is issued, waits for the flash to be ready. + * + * @param addr 24-bit address of the block to erase. +*/ +w25q_error_codes_t w25q128jw_64k_erase(uint32_t addr); + +/** + * @brief Erase the entire chip. + * + * Sets all memory within the chip to the erased state of all 1s (FFh). + * After the erase is issued, waits for the flash to be ready. +*/ +void w25q128jw_chip_erase(void); + + +/** + * @brief Reset the flash. + * + * Before issuing the reset command, the function checks (and eventually wait) + * any ongoing read/write operation in order to preserve data integrity. + * After the reset is issued, wait for the flash to be ready. +*/ +void w25q128jw_reset(void); + +/** + * @brief Reset the flash without checking for ongoing operations. + * + * This function is used to reset the flash when it is not possible to check + * for ongoing operations (e.g. when the flash is not responding). + * Upon receiving the reset command, the flash will abort any ongoing operation. + * After the reset is issued, waits for the flash to be ready. +*/ +void w25q128jw_reset_force(void); + +/** + * @brief Power down the flash. + * + * During power down state, the only command that can be issued is the + * release power down command. All other commands are going to be ignored + * by the flash. +*/ +void w25q128jw_power_down(void); + +/****************************************************************************/ +/** **/ +/** INLINE FUNCTIONS **/ +/** **/ +/****************************************************************************/ +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* W25Q128JW_H */ +/****************************************************************************/ +/** **/ +/** EOF **/ +/** **/ +/****************************************************************************/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/base.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/base.h index e0582e74..0d56792b 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/base.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/base.h @@ -106,7 +106,7 @@ typedef enum dif_toggle { // * @param val A potential dif_toggle_t value. // * @return Bool indicating validity of toggle value. // */ -// inline bool dif_is_valid_toggle(dif_toggle_t val) { +// static inline bool dif_is_valid_toggle(dif_toggle_t val) { // switch (val) { // case kDifToggleEnabled: // return true; @@ -123,7 +123,7 @@ typedef enum dif_toggle { // * @param val A dif_toggle_t value. // * @return Corresponding bool value. // */ -// inline bool dif_toggle_to_bool(dif_toggle_t val) { +// static inline bool dif_toggle_to_bool(dif_toggle_t val) { // switch (val) { // case kDifToggleEnabled: // return true; @@ -140,7 +140,7 @@ typedef enum dif_toggle { // * @param val A bool value. // * @return Corresponding dif_toggle_t value. // */ -// inline dif_toggle_t dif_bool_to_toggle(bool val) { +// static inline dif_toggle_t dif_bool_to_toggle(bool val) { // return val ? kDifToggleEnabled : kDifToggleDisabled; // } @@ -150,7 +150,7 @@ typedef enum dif_toggle { // * @param val A multi-bit bool value. // * @return Corresponding dif_toggle_t value. // */ -// inline dif_toggle_t dif_multi_bit_bool_to_toggle(multi_bit_bool_t val) { +// static inline dif_toggle_t dif_multi_bit_bool_to_toggle(multi_bit_bool_t val) { // switch (val) { // case kMultiBitBool4True: // case kMultiBitBool8True: @@ -169,7 +169,7 @@ typedef enum dif_toggle { // * @return Corresponding `multi_bit_bool_t` value. Invalid values resolve to // * "false". // */ -// inline multi_bit_bool_t dif_toggle_to_multi_bit_bool4(dif_toggle_t val) { +// static inline multi_bit_bool_t dif_toggle_to_multi_bit_bool4(dif_toggle_t val) { // if (val == kDifToggleEnabled) { // return kMultiBitBool4True; // } else { @@ -184,7 +184,7 @@ typedef enum dif_toggle { // * @return Corresponding `multi_bit_bool_t` value. Invalid values resolve to // * "false". // */ -// inline multi_bit_bool_t dif_toggle_to_multi_bit_bool8(dif_toggle_t val) { +// static inline multi_bit_bool_t dif_toggle_to_multi_bit_bool8(dif_toggle_t val) { // if (val == kDifToggleEnabled) { // return kMultiBitBool8True; // } else { @@ -199,7 +199,7 @@ typedef enum dif_toggle { // * @return Corresponding `multi_bit_bool_t` value. Invalid values resolve to // * "false". // */ -// inline multi_bit_bool_t dif_toggle_to_multi_bit_bool12(dif_toggle_t val) { +// static inline multi_bit_bool_t dif_toggle_to_multi_bit_bool12(dif_toggle_t val) { // if (val == kDifToggleEnabled) { // return kMultiBitBool12True; // } else { @@ -214,7 +214,7 @@ typedef enum dif_toggle { // * @return Corresponding `multi_bit_bool_t` value. Invalid values resolve to // * "false". // */ -// inline multi_bit_bool_t dif_toggle_to_multi_bit_bool16(dif_toggle_t val) { +// static inline multi_bit_bool_t dif_toggle_to_multi_bit_bool16(dif_toggle_t val) { // if (val == kDifToggleEnabled) { // return kMultiBitBool16True; // } else { diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/bitfield.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/bitfield.c deleted file mode 100644 index b2562c0d..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/bitfield.c +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include "bitfield.h" - -// `extern` declarations to give the inline functions in the -// corresponding header a link location. - -extern uint32_t bitfield_field32_read(uint32_t bitfield, - bitfield_field32_t field); -extern uint32_t bitfield_field32_write(uint32_t bitfield, - bitfield_field32_t field, - uint32_t value); - -extern bitfield_field32_t bitfield_bit32_to_field32( - bitfield_bit32_index_t bit_index); - -extern bool bitfield_bit32_read(uint32_t bitfield, - bitfield_bit32_index_t bit_index); -extern uint32_t bitfield_bit32_write(uint32_t bitfield, - bitfield_bit32_index_t bit_index, - bool value); - -extern int32_t bitfield_find_first_set32(int32_t bitfield); -extern int32_t bitfield_count_leading_zeroes32(uint32_t bitfield); -extern int32_t bitfield_count_trailing_zeroes32(uint32_t bitfield); -extern int32_t bitfield_popcount32(uint32_t bitfield); -extern int32_t bitfield_parity32(uint32_t bitfield); -extern uint32_t bitfield_byteswap32(uint32_t bitfield); diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/bitfield.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/bitfield.h index e2b81b83..19377e35 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/bitfield.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/bitfield.h @@ -74,7 +74,7 @@ typedef struct bitfield_field32 { * @return Zero-extended `field` from `bitfield`. */ BITFIELD_WARN_UNUSED_RESULT -inline uint32_t bitfield_field32_read(uint32_t bitfield, +static inline uint32_t bitfield_field32_read(uint32_t bitfield, bitfield_field32_t field) { return (bitfield >> field.index) & field.mask; } @@ -92,7 +92,7 @@ inline uint32_t bitfield_field32_read(uint32_t bitfield, * @return `bitfield` with `field` set to `value`. */ BITFIELD_WARN_UNUSED_RESULT -inline uint32_t bitfield_field32_write(uint32_t bitfield, +static inline uint32_t bitfield_field32_write(uint32_t bitfield, bitfield_field32_t field, uint32_t value) { bitfield &= ~(field.mask << field.index); @@ -123,7 +123,7 @@ typedef uint32_t bitfield_bit32_index_t; * @return A 1-bit field that corresponds to `bit_index`. */ BITFIELD_WARN_UNUSED_RESULT -inline bitfield_field32_t bitfield_bit32_to_field32( +static inline bitfield_field32_t bitfield_bit32_to_field32( bitfield_bit32_index_t bit_index) { return (bitfield_field32_t){ .mask = 0x1, .index = bit_index, @@ -138,7 +138,7 @@ inline bitfield_field32_t bitfield_bit32_to_field32( * @return `true` if the bit was one, `false` otherwise. */ BITFIELD_WARN_UNUSED_RESULT -inline bool bitfield_bit32_read(uint32_t bitfield, +static inline bool bitfield_bit32_read(uint32_t bitfield, bitfield_bit32_index_t bit_index) { return bitfield_field32_read(bitfield, bitfield_bit32_to_field32(bit_index)) == 0x1u; @@ -153,7 +153,7 @@ inline bool bitfield_bit32_read(uint32_t bitfield, * @return `bitfield` with the `bit_index`th bit set to `value`. */ BITFIELD_WARN_UNUSED_RESULT -inline uint32_t bitfield_bit32_write(uint32_t bitfield, +static inline uint32_t bitfield_bit32_write(uint32_t bitfield, bitfield_bit32_index_t bit_index, bool value) { return bitfield_field32_write(bitfield, bitfield_bit32_to_field32(bit_index), @@ -174,7 +174,7 @@ inline uint32_t bitfield_bit32_write(uint32_t bitfield, * @return Zero-extended `field` from `bitfield`. */ BITFIELD_WARN_UNUSED_RESULT -inline uint32_t bitfield_read(uint32_t bitfield, +static inline uint32_t bitfield_read(uint32_t bitfield, uint32_t mask, uint32_t index) { @@ -195,7 +195,7 @@ inline uint32_t bitfield_read(uint32_t bitfield, * @return `bitfield` with `field` set to `value`. */ BITFIELD_WARN_UNUSED_RESULT -inline uint32_t bitfield_write(uint32_t bitfield, +static inline uint32_t bitfield_write(uint32_t bitfield, uint32_t mask, uint32_t index, uint32_t value) @@ -223,7 +223,7 @@ inline uint32_t bitfield_write(uint32_t bitfield, * @return One plus the index of the least-significant 1-bit of `bitfield`. */ BITFIELD_WARN_UNUSED_RESULT -inline int32_t bitfield_find_first_set32(int32_t bitfield) { +static inline int32_t bitfield_find_first_set32(int32_t bitfield) { return __builtin_ffs(bitfield); } @@ -247,7 +247,7 @@ inline int32_t bitfield_find_first_set32(int32_t bitfield) { * @return The number of leading 0-bits in `bitfield`. */ BITFIELD_WARN_UNUSED_RESULT -inline int32_t bitfield_count_leading_zeroes32(uint32_t bitfield) { +static inline int32_t bitfield_count_leading_zeroes32(uint32_t bitfield) { return (bitfield != 0) ? __builtin_clz(bitfield) : 32; } @@ -271,7 +271,7 @@ inline int32_t bitfield_count_leading_zeroes32(uint32_t bitfield) { * @return The number of trailing 0-bits in `bitfield`. */ BITFIELD_WARN_UNUSED_RESULT -inline int32_t bitfield_count_trailing_zeroes32(uint32_t bitfield) { +static inline int32_t bitfield_count_trailing_zeroes32(uint32_t bitfield) { return (bitfield != 0) ? __builtin_ctz(bitfield) : 32; } @@ -293,7 +293,7 @@ inline int32_t bitfield_count_trailing_zeroes32(uint32_t bitfield) { * @return The number of 1-bits in `bitfield`. */ BITFIELD_WARN_UNUSED_RESULT -inline int32_t bitfield_popcount32(uint32_t bitfield) { +static inline int32_t bitfield_popcount32(uint32_t bitfield) { return __builtin_popcount(bitfield); } @@ -315,7 +315,7 @@ inline int32_t bitfield_popcount32(uint32_t bitfield) { * @return The number of 1-bits in `bitfield`, modulo 2. */ BITFIELD_WARN_UNUSED_RESULT -inline int32_t bitfield_parity32(uint32_t bitfield) { +static inline int32_t bitfield_parity32(uint32_t bitfield) { return __builtin_parity(bitfield); } @@ -338,7 +338,7 @@ inline int32_t bitfield_parity32(uint32_t bitfield) { * @return `bitfield` with the order of bytes reversed. */ BITFIELD_WARN_UNUSED_RESULT -inline uint32_t bitfield_byteswap32(uint32_t bitfield) { +static inline uint32_t bitfield_byteswap32(uint32_t bitfield) { return __builtin_bswap32(bitfield); } diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/freestanding/assert.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/freestanding/assert.h index 0b701dc8..2619af76 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/freestanding/assert.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/freestanding/assert.h @@ -21,11 +21,26 @@ // defined for C. #ifndef __cplusplus #define static_assert _Static_assert -#endif // __cplusplus +#endif + // `assert()` should not be used. When building with Clang, using this function // in device code will emit a compile-time error. + + +#ifndef __cplusplus #define assert(do_not_use) \ static_assert(false, "do not use assert(); use CHECK() instead") +#else + #include + #define assert(expression) \ + do { \ + if (!(expression)) { \ + printf("Assertion failed: %s, file %s, line %d\n", \ + #expression, __FILE__, __LINE__); \ + while(1); \ + } \ + } while (0) +#endif // __cplusplus*/ #endif // OPENTITAN_SW_DEVICE_LIB_BASE_FREESTANDING_ASSERT_H_ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/freestanding/stdalign.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/freestanding/stdalign.h index 10126c9e..d0cc3f2a 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/freestanding/stdalign.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/freestanding/stdalign.h @@ -13,10 +13,16 @@ * S4p6. This header is specified in detail in S7.15 of the same. */ + + +#ifndef __cplusplus #define alignas _Alignas #define __alignas_is_defined 1 #define alignof _Alignof #define __alignof_is_defined 1 +#endif // __cplusplus + + #endif // OPENTITAN_SW_DEVICE_LIB_BASE_FREESTANDING_STDALIGN_H_ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/freestanding/stdbool.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/freestanding/stdbool.h index f9a9fa0b..2b04a3af 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/freestanding/stdbool.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/freestanding/stdbool.h @@ -12,11 +12,15 @@ * This header implements the stdbool.h standard header, as required by C11 * S4p6. This header is specified in detail in S7.18 of the same. */ +#ifndef __cplusplus +#define _Bool char #define bool _Bool #define true 1 #define false 0 #define __bool_true_false_are_defined 1 +#endif + #endif // OPENTITAN_SW_DEVICE_LIB_BASE_FREESTANDING_STDBOOL_H_ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/memory.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/memory.c index 180cdd90..a534074e 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/memory.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/memory.c @@ -2,10 +2,11 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 -#include "memory.h" +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus -extern uint32_t read_32(const void *); -extern void write_32(uint32_t, void *); +#include "memory.h" // Some symbols below are only defined for device builds. For host builds, we // their implementations will be provided by the host's libc implementation. @@ -18,7 +19,7 @@ extern void write_32(uint32_t, void *); // built for host-side software. #if !defined(HOST_BUILD) -void *memcpy(void *restrict dest, const void *restrict src, size_t len) { +void *memcpy(void *__restrict dest, const void *__restrict src, size_t len) { uint8_t *dest8 = (uint8_t *)dest; uint8_t *src8 = (uint8_t *)src; for (size_t i = 0; i < len; ++i) { @@ -84,3 +85,9 @@ void *memrchr(const void *ptr, int value, size_t len) { } return NULL; } + + + +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/memory.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/memory.h index 4a9f213b..7f91de70 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/memory.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/memory.h @@ -55,7 +55,7 @@ extern "C" { * @param ptr a word-aligned pointer pointed to at least four bytes of memory. * @return the word `ptr` points to. */ -inline uint32_t read_32(const void *ptr) { +static inline uint32_t read_32(const void *ptr) { // Both GCC and Clang optimize the code below into a single word-load on most // platforms. It is necessary and sufficient to indicate to the compiler that // the pointer points to four bytes of four-byte-aligned memory. @@ -86,7 +86,7 @@ inline uint32_t read_32(const void *ptr) { * @param value the value to store. * @param ptr a word-aligned pointer pointed to at least four bytes of memory. */ -inline void write_32(uint32_t value, void *ptr) { +static inline void write_32(uint32_t value, void *ptr) { // Both GCC and Clang optimize the code below into a single word-store on most // platforms. See the comment in `read_32()` for more implementation-private // information. @@ -107,7 +107,7 @@ inline void write_32(uint32_t value, void *ptr) { * @param len the number of bytes to copy. * @return the value of `dest`. */ -void *memcpy(void *restrict dest, const void *restrict src, size_t len); +void *memcpy(void *__restrict dest, const void *__restrict src, size_t len); /** * Set a region of memory to a particular byte value. diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/mmio.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/mmio.c index 58309170..be75927d 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/mmio.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/mmio.c @@ -2,6 +2,11 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + #include "mmio.h" #include @@ -120,41 +125,7 @@ void mmio_region_memcpy_to_mmio32(mmio_region_t base, uint32_t offset, mmio_region_memcpy32(base, offset, (void *)src, len, false); } -// `extern` declarations to give the inline functions in the -// corresponding header a link location. -extern uint8_t mmio_region_read8(mmio_region_t base, ptrdiff_t offset); -extern uint32_t mmio_region_read32(mmio_region_t base, ptrdiff_t offset); -extern void mmio_region_write8(mmio_region_t base, ptrdiff_t offset, - uint8_t value); -extern void mmio_region_write32(mmio_region_t base, ptrdiff_t offset, - uint32_t value); -extern uint32_t mmio_region_read_mask32(mmio_region_t base, ptrdiff_t offset, - uint32_t mask, uint32_t mask_index); -extern bool mmio_region_get_bit32(mmio_region_t base, ptrdiff_t offset, - uint32_t bit_index); -extern void mmio_region_nonatomic_clear_mask32(mmio_region_t base, - ptrdiff_t offset, uint32_t mask, - uint32_t mask_index); -extern void mmio_region_nonatomic_set_mask32(mmio_region_t base, - ptrdiff_t offset, uint32_t mask, - uint32_t mask_index); -extern void mmio_region_write_only_set_mask32(mmio_region_t base, - ptrdiff_t offset, uint32_t mask, - uint32_t mask_index); -extern void mmio_region_nonatomic_set_field32(mmio_region_t base, - ptrdiff_t offset, - bitfield_field32_t field, - uint32_t value); -extern void mmio_region_write_only_set_field32(mmio_region_t base, - ptrdiff_t offset, - bitfield_field32_t field, - uint32_t value); -extern void mmio_region_nonatomic_clear_bit32(mmio_region_t base, - ptrdiff_t offset, - uint32_t bit_index); -extern void mmio_region_nonatomic_set_bit32(mmio_region_t base, - ptrdiff_t offset, - uint32_t bit_index); -extern void mmio_region_write_only_set_bit32(mmio_region_t base, - ptrdiff_t offset, - uint32_t bit_index); + +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/mmio.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/mmio.h index d0b94a46..51173781 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/mmio.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/base/mmio.h @@ -63,7 +63,7 @@ typedef struct mmio_region { volatile void *base; } mmio_region_t; * @return a `mmio_region_t` value representing that region. */ MMIO_WARN_UNUSED_RESULT -inline mmio_region_t mmio_region_from_addr(uintptr_t address) { +static inline mmio_region_t mmio_region_from_addr(uintptr_t address) { return (mmio_region_t){ .base = (volatile void *)address, }; @@ -81,7 +81,7 @@ inline mmio_region_t mmio_region_from_addr(uintptr_t address) { * @return the read value. */ MMIO_WARN_UNUSED_RESULT -inline uint8_t mmio_region_read8(mmio_region_t base, ptrdiff_t offset) { +static inline uint8_t mmio_region_read8(mmio_region_t base, ptrdiff_t offset) { return ((volatile uint8_t *)base.base)[offset / sizeof(uint8_t)]; } @@ -97,7 +97,7 @@ inline uint8_t mmio_region_read8(mmio_region_t base, ptrdiff_t offset) { * @return the read value. */ MMIO_WARN_UNUSED_RESULT -inline uint32_t mmio_region_read32(mmio_region_t base, ptrdiff_t offset) { +static inline uint32_t mmio_region_read32(mmio_region_t base, ptrdiff_t offset) { return ((volatile uint32_t *)base.base)[offset / sizeof(uint32_t)]; } @@ -112,7 +112,7 @@ inline uint32_t mmio_region_read32(mmio_region_t base, ptrdiff_t offset) { * @param offset the offset to write at, in bytes. * @param value the value to write. */ -inline void mmio_region_write8(mmio_region_t base, ptrdiff_t offset, +static inline void mmio_region_write8(mmio_region_t base, ptrdiff_t offset, uint8_t value) { ((volatile uint8_t *)base.base)[offset / sizeof(uint8_t)] = value; } @@ -128,7 +128,7 @@ inline void mmio_region_write8(mmio_region_t base, ptrdiff_t offset, * @param offset the offset to write at, in bytes. * @param value the value to write. */ -inline void mmio_region_write32(mmio_region_t base, ptrdiff_t offset, +static inline void mmio_region_write32(mmio_region_t base, ptrdiff_t offset, uint32_t value) { ((volatile uint32_t *)base.base)[offset / sizeof(uint32_t)] = value; } @@ -171,7 +171,7 @@ void mmio_region_write32(mmio_region_t base, ptrdiff_t offset, uint32_t value); */ MMIO_WARN_UNUSED_RESULT MMIO_DEPRECATED -inline uint32_t mmio_region_read_mask32(mmio_region_t base, ptrdiff_t offset, +static inline uint32_t mmio_region_read_mask32(mmio_region_t base, ptrdiff_t offset, uint32_t mask, uint32_t mask_index) { return bitfield_field32_read( mmio_region_read32(base, offset), @@ -192,7 +192,7 @@ inline uint32_t mmio_region_read_mask32(mmio_region_t base, ptrdiff_t offset, */ MMIO_WARN_UNUSED_RESULT MMIO_DEPRECATED -inline bool mmio_region_get_bit32(mmio_region_t base, ptrdiff_t offset, +static inline bool mmio_region_get_bit32(mmio_region_t base, ptrdiff_t offset, uint32_t bit_index) { return bitfield_bit32_read(mmio_region_read32(base, offset), bit_index); } @@ -209,7 +209,7 @@ inline bool mmio_region_get_bit32(mmio_region_t base, ptrdiff_t offset, * @param mask_index mask position within the selected register. */ MMIO_DEPRECATED -inline void mmio_region_nonatomic_clear_mask32(mmio_region_t base, +static inline void mmio_region_nonatomic_clear_mask32(mmio_region_t base, ptrdiff_t offset, uint32_t mask, uint32_t mask_index) { uint32_t register_value = mmio_region_read32(base, offset); @@ -231,7 +231,7 @@ inline void mmio_region_nonatomic_clear_mask32(mmio_region_t base, * @param mask_index mask position within the selected register. */ MMIO_DEPRECATED -inline void mmio_region_nonatomic_set_mask32(mmio_region_t base, +static inline void mmio_region_nonatomic_set_mask32(mmio_region_t base, ptrdiff_t offset, uint32_t mask, uint32_t mask_index) { uint32_t register_value = mmio_region_read32(base, offset); @@ -253,7 +253,7 @@ inline void mmio_region_nonatomic_set_mask32(mmio_region_t base, * @param mask_index mask position within the selected register. */ MMIO_DEPRECATED -inline void mmio_region_write_only_set_mask32(mmio_region_t base, +static inline void mmio_region_write_only_set_mask32(mmio_region_t base, ptrdiff_t offset, uint32_t mask, uint32_t mask_index) { uint32_t register_value = 0x0u; @@ -278,7 +278,7 @@ inline void mmio_region_write_only_set_mask32(mmio_region_t base, * @param value value to set the field to. */ MMIO_DEPRECATED -inline void mmio_region_nonatomic_set_field32(mmio_region_t base, +static inline void mmio_region_nonatomic_set_field32(mmio_region_t base, ptrdiff_t offset, bitfield_field32_t field, uint32_t value) { @@ -299,7 +299,7 @@ inline void mmio_region_nonatomic_set_field32(mmio_region_t base, * @param value value to set field to. */ MMIO_DEPRECATED -inline void mmio_region_write_only_set_field32(mmio_region_t base, +static inline void mmio_region_write_only_set_field32(mmio_region_t base, ptrdiff_t offset, bitfield_field32_t field, uint32_t value) { @@ -319,7 +319,7 @@ inline void mmio_region_write_only_set_field32(mmio_region_t base, * @param bit_index the bit to clear. */ MMIO_DEPRECATED -inline void mmio_region_nonatomic_clear_bit32(mmio_region_t base, +static inline void mmio_region_nonatomic_clear_bit32(mmio_region_t base, ptrdiff_t offset, uint32_t bit_index) { uint32_t register_value = mmio_region_read32(base, offset); @@ -337,7 +337,7 @@ inline void mmio_region_nonatomic_clear_bit32(mmio_region_t base, * @param bit_index the bit to set. */ MMIO_DEPRECATED -inline void mmio_region_nonatomic_set_bit32(mmio_region_t base, +static inline void mmio_region_nonatomic_set_bit32(mmio_region_t base, ptrdiff_t offset, uint32_t bit_index) { uint32_t register_value = mmio_region_read32(base, offset); @@ -358,7 +358,7 @@ inline void mmio_region_nonatomic_set_bit32(mmio_region_t base, * @param bit_index the bit to set. */ MMIO_DEPRECATED -inline void mmio_region_write_only_set_bit32(mmio_region_t base, +static inline void mmio_region_write_only_set_bit32(mmio_region_t base, ptrdiff_t offset, uint32_t bit_index) { uint32_t register_value = 0x0u; diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/crt0.S b/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/crt0.S deleted file mode 100644 index b5f843ab..00000000 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/crt0.S +++ /dev/null @@ -1,246 +0,0 @@ -/* Copyright (c) 2017 SiFive Inc. All rights reserved. - * Copyright (c) 2019 ETH Zürich and University of Bologna - * Copyright (c) 2022 EPFL - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the FreeBSD License. This program is distributed in the hope that - * it will be useful, but WITHOUT ANY WARRANTY expressed or implied, - * including the implied warranties of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. A copy of this license is available at - * http://www.opensource.org/licenses. - */ - -#include "x-heep.h" -#include "core_v_mini_mcu.h" -#include "soc_ctrl_regs.h" - -/* In case the operation is to load from FLASH -*/ -#ifdef FLASH_LOAD -#include "spi_host_regs.h" -#endif - -/* Entry point for bare metal programs */ -.section .text.start -.global _start -.type _start, @function - -_start: -/* initialize global pointer */ -.option push -.option norelax -1: auipc gp, %pcrel_hi(__global_pointer$) - addi gp, gp, %pcrel_lo(1b) -.option pop - -/* initialize stack pointer */ - la sp, _sp - -/* set the frequency */ - li a0, SOC_CTRL_START_ADDRESS - li a2, REFERENCE_CLOCK_Hz - sw a2, SOC_CTRL_SYSTEM_FREQUENCY_HZ_REG_OFFSET(a0) - -#ifdef EXTERNAL_CRTO - #include "external_crt0.S" -#endif - -#ifdef FLASH_LOAD -/* copy the remaining (if any) text and data sections */ - // Setup the in/out pointers and copy size knowing 1KiB as already been copied - li a2, FLASH_MEM_START_ADDRESS # src ptr (flash) - addi a2, a2, 1024 - // This assumes ram base address is 0x00000000 - li s1, 1024 # dst ptr (ram) - la a0, _edata - addi a0, a0, -4 # _edata point to next address, so decrease it by one word - // Skip if everything has already been copied - blt a0, s1, _init_bss - addi a3, a0, -1024 # copy size in bytes (_edata is word aligned, so -1020 to make sure last word is copied) - - li a1, SPI_FLASH_START_ADDRESS - // Spi should already be enabled, powered-up and TXWM to 8 - // Address in byte reversed order (might be useless for the 1KiB address value) - // Highest byte is discarded(address on 3 bytes) - // ((x << 24) | (((x>>16)<<24)>>16) | (((x<<16)>>24)<<16)) - slli a4, a2, 24 - srli s0, a2, 16 - slli s0, s0, 24 - srli s0, s0, 16 - slli a5, a2, 16 - srli a5, a5, 24 - slli a5, a5, 16 - or a4, a4, s0 - or a2, a4, a5 - or a2, a2, 0x03 - sw a2, SPI_HOST_TXDATA_REG_OFFSET(a1) - nop # otherwise ready bit check is too fast - -_wait_spi_ready_read_prog: - lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) - bgez a5, _wait_spi_ready_read_prog - // Read command: 0x11000003 - lui a4, 0x11000 - addi a4, a4, 3 # spi cmd: txonly + stdspeed + csaat + 4B - sw a4, SPI_HOST_COMMAND_REG_OFFSET(a1) - nop # otherwise ready bit check is too fast - -_wait_spi_ready_copy_cmd: - lw a4, SPI_HOST_STATUS_REG_OFFSET(a1) - bgez a4, _wait_spi_ready_copy_cmd - - // For loop until the copy from flash to ram is done - // Try first to do as much as 256-bytes copies as possible - // mv s0, a3 - li s6, 256 - // Read command: 0x90000FF - lui s5, 0x9000 - addi s5, s5, 255 # spi cmd: rxonly + stdspeed + csaat + 255 bytes - -_32B_chunk_loop: - blt s6, a3, _read_32B_chunk - // Read remaining bytes - lui a5, 0x8000 - addi a4, a3, -1 - or a5, a5, a4 # spi cmd: rxonly + stdspeed + remaining bytes (a3-1) - sw a5, SPI_HOST_COMMAND_REG_OFFSET(a1) - nop # otherwise ready bit check is too fast - -_wait_spi_ready_remaining_bytes: - lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) - bgez a5, _wait_spi_ready_remaining_bytes - li s4, 32 - j _last_bytes_read_start - -_read_32B_chunk: - sw s5, SPI_HOST_COMMAND_REG_OFFSET(a1) - nop # otherwise ready bit check is too fast - -_wait_spi_ready_read_32B_chunk: - lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) - bgez a5, _wait_spi_ready_read_32B_chunk - addi s7, s1, 256 # add 32*8 (256 bytes) to dst ptr - -_wait_spi_rxwm_8_words: - lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) - srli a5, a5, 0x14 - andi a5, a5, 1 # SPI_HOST_STATUS_RXWM_BIT - beqz a5, _wait_spi_rxwm_8_words - addi a2, s1, 32 # add 32 bytes (4 words) to dst ptr - -_spi_fifo_read_8_words: - // Read 32B (8 words) from RX FIFO - lw a7, SPI_HOST_RXDATA_REG_OFFSET(a1) - sw a7, 0(s1) - addi s1, s1, 4 - bne s1, a2, _spi_fifo_read_8_words - bne s1, s7, _wait_spi_rxwm_8_words - addi a3, a3, -256 - j _32B_chunk_loop - -_wait_spi_rxwm_8_words_1: - lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) - srli a5, a5, 0x14 - andi a5, a5, 1 # SPI_HOST_STATUS_RXWM_BIT - beqz a5, _wait_spi_rxwm_8_words_1 - addi a2, s1, 32 # add 32 bytes (4 words) to dst ptr - -_spi_fifo_read_8_words_1: - // Read 32B (8 words) from RX FIFO - lw a7, SPI_HOST_RXDATA_REG_OFFSET(a1) - sw a7, 0(s1) - addi s1, s1, 4 - bne s1, a2, _spi_fifo_read_8_words_1 - addi a3, a3, -32 - -_last_bytes_read_start: - bltu s4, a3, _wait_spi_rxwm_8_words_1 - // Update RX watermark with remaining words (<=8) - lw a4, SPI_HOST_CONTROL_REG_OFFSET(a1) - andi a4, a4, -256 # ~SPI_HOST_CONTROL_RX_WATERMARK_MASK - srli a5, a3, 0x2 # 4 bytes = 1 word - or a5, a5, a4 - sw a5, SPI_HOST_CONTROL_REG_OFFSET(a1) - -_wait_spi_rxwm_n_words: - lw a5, SPI_HOST_STATUS_REG_OFFSET(a1) - srli a5, a5, 0x14 - andi a5, a5, 1 # SPI_HOST_STATUS_RXWM_BIT - beqz a5, _wait_spi_rxwm_n_words - -_remaining_bytes_loop: - bnez a3, _spi_read_word - j _init_bss - -_spi_read_word: - lw a7, SPI_HOST_RXDATA_REG_OFFSET(a1) - sw a7, 0(s1) - addi a3, a3, -4 - addi s1, s1, 4 - j _remaining_bytes_loop - -/* clear the bss segment */ -_init_bss: - la a0, __bss_start - la a2, __bss_end - sub a2, a2, a0 - li a1, 0 - call memset -#else -/* clear the bss segment */ - la a0, __bss_start - la a2, __bss_end - sub a2, a2, a0 - li a1, 0 - call memset -#endif - -#ifdef FLASH_EXEC -/* copy initialized data sections from flash to ram (to be verified, copied from picosoc)*/ - la a0, _sidata - la a1, _sdata - la a2, _edata - bge a1, a2, end_init_data - loop_init_data: - lw a3, 0(a0) - sw a3, 0(a1) - addi a0, a0, 4 - addi a1, a1, 4 - blt a1, a2, loop_init_data - end_init_data: -#endif - -/* set vector table address and vectored mode */ - la a0, __vector_start - ori a0, a0, 0x1 - csrw mtvec, a0 - -/* new-style constructors and destructors */ - la a0, __libc_fini_array - call atexit - call __libc_init_array - -/* call main */ - lw a0, 0(sp) /* a0 = argc */ - addi a1, sp, __SIZEOF_POINTER__ /* a1 = argv */ - li a2, 0 /* a2 = envp = NULL */ - call main - tail exit - -.size _start, .-_start - -.global _init -.type _init, @function -.global _fini -.type _fini, @function -_init: - call init -_fini: - /* These don't have to do anything since we use init_array/fini_array. Prevent - missing symbol error */ - ret -.size _init, .-_init -.size _fini, .-_fini - - - diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/crt0.S.tpl b/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/crt0.S.tpl new file mode 100644 index 00000000..8b8ccfb7 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/crt0.S.tpl @@ -0,0 +1,153 @@ +/* Copyright (c) 2017 SiFive Inc. All rights reserved. + * Copyright (c) 2019 ETH Zürich and University of Bologna + * Copyright (c) 2022 EPFL + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the FreeBSD License. This program is distributed in the hope that + * it will be useful, but WITHOUT ANY WARRANTY expressed or implied, + * including the implied warranties of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. A copy of this license is available at + * http://www.opensource.org/licenses. + */ + +#include "x-heep.h" +#include "core_v_mini_mcu.h" +#include "soc_ctrl_regs.h" + +#define RAMSIZE_COPIEDBY_BOOTROM 2048 + +/* Entry point for bare metal programs */ +.section .text.start +.global _start +.type _start, @function + +_start: +/* initialize global pointer */ +.option push +.option norelax +1: auipc gp, %pcrel_hi(__global_pointer$) + addi gp, gp, %pcrel_lo(1b) +.option pop + +/* initialize stack pointer */ + la sp, _sp + +/* set the frequency */ + li a0, SOC_CTRL_START_ADDRESS + li a2, REFERENCE_CLOCK_Hz + sw a2, SOC_CTRL_SYSTEM_FREQUENCY_HZ_REG_OFFSET(a0) + +#ifdef EXTERNAL_CRTO + #include "external_crt0.S" +#endif + +#ifdef FLASH_LOAD + + call w25q128jw_init_crt0 + + // This assumes ram base address is 0x00000000 and the section .text stars from ram0 (in the first RAMSIZE_COPIEDBY_BOOTROM Byte) + li s1, RAMSIZE_COPIEDBY_BOOTROM + li s2, FLASH_MEM_START_ADDRESS + + // copy the remaining (if any) text and data sections // + // Setup the in/out pointers and copy size knowing 1KiB as already been copied + mv a0, s2 // src ptr (flash) + add a0, a0, s1 + + la a1, _etext + // Skip if everything has already been copied, and copy the data section + blt a1, s1, _load_data_section + + // copy size in bytes, i.e. _etext - RAMSIZE_COPIEDBY_BOOTROM + sub a2, a1, s1 + + // dst ptr (ram) + mv a1, s1 + + // copy the remaining data --> w25q128jw_read_standard(a0 is src addr, a1 is dest ptr data, a2 is length) + + // this sub is redundat as we could have simply set a0 to RAMSIZE_COPIEDBY_BOOTROM+0x0, + // but like this is more readable as we set the FLASH address as memory mapped to FLASH_MEM_START_ADDRESS, and then remove the offset + // as required bz the w25q128jw_read_standard function + sub a0,a0,s2 + call w25q128jw_read_standard + +% for i, section in enumerate(xheep.iter_linker_sections()): +% if section.name != "code": +_load_${section.name}_section: + // src ptr + la a0, _lma_${section.name}_start + // dst ptr + la a1, __${section.name}_start + // copy size in bytes + la a2, _lma_${section.name}_end + sub a2, a2, a0 + + bltz a2, _load_${section.name}_section_end // dont do anything if you do not have something in ${section.name} + + sub a0,a0,s2 + call w25q128jw_read_standard +_load_${section.name}_section_end: + +% endif +% endfor + +#endif + +/* clear the bss segment */ +_init_bss: + la a0, __bss_start + la a2, __bss_end + sub a2, a2, a0 + li a1, 0 + call memset + +#ifdef FLASH_EXEC +/* copy initialized data sections from flash to ram (to be verified, copied from picosoc)*/ + la a0, _sidata + la a1, _sdata + la a2, _edata + bge a1, a2, end_init_data + loop_init_data: + lw a3, 0(a0) + sw a3, 0(a1) + addi a0, a0, 4 + addi a1, a1, 4 + blt a1, a2, loop_init_data + end_init_data: +#endif + +/* set vector table address and vectored mode */ + la a0, __vector_start + ori a0, a0, 0x1 + csrw mtvec, a0 + +/* new-style constructors and destructors */ + la a0, __libc_fini_array + call atexit + call __libc_init_array + +/* call main */ + lw a0, 0(sp) /* a0 = argc */ + addi a1, sp, __SIZEOF_POINTER__ /* a1 = argv */ + li a2, 0 /* a2 = envp = NULL */ + call main + tail exit + +.size _start, .-_start + +.global _init +.type _init, @function +.global _fini +.type _fini, @function +_init: + call init +_fini: + /* These don't have to do anything since we use init_array/fini_array. Prevent + missing symbol error */ + ret +.size _init, .-_init +.size _fini, .-_fini + + + diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/vectors.S b/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/vectors.S index f6a805c6..8e573eef 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/vectors.S +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/vectors.S @@ -126,39 +126,13 @@ new vector table (which is at mtvec) */ .section .text.vecs /* exception handling */ +.globl __no_irq_handler __no_irq_handler: la a0, no_exception_handler_msg jal ra, puts j __no_irq_handler - -sw_irq_handler: - csrr t0, mcause - slli t0, t0, 1 /* shift off the high bit */ - srli t0, t0, 1 - li t1, 2 - beq t0, t1, handle_illegal_insn - li t1, 11 - beq t0, t1, handle_ecall - li t1, 3 - beq t0, t1, handle_ebreak - j handle_unknown - -handle_ecall: - la a0, ecall_msg - jal ra, puts - j end_handler - -handle_ebreak: - la a0, ebreak_msg - jal ra, puts - j end_handler - -handle_illegal_insn: - la a0, illegal_insn_msg - jal ra, puts - j end_handler - +.globl handle_unknown handle_unknown: la a0, unknown_msg jal ra, puts diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/vectors_freertos.S b/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/vectors_freertos.S index 3596dc18..c4586b30 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/vectors_freertos.S +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/crt/vectors_freertos.S @@ -132,33 +132,6 @@ __no_irq_handler: jal ra, puts j __no_irq_handler -sw_irq_handler: - csrr t0, mcause - slli t0, t0, 1 /* shift off the high bit */ - srli t0, t0, 1 - li t1, 2 - beq t0, t1, handle_illegal_insn - li t1, 11 - beq t0, t1, handle_ecall - li t1, 3 - beq t0, t1, handle_ebreak - j handle_unknown - -handle_ecall: - la a0, ecall_msg - jal ra, puts - j end_handler - -handle_ebreak: - la a0, ebreak_msg - jal ra, puts - j end_handler - -handle_illegal_insn: - la a0, illegal_insn_msg - jal ra, puts - j end_handler - handle_unknown: la a0, unknown_msg jal ra, puts diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.c index c30b6105..3d102314 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.c @@ -31,6 +31,11 @@ /** **/ /****************************************************************************/ +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + #include "dma.h" /* To manage addresses. */ @@ -57,11 +62,6 @@ */ #define DMA_CSR_REG_MIE_MASK (( 1 << 19 ) | (1 << 11 ) ) // @ToDo Add definitions for this 19 and 11 -/** - * Size of a register of 32 bits. - */ -#define DMA_REGISTER_SIZE_BYTES sizeof(int) - /** * Mask to determine if an address is multiple of 4 (Word aligned). */ @@ -125,7 +125,7 @@ typedef enum * @return A configuration flags mask. Each individual flag can be accessed with * a bitwise AND ( ret & DMA_CONFIG_* ). */ -dma_config_flags_t validate_target( dma_target_t *p_tgt ); +dma_config_flags_t validate_target( dma_target_t *p_tgt, dma_trans_t *p_trans ); /** * @brief Creates an environment where targets can be added. An environment @@ -159,42 +159,55 @@ static inline uint8_t get_misalignment_b( uint8_t *p_ptr, * @param p_start Pointer to the beginning of the region. * @param p_end Pointer to the last byte of the environment. * @param p_type The data type to be transferred. - * @param p_size_du The number of data units to be transferred. Must be + * @param p_size_d1_du The number of data units to be transferred. Must be * non-zero. - * @param p_inc_du The size in data units of each increment. + * @param p_inc_d1_du The size in data units of each increment. * @retval 1 There is an outbound. * @retval 0 There is NOT an outbound. */ -static inline uint8_t is_region_outbound( uint8_t *p_start, +static inline uint8_t is_region_outbound_1D( uint8_t *p_start, uint8_t *p_end, uint32_t p_type, - uint32_t p_size_du, - uint32_t p_inc_du ); + uint32_t p_size_d1_du, + uint32_t p_inc_d1_du ); /** - * @brief Writes a given value into the specified register. Its operation - * mimics that of bitfield_field32_write(), but does not require the use of - * a field structure, that is not always provided in the _regs.h file. - * @param p_val The value to be written. - * @param p_offset The register's offset from the peripheral's base address - * where the target register is located. - * @param p_mask The variable's mask to only modify its bits inside the whole - * register. - * @param p_sel The selection index (i.e. From which bit inside the register - * the value is to be written). + * @brief Determines whether a given region will fit before the end of an + * environment with a 2D transaction. + * @param p_start Pointer to the beginning of the region. + * @param p_end Pointer to the last byte of the environment. + * @param p_type The data type to be transferred. + * @param p_size_d1_du The number of data units to be transferred. Must be + * non-zero. + * @param p_inc_d1_du The size in data units of each increment. + * @retval 1 There is an outbound. + * @retval 0 There is NOT an outbound. */ -static inline void write_register( uint32_t p_val, - uint32_t p_offset, - uint32_t p_mask, - uint8_t p_sel ); +static inline uint8_t is_region_outbound_2D( uint8_t *p_start, + uint8_t *p_end, + uint32_t p_type, + uint32_t p_size_d1_du, + uint32_t p_size_d2_du, + uint32_t p_inc_d1_du, + uint32_t p_inc_d2_du ); +/** + * @brief Analyzes a target to determine the size of its D1 increment (in bytes). + * @param p_tgt A pointer to the target to analyze. + * @param channel The channel to use as target. + * @return The number of bytes of the increment. + */ +static inline uint32_t get_increment_b_1D( dma_target_t * p_tgt, + uint8_t channel ); /** - * @brief Analyzes a target to determine the size of its increment (in bytes). + * @brief Analyzes a target to determine the size of its D2 increment (in bytes). * @param p_tgt A pointer to the target to analyze. + * @param channel The channel to use as target. * @return The number of bytes of the increment. */ -static inline uint32_t get_increment_b( dma_target_t * p_tgt ); +static inline uint32_t get_increment_b_2D( dma_target_t * p_tgt, + uint8_t channel ); /****************************************************************************/ @@ -210,10 +223,10 @@ static inline uint32_t get_increment_b( dma_target_t * p_tgt ); /****************************************************************************/ /** - * Control Block (CB) of the DMA peripheral. + * Control Block (CB) of a single DMA channel. * Has variables and constant necessary/useful for its control. */ -static struct +typedef struct { /** * Pointer to the transaction to be performed. @@ -232,7 +245,14 @@ static struct */ dma *peri; -}dma_cb; +}dma_ch_cb; + +/* Allocate the channel's memory space */ +static dma_ch_cb dma_subsys_per[DMA_CH_NUM]; + +/* High priority interrupts counters */ +uint16_t dma_hp_tr_intr_counter = 0; +uint16_t dma_hp_win_intr_counter = 0; /****************************************************************************/ @@ -243,45 +263,130 @@ static struct void handler_irq_dma(uint32_t id) { - /* - * Call the weak implementation provided in this module, + /* + * Find out which channel raised the interrupt and call + * either the weak implementation provided in this module, * or the non-weak implementation. */ - dma_intr_handler_window_done(); + + for (int i = 0; i < DMA_CH_NUM; i++) + { + if (dma_subsys_per[i].peri->WINDOW_IFR == 1) + { + dma_intr_handler_window_done(i); + + #ifdef DMA_HP_INTR_INDEX + /* + * If the channel that raised the interrupt is among the high priority channels, + * return to break the loop. + */ + #ifdef DMA_NUM_HP_INTR + if (i <= DMA_HP_INTR_INDEX && dma_hp_win_intr_counter < DMA_NUM_HP_INTR) + { + dma_hp_win_intr_counter++; + return; + } else if (i > DMA_HP_INTR_INDEX) + { + dma_hp_win_intr_counter = 0; + } + + #else + + if (i <= DMA_HP_INTR_INDEX) + { + return; + } + #endif + + #endif + } + } + return; } void fic_irq_dma(void) { - /* The flag is raised so the waiting loop can be broken.*/ - dma_cb.intrFlag = 1; - - /* - * Call the weak implementation provided in this module, + /* + * Find out which channel raised the interrupt and call + * either the weak implementation provided in this module, * or the non-weak implementation. */ - dma_intr_handler_trans_done(); + + for (int i = 0; i < DMA_CH_NUM; i++) + { + if (dma_subsys_per[i].peri->TRANSACTION_IFR == 1) + { + dma_subsys_per[i].intrFlag = 1; + dma_intr_handler_trans_done(i); + + #ifdef DMA_HP_INTR_INDEX + /* + * If the channel that raised the interrupt is among the high priority channels, + * return to break the loop. + */ + #ifdef DMA_NUM_HP_INTR + if (i <= DMA_HP_INTR_INDEX && dma_hp_tr_intr_counter < DMA_NUM_HP_INTR) + { + dma_hp_tr_intr_counter++; + return; + } + else if (i > DMA_HP_INTR_INDEX) + { + dma_hp_tr_intr_counter = 0; + } + + #else + + if (i <= DMA_HP_INTR_INDEX) + { + return; + } + #endif + + #endif + } + } + return; } -void dma_init( dma *peri ) +void dma_init( dma *dma_peri ) { /* * If a DMA peripheral was provided, use that one, otherwise use the * integrated one. */ - dma_cb.peri = peri ? peri : dma_peri; - - /* Clear the loaded transaction */ - dma_cb.trans = NULL; - /* Clear all values in the DMA registers. */ - dma_cb.peri->SRC_PTR = 0; - dma_cb.peri->DST_PTR = 0; - dma_cb.peri->SIZE = 0; - dma_cb.peri->PTR_INC = 0; - dma_cb.peri->SLOT = 0; - dma_cb.peri->DATA_TYPE = 0; - dma_cb.peri->MODE = 0; - dma_cb.peri->WINDOW_SIZE = 0; - dma_cb.peri->INTERRUPT_EN = 0; + + for (int i = 0; i < DMA_CH_NUM; i++) + { + dma_subsys_per[i].peri = dma_peri ? dma_peri : dma_peri(i); + + /* Clear the loaded transaction */ + dma_subsys_per[i].trans = NULL; + + /* Clear all values in the DMA registers. */ + dma_subsys_per[i].peri->SRC_PTR = 0; + dma_subsys_per[i].peri->DST_PTR = 0; + dma_subsys_per[i].peri->ADDR_PTR = 0; + dma_subsys_per[i].peri->SIZE_D1 = 0; + dma_subsys_per[i].peri->SIZE_D2 = 0; + dma_subsys_per[i].peri->SRC_PTR_INC_D1 = 0; + dma_subsys_per[i].peri->SRC_PTR_INC_D2 = 0; + dma_subsys_per[i].peri->DST_PTR_INC_D1 = 0; + dma_subsys_per[i].peri->DST_PTR_INC_D2 = 0; + dma_subsys_per[i].peri->DIM_CONFIG = 0; + dma_subsys_per[i].peri->DIM_INV = 0; + dma_subsys_per[i].peri->SLOT = 0; + dma_subsys_per[i].peri->SRC_DATA_TYPE = 0; + dma_subsys_per[i].peri->DST_DATA_TYPE = 0; + dma_subsys_per[i].peri->SIGN_EXT = 0; + dma_subsys_per[i].peri->MODE = 0; + dma_subsys_per[i].peri->WINDOW_SIZE = 0; + dma_subsys_per[i].peri->PAD_TOP = 0; + dma_subsys_per[i].peri->PAD_BOTTOM = 0; + dma_subsys_per[i].peri->PAD_LEFT = 0; + dma_subsys_per[i].peri->PAD_RIGHT = 0; + dma_subsys_per[i].peri->INTERRUPT_EN = 0; + } } dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, @@ -308,6 +413,14 @@ dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, /* The checks request should be a valid request. */ DMA_STATIC_ASSERT( p_check < DMA_PERFORM_CHECKS__size, "Check request not valid"); + /* The padding should be a valid number */ + DMA_STATIC_ASSERT( ((p_trans->pad_top_du >= 0 && p_trans->pad_top_du < 64) && + (p_trans->pad_bottom_du >= 0 && p_trans->pad_bottom_du < 64) && + (p_trans->pad_left_du >= 0 && p_trans->pad_left_du < 64) && + (p_trans->pad_right_du >= 0 && p_trans->pad_right_du < 64)), + "Padding not valid"); + /* The dimensionality should be valid*/ + DMA_STATIC_ASSERT( p_trans->dim < DMA_DIM_CONF__size, "Dimensionality not valid"); /* * CHECK IF TARGETS HAVE ERRORS @@ -318,8 +431,8 @@ dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, * A successful target validation has to be done before loading it to the * DMA. */ - uint8_t errorSrc = validate_target( p_trans->src ); - uint8_t errorDst = validate_target( p_trans->dst ); + uint8_t errorSrc = validate_target( p_trans->src, p_trans); + uint8_t errorDst = validate_target( p_trans->dst, p_trans); /* * If there are any errors or warnings in the valdiation of the targets, @@ -335,6 +448,43 @@ dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, return p_trans->flags; } + /* + * CHECK IF THERE ARE INCREMENTS INCONSISTENCIES + */ + + /* + * A transaction is considered 2D if the source and/or the destination has a 2D increment. + * e.g. It's possible to copy a 1x9 matrix to a 3x3 matrix or to copy a 3x3 matrix to a 1x9 one. + */ + + if (p_check) + { + // If the transaction is 2D, check that the D2 increment of the targets are non zero. + // If the transaction is 1D, check that the D2 increment of the targets are zero. + if((p_trans->dim == DMA_DIM_CONF_2D && (p_trans->src->inc_d2_du == 0 || p_trans->dst->inc_d2_du == 0)) || + (p_trans->dim == DMA_DIM_CONF_1D && (p_trans->src->inc_d2_du != 0 || p_trans->dst->inc_d2_du != 0))) + { + p_trans->flags |= DMA_CONFIG_INCOMPATIBLE; + p_trans->flags |= DMA_CONFIG_CRITICAL_ERROR; + return p_trans->flags; + } + } + + /* + * CHECK IF THERE ARE PADDING INCONSISTENCIES + */ + + if (p_check) + { + // If the transaction is 1D, check that the top and bottom paddings are set to zero. + if((p_trans->dim == DMA_DIM_CONF_1D && (p_trans->pad_top_du != 0 || p_trans->pad_bottom_du != 0))) + { + p_trans->flags |= DMA_CONFIG_INCOMPATIBLE; + p_trans->flags |= DMA_CONFIG_CRITICAL_ERROR; + return p_trans->flags; + } + } + /* * CHECK IF THERE ARE TRIGGER INCONSISTENCIES */ @@ -387,12 +537,10 @@ dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, /* The flags are cleaned in case the structure was used before.*/ p_trans->flags = DMA_CONFIG_OK; - /* The copy size of the source (in data units -of the source-) is - transformed to bytes, to be used as default size.*/ - uint8_t dataSize_b = DMA_DATA_TYPE_2_SIZE(p_trans->src->type); - p_trans->size_b = p_trans->src->size_du * dataSize_b; - /* By default, the source defines the data type.*/ - p_trans->type = p_trans->src->type; + + p_trans->src_type = p_trans->src->type; + p_trans->dst_type = p_trans->dst->type; + /* * By default, the transaction increment is set to 0 and, if required, * it will be changed to 1 (in which case both src and dst will have an @@ -416,12 +564,12 @@ dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, if( p_trans->src->trig == DMA_TRIG_MEMORY ) { - misalignment = get_misalignment_b( p_trans->src->ptr, p_trans->type ); + misalignment = get_misalignment_b( p_trans->src->ptr, p_trans->src_type ); } if( p_trans->dst->trig == DMA_TRIG_MEMORY ) { - dstMisalignment = get_misalignment_b( p_trans->dst->ptr, p_trans->type ); + dstMisalignment = get_misalignment_b( p_trans->dst->ptr, p_trans->dst_type ); } p_trans->flags |= ( misalignment ? DMA_CONFIG_SRC : DMA_CONFIG_OK ); @@ -491,8 +639,8 @@ dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, * No further operations are done to prevent corrupting * information that could be useful for debugging purposes. */ - if( ( p_trans->src->inc_du > 1 ) - || ( p_trans->dst->inc_du > 1 ) ) + if( ( p_trans->src->inc_d1_du > 1 ) + || ( p_trans->dst->inc_d1_du > 1 ) ) { p_trans->flags |= DMA_CONFIG_DISCONTINUOUS; p_trans->flags |= DMA_CONFIG_CRITICAL_ERROR; @@ -507,27 +655,28 @@ dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, * If realignment is allowed and there are no discontinuities, * a more granular data type is used according to the detected * misalignment in order to overcome it. - */ - p_trans->type += misalignment; - /* + */ + p_trans->dst_type = p_trans->dst_type + misalignment; + + /* * Source and destination increment should now be of the size * of the data. * As increments are given in bytes, in both cases should be the * size of a data unit. */ - p_trans->inc_b = DMA_DATA_TYPE_2_SIZE( p_trans->type ); + p_trans->inc_b = DMA_DATA_TYPE_2_SIZE( p_trans->dst_type ); /* The copy size does not change, as it is already stored in bytes.*/ } /* - * CHECK IF SOURCE HAS SIZE 0 + * CHECK IF SOURCE HAS ZERO SIZE(s) */ /* * No further operations are done to prevent corrupting information * that could be useful for debugging purposes. */ - if( p_trans->src->size_du == 0 ) + if(p_trans->size_d1_du == 0 || (p_trans->dim == DMA_DIM_CONF_2D && p_trans->size_d2_du == 0)) { p_trans->flags |= DMA_CONFIG_SRC; p_trans->flags |= DMA_CONFIG_CRITICAL_ERROR; @@ -562,21 +711,24 @@ dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, * No further operations are done to prevent corrupting information * that could be useful for debugging purposes. */ - uint8_t isEnv = p_trans->dst->env; - uint8_t isOutb = is_region_outbound( - p_trans->dst->ptr, - p_trans->dst->env->end, - p_trans->type, - p_trans->src->size_du, - p_trans->dst->inc_du ); - if( isEnv && isOutb ) - { - p_trans->flags |= DMA_CONFIG_DST; - p_trans->flags |= DMA_CONFIG_OUTBOUNDS; - p_trans->flags |= DMA_CONFIG_CRITICAL_ERROR; - return p_trans->flags; - } + uint8_t isEnv = (p_trans->dst->env != NULL); + + if(isEnv) { + uint8_t isOutb = is_region_outbound_1D( + p_trans->dst->ptr, + p_trans->dst->env->end, + p_trans->dst_type, + p_trans->size_d1_du, + p_trans->dst->inc_d1_du ); + if( isOutb ) + { + p_trans->flags |= DMA_CONFIG_DST; + p_trans->flags |= DMA_CONFIG_OUTBOUNDS; + p_trans->flags |= DMA_CONFIG_CRITICAL_ERROR; + return p_trans->flags; + } + } // @ToDo: It should also be checked that the destination is behind the // source if there will be overlap. // @ToDo: Consider if (when a destination target has no environment) @@ -591,7 +743,7 @@ dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, * this would not cause any error, the transaction is rejected because * it is likely a mistake. */ - if( p_trans->win_du > p_trans->size_b ) + if( p_trans->win_du > p_trans->size_d1_du ) { p_trans->flags |= DMA_CONFIG_WINDOW_SIZE; p_trans->flags |= DMA_CONFIG_CRITICAL_ERROR; @@ -609,7 +761,7 @@ dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, * certainty that an real error will occur. */ uint32_t threshold = dma_window_ratio_warning_threshold(); - uint32_t ratio = p_trans->size_b / p_trans->win_du; + uint32_t ratio = p_trans->size_d1_du / p_trans->win_du; if( p_trans->win_du && threshold && ( ratio > threshold) ) @@ -622,8 +774,9 @@ dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, return p_trans->flags; } -dma_config_flags_t dma_load_transaction( dma_trans_t *p_trans ) +dma_config_flags_t dma_load_transaction( dma_trans_t *p_trans) { + uint8_t channel = p_trans->channel; /* * CHECK FOR CRITICAL ERRORS */ @@ -635,7 +788,7 @@ dma_config_flags_t dma_load_transaction( dma_trans_t *p_trans ) */ if( p_trans->flags & DMA_CONFIG_CRITICAL_ERROR ) { - dma_cb.trans = NULL; + dma_subsys_per[channel].trans = NULL; return DMA_CONFIG_CRITICAL_ERROR; } @@ -650,74 +803,137 @@ dma_config_flags_t dma_load_transaction( dma_trans_t *p_trans ) * until it has ended. * Transactions can still be validated in the meantime. */ - if( !dma_is_ready() ) + if( !dma_is_ready(channel) ) { return DMA_CONFIG_TRANS_OVERRIDE; } /* Save the current transaction */ - dma_cb.trans = p_trans; + dma_subsys_per[channel].trans = p_trans; /* * ENABLE/DISABLE INTERRUPTS */ /* - * If the selected en event is polling, interrupts are disabled. + * If the selected end event is polling, interrupts are disabled. * Otherwise the mie.MEIE bit is set to one to enable machine-level * fast DMA interrupt. */ - dma_cb.peri->INTERRUPT_EN = INTR_EN_NONE; + dma_subsys_per[channel].peri->INTERRUPT_EN = INTR_EN_NONE; CSR_CLEAR_BITS(CSR_REG_MIE, DMA_CSR_REG_MIE_MASK ); - if( dma_cb.trans->end != DMA_TRANS_END_POLLING ) + if( dma_subsys_per[channel].trans->end != DMA_TRANS_END_POLLING ) { - /* Enable global interrupt for machine-level interrupts. */ + /* Enable global interrupt. */ CSR_SET_BITS(CSR_REG_MSTATUS, 0x8 ); - /* @ToDo: What does this do? */ + /* Enable machine-level fast interrupt. */ CSR_SET_BITS(CSR_REG_MIE, DMA_CSR_REG_MIE_MASK ); - dma_cb.peri->INTERRUPT_EN |= INTR_EN_TRANS_DONE; + /* Enable the transaction interrupt for the channel by setting the corresponding bit in Transaction IFR */ + write_register( + 0x1, + DMA_INTERRUPT_EN_REG_OFFSET, + 0xffff, + DMA_INTERRUPT_EN_TRANSACTION_DONE_BIT, + dma_subsys_per[channel].peri + ); /* Only if a window is used should the window interrupt be set. */ if( p_trans->win_du > 0 ) { - dma_cb.peri->INTERRUPT_EN |= INTR_EN_WINDOW_DONE; + write_register( + 0x1, + DMA_INTERRUPT_EN_REG_OFFSET, + 0xffff, + DMA_INTERRUPT_EN_WINDOW_DONE_BIT, + dma_subsys_per[channel].peri + ); } } + /* + * SET THE PADDING + */ + + /* + * In the case of a 1D transaction with padding enabled, the DMA has to be configured to treat + * the transaction as a 2D one with a second dimension of 1 du and a second dimension increment of 1 du. + */ + + if (p_trans->dim == DMA_DIM_CONF_1D && (p_trans->pad_left_du != 0 || p_trans->pad_right_du != 0)) + { + p_trans->dim = DMA_DIM_CONF_2D; + /* Set the d2 size and increment to just the minimum */ + p_trans->size_d2_du = 1; + p_trans->src->inc_d2_du = DMA_DATA_TYPE_2_SIZE( p_trans->dst_type ); + + write_register( dma_subsys_per[channel].trans->pad_left_du, + DMA_PAD_LEFT_REG_OFFSET, + DMA_PAD_LEFT_PAD_MASK, + DMA_PAD_LEFT_PAD_OFFSET, + dma_subsys_per[channel].peri); + + write_register( dma_subsys_per[channel].trans->pad_right_du, + DMA_PAD_RIGHT_REG_OFFSET, + DMA_PAD_RIGHT_PAD_MASK, + DMA_PAD_RIGHT_PAD_OFFSET, + dma_subsys_per[channel].peri); + } + else if (p_trans->dim == DMA_DIM_CONF_2D) + { + write_register( dma_subsys_per[channel].trans->pad_top_du, + DMA_PAD_TOP_REG_OFFSET, + DMA_PAD_TOP_PAD_MASK, + DMA_PAD_TOP_PAD_OFFSET, + dma_subsys_per[channel].peri); + + write_register( dma_subsys_per[channel].trans->pad_bottom_du, + DMA_PAD_BOTTOM_REG_OFFSET, + DMA_PAD_BOTTOM_PAD_MASK, + DMA_PAD_BOTTOM_PAD_OFFSET, + dma_subsys_per[channel].peri); + + write_register( dma_subsys_per[channel].trans->pad_left_du, + DMA_PAD_LEFT_REG_OFFSET, + DMA_PAD_LEFT_PAD_MASK, + DMA_PAD_LEFT_PAD_OFFSET, + dma_subsys_per[channel].peri); + + write_register( dma_subsys_per[channel].trans->pad_right_du, + DMA_PAD_RIGHT_REG_OFFSET, + DMA_PAD_RIGHT_PAD_MASK, + DMA_PAD_RIGHT_PAD_OFFSET, + dma_subsys_per[channel].peri); + } /* * SET THE POINTERS */ - dma_cb.peri->SRC_PTR = dma_cb.trans->src->ptr; + dma_subsys_per[channel].peri->SRC_PTR = (uint32_t)dma_subsys_per[channel].trans->src->ptr; - if(dma_cb.trans->mode != DMA_TRANS_MODE_ADDRESS) + if(dma_subsys_per[channel].trans->mode != DMA_TRANS_MODE_ADDRESS) { /* - Write to the destination pointers only if we are not in address mode, - otherwise the destination address is read in a separate port in parallel with the data - from the address port + Write to the destination pointers only if we are not in address mode, + otherwise the destination address is read in a separate port in parallel with the data + from the address port */ - dma_cb.peri->DST_PTR = dma_cb.trans->dst->ptr; - } - else - { - dma_cb.peri->ADDR_PTR = dma_cb.trans->src_addr->ptr; - } - - if(dma_cb.trans->mode != DMA_TRANS_MODE_ADDRESS) + dma_subsys_per[channel].peri->DST_PTR = (uint32_t)dma_subsys_per[channel].trans->dst->ptr; + } + else { - /* - Write to the destination pointers only if we are not in address mode, - otherwise the destination address is read in a separate port in parallel with the data - from the address port - */ - dma_cb.peri->DST_PTR = dma_cb.trans->dst->ptr; - } - else - { - dma_cb.peri->ADDR_PTR = dma_cb.trans->src_addr->ptr; - } + dma_subsys_per[channel].peri->ADDR_PTR = (uint32_t)dma_subsys_per[channel].trans->src_addr->ptr; + } + + /* + * SET THE TRANSPOSITION MODE + */ + + write_register(dma_subsys_per[channel].trans->dim_inv, + DMA_DIM_INV_REG_OFFSET, + 0x1 << DMA_DIM_INV_SEL_BIT, + DMA_DIM_INV_SEL_BIT, + dma_subsys_per[channel].peri); /* * SET THE INCREMENTS @@ -731,66 +947,124 @@ dma_config_flags_t dma_load_transaction( dma_trans_t *p_trans ) * In that case, a increment of 0 is necessary. * In case of DMA Address mode transaction, the dst pointer is ignored * as the values read from the second port are instead used. + * In case of a 2D DMA transaction, the second dimension increment is set. */ - write_register( get_increment_b( dma_cb.trans->src ), - DMA_PTR_INC_REG_OFFSET, - DMA_PTR_INC_SRC_PTR_INC_MASK, - DMA_PTR_INC_SRC_PTR_INC_OFFSET ); - - + write_register( get_increment_b_1D( dma_subsys_per[channel].trans->src, channel), + DMA_SRC_PTR_INC_D1_REG_OFFSET, + DMA_SRC_PTR_INC_D1_INC_MASK, + DMA_SRC_PTR_INC_D1_INC_OFFSET, + dma_subsys_per[channel].peri); - if(dma_cb.trans->mode != DMA_TRANS_MODE_ADDRESS) + if(dma_subsys_per[channel].trans->dim == DMA_DIM_CONF_2D) { - write_register( get_increment_b( dma_cb.trans->dst ), - DMA_PTR_INC_REG_OFFSET, - DMA_PTR_INC_DST_PTR_INC_MASK, - DMA_PTR_INC_DST_PTR_INC_OFFSET ); + write_register( get_increment_b_2D( dma_subsys_per[channel].trans->src, channel), + DMA_SRC_PTR_INC_D2_REG_OFFSET, + DMA_SRC_PTR_INC_D2_INC_MASK, + DMA_SRC_PTR_INC_D2_INC_OFFSET, + dma_subsys_per[channel].peri ); } + if(dma_subsys_per[channel].trans->mode != DMA_TRANS_MODE_ADDRESS) + { + write_register( get_increment_b_1D( dma_subsys_per[channel].trans->dst, channel), + DMA_DST_PTR_INC_D1_REG_OFFSET, + DMA_DST_PTR_INC_D1_INC_MASK, + DMA_DST_PTR_INC_D1_INC_OFFSET, + dma_subsys_per[channel].peri ); + + if(dma_subsys_per[channel].trans->dim == DMA_DIM_CONF_2D) + { + write_register( get_increment_b_2D( dma_subsys_per[channel].trans->dst, channel), + DMA_DST_PTR_INC_D2_REG_OFFSET, + DMA_DST_PTR_INC_D2_INC_MASK, + DMA_DST_PTR_INC_D2_INC_OFFSET, + dma_subsys_per[channel].peri ); + } + } /* * SET THE OPERATION MODE AND WINDOW SIZE */ - dma_cb.peri->MODE = dma_cb.trans->mode; + dma_subsys_per[channel].peri->MODE = dma_subsys_per[channel].trans->mode; /* The window size is set to the transaction size if it was set to 0 in order to disable the functionality (it will never be triggered). */ - dma_cb.peri->WINDOW_SIZE = dma_cb.trans->win_du - ? dma_cb.trans->win_du - : dma_cb.trans->size_b; + dma_subsys_per[channel].peri->WINDOW_SIZE = dma_subsys_per[channel].trans->win_du + ? dma_subsys_per[channel].trans->win_du + : dma_subsys_per[channel].trans->size_d1_du; + + /* + * SET THE DIMENSIONALITY + */ + write_register( dma_subsys_per[channel].trans->dim, + DMA_DIM_CONFIG_REG_OFFSET, + 0x1, + DMA_DIM_CONFIG_DMA_DIM_BIT, + dma_subsys_per[channel].peri ); + + /* + * SET THE SIGN EXTENSION BIT + */ + write_register( dma_subsys_per[channel].trans->sign_ext, + DMA_SIGN_EXT_REG_OFFSET, + 0x1 << DMA_SIGN_EXT_SIGNED_BIT, + DMA_SIGN_EXT_SIGNED_BIT, + dma_subsys_per[channel].peri ); + + + /* + * SET THE SIGN EXTENSION BIT + */ + write_register( dma_subsys_per[channel].trans->sign_ext, + DMA_SIGN_EXT_REG_OFFSET, + 0x1 << DMA_SIGN_EXT_SIGNED_BIT, + DMA_SIGN_EXT_SIGNED_BIT, + dma_subsys_per[channel].peri ); + /* * SET TRIGGER SLOTS AND DATA TYPE */ - write_register( dma_cb.trans->src->trig, + write_register( dma_subsys_per[channel].trans->src->trig, DMA_SLOT_REG_OFFSET, DMA_SLOT_RX_TRIGGER_SLOT_MASK, - DMA_SLOT_RX_TRIGGER_SLOT_OFFSET ); + DMA_SLOT_RX_TRIGGER_SLOT_OFFSET, + dma_subsys_per[channel].peri ); - write_register( dma_cb.trans->dst->trig, + write_register( dma_subsys_per[channel].trans->dst->trig, DMA_SLOT_REG_OFFSET, DMA_SLOT_TX_TRIGGER_SLOT_MASK, - DMA_SLOT_TX_TRIGGER_SLOT_OFFSET ); - - write_register( dma_cb.trans->type, - DMA_DATA_TYPE_REG_OFFSET, - DMA_DATA_TYPE_DATA_TYPE_MASK, - DMA_SELECTION_OFFSET_START ); + DMA_SLOT_TX_TRIGGER_SLOT_OFFSET, + dma_subsys_per[channel].peri ); + + write_register( dma_subsys_per[channel].trans->dst_type, + DMA_DST_DATA_TYPE_REG_OFFSET, + DMA_DST_DATA_TYPE_DATA_TYPE_MASK, + DMA_SELECTION_OFFSET_START, + dma_subsys_per[channel].peri ); + + write_register( dma_subsys_per[channel].trans->src_type, + DMA_SRC_DATA_TYPE_REG_OFFSET, + DMA_SRC_DATA_TYPE_DATA_TYPE_MASK, + DMA_SELECTION_OFFSET_START, + dma_subsys_per[channel].peri ); return DMA_CONFIG_OK; } -dma_config_flags_t dma_launch( dma_trans_t *p_trans ) +dma_config_flags_t dma_launch( dma_trans_t *p_trans) { + uint8_t channel = p_trans->channel; + /* * Make sure that the loaded transaction is the intended transaction. * If the loaded trans was NULL'd, then this the transaction is never * launched. */ if( ( p_trans == NULL ) - || ( dma_cb.trans != p_trans ) ) // @ToDo: Check per-element. + || ( dma_subsys_per[channel].trans != p_trans ) ) // @ToDo: Check per-element. { return DMA_CONFIG_CRITICAL_ERROR; } @@ -806,7 +1080,7 @@ dma_config_flags_t dma_launch( dma_trans_t *p_trans ) * until it has ended. * Transactions can still be validated in the meantime. */ - if( !dma_is_ready() ) + if( !dma_is_ready(channel) ) { return DMA_CONFIG_TRANS_OVERRIDE; } @@ -815,58 +1089,74 @@ dma_config_flags_t dma_launch( dma_trans_t *p_trans ) * This has to be done prior to writing the register because otherwise * the interrupt could arrive before it is lowered. */ - dma_cb.intrFlag = 0; + dma_subsys_per[channel].intrFlag = 0; + + /* Load the size(s) and start the transaction. */ - /* Load the size and start the transaction. */ - dma_cb.peri->SIZE = dma_cb.trans->size_b; + if(dma_subsys_per[channel].trans->dim == DMA_DIM_CONF_2D) + { + write_register( dma_subsys_per[channel].trans->size_d2_du, + DMA_SIZE_D2_REG_OFFSET, + DMA_SIZE_D2_SIZE_MASK, + DMA_SIZE_D2_SIZE_OFFSET, + dma_subsys_per[channel].peri + ); + } + write_register( dma_subsys_per[channel].trans->size_d1_du, + DMA_SIZE_D1_REG_OFFSET, + DMA_SIZE_D1_SIZE_MASK, + DMA_SIZE_D1_SIZE_OFFSET, + dma_subsys_per[channel].peri + ); /* * If the end event was set to wait for the interrupt, the dma_launch * will not return until the interrupt arrives. */ + + while( p_trans->end == DMA_TRANS_END_INTR_WAIT - && ( dma_cb.intrFlag != 0 ) ) { // @ToDo: add a label for this 0 - wait_for_interrupt(); + && ( dma_subsys_per[channel].intrFlag != 0x0 ) ) { + wait_for_interrupt(); } return DMA_CONFIG_OK; } - -__attribute__((optimize("O0"))) uint32_t dma_is_ready(void) +__attribute__((optimize("O0"))) uint32_t dma_is_ready(uint8_t channel) { /* The transaction READY bit is read from the status register*/ - uint32_t ret = ( dma_cb.peri->STATUS & (1<STATUS & (1<DONE ); + * return ( 1 && dma_subsys_per[channel].peri->DONE ); * 2) Consider only the LSB == 1 to be a valid 1 using a BITWISE AND. - * return ( 1 & dma_cb.peri->DONE ); + * return ( 1 & dma_subsys_per[channel].peri->DONE ); * This would be fixed if the DONE register was a 1 bit field. */ -uint32_t dma_get_window_count() +uint32_t dma_get_window_count(uint8_t channel) { - return dma_cb.peri->WINDOW_COUNT; + return dma_subsys_per[channel].peri->WINDOW_COUNT; } -void dma_stop_circular() +void dma_stop_circular(uint8_t channel) { /* * The DMA finishes the current transaction before and does not start * a new one. */ - dma_cb.peri->MODE = DMA_TRANS_MODE_SINGLE; + dma_subsys_per[channel].peri->MODE = DMA_TRANS_MODE_SINGLE; } -__attribute__((weak, optimize("O0"))) void dma_intr_handler_trans_done() +__attribute__((weak, optimize("O0"))) void dma_intr_handler_trans_done(uint8_t channel) { /* * The DMA transaction has finished! @@ -877,7 +1167,7 @@ __attribute__((weak, optimize("O0"))) void dma_intr_handler_trans_done() */ } -__attribute__((weak, optimize("O0"))) void dma_intr_handler_window_done() +__attribute__((weak, optimize("O0"))) void dma_intr_handler_window_done(uint8_t channel) { /* * The DMA has copied another window. @@ -906,7 +1196,7 @@ __attribute__((weak, optimize("O0"))) uint8_t dma_window_ratio_warning_threshold /** **/ /****************************************************************************/ -dma_config_flags_t validate_target( dma_target_t *p_tgt ) +dma_config_flags_t validate_target( dma_target_t *p_tgt, dma_trans_t *p_trans ) { /* Flags variable to pass encountered errors. */ dma_config_flags_t flags = DMA_CONFIG_OK; @@ -915,14 +1205,19 @@ dma_config_flags_t validate_target( dma_target_t *p_tgt ) */ /* Increment can be 0 when a trigger is used. */ - DMA_STATIC_ASSERT( p_tgt->inc_du >= 0 , "Increment not valid"); + DMA_STATIC_ASSERT( p_tgt->inc_d1_du >= 0 && p_tgt->inc_d1_du < 64 , "Increment not valid"); + /* Increment on D2 has to be 0 for 1D operations */ + DMA_STATIC_ASSERT( p_tgt->inc_d2_du >= 0 && p_tgt->inc_d2_du < 4194304 , "Increment d2 not valid"); /* The size could be 0 if the target is only going to be used as a destination. */ - DMA_STATIC_ASSERT( p_tgt->size_du >= 0 , "Size not valid"); + DMA_STATIC_ASSERT( p_tgt->size_d1_du >= 0 && p_tgt->size_d1_du < 65536 , "Size not valid"); + /* The size can be 0 or 1 if the target is involved in a 1D padded transaction */ + DMA_STATIC_ASSERT( p_tgt->size_d2_du >= 0 && p_tgt->size_d1_du < 65536 , "Size d2 not valid"); /* The data type must be a valid type */ - DMA_STATIC_ASSERT( p_tgt->type < DMA_DATA_TYPE__size , "Type not valid"); + DMA_STATIC_ASSERT( p_tgt->type < DMA_DATA_TYPE__size , "Source type not valid"); /* The trigger must be among the valid trigger values. */ DMA_STATIC_ASSERT( p_tgt->trig < DMA_TRIG__size , "Trigger not valid"); + /* * INTEGRITY CHECKS @@ -937,19 +1232,30 @@ dma_config_flags_t validate_target( dma_target_t *p_tgt ) { /* Check if the environment was properly formed.*/ flags |= validate_environment( p_tgt->env ); - /* - * Check if the target selected size goes beyond the boundaries of + * Check if the transaction size goes beyond the boundaries of * the environment. - * This is only analyzed if a size was defined. */ - if( p_tgt->size_du != 0 ) + + if( p_trans->size_d2_du != 0 ) { - uint8_t isOutb = is_region_outbound( p_tgt->ptr, + uint8_t isOutb = is_region_outbound_2D( p_tgt->ptr, p_tgt->env->end, p_tgt->type, - p_tgt->size_du, - p_tgt->inc_du ); + p_trans->size_d1_du, + p_trans->size_d2_du, + p_tgt->inc_d1_du, + p_tgt->inc_d2_du); + if( isOutb ) + { + flags |= DMA_CONFIG_OUTBOUNDS; + } + } else { + uint8_t isOutb = is_region_outbound_1D( p_tgt->ptr, + p_tgt->env->end, + p_tgt->type, + p_trans->size_d1_du, + p_tgt->inc_d1_du ); if( isOutb ) { flags |= DMA_CONFIG_OUTBOUNDS; @@ -975,7 +1281,7 @@ dma_config_flags_t validate_target( dma_target_t *p_tgt ) if( p_tgt->trig == DMA_TRIG_MEMORY ){ /* If it is a memory region. */ /* It should have an increment. */ - if( ( p_tgt->inc_du == 0 ) ){ + if( ( p_tgt->inc_d1_du == 0 ) ){ flags |= DMA_CONFIG_INCOMPATIBLE; } } @@ -983,7 +1289,7 @@ dma_config_flags_t validate_target( dma_target_t *p_tgt ) { /* It should not have neither an environment nor an increment. */ if( ( (p_tgt->env != NULL) - || ( p_tgt->inc_du != 0 ) ) ) + || ( p_tgt->inc_d1_du != 0 ) ) ) { flags |= DMA_CONFIG_INCOMPATIBLE; } @@ -1085,11 +1391,11 @@ static inline uint8_t get_misalignment_b( uint8_t *p_ptr, return misalignment; } -static inline uint8_t is_region_outbound( uint8_t *p_start, +static inline uint8_t is_region_outbound_1D( uint8_t *p_start, uint8_t *p_end, uint32_t p_type, - uint32_t p_size_du, - uint32_t p_inc_du ) + uint32_t p_size_d1_du, + uint32_t p_inc_d1_du ) { /* 000 = A data unit to be copied * xxx = A data unit to be skipped @@ -1105,39 +1411,62 @@ static inline uint8_t is_region_outbound( uint8_t *p_start, * If the environment ends before the last affected byte, then there is * outbound writing and the function returns 1. */ - uint32_t affectedUnits = ( p_size_du - 1 ) * p_inc_du + 1; + uint32_t affectedUnits = ( p_size_d1_du - 1 ) * p_inc_d1_du + 1; uint32_t rangeSize = DMA_DATA_TYPE_2_SIZE(p_type) * affectedUnits; - uint32_t lasByteInsideRange = p_start + rangeSize -1; - return ( p_end < lasByteInsideRange ); + uint32_t lastByteInsideRange = (uint32_t)p_start + rangeSize -1; + return ( p_end < lastByteInsideRange ); // Size is be guaranteed to be non-zero before calling this function. } -/* @ToDo: Consider changing the "mask" parameter for a bitfield definition -(see dma_regs.h) */ -static inline void write_register( uint32_t p_val, - uint32_t p_offset, - uint32_t p_mask, - uint8_t p_sel ) +static inline uint8_t is_region_outbound_2D( uint8_t *p_start, + uint8_t *p_end, + uint32_t p_type, + uint32_t p_size_d1_du, + uint32_t p_size_d2_du, + uint32_t p_inc_d1_du, + uint32_t p_inc_d2_du ) { - /* - * The index is computed to avoid needing to access the structure - * as a structure. - */ - uint8_t index = p_offset / DMA_REGISTER_SIZE_BYTES; - /* - * An intermediate variable "value" is used to prevent writing twice into - * the register. - */ - uint32_t value = (( uint32_t * ) dma_cb.peri ) [ index ]; - value &= ~( p_mask << p_sel ); - value |= (p_val & p_mask) << p_sel; - (( uint32_t * ) dma_cb.peri ) [ index ] = value; + /* + * If the environment ends before the last affected byte, then there is + * outbound writing and the function returns 1. + */ + + uint32_t affectedUnits = (( p_size_d1_du - 1 ) * p_inc_d1_du + 1) * (p_size_d2_du) + p_inc_d2_du * (p_size_d2_du - 1); + uint32_t rangeSize = DMA_DATA_TYPE_2_SIZE(p_type) * affectedUnits; + uint32_t lastByteInsideRange = (uint32_t)p_start + rangeSize -1; + return ( p_end < lastByteInsideRange ); + + // Size is be guaranteed to be non-zero before calling this function. +} -// @ToDo: mmio_region_write32(dma->base_addr, (ptrdiff_t)(DMA_SLOT_REG_OFFSET), (tx_slot_mask << DMA_SLOT_TX_TRIGGER_SLOT_OFFSET) + rx_slot_mask) +static inline uint32_t get_increment_b_1D( dma_target_t * p_tgt, + uint8_t channel) +{ + uint32_t inc_b = 0; + /* If the target uses a trigger, the increment remains 0. */ + if( p_tgt->trig == DMA_TRIG_MEMORY ) + { + /* + * If the transaction increment has been overriden (due to + * misalignments), then that value is used (it's always set to 1). + */ + inc_b = dma_subsys_per[channel].trans->inc_b; + /* + * Otherwise, the target-specific increment is used transformed into + * bytes). + */ + if( inc_b == 0 ) + { + uint8_t dataSize_d1_du = DMA_DATA_TYPE_2_SIZE( p_tgt->type ); + inc_b = ( p_tgt->inc_d1_du * dataSize_d1_du ); + } + } + return inc_b; } -static inline uint32_t get_increment_b( dma_target_t * p_tgt ) +static inline uint32_t get_increment_b_2D( dma_target_t * p_tgt, + uint8_t channel ) { uint32_t inc_b = 0; /* If the target uses a trigger, the increment remains 0. */ @@ -1147,7 +1476,7 @@ static inline uint32_t get_increment_b( dma_target_t * p_tgt ) * If the transaction increment has been overriden (due to * misalignments), then that value is used (it's always set to 1). */ - inc_b = dma_cb.trans->inc_b; + inc_b = dma_subsys_per[channel].trans->inc_b; /* * Otherwise, the target-specific increment is used transformed into @@ -1155,13 +1484,18 @@ static inline uint32_t get_increment_b( dma_target_t * p_tgt ) */ if( inc_b == 0 ) { - uint8_t dataSize_b = DMA_DATA_TYPE_2_SIZE( dma_cb.trans->type ); - inc_b = ( p_tgt->inc_du * dataSize_b ); + uint8_t dataSize_d1_du = DMA_DATA_TYPE_2_SIZE( p_tgt->type ); + inc_b = ( p_tgt->inc_d2_du * dataSize_d1_du ); } } return inc_b; } + +#ifdef __cplusplus +} +#endif // __cplusplus + /****************************************************************************/ /** **/ /* EOF */ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.h index 1956f9e8..98a4f0f4 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma.h @@ -68,6 +68,36 @@ #define DMA_SPI_FLASH_TX_SLOT 0x08 #define DMA_I2S_RX_SLOT 0x10 +#define DMA_INT_TR_START 0x0 + +/* + * For multichannel configurations, a priority mechanism can be set up to allow the interrupt handler + * to prioritize a set of channels. + * + * In order to enable this feature, the user must define DMA_HP_INTR_INDEX. + * + * When an interrupt is raised, the handler will loop through the channels. If the channel that + * raised the interrupt is part of the high priority channels (index <= DMA_HP_INTR_INDEX), + * it will call the actual handler and exit the loop. + * It this way, low index channels will always be serviced first. + * + * However, this feature could cause low priority channels to never be serviced if the high priority + * interrupts are raised at a faster frequency. + * In order to avoid this, the user can define DMA_NUM_HP_INTR (uint16_t). + * This macro puts a limit to the number of consecutive interrupts raised by high priority channels + * that can trigger a "return". + * If N = DMA_NUM_HP_INTR interrupts are raised by high priority channels, the N+1 interrupt will be + * serviced and then no "return" will be triggered, thus allowing the handler's loop to continue and + * low priority channels to be serviced, if necessary. + * + * The priority mechanism is applied to both transaction done and window done interrupts, if enabled. + * Separate counters are used for each type of interrupt. + */ + +//#define DMA_HP_INTR_INDEX 0 +//#define DMA_NUM_HP_INTR 5 + + #ifdef __cplusplus extern "C" { #endif @@ -77,6 +107,8 @@ extern "C" { */ #define DMA_DATA_TYPE_2_SIZE(type) (0b00000100 >> (type) ) +#define DMA_SELECTION_OFFSET_START 0 + /****************************************************************************/ /** **/ /** TYPEDEFS AND STRUCTURES **/ @@ -104,6 +136,8 @@ typedef enum DMA_TRIG_SLOT_SPI_FLASH_RX = 4, /*!< Slot 3 (MEM < SPI FLASH). */ DMA_TRIG_SLOT_SPI_FLASH_TX = 8, /*!< Slot 4 (MEM > SPI FLASH). */ DMA_TRIG_SLOT_I2S = 16,/*!< Slot 5 (I2S). */ + DMA_TRIG_SLOT_EXT_TX = 32,/*!< Slot 6 (External peripherals TX). */ + DMA_TRIG_SLOT_EXT_RX = 64,/*!< Slot 7 (External peripherals RX). */ DMA_TRIG__size, /*!< Not used, only for sanity checks. */ DMA_TRIG__undef, /*!< DMA will not be used. */ } dma_trigger_slot_mask_t; @@ -116,11 +150,11 @@ typedef enum */ typedef enum { - DMA_DATA_TYPE_WORD = DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD,/*!< + DMA_DATA_TYPE_WORD = DMA_SRC_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD,/*!< Word = 4 bytes = 32 bits */ - DMA_DATA_TYPE_HALF_WORD = DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_16BIT_WORD,/*!< + DMA_DATA_TYPE_HALF_WORD = DMA_SRC_DATA_TYPE_DATA_TYPE_VALUE_DMA_16BIT_WORD,/*!< Half Word = 2 bytes = 16 bits */ - DMA_DATA_TYPE_BYTE = DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD,/*!< + DMA_DATA_TYPE_BYTE = DMA_SRC_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD,/*!< Byte = 1 byte = 8 bits */ /* DMA_DATA_TYPE_BYTE_alt = DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD_2, * BYTE and BYTE_alt are interchangeable in hw, but we advice against @@ -132,6 +166,19 @@ typedef enum DMA_DATA_TYPE__undef, /*!< DMA will not be used. */ } dma_data_type_t; +typedef enum +{ + DMA_DIM_CONF_1D = 0, /* The DMA will copy data along D1 only. */ + DMA_DIM_CONF_2D = 1, /* The DMA will copy data along D1 and D2. */ + DMA_DIM_CONF__size, /* Not used, only for sanity checks. */ + /* + Padding is enabled with the 2D mode. This means that to pad a 1D + data structure, i.e. an array, the DMA would have to be set in 2D + mode with the D2 dimension set to 1. + This case is handled by the DMA HAL, so it's transparent to the user. + */ +} dma_dim_t; + /** * It is possible to choose the level of safety with which the DMA operation * should be configured. @@ -277,11 +324,11 @@ typedef struct if the target is a peripheral. */ uint8_t* ptr; /*!< Pointer to the start address from/to where data will be copied/pasted. */ - uint16_t inc_du; /*!< How much the pointer will increase + uint8_t inc_d1_du; /*!< How much the pointer will increase every time a read/write operation is done. It is a multiple of the data units. Can be left blank if the target is a peripheral. */ - uint32_t size_du; /*!< The size (in data units) of the data to - be copied. Can be left blank if the target will only be used as destination.*/ + uint32_t inc_d2_du; /*!< How much the D2 pointer will increase + every time the DMA finishes to read a #D1 of data units. */ dma_data_type_t type; /*!< The type of data to be transferred. Can be left blank if the target will only be used as destination. */ dma_trigger_slot_mask_t trig; /*!< If the target is a peripheral, a @@ -294,6 +341,7 @@ typedef struct * It also includes control parameters to override the targets' specific ones * if needed. */ + typedef struct { dma_target_t* src; /*!< Target from where the data will be @@ -304,11 +352,21 @@ typedef struct copied. - only valid in address mode */ uint16_t inc_b; /*!< A common increment in case both targets need to use one same increment. */ - uint32_t size_b; /*!< The size of the transfer, in bytes (in - contrast, the size stored in the targets is in data units). */ - dma_data_type_t type; /*!< The data type to use. One is chosen among + uint32_t size_d1_du; /*!< The size of the transfer along D1, in data units */ + uint32_t size_d2_du; /*!< The size of the transfer along D2, in data units */ + dma_dim_t dim; /*!< Sets the dimensionality of the + DMA, either 1D or 2D. */ + uint8_t pad_top_du; /*!< Padding at the top of the 2D transfer. */ + uint8_t pad_bottom_du; /*!< Padding at the bottom of the 2D transfer. */ + uint8_t pad_left_du; /*!< Padding at the left of the 2D transfer. */ + uint8_t pad_right_du; /*!< Padding at the right of the 2D transfer. */ + dma_data_type_t src_type; /*!< Source data type to use. One is chosen among + the targets. */ + dma_data_type_t dst_type; /*!< Destination data type to use. One is chosen among the targets. */ + uint8_t sign_ext; /*!< Whether to sign extend the data. */ dma_trans_mode_t mode; /*!< The copy mode to use. */ + uint8_t dim_inv; /*!< If the D1 and D2 dimensions are inverted, i.e. perform transposition. */ uint32_t win_du; /*!< The amount of data units every which the WINDOW_DONE flag is raised and its corresponding interrupt triggered. It can be set to 0 to disable this functionality. */ @@ -316,6 +374,7 @@ typedef struct is launched. */ dma_config_flags_t flags; /*!< A mask with possible issues aroused from the creation of the transaction. */ + uint8_t channel; /*!< The channel to use. */ } dma_trans_t; /****************************************************************************/ @@ -333,22 +392,62 @@ typedef struct /** * @brief Attends the plic interrupt. */ -void handler_irq_dma( uint32_t id ); +__attribute__((optimize("O0"))) void handler_irq_dma( uint32_t id ); /** * @brief This is a non-weak implementation of the function declared in * fast_intr_ctrl.c */ -void fic_irq_dma(void); +__attribute__((optimize("O0"))) void fic_irq_dma(void); + +/** + * @brief Writes a given value into the specified register. Its operation + * mimics that of bitfield_field32_write(), but does not require the use of + * a field structure, that is not always provided in the _regs.h file. + * @param p_val The value to be written. + * @param p_offset The register's offset from the peripheral's base address + * where the target register is located. + * @param p_mask The variable's mask to only modify its bits inside the whole + * register. + * @param p_sel The selection index (i.e. From which bit inside the register + * the value is to be written). + * @param p_peri The peripheral where the register is located. + */ +/* @ToDo: Consider changing the "mask" parameter for a bitfield definition +(see dma_regs.h) */ +static inline void write_register( uint32_t p_val, + uint32_t p_offset, + uint32_t p_mask, + uint8_t p_sel, + dma* p_dma) +{ + /* + * The index is computed to avoid needing to access the structure + * as a structure. + */ + uint8_t index = p_offset / sizeof(uint32_t); + /* + * An intermediate variable "value" is used to prevent writing twice into + * the register. + */ + uint32_t value = (( uint32_t * ) p_dma ) [ index ]; + value &= ~( p_mask << p_sel ); + value |= (p_val & p_mask) << p_sel; + (( uint32_t * ) p_dma ) [ index ] = value; + +// @ToDo: mmio_region_write32(dma->base_addr, (ptrdiff_t)(DMA_SLOT_REG_OFFSET), (tx_slot_mask << DMA_SLOT_TX_TRIGGER_SLOT_OFFSET) + rx_slot_mask) + +} + /** *@brief Takes all DMA configurations to a state where no accidental * transaction can be performed. * It can be called anytime to reset the DMA control block. - * @param peri Pointer to a register address following the dma structure. By + * @param dma_peri Pointer to a register address following the dma structure. By * default (peri == NULL), the integrated DMA will be used. */ -void dma_init( dma *peri ); +void dma_init( dma *dma_peri); /** * @brief Creates a transaction that can be loaded into the DMA. @@ -379,7 +478,7 @@ dma_config_flags_t dma_validate_transaction( dma_trans_t *p_trans, * the result from inside target structure as an error could have appeared * before the creation of the structure. */ -dma_config_flags_t dma_load_transaction( dma_trans_t* p_trans ); +dma_config_flags_t dma_load_transaction( dma_trans_t* p_trans); /** * @brief Launches the loaded transaction. @@ -391,7 +490,7 @@ dma_config_flags_t dma_load_transaction( dma_trans_t* p_trans ); * loaded is not the desired one). * @retval DMA_CONFIG_OK == 0 otherwise. */ -dma_config_flags_t dma_launch( dma_trans_t* p_trans ); +dma_config_flags_t dma_launch( dma_trans_t* p_trans); /** * @brief Read from the done register of the DMA. Additionally decreases the @@ -400,41 +499,45 @@ dma_config_flags_t dma_launch( dma_trans_t* p_trans ); * running or a new transaction was launched. * Be careful when calling this function if interrupts were chosen as the end * event. + * @param channel The channel to read from. * @return Whether the DMA is working or not. It starts returning 0 as soon as * the dma_launch function has returned. * @retval 0 - DMA is working. * @retval 1 - DMA has finished the transmission. DMA is idle. */ -uint32_t dma_is_ready(void); +uint32_t dma_is_ready(uint8_t channel); /** * @brief Get the number of windows that have already been written. Resets on * the start of each transaction. + * @param channel The channel to read from. * @return The number of windows that have been written from this transaction. */ -uint32_t dma_get_window_count(void); +uint32_t dma_get_window_count(uint8_t channel); /** * @brief Prevent the DMA from relaunching the transaction automatically after * finishing the current one. It does not affect the currently running - * transaction. It has no effect if the DMA is operating in SINGULAR + * transaction. It has no effect if the DMA is operating in SINGLE * transaction mode. + * @param channel The channel to stop. */ -void dma_stop_circular(void); +void dma_stop_circular(uint8_t channel); /** * @brief DMA interrupt handler. * `dma.c` provides a weak definition of this symbol, which can be overridden * at link-time by providing an additional non-weak definition. +* @param channel The channel that triggered the interrupt. */ -void dma_intr_handler_trans_done(void); +void dma_intr_handler_trans_done(uint8_t channel); /** * @brief DMA interrupt handler. * `dma.c` provides a weak definition of this symbol, which can be overridden * at link-time by providing an additional non-weak definition. */ -void dma_intr_handler_window_done(void); +void dma_intr_handler_window_done(uint8_t channel); /** * @brief This weak implementation allows the user to override the threshold @@ -463,4 +566,4 @@ uint8_t dma_window_ratio_warning_threshold(void); /** **/ /** EOF **/ /** **/ -/****************************************************************************/ \ No newline at end of file +/****************************************************************************/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma_regs.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma_regs.h index ce6169c1..c0ef3797 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma_regs.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/dma/dma_regs.h @@ -25,27 +25,57 @@ extern "C" { // Addess data pointer (word aligned) #define DMA_ADDR_PTR_REG_OFFSET 0x8 -// Number of bytes to copy - Once a value is written, the copy starts -#define DMA_SIZE_REG_OFFSET 0xc +// Number of elements to copy from, defined with respect to the first +// dimension - Once a value is written, the copy starts +#define DMA_SIZE_D1_REG_OFFSET 0xc +#define DMA_SIZE_D1_SIZE_MASK 0xffff +#define DMA_SIZE_D1_SIZE_OFFSET 0 +#define DMA_SIZE_D1_SIZE_FIELD \ + ((bitfield_field32_t) { .mask = DMA_SIZE_D1_SIZE_MASK, .index = DMA_SIZE_D1_SIZE_OFFSET }) + +// Number of elements to copy from, defined with respect to the second +// dimension +#define DMA_SIZE_D2_REG_OFFSET 0x10 +#define DMA_SIZE_D2_SIZE_MASK 0xffff +#define DMA_SIZE_D2_SIZE_OFFSET 0 +#define DMA_SIZE_D2_SIZE_FIELD \ + ((bitfield_field32_t) { .mask = DMA_SIZE_D2_SIZE_MASK, .index = DMA_SIZE_D2_SIZE_OFFSET }) // Status bits are set to one if a given event occurred -#define DMA_STATUS_REG_OFFSET 0x10 +#define DMA_STATUS_REG_OFFSET 0x14 #define DMA_STATUS_READY_BIT 0 #define DMA_STATUS_WINDOW_DONE_BIT 1 -// Increment number of src/dst pointer every time a word is copied -#define DMA_PTR_INC_REG_OFFSET 0x14 -#define DMA_PTR_INC_SRC_PTR_INC_MASK 0xff -#define DMA_PTR_INC_SRC_PTR_INC_OFFSET 0 -#define DMA_PTR_INC_SRC_PTR_INC_FIELD \ - ((bitfield_field32_t) { .mask = DMA_PTR_INC_SRC_PTR_INC_MASK, .index = DMA_PTR_INC_SRC_PTR_INC_OFFSET }) -#define DMA_PTR_INC_DST_PTR_INC_MASK 0xff -#define DMA_PTR_INC_DST_PTR_INC_OFFSET 8 -#define DMA_PTR_INC_DST_PTR_INC_FIELD \ - ((bitfield_field32_t) { .mask = DMA_PTR_INC_DST_PTR_INC_MASK, .index = DMA_PTR_INC_DST_PTR_INC_OFFSET }) +// Increment the D1 source pointer every time a word is copied +#define DMA_SRC_PTR_INC_D1_REG_OFFSET 0x18 +#define DMA_SRC_PTR_INC_D1_INC_MASK 0x3f +#define DMA_SRC_PTR_INC_D1_INC_OFFSET 0 +#define DMA_SRC_PTR_INC_D1_INC_FIELD \ + ((bitfield_field32_t) { .mask = DMA_SRC_PTR_INC_D1_INC_MASK, .index = DMA_SRC_PTR_INC_D1_INC_OFFSET }) + +// Increment the D2 source pointer every time a word is copied +#define DMA_SRC_PTR_INC_D2_REG_OFFSET 0x1c +#define DMA_SRC_PTR_INC_D2_INC_MASK 0x7fffff +#define DMA_SRC_PTR_INC_D2_INC_OFFSET 0 +#define DMA_SRC_PTR_INC_D2_INC_FIELD \ + ((bitfield_field32_t) { .mask = DMA_SRC_PTR_INC_D2_INC_MASK, .index = DMA_SRC_PTR_INC_D2_INC_OFFSET }) + +// Increment the D1 destination pointer every time a word is copied +#define DMA_DST_PTR_INC_D1_REG_OFFSET 0x20 +#define DMA_DST_PTR_INC_D1_INC_MASK 0x3f +#define DMA_DST_PTR_INC_D1_INC_OFFSET 0 +#define DMA_DST_PTR_INC_D1_INC_FIELD \ + ((bitfield_field32_t) { .mask = DMA_DST_PTR_INC_D1_INC_MASK, .index = DMA_DST_PTR_INC_D1_INC_OFFSET }) + +// Increment the D2 destination pointer every time a word is copied +#define DMA_DST_PTR_INC_D2_REG_OFFSET 0x24 +#define DMA_DST_PTR_INC_D2_INC_MASK 0x7fffff +#define DMA_DST_PTR_INC_D2_INC_OFFSET 0 +#define DMA_DST_PTR_INC_D2_INC_FIELD \ + ((bitfield_field32_t) { .mask = DMA_DST_PTR_INC_D2_INC_MASK, .index = DMA_DST_PTR_INC_D2_INC_OFFSET }) // The DMA will wait for the signal -#define DMA_SLOT_REG_OFFSET 0x18 +#define DMA_SLOT_REG_OFFSET 0x28 #define DMA_SLOT_RX_TRIGGER_SLOT_MASK 0xffff #define DMA_SLOT_RX_TRIGGER_SLOT_OFFSET 0 #define DMA_SLOT_RX_TRIGGER_SLOT_FIELD \ @@ -55,19 +85,35 @@ extern "C" { #define DMA_SLOT_TX_TRIGGER_SLOT_FIELD \ ((bitfield_field32_t) { .mask = DMA_SLOT_TX_TRIGGER_SLOT_MASK, .index = DMA_SLOT_TX_TRIGGER_SLOT_OFFSET }) -// Width/type of the data to transfer -#define DMA_DATA_TYPE_REG_OFFSET 0x1c -#define DMA_DATA_TYPE_DATA_TYPE_MASK 0x3 -#define DMA_DATA_TYPE_DATA_TYPE_OFFSET 0 -#define DMA_DATA_TYPE_DATA_TYPE_FIELD \ - ((bitfield_field32_t) { .mask = DMA_DATA_TYPE_DATA_TYPE_MASK, .index = DMA_DATA_TYPE_DATA_TYPE_OFFSET }) -#define DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD 0x0 -#define DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_16BIT_WORD 0x1 -#define DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD 0x2 -#define DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD_2 0x3 +// Width/type of the source data to transfer +#define DMA_SRC_DATA_TYPE_REG_OFFSET 0x2c +#define DMA_SRC_DATA_TYPE_DATA_TYPE_MASK 0x3 +#define DMA_SRC_DATA_TYPE_DATA_TYPE_OFFSET 0 +#define DMA_SRC_DATA_TYPE_DATA_TYPE_FIELD \ + ((bitfield_field32_t) { .mask = DMA_SRC_DATA_TYPE_DATA_TYPE_MASK, .index = DMA_SRC_DATA_TYPE_DATA_TYPE_OFFSET }) +#define DMA_SRC_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD 0x0 +#define DMA_SRC_DATA_TYPE_DATA_TYPE_VALUE_DMA_16BIT_WORD 0x1 +#define DMA_SRC_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD 0x2 +#define DMA_SRC_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD_2 0x3 + +// Width/type of the destination data to transfer +#define DMA_DST_DATA_TYPE_REG_OFFSET 0x30 +#define DMA_DST_DATA_TYPE_DATA_TYPE_MASK 0x3 +#define DMA_DST_DATA_TYPE_DATA_TYPE_OFFSET 0 +#define DMA_DST_DATA_TYPE_DATA_TYPE_FIELD \ + ((bitfield_field32_t) { .mask = DMA_DST_DATA_TYPE_DATA_TYPE_MASK, .index = DMA_DST_DATA_TYPE_DATA_TYPE_OFFSET }) +#define DMA_DST_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD 0x0 +#define DMA_DST_DATA_TYPE_DATA_TYPE_VALUE_DMA_16BIT_WORD 0x1 +#define DMA_DST_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD 0x2 +#define DMA_DST_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD_2 0x3 + +// Is the data to be sign extended? (Checked only if the dst data type is +// wider than the src data type) +#define DMA_SIGN_EXT_REG_OFFSET 0x34 +#define DMA_SIGN_EXT_SIGNED_BIT 0 // Set the operational mode of the DMA -#define DMA_MODE_REG_OFFSET 0x20 +#define DMA_MODE_REG_OFFSET 0x38 #define DMA_MODE_MODE_MASK 0x3 #define DMA_MODE_MODE_OFFSET 0 #define DMA_MODE_MODE_FIELD \ @@ -76,17 +122,69 @@ extern "C" { #define DMA_MODE_MODE_VALUE_CIRCULAR_MODE 0x1 #define DMA_MODE_MODE_VALUE_ADDRESS_MODE 0x2 +// Set the dimensionality of the DMA +#define DMA_DIM_CONFIG_REG_OFFSET 0x3c +#define DMA_DIM_CONFIG_DMA_DIM_BIT 0 + +// DMA dimensionality inversion selector +#define DMA_DIM_INV_REG_OFFSET 0x40 +#define DMA_DIM_INV_SEL_BIT 0 + +// Set the top padding +#define DMA_PAD_TOP_REG_OFFSET 0x44 +#define DMA_PAD_TOP_PAD_MASK 0x3f +#define DMA_PAD_TOP_PAD_OFFSET 0 +#define DMA_PAD_TOP_PAD_FIELD \ + ((bitfield_field32_t) { .mask = DMA_PAD_TOP_PAD_MASK, .index = DMA_PAD_TOP_PAD_OFFSET }) + +// Set the bottom padding +#define DMA_PAD_BOTTOM_REG_OFFSET 0x48 +#define DMA_PAD_BOTTOM_PAD_MASK 0x3f +#define DMA_PAD_BOTTOM_PAD_OFFSET 0 +#define DMA_PAD_BOTTOM_PAD_FIELD \ + ((bitfield_field32_t) { .mask = DMA_PAD_BOTTOM_PAD_MASK, .index = DMA_PAD_BOTTOM_PAD_OFFSET }) + +// Set the right padding +#define DMA_PAD_RIGHT_REG_OFFSET 0x4c +#define DMA_PAD_RIGHT_PAD_MASK 0x3f +#define DMA_PAD_RIGHT_PAD_OFFSET 0 +#define DMA_PAD_RIGHT_PAD_FIELD \ + ((bitfield_field32_t) { .mask = DMA_PAD_RIGHT_PAD_MASK, .index = DMA_PAD_RIGHT_PAD_OFFSET }) + +// Set the left padding +#define DMA_PAD_LEFT_REG_OFFSET 0x50 +#define DMA_PAD_LEFT_PAD_MASK 0x3f +#define DMA_PAD_LEFT_PAD_OFFSET 0 +#define DMA_PAD_LEFT_PAD_FIELD \ + ((bitfield_field32_t) { .mask = DMA_PAD_LEFT_PAD_MASK, .index = DMA_PAD_LEFT_PAD_OFFSET }) + // Will trigger a every "WINDOW_SIZE" writes -#define DMA_WINDOW_SIZE_REG_OFFSET 0x24 +#define DMA_WINDOW_SIZE_REG_OFFSET 0x54 +#define DMA_WINDOW_SIZE_WINDOW_SIZE_MASK 0x1fff +#define DMA_WINDOW_SIZE_WINDOW_SIZE_OFFSET 0 +#define DMA_WINDOW_SIZE_WINDOW_SIZE_FIELD \ + ((bitfield_field32_t) { .mask = DMA_WINDOW_SIZE_WINDOW_SIZE_MASK, .index = DMA_WINDOW_SIZE_WINDOW_SIZE_OFFSET }) // Number of times the end of the window was reached since the beginning. -#define DMA_WINDOW_COUNT_REG_OFFSET 0x28 +#define DMA_WINDOW_COUNT_REG_OFFSET 0x58 +#define DMA_WINDOW_COUNT_WINDOW_COUNT_MASK 0xff +#define DMA_WINDOW_COUNT_WINDOW_COUNT_OFFSET 0 +#define DMA_WINDOW_COUNT_WINDOW_COUNT_FIELD \ + ((bitfield_field32_t) { .mask = DMA_WINDOW_COUNT_WINDOW_COUNT_MASK, .index = DMA_WINDOW_COUNT_WINDOW_COUNT_OFFSET }) // Interrupt Enable Register -#define DMA_INTERRUPT_EN_REG_OFFSET 0x2c +#define DMA_INTERRUPT_EN_REG_OFFSET 0x5c #define DMA_INTERRUPT_EN_TRANSACTION_DONE_BIT 0 #define DMA_INTERRUPT_EN_WINDOW_DONE_BIT 1 +// Interrupt Flag Register for transactions +#define DMA_TRANSACTION_IFR_REG_OFFSET 0x60 +#define DMA_TRANSACTION_IFR_FLAG_BIT 0 + +// Interrupt Flag Register for windows +#define DMA_WINDOW_IFR_REG_OFFSET 0x64 +#define DMA_WINDOW_IFR_FLAG_BIT 0 + #ifdef __cplusplus } // extern "C" #endif diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.c index 27c000a0..0493864e 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.c @@ -29,6 +29,9 @@ /* MODULES USED */ /** **/ /****************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif #include "fast_intr_ctrl.h" #include "core_v_mini_mcu.h" @@ -418,6 +421,9 @@ void handler_irq_fast_gpio_7(void) // call the weak fic handler fic_irq_gpio_7(); } +#ifdef __cplusplus +} +#endif /****************************************************************************/ /** **/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.h index 87997551..46c0ada2 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.h @@ -32,7 +32,9 @@ /** MODULES USED **/ /** **/ /****************************************************************************/ - +#ifdef __cplusplus +extern "C" { +#endif #include #include #include "mmio.h" @@ -242,7 +244,9 @@ void fic_irq_gpio_7(void); /** INLINE FUNCTIONS **/ /** **/ /****************************************************************************/ - +#ifdef __cplusplus +} +#endif /****************************************************************************/ /** **/ /** EOF **/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/gpio/gpio.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/gpio/gpio.c index 3e733ecd..7f28db54 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/gpio/gpio.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/gpio/gpio.c @@ -23,7 +23,9 @@ * @version 1 * @brief GPIO driver */ - +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus /****************************************************************************/ /** **/ /* MODULES USED */ @@ -150,7 +152,7 @@ gpio_result_t gpio_assign_irq_handler( uint32_t intr_id, { if( intr_id >= GPIO_INTR_START && intr_id <= GPIO_INTR_END ) { - gpio_handlers[ intr_id - GPIO_INTR_START ] = handler; + gpio_handlers[ intr_id - GPIO_INTR_START ] = (void (*)(void))handler; return GpioOk; } return GpioError; @@ -160,7 +162,7 @@ void gpio_reset_handlers_list( ) { for( uint8_t i = 0; i < GPIO_INTR_QTY; i++ ) { - gpio_handlers[ i ] = &gpio_handler_irq_dummy; + gpio_handlers[ i ] = (void (*)(void))&gpio_handler_irq_dummy; } } @@ -572,4 +574,9 @@ __attribute__((optimize("O0"))) static void gpio_handler_irq_dummy( uint32_t dum /** **/ /* EOF */ /** **/ -/****************************************************************************/ \ No newline at end of file +/****************************************************************************/ + + +#ifdef __cplusplus +} +#endif // __cplusplus \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo.h new file mode 100644 index 00000000..03ec588a --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo.h @@ -0,0 +1,56 @@ +/* + ******************* +******************************* C SOURCE FILE ******************************* +** ******************* ** +** ** +** project : x-heep ** +** filename : i2s.h ** +** date : 28/10/2023 ** +** ** +***************************************************************************** +** ** +** Copyright (c) EPFL contributors. ** +** All rights reserved. ** +** ** +***************************************************************************** + +*/ + +/***************************************************************************/ +/***************************************************************************/ + +/** +* @file iffifo.h +* @date 28/10/2023 +* @author Pierre Guillod +* @brief HAL of the IFFIFO peripheral +* +*/ + +#ifndef _DRIVERS_IFFIFO_H_ +#define _DRIVERS_IFFIFO_H_ + +/****************************************************************************/ +/** **/ +/* MODULES USED */ +/** **/ +/****************************************************************************/ + + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) void handler_irq_iffifo(uint32_t id); + +#ifdef __cplusplus +} +#endif + +#endif // _DRIVERS_IFFIFO_H_ + +/****************************************************************************/ +/** **/ +/* EOF */ +/** **/ +/****************************************************************************/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo_regs.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo_regs.h new file mode 100644 index 00000000..6acd3aa8 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/iffifo/iffifo_regs.h @@ -0,0 +1,47 @@ +// Generated register defines for iffifo + +// Copyright information found in source file: +// Copyright EPFL contributors. + +// Licensing information found in source file: +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef _IFFIFO_REG_DEFS_ +#define _IFFIFO_REG_DEFS_ + +#ifdef __cplusplus +extern "C" { +#endif +// Register width +#define IFFIFO_PARAM_REG_WIDTH 32 + +// Data coming from the FIFO (Fifo Output/Software RX) +#define IFFIFO_FIFO_OUT_REG_OFFSET 0x0 + +// Data sent to the FIFO (Fifo Input/Software TX) +#define IFFIFO_FIFO_IN_REG_OFFSET 0x4 + +// General purpose status register +#define IFFIFO_STATUS_REG_OFFSET 0x8 +#define IFFIFO_STATUS_EMPTY_BIT 0 +#define IFFIFO_STATUS_AVAILABLE_BIT 1 +#define IFFIFO_STATUS_REACHED_BIT 2 +#define IFFIFO_STATUS_FULL_BIT 3 + +// Current number of occupied FIFO slots +#define IFFIFO_OCCUPANCY_REG_OFFSET 0xc + +// FIFO occupancy at which the STATUS:REACHED bit is asserted +#define IFFIFO_WATERMARK_REG_OFFSET 0x10 + +// Write any value to assert an interrupt. Write 0 or 1 to disable or enable +// an interrupt. +#define IFFIFO_INTERRUPTS_REG_OFFSET 0x14 +#define IFFIFO_INTERRUPTS_REACHED_BIT 0 + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _IFFIFO_REG_DEFS_ +// End generated register defines for iffifo \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/im2col_spc/im2col.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/im2col_spc/im2col.c new file mode 100644 index 00000000..af7e20f4 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/im2col_spc/im2col.c @@ -0,0 +1,234 @@ +/* + Copyright EPFL contributors. + Licensed under the Apache License, Version 2.0, see LICENSE for details. + SPDX-License-Identifier: Apache-2.0 + + Author: Tommaso Terzano + + + Info: This simple HAL is used to load the im2col SPC and to run it. +*/ + +#include "im2col.h" + +uint32_t im2col_spc_base_addr; + +void handler_irq_im2col_spc( void ) +{ + /* Read the IFR to lower the interrupt flag */ + * (volatile uint32_t * )(im2col_spc_base_addr + IM2COL_SPC_SPC_IFR_REG_OFFSET); + return; +} + +void im2col_spc_init(uint32_t im2col_spc_base_addr_i) +{ + if (im2col_spc_base_addr_i == NULL) + { + im2col_spc_base_addr = EXT_PERIPHERAL_START_ADDRESS + 0x4000; + } else { + im2col_spc_base_addr = im2col_spc_base_addr_i; + } +} + +/* Simple function to extract the channel from the channel mask */ +int get_channel_number(uint32_t mask) { + int channel = 0; + + // Check the position of the first set bit + while (mask > 0) { + channel++; + if (mask & 1) { // If the least significant bit is set + return channel - 1; + } + mask >>= 1; // Right shift the mask to check the next bit + } + + // If no bit is set, return -1 indicating no valid channel + return -1; +} + +int im2col_spc_run(im2col_trans_t trans){ + + /* Initializing PLIC */ + if(plic_Init()) + { + return EXIT_FAILURE; + }; + + if(plic_irq_set_priority(EXT_INTR_2, 1)) + { + return EXIT_FAILURE; + }; + + if(plic_irq_set_enabled(EXT_INTR_2, kPlicToggleEnabled)) + { + return EXIT_FAILURE; + }; + + plic_assign_external_irq_handler(EXT_INTR_2, &handler_irq_im2col_spc); + + /* Enable global interrupt for machine-level interrupts */ + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + + /* Set mie.MEIE bit to one to enable machine-level external interrupts */ + const uint32_t mask = 1 << 11; + CSR_SET_BITS(CSR_REG_MIE, mask); + + dma_init(NULL); + + /* Write the DMA channel mask that the SPC has access to */ + write_register( trans.ch_mask, + IM2COL_SPC_SPC_CH_MASK_REG_OFFSET, + 0xffffffff, + 0, + im2col_spc_base_addr ); + + /* Write the offset of the DMA channel the SPC has access to */ + write_register( get_channel_number(trans.ch_mask) * DMA_CH_SIZE + DMA_START_ADDRESS, + IM2COL_SPC_SPC_CH_OFFSET_REG_OFFSET, + 0xffffffff, + 0, + im2col_spc_base_addr ); + + /* Write the source */ + write_register( trans.src, + IM2COL_SPC_SRC_PTR_REG_OFFSET, + 0xffffffff, + 0, + im2col_spc_base_addr ); + + /* Write the destination */ + write_register( trans.dst, + IM2COL_SPC_DST_PTR_REG_OFFSET, + 0xffffffff, + 0, + im2col_spc_base_addr ); + + /* Write the datatype */ + write_register( trans.datatype, + IM2COL_SPC_DATA_TYPE_REG_OFFSET, + IM2COL_SPC_DATA_TYPE_DATA_TYPE_MASK, + IM2COL_SPC_DATA_TYPE_DATA_TYPE_OFFSET, + im2col_spc_base_addr ); + + /* Write the filter dimensions */ + write_register( trans.filter_width, + IM2COL_SPC_FW_REG_OFFSET, + IM2COL_SPC_FW_SIZE_MASK, + IM2COL_SPC_FW_SIZE_OFFSET, + im2col_spc_base_addr ); + + write_register( trans.filter_height, + IM2COL_SPC_FH_REG_OFFSET, + IM2COL_SPC_FH_SIZE_MASK, + IM2COL_SPC_FH_SIZE_OFFSET, + im2col_spc_base_addr ); + + /* Write the image dimensions */ + write_register( trans.im_width, + IM2COL_SPC_IW_REG_OFFSET, + 0xffffffff, + 0, + im2col_spc_base_addr ); + + write_register( trans.im_height, + IM2COL_SPC_IH_REG_OFFSET, + 0xffffffff, + 0, + im2col_spc_base_addr ); + + /* Write the CH_COL */ + write_register( trans.num_channels_col, + IM2COL_SPC_CH_COL_REG_OFFSET, + IM2COL_SPC_CH_COL_NUM_MASK, + IM2COL_SPC_CH_COL_NUM_OFFSET, + im2col_spc_base_addr ); + + /* Write n_patches */ + write_register( trans.n_patches_w, + IM2COL_SPC_N_PATCHES_W_REG_OFFSET, + IM2COL_SPC_N_PATCHES_W_NUM_MASK, + IM2COL_SPC_N_PATCHES_W_NUM_OFFSET, + im2col_spc_base_addr ); + + write_register( trans.n_patches_h, + IM2COL_SPC_N_PATCHES_H_REG_OFFSET, + IM2COL_SPC_N_PATCHES_H_NUM_MASK, + IM2COL_SPC_N_PATCHES_H_NUM_OFFSET, + im2col_spc_base_addr ); + + /* Write the padding */ + write_register( trans.left_pad, + IM2COL_SPC_PAD_LEFT_REG_OFFSET, + IM2COL_SPC_PAD_LEFT_PAD_MASK, + IM2COL_SPC_PAD_LEFT_PAD_OFFSET, + im2col_spc_base_addr ); + + write_register( trans.right_pad, + IM2COL_SPC_PAD_RIGHT_REG_OFFSET, + IM2COL_SPC_PAD_RIGHT_PAD_MASK, + IM2COL_SPC_PAD_RIGHT_PAD_OFFSET, + im2col_spc_base_addr ); + + write_register( trans.top_pad, + IM2COL_SPC_PAD_TOP_REG_OFFSET, + IM2COL_SPC_PAD_TOP_PAD_MASK, + IM2COL_SPC_PAD_TOP_PAD_OFFSET, + im2col_spc_base_addr ); + + write_register( trans.bottom_pad, + IM2COL_SPC_PAD_BOTTOM_REG_OFFSET, + IM2COL_SPC_PAD_BOTTOM_PAD_MASK, + IM2COL_SPC_PAD_BOTTOM_PAD_OFFSET, + im2col_spc_base_addr ); + + /* + * Write the strides. With respect to test_2 these are the application-point-of-view + * strides, so they are the same as STRIDE_D1 and STRIDE_D2. + */ + write_register( (int) log2(trans.stride_d1), + IM2COL_SPC_LOG_STRIDES_D1_REG_OFFSET, + IM2COL_SPC_LOG_STRIDES_D1_SIZE_MASK, + IM2COL_SPC_LOG_STRIDES_D1_SIZE_OFFSET, + im2col_spc_base_addr ); + + write_register( (int) log2(trans.stride_d2), + IM2COL_SPC_LOG_STRIDES_D2_REG_OFFSET, + IM2COL_SPC_LOG_STRIDES_D2_SIZE_MASK, + IM2COL_SPC_LOG_STRIDES_D2_SIZE_OFFSET, + im2col_spc_base_addr ); + + /* Write the batch size */ + write_register( trans.batch, + IM2COL_SPC_BATCH_REG_OFFSET, + IM2COL_SPC_BATCH_SIZE_MASK, + IM2COL_SPC_BATCH_SIZE_OFFSET, + im2col_spc_base_addr ); + + /* Write the adapted pad regions */ + write_register( trans.adpt_pad_right, + IM2COL_SPC_ADPT_PAD_RIGHT_REG_OFFSET, + 0xffffffff, + 0, + im2col_spc_base_addr ); + + write_register( trans.adpt_pad_bottom, + IM2COL_SPC_ADPT_PAD_BOTTOM_REG_OFFSET, + 0xffffffff, + 0, + im2col_spc_base_addr ); + + /* Enable the interrupt logic */ + write_register( 0x1, + IM2COL_SPC_INTERRUPT_EN_REG_OFFSET, + 0x1, + IM2COL_SPC_INTERRUPT_EN_EN_BIT, + im2col_spc_base_addr ); + + /* Write the number of channels to start the process */ + write_register( trans.num_channels, + IM2COL_SPC_NUM_CH_REG_OFFSET, + IM2COL_SPC_NUM_CH_NUM_MASK, + IM2COL_SPC_NUM_CH_NUM_OFFSET, + im2col_spc_base_addr ); +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/im2col_spc/im2col.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/im2col_spc/im2col.h new file mode 100644 index 00000000..eaefc0af --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/im2col_spc/im2col.h @@ -0,0 +1,60 @@ +/* + Copyright EPFL contributors. + Licensed under the Apache License, Version 2.0, see LICENSE for details. + SPDX-License-Identifier: Apache-2.0 + + Author: Tommaso Terzano + + + Info: This simple HAL is used to load the im2col SPC and to run it. Remember, only one DMA channel + at a time can be used! +*/ + +#ifndef _IM2COL_SPC_ +#define _IM2COL_SPC_ + +#include +#include +#include +#include "dma.h" +#include "im2col_spc_regs.h" +#include "core_v_mini_mcu.h" +#include "x-heep.h" +#include "rv_plic.h" +#include "csr.h" +#include +#include "mmio.h" +#include "hart.h" +#include "fast_intr_ctrl.h" + +/* Transaction structure */ +typedef struct +{ + uint32_t* src; /*!< Target from where the data will be copied. */ + uint32_t* dst; /*!< Target to where the data will be copied. */ + uint32_t ch_mask; /*!< Mask of the channels to be used. */ + uint32_t im_width; /*!< Width of the input image. */ + uint32_t im_height; /*!< Height of the input image. */ + uint32_t filter_width; /*!< Width of the filter. */ + uint32_t filter_height; /*!< Height of the filter. */ + uint32_t num_channels; /*!< Number of channels. */ + uint32_t num_channels_col; /*!< Number of channels to be processed. */ + uint32_t stride_d1; /*!< Stride in the first dimension. */ + uint32_t stride_d2; /*!< Stride in the second dimension. */ + uint32_t batch; /*!< Number of batches. */ + uint32_t n_patches_w; /*!< Number of patches in the width. */ + uint32_t n_patches_h; /*!< Number of patches in the height. */ + uint32_t left_pad; /*!< Padding on the left. */ + uint32_t right_pad; /*!< Padding on the right. */ + uint32_t top_pad; /*!< Padding on the top. */ + uint32_t bottom_pad; /*!< Padding on the bottom. */ + uint32_t adpt_pad_right; /*!< Adaptive padding on the right. */ + uint32_t adpt_pad_bottom; /*!< Adaptive padding on the bottom. */ + uint32_t datatype; /*!< Data type of the input. */ +} im2col_trans_t; + +int im2col_spc_run(im2col_trans_t trans); +void im2col_spc_init(uint32_t im2col_spc_base_addr_i); +__attribute__((weak, optimize("00"))) void handler_irq_im2col_spc(void); + +#endif \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/im2col_spc/im2col_spc_regs.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/im2col_spc/im2col_spc_regs.h new file mode 100644 index 00000000..ac34172a --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/im2col_spc/im2col_spc_regs.h @@ -0,0 +1,188 @@ +// Generated register defines for im2col_spc + +// Copyright information found in source file: +// Copyright EPFL contributors. + +// Licensing information found in source file: +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef _IM2COL_SPC_REG_DEFS_ +#define _IM2COL_SPC_REG_DEFS_ + +#ifdef __cplusplus +extern "C" { +#endif +// Register width +#define IM2COL_SPC_PARAM_REG_WIDTH 32 + +// Input data pointer (word aligned) +#define IM2COL_SPC_SRC_PTR_REG_OFFSET 0x0 + +// Output data pointer (word aligned) +#define IM2COL_SPC_DST_PTR_REG_OFFSET 0x4 + +// Image width +#define IM2COL_SPC_IW_REG_OFFSET 0x8 +#define IM2COL_SPC_IW_SIZE_MASK 0xffff +#define IM2COL_SPC_IW_SIZE_OFFSET 0 +#define IM2COL_SPC_IW_SIZE_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_IW_SIZE_MASK, .index = IM2COL_SPC_IW_SIZE_OFFSET }) + +// Image heigth +#define IM2COL_SPC_IH_REG_OFFSET 0xc +#define IM2COL_SPC_IH_SIZE_MASK 0xffff +#define IM2COL_SPC_IH_SIZE_OFFSET 0 +#define IM2COL_SPC_IH_SIZE_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_IH_SIZE_MASK, .index = IM2COL_SPC_IH_SIZE_OFFSET }) + +// Filter width +#define IM2COL_SPC_FW_REG_OFFSET 0x10 +#define IM2COL_SPC_FW_SIZE_MASK 0xff +#define IM2COL_SPC_FW_SIZE_OFFSET 0 +#define IM2COL_SPC_FW_SIZE_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_FW_SIZE_MASK, .index = IM2COL_SPC_FW_SIZE_OFFSET }) + +// Filter heigth +#define IM2COL_SPC_FH_REG_OFFSET 0x14 +#define IM2COL_SPC_FH_SIZE_MASK 0xff +#define IM2COL_SPC_FH_SIZE_OFFSET 0 +#define IM2COL_SPC_FH_SIZE_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_FH_SIZE_MASK, .index = IM2COL_SPC_FH_SIZE_OFFSET }) + +// Batch number +#define IM2COL_SPC_BATCH_REG_OFFSET 0x18 +#define IM2COL_SPC_BATCH_SIZE_MASK 0xff +#define IM2COL_SPC_BATCH_SIZE_OFFSET 0 +#define IM2COL_SPC_BATCH_SIZE_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_BATCH_SIZE_MASK, .index = IM2COL_SPC_BATCH_SIZE_OFFSET }) + +// Number of channels. When written, the im2col will start executing +#define IM2COL_SPC_NUM_CH_REG_OFFSET 0x1c +#define IM2COL_SPC_NUM_CH_NUM_MASK 0xff +#define IM2COL_SPC_NUM_CH_NUM_OFFSET 0 +#define IM2COL_SPC_NUM_CH_NUM_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_NUM_CH_NUM_MASK, .index = IM2COL_SPC_NUM_CH_NUM_OFFSET }) + +// Number of iterations to perform +#define IM2COL_SPC_CH_COL_REG_OFFSET 0x20 +#define IM2COL_SPC_CH_COL_NUM_MASK 0xffff +#define IM2COL_SPC_CH_COL_NUM_OFFSET 0 +#define IM2COL_SPC_CH_COL_NUM_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_CH_COL_NUM_MASK, .index = IM2COL_SPC_CH_COL_NUM_OFFSET }) + +// Number of patches along W +#define IM2COL_SPC_N_PATCHES_W_REG_OFFSET 0x24 +#define IM2COL_SPC_N_PATCHES_W_NUM_MASK 0xffff +#define IM2COL_SPC_N_PATCHES_W_NUM_OFFSET 0 +#define IM2COL_SPC_N_PATCHES_W_NUM_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_N_PATCHES_W_NUM_MASK, .index = IM2COL_SPC_N_PATCHES_W_NUM_OFFSET }) + +// Number of patches along H +#define IM2COL_SPC_N_PATCHES_H_REG_OFFSET 0x28 +#define IM2COL_SPC_N_PATCHES_H_NUM_MASK 0xffff +#define IM2COL_SPC_N_PATCHES_H_NUM_OFFSET 0 +#define IM2COL_SPC_N_PATCHES_H_NUM_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_N_PATCHES_H_NUM_MASK, .index = IM2COL_SPC_N_PATCHES_H_NUM_OFFSET }) + +// Adapted right padded region +#define IM2COL_SPC_ADPT_PAD_RIGHT_REG_OFFSET 0x2c +#define IM2COL_SPC_ADPT_PAD_RIGHT_SIZE_MASK 0xff +#define IM2COL_SPC_ADPT_PAD_RIGHT_SIZE_OFFSET 0 +#define IM2COL_SPC_ADPT_PAD_RIGHT_SIZE_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_ADPT_PAD_RIGHT_SIZE_MASK, .index = IM2COL_SPC_ADPT_PAD_RIGHT_SIZE_OFFSET }) + +// Adapted bottom padded region +#define IM2COL_SPC_ADPT_PAD_BOTTOM_REG_OFFSET 0x30 +#define IM2COL_SPC_ADPT_PAD_BOTTOM_SIZE_MASK 0xff +#define IM2COL_SPC_ADPT_PAD_BOTTOM_SIZE_OFFSET 0 +#define IM2COL_SPC_ADPT_PAD_BOTTOM_SIZE_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_ADPT_PAD_BOTTOM_SIZE_MASK, .index = IM2COL_SPC_ADPT_PAD_BOTTOM_SIZE_OFFSET }) + +// Logarithmic number of strides along D1, set to 1 for no stride +#define IM2COL_SPC_LOG_STRIDES_D1_REG_OFFSET 0x34 +#define IM2COL_SPC_LOG_STRIDES_D1_SIZE_MASK 0xf +#define IM2COL_SPC_LOG_STRIDES_D1_SIZE_OFFSET 0 +#define IM2COL_SPC_LOG_STRIDES_D1_SIZE_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_LOG_STRIDES_D1_SIZE_MASK, .index = IM2COL_SPC_LOG_STRIDES_D1_SIZE_OFFSET }) + +// Logarithmic number of strides along D2, set to 1 for no stride +#define IM2COL_SPC_LOG_STRIDES_D2_REG_OFFSET 0x38 +#define IM2COL_SPC_LOG_STRIDES_D2_SIZE_MASK 0xf +#define IM2COL_SPC_LOG_STRIDES_D2_SIZE_OFFSET 0 +#define IM2COL_SPC_LOG_STRIDES_D2_SIZE_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_LOG_STRIDES_D2_SIZE_MASK, .index = IM2COL_SPC_LOG_STRIDES_D2_SIZE_OFFSET }) + +// Status bit is set to one when the im2col SPC is ready +#define IM2COL_SPC_STATUS_REG_OFFSET 0x3c +#define IM2COL_SPC_STATUS_READY_BIT 0 + +// The DMA will wait for the signal +#define IM2COL_SPC_SLOT_REG_OFFSET 0x40 +#define IM2COL_SPC_SLOT_RX_TRIGGER_SLOT_MASK 0xffff +#define IM2COL_SPC_SLOT_RX_TRIGGER_SLOT_OFFSET 0 +#define IM2COL_SPC_SLOT_RX_TRIGGER_SLOT_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_SLOT_RX_TRIGGER_SLOT_MASK, .index = IM2COL_SPC_SLOT_RX_TRIGGER_SLOT_OFFSET }) +#define IM2COL_SPC_SLOT_TX_TRIGGER_SLOT_MASK 0xffff +#define IM2COL_SPC_SLOT_TX_TRIGGER_SLOT_OFFSET 16 +#define IM2COL_SPC_SLOT_TX_TRIGGER_SLOT_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_SLOT_TX_TRIGGER_SLOT_MASK, .index = IM2COL_SPC_SLOT_TX_TRIGGER_SLOT_OFFSET }) + +// Width/type of the data to transfer +#define IM2COL_SPC_DATA_TYPE_REG_OFFSET 0x44 +#define IM2COL_SPC_DATA_TYPE_DATA_TYPE_MASK 0x3 +#define IM2COL_SPC_DATA_TYPE_DATA_TYPE_OFFSET 0 +#define IM2COL_SPC_DATA_TYPE_DATA_TYPE_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_DATA_TYPE_DATA_TYPE_MASK, .index = IM2COL_SPC_DATA_TYPE_DATA_TYPE_OFFSET }) +#define IM2COL_SPC_DATA_TYPE_DATA_TYPE_VALUE_DMA_32BIT_WORD 0x0 +#define IM2COL_SPC_DATA_TYPE_DATA_TYPE_VALUE_DMA_16BIT_WORD 0x1 +#define IM2COL_SPC_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD 0x2 +#define IM2COL_SPC_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD_2 0x3 + +// Set the top padding +#define IM2COL_SPC_PAD_TOP_REG_OFFSET 0x48 +#define IM2COL_SPC_PAD_TOP_PAD_MASK 0x3f +#define IM2COL_SPC_PAD_TOP_PAD_OFFSET 0 +#define IM2COL_SPC_PAD_TOP_PAD_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_PAD_TOP_PAD_MASK, .index = IM2COL_SPC_PAD_TOP_PAD_OFFSET }) + +// Set the bottom padding +#define IM2COL_SPC_PAD_BOTTOM_REG_OFFSET 0x4c +#define IM2COL_SPC_PAD_BOTTOM_PAD_MASK 0x3f +#define IM2COL_SPC_PAD_BOTTOM_PAD_OFFSET 0 +#define IM2COL_SPC_PAD_BOTTOM_PAD_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_PAD_BOTTOM_PAD_MASK, .index = IM2COL_SPC_PAD_BOTTOM_PAD_OFFSET }) + +// Set the right padding +#define IM2COL_SPC_PAD_RIGHT_REG_OFFSET 0x50 +#define IM2COL_SPC_PAD_RIGHT_PAD_MASK 0x3f +#define IM2COL_SPC_PAD_RIGHT_PAD_OFFSET 0 +#define IM2COL_SPC_PAD_RIGHT_PAD_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_PAD_RIGHT_PAD_MASK, .index = IM2COL_SPC_PAD_RIGHT_PAD_OFFSET }) + +// Set the left padding +#define IM2COL_SPC_PAD_LEFT_REG_OFFSET 0x54 +#define IM2COL_SPC_PAD_LEFT_PAD_MASK 0x3f +#define IM2COL_SPC_PAD_LEFT_PAD_OFFSET 0 +#define IM2COL_SPC_PAD_LEFT_PAD_FIELD \ + ((bitfield_field32_t) { .mask = IM2COL_SPC_PAD_LEFT_PAD_MASK, .index = IM2COL_SPC_PAD_LEFT_PAD_OFFSET }) + +// Interrupt Enable Register +#define IM2COL_SPC_INTERRUPT_EN_REG_OFFSET 0x58 +#define IM2COL_SPC_INTERRUPT_EN_EN_BIT 0 + +// Interrupt Flag Register for the SPC operation +#define IM2COL_SPC_SPC_IFR_REG_OFFSET 0x5c +#define IM2COL_SPC_SPC_IFR_FLAG_BIT 0 + +// Mask that defines which DMA channel the SPC can access +#define IM2COL_SPC_SPC_CH_MASK_REG_OFFSET 0x60 + +// Offset of the DMA channel the SPC can access +#define IM2COL_SPC_SPC_CH_OFFSET_REG_OFFSET 0x64 + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _IM2COL_SPC_REG_DEFS_ +// End generated register defines for im2col_spc \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/data/power_manager.h.tpl b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/data/power_manager.h.tpl index 7f0d939e..52215d27 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/data/power_manager.h.tpl +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/data/power_manager.h.tpl @@ -105,16 +105,16 @@ typedef struct power_manager_ram_map_t { uint32_t monitor_power_gate; } power_manager_ram_map_t; -static power_manager_ram_map_t power_manager_ram_map[${ram_numbanks}] = { -% for bank in range(ram_numbanks): +static power_manager_ram_map_t power_manager_ram_map[${xheep.ram_numbanks()}] = { +% for bank in xheep.iter_ram_banks(): (power_manager_ram_map_t) { - .clk_gate = POWER_MANAGER_RAM_${bank}_CLK_GATE_REG_OFFSET, - .power_gate_ack = POWER_MANAGER_POWER_GATE_RAM_BLOCK_${bank}_ACK_REG_OFFSET, - .switch_off = POWER_MANAGER_RAM_${bank}_SWITCH_REG_OFFSET, - .wait_ack_switch = POWER_MANAGER_RAM_${bank}_WAIT_ACK_SWITCH_ON_REG_OFFSET, - .iso = POWER_MANAGER_RAM_${bank}_ISO_REG_OFFSET, - .retentive = POWER_MANAGER_RAM_${bank}_RETENTIVE_REG_OFFSET, - .monitor_power_gate = POWER_MANAGER_MONITOR_POWER_GATE_RAM_BLOCK_${bank}_REG_OFFSET + .clk_gate = POWER_MANAGER_RAM_${bank.name()}_CLK_GATE_REG_OFFSET, + .power_gate_ack = POWER_MANAGER_POWER_GATE_RAM_BLOCK_${bank.name()}_ACK_REG_OFFSET, + .switch_off = POWER_MANAGER_RAM_${bank.name()}_SWITCH_REG_OFFSET, + .wait_ack_switch = POWER_MANAGER_RAM_${bank.name()}_WAIT_ACK_SWITCH_ON_REG_OFFSET, + .iso = POWER_MANAGER_RAM_${bank.name()}_ISO_REG_OFFSET, + .retentive = POWER_MANAGER_RAM_${bank.name()}_RETENTIVE_REG_OFFSET, + .monitor_power_gate = POWER_MANAGER_MONITOR_POWER_GATE_RAM_BLOCK_${bank.name()}_REG_OFFSET }, % endfor }; diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/power_manager.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/power_manager.c index 4a9c37a8..06677121 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/power_manager.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/power_manager.c @@ -15,174 +15,7 @@ #include "x-heep.h" - -void __attribute__ ((noinline)) power_gate_core_asm() -{ - asm volatile ( - - // write POWER_GATE_CORE[0] = 1 - "lui a0, %[base_address_20bit]\n" - "li a1, 1\n" - "sw a1, %[power_manager_power_gate_core_reg_offset](a0)\n" - - // write WAKEUP_STATE[0] = 1 - "sw a1, %[power_manager_wakeup_state_reg_offset](a0)\n" : : \ - \ - [base_address_20bit] "i" (POWER_MANAGER_START_ADDRESS >> 12), \ - [power_manager_power_gate_core_reg_offset] "i" (POWER_MANAGER_POWER_GATE_CORE_REG_OFFSET), \ - [power_manager_wakeup_state_reg_offset] "i" (POWER_MANAGER_WAKEUP_STATE_REG_OFFSET) : "a0", "a1" \ - ); - - asm volatile ( - - // write registers - "la a0, __power_manager_start\n" - "sw x1, 0(a0)\n" - "sw x2, 4(a0)\n" - "sw x3, 8(a0)\n" - "sw x4, 12(a0)\n" - "sw x5, 16(a0)\n" - "sw x6, 20(a0)\n" - "sw x7, 24(a0)\n" - "sw x8, 28(a0)\n" - "sw x9, 32(a0)\n" - "sw x10, 36(a0)\n" - "sw x11, 40(a0)\n" - "sw x12, 44(a0)\n" - "sw x13, 48(a0)\n" - "sw x14, 52(a0)\n" - "sw x15, 56(a0)\n" - "sw x16, 60(a0)\n" - "sw x17, 64(a0)\n" - "sw x18, 68(a0)\n" - "sw x19, 72(a0)\n" - "sw x20, 76(a0)\n" - "sw x21, 80(a0)\n" - "sw x22, 88(a0)\n" - "sw x23, 92(a0)\n" - "sw x24, 96(a0)\n" - "sw x25, 100(a0)\n" - "sw x26, 104(a0)\n" - "sw x27, 108(a0)\n" - "sw x28, 112(a0)\n" - "sw x29, 116(a0)\n" - "sw x30, 120(a0)\n" - "sw x31, 124(a0)\n" - //csr - "csrr a1, mstatus\n" - "sw a1, 128(a0)\n" - "csrr a1, mie\n" - "sw a1, 132(a0)\n" - "csrr a1, mtvec\n" - "sw a1, 136(a0)\n" - "csrr a1, mscratch\n" - "sw a1, 140(a0)\n" - "csrr a1, mepc\n" - "sw a1, 144(a0)\n" - "csrr a1, mcause\n" - "sw a1, 148(a0)\n" - "csrr a1, mtval\n" - "sw a1, 152(a0)\n" - "csrr a1, mcycle\n" - "sw a1, 156(a0)\n" - "csrr a1, minstret\n" - "sw a1, 160(a0)\n" : : : "a0", "a1" \ - ); - - asm volatile ( - - // write RESTORE_ADDRESS[31:0] = PC - "lui a0, %[base_address_20bit]\n" - "la a1, wakeup\n" - "sw a1, %[power_manager_restore_address_reg_offset](a0)\n" - - // wait for interrupt - "wfi\n" - - // ---------------------------- - // power-gate - // ---------------------------- - - // ---------------------------- - // wake-up - // ---------------------------- - - // write POWER_GATE_CORE[0] = 0 - "wakeup:" - "lui a0, %[base_address_20bit]\n" - "sw x0, %[power_manager_power_gate_core_reg_offset](a0)\n" - - // write WAKEUP_STATE[0] = 0 - "sw x0, %[power_manager_wakeup_state_reg_offset](a0)\n" - - // write RESTORE_ADDRESS[31:0] = 0 - "sw x0, %[power_manager_restore_address_reg_offset](a0)\n" : : \ - \ - [base_address_20bit] "i" (POWER_MANAGER_START_ADDRESS >> 12), \ - [power_manager_power_gate_core_reg_offset] "i" (POWER_MANAGER_POWER_GATE_CORE_REG_OFFSET), \ - [power_manager_wakeup_state_reg_offset] "i" (POWER_MANAGER_WAKEUP_STATE_REG_OFFSET), \ - [power_manager_restore_address_reg_offset] "i" (POWER_MANAGER_RESTORE_ADDRESS_REG_OFFSET) : "a0", "a1" \ - ); - - asm volatile ( - - // write CORE_REG_Xn[31:0] = Xn - "la a0, __power_manager_start\n" - //one of the following load is gonna overwrite a0, but a0 was already stored before to the right value - "lw x1, 0(a0)\n" - "lw x2, 4(a0)\n" - "lw x3, 8(a0)\n" - "lw x4, 12(a0)\n" - "lw x5, 16(a0)\n" - "lw x6, 20(a0)\n" - "lw x7, 24(a0)\n" - "lw x8, 28(a0)\n" - "lw x9, 32(a0)\n" - "lw x10, 36(a0)\n" - "lw x11, 40(a0)\n" - "lw x12, 44(a0)\n" - "lw x13, 48(a0)\n" - "lw x14, 52(a0)\n" - "lw x15, 56(a0)\n" - "lw x16, 60(a0)\n" - "lw x17, 64(a0)\n" - "lw x18, 68(a0)\n" - "lw x19, 72(a0)\n" - "lw x20, 76(a0)\n" - "lw x21, 80(a0)\n" - "lw x22, 88(a0)\n" - "lw x23, 92(a0)\n" - "lw x24, 96(a0)\n" - "lw x25, 100(a0)\n" - "lw x26, 104(a0)\n" - "lw x27, 108(a0)\n" - "lw x28, 112(a0)\n" - "lw x29, 116(a0)\n" - "lw x30, 120(a0)\n" - "lw x31, 124(a0)\n" - //csr - "lw a1, 128(a0)\n" - "csrw mstatus, a1\n" - "lw a1, 132(a0)\n" - "csrw mie, a1\n" - "lw a1, 136(a0)\n" - "csrw mtvec, a1\n" - "lw a1, 140(a0)\n" - "csrw mscratch, a1\n" - "lw a1, 144(a0)\n" - "csrw mepc, a1\n" - "lw a1, 148(a0)\n" - "csrw mcause, a1\n" - "lw a1, 152(a0)\n" - "csrw mtval, a1\n" - "lw a1, 156(a0)\n" - "csrw mcycle, a1\n" - "lw a1, 160(a0)\n" - "csrw minstret, a1\n": : : "a0", "a1" \ - ); - - return; -} +extern void power_manager_cpu_store(); power_manager_result_t __attribute__ ((noinline)) power_gate_core(const power_manager_t *power_manager, power_manager_sel_intr_t sel_intr, power_manager_counters_t* cpu_counter) { @@ -201,14 +34,11 @@ power_manager_result_t __attribute__ ((noinline)) power_gate_core(const power_ma mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_INTR_STATE_REG_OFFSET), 0x0); // enable wait for SWITCH ACK - #ifdef TARGET_PYNQ_Z2 - reg = bitfield_bit32_write(reg, POWER_MANAGER_CPU_WAIT_ACK_SWITCH_ON_COUNTER_CPU_WAIT_ACK_SWITCH_ON_COUNTER_BIT, 0x0); - #else - reg = bitfield_bit32_write(reg, POWER_MANAGER_CPU_WAIT_ACK_SWITCH_ON_COUNTER_CPU_WAIT_ACK_SWITCH_ON_COUNTER_BIT, 0x1); - #endif + reg = bitfield_bit32_write(reg, POWER_MANAGER_CPU_WAIT_ACK_SWITCH_ON_COUNTER_CPU_WAIT_ACK_SWITCH_ON_COUNTER_BIT, 0x1); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_CPU_WAIT_ACK_SWITCH_ON_COUNTER_REG_OFFSET), reg); - power_gate_core_asm(); + power_manager_cpu_store(); // clean up states mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_EN_WAIT_FOR_INTR_REG_OFFSET), 0x0); @@ -231,11 +61,7 @@ power_manager_result_t __attribute__ ((noinline)) power_gate_periph(const power_ { uint32_t reg = 0; - #ifdef TARGET_PYNQ_Z2 - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_PERIPH_WAIT_ACK_SWITCH_ON_REG_OFFSET), 0x0); - #else - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_PERIPH_WAIT_ACK_SWITCH_ON_REG_OFFSET), 0x1); - #endif + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_PERIPH_WAIT_ACK_SWITCH_ON_REG_OFFSET), 0x1); if (sel_state == kOn_e) { @@ -265,11 +91,7 @@ power_manager_result_t __attribute__ ((noinline)) power_gate_ram_block(const pow if (sel_state == kOn_e) { - #ifdef TARGET_PYNQ_Z2 - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_ram_map[sel_block].wait_ack_switch), 0x0); - #else - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_ram_map[sel_block].wait_ack_switch), 0x1); - #endif + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_ram_map[sel_block].wait_ack_switch), 0x1); for (int i=0; iswitch_on; i++) asm volatile ("nop\n;"); mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_ram_map[sel_block].switch_off), 0x0); for (int i=0; iiso_off; i++) asm volatile ("nop\n;"); @@ -277,11 +99,7 @@ power_manager_result_t __attribute__ ((noinline)) power_gate_ram_block(const pow } else if (sel_state == kOff_e) { - #ifdef TARGET_PYNQ_Z2 - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_ram_map[sel_block].wait_ack_switch), 0x0); - #else - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_ram_map[sel_block].wait_ack_switch), 0x1); - #endif + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_ram_map[sel_block].wait_ack_switch), 0x1); for (int i=0; iiso_on; i++) asm volatile ("nop\n;"); mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_ram_map[sel_block].iso), 0x1); for (int i=0; iswitch_off; i++) asm volatile ("nop\n;"); @@ -309,11 +127,7 @@ power_manager_result_t __attribute__ ((noinline)) power_gate_external(const powe if (sel_state == kOn_e) { - #ifdef TARGET_PYNQ_Z2 - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_external_map[sel_external].wait_ack_switch), 0x0); - #else - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_external_map[sel_external].wait_ack_switch), 0x1); - #endif + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_external_map[sel_external].wait_ack_switch), 0x1); for (int i=0; iswitch_on; i++) asm volatile ("nop\n;"); mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_external_map[sel_external].switch_off), 0x0); for (int i=0; iiso_off; i++) asm volatile ("nop\n;"); @@ -323,11 +137,7 @@ power_manager_result_t __attribute__ ((noinline)) power_gate_external(const powe } else if (sel_state == kOff_e) { - #ifdef TARGET_PYNQ_Z2 - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_external_map[sel_external].wait_ack_switch), 0x0); - #else - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_external_map[sel_external].wait_ack_switch), 0x1); - #endif + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_external_map[sel_external].wait_ack_switch), 0x1); for (int i=0; iiso_on; i++) asm volatile ("nop\n;"); mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(power_manager_external_map[sel_external].iso), 0x1); for (int i=0; iswitch_off; i++) asm volatile ("nop\n;"); diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/power_manager_cpu_restore.S b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/power_manager_cpu_restore.S new file mode 100644 index 00000000..00c9f9f3 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/power_manager_cpu_restore.S @@ -0,0 +1,88 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#include "core_v_mini_mcu.h" +#include "power_manager_regs.h" // Generated. + +# power_manager_cpu.S +# This function re-stores the CPU context when back from (deep) sleep +.global power_manager_cpu_restore +.type power_manager_cpu_restore, @function + +#define POWER_MANAGER_START_ADDRESS_20bit (POWER_MANAGER_START_ADDRESS >> 12) + + +power_manager_cpu_restore: + + //using lui to load the upper 20 bits of the address instead of la as I want to be sure no other registers are used + lui t0, POWER_MANAGER_START_ADDRESS_20bit + sw x0, POWER_MANAGER_POWER_GATE_CORE_REG_OFFSET(t0) + + // write WAKEUP_STATE[0] = 0 + sw x0, POWER_MANAGER_WAKEUP_STATE_REG_OFFSET(t0) + + // write RESTORE_ADDRESS[31:0] = 0 + sw x0, POWER_MANAGER_RESTORE_ADDRESS_REG_OFFSET(t0) + + // restore gp as it is gonna be used to calculate the address of __power_manager_start + lw gp, POWER_MANAGER_GLOBAL_POINTER_REG_OFFSET(t0) + + // write CORE_REG_Xn[31:0] = Xn + la t0, __power_manager_start + // restore context, this part could be optimized + + //one of the following load is gonna overwrite t0, but t0 was already stored before to the right value + lw x1, 0(t0) + lw x2, 4(t0) + lw x3, 8(t0) + lw x4, 12(t0) + lw x5, 16(t0) + lw x6, 20(t0) + lw x7, 24(t0) + lw x8, 28(t0) + lw x9, 32(t0) + lw x10, 36(t0) + lw x11, 40(t0) + lw x12, 44(t0) + lw x13, 48(t0) + lw x14, 52(t0) + lw x15, 56(t0) + lw x16, 60(t0) + lw x17, 64(t0) + lw x18, 68(t0) + lw x19, 72(t0) + lw x20, 76(t0) + lw x21, 80(t0) + lw x22, 88(t0) + lw x23, 92(t0) + lw x24, 96(t0) + lw x25, 100(t0) + lw x26, 104(t0) + lw x27, 108(t0) + lw x28, 112(t0) + lw x29, 116(t0) + lw x30, 120(t0) + lw x31, 124(t0) + //csr + lw t1, 128(t0) + csrw mstatus, t1 + lw t1, 132(t0) + csrw mie, t1 + lw t1, 136(t0) + csrw mtvec, t1 + lw t1, 140(t0) + csrw mscratch, t1 + lw t1, 144(t0) + csrw mepc, t1 + lw t1, 148(t0) + csrw mcause, t1 + lw t1, 152(t0) + csrw mtval, t1 + lw t1, 156(t0) + csrw mcycle, t1 + lw t1, 160(t0) + csrw minstret, t1 + + + ret \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/power_manager_cpu_store.S b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/power_manager_cpu_store.S new file mode 100644 index 00000000..92e1ca8e --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/power_manager/power_manager_cpu_store.S @@ -0,0 +1,88 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#include "core_v_mini_mcu.h" +#include "power_manager_regs.h" // Generated. + +# power_manager_cpu.S +# This function stores the CPU context, goes to (deep) sleep with WFI +.global power_manager_cpu_store # make the function visible to the linker +.type power_manager_cpu_store, @function + +power_manager_cpu_store: + + // write POWER_GATE_CORE[0] = 1 + la t0, POWER_MANAGER_START_ADDRESS + li t1, 1 + sw t1, POWER_MANAGER_POWER_GATE_CORE_REG_OFFSET(t0) + + // write WAKEUP_STATE[0] = 1, this is check in the bootrom at reset time when waking up + sw t1, POWER_MANAGER_WAKEUP_STATE_REG_OFFSET(t0) + + // save the global pointer, _power_manager_start is the start of the power_manager section and saved in the gp reg + // when returning from deep sleep, the gp register is used to restore the context, thus saving it in an always on register + sw gp, POWER_MANAGER_GLOBAL_POINTER_REG_OFFSET(t0) + + // save context, this part could be optimized + la t0, __power_manager_start + sw x1, 0(t0) + sw x2, 4(t0) + sw x3, 8(t0) + sw x4, 12(t0) + sw x5, 16(t0) + sw x6, 20(t0) + sw x7, 24(t0) + sw x8, 28(t0) + sw x9, 32(t0) + sw x10, 36(t0) + sw x11, 40(t0) + sw x12, 44(t0) + sw x13, 48(t0) + sw x14, 52(t0) + sw x15, 56(t0) + sw x16, 60(t0) + sw x17, 64(t0) + sw x18, 68(t0) + sw x19, 72(t0) + sw x20, 76(t0) + sw x21, 80(t0) + sw x22, 88(t0) + sw x23, 92(t0) + sw x24, 96(t0) + sw x25, 100(t0) + sw x26, 104(t0) + sw x27, 108(t0) + sw x28, 112(t0) + sw x29, 116(t0) + sw x30, 120(t0) + sw x31, 124(t0) + //csr + csrr t1, mstatus + sw t1, 128(t0) + csrr t1, mie + sw t1, 132(t0) + csrr t1, mtvec + sw t1, 136(t0) + csrr t1, mscratch + sw t1, 140(t0) + csrr t1, mepc + sw t1, 144(t0) + csrr t1, mcause + sw t1, 148(t0) + csrr t1, mtval + sw t1, 152(t0) + csrr t1, mcycle + sw t1, 156(t0) + csrr t1, minstret + sw t1, 160(t0) + + la t0, POWER_MANAGER_START_ADDRESS + //save return address to restore + la t1, power_manager_cpu_restore + sw t1, POWER_MANAGER_RESTORE_ADDRESS_REG_OFFSET(t0) + + // wait for interrupt + wfi + + ret \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/rv_plic/rv_plic.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/rv_plic/rv_plic.c index 7b6ba5f4..c7fb8c7c 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/rv_plic/rv_plic.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/rv_plic/rv_plic.c @@ -34,6 +34,9 @@ /* MODULES USED */ /** **/ /****************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif #include "rv_plic.h" #include "rv_plic_structs.h" @@ -72,7 +75,7 @@ const uint32_t plicMaxPriority = RV_PLIC_PRIO0_PRIO0_MASK; * Pointer used to dynamically access the different interrupt handlers. */ typedef void (*handler_funct_t)(uint32_t); - +//#endif /****************************************************************************/ /** **/ /* PROTOTYPES OF LOCAL FUNCTIONS */ @@ -366,17 +369,17 @@ plic_result_t plic_software_irq_is_pending(void) } -plic_result_t plic_assign_external_irq_handler( uint32_t id, - void *handler ) +plic_result_t plic_assign_external_irq_handler( uint32_t id, void *handler ) { if( id >= EXT_IRQ_START && id <= QTY_INTR ) { - handlers[ id ] = (handler_funct_t*) handler; + handlers[ id ] = (handler_funct_t) handler; return kPlicOk; } return kPlicBadArg; } + void plic_reset_handlers_list(void) { handlers[NULL_INTR] = &handler_irq_dummy; @@ -433,7 +436,9 @@ static uint8_t plic_irq_bit_index( uint32_t irq) { return irq % RV_PLIC_PARAM_REG_WIDTH; } - +#ifdef __cplusplus +} +#endif /****************************************************************************/ /** **/ /* EOF */ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/rv_timer/rv_timer.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/rv_timer/rv_timer.h index 09f30945..cba44974 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/rv_timer/rv_timer.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/rv_timer/rv_timer.h @@ -105,6 +105,12 @@ typedef enum rv_timer_approximate_tick_params_result { * @param[out] out Tick parameters that will approximately produce the desired * counter frequency. * @return The result of the operation. + * + * The minimum value for `counter_freq` is given by: + * counter_freq_min = (255/4096) * clock_freq + * For example, if the clock frequency is 15MHz, the minimum value for `counter_freq` is about + * 1 MHz. + * The maximum value for `counter_freq` is given by the clock frequency. */ rv_timer_approximate_tick_params_result_t rv_timer_approximate_tick_params(uint64_t clock_freq, uint64_t counter_freq, diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/soc_ctrl/soc_ctrl.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/soc_ctrl/soc_ctrl.h index 9cfa45af..fe0e33c7 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/soc_ctrl/soc_ctrl.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/soc_ctrl/soc_ctrl.h @@ -21,7 +21,7 @@ extern "C" { * Initialization parameters for SOC CTRL. * */ -typedef struct soc_ctrl { +typedef struct /*soc_ctrl*/ { /** * The base address for the soc_ctrl hardware registers. */ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/spi_host/spi_host.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/spi_host/spi_host.c index 3312b8cd..f22c2bdb 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/spi_host/spi_host.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/spi_host/spi_host.c @@ -1,127 +1,491 @@ -// Copyright EPFL contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 +/* + ******************* +******************************* C SOURCE FILE ***************************** +** ******************* +** +** project : X-HEEP +** filename : spi_host.c +** version : 1 +** date : 06/03/24 +** +*************************************************************************** +** +** Copyright (c) EPFL contributors. +** All rights reserved. +** +*************************************************************************** +*/ +/***************************************************************************/ +/***************************************************************************/ +/** +* @file spi_host.c +* @date 06/03/24 +* @author Llorenç Muela +* @brief The Serial Peripheral Interface (SPI) driver to set up and use the +* SPI peripheral +*/ + +/****************************************************************************/ +/** **/ +/* MODULES USED */ +/** **/ +/****************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif #include "spi_host.h" -#include "mmio.h" #include "bitfield.h" -// SPI get functions -volatile uint8_t spi_get_tx_queue_depth(const spi_host_t *spi) { - volatile uint32_t status_reg = spi_get_status(spi); - return bitfield_field32_read(status_reg, SPI_HOST_STATUS_TXQD_FIELD); +/****************************************************************************/ +/** **/ +/* DEFINITIONS AND MACROS */ +/** **/ +/****************************************************************************/ + +#define SPI_EVENTS_INDEX 0 +#define SPI_ERRORS_INDEX 0 + +#define SPI_CONFIGOPTS_ADDR(spi, csid) ((&SPI_HW(spi)->CONFIGOPTS0) + csid*sizeof(uint32_t)) + +/****************************************************************************/ +/** **/ +/* TYPEDEFS AND STRUCTURES */ +/** **/ +/****************************************************************************/ + +/****************************************************************************/ +/** **/ +/* PROTOTYPES OF LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + +/** + * @brief Function that translates the status register to spi_event_e type. This + * has been implemented because the SPI peripheral has no other way to know which + * event was triggered other than reading the status. + * This function has been made local since only the event interrupt handler should + * need it. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @param events Pointer to store the events that were triggered. + * @return spi_return_flags_e indicating problems, SPI_FLAG_OK if all went well. + */ +spi_return_flags_e spi_get_events(spi_host_t* spi, spi_event_e* events); + +/** + * @brief Function to acknoledge event interrupts once received to prevent them + * from triggering again. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return spi_return_flags_e indicating problems, SPI_FLAG_OK if all went well. + */ +spi_return_flags_e spi_acknowledge_event(spi_host_t* spi); + +/****************************************************************************/ +/** **/ +/* EXPORTED VARIABLES */ +/** **/ +/****************************************************************************/ + +/****************************************************************************/ +/** **/ +/* GLOBAL VARIABLES */ +/** **/ +/****************************************************************************/ + +/****************************************************************************/ +/** **/ +/* EXPORTED FUNCTIONS */ +/** **/ +/****************************************************************************/ + +spi_return_flags_e spi_get_events_enabled(spi_host_t* spi, spi_event_e* events) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + *events = bitfield_read(SPI_HW(spi)->EVENT_ENABLE, SPI_EVENT_ALL, SPI_EVENTS_INDEX); + return SPI_FLAG_OK; } -volatile spi_ch_status_t spi_get_tx_channel_status(const spi_host_t *spi) { - volatile uint32_t status_reg = spi_get_status(spi); - spi_ch_status_t ch_status = { - .empty = bitfield_bit32_read(status_reg, SPI_HOST_STATUS_TXEMPTY_BIT), - .full = bitfield_bit32_read(status_reg, SPI_HOST_STATUS_TXFULL_BIT), - .stall = bitfield_bit32_read(status_reg, SPI_HOST_STATUS_TXSTALL_BIT), - .wm = bitfield_bit32_read(status_reg, SPI_HOST_STATUS_TXWM_BIT) - }; - return ch_status; +spi_return_flags_e spi_set_events_enabled(spi_host_t* spi, spi_event_e events, bool enable) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + if (events > SPI_EVENT_ALL) return SPI_FLAG_EVENT_INVALID; + // Since spi_event_e is mapped to EVENT_ENABLE: | = set, & ~ = clear + if (enable) SPI_HW(spi)->EVENT_ENABLE |= events; + else SPI_HW(spi)->EVENT_ENABLE &= ~events; + + return SPI_FLAG_OK; } -volatile uint8_t spi_get_rx_queue_depth(const spi_host_t *spi) { - volatile uint32_t status_reg = spi_get_status(spi); - return bitfield_field32_read(status_reg, SPI_HOST_STATUS_RXQD_FIELD); +spi_return_flags_e spi_get_errors_enabled(spi_host_t* spi, spi_error_e* errors) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + *errors = bitfield_read(SPI_HW(spi)->ERROR_ENABLE, SPI_ERROR_IRQALL, SPI_ERRORS_INDEX); + return SPI_FLAG_OK; } -volatile spi_ch_status_t spi_get_rx_channel_status(const spi_host_t *spi) { - volatile uint32_t status_reg = spi_get_status(spi); - spi_ch_status_t ch_status = { - .empty = bitfield_bit32_read(status_reg, SPI_HOST_STATUS_RXEMPTY_BIT), - .full = bitfield_bit32_read(status_reg, SPI_HOST_STATUS_RXFULL_BIT), - .stall = bitfield_bit32_read(status_reg, SPI_HOST_STATUS_RXSTALL_BIT), - .wm = bitfield_bit32_read(status_reg, SPI_HOST_STATUS_RXWM_BIT) - }; - return ch_status; +spi_return_flags_e spi_set_errors_enabled(spi_host_t* spi, spi_error_e errors, bool enable) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + if (errors > SPI_ERROR_IRQALL) return SPI_FLAG_ERROR_INVALID; + // Since spi_error_e is mapped to ERROR_ENABLE: | = set, & ~ = clear + if (enable) SPI_HW(spi)->ERROR_ENABLE |= errors; + else SPI_HW(spi)->ERROR_ENABLE &= ~errors; + + return SPI_FLAG_OK; +} + +spi_return_flags_e spi_get_errors(spi_host_t* spi, spi_error_e* errors) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + *errors = bitfield_read(SPI_HW(spi)->ERROR_STATUS, SPI_ERROR_ALL, SPI_ERRORS_INDEX); + return SPI_FLAG_OK; +} + +spi_return_flags_e spi_acknowledge_errors(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + // Write a one to each bit in ERROR_STATUS to clear these bits + SPI_HW(spi)->ERROR_STATUS = bitfield_write(SPI_HW(spi)->ERROR_STATUS, + SPI_ERROR_ALL, SPI_ERRORS_INDEX, + SPI_ERROR_ALL); + // Write a one to INTR_STATE error bit to clear the error + SPI_HW(spi)->INTR_STATE = bitfield_write(SPI_HW(spi)->INTR_STATE, BIT_MASK_1, + SPI_HOST_INTR_STATE_ERROR_BIT, true); + return SPI_FLAG_OK; +} + +spi_return_flags_e spi_enable_error_intr_test(spi_host_t* spi, bool enable) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + SPI_HW(spi)->INTR_TEST = bitfield_write(SPI_HW(spi)->INTR_TEST, BIT_MASK_1, + SPI_HOST_INTR_TEST_ERROR_BIT, enable); + return SPI_FLAG_OK; +} + +spi_return_flags_e spi_enable_evt_intr_test(spi_host_t* spi, bool enable) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + SPI_HW(spi)->INTR_TEST = bitfield_write(SPI_HW(spi)->INTR_TEST, BIT_MASK_1, + SPI_HOST_INTR_TEST_SPI_EVENT_BIT, enable); + return SPI_FLAG_OK; +} + +spi_return_flags_e spi_alert_test_fatal_fault_trigger(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + SPI_HW(spi)->ALERT_TEST = bitfield_write(SPI_HW(spi)->ALERT_TEST, BIT_MASK_1, + SPI_HOST_ALERT_TEST_FATAL_FAULT_BIT, true); + return SPI_FLAG_OK; +} + +volatile uint8_t spi_get_tx_queue_depth(spi_host_t* spi) +{ + // Returning an impossible value (tx fifo is 76 words long...) + SPI_NULL_CHECK(spi, UINT8_MAX) + return spi_get_status(spi).txqd; +} + +volatile uint8_t spi_get_rx_queue_depth(spi_host_t* spi) +{ + // Returning an impossible value (rx fifo is 64 words long...) + SPI_NULL_CHECK(spi, UINT8_MAX) + return spi_get_status(spi).rxqd; +} + +volatile uint32_t spi_get_csid(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, UINT32_MAX) + return SPI_HW(spi)->CSID; +} + +spi_return_flags_e spi_sw_reset(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + // Assert spi reset bit + SPI_HW(spi)->CONTROL = bitfield_write(SPI_HW(spi)->CONTROL, BIT_MASK_1, + SPI_HOST_CONTROL_SW_RST_BIT, true); + + volatile spi_status_t status = spi_get_status(spi); + // Wait for spi active and txqd & rxqd both go to 0 + while (status.active || status.txqd || status.rxqd); + // Deassert spi reset bit + SPI_HW(spi)->CONTROL = bitfield_write(SPI_HW(spi)->CONTROL, BIT_MASK_1, + SPI_HOST_CONTROL_SW_RST_BIT, false); + return SPI_FLAG_OK; } -volatile uint32_t spi_get_csid(const spi_host_t *spi) { - return mmio_region_read32(spi->base_addr, SPI_HOST_CSID_REG_OFFSET); +spi_return_flags_e spi_set_enable(spi_host_t* spi, bool enable) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + SPI_HW(spi)->CONTROL = bitfield_write(SPI_HW(spi)->CONTROL, BIT_MASK_1, + SPI_HOST_CONTROL_SPIEN_BIT, enable); + return SPI_FLAG_OK; } -// SPI set functions +spi_return_flags_e spi_set_tx_watermark(spi_host_t* spi, uint8_t watermark) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + // Check that watermark is not bigger than the fifo size (makes no sense otherwise) + if (watermark > SPI_HOST_PARAM_TX_DEPTH) return SPI_FLAG_WATERMARK_EXCEEDS; -void spi_sw_reset(const spi_host_t *spi) { - volatile uint32_t ctrl_reg = mmio_region_read32(spi->base_addr, SPI_HOST_CONTROL_REG_OFFSET); - ctrl_reg = bitfield_bit32_write(ctrl_reg, SPI_HOST_CONTROL_SW_RST_BIT, 1); - mmio_region_write32(spi->base_addr, SPI_HOST_CONTROL_REG_OFFSET, ctrl_reg); + SPI_HW(spi)->CONTROL = bitfield_write(SPI_HW(spi)->CONTROL, + SPI_HOST_CONTROL_TX_WATERMARK_MASK, + SPI_HOST_CONTROL_TX_WATERMARK_OFFSET, + watermark); + return SPI_FLAG_OK; } -void spi_set_enable(const spi_host_t *spi, bool enable) { - volatile uint32_t ctrl_reg = mmio_region_read32(spi->base_addr, SPI_HOST_CONTROL_REG_OFFSET); - ctrl_reg = bitfield_bit32_write(ctrl_reg, SPI_HOST_CONTROL_SPIEN_BIT, enable); - mmio_region_write32(spi->base_addr, SPI_HOST_CONTROL_REG_OFFSET, ctrl_reg); +spi_return_flags_e spi_set_rx_watermark(spi_host_t* spi, uint8_t watermark) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + // Check that watermark is not bigger than the fifo size (makes no sense otherwise) + if (watermark > SPI_HOST_PARAM_RX_DEPTH) return SPI_FLAG_WATERMARK_EXCEEDS; + + SPI_HW(spi)->CONTROL = bitfield_write(SPI_HW(spi)->CONTROL, + SPI_HOST_CONTROL_RX_WATERMARK_MASK, + SPI_HOST_CONTROL_RX_WATERMARK_OFFSET, + watermark); + return SPI_FLAG_OK; } -void spi_set_tx_watermark(const spi_host_t *spi, uint8_t watermark) { - volatile uint32_t ctrl_reg = mmio_region_read32(spi->base_addr, SPI_HOST_CONTROL_REG_OFFSET); - ctrl_reg = bitfield_field32_write(ctrl_reg, SPI_HOST_CONTROL_TX_WATERMARK_FIELD, watermark); - mmio_region_write32(spi->base_addr, SPI_HOST_CONTROL_REG_OFFSET, ctrl_reg); +spi_return_flags_e spi_set_configopts(spi_host_t* spi, uint32_t csid, const uint32_t conf_reg) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + if (SPI_CSID_INVALID(csid)) return SPI_FLAG_CSID_INVALID; + // Since the configopts registers always follow one after another, offset + // by csid times address delta + *SPI_CONFIGOPTS_ADDR(spi, csid) = conf_reg; + return SPI_FLAG_OK; } -void spi_set_rx_watermark(const spi_host_t *spi, uint8_t watermark) { - volatile uint32_t ctrl_reg = mmio_region_read32(spi->base_addr, SPI_HOST_CONTROL_REG_OFFSET); - ctrl_reg = bitfield_field32_write(ctrl_reg, SPI_HOST_CONTROL_RX_WATERMARK_FIELD, watermark); - mmio_region_write32(spi->base_addr, SPI_HOST_CONTROL_REG_OFFSET, ctrl_reg); +spi_return_flags_e spi_get_configopts(spi_host_t* spi, uint32_t csid, uint32_t* conf_reg) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + if (SPI_CSID_INVALID(csid)) return SPI_FLAG_CSID_INVALID; + // Since the configopts registers always follow one after another, offset + // by csid times address delta + *conf_reg = *SPI_CONFIGOPTS_ADDR(spi, csid); + return SPI_FLAG_OK; } -void spi_set_configopts(const spi_host_t *spi, uint32_t csid, const uint32_t conf_reg) { - mmio_region_write32(spi->base_addr, sizeof(uint32_t) * csid + SPI_HOST_CONFIGOPTS_0_REG_OFFSET, conf_reg); +spi_return_flags_e spi_set_csid(spi_host_t* spi, uint32_t csid) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + if (SPI_CSID_INVALID(csid)) return SPI_FLAG_CSID_INVALID; + + SPI_HW(spi)->CSID = csid; + return SPI_FLAG_OK; } -void spi_set_csid(const spi_host_t* spi, uint32_t csid) { - mmio_region_write32(spi->base_addr, SPI_HOST_CSID_REG_OFFSET, csid); +spi_return_flags_e spi_set_command(spi_host_t* spi, const uint32_t cmd_reg) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + + spi_return_flags_e flags = SPI_FLAG_OK; + spi_speed_e speed = bitfield_read(cmd_reg, SPI_HOST_COMMAND_SPEED_MASK, + SPI_HOST_COMMAND_SPEED_OFFSET); + spi_dir_e direction = bitfield_read(cmd_reg, SPI_HOST_COMMAND_DIRECTION_MASK, + SPI_HOST_COMMAND_DIRECTION_OFFSET); + + // Incompatible speed and direction produces an error + if (!spi_validate_cmd(direction, speed)) flags |= SPI_FLAG_SPEED_INVALID; + // Writing a command while not ready produces an error + if (spi_get_ready(spi) != SPI_TRISTATE_TRUE) flags |= SPI_FLAG_NOT_READY; + if (flags) return flags; + + SPI_HW(spi)->COMMAND = cmd_reg; + return SPI_FLAG_OK; } -void spi_set_command(const spi_host_t *spi, const uint32_t cmd_reg) { - mmio_region_write32(spi->base_addr, SPI_HOST_COMMAND_REG_OFFSET, cmd_reg); +spi_return_flags_e spi_write_word(spi_host_t* spi, uint32_t wdata) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + // Check we're not overflowing + if (spi_get_tx_queue_depth(spi) >= SPI_HOST_PARAM_TX_DEPTH) + return SPI_FLAG_TX_QUEUE_FULL; + SPI_HW(spi)->TXDATA = wdata; + return SPI_FLAG_OK; } -void spi_write_word(const spi_host_t *spi, uint32_t wdata) { - mmio_region_write32(spi->base_addr, SPI_HOST_TXDATA_REG_OFFSET, wdata); +spi_return_flags_e spi_write_byte(spi_host_t* spi, uint8_t bdata) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + // Check we're not overflowing + if (spi_get_tx_queue_depth(spi) >= SPI_HOST_PARAM_TX_DEPTH) + return SPI_FLAG_TX_QUEUE_FULL; + SPI_HW(spi)->TXDATA = bdata; + return SPI_FLAG_OK; } -void spi_read_word(const spi_host_t *spi, uint32_t* dst) { - *dst = mmio_region_read32(spi->base_addr, SPI_HOST_RXDATA_REG_OFFSET); +spi_return_flags_e spi_read_word(spi_host_t* spi, uint32_t* dst) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + // Check we're not underflowing + if (spi_get_rx_queue_depth(spi) == 0) return SPI_FLAG_RX_QUEUE_EMPTY; + *dst = SPI_HW(spi)->RXDATA; + return SPI_FLAG_OK; } -void spi_enable_evt_intr(const spi_host_t *spi, bool enable) { - volatile uint32_t intr_enable_reg = mmio_region_read32(spi->base_addr, SPI_HOST_INTR_ENABLE_REG_OFFSET); - intr_enable_reg = bitfield_bit32_write(intr_enable_reg, SPI_HOST_INTR_ENABLE_SPI_EVENT_BIT, enable); - mmio_region_write32(spi->base_addr, SPI_HOST_INTR_ENABLE_REG_OFFSET, intr_enable_reg); +spi_return_flags_e spi_enable_evt_intr(spi_host_t* spi, bool enable) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + SPI_HW(spi)->INTR_ENABLE = bitfield_write(SPI_HW(spi)->INTR_ENABLE, BIT_MASK_1, + SPI_HOST_INTR_ENABLE_SPI_EVENT_BIT, + enable); + return SPI_FLAG_OK; } -void spi_enable_error_intr(const spi_host_t *spi, bool enable) { - volatile uint32_t intr_enable_reg = mmio_region_read32(spi->base_addr, SPI_HOST_INTR_ENABLE_REG_OFFSET); - intr_enable_reg = bitfield_bit32_write(intr_enable_reg, SPI_HOST_INTR_STATE_ERROR_BIT, enable); - mmio_region_write32(spi->base_addr, SPI_HOST_INTR_ENABLE_REG_OFFSET, intr_enable_reg); +spi_return_flags_e spi_enable_error_intr(spi_host_t* spi, bool enable) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + SPI_HW(spi)->INTR_ENABLE = bitfield_write(SPI_HW(spi)->INTR_ENABLE, BIT_MASK_1, + SPI_HOST_INTR_STATE_ERROR_BIT, + enable); + return SPI_FLAG_OK; } -void spi_enable_rxwm_intr(const spi_host_t *spi, bool enable) { - volatile uint32_t intr_enable_reg = mmio_region_read32(spi->base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET); - intr_enable_reg = bitfield_bit32_write(intr_enable_reg, SPI_HOST_EVENT_ENABLE_RXWM_BIT, enable); - mmio_region_write32(spi->base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET, intr_enable_reg); +spi_return_flags_e spi_output_enable(spi_host_t* spi, bool enable) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + SPI_HW(spi)->CONTROL = bitfield_write(SPI_HW(spi)->CONTROL, BIT_MASK_1, + SPI_HOST_CONTROL_OUTPUT_EN_BIT, enable); + return SPI_FLAG_OK; } -void spi_enable_txempty_intr(const spi_host_t *spi, bool enable) { - volatile uint32_t intr_enable_reg = mmio_region_read32(spi->base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET); - intr_enable_reg = bitfield_bit32_write(intr_enable_reg, SPI_HOST_EVENT_ENABLE_TXEMPTY_BIT, enable); - mmio_region_write32(spi->base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET, intr_enable_reg); +// PLIC handles SPI Host 2 interrupts +void handler_irq_spi(uint32_t id) +{ + spi_error_e errors; + // Get errors and check if error triggered the interrupt + spi_get_errors(spi_host2, &errors); + if (errors) { + // Call either weak error handler in this module, or user implementation + spi_intr_handler_error_host2(errors); + } + else { + // If it wasn't an error it must have been an event + spi_event_e events; + // We need to acknowledge the event to avoid triggering in loop + spi_acknowledge_event(spi_host2); + spi_get_events(spi_host2, &events); + // Call either weak event handler in this module, or user implementation + spi_intr_handler_event_host2(events); + } } -void spi_output_enable(const spi_host_t *spi, bool enable){ - volatile uint32_t output_enable_reg = mmio_region_read32(spi->base_addr, SPI_HOST_CONTROL_REG_OFFSET); - output_enable_reg = bitfield_bit32_write(output_enable_reg, SPI_HOST_CONTROL_OUTPUT_EN_BIT, enable); - mmio_region_write32(spi->base_addr, SPI_HOST_CONTROL_REG_OFFSET, output_enable_reg); +// FIC SPI Host 1 interrupt handler +void fic_irq_spi(void) +{ + spi_error_e errors; + // Get errors and check if error triggered the interrupt + spi_get_errors(spi_host1, &errors); + if (errors) { + // Call either weak error handler in this module, or user implementation + spi_intr_handler_error_host(errors); + } + else { + // If it wasn't an error it must have been an event + spi_event_e events; + // We need to acknowledge the event to avoid triggering in loop + spi_acknowledge_event(spi_host1); + spi_get_events(spi_host1, &events); + // Call either weak event handler in this module, or user implementation + spi_intr_handler_event_host(events); + } } -__attribute__((weak, optimize("O0"))) void handler_irq_spi(uint32_t id) +// FIC SPI Flash interrupt handler +void fic_irq_spi_flash(void) { - // Replace this function with a non-weak implementation -} \ No newline at end of file + spi_error_e errors; + // Get errors and check if error triggered the interrupt + spi_get_errors(spi_flash, &errors); + if (errors) { + // Call either weak error handler in this module, or user implementation + spi_intr_handler_error_flash(errors); + } + else { + // If it wasn't an error it must have been an event + spi_event_e events; + // We need to acknowledge the event to avoid triggering in loop + spi_acknowledge_event(spi_flash); + spi_get_events(spi_flash, &events); + // Call either weak event handler in this module, or user implementation + spi_intr_handler_event_flash(events); + } +} + +__attribute__((weak, optimize("O0"))) void spi_intr_handler_event_flash(spi_event_e events) { + +} + +__attribute__((weak, optimize("O0"))) void spi_intr_handler_error_flash(spi_error_e errors) { + +} + +__attribute__((weak, optimize("O0"))) void spi_intr_handler_event_host(spi_event_e events) { + +} + +__attribute__((weak, optimize("O0"))) void spi_intr_handler_error_host(spi_error_e errors) { + +} + +__attribute__((weak, optimize("O0"))) void spi_intr_handler_event_host2(spi_event_e events) { + +} + +__attribute__((weak, optimize("O0"))) void spi_intr_handler_error_host2(spi_error_e errors) { + +} + +/****************************************************************************/ +/** **/ +/* LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + +spi_return_flags_e spi_get_events(spi_host_t* spi, spi_event_e* events) { + // This function is somewhat a little cheat. Since there is no hardware implementation + // telling which event triggered the interrupt, we just read the status register and + // map the statuses to their respective event. This allows to pass a pseudo-event + // variable to the event handlers. + volatile spi_status_t status = spi_get_status(spi); + // Also, we do not need any NULL check since this function is made to be called + // __ONLY__ from `handler_irq_spi`, `fic_irq_spi`, `fic_irq_spi_flash`. + // Therefore we know that spi argument will not be NULL. + *events = bitfield_write(*events, BIT_MASK_1, + SPI_HOST_EVENT_ENABLE_RXFULL_BIT, status.rxfull); + *events = bitfield_write(*events, BIT_MASK_1, + SPI_HOST_EVENT_ENABLE_TXEMPTY_BIT, status.txempty); + *events = bitfield_write(*events, BIT_MASK_1, + SPI_HOST_EVENT_ENABLE_RXWM_BIT, status.rxwm); + *events = bitfield_write(*events, BIT_MASK_1, + SPI_HOST_EVENT_ENABLE_TXWM_BIT, status.txwm); + *events = bitfield_write(*events, BIT_MASK_1, + SPI_HOST_EVENT_ENABLE_READY_BIT, status.ready); + *events = bitfield_write(*events, BIT_MASK_1, + SPI_HOST_EVENT_ENABLE_IDLE_BIT, ~status.active); + return SPI_FLAG_OK; +} + +spi_return_flags_e spi_acknowledge_event(spi_host_t* spi) { + // We do not need any NULL check since this function is made to be called + // __ONLY__ from `handler_irq_spi`, `fic_irq_spi`, `fic_irq_spi_flash`. + // Therefore we know that spi argument will not be NULL. + SPI_HW(spi)->INTR_STATE = bitfield_write(SPI_HW(spi)->INTR_STATE, BIT_MASK_1, + SPI_HOST_INTR_STATE_SPI_EVENT_BIT, true); + return SPI_FLAG_OK; +} +#ifdef __cplusplus +} +#endif +/****************************************************************************/ +/** **/ +/* EOF */ +/** **/ +/****************************************************************************/ \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/spi_host/spi_host.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/spi_host/spi_host.h index b5db646d..6eef81b9 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/spi_host/spi_host.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/spi_host/spi_host.h @@ -1,351 +1,1014 @@ -// Copyright EPFL contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 +/* + ******************* +******************************* C SOURCE FILE ***************************** +** ******************* +** +** project : X-HEEP +** filename : spi_host.h +** version : 1 +** date : 06/03/24 +** +*************************************************************************** +** +** Copyright (c) EPFL contributors. +** All rights reserved. +** +*************************************************************************** +*/ -// Basic device functions for opentitan SPI host +/***************************************************************************/ +/***************************************************************************/ +/** +* @file spi_host.h +* @date 06/03/24 +* @author Llorenç Muela +* @brief The Serial Peripheral Interface (SPI) driver to set up and use the +* SPI peripheral +*/ #ifndef _DRIVERS_SPI_HOST_H_ #define _DRIVERS_SPI_HOST_H_ +/****************************************************************************/ +/** **/ +/** MODULES USED **/ +/** **/ +/****************************************************************************/ + #include +#include + +#include "fast_intr_ctrl.h" +#include "rv_plic.h" + +#include "spi_host_regs.h" // Generated +#include "spi_host_structs.h" // Generated -#include "mmio.h" -#include "spi_host_regs.h" +/****************************************************************************/ +/** **/ +/** DEFINITIONS AND MACROS **/ +/** **/ +/****************************************************************************/ + +#define SPI_CSID_INVALID(csid) csid >= SPI_HOST_PARAM_NUM_C_S + +#define spi_host1_peri ((volatile spi_host *) SPI_HOST_START_ADDRESS) +#define spi_host2_peri ((volatile spi_host *) SPI2_START_ADDRESS) +#define spi_flash_peri ((volatile spi_host *) SPI_FLASH_START_ADDRESS) + +#define spi_host1 ((spi_host_t*) spi_host1_peri) +#define spi_host2 ((spi_host_t*) spi_host2_peri) +#define spi_flash ((spi_host_t*) spi_flash_peri) + +#define SPI_HW(spi_inst) ((volatile spi_host *) spi_inst) + +// Sanity check to return retval when spi is NULL. +// For development purposes. If 100% sure spi will NEVER be NULL, comment out +// the macro expansion to speed up SPI HAL. +#define SPI_NULL_CHECK(spi,retval) if (spi == NULL) return retval; #ifdef __cplusplus extern "C" { #endif -/** - * Initialization parameters for SPI. - * - */ -typedef struct spi { - /** - * The base address for the SPI hardware registers. - */ - mmio_region_t base_addr; -} spi_host_t; +/****************************************************************************/ +/** **/ +/** TYPEDEFS AND STRUCTURES **/ +/** **/ +/****************************************************************************/ /** -* SPI channel status structure +* SPI endianness */ -typedef struct spi_ch_status { - bool empty : 1; - bool full : 1; - bool wm : 1; - bool stall : 1; -} spi_ch_status_t; +typedef enum { + SPI_BYTE_ORDER_BIG_ENDIAN = 0, + SPI_BYTE_ORDER_LITTLE_ENDIAN = 1 +} spi_byte_order_e; /** * SPI speed type */ typedef enum { - kSpiSpeedStandard = 0, - kSpiSpeedDual = 1, - kSpiSpeedQuad = 2 + SPI_SPEED_STANDARD = 0, + SPI_SPEED_DUAL = 1, + SPI_SPEED_QUAD = 2 } spi_speed_e; /** * SPI directionality */ typedef enum { - kSpiDirDummy = 0, - kSpiDirRxOnly = 1, - kSpiDirTxOnly = 2, - kSpiDirBidir = 3 + SPI_DIR_DUMMY = 0, + SPI_DIR_RX_ONLY = 1, + SPI_DIR_TX_ONLY = 2, + SPI_DIR_BIDIR = 3 } spi_dir_e; +/** +* SPI events +*/ +typedef enum { + SPI_EVENT_NONE = 0, + // Triggers event when RX becomes full + SPI_EVENT_RXFULL = (1 << SPI_HOST_EVENT_ENABLE_RXFULL_BIT), + // Triggers event when TX becomes empty + SPI_EVENT_TXEMPTY = (1 << SPI_HOST_EVENT_ENABLE_TXEMPTY_BIT), + // Triggers event when RX goes above watermark + SPI_EVENT_RXWM = (1 << SPI_HOST_EVENT_ENABLE_RXWM_BIT), + // Triggers event when TX falls below watermark + SPI_EVENT_TXWM = (1 << SPI_HOST_EVENT_ENABLE_TXWM_BIT), + // Triggers event as soon as SPI Host IP is ready to receive more commands + SPI_EVENT_READY = (1 << SPI_HOST_EVENT_ENABLE_READY_BIT), + // Triggers event as soon as SPI Host IP is not processing any command + SPI_EVENT_IDLE = (1 << SPI_HOST_EVENT_ENABLE_IDLE_BIT), + // All the above mentioned events + SPI_EVENT_ALL = (1 << SPI_HOST_EVENT_ENABLE_IDLE_BIT+1) - 1 +} spi_event_e; + +/** +* SPI errors +*/ +typedef enum { + SPI_ERROR_NONE = 0, + // Triggers error interrupt whenever a command is issued while busy. + SPI_ERROR_CMDBUSY = (1 << SPI_HOST_ERROR_ENABLE_CMDBUSY_BIT), + // Triggers error interrupt whenever the TX FIFO overflows. + SPI_ERROR_OVERFLOW = (1 << SPI_HOST_ERROR_ENABLE_OVERFLOW_BIT), + // Triggers error interrupt whenever there is a read from RXDATA but the RX + // FIFO is empty. + SPI_ERROR_UNDERFLOW = (1 << SPI_HOST_ERROR_ENABLE_UNDERFLOW_BIT), + // Triggers error interrupt whenever a command is sent with invalid values for + // COMMAND.SPEED or COMMAND.DIRECTION. + SPI_ERROR_CMDINVAL = (1 << SPI_HOST_ERROR_ENABLE_CMDINVAL_BIT), + // Triggers error interrupt whenever a command is submitted, but CSID exceeds + // NumCS. + SPI_ERROR_CSIDINVAL = (1 << SPI_HOST_ERROR_ENABLE_CSIDINVAL_BIT), + // INDICATES that TLUL attempted to write to TXDATA with no bytes enabled. + // This error cannot be set (enabled or disabled). + // This error should never happen since it is the hardware that controls this. + SPI_ERROR_ACCESSINVAL = (1 << SPI_HOST_ERROR_STATUS_ACCESSINVAL_BIT), + // All the above mentioned errors that can be set. + SPI_ERROR_IRQALL = (1 << SPI_HOST_ERROR_ENABLE_CSIDINVAL_BIT+1) - 1, + // All the above mentioned errors. + SPI_ERROR_ALL = (1 << SPI_HOST_ERROR_STATUS_ACCESSINVAL_BIT+1) - 1 +} spi_error_e; + +/** +* SPI functions return flags, informs user what problem there was or if all OK +*/ +typedef enum { + // Everithing went well + SPI_FLAG_OK = 0x0000, + // The SPI variabled passed was a null pointer + SPI_FLAG_NULL_PTR = 0x0001, + // The Watermark exceeded SPI_HOST_PARAM_TX_DEPTH or SPI_HOST_PARAM_RX_DEPTH + // and was therefore not set + SPI_FLAG_WATERMARK_EXCEEDS = 0x0002, + // The CSID was out of the bounds specified inSPI_HOST_PARAM_NUM_C_S + SPI_FLAG_CSID_INVALID = 0x0004, + // The CMD FIFO is currently full so couldn't write command + SPI_FLAG_COMMAND_FULL = 0x0008, + // The specified speed is not valid so couldn't write command + SPI_FLAG_SPEED_INVALID = 0x0010, + // The TX Queue is full, thus could not write to TX register + SPI_FLAG_TX_QUEUE_FULL = 0x0020, + // The RX Queue is empty, thus could not read from RX register + SPI_FLAG_RX_QUEUE_EMPTY = 0x0040, + // The SPI is not ready + SPI_FLAG_NOT_READY = 0x0080, + // The event to enable is not a valid event + SPI_FLAG_EVENT_INVALID = 0x0100, + // The error irq to enable is not a valid error irq + SPI_FLAG_ERROR_INVALID = 0x0200 +} spi_return_flags_e; + +/** +* Extended bool to return if a function catched an error +*/ +typedef enum { + SPI_TRISTATE_ERROR = 0, + SPI_TRISTATE_TRUE = 1, + SPI_TRISTATE_FALSE = 2 +} spi_tristate_e; + +/** + * Opaque structure definition to hide the registers. + */ +typedef struct spi_s spi_host_t; + /** * SPI chip (slave) configuration structure */ -typedef struct spi_configopts { +typedef struct spi_configopts_s { + // The clock divider to use with a paricular slave uint16_t clkdiv : 16; - uint8_t csnidle : 4; + // Indicates the minimum number of sck half-cycles to hold cs_n high between + // commands + uint8_t csnidle : 4; + // Indicates the number of half sck cycles, CSNTRAIL+1, to leave between last + // edge of sck and the rising edge of cs_n uint8_t csntrail : 4; + // Indicates the number of half sck cycles, CSNLEAD+1, to leave between the + // falling edge of cs_n and the first edge of sck uint8_t csnlead : 4; + // Will be ignored by hardware bool __rsvd0 : 1; + // If 1 data is sampled a full cycle after shifting data out, instead of half cycle bool fullcyc : 1; + // If 0 data lines change on trailing edge and sample done on leading edge, + // if 1 it is the opposite bool cpha : 1; + // If 0 sck is low when idle, and emits high pulses. If 1 sck is high when idle, + // and emits of low pulses bool cpol : 1; } spi_configopts_t; /** * SPI command structure */ -typedef struct spi_command { +typedef struct spi_command_s { + // Length-1 in bytes for the command to transmit/receive uint32_t len : 24; + // Keep CS line active after command has finished (allows to instruct series + // of commands) bool csaat : 1; + // Speed of communication spi_speed_e speed : 2; + // Direction of communication spi_dir_e direction : 2; } spi_command_t; -// SPI registers access functions +/** +* SPI status structure +*/ +typedef struct spi_status_s { + union { + struct { + // TX queue depth (how many unsent words are in the FIFO) + uint8_t txqd : 8; + // RX queue depth (how many unread words are in the FIFO) + uint8_t rxqd : 8; + // CMD queue depth (how many unprocessed commands are in the FIFO) + uint8_t cmdqd : 4; + // Indicates wether rxqd is above the RX Watermark + bool rxwm : 1; + // Not used + bool __rsvd0 : 1; + // The endianness of the SPI Peripheral + bool byteorder : 1; + // Indicates if the SPI still still has more data to read but the RX FIFO is full + bool rxstall : 1; + // Indicates RX FIFO is empty + bool rxempty : 1; + // Indicates RX FIFO is full + bool rxfull : 1; + // Indicates wether txqd is below the TX Watermark + bool txwm : 1; + // Indicates if the SPI still has more data to send but the TX FIFO is empty + bool txstall : 1; + // Indicates TX FIFO is empty + bool txempty : 1; + // Indicates TX FIFO is full + bool txfull : 1; + // Indicates if the SPI peripheral is currently processing a command + bool active : 1; + // Indicates if the SPI peripheral is ready to receive more commands + bool ready : 1; + }; + uint32_t value; // This allows accessing all the bitfields as a single 32-bit integer + }; +} spi_status_t; + + +/****************************************************************************/ +/** **/ +/** EXPORTED VARIABLES **/ +/** **/ +/****************************************************************************/ + +/****************************************************************************/ +/** **/ +/** EXPORTED FUNCTIONS **/ +/** **/ +/****************************************************************************/ /** - * Read the TX FIFO depth register. + * @brief Get enabled events for a specified SPI peripheral. * * @param spi Pointer to spi_host_t representing the target SPI. - * @return TX FIFO depth. + * @param events Pointer to store enabled event interrupts. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. */ -volatile uint8_t spi_get_tx_queue_depth(const spi_host_t *spi); +spi_return_flags_e spi_get_events_enabled(spi_host_t* spi, spi_event_e* events); /** - * Read the TX channel status register. + * @brief Set enabled events for a specified SPI peripheral. * * @param spi Pointer to spi_host_t representing the target SPI. - * @return TX channel status structure. + * @param events Pointer to events to enable/disable and to store the currently enabled + * event interrupts. + * @param enable Flag to enable (true) or disable (false) the specified event interrupts. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_EVENT_INVALID if events not valid. + * @return SPI_FLAG_OK if success. */ -volatile spi_ch_status_t spi_get_tx_channel_status(const spi_host_t *spi); +spi_return_flags_e spi_set_events_enabled(spi_host_t* spi, spi_event_e events, bool enable); /** - * Read the RX FIFO depth register. + * @brief Get enabled error interrupts for a specified SPI peripheral. * * @param spi Pointer to spi_host_t representing the target SPI. - * @return RX FIFO depth. + * @param errors Pointer to store enabled error interrupts. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. */ -volatile uint8_t spi_get_rx_queue_depth(const spi_host_t *spi); +spi_return_flags_e spi_get_errors_enabled(spi_host_t* spi, spi_error_e* errors); /** - * Read the RX channel status register. + * @brief Set enabled error interrupts for a specified SPI peripheral. * * @param spi Pointer to spi_host_t representing the target SPI. - * @return RX channel status structure. + * @param errors Pointer to error interrupts to enable/disable and to store the currently + * enabled error interrupts. + * @param enable Flag to enable (true) or disable (false) the specified error interrupts. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_ERROR_INVALID if errors not valid. + * @return SPI_FLAG_OK if success. */ -volatile spi_ch_status_t spi_get_rx_channel_status(const spi_host_t *spi); +spi_return_flags_e spi_set_errors_enabled(spi_host_t* spi, spi_error_e errors, bool enable); /** - * Read the Chip Select (CS) ID register. + * @brief Get the errors that have raised if any. * * @param spi Pointer to spi_host_t representing the target SPI. - * @return Chip Select (CS) ID. + * @param errors Pointer to store the errors. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. */ -volatile uint32_t spi_get_csid(const spi_host_t *spi); +spi_return_flags_e spi_get_errors(spi_host_t* spi, spi_error_e* errors); /** - * Reset the SPI from software. + * @brief Acknoledge the errors that have raised once solved in order to renable + * the SPI peripheral operation. * * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. */ -void spi_sw_reset(const spi_host_t *spi); +spi_return_flags_e spi_acknowledge_errors(spi_host_t* spi); /** - * Enable the SPI host. + * @brief Enable or disable error interrupt test mode for a specified SPI peripheral. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @param enable Flag to enable (true) or disable (false) error interrupt test mode. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. + */ +spi_return_flags_e spi_enable_error_intr_test(spi_host_t* spi, bool enable); + +/** + * @brief Enable or disable event interrupt test mode for a specified SPI peripheral. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @param enable Flag to enable (true) or disable (false) event interrupt test mode. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. + */ +spi_return_flags_e spi_enable_evt_intr_test(spi_host_t* spi, bool enable); + +/** + * @brief Trigger a fatal fault test alert for a specified SPI peripheral. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. + */ +spi_return_flags_e spi_alert_test_fatal_fault_trigger(spi_host_t* spi); + +/** + * @brief Read the TX FIFO depth register. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return TX FIFO depth. UINT8_MAX if spi is NULL. + */ +volatile uint8_t spi_get_tx_queue_depth(spi_host_t* spi); + +/** + * @brief Read the RX FIFO depth register. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return RX FIFO depth. UINT8_MAX if spi is NULL. + */ +volatile uint8_t spi_get_rx_queue_depth(spi_host_t* spi); + +/** + * @brief Read the Chip Select (CS) ID register. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return Chip Select (CS) ID. UINT32_MAX if spi is NULL. + */ +volatile uint32_t spi_get_csid(spi_host_t* spi); + +/** + * @brief Reset the SPI from software. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. + */ +spi_return_flags_e spi_sw_reset(spi_host_t* spi); + +/** + * @brief Enable the SPI host. * * @param spi Pointer to spi_host_t representing the target SPI. * @param enable SPI enable register value. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. */ -void spi_set_enable(const spi_host_t *spi, bool enable); +spi_return_flags_e spi_set_enable(spi_host_t* spi, bool enable); /** - * Set the transmit queue watermark level (to enable interrupt triggering). + * @brief Set the transmit queue watermark level (to enable interrupt triggering). * * @param spi Pointer to spi_host_t representing the target SPI. * @param watermark Queue/fifo trigger level (minimum level). + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_WATERMARK_EXCEEDS if watermark exceeds max (currently 76). + * @return SPI_FLAG_OK if success. */ -void spi_set_tx_watermark(const spi_host_t *spi, uint8_t watermark); +spi_return_flags_e spi_set_tx_watermark(spi_host_t* spi, uint8_t watermark); /** - * Set the receive queue watermark level (to enable interrupt triggering). + * @brief Set the receive queue watermark level (to enable interrupt triggering). * * @param spi Pointer to spi_host_t representing the target SPI. * @param watermark Queue/fifo trigger level (maximum level). + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_WATERMARK_EXCEEDS if watermark exceeds max (currently 64). + * @return SPI_FLAG_OK if success. + */ +spi_return_flags_e spi_set_rx_watermark(spi_host_t* spi, uint8_t watermark); + +/** + * @brief Set the requirement of a target device (slave). + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @param csid Chip Select (CS) ID. + * @param conf_reg Slave configuration. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_CSID_INVALID if csid out of range. + * @return SPI_FLAG_OK if success. */ -void spi_set_rx_watermark(const spi_host_t *spi, uint8_t watermark); +spi_return_flags_e spi_set_configopts(spi_host_t* spi, uint32_t csid, const uint32_t conf_reg); /** - * Set the requirement of a target device (i.e., a slave). + * @brief Get the requirement of a target device (slave). * * @param spi Pointer to spi_host_t representing the target SPI. * @param csid Chip Select (CS) ID. - * @param conf_reg Slave transmission configuration. + * @param conf_reg Where slave configuration gets stored. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_CSID_INVALID if csid out of range. + * @return SPI_FLAG_OK if success. */ -void spi_set_configopts(const spi_host_t *spi, uint32_t csid, uint32_t conf_reg); +spi_return_flags_e spi_get_configopts(spi_host_t* spi, uint32_t csid, uint32_t* conf_reg); /** - * Select which device to target with the next command. + * @brief Select which device to target with the next command. * * @param spi Pointer to spi_host_t representing the target SPI. * @param csid Chip Select (SC) ID. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_CSID_INVALID if csid out of range. + * @return SPI_FLAG_OK if success. */ -void spi_set_csid(const spi_host_t *spi, uint32_t csid); +spi_return_flags_e spi_set_csid(spi_host_t* spi, uint32_t csid); /** - * Set the next command (one for all attached SPI devices). + * @brief Set the next command (one for all attached SPI devices). * * @param spi Pointer to spi_host_t representing the target SPI. * @param cmd_reg Command register value (Length, speed, ...). + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_SPEED_INVALID if direction and speed incompatible. + * @return SPI_FLAG_NOT_READY if SPI Host not ready. + * @return SPI_FLAG_OK if success. */ -void spi_set_command(const spi_host_t *spi, uint32_t cmd_reg); +spi_return_flags_e spi_set_command(spi_host_t* spi, uint32_t cmd_reg); /** - * Write one word to the TX FIFO. + * @brief Write one word to the TX FIFO. * * @param spi Pointer to spi_host_t representing the target SPI. * @param wdata Data to write. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_TX_QUEUE_FULL if TX FIFO is full. + * @return SPI_FLAG_OK if success. */ -void spi_write_word(const spi_host_t *spi, uint32_t wdata); +spi_return_flags_e spi_write_word(spi_host_t* spi, uint32_t wdata); /** - * Read one word to the RX FIFO. + * @brief Write a byte of data to the transmit queue of a specified SPI peripheral. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @param bdata Byte of data to write. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_TX_QUEUE_FULL if TX FIFO is full. + * @return SPI_FLAG_OK if success. + */ +spi_return_flags_e spi_write_byte(spi_host_t* spi, uint8_t bdata); + +/** + * @brief Read one word to the RX FIFO. * * @param spi Pointer to spi_host_t representing the target SPI. * @param rdata Read data. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_RX_QUEUE_EMPTY if RX FIFO is empty. + * @return SPI_FLAG_OK if success. */ -void spi_read_word(const spi_host_t *spi, uint32_t* dst); +spi_return_flags_e spi_read_word(spi_host_t* spi, uint32_t* dst); /** - * Enable SPI event interrupt + * @brief Enable SPI event interrupt * * @param spi Pointer to spi_host_t representing the target SPI. * @param enable SPI event interrupt bit value. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. */ -void spi_enable_evt_intr(const spi_host_t *spi, bool enable); +spi_return_flags_e spi_enable_evt_intr(spi_host_t* spi, bool enable); /** - * Enable SPI error interrupt + * @brief Enable SPI error interrupt * * @param spi Pointer to spi_host_t representing the target SPI. * @param enable SPI error interrupt bit value. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. */ -void spi_enable_error_intr(const spi_host_t *spi, bool enable); +spi_return_flags_e spi_enable_error_intr(spi_host_t* spi, bool enable); /** - * Enable SPI watermark event interrupt + * @brief Enable SPI output * * @param spi Pointer to spi_host_t representing the target SPI. - * @param enable SPI RX watermark interrupt bit value. + * @param enable SPI TX empty interrupt bit value. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. */ -void spi_enable_rxwm_intr(const spi_host_t *spi, bool enable); +spi_return_flags_e spi_output_enable(spi_host_t* spi, bool enable); + +/****************************************************************************/ +/** **/ +/** INLINE FUNCTIONS **/ +/** **/ +/****************************************************************************/ /** - * Enable SPI TX empty event interrupt + * @brief Check if a given direction and speed are compatible. + * i.e. bidirectional communication only possible at standard speed * * @param spi Pointer to spi_host_t representing the target SPI. - * @param enable SPI TX empty interrupt bit value. + * @param direction spi_dir_e direction of communication. + * @param speed spi_speed_e speed of communication. + * @return true if compatible false otherwise. + */ +static inline __attribute__((always_inline)) +bool spi_validate_cmd(uint8_t direction, uint8_t speed) +{ + if (speed > SPI_SPEED_QUAD || direction > SPI_DIR_BIDIR || + (direction == SPI_DIR_BIDIR && speed != SPI_SPEED_STANDARD)) + return false; + else + return true; +} + +/** + * @brief Get the state of the event interrupt flag (indicates if event has been + * triggered). + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_TRISTATE_ERROR if null pointer, else SPI_TRISTATE_TRUE if flag active + * or SPI_TRISTATE_FALSE if not active. */ -void spi_enable_txempty_intr(const spi_host_t *spi, bool enable); +static inline __attribute__((always_inline)) +spi_tristate_e spi_get_evt_intr_state(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_TRISTATE_ERROR) + + if (bitfield_read(SPI_HW(spi)->INTR_STATE, BIT_MASK_1, + SPI_HOST_INTR_STATE_SPI_EVENT_BIT)) + return SPI_TRISTATE_TRUE; + else + return SPI_TRISTATE_FALSE; +} /** - * Enable SPI output + * @brief Get the state of the error interrupt flag (indicates if error has been + * triggered). * * @param spi Pointer to spi_host_t representing the target SPI. - * @param enable SPI TX empty interrupt bit value. + * @return SPI_TRISTATE_ERROR if null pointer, else SPI_TRISTATE_TRUE if flag active + * or SPI_TRISTATE_FALSE if not active. */ -void spi_output_enable(const spi_host_t *spi, bool enable); +static inline __attribute__((always_inline)) +spi_tristate_e spi_get_error_intr_state(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_TRISTATE_ERROR) + if (bitfield_read(SPI_HW(spi)->INTR_STATE, BIT_MASK_1, + SPI_HOST_INTR_STATE_ERROR_BIT)) + return SPI_TRISTATE_TRUE; + else + return SPI_TRISTATE_FALSE; +} -// Inline functions +/** + * @brief Check if event interrupts are enabled. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_TRISTATE_ERROR if null pointer, else SPI_TRISTATE_TRUE if enabled + * or SPI_TRISTATE_FALSE otherwise. + */ +static inline __attribute__((always_inline)) +spi_tristate_e spi_get_evt_intr_enable(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_TRISTATE_ERROR) + + if (bitfield_read(SPI_HW(spi)->INTR_ENABLE, BIT_MASK_1, + SPI_HOST_INTR_ENABLE_SPI_EVENT_BIT)) + return SPI_TRISTATE_TRUE; + else + return SPI_TRISTATE_FALSE; +} /** - * Read SPI status register + * @brief Check if error interrupts are enabled. * * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_TRISTATE_ERROR if null pointer, else SPI_TRISTATE_TRUE if enabled + * or SPI_TRISTATE_FALSE otherwise. */ -static inline __attribute__((always_inline)) volatile uint32_t spi_get_status(const spi_host_t *spi) { - return mmio_region_read32(spi->base_addr, SPI_HOST_STATUS_REG_OFFSET); +static inline __attribute__((always_inline)) +spi_tristate_e spi_get_error_intr_enable(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_TRISTATE_ERROR) + + if (bitfield_read(SPI_HW(spi)->INTR_ENABLE, BIT_MASK_1, + SPI_HOST_INTR_ENABLE_ERROR_BIT)) + return SPI_TRISTATE_TRUE; + else + return SPI_TRISTATE_FALSE; } /** - * Read SPI active bit from status register + * @brief Read SPI status register * * @param spi Pointer to spi_host_t representing the target SPI. + * @return Pointer to spi_status_t structure. NULL if spi is NULL. */ -static inline __attribute__((always_inline)) volatile bool spi_get_active(const spi_host_t *spi) { - volatile uint32_t status_reg = spi_get_status(spi); - return bitfield_bit32_read(status_reg, SPI_HOST_STATUS_ACTIVE_BIT); +static inline __attribute__((always_inline)) +const volatile spi_status_t spi_get_status(spi_host_t* spi) +{ + spi_status_t status; + status.value = SPI_HW(spi)->STATUS; // Assuming SPI_HW(spi)->STATUS returns a uint32_t value representing the status + return status; } /** - * Read SPI ready bit from status register + * @brief Read SPI active bit from status register (indicates if SPI peripheral + * is currently processing a command) * * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_TRISTATE_ERROR if null pointer, else SPI_TRISTATE_TRUE if active + * or SPI_TRISTATE_FALSE otherwise. */ -static inline __attribute__((always_inline)) volatile bool spi_get_ready(const spi_host_t *spi) { - volatile uint32_t status_reg = spi_get_status(spi); - return bitfield_bit32_read(status_reg, SPI_HOST_STATUS_READY_BIT); +static inline __attribute__((always_inline)) +spi_tristate_e spi_get_active(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_TRISTATE_ERROR) + //return spi_get_status(spi)->active ? SPI_TRISTATE_TRUE : SPI_TRISTATE_FALSE; + spi_status_t spi_status; + spi_status.value = 0x00; + spi_status.value = SPI_HW(spi)->STATUS; } /** - * Wait SPI is ready to receive commands. + * @brief Read SPI ready bit from status register (indicates if SPI peripheral + * is ready to receive more commands) * * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_TRISTATE_ERROR if null pointer, else SPI_TRISTATE_TRUE if ready + * or SPI_TRISTATE_FALSE otherwise. */ -static inline __attribute__((always_inline)) void spi_wait_for_ready(const spi_host_t *spi) { - while (!spi_get_ready(spi)); +static inline __attribute__((always_inline)) +spi_tristate_e spi_get_ready(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_TRISTATE_ERROR) + return spi_get_status(spi).ready ? SPI_TRISTATE_TRUE : SPI_TRISTATE_FALSE; } /** - * Wait TX FIFO reach watermark. + * @brief Wait SPI is ready to receive commands. * * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. */ -static inline __attribute__((always_inline)) void spi_wait_for_tx_watermark(const spi_host_t *spi) { - while (!mmio_region_get_bit32(spi->base_addr, SPI_HOST_STATUS_REG_OFFSET, SPI_HOST_STATUS_TXWM_BIT)); +static inline __attribute__((always_inline)) +spi_return_flags_e spi_wait_for_ready(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + while (spi_get_ready(spi) == SPI_TRISTATE_FALSE); + return SPI_FLAG_OK; } /** - * Wait TX FIFO empty. + * @brief Wait SPI is no longer processing commands. * * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. */ -static inline __attribute__((always_inline)) void spi_wait_for_tx_empty(const spi_host_t *spi) { - while (!mmio_region_get_bit32(spi->base_addr, SPI_HOST_STATUS_REG_OFFSET, SPI_HOST_STATUS_TXEMPTY_BIT)); +static inline __attribute__((always_inline)) +spi_return_flags_e spi_wait_for_idle(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + while (spi_get_active(spi) == SPI_TRISTATE_TRUE); + return SPI_FLAG_OK; } /** - * Wait TX FIFO not empty. + * @brief Wait CMD FIFO not full. * * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. */ -static inline __attribute__((always_inline)) void spi_wait_for_tx_not_empty(const spi_host_t *spi) { - while (mmio_region_get_bit32(spi->base_addr, SPI_HOST_STATUS_REG_OFFSET, SPI_HOST_STATUS_TXEMPTY_BIT)); +static inline __attribute__((always_inline)) +spi_return_flags_e spi_wait_for_cmdqd_not_full(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + while (spi_get_status(spi).cmdqd >= SPI_HOST_PARAM_CMD_DEPTH); + return SPI_FLAG_OK; } /** - * Wait RX FIFO reach watermark. + * @brief Wait TX FIFO reach watermark. * * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. */ -static inline __attribute__((always_inline)) void spi_wait_for_rx_watermark(const spi_host_t *spi) { - while (!mmio_region_get_bit32(spi->base_addr, SPI_HOST_STATUS_REG_OFFSET, SPI_HOST_STATUS_RXWM_BIT)); +static inline __attribute__((always_inline)) +spi_return_flags_e spi_wait_for_tx_watermark(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + while (!spi_get_status(spi).txwm); + return SPI_FLAG_OK; } /** - * Create SPI target device configuration word. + * @brief Wait TX FIFO empty. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. + */ +static inline __attribute__((always_inline)) +spi_return_flags_e spi_wait_for_tx_empty(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + while (!spi_get_status(spi).txempty); + return SPI_FLAG_OK; +} + +/** + * @brief Wait TX FIFO not empty. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. + */ +static inline __attribute__((always_inline)) +spi_return_flags_e spi_wait_for_tx_not_empty(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + while (spi_get_status(spi).txempty); + return SPI_FLAG_OK; +} + +/** + * @brief Wait TX FIFO not full. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. + */ +static inline __attribute__((always_inline)) +spi_return_flags_e spi_wait_for_tx_not_full(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + while (spi_get_status(spi).txfull); + return SPI_FLAG_OK; +} + +/** + * @brief Wait RX FIFO empty. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. + */ +static inline __attribute__((always_inline)) +spi_return_flags_e spi_wait_for_rx_empty(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + while (!spi_get_status(spi).rxempty); + return SPI_FLAG_OK; +} + +/** + * @brief Wait RX FIFO not empty. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. + */ +static inline __attribute__((always_inline)) +spi_return_flags_e spi_wait_for_rx_not_empty(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + while (spi_get_status(spi).rxempty); + return SPI_FLAG_OK; +} + +/** + * @brief Wait RX FIFO full. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. + */ +static inline __attribute__((always_inline)) +spi_return_flags_e spi_wait_for_rx_full(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + while (!spi_get_status(spi).rxfull); + return SPI_FLAG_OK; +} + +/** + * @brief Wait RX FIFO reach watermark. + * + * @param spi Pointer to spi_host_t representing the target SPI. + * @return SPI_FLAG_NULL_PTR if spi NULL pointer. + * @return SPI_FLAG_OK if success. + */ +static inline __attribute__((always_inline)) +spi_return_flags_e spi_wait_for_rx_watermark(spi_host_t* spi) +{ + SPI_NULL_CHECK(spi, SPI_FLAG_NULL_PTR) + while (!spi_get_status(spi).rxwm); + return SPI_FLAG_OK; +} + +/** + * @brief Create SPI target device configuration word. * * @param configopts Target device configuation structure. + * @return uint32 representing the configopts. */ -static inline __attribute__((always_inline)) __attribute__((const)) uint32_t spi_create_configopts(const spi_configopts_t configopts) { +static inline __attribute__((always_inline)) __attribute__((const)) +uint32_t spi_create_configopts(const spi_configopts_t configopts) +{ uint32_t conf_reg = 0; - conf_reg = bitfield_field32_write(conf_reg, SPI_HOST_CONFIGOPTS_0_CLKDIV_0_FIELD, configopts.clkdiv); - conf_reg = bitfield_field32_write(conf_reg, SPI_HOST_CONFIGOPTS_0_CSNIDLE_0_FIELD, configopts.csnidle); - conf_reg = bitfield_field32_write(conf_reg, SPI_HOST_CONFIGOPTS_0_CSNTRAIL_0_FIELD, configopts.csntrail); - conf_reg = bitfield_field32_write(conf_reg, SPI_HOST_CONFIGOPTS_0_CSNLEAD_0_FIELD, configopts.csnlead); - conf_reg = bitfield_bit32_write(conf_reg, SPI_HOST_CONFIGOPTS_0_FULLCYC_0_BIT, configopts.fullcyc); - conf_reg = bitfield_bit32_write(conf_reg, SPI_HOST_CONFIGOPTS_0_CPHA_0_BIT, configopts.cpha); - conf_reg = bitfield_bit32_write(conf_reg, SPI_HOST_CONFIGOPTS_0_CPOL_0_BIT, configopts.cpol); + conf_reg = bitfield_write(conf_reg, SPI_HOST_CONFIGOPTS_0_CLKDIV_0_MASK, + SPI_HOST_CONFIGOPTS_0_CLKDIV_0_OFFSET, configopts.clkdiv); + conf_reg = bitfield_write(conf_reg, SPI_HOST_CONFIGOPTS_0_CSNIDLE_0_MASK, + SPI_HOST_CONFIGOPTS_0_CSNIDLE_0_OFFSET, configopts.csnidle); + conf_reg = bitfield_write(conf_reg, SPI_HOST_CONFIGOPTS_0_CSNTRAIL_0_MASK, + SPI_HOST_CONFIGOPTS_0_CSNTRAIL_0_OFFSET, configopts.csntrail); + conf_reg = bitfield_write(conf_reg, SPI_HOST_CONFIGOPTS_0_CSNLEAD_0_MASK, + SPI_HOST_CONFIGOPTS_0_CSNLEAD_0_OFFSET, configopts.csnlead); + conf_reg = bitfield_write(conf_reg, BIT_MASK_1, + SPI_HOST_CONFIGOPTS_0_FULLCYC_0_BIT, configopts.fullcyc); + conf_reg = bitfield_write(conf_reg, BIT_MASK_1, + SPI_HOST_CONFIGOPTS_0_CPHA_0_BIT, configopts.cpha); + conf_reg = bitfield_write(conf_reg, BIT_MASK_1, + SPI_HOST_CONFIGOPTS_0_CPOL_0_BIT, configopts.cpol); return conf_reg; } /** - * Create SPI command word. + * @brief Convert SPI target device configuration word to spi_configopts_t structure. + * + * @param configopts Target device configuation structure. + * @return spi_configopts_t representing the config_reg. + */ +static inline __attribute__((always_inline)) __attribute__((const)) +spi_configopts_t spi_create_configopts_structure(const uint32_t config_reg) +{ + spi_configopts_t configopts = { + .clkdiv = bitfield_read(config_reg, SPI_HOST_CONFIGOPTS_0_CLKDIV_0_MASK, + SPI_HOST_CONFIGOPTS_0_CLKDIV_0_OFFSET), + .csnidle = bitfield_read(config_reg, SPI_HOST_CONFIGOPTS_0_CSNIDLE_0_MASK, + SPI_HOST_CONFIGOPTS_0_CSNIDLE_0_OFFSET), + .csntrail = bitfield_read(config_reg, SPI_HOST_CONFIGOPTS_0_CSNTRAIL_0_MASK, + SPI_HOST_CONFIGOPTS_0_CSNTRAIL_0_OFFSET), + .csnlead = bitfield_read(config_reg, SPI_HOST_CONFIGOPTS_0_CSNLEAD_0_MASK, + SPI_HOST_CONFIGOPTS_0_CSNLEAD_0_OFFSET), + .fullcyc = bitfield_read(config_reg, BIT_MASK_1, + SPI_HOST_CONFIGOPTS_0_FULLCYC_0_BIT), + .cpha = bitfield_read(config_reg, BIT_MASK_1, + SPI_HOST_CONFIGOPTS_0_CPHA_0_BIT), + .cpol = bitfield_read(config_reg, BIT_MASK_1, + SPI_HOST_CONFIGOPTS_0_CPOL_0_BIT) + }; + return configopts; +} + +/** + * @brief Create SPI command word. * * @param command Command configuration structure. + * @return uint32 representing the command. */ -static inline __attribute__((always_inline)) __attribute__((const)) uint32_t spi_create_command(const spi_command_t command) { +static inline __attribute__((always_inline)) __attribute__((const)) +uint32_t spi_create_command(const spi_command_t command) +{ uint32_t cmd_reg = 0; - cmd_reg = bitfield_field32_write(cmd_reg, SPI_HOST_COMMAND_LEN_FIELD, command.len); - cmd_reg = bitfield_bit32_write(cmd_reg, SPI_HOST_COMMAND_CSAAT_BIT, command.csaat); - cmd_reg = bitfield_field32_write(cmd_reg, SPI_HOST_COMMAND_SPEED_FIELD, command.speed); - cmd_reg = bitfield_field32_write(cmd_reg, SPI_HOST_COMMAND_DIRECTION_FIELD, command.direction); + cmd_reg = bitfield_write(cmd_reg, SPI_HOST_COMMAND_LEN_MASK, + SPI_HOST_COMMAND_LEN_OFFSET, command.len); + cmd_reg = bitfield_write(cmd_reg, BIT_MASK_1, + SPI_HOST_COMMAND_CSAAT_BIT, command.csaat); + cmd_reg = bitfield_write(cmd_reg, SPI_HOST_COMMAND_SPEED_MASK, + SPI_HOST_COMMAND_SPEED_OFFSET, command.speed); + cmd_reg = bitfield_write(cmd_reg, SPI_HOST_COMMAND_DIRECTION_MASK, + SPI_HOST_COMMAND_DIRECTION_OFFSET, command.direction); return cmd_reg; } /** - * @brief Attends the plic interrupt. + * @brief Attends the plic interrupt for SPI Host 2. + */ +void handler_irq_spi(uint32_t id); + +/** + * @brief Attends the fic interrupt for SPI Host. */ -__attribute__((weak, optimize("O0"))) void handler_irq_spi(uint32_t id); +void fic_irq_spi(void); + +/** + * @brief Attends the fic interrupt for SPI Flash. + */ +void fic_irq_spi_flash(void); + +/** + * @brief weak implementation of the function that gets called when an event + * interrupt is triggered on the SPI Flash. + * Replace with your own implementation. + */ +void spi_intr_handler_event_flash(spi_event_e events); + +/** + * @brief weak implementation of the function that gets called when an error + * interrupt is triggered on the SPI Flash. + * Replace with your own implementation. + */ +void spi_intr_handler_error_flash(spi_error_e errors); + +/** + * @brief weak implementation of the function that gets called when an event + * interrupt is triggered on the SPI Host. + * Replace with your own implementation. + */ +void spi_intr_handler_event_host(spi_event_e events); + +/** + * @brief weak implementation of the function that gets called when an error + * interrupt is triggered on the SPI Host. + * Replace with your own implementation. + */ +void spi_intr_handler_error_host(spi_error_e errors); + +/** + * @brief weak implementation of the function that gets called when an event + * interrupt is triggered on the SPI Host 2. + * Replace with your own implementation. + */ +void spi_intr_handler_event_host2(spi_event_e events); + +/** + * @brief weak implementation of the function that gets called when an error + * interrupt is triggered on the SPI Host 2. + * Replace with your own implementation. + */ +void spi_intr_handler_error_host2(spi_error_e errors); #ifdef __cplusplus @@ -353,3 +1016,9 @@ __attribute__((weak, optimize("O0"))) void handler_irq_spi(uint32_t id); #endif #endif // _DRIVERS_SPI_HOST_H_ + +/****************************************************************************/ +/** **/ +/** EOF **/ +/** **/ +/****************************************************************************/ \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/uart/uart.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/uart/uart.c index 08a32fa7..fef349c4 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/uart/uart.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/drivers/uart/uart.c @@ -4,12 +4,14 @@ // Modified version for core-v-mini-mcu // original at: https://github.com/lowRISC/opentitan/blob/master/sw/ - +#ifdef __cplusplus +extern "C" { +#endif #include "uart.h" #include #include - +#include "assert.h" #include "bitfield.h" #include "mmio.h" #include "error.h" @@ -17,8 +19,12 @@ #include "uart_regs.h" // Generated. #define NCO_WIDTH 16 -_Static_assert((1UL << NCO_WIDTH) - 1 == UART_CTRL_NCO_MASK, - "Bad value for NCO_WIDTH"); + +//#ifdef __cplusplus +static_assert((1UL << NCO_WIDTH) - 1 == UART_CTRL_NCO_MASK, "Bad value for NCO_WIDTH"); +//#else +static_assert((1UL << NCO_WIDTH) - 1 == UART_CTRL_NCO_MASK, "Bad value for NCO_WIDTH"); +//#endif static void uart_reset(const uart_t *uart) { mmio_region_write32(uart->base_addr, UART_CTRL_REG_OFFSET, 0u); @@ -147,4 +153,8 @@ size_t uart_sink(void *uart, const char *data, size_t len) { __attribute__((weak, optimize("O0"))) void handler_irq_uart(uint32_t id) { // Replace this function with a non-weak implementation -} \ No newline at end of file +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.c new file mode 100644 index 00000000..326fd963 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.c @@ -0,0 +1,37 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#include "core_v_mini_mcu.h" +#include + +//heep functions prototypes +uint32_t * heep_get_flash_address_offset(uint32_t* data_address_lma); +void heep_init_lfsr(); +uint32_t heep_rand_lfsr(); + +// this translates the logical address of the FLASH relative to 0 instead of FLASH_MEM_START_ADDRESS, as used by the BSP +uint32_t * heep_get_flash_address_offset(uint32_t* data_address_lma){ + +#ifdef ON_CHIP + // no need to translate as FLASH is not memory mapped + return data_address_lma; +#else + uint32_t* data_address_adjusted = (uint32_t*) ((uint32_t)(data_address_lma) - FLASH_MEM_START_ADDRESS); + return data_address_adjusted; +#endif + +} + +//get random values +uint32_t lfsr; + +void heep_init_lfsr() { + lfsr = (uint32_t)0xAABBCCDD; +} + +uint32_t heep_rand_lfsr() { + uint32_t bit = (lfsr ^ (lfsr >> 10) ^ (lfsr >> 11) ^ (lfsr >> 12)) & 1; + lfsr = (lfsr >> 1) | (bit << 31); + return lfsr; +} diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.h.tpl b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.h.tpl index 1491a6ed..aa4d3b79 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.h.tpl +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu.h.tpl @@ -9,7 +9,16 @@ extern "C" { #endif // __cplusplus -#define MEMORY_BANKS ${ram_numbanks} +#define MEMORY_BANKS ${xheep.ram_numbanks()} +% if xheep.has_il_ram(): +#define HAS_MEMORY_BANKS_IL +% endif + +% for bank in xheep.iter_ram_banks(): +#define RAM${bank.name()}_START_ADDRESS 0x${f'{bank.start_address():08X}'} +#define RAM${bank.name()}_END_ADDRESS 0x${f'{bank.end_address():08X}'} +% endfor + #define EXTERNAL_DOMAINS ${external_domains} @@ -26,9 +35,14 @@ extern "C" { #define ${name.upper()}_START_ADDRESS (AO_PERIPHERAL_START_ADDRESS + 0x${peripheral['offset']}) #define ${name.upper()}_SIZE 0x${peripheral['length']} #define ${name.upper()}_END_ADDRESS (${name.upper()}_START_ADDRESS + ${name.upper()}_SIZE) +#define ${name.upper()}_IDX ${loop.index} %endfor +#define DMA_CH_NUM ${dma_ch_count} +#define DMA_CH_SIZE 0x${dma_ch_size} +#define DMA_NUM_MASTER_PORTS ${num_dma_master_ports} + //switch-on/off peripherals #define PERIPHERAL_START_ADDRESS 0x${peripheral_start_address} #define PERIPHERAL_SIZE 0x${peripheral_size_address} @@ -38,6 +52,7 @@ extern "C" { #define ${name.upper()}_START_ADDRESS (PERIPHERAL_START_ADDRESS + 0x${peripheral['offset']}) #define ${name.upper()}_SIZE 0x${peripheral['length']} #define ${name.upper()}_END_ADDRESS (${name.upper()}_START_ADDRESS + ${name.upper()}_SIZE) +#define ${name.upper()}_IDX ${loop.index + len(ao_peripherals.items())} % if "yes" in peripheral['is_included']: #define ${name.upper()}_IS_INCLUDED @@ -67,6 +82,7 @@ extern "C" { #define GPIO_AO_DOMAIN_LIMIT 8 + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu_memory.h.tpl b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu_memory.h.tpl new file mode 100644 index 00000000..02a99da5 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/core_v_mini_mcu_memory.h.tpl @@ -0,0 +1,29 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#ifndef COREV_MINI_MCU_MEMORY_H_ +#define COREV_MINI_MCU_MEMORY_H_ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#include "core_v_mini_mcu.h" + +typedef struct memory_address { + unsigned int start; + unsigned int end; +} xheep_memory_address_t; + +xheep_memory_address_t xheep_memory_regions[MEMORY_BANKS] = { +% for bank in xheep.iter_ram_banks(): + {.start = RAM${bank.name()}_START_ADDRESS, .end = RAM${bank.name()}_END_ADDRESS}, +% endfor +}; + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // COREV_MINI_MCU_MEMORY_H_ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/handler.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/handler.c index 8ee1a0d8..564abdcd 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/handler.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/handler.c @@ -2,10 +2,14 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 -#include "handler.h" +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus +#include "handler.h" #include "csr.h" #include "stdasm.h" +#include ' /** * Return value of mtval @@ -110,3 +114,7 @@ __attribute__((weak)) void handler_ecall(void) { while (1) { } } +#ifdef __cplusplus +} +#endif // __cplusplus + diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/handler.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/handler.h index 8f987be7..1aaacc3b 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/handler.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/handler.h @@ -5,6 +5,10 @@ #ifndef OPENTITAN_SW_DEVICE_LIB_HANDLER_H_ #define OPENTITAN_SW_DEVICE_LIB_HANDLER_H_ +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + typedef enum exc_id { kInstMisa = 0, kInstAccFault = 1, @@ -126,4 +130,9 @@ void handler_lsu_fault(void); */ void handler_ecall(void); + +#ifdef __cplusplus +} +#endif // __cplusplus + #endif // OPENTITAN_SW_DEVICE_LIB_HANDLER_H_ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/hart.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/hart.h index c2e885c0..64e4d090 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/hart.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/hart.h @@ -5,6 +5,11 @@ #ifndef OPENTITAN_SW_DEVICE_LIB_RUNTIME_HART_H_ #define OPENTITAN_SW_DEVICE_LIB_RUNTIME_HART_H_ +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + #include #include @@ -22,6 +27,11 @@ * * This function may behave as if it is a no-op. */ -inline void wait_for_interrupt(void) { asm volatile("wfi"); } +static inline void wait_for_interrupt(void) { asm volatile("wfi"); } + + +#ifdef __cplusplus +} +#endif // __cplusplus #endif // OPENTITAN_SW_DEVICE_LIB_RUNTIME_HART_H_ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/heap.cpp b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/heap.cpp new file mode 100644 index 00000000..d4c8fd8b --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/heap.cpp @@ -0,0 +1,60 @@ +/* +* Copyright 2024 Anestis Athanasiadis +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +//Additional heap functions required for C++ + +#include +#include + +void* operator new(size_t size) noexcept +{ + return malloc(size); +} + +void operator delete(void *p) noexcept +{ + free(p); +} + +void* operator new[](size_t size) noexcept +{ + return operator new(size); // Same as regular new +} + +void operator delete[](void *p) noexcept +{ + operator delete(p); // Same as regular delete +} + +void* operator new(size_t size, std::nothrow_t) noexcept +{ + return operator new(size); // Same as regular new +} + +void operator delete(void *p, std::nothrow_t) noexcept +{ + operator delete(p); // Same as regular delete +} + +void* operator new[](size_t size, std::nothrow_t) noexcept +{ + return operator new(size); // Same as regular new +} + +void operator delete[](void *p, std::nothrow_t) noexcept +{ + operator delete(p); // Same as regular delete +} \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/init.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/init.c index cfbf206a..ad29fca6 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/init.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/init.c @@ -1,7 +1,16 @@ // Copyright 2022 OpenHW Group // Solderpad Hardware License, Version 2.1, see LICENSE.md for details. // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#ifdef __cplusplus +extern "C" { +#endif + int init() { return 0; -} \ No newline at end of file +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/syscalls.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/syscalls.c index 05dd28f9..8e516af0 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/syscalls.c +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/syscalls.c @@ -17,34 +17,48 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#ifdef __cplusplus +extern "C" { +#endif + #include +#include +#include #include #include +#include #include #include "uart.h" #include "soc_ctrl.h" #include "core_v_mini_mcu.h" #include "error.h" #include "x-heep.h" +#include #undef errno extern int errno; #define STDOUT_FILENO 1 -/* It turns out that older newlib versions use different symbol names which goes - * against newlib recommendations. Anyway this is fixed in later version. - */ -#if __NEWLIB__ <= 2 && __NEWLIB_MINOR__ <= 5 -# define _sbrk sbrk -# define _write write -# define _close close -# define _lseek lseek -# define _read read -# define _fstat fstat -# define _isatty isatty +#ifndef _LIBC +/* Provide prototypes for most of the _ names that are + provided in newlib for some compilers. */ +int _close (int __fildes); +pid_t _fork (void); +pid_t _getpid (void); +int _isatty (int __fildes); +int _link (const char *__path1, const char *__path2); +_off_t _lseek (int __fildes, _off_t __offset, int __whence); +ssize_t _read (int __fd, void *__buf, size_t __nbyte); +void * _sbrk (ptrdiff_t __incr); +int _brk(void *addr); +int _unlink (const char *__path); +ssize_t _write (int __fd, const void *__buf, size_t __nbyte); +int _execve (const char *__path, char * const __argv[], char * const __envp[]); +int _kill (pid_t pid, int sig); #endif + void unimplemented_syscall() { const char *p = "Unimplemented system call called!\n"; @@ -108,7 +122,7 @@ int _faccessat(int dirfd, const char *file, int mode, int flags) return -1; } -int _fork(void) +pid_t _fork(void) { errno = EAGAIN; return -1; @@ -140,7 +154,7 @@ char *_getcwd(char *buf, size_t size) return NULL; } -int _getpid() +pid_t _getpid() { return 1; } @@ -156,7 +170,7 @@ int _isatty(int file) return (file == STDOUT_FILENO); } -int _kill(int pid, int sig) +int _kill(pid_t pid, int sig) { errno = EINVAL; return -1; @@ -251,9 +265,13 @@ ssize_t _write(int file, const void *ptr, size_t len) errno = ENOSYS; return -1; } - return uart_write(&uart,(uint8_t *)ptr,len); +} + +_ssize_t _write_r(struct _reent *ptr, int fd, const void *buf, size_t cnt) +{ + return _write(fd,buf,cnt); } extern char __heap_start[]; @@ -262,8 +280,12 @@ static char *brk = __heap_start; int _brk(void *addr) { - brk = addr; - return 0; + if (addr >= (void *)__heap_start && addr <= (void *)__heap_end) { + brk = addr; + return 0; + } else { + return -1; + } } void *_sbrk(ptrdiff_t incr) @@ -271,13 +293,27 @@ void *_sbrk(ptrdiff_t incr) char *old_brk = brk; if (__heap_start == __heap_end) { - return NULL; + return NULL; } - if ((brk += incr) < __heap_end) { + if (brk + incr < __heap_end && brk + incr >= __heap_start) { brk += incr; } else { - brk = __heap_end; + return (void *)-1; } return old_brk; } + +int raise(int sig) +{ + return _kill(_getpid(), sig); +} + +void abort(void) +{ + _exit(-1); +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/syscalls_cpp.cpp b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/syscalls_cpp.cpp new file mode 100644 index 00000000..3385fcb5 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/runtime/syscalls_cpp.cpp @@ -0,0 +1,39 @@ +/* +* Copyright 2024 Anestis Athanasiadis +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +// This function is required to register the call for the destructor +// of static object +extern "C" int __aeabi_atexit(void *object, void (*destructor)(void *),void *dso_handle) +{ + static_cast(object); + static_cast(destructor); + static_cast(dso_handle); + return 0; +} + +void operator delete(void *,unsigned int) +{ +} + +// Required when there is pure virtual function +extern "C" void __cxa_pure_virtual() +{ + while (true) {} +} + + +void *__dso_handle = 0; \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/dma/dma_sdk.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/dma/dma_sdk.c new file mode 100644 index 00000000..8457086d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/dma/dma_sdk.c @@ -0,0 +1,100 @@ +// Copyright 2024 EPFL and Politecnico di Torino. +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// File: dma_sdk.c +// Author: Michele Caon, Luigi Giuffrida +// Date: 19/06/2023 +// Description: Utility functions for DMA peripheral. + +#include "dma_sdk.h" +#include "dma.h" +#include "hart.h" +#include "handler.h" +#include "fast_intr_ctrl.h" +#include "core_v_mini_mcu.h" +#include "csr.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /******************************/ + /* ---- GLOBAL VARIABLES ---- */ + /******************************/ + + volatile uint8_t dma_sdk_intr_flag; + +#define DMA_REGISTER_SIZE_BYTES sizeof(int) +#define DMA_SELECTION_OFFSET_START 0 + +/* Mask for direct register operations */ +#define DMA_CSR_REG_MIE_MASK ((1 << 19) | (1 << 11)) + + /**********************************/ + /* ---- FUNCTION DEFINITIONS ---- */ + /**********************************/ + + static __attribute__((always_inline)) void dma_start(dma *peri, uint32_t size, dma_data_type_t src_type) + { + peri->SIZE_D1 = (uint32_t)((size) & DMA_SIZE_D1_SIZE_MASK); + } + + // Initialize the DMA + void dma_sdk_init(void) + { + dma_init(NULL); + + /* Enable global interrupts */ + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + + /* Enable fast interrupts */ + CSR_SET_BITS(CSR_REG_MIE, DMA_CSR_REG_MIE_MASK); + + return; + } + + void dma_copy(uint32_t dst_ptr, uint32_t src_ptr, uint32_t size, uint8_t channel, dma_data_type_t src_type, dma_data_type_t dst_type, uint8_t signed_data) + { + volatile dma *the_dma = dma_peri(channel); + DMA_COPY(dst_ptr, src_ptr, size, src_type, dst_type, signed_data, the_dma); + dma_start(the_dma, size, src_type); + DMA_WAIT(channel); + return; + } + + void dma_fill(uint32_t dst_ptr, uint32_t value_ptr, uint32_t size, uint8_t channel, dma_data_type_t src_type, dma_data_type_t dst_type, uint8_t signed_data) + { + volatile dma *the_dma = dma_peri(channel); + DMA_FILL(dst_ptr, value_ptr, size, src_type, dst_type, signed_data, the_dma); + dma_start(the_dma, size, src_type); + DMA_WAIT(channel); + return; + } + + void __attribute__ ((noinline)) dma_copy_async(uint32_t dst_ptr, uint32_t src_ptr, uint32_t size, uint8_t channel, dma_data_type_t src_type, dma_data_type_t dst_type, uint8_t signed_data) + { + volatile dma *the_dma = dma_peri(channel); + DMA_COPY(dst_ptr, src_ptr, size, src_type, dst_type, signed_data, the_dma); + dma_start(the_dma, size, src_type); + return; + } + + void __attribute__ ((noinline)) dma_fill_async(uint32_t dst_ptr, uint32_t value_ptr, uint32_t size, uint8_t channel, dma_data_type_t src_type, dma_data_type_t dst_type, uint8_t signed_data) + { + volatile dma *the_dma = dma_peri(channel); + DMA_FILL(dst_ptr, value_ptr, size, src_type, dst_type, signed_data, the_dma); + dma_start(the_dma, size, src_type); + return; + } + + void __attribute__ ((noinline)) dma_wait(uint8_t channel) + { + DMA_WAIT(channel); + return; + } + +#ifdef __cplusplus +} +#endif diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/dma/dma_sdk.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/dma/dma_sdk.h new file mode 100644 index 00000000..726024e0 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/dma/dma_sdk.h @@ -0,0 +1,108 @@ +// Copyright 2024 EPFL and Politecnico di Torino. +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// File: dma_sdk.h +// Author: Michele Caon, Luigi Giuffrida +// Date: 19/06/2023 +// Description: DMA utility functions + +#ifndef DMA_SDK_H_ +#define DMA_SDK_H_ + +#include +#include // for size_t +#include "csr.h" + +#include "dma.h" +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +#define INCREMENT(TYPE) ((TYPE == DMA_DATA_TYPE_BYTE) ? 1 : (TYPE == DMA_DATA_TYPE_HALF_WORD) ? 2 \ + : 4) + +#define DMA_COPY(DST, SRC, SIZE, SRC_TYPE, DST_TYPE, SIGNED, DMA_PERI) \ + DMA_PERI->INTERRUPT_EN = (uint32_t)0x1; \ + DMA_PERI->SRC_PTR = (uint32_t)SRC; \ + DMA_PERI->DST_PTR = (uint32_t)DST; \ + DMA_PERI->SRC_PTR_INC_D1 = (uint32_t)(INCREMENT(SRC_TYPE) & DMA_SRC_PTR_INC_D1_INC_MASK); \ + DMA_PERI->DST_PTR_INC_D1 = (uint32_t)(INCREMENT(DST_TYPE) & DMA_DST_PTR_INC_D1_INC_MASK); \ + DMA_PERI->MODE = (uint32_t)(DMA_TRANS_MODE_SINGLE & DMA_MODE_MODE_MASK); \ + DMA_PERI->SRC_DATA_TYPE = (uint32_t)(SRC_TYPE & DMA_SRC_DATA_TYPE_DATA_TYPE_MASK); \ + DMA_PERI->DST_DATA_TYPE = (uint32_t)(DST_TYPE & DMA_DST_DATA_TYPE_DATA_TYPE_MASK); \ + DMA_PERI->SIGN_EXT = (uint32_t)SIGNED; + +#define DMA_FILL(DST, VALUE_PTR, SIZE, SRC_TYPE, DST_TYPE, SIGNED, DMA_PERI) \ + DMA_PERI->INTERRUPT_EN = (uint32_t)0x1; \ + DMA_PERI->SRC_PTR = (uint32_t)VALUE_PTR; \ + DMA_PERI->DST_PTR = (uint32_t)DST; \ + DMA_PERI->SRC_PTR_INC_D1 = (uint32_t)0; \ + DMA_PERI->DST_PTR_INC_D1 = (uint32_t)(INCREMENT(DST_TYPE) & DMA_DST_PTR_INC_D1_INC_MASK); \ + DMA_PERI->MODE = (uint32_t)(DMA_TRANS_MODE_SINGLE & DMA_MODE_MODE_MASK); \ + DMA_PERI->SRC_DATA_TYPE = (uint32_t)(SRC_TYPE & DMA_SRC_DATA_TYPE_DATA_TYPE_MASK); \ + DMA_PERI->DST_DATA_TYPE = (uint32_t)(DST_TYPE & DMA_DST_DATA_TYPE_DATA_TYPE_MASK); \ + DMA_PERI->SIGN_EXT = (uint32_t)SIGNED; + +#define DMA_WAIT(CH) \ + while (!dma_is_ready(CH)) \ + { \ + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); \ + if (dma_is_ready(CH) == 0) \ + { \ + wait_for_interrupt(); \ + } \ + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); \ + } + + /********************************/ + /* ---- EXPORTED VARIABLES ---- */ + /********************************/ + + extern volatile uint8_t dma_sdk_intr_flag; + + /** + * @brief Initializes the DMA SDK. + * + * This function initializes the DMA SDK and prepares it for use. + */ + void __attribute__((noinline)) dma_sdk_init(void); + + /** + * @brief Copies data from source to destination using DMA. + * + * @param dst_ptr Pointer to the destination memory location. + * @param src_ptr Pointer to the source memory location. + * @param size Size of the data to be copied in bytes. + * @param channel DMA channel to be used for the transfer. + * @param src_type Source variable type (byte, half-word, word). + * @param dst_type Destination variable type (byte, half-word, word). + * @param signed_data Indicates whether the data is signed or unsigned. + */ + void __attribute__((noinline)) dma_copy(uint32_t dst_ptr, uint32_t src_ptr, uint32_t size, uint8_t channel, dma_data_type_t src_type, dma_data_type_t dst_type, uint8_t signed_data); + + /** + * @brief Fills a memory region with a specified value using DMA. + * + * @param dst_ptr Pointer to the destination memory location. + * @param value_ptr Pointer to the value to be filled. + * @param size Size of the memory region to be filled in bytes. + * @param channel DMA channel to be used for the transfer. + * @param src_type Source variable type (byte, half-word, word). + * @param dst_type Destination variable type (byte, half-word, word). + * @param signed_data Indicates whether the data is signed or unsigned. + */ + void __attribute__((noinline)) dma_fill(uint32_t dst_ptr, uint32_t value_ptr, uint32_t size, uint8_t channel, dma_data_type_t src_type, dma_data_type_t dst_type, uint8_t signed_data); + + void __attribute__((noinline)) dma_copy_async(uint32_t dst_ptr, uint32_t src_ptr, uint32_t size, uint8_t channel, dma_data_type_t src_type, dma_data_type_t dst_type, uint8_t signed_data); + + void __attribute__((noinline)) dma_fill_async(uint32_t dst_ptr, uint32_t value_ptr, uint32_t size, uint8_t channel, dma_data_type_t src_type, dma_data_type_t dst_type, uint8_t signed_data); + + void __attribute__((noinline)) dma_wait(uint8_t channel); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* DMA_SDK_H_ */ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/spi/spi_sdk.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/spi/spi_sdk.c new file mode 100644 index 00000000..8c8a6a16 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/spi/spi_sdk.c @@ -0,0 +1,1127 @@ +/* + ******************* +******************************* C SOURCE FILE ***************************** +** ******************* +** +** project : X-HEEP +** filename : spi_sdk.c +** version : 1 +** date : 18/04/24 +** +*************************************************************************** +** +** Copyright (c) EPFL contributors. +** All rights reserved. +** +*************************************************************************** +*/ + +/***************************************************************************/ +/***************************************************************************/ +/** +* @file spi_sdk.c +* @date 18/04/24 +* @author Llorenç Muela +* @brief The Serial Peripheral Interface (SPI) SDK to set up and use the +* SPI peripheral +*/ + +/****************************************************************************/ +/** **/ +/** MODULES USED **/ +/** **/ +/****************************************************************************/ + +#include "spi_sdk.h" +#include "spi_host.h" +#include "spi_host_regs.h" +#include "soc_ctrl_structs.h" +#include "bitfield.h" +#include "csr.h" + +/****************************************************************************/ +/** **/ +/** DEFINITIONS AND MACROS **/ +/** **/ +/****************************************************************************/ + +#define DATA_MODE_CPHA_OFFS 0 +#define DATA_MODE_CPOL_OFFS 1 + +#define SPI_MAX_IDX 2 +#define SPI_IDX_INVALID(idx) idx > SPI_MAX_IDX + +#define SYS_FREQ (soc_ctrl_peri->SYSTEM_FREQUENCY_HZ) +#define SPI_MIN_FREQ (SYS_FREQ / (2 * 65535 + 2)) // 65535 = 2^16 - 1 + +// Maximum length of data (in bytes) for a command segment (currently 2^24) +#define MAX_COMMAND_LENGTH SPI_HOST_COMMAND_LEN_MASK +#define BYTES_PER_WORD 4 +// Convert byte count to word count +#define LEN_WORDS(bytes) ((bytes / BYTES_PER_WORD) + (bytes % BYTES_PER_WORD ? 1 : 0)) + +// Bitmasks for speed and direction relative to spi_mode_e +#define DIR_SPD_MASK 0b11 +#define DIR_INDEX 0 +#define SPD_INDEX 2 + +#define TRIGGERING_EVENTS (SPI_EVENT_IDLE | SPI_EVENT_READY | SPI_EVENT_TXWM | SPI_EVENT_RXWM) + +// The standard watermark for all transactions (seems reasonable) +#define TXWM_DEFAULT (SPI_HOST_PARAM_TX_DEPTH / 4) // Arbirarily chosen +#define RXWM_DEFAULT (SPI_HOST_PARAM_RX_DEPTH - 12) // Arbirarily chosen + +#define NULL_CALLBACKS (spi_callbacks_t) {NULL, NULL, NULL, NULL} + +// SPI peripheral busy checks +#define SPI_BUSY(peri) (peri.state == SPI_STATE_BUSY) +#define SPI_NOT_BUSY(peri) (peri.state != SPI_STATE_BUSY) + +// Check command length validity +#define SPI_INVALID_LEN(len) (len == 0 || len > MAX_COMMAND_LENGTH) + +/** + * @brief Allows easy TX Transaction instantiation. + */ +#define SPI_TXN_TX(segment, txbuff, len) (spi_transaction_t) { \ + .segments = segment, \ + .seglen = 1, \ + .txbuffer = txbuff, \ + .txlen = len, \ + .rxbuffer = NULL, \ + .rxlen = 0 \ +} + +/** + * @brief Allows easy RX Transaction instantiation. + */ +#define SPI_TXN_RX(segment, rxbuff, len) (spi_transaction_t) { \ + .segments = segment, \ + .seglen = 1, \ + .txbuffer = NULL, \ + .txlen = 0, \ + .rxbuffer = rxbuff, \ + .rxlen = len \ +} + +/** + * @brief Allows easy BIDIR Transaction instantiation. + */ +#define SPI_TXN_BIDIR(segment, txbuff, rxbuff, len) (spi_transaction_t) { \ + .segments = segment, \ + .seglen = 1, \ + .txbuffer = txbuff, \ + .txlen = len, \ + .rxbuffer = rxbuff, \ + .rxlen = len \ +} + +/** + * @brief Allows easy generic Transaction instantiation. + */ +#define SPI_TXN(segment, seg_len, txbuff, rxbuff) (spi_transaction_t) { \ + .segments = segment, \ + .seglen = seg_len, \ + .txbuffer = txbuff, \ + .txlen = 0, \ + .rxbuffer = rxbuff, \ + .rxlen = 0 \ +} + +/****************************************************************************/ +/** **/ +/** TYPEDEFS AND STRUCTURES **/ +/** **/ +/****************************************************************************/ + +/** + * @brief Transaction Structure. Holds all information relevant to a transaction. + */ +typedef struct { + const spi_segment_t* segments; // Pointer to array/buffer of command segments + uint8_t seglen; // Size of the command segents array/buffer + const uint32_t* txbuffer; // Pointer to array/buffer of TX data + uint32_t txlen; // Size of TX array/buffer + uint32_t* rxbuffer; // Pointer to array/buffer for RX data + uint32_t rxlen; // Size of RX array/buffer +} spi_transaction_t; + +/** + * @brief Structure to hold all relative information about a particular peripheral. + * peripherals variable in this file holds an instance of this structure for every + * SPI peripheral defined in the HAL. This is in order to store relevant information + * of the peripheral current status, transaction info, and peripheral instance. + */ +typedef struct { + spi_host_t* instance; // Instance of peripheral defined in HAL + uint8_t txwm; // TX watermark for this particular peripheral + uint8_t rxwm; // RX watermark for this particular peripheral + uint32_t last_id; // ID of last used spi_t to avoid resetting slave + uint32_t timeout; // Timeout for blocking transactions in ms + spi_state_e state; // Current state of device + spi_transaction_t txn; // Current transaction being processed + uint32_t scnt; // Counter to track segment to process + uint32_t txcnt; // Counter to track TX word being processed + uint32_t rxcnt; // Counter to track RX word being processed + spi_callbacks_t callbacks; // Callback functions to call +} spi_peripheral_t; + +/****************************************************************************/ +/** **/ +/* PROTOTYPES OF LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + +/** + * @brief Validates the idx and init variables of spi_t. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @return spi_codes_e information about error. SPI_CODE_OK if all went well + */ +spi_codes_e spi_check_valid(spi_t* spi); + +/** + * @brief Validates slave csid. + * + * @param slave to validate + * @return spi_codes_e information about error. SPI_CODE_OK if all went well + */ +spi_codes_e spi_validate_slave(spi_slave_t slave); + +/** + * @brief Sets the slave configuration options and the slave CSID. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @return spi_codes_e information about error. SPI_CODE_OK if all went well + */ +spi_codes_e spi_set_slave(spi_t* spi); + +/** + * @brief Validation and configuration of device prior to any transaction. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @return spi_codes_e information about error. SPI_CODE_OK if all went well + */ +spi_codes_e spi_prepare_transfer(spi_t* spi); + +/** + * @brief Computes the true frequency that will be set based on the user desired + * frequency. + * + * @param freq Frequency defined by user + * @return uint32_t True frequency after determining the SPI clk divider + */ +uint32_t spi_true_slave_freq(uint32_t freq); + +/** + * @brief Validates all the provided segments and counts the number of words for + * TX and RX buffers. + * + * @param segments An array of segments to validate + * @param segments_len The length of the array of segments + * @param tx_count Variable to store the counted TX words + * @param rx_count Variable to store the counted RX words + * @return true if all segments are valid + * @return false otherwise + */ +bool spi_validate_segments(const spi_segment_t* segments, uint32_t segments_len, + uint32_t* tx_count, uint32_t* rx_count); + +/** + * @brief Fills the TX FIFO until no more space or no more data. + * + * @param peri Pointer to the spi_peripheral_t instance with the relevant data + * @return true if any word has been written to TX fifo + * @return false otherwise + */ +bool spi_fill_tx(spi_peripheral_t* peri); + +/** + * @brief Empties the RX FIFO. + * + * @param peri Pointer to the spi_peripheral_t instance with the relevant data + * @return true if any word has been read to RX fifo + * @return false otherwise + */ +bool spi_empty_rx(spi_peripheral_t* peri); + +/** + * @brief Proceeds to initiate transaction once all tests passed. + * + * @param peri Pointer to the relevant spi_peripheral_t instance + * @param spi Pointer to the spi_t that requested transaction + * @param txn Transaction data (segments, buffers, lengths) + * @param done_cb The callback to be called once transaction is over + * @param error_cb The callback to be called if a Hardware error occurs + */ +void spi_launch(spi_peripheral_t* peri, spi_t* spi, spi_transaction_t txn, + spi_callbacks_t callbacks); + +/** + * @brief Issues a command segment and increments counter (post inc.). + * Determines value of CSAAT bit based on if it is last segment of transaction + * or not. + * + * @param peri Pointer to the relevant spi_peripheral_t instance + */ +void spi_wait_transaction_done(spi_peripheral_t* peri); + +/** + * @brief Issues a command segment and increments counter (post inc.). + * Determines value of CSAAT bit based on if it is last segment of transaction + * or not. + * + * @param peri Pointer to the relevant spi_peripheral_t instance + */ +void spi_issue_next_seg(spi_peripheral_t* peri); + +/** + * @brief Resets the entire peripheral, hardware included + * + * @param peri Pointer to the relevant spi_peripheral_t instance + */ +void spi_reset_peri(spi_peripheral_t* peri); + +/** + * @brief Resets the transaction-related variables of the spi_peripheral_t to + * their initial values + * + * @param peri Pointer to the relevant spi_peripheral_t instance + */ +void spi_reset_transaction(spi_peripheral_t* peri); + +/** + * @brief Function that gets called on each Event Interrupt. Handles all the logic + * of a transacton since all transactions use the interrupt. + * + * @param peri Pointer to the relevant spi_peripheral_t instance + * @param events Variable holding all the current events + */ +void spi_event_handler(spi_peripheral_t* peri, spi_event_e events); + +/** + * @brief Function that handles the harware errors. It is responsible of aborting + * any current transaction, resetting variables and calling the error callback if any. + * + * @param peri Pointer to the relevant spi_peripheral_t instance + * @param error Variable holding all the errors that occured + */ +void spi_error_handler(spi_peripheral_t* peri, spi_error_e error); + +/****************************************************************************/ +/** **/ +/** EXPORTED VARIABLES **/ +/** **/ +/****************************************************************************/ + +/****************************************************************************/ +/** **/ +/* GLOBAL VARIABLES */ +/** **/ +/****************************************************************************/ + +/** + * @brief Global SDK spi_t instance counter to assign each instance a unique ID. + */ +static uint32_t global_id = 0; + +/** + * @brief Static variable representing each SPI peripheral (FLASH, HOST, HOST2) + * We can have infinitely many spi_t variables but all reference one of these + * spi_peripheral_t. Each variable here holds all the relevant information about + * the current transaction the peripheral is executing. + */ +static volatile spi_peripheral_t peripherals[] = { + (spi_peripheral_t) { + .instance = spi_flash, + .txwm = TXWM_DEFAULT, + .rxwm = RXWM_DEFAULT, + .last_id = 0, + .timeout = SPI_TIMEOUT_DEFAULT, + .state = SPI_STATE_NONE, + .txn = {0}, + .scnt = 0, + .txcnt = 0, + .rxcnt = 0, + .callbacks = {0} + }, + (spi_peripheral_t) { + .instance = spi_host1, + .txwm = TXWM_DEFAULT, + .rxwm = RXWM_DEFAULT, + .last_id = 0, + .timeout = SPI_TIMEOUT_DEFAULT, + .state = SPI_STATE_NONE, + .txn = {0}, + .scnt = 0, + .txcnt = 0, + .rxcnt = 0, + .callbacks = {0} + }, + (spi_peripheral_t) { + .instance = spi_host2, + .txwm = TXWM_DEFAULT, + .rxwm = RXWM_DEFAULT, + .last_id = 0, + .timeout = SPI_TIMEOUT_DEFAULT, + .state = SPI_STATE_NONE, + .txn = {0}, + .scnt = 0, + .txcnt = 0, + .rxcnt = 0, + .callbacks = {0} + } +}; + +/****************************************************************************/ +/** **/ +/** EXPORTED FUNCTIONS **/ +/** **/ +/****************************************************************************/ + +spi_t spi_init(spi_idx_e idx, spi_slave_t slave) +{ + // Make sure all parameters of the slave are valid. + spi_codes_e error = spi_validate_slave(slave); + // Check that the SPI peripheral identifier is valid. + if (SPI_IDX_INVALID(idx)) error |= SPI_CODE_IDX_INVAL; + // Since watermark is set here, not a good idea to allow for initialization. + // Anyways not very elegant to initialize while being busy... right? + if (SPI_BUSY(peripherals[idx])) error |= SPI_CODE_IS_BUSY; + if (error) + return (spi_t) { + .idx = UINT32_MAX, + .id = 0, + .init = false, + .slave = (spi_slave_t) {0} + }; + // Enable SPI peripheral. We do not check return value since we know here that + // it will never return an error. + spi_set_enable(peripherals[idx].instance, true); + spi_output_enable(peripherals[idx].instance, true); + // Enable all error interrupts so that the SPI peripheral doesn't get stuck if + // there is an error. And we don't check return value since we know it's error free. + spi_set_errors_enabled(peripherals[idx].instance, SPI_ERROR_IRQALL, true); + spi_enable_error_intr(peripherals[idx].instance, true); + // Set the watermarks for the specific peripheral + spi_set_tx_watermark(peripherals[idx].instance, peripherals[idx].txwm); + spi_set_rx_watermark(peripherals[idx].instance, peripherals[idx].rxwm); + // Just set a state so user can see it has been initialized somewhen. + peripherals[idx].state = SPI_STATE_INIT; + // Set the true frequency at which the SCK will be for that particular slave + // so the user can know the real frequency. + slave.freq = spi_true_slave_freq(slave.freq); + return (spi_t) { + .idx = idx, + .id = ++global_id, // Pre-increment because id 0 defined as invalid + .init = true, + .slave = slave + }; +} + +void spi_deinit(spi_t* spi) +{ + // Set all values to something that will prevent spi variable to be used. + spi->idx = UINT32_MAX; + spi->id = 0; + spi->init = false; + spi->slave = (spi_slave_t) {0}; +} + +spi_codes_e spi_reset(spi_t* spi) +{ + spi_codes_e error = spi_check_valid(spi); + if (error) return error; + // Reset entire peripheral + spi_reset_peri(&peripherals[spi->idx]); + + return SPI_CODE_OK; +} + +spi_codes_e spi_set_txwm(spi_t* spi, uint8_t watermark) +{ + spi_codes_e error = spi_check_valid(spi); + if (error) return error; + // Do not change watermark if SPI is busy + if (SPI_BUSY(peripherals[spi->idx])) return SPI_CODE_IS_BUSY; + // Set the new value at hardware level + if (spi_set_tx_watermark(peripherals[spi->idx].instance, watermark)) + return SPI_CODE_WM_EXCEEDS; + // Store the watermark if previous operation succeeded + peripherals[spi->idx].txwm = watermark; + + return SPI_CODE_OK; +} + +spi_codes_e spi_get_txwm(spi_t* spi, uint8_t* watermark) +{ + spi_codes_e error = spi_check_valid(spi); + if (error) return error; + + *watermark = peripherals[spi->idx].txwm; + + return SPI_CODE_OK; +} + +spi_codes_e spi_set_rxwm(spi_t* spi, uint8_t watermark) +{ + spi_codes_e error = spi_check_valid(spi); + if (error) return error; + // Do not change watermark if SPI is busy + if (SPI_BUSY(peripherals[spi->idx])) return SPI_CODE_IS_BUSY; + // Set the new value at hardware level + if (spi_set_rx_watermark(peripherals[spi->idx].instance, watermark)) + return SPI_CODE_WM_EXCEEDS; + // Store the watermark if previous operation succeeded + peripherals[spi->idx].rxwm = watermark; + + return SPI_CODE_OK; +} + +spi_codes_e spi_get_rxwm(spi_t* spi, uint8_t* watermark) +{ + spi_codes_e error = spi_check_valid(spi); + if (error) return error; + + *watermark = peripherals[spi->idx].rxwm; + + return SPI_CODE_OK; +} + +spi_codes_e spi_set_timeout(spi_t* spi, uint32_t timeout) +{ + spi_codes_e error = spi_check_valid(spi); + if (error) return error; + + peripherals[spi->idx].timeout = timeout; + + return SPI_CODE_OK; +} + +spi_codes_e spi_get_timeout(spi_t* spi, uint32_t* timeout) +{ + spi_codes_e error = spi_check_valid(spi); + if (error) return error; + + *timeout = peripherals[spi->idx].timeout; + + return SPI_CODE_OK; +} + +spi_codes_e spi_set_slave_freq(spi_t* spi, uint32_t freq) +{ + spi_codes_e error = spi_check_valid(spi); + if (error) return error; + // Save current freq and change to new freq to check validity + const uint32_t old_freq = spi->slave.freq; + spi->slave.freq = freq; + error = spi_validate_slave(spi->slave); + if (error) { + // If not valid reset the frequency and return error + spi->slave.freq = old_freq; + return error; + } + // If valid set the true frequency and return OK + spi->slave.freq = spi_true_slave_freq(freq); + return SPI_CODE_OK; +} + +spi_state_e spi_get_state(spi_t* spi) +{ + spi_codes_e error = spi_check_valid(spi); + if (error) return SPI_STATE_ARG_INVAL; // The spi parameter passed is invalid + + return peripherals[spi->idx].state; +} + +spi_codes_e spi_transmit(spi_t* spi, const uint32_t* src_buffer, uint32_t len) +{ + // Make validity checks and set the slave at hardware level + spi_codes_e error = spi_prepare_transfer(spi); + // Check that length doesn't exceed maximum and is not 0 + if (SPI_INVALID_LEN(len)) error |= SPI_CODE_TXN_LEN_INVAL; + if (error) return error; + + // Create command segment for TX transaction + spi_segment_t seg = SPI_SEG_TX(len); + // Create the transaction with the created segment + spi_transaction_t txn = SPI_TXN_TX(&seg, src_buffer, LEN_WORDS(len)); + + // Launch the transaction. All data has been verified, launch doesn't check + // anything. No callbacks since function is blocking. + spi_launch(&peripherals[spi->idx], spi, txn, NULL_CALLBACKS); + + spi_wait_transaction_done(&peripherals[spi->idx]); + // while (SPI_BUSY(peripherals[spi->idx])) wait_for_interrupt(); + + return SPI_CODE_OK; +} + +spi_codes_e spi_receive(spi_t* spi, uint32_t* dest_buffer, uint32_t len) +{ + // Make validity checks and set the slave at hardware level + spi_codes_e error = spi_prepare_transfer(spi); + // Check that length doesn't exceed maximum and is not 0 + if (SPI_INVALID_LEN(len)) error |= SPI_CODE_TXN_LEN_INVAL; + if (error) return error; + + // Create command segment for RX transaction + spi_segment_t seg = SPI_SEG_RX(len); + // Create the transaction with the created segment + spi_transaction_t txn = SPI_TXN_RX(&seg, dest_buffer, LEN_WORDS(len)); + + // Launch the transaction. All data has been verified, launch doesn't check + // anything. No callbacks since function is blocking. + spi_launch(&peripherals[spi->idx], spi, txn, NULL_CALLBACKS); + + spi_wait_transaction_done(&peripherals[spi->idx]); + // while (SPI_BUSY(peripherals[spi->idx])) wait_for_interrupt(); + + return SPI_CODE_OK; +} + +spi_codes_e spi_transceive(spi_t* spi, const uint32_t* src_buffer, + uint32_t* dest_buffer, uint32_t len) +{ + // Make validity checks and set the slave at hardware level + spi_codes_e error = spi_prepare_transfer(spi); + // Check that length doesn't exceed maximum and is not 0 + if (SPI_INVALID_LEN(len)) error |= SPI_CODE_TXN_LEN_INVAL; + if (error) return error; + + // Create command segment for BIDIR transaction + spi_segment_t seg = SPI_SEG_BIDIR(len); + // Create the transaction with the created segment + spi_transaction_t txn = SPI_TXN_BIDIR(&seg, src_buffer, dest_buffer, LEN_WORDS(len)); + + // Launch the transaction. All data has been verified, launch doesn't check + // anything. No callbacks since function is blocking. + spi_launch(&peripherals[spi->idx], spi, txn, NULL_CALLBACKS); + + spi_wait_transaction_done(&peripherals[spi->idx]); + // while (SPI_BUSY(peripherals[spi->idx])) wait_for_interrupt(); + + return SPI_CODE_OK; +} + +spi_codes_e spi_execute(spi_t* spi, const spi_segment_t* segments, + uint32_t segments_len, const uint32_t* src_buffer, + uint32_t* dest_buffer) +{ + // Make validity checks and set the slave at hardware level + spi_codes_e error = spi_prepare_transfer(spi); + if (error) return error; + + // Create the transaction with the provided segments + spi_transaction_t txn = SPI_TXN(segments, segments_len, src_buffer, dest_buffer); + + // We check every segment for validity since they are defined by user. + // This function also counts the number of words of TX and RX the entire + // transaction is composed of. + if (!spi_validate_segments(txn.segments, txn.seglen, &txn.txlen, &txn.rxlen)) + return SPI_CODE_SEGMENT_INVAL; + + // Launch the transaction. All data has been verified, launch doesn't check + // anything. No callbacks since function is blocking. + spi_launch(&peripherals[spi->idx], spi, txn, NULL_CALLBACKS); + + spi_wait_transaction_done(&peripherals[spi->idx]); + // while (SPI_BUSY(peripherals[spi->idx])) wait_for_interrupt(); + + return SPI_CODE_OK; +} + +spi_codes_e spi_transmit_nb(spi_t* spi, const uint32_t* src_buffer, uint32_t len, + spi_callbacks_t callbacks) +{ + // Make validity checks and set the slave at hardware level + spi_codes_e error = spi_prepare_transfer(spi); + // Check that length doesn't exceed maximum and is not 0 + if (SPI_INVALID_LEN(len)) error |= SPI_CODE_TXN_LEN_INVAL; + if (error) return error; + + // Create command segment for TX transaction + spi_segment_t seg = SPI_SEG_TX(len); + // Create the transaction with the created segment + spi_transaction_t txn = SPI_TXN_TX(&seg, src_buffer, LEN_WORDS(len)); + + // Launch the transaction. All data has been verified, launch doesn't check + // anything. Here user callbacks are used because non-blocking function. + spi_launch(&peripherals[spi->idx], spi, txn, callbacks); + + return SPI_CODE_OK; +} + +spi_codes_e spi_receive_nb(spi_t* spi, uint32_t* dest_buffer, uint32_t len, + spi_callbacks_t callbacks) +{ + // Make validity checks and set the slave at hardware level + spi_codes_e error = spi_prepare_transfer(spi); + // Check that length doesn't exceed maximum and is not 0 + if (SPI_INVALID_LEN(len)) error |= SPI_CODE_TXN_LEN_INVAL; + if (error) return error; + + // Create command segment for RX transaction + spi_segment_t seg = SPI_SEG_RX(len); + // Create the transaction with the created segment + spi_transaction_t txn = SPI_TXN_RX(&seg, dest_buffer, LEN_WORDS(len)); + + // Launch the transaction. All data has been verified, launch doesn't check + // anything. Here user callbacks are used because non-blocking function. + spi_launch(&peripherals[spi->idx], spi, txn, callbacks); + + return SPI_CODE_OK; +} + +spi_codes_e spi_transceive_nb(spi_t* spi, const uint32_t* src_buffer, + uint32_t* dest_buffer, uint32_t len, + spi_callbacks_t callbacks) +{ + // Make validity checks and set the slave at hardware level + spi_codes_e error = spi_prepare_transfer(spi); + // Check that length doesn't exceed maximum and is not 0 + if (SPI_INVALID_LEN(len)) error |= SPI_CODE_TXN_LEN_INVAL; + if (error) return error; + + // Create command segment for BIDIR transaction + spi_segment_t seg = SPI_SEG_BIDIR(len); + // Create the transaction with the created segment + spi_transaction_t txn = SPI_TXN_BIDIR(&seg, src_buffer, dest_buffer, LEN_WORDS(len)); + + // Launch the transaction. All data has been verified, launch doesn't check + // anything. Here user callbacks are used because non-blocking function. + spi_launch(&peripherals[spi->idx], spi, txn, callbacks); + + return SPI_CODE_OK; +} + +spi_codes_e spi_execute_nb(spi_t* spi, const spi_segment_t* segments, + uint32_t segments_len, const uint32_t* src_buffer, + uint32_t* dest_buffer, spi_callbacks_t callbacks) +{ + // Make validity checks and set the slave at hardware level + spi_codes_e error = spi_prepare_transfer(spi); + if (error) return error; + + // Create the transaction with the provided segments + spi_transaction_t txn = SPI_TXN(segments, segments_len, src_buffer, dest_buffer); + + // We check every segment for validity since they are defined by user. + // This function also counts the number of words of TX and RX the entire + // transaction is composed of. + if (!spi_validate_segments(txn.segments, txn.seglen, &txn.txlen, &txn.rxlen)) + return SPI_CODE_SEGMENT_INVAL; + + // Launch the transaction. All data has been verified, launch doesn't check + // anything. Here user callbacks are used because non-blocking function. + spi_launch(&peripherals[spi->idx], spi, txn, callbacks); + + return SPI_CODE_OK; +} + +/****************************************************************************/ +/** **/ +/* LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + +spi_codes_e spi_check_valid(spi_t* spi) +{ + // Is SPI peripheral identifier valid? + if (SPI_IDX_INVALID(spi->idx)) return SPI_CODE_IDX_INVAL; + // Has the spi been initialized (i.e. base validity checks made)? + if (!spi->init) return SPI_CODE_NOT_INIT; + return SPI_CODE_OK; +} + +spi_codes_e spi_validate_slave(spi_slave_t slave) +{ + spi_codes_e error = SPI_CODE_OK; + // Is chip select line number a valid one? + if (SPI_CSID_INVALID(slave.csid)) error |= SPI_CODE_SLAVE_CSID_INVAL; + // Is the slave max frequency less than the minimum frequency? + if (slave.freq < SPI_MIN_FREQ) error |= SPI_CODE_SLAVE_FREQ_INVAL; + return error; +} + +spi_codes_e spi_set_slave(spi_t* spi) +{ + // Compute the best clock divider + uint16_t clk_div = 0; + if (spi->slave.freq < SYS_FREQ / 2) + { + clk_div = (SYS_FREQ / spi->slave.freq - 2) / 2; + if (SYS_FREQ / (2 * clk_div + 2) > spi->slave.freq) clk_div++; + } + // Build the HAL configopts to be set based on our slave + spi_configopts_t config = { + .clkdiv = clk_div, + .csnidle = spi->slave.csn_idle, + .csntrail = spi->slave.csn_trail, + .csnlead = spi->slave.csn_lead, + .fullcyc = spi->slave.full_cycle, + .cpha = bitfield_read(spi->slave.data_mode, BIT_MASK_1, DATA_MODE_CPHA_OFFS), + .cpol = bitfield_read(spi->slave.data_mode, BIT_MASK_1, DATA_MODE_CPOL_OFFS) + }; + // Set the configopts + spi_return_flags_e config_error = spi_set_configopts(peripherals[spi->idx].instance, + spi->slave.csid, + spi_create_configopts(config)); + // CSID is invalid! This can only happen if user didn't properly initialize spi_t! + if (config_error) return SPI_CODE_SLAVE_INVAL; + // We already made sure csid was valid by calling spi_set_configopts. And we know + // instance is not NULL by definition. Hence won't return any errors. + spi_set_csid(peripherals[spi->idx].instance, spi->slave.csid); + return SPI_CODE_OK; +} + +spi_codes_e spi_prepare_transfer(spi_t* spi) +{ + // Check the idx and init of spi_t parameter. + // Notice that we do not check for slave's validity. This is because we assume + // that the user properly initialized his spi_t and didn't change its slave. + // Anyway spi_set_slave will give an error if the slave is invalid. But user + // should follow guidelines! + spi_codes_e error = spi_check_valid(spi); + if (error) return error; + + // If busy don't start a new transaction... + if (SPI_BUSY(peripherals[spi->idx])) return SPI_CODE_IS_BUSY; + // Check also at hardware level if busy, we don't know if maybe there is a + // problem somewhere + if (spi_get_active(peripherals[spi->idx].instance) == SPI_TRISTATE_TRUE) + return SPI_CODE_NOT_IDLE; + + // If the last spi instance was NOT the same as the current, slave may have + // changed, therefore set the "new" slave. Otherwise don't bother. + if (spi->id != peripherals[spi->idx].last_id) + { + error = spi_set_slave(spi); + if (error) return error; + } + + return SPI_CODE_OK; +} + +uint32_t spi_true_slave_freq(uint32_t freq) +{ + // Compute the best clock divider + uint16_t clk_div = 0; + if (freq < SYS_FREQ / 2) + { + clk_div = (SYS_FREQ / freq - 2) / 2; + if (SYS_FREQ / (2 * clk_div + 2) > freq) clk_div++; + } + // Based on the computed divider return the true frequency the SCK will be at + return SYS_FREQ / (2 * clk_div + 2); +} + +bool spi_validate_segments(const spi_segment_t* segments, uint32_t segments_len, + uint32_t* tx_count, uint32_t* rx_count) +{ + // Check that there are any segments + if (segments_len == 0) return false; + + // Make sure our word counters start at 0 + *tx_count = 0; + *rx_count = 0; + + for (int i = 0; i < segments_len; i++) + { + // Check that speed and direction are compatible and valid. + // Unfortunately this check will be done twice since when we set the command + // through the HAL the check will be done again. + // The problem is that, since starting a full transaction before being sure + // that all segments are valid would be undesirable, we have to check each + // segment before initiating a transaction. + uint8_t direction = bitfield_read(segments[i].mode, DIR_SPD_MASK, DIR_INDEX); + uint8_t speed = bitfield_read(segments[i].mode, DIR_SPD_MASK, SPD_INDEX); + if (!spi_validate_cmd(direction, speed)) return false; + // Translate bytes len to words len + uint32_t word_len = LEN_WORDS(segments[i].len); + // Increase corresponding counter. There are dummy cycles, hence we need to + // specifically check for the exact direction. + if (direction == SPI_DIR_TX_ONLY || direction == SPI_DIR_BIDIR) + *tx_count += word_len; + if (direction == SPI_DIR_RX_ONLY || direction == SPI_DIR_BIDIR) + *rx_count += word_len; + } + + return true; +} + +bool spi_fill_tx(spi_peripheral_t* peri) +{ + // If we have a TX buffer and didn't exceed the count then fill the TX FIFO + if (peri->txn.txbuffer != NULL && peri->txcnt < peri->txn.txlen) { + // While there is still data to be fed and there wasn't an error from HAL + // continue. HAL error in this case means that the fifo is full since + // it's the only possibility. + while ( + peri->txcnt < peri->txn.txlen + && !spi_write_word(peri->instance, peri->txn.txbuffer[peri->txcnt]) + ) peri->txcnt++; // Keep track of counter + return true; + } + return false; +} + +bool spi_empty_rx(spi_peripheral_t* peri) +{ + // If we have a RX buffer and didn't exceed the count then read from RX FIFO + if (peri->txn.rxbuffer != NULL && peri->rxcnt < peri->txn.rxlen) { + // While there is still data to be read and there wasn't an error from HAL + // continue. HAL error in this case means that the fifo is empty since + // it's the only possibility. + while ( + peri->rxcnt < peri->txn.rxlen + && !spi_read_word(peri->instance, &peri->txn.rxbuffer[peri->rxcnt]) + ) peri->rxcnt++; // Keep track of counter + return true; + } + return false; +} + +void spi_launch(spi_peripheral_t* peri, spi_t* spi, spi_transaction_t txn, + spi_callbacks_t callbacks) +{ + // All checks have been made, therefore there can't be any error here. + // This also means that we can safely set the state since we know we will + // proceed to launch without any doubt. + peri->state = SPI_STATE_BUSY; + // Set all transaction data to our static peripheral variable + peri->txn = txn; + // Indicate the callbacks that should be called + peri->callbacks = callbacks; + + // Fill the TX fifo before starting so there is data once command launched + spi_fill_tx(peri); + + // Enable event interrupts since they are enabled only during a transaction + spi_set_events_enabled(peri->instance, TRIGGERING_EVENTS, true); + spi_enable_evt_intr (peri->instance, true); + + // Wait for the SPI peripheral to be ready before writing a command segment. + spi_wait_for_ready(peri->instance); + // Write command segment. This immediately triggers the SPI peripheral into action. + spi_issue_next_seg(peri); +} + +void spi_wait_transaction_done(spi_peripheral_t* peri) +{ + // Convert ms timeout to clock ticks + uint64_t timeout_ticks = ((uint64_t) peri->timeout) * (SYS_FREQ / 1000); + uint32_t start[2]; + uint32_t end[2]; + + // Enable tick counter + CSR_CLEAR_BITS(CSR_REG_MCOUNTINHIBIT, 0x1); + // Record start tick counter value + CSR_READ(CSR_REG_MCYCLE, &start[0]); + CSR_READ(CSR_REG_MCYCLEH, &start[1]); + + // Wait until transaction has finished or timed-out + do + { + // Read tick counter value + CSR_READ(CSR_REG_MCYCLE, &end[0]); + CSR_READ(CSR_REG_MCYCLEH, &end[1]); + // If ticks elapsed exceed timeout ticks, cancel transaction and return + if (*((uint64_t*)end) - *((uint64_t*)start) > timeout_ticks) + { + // Fully reset spi peripheral to cancel transaction, empty fifos, etc. + spi_reset_peri(peri); + // Indicate to user the transaction has timed-out + peri->state = SPI_STATE_TIMEOUT; + break; + } + + } while (SPI_BUSY((*peri))); +} + +void spi_issue_next_seg(spi_peripheral_t* peri) +{ + const spi_segment_t seg = peri->txn.segments[peri->scnt]; + peri->scnt++; + // Construct our word command to be passed to HAL + uint32_t cmd_reg = spi_create_command((spi_command_t) { + .len = seg.len - 1, // -1 because of SPI Host IP specifications + .csaat = peri->txn.seglen == peri->scnt ? false : true, + .speed = bitfield_read(seg.mode, DIR_SPD_MASK, SPD_INDEX), + .direction = bitfield_read(seg.mode, DIR_SPD_MASK, DIR_INDEX), + }); + // Since all checks were already made we do not need to check the result of function + spi_set_command(peri->instance, cmd_reg); +} + +void spi_reset_peri(spi_peripheral_t* peri) +{ + // Reset static peripheral variables + spi_reset_transaction(peri); + // Reset the SPI peripheral (at hardware level) + spi_sw_reset(peri->instance); + // Enable SPI peripheral. We do not check return value since we know here that + // it will never return an error. + spi_set_enable(peri->instance, true); + spi_output_enable(peri->instance, true); + // Enable all error interrupts so that the SPI peripheral doesn't get stuck if + // there is an error. And we don't check return value since we know it's error free. + spi_set_errors_enabled(peri->instance, SPI_ERROR_IRQALL, true); + spi_enable_error_intr(peri->instance, true); + // Set the watermarks for the specific peripheral. + spi_set_tx_watermark(peri->instance, peri->txwm); + spi_set_rx_watermark(peri->instance, peri->rxwm); + // Just reset the state. + peri->state = SPI_STATE_INIT; + // Force the next transaction to set the slave at hardware level + peri->last_id = 0; +} + +void spi_reset_transaction(spi_peripheral_t* peri) +{ + // Reset all variables relative to the transaction of the static peripheral + // instance + peri->scnt = 0; + peri->txcnt = 0; + peri->rxcnt = 0; + peri->txn = (spi_transaction_t) {0}; + peri->callbacks = NULL_CALLBACKS; +} + +void spi_event_handler(spi_peripheral_t* peri, spi_event_e events) +{ + // Ready means it is ready to accept new command segments. So we have two + // possibilities if the device is ready: + // 1) It is ready but not idle + // 2) It is ready and idle + if (events & SPI_EVENT_READY) + { + // If SPI is ready and there are still commands to execute, issue next command + if (peri->txn.segments != NULL && peri->scnt < peri->txn.seglen) + { + spi_issue_next_seg(peri); + } + // If no more commands and SPI is idle, it means the transaction is over + else if (events & SPI_EVENT_IDLE) + { + // Disable all event interrupts + spi_set_events_enabled(peri->instance, SPI_EVENT_ALL, false); + spi_enable_evt_intr (peri->instance, false); + // Read the last data from the RX fifo + spi_empty_rx(peri); + // Set the state to Transaction is done (meaning successful) + peri->state = SPI_STATE_DONE; + // If there is a callback defined call it + if (peri->callbacks.done_cb != NULL) + { + peri->callbacks.done_cb(peri->txn.txbuffer, peri->txcnt, + peri->txn.rxbuffer, peri->rxcnt); + } + // Reset all transaction related variables + spi_reset_transaction(peri); + return; + } + } + if (events & SPI_EVENT_TXWM) + { + // TX watermark reached. Refill TX fifo if more data + // If there is a callback defined call it + if (spi_fill_tx(peri) && peri->callbacks.txwm_cb != NULL) + { + peri->callbacks.txwm_cb(peri->txn.txbuffer, peri->txcnt, + peri->txn.rxbuffer, peri->rxcnt); + } + } + if (events & SPI_EVENT_RXWM) + { + // RX watermark reached. Empty RX fifo to get more data + // If there is a callback defined call it + if (spi_empty_rx(peri) && peri->callbacks.rxwm_cb != NULL) + { + peri->callbacks.rxwm_cb(peri->txn.txbuffer, peri->txcnt, + peri->txn.rxbuffer, peri->rxcnt); + } + } +} + +void spi_error_handler(spi_peripheral_t* peri, spi_error_e error) +{ + // Disable event interrupts + spi_set_events_enabled(peri->instance, SPI_EVENT_ALL, false); + spi_enable_evt_intr (peri->instance, false); + // If there is a callback defined invoke it + if (peri->callbacks.error_cb != NULL) + { + peri->callbacks.error_cb(peri->txn.txbuffer, peri->txcnt, + peri->txn.rxbuffer, peri->rxcnt); + } + spi_reset_peri(peri); + // Set the state to error + peri->state = SPI_STATE_ERROR; +} + +/****************************************************************************/ +/** **/ +/* INTERRUPTS */ +/** **/ +/****************************************************************************/ + +/** + * @brief Implementation of the weak function of the HAL + */ +void spi_intr_handler_event_flash(spi_event_e events) +{ + if (SPI_NOT_BUSY(peripherals[SPI_IDX_FLASH])) return; + spi_event_handler(&peripherals[SPI_IDX_FLASH], events); +} + +/** + * @brief Implementation of the weak function of the HAL + */ +void spi_intr_handler_error_flash(spi_error_e errors) +{ + if (SPI_NOT_BUSY(peripherals[SPI_IDX_FLASH])) return; + spi_error_handler(&peripherals[SPI_IDX_FLASH], errors); +} + +/** + * @brief Implementation of the weak function of the HAL + */ +void spi_intr_handler_event_host(spi_event_e events) +{ + if (SPI_NOT_BUSY(peripherals[SPI_IDX_HOST])) return; + spi_event_handler(&peripherals[SPI_IDX_HOST], events); +} + +/** + * @brief Implementation of the weak function of the HAL + */ +void spi_intr_handler_error_host(spi_error_e errors) +{ + if (SPI_NOT_BUSY(peripherals[SPI_IDX_HOST])) return; + spi_error_handler(&peripherals[SPI_IDX_HOST], errors); +} + +/** + * @brief Implementation of the weak function of the HAL + */ +void spi_intr_handler_event_host2(spi_event_e events) +{ + if (SPI_NOT_BUSY(peripherals[SPI_IDX_HOST_2])) return; + spi_event_handler(&peripherals[SPI_IDX_HOST_2], events); +} + +/** + * @brief Implementation of the weak function of the HAL + */ +void spi_intr_handler_error_host2(spi_error_e errors) +{ + if (SPI_NOT_BUSY(peripherals[SPI_IDX_HOST_2])) return; + spi_error_handler(&peripherals[SPI_IDX_HOST_2], errors); +} + +/****************************************************************************/ +/** **/ +/** EOF **/ +/** **/ +/****************************************************************************/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/spi/spi_sdk.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/spi/spi_sdk.h new file mode 100644 index 00000000..28982b31 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/spi/spi_sdk.h @@ -0,0 +1,576 @@ +/* + ******************* +******************************* C SOURCE FILE ***************************** +** ******************* +** +** project : X-HEEP +** filename : spi_sdk.h +** version : 1 +** date : 18/04/24 +** +*************************************************************************** +** +** Copyright (c) EPFL contributors. +** All rights reserved. +** +*************************************************************************** +*/ + +/***************************************************************************/ +/***************************************************************************/ +/** +* @file spi_sdk.h +* @date 18/04/24 +* @author Llorenç Muela +* @brief The Serial Peripheral Interface (SPI) SDK to set up and use the +* SPI peripheral +*/ + +#ifndef _SDK_SPI_H_ +#define _SDK_SPI_H_ + +/****************************************************************************/ +/** **/ +/** MODULES USED **/ +/** **/ +/****************************************************************************/ + +#include +#include + +/****************************************************************************/ +/** **/ +/** DEFINITIONS AND MACROS **/ +/** **/ +/****************************************************************************/ + +// Chosen arbitrarily +#define SPI_CSN_TIMES_DEFAULT 15 +// Default timeout for blocking transactions in milliseconds +#define SPI_TIMEOUT_DEFAULT 100 + +/** + * @brief Macro to create a Slave SPI device with standard parameters. + */ +#define SPI_SLAVE(cs_id, freq_max) (spi_slave_t) { \ + .csid = cs_id, \ + .data_mode = SPI_DATA_MODE_0, \ + .full_cycle = false, \ + .csn_lead = SPI_CSN_TIMES_DEFAULT, \ + .csn_trail = SPI_CSN_TIMES_DEFAULT, \ + .csn_idle = SPI_CSN_TIMES_DEFAULT, \ + .freq = freq_max \ +} + +/** + * @brief Macro to instantiate a Dummy Segment + */ +#define SPI_SEG_DUMMY(cycles) (spi_segment_t) { \ + .len = cycles, \ + .mode = SPI_MODE_DUMMY \ +} + +/** + * @brief Macro to instantiate a TX Segment + */ +#define SPI_SEG_TX(bytes) (spi_segment_t) { \ + .len = bytes, \ + .mode = SPI_MODE_TX_STD \ +} + +/** + * @brief Macro to instantiate a RX Segment + */ +#define SPI_SEG_RX(bytes) (spi_segment_t) { \ + .len = bytes, \ + .mode = SPI_MODE_RX_STD \ +} + +/** + * @brief Macro to instantiate a BIDIR Segment + */ +#define SPI_SEG_BIDIR(bytes) (spi_segment_t) { \ + .len = bytes, \ + .mode = SPI_MODE_BIDIR \ +} + +/** + * @brief Macro to instantiate a Dual Speed TX Segment + */ +#define SPI_SEG_TX_DUAL(bytes) (spi_segment_t) { \ + .len = bytes, \ + .mode = SPI_MODE_TX_DUAL \ +} + +/** + * @brief Macro to instantiate a Dual Speed RX Segment + */ +#define SPI_SEG_RX_DUAL(bytes) (spi_segment_t) { \ + .len = bytes, \ + .mode = SPI_MODE_RX_DUAL \ +} + +/** + * @brief Macro to instantiate a Quad Speed TX Segment + */ +#define SPI_SEG_TX_QUAD(bytes) (spi_segment_t) { \ + .len = bytes, \ + .mode = SPI_MODE_TX_QUAD \ +} + +/** + * @brief Macro to instantiate a Quad Speed RX Segment + */ +#define SPI_SEG_RX_QUAD(bytes) (spi_segment_t) { \ + .len = bytes, \ + .mode = SPI_MODE_RX_QUAD \ +} + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************/ +/** **/ +/** TYPEDEFS AND STRUCTURES **/ +/** **/ +/****************************************************************************/ + +/** +* @brief SPI Peripheral IDX +*/ +typedef enum { + SPI_IDX_FLASH = 0, // Identifier for the SPI FLASH peripheral + SPI_IDX_HOST = 1, // Identifier for the SPI HOST1 peripheral + SPI_IDX_HOST_2 = 2 // Identifier for the SPI HOST2 peripheral +} spi_idx_e; + +typedef enum { + SPI_CODE_OK = 0x0000, // Everything Okay + SPI_CODE_BASE_ERROR = 0x0001, // HAL complained (should never happen) + SPI_CODE_IDX_INVAL = 0x0002, // The idx of the provided spi_t is not valid + SPI_CODE_WM_EXCEEDS = 0x0004, // The provided watermark is too big + SPI_CODE_NOT_INIT = 0x0008, // The provided spi_t was not initialized + SPI_CODE_SLAVE_CSID_INVAL = 0x0010, // The csid of the slave is not valid + SPI_CODE_SLAVE_FREQ_INVAL = 0x0020, // Max frequency of the slave is too low + SPI_CODE_NOT_IDLE = 0x0040, // The SPI device is busy (but not from SDK) + SPI_CODE_SLAVE_INVAL = 0x0080, // Something was wrong with the slave configuration + SPI_CODE_SEGMENT_INVAL = 0x0100, // The spi_mode_e of the segment was invalid + SPI_CODE_IS_BUSY = 0x0200, // The SPI device is busy + SPI_CODE_TXN_LEN_INVAL = 0x0400, // The transaction length is 0 or too long + SPI_CODE_TIMEOUT_INVAL = 0x0800 // The specified timeout is invalid +} spi_codes_e; + +typedef enum { + SPI_DATA_MODE_0 = 0, // cpol = 0, cpha = 0 + SPI_DATA_MODE_1 = 1, // cpol = 0, cpha = 1 + SPI_DATA_MODE_2 = 2, // cpol = 1, cpha = 0 + SPI_DATA_MODE_3 = 3 // cpol = 1, cpha = 1 +} spi_datamode_e; + +typedef enum { + SPI_MODE_DUMMY = 0, // Dummy SCK command segment + SPI_MODE_RX_STD = 1, // Standard receive command segment + SPI_MODE_TX_STD = 2, // Standard transmit command segment + SPI_MODE_BIDIR = 3, // Standard bidirectional command segment + // 4 is same than DUMMY + SPI_MODE_RX_DUAL = 5, // Dual speed receive command segment + SPI_MODE_TX_DUAL = 6, // Dual speed transmit command segment + // 7 is invalid + // 8 is same than DUMMY + SPI_MODE_RX_QUAD = 9, // Quad speed receive command segment + SPI_MODE_TX_QUAD = 10 // Quad speed transmit command segment + // everything > 10 is invalid +} spi_mode_e; + +// State is useful to know if the peripheral is busy, but also very useful if a +// blocking transaction was made and we want to check the result of the blocking +// transation (i.e. error or success) +typedef enum { + // Indicates SPI device was never initialized (should never happen!) + SPI_STATE_NONE = 0x00, + // Indicates SPI device never executed a transaction + SPI_STATE_INIT = 0x01, + // Indicates SPI device is currently processing a transaction + SPI_STATE_BUSY = 0x02, + // Indicates SPI device has successfully executed a transaction + SPI_STATE_DONE = 0x04, + // Indicates there was an error during transaction + SPI_STATE_ERROR = 0x08, + // Indicates the transaction execution has timed-out + SPI_STATE_TIMEOUT = 0x10, + // Indicates the argument passed to spi_get_state was not valid + SPI_STATE_ARG_INVAL = 0x20 +} spi_state_e; + +/** + * @brief Type defining the configuration of the slave device with whom to communicate + */ +typedef struct { + // The Chip Select line where device connected + uint8_t csid : 2; + // The data sampling and transmitting mode (polarity and phase) + spi_datamode_e data_mode : 2; + // If 1 data is sampled a full cycle after shifting data out, instead of half cycle + bool full_cycle : 1; + // The minimum number of sck half-cycles to hold cs_n high between commands + uint8_t csn_idle : 4; + // The number of half sck cycles, CSNTRAIL+1, to leave between last edge of sck + // and the rising edge of cs_n + uint8_t csn_trail : 4; + // The number of half sck cycles, CSNLEAD+1, to leave between the falling edge + // of cs_n and the first edge of sck + uint8_t csn_lead : 4; + // The maximum frequency in hertz of the slave + uint32_t freq : 32; +} spi_slave_t; + +/** + * @brief Type defining a command segment + */ +typedef struct { + uint32_t len : 24; // Length of data in bytes for the particular segment + spi_mode_e mode : 4; // Communication mode (TX, BIDIR, RX_QUAD, ...) +} spi_segment_t; + +// Event / Error interrupt callback (txbuffer, txlen, rxbuffer, rxlen) +typedef void (*spi_cb_t)(const uint32_t*, uint32_t, uint32_t*, uint32_t); + +/** + * @brief Structure holding all the callbacks for a transaction. + * Each callback may be NULL if you don't want it to be called. + */ +typedef struct { + spi_cb_t done_cb; // Called once transaction is done + spi_cb_t txwm_cb; // Called each time TX watermark event is triggered + spi_cb_t rxwm_cb; // Called each time RX watermark event is triggered + spi_cb_t error_cb; // Called when there was an error during transaction +} spi_callbacks_t; + +/** + * @brief Type holding Information to use SDK. + */ +typedef struct { + spi_idx_e idx; // The identifier for the desired SPI devide + uint32_t id; // spi_t instance ID + bool init; // Indicates if initialization was successful + spi_slave_t slave; // The slave with whom to communicate configuration +} spi_t; + +/****************************************************************************/ +/** **/ +/** EXPORTED VARIABLES **/ +/** **/ +/****************************************************************************/ + +/****************************************************************************/ +/** **/ +/** EXPORTED FUNCTIONS **/ +/** **/ +/****************************************************************************/ + +/** + * @brief Initialize desired SPI device and obtain structure to use SDK functions. + * This method has to be called prior to any use of other functions of the SDK. + * + * Important: This method validates the provided slave and adapts its frequency + * based on the MCU frequency and the SCK divider. If you do not create the spi_t + * structure by calling this function the slave may be invalid resulting in errors. + * + * @param idx spi_idx_e representing the SPI device + * @param slave spi_slave_t correctly configured slave SPI device to interact with + * @return spi_t structure to use SDK functions + */ +spi_t spi_init(spi_idx_e idx, spi_slave_t slave); + +/** + * @brief Uninitializes the spi by unsetting all fields. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + */ +void spi_deinit(spi_t* spi); + +/** + * @brief Completely reset the SPI device (clears all status, stops all transactions, + * empties FIFOs) + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_reset(spi_t* spi); + +/** + * @brief Change the TX watermark of the specific SPI Host peripheral + * Maximum is currently 72. Check SPI_HOST_PARAM_TX_DEPTH in HAL. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param watermark The desired new watermark + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_WM_EXCEEDS if specified watermark is too high + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_set_txwm(spi_t* spi, uint8_t watermark); + +/** + * @brief Get the TX watermark of the specific SPI Host peripheral + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param watermark The current watermark will be stored in this variable + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_get_txwm(spi_t* spi, uint8_t* watermark); + +/** + * @brief Change the RX watermark of the specific SPI Host peripheral + * Maximum is currently 64. Check SPI_HOST_PARAM_RX_DEPTH in HAL. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param watermark The desired new watermark + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_WM_EXCEEDS if specified watermark is too high + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_set_rxwm(spi_t* spi, uint8_t watermark); + +/** + * @brief Get the RX watermark of the specific SPI Host peripheral + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param watermark The current watermark will be stored in this variable + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_get_rxwm(spi_t* spi, uint8_t* watermark); + +/** + * @brief Set the timeout in milliseconds for blocking transactions for the + * specific SPI Host peripheral. + * Maximum is UINT32_MAX * 1000 / core_frequency. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param watermark The desired new watermark + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_TIMEOUT_INVAL if the specified timout is too large + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_set_timeout(spi_t* spi, uint32_t timeout); + +/** + * @brief Get the timeout in milliseconds for blocking transactions for the + * specific SPI Host peripheral. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param timeout The current timeout will be stored in this variable + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_get_timeout(spi_t* spi, uint32_t* timeout); + +/** + * @brief Change the communication frequency of the slave + * /!\ If the frequency is higher than the maximum frequency it will just + * be capped (i.e. no error) + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param freq The new frequency the slave should be changed + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_SLAVE_CSID_INVAL if slave's csid is invalid + * @return SPI_CODE_SLAVE_FREQ_INVAL if new frequency is too low + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_set_slave_freq(spi_t* spi, uint32_t freq); + +/** + * @brief Read the SPI current state. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @return SPI_STATE_NONE : SPI device was never initialized (should never happen!) + * @return SPI_STATE_INIT : SPI device never executed a transaction + * @return SPI_STATE_BUSY : SPI device is currently processing a transaction + * @return SPI_STATE_DONE : SPI device has successfully executed a transaction + * @return SPI_STATE_ERROR : There was an error during transaction + * @return SPI_STATE_ARG_INVAL : The argument passed to this function was not valid + */ +spi_state_e spi_get_state(spi_t* spi); + +/** + * @brief Executes a TX command. + * /!\ Caution: len is in bytes. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param src_buffer An initialized buffer/array with all the data to send + * @param len The size in bytes of the transaction (/!\ must be coherent with + * src_buffer size) + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_transmit(spi_t* spi, const uint32_t* src_buffer, uint32_t len); + +/** + * @brief Executes an RX command. + * /!\ Caution: len is in bytes. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param dest_buffer An initialized buffer/array to store the received data + * @param len The size in bytes of the transaction (/!\ must be coherent with + * dest_buffer size) + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_receive(spi_t* spi, uint32_t* dest_buffer, uint32_t len); + +/** + * @brief Executes a Bidirectional (TX and RX) command. + * /!\ Caution: len is in bytes and is for the TX as well as RX. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param src_buffer An initialized buffer/array with all the data to send + * @param dest_buffer An initialized buffer/array to store the received data + * @param len The size in bytes of the transaction (/!\ must be coherent with + * src_buffer and dest_buffer size) + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_transceive(spi_t* spi, const uint32_t* src_buffer, + uint32_t* dest_buffer, uint32_t len); + +/** + * @brief Executes a transacton composed of multiple command segments. + * Each segment already contains the Information about the length and the + * src/dest buffer concerned. Therefore no need for length parameter here. + * /!\ Caution: please be consistent with the length of src_buffer/dest_buffer + * and the lenghts specified for the segments. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param segments An array of command segments + * @param segments_len The size of segments array + * @param src_buffer An initialized buffer/array with all the data to send + * @param dest_buffer An initialized buffer/array to store the received data + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_SEGMENT_INVAL if segments contains an invalid segment + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_execute(spi_t* spi, const spi_segment_t* segments, + uint32_t segments_len, const uint32_t* src_buffer, + uint32_t* dest_buffer); + +/** + * @brief Executes a TX command. This is Non-Blocking, the function will return + * immediately. + * /!\ Caution: len is in bytes. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param src_buffer An initialized buffer/array with all the data to send + * @param len The size in bytes of the transaction (/!\ must be coherent with + * src_buffer size) + * @param done_cb A callback function of type spi_cb_t that gets called when + * transaction is done + * @param error_cb A callback function of type spi_cb_t that gets called when there + * is an error during transaction + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_transmit_nb(spi_t* spi, const uint32_t* src_buffer, uint32_t len, + spi_callbacks_t callbacks); + +/** + * @brief Executes an RX command. This is Non-Blocking, the function will return + * immediately. + * /!\ Caution: len is in bytes. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param dest_buffer An initialized buffer/array to store the received data + * @param len The size in bytes of the transaction (/!\ must be coherent with + * dest_buffer size) + * @param done_cb A callback function of type spi_cb_t that gets called when + * transaction is done + * @param error_cb A callback function of type spi_cb_t that gets called when there + * is an error during transaction + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_receive_nb(spi_t* spi, uint32_t* dest_buffer, uint32_t len, + spi_callbacks_t callbacks); + +/** + * @brief Executes a Bidirectional (TX and RX) command. This is Non-Blocking, the + * function will return immediately. + * /!\ Caution: len is in bytes and is for the TX as well as RX. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param src_buffer An initialized buffer/array with all the data to send + * @param dest_buffer An initialized buffer/array to store the received data + * @param len The size in bytes of the transaction (/!\ must be coherent with + * src_buffer and dest_buffer size) + * @param done_cb A callback function of type spi_cb_t that gets called when + * transaction is done + * @param error_cb A callback function of type spi_cb_t that gets called when there + * is an error during transaction + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_transceive_nb(spi_t* spi, const uint32_t* src_buffer, + uint32_t* dest_buffer, uint32_t len, + spi_callbacks_t callbacks); + +/** + * @brief Executes a transacton composed of multiple command segments. This is + * Non-Blocking, the function will return immediately. + * Each segment already contains the Information about the length and the + * src/dest buffer concerned. Therefore no need for length parameter here. + * /!\ Caution: please be consistent with the length of src_buffer/dest_buffer + * and the lenghts specified for the segments. + * + * @param spi Pointer to spi_t structure obtained through spi_init call + * @param segments An array of command segments + * @param segments_len The size of segments array + * @param src_buffer An initialized buffer/array with all the data to send + * @param dest_buffer An initialized buffer/array to store the received data + * @param done_cb A callback function of type spi_cb_t that gets called when + * transaction is done + * @param error_cb A callback function of type spi_cb_t that gets called when there + * is an error during transaction + * @return SPI_CODE_IDX_INVAL if spi.idx not valid + * @return SPI_CODE_NOT_INIT if spi.init false (indicates if spi was initialized) + * @return SPI_CODE_SEGMENT_INVAL if segments contains an invalid segment + * @return SPI_CODE_OK if success + */ +spi_codes_e spi_execute_nb(spi_t* spi, const spi_segment_t* segments, + uint32_t segments_len, const uint32_t* src_buffer, + uint32_t* dest_buffer, spi_callbacks_t callbacks); + +/****************************************************************************/ +/** **/ +/** INLINE FUNCTIONS **/ +/** **/ +/****************************************************************************/ + + +#ifdef __cplusplus +} +#endif + +#endif // _SDK_SPI_H_ + +/****************************************************************************/ +/** **/ +/** EOF **/ +/** **/ +/****************************************************************************/ diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/timer/timer_sdk.c b/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/timer/timer_sdk.c new file mode 100644 index 00000000..3e4e2719 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/timer/timer_sdk.c @@ -0,0 +1,142 @@ +// Copyright 2023 EPFL and Politecnico di Torino. +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// File: timer_sdk.c +// Author: Michele Caon, Francesco Poluzzi +// Date: 23/07/2024 +// Description: Timer functions + +#include + +#include "timer_sdk.h" +#include "csr.h" +#include "soc_ctrl.h" + + +/******************************/ +/* ---- GLOBAL VARIABLES ---- */ +/******************************/ + +// Timer value +int32_t hw_timer_value = 0; + +rv_timer_t timer; + +rv_timer_config_t timer_cfg = { + .hart_count = RV_TIMER_PARAM_N_HARTS, + .comparator_count = RV_TIMER_PARAM_N_TIMERS, +}; + +mmio_region_t timer_base = { + .base = (void *)RV_TIMER_AO_START_ADDRESS, +}; + +rv_timer_tick_params_t tick_params; + + +/*************************************/ +/* ---- FUNCTION IMPLEMENTATION ---- */ +/*************************************/ + +uint32_t timer_get_cycles() +{ + uint64_t cycle_count; + rv_timer_counter_read(&timer, 0, &cycle_count); + return (uint32_t)cycle_count; +} + +void timer_irq_enable() +{ + rv_timer_irq_enable(&timer, 0, 0, kRvTimerEnabled); +} + +void timer_irq_clear() +{ + rv_timer_irq_clear(&timer, 0, 0); +} + +void timer_arm_start(uint32_t threshold) +{ + rv_timer_arm(&timer, 0, 0, threshold); + timer_start(); +} + +void timer_arm_stop() +{ + rv_timer_counter_set_enabled(&timer, 0, kRvTimerDisabled); +} + + +void timer_arm_set(uint32_t threshold) +{ + rv_timer_arm(&timer, 0, 0, threshold); +} + +void timer_start() +{ + hw_timer_value = -timer_get_cycles(); + rv_timer_counter_set_enabled(&timer, 0, kRvTimerEnabled); +} + +void timer_reset() +{ + hw_timer_value = 0; + rv_timer_reset(&timer); +} + +uint32_t timer_stop() +{ + hw_timer_value += timer_get_cycles(); + rv_timer_counter_set_enabled(&timer, 0, kRvTimerDisabled); + return hw_timer_value; +} + +// Initialize the timer +void timer_cycles_init() +{ + // Get current Frequency + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + uint32_t freq_hz = soc_ctrl_get_frequency(&soc_ctrl); + + // Initialize the timer + timer_reset(); + rv_timer_init(timer_base, timer_cfg, &timer); + rv_timer_approximate_tick_params(freq_hz, freq_hz, &tick_params); + rv_timer_set_tick_params(&timer, 0, tick_params); +} + +// Initialize the timer +void timer_wait_us(uint32_t us) +{ + // Get current Frequency + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + uint32_t freq_hz = soc_ctrl_get_frequency(&soc_ctrl); + + timer_cycles_init(); + timer_irq_enable(); + timer_arm_start(us*(freq_hz/1000000)-50); // 50 cycles for taking into account initialization + asm volatile ("wfi"); + timer_irq_clear(); + return; +} + +void enable_timer_interrupt() +{ + //enable timer interrupt + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + // Set mie.MEIE bit to one to enable machine-level timer interrupts + const uint32_t mask = 1 << 7; + CSR_SET_BITS(CSR_REG_MIE, mask); +} + +float get_time_from_cycles(uint32_t cycles){ + // Get current Frequency + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + uint32_t freq_hz = soc_ctrl_get_frequency(&soc_ctrl); + + return (float)cycles/((float)freq_hz/1000000); +} \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/timer/timer_sdk.h b/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/timer/timer_sdk.h new file mode 100644 index 00000000..154ef30b --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/lib/sdk/timer/timer_sdk.h @@ -0,0 +1,121 @@ + +// Copyright 2023 EPFL and Politecnico di Torino. +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// File: timer_sdk.h +// Authors: Michele Caon, Luigi Giuffrida, Francesco Poluzzi +// Date: 23/07/2024 +// Description: Execution time measurements utilities + +#ifndef TIMER_SDK_H_ +#define TIMER_SDK_H_ + +#include + +#include "csr.h" +#include "gpio.h" +#include "rv_timer.h" +#include "rv_timer_regs.h" +#include "core_v_mini_mcu.h" +#include "x-heep.h" + +#define FREQ_1MHz 1000000 + +/******************************/ +/* ---- GLOBAL VARIABLES ---- */ +/******************************/ + +// Timer value +extern int32_t hw_timer_value; + +extern rv_timer_t timer; + +/********************************/ +/* ---- EXPORTED FUNCTIONS ---- */ +/********************************/ + +/** + * @brief Get the current value of the HW timer + * +* @return int64_t Current value of the HW timer + */ +uint32_t timer_get_cycles(); + +/** + * @brief Start the timer + * + */ +void timer_start(); + +/** + * @brief Stop and reset the timer to 0 + * + */ +void timer_reset(); + +/** + * @brief Stop the HW timer + * + * @return int64_t Elapsed time in clock cycles + */ +uint32_t timer_stop(); + +/** + * @brief Initialize the timer for counting clock cycles + * @brief Initialize the timer for counting clock cycles + * + */ +void timer_cycles_init(); + +/** + * @brief Enable the timer IRQ + */ +void timer_irq_enable(); + +/** + * @brief Clear the timer IRQ + */ +void timer_irq_clear(); + +/** + * @brief Arms the timer to go off once the counter value is greater than or equal to threshold + * and starts the timer + */ +void timer_arm_start(uint32_t threshold); + +/** + * @brief Stop to output when timer is greater than or equal to threshold previously set + */ +void timer_arm_stop(); + +/** + * @brief Set the timer to go off once the counter value is greater than or equal to threshold, + * without starting the timer + */ +void timer_arm_set(uint32_t threshold); + +/** + * @brief Enable the timer machine-level interrupts for X-Heep + */ +void enable_timer_interrupt(); + +/** + * @brief Wait for a certain amount of microseconds. + * You need to enable timer interrupts with enable_timer_interrupt() before using this function + */ +void timer_wait_us(uint32_t ms); + +/** + * @brief Enable the timer machine-level interrupts for X-Heep + */ +void enable_timer_interrupt(); + +/** + * @brief Get the time taken to execute a certain number of cycles + * + * @return float value representing the time taken in microseconds + */ +float get_time_from_cycles(uint32_t cycles); + +#endif /* TIMER_SDK_H_ */ \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/target/nexys-a7-100t/x-heep.h b/hw/vendor/esl_epfl_x_heep/sw/device/target/nexys-a7-100t/x-heep.h new file mode 100644 index 00000000..072a31e0 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/target/nexys-a7-100t/x-heep.h @@ -0,0 +1,31 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef X_HEEP +#define X_HEEP + +#pragma message ( "the x-heep.h for NEXYS-A7-100T is used" ) + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + +#define REFERENCE_CLOCK_Hz 15*1000*1000 +#define UART_BAUDRATE 9600 +#define TARGET_NEXYS_A7_100T 1 +#define TARGET_IS_FPGA 1 + +/** + * As the hw is configurable, we can have setups with different number of + * Gpio pins + */ +#define MAX_PIN 32 + + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // X_HEEP diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/target/pynq-z2/x-heep.h b/hw/vendor/esl_epfl_x_heep/sw/device/target/pynq-z2/x-heep.h index 43cef0d4..2733e716 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/device/target/pynq-z2/x-heep.h +++ b/hw/vendor/esl_epfl_x_heep/sw/device/target/pynq-z2/x-heep.h @@ -15,6 +15,7 @@ extern "C" { #define REFERENCE_CLOCK_Hz 15*1000*1000 #define UART_BAUDRATE 9600 #define TARGET_PYNQ_Z2 1 +#define TARGET_IS_FPGA 1 /** * As the hw is configurable, we can have setups with different number of diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/target/systemc/x-heep.h b/hw/vendor/esl_epfl_x_heep/sw/device/target/systemc/x-heep.h new file mode 100644 index 00000000..1c1390cb --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/target/systemc/x-heep.h @@ -0,0 +1,30 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef X_HEEP +#define X_HEEP + +#pragma message ( "the x-heep.h for SIMULATION in SYSTEMC is used" ) + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + +#define REFERENCE_CLOCK_Hz 100*1000*1000 +#define UART_BAUDRATE 256000 +#define TARGET_SYSTEMC 1 + +/** + * As the hw is configurable, we can have setups with different number of + * Gpio pins + */ +#define MAX_PIN 32 + + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // X_HEEP diff --git a/hw/vendor/esl_epfl_x_heep/sw/device/target/zcu104/x-heep.h b/hw/vendor/esl_epfl_x_heep/sw/device/target/zcu104/x-heep.h new file mode 100644 index 00000000..7c0b0602 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/sw/device/target/zcu104/x-heep.h @@ -0,0 +1,29 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef X_HEEP +#define X_HEEP + +#pragma message ( "the x-heep.h for ZCU104 is used" ) + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#define REFERENCE_CLOCK_Hz 15*1000*1000 +#define UART_BAUDRATE 9600 +#define TARGET_ZCU104 1 +#define TARGET_IS_FPGA 1 + +/** + * As the hw is configurable, we can have setups with different number of + * Gpio pins + */ +#define MAX_PIN 32 + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // X_HEEP diff --git a/hw/vendor/esl_epfl_x_heep/sw/linker/link.ld.tpl b/hw/vendor/esl_epfl_x_heep/sw/linker/link.ld.tpl index f05c107b..b499b576 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/linker/link.ld.tpl +++ b/hw/vendor/esl_epfl_x_heep/sw/linker/link.ld.tpl @@ -20,11 +20,9 @@ MEMORY /* Our testbench is a bit weird in that we initialize the RAM (thus allowing initialized sections to be placed there). Infact we dump all sections to ram. */ - ram0 (rwxai) : ORIGIN = 0x${linker_onchip_code_start_address}, LENGTH = 0x${linker_onchip_code_size_address} - ram1 (rwxai) : ORIGIN = 0x${linker_onchip_data_start_address}, LENGTH = 0x${linker_onchip_data_size_address} -% if ram_numbanks_cont > 1 and ram_numbanks_il > 0: - ram_il (rwxai) : ORIGIN = 0x${linker_onchip_il_start_address}, LENGTH = 0x${linker_onchip_il_size_address} -% endif + % for i, section in enumerate(xheep.iter_linker_sections()): + ram${i} (rwxai) : ORIGIN = ${f"{section.start:#08x}"}, LENGTH = ${f"{section.size:#08x}"} +% endfor } /* @@ -38,51 +36,13 @@ SECTIONS PROVIDE(__boot_address = 0x180); /* stack and heap related settings */ - __stack_size = DEFINED(__stack_size) ? __stack_size : 0x800; + __stack_size = DEFINED(__stack_size) ? __stack_size : 0x${stack_size}; PROVIDE(__stack_size = __stack_size); - __heap_size = DEFINED(__heap_size) ? __heap_size : 0x800; + __heap_size = DEFINED(__heap_size) ? __heap_size : 0x${heap_size}; /* Read-only sections, merged into text segment: */ PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x10000)); . = SEGMENT_START("text-segment", 0x10000) + SIZEOF_HEADERS; - /* We don't do any dynamic linking so we remove everything related to it */ -/* - .interp : { *(.interp) } - .note.gnu.build-id : { *(.note.gnu.build-id) } - .hash : { *(.hash) } - .gnu.hash : { *(.gnu.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - .rela.dyn : - { - *(.rela.init) - *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) - *(.rela.fini) - *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) - *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) - *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) - *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) - *(.rela.ctors) - *(.rela.dtors) - *(.rela.got) - *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) - *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) - *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) - *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) - *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) - PROVIDE_HIDDEN (__rela_iplt_start = .); - *(.rela.iplt) - PROVIDE_HIDDEN (__rela_iplt_end = .); - } - .rela.plt : - { - *(.rela.plt) - } -*/ - /* interrupt vectors */ .vectors (ORIGIN(ram0)): { @@ -97,11 +57,6 @@ SECTIONS KEEP (*(.text.start)) } >ram0 - /* More dynamic linking sections */ -/* - .plt : { *(.plt) } - .iplt : { *(.iplt) } -*/ /* the bulk of the program: main, libc, functions etc. */ .text : @@ -268,6 +223,8 @@ SECTIONS *(.data1) } >ram1 + _lma_vma_data_offset = 0x0; + /* no dynamic linking, no object tables required */ /* .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } */ @@ -335,11 +292,16 @@ SECTIONS PROVIDE(__freertos_irq_stack_top = .); } >ram1 -% if ram_numbanks_cont > 1 and ram_numbanks_il > 0: - .data_interleaved : +% for i, section in enumerate(xheep.iter_linker_sections()): +% if not section.name in ["code", "data"]: + .${section.name} : { - } >ram_il + . = ALIGN(4); + *(.xheep_${section.name}) + . = ALIGN(4); + } >ram${i} % endif +% endfor /* Stabs debugging sections. */ .stab 0 : { *(.stab) } diff --git a/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_exec.ld.tpl b/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_exec.ld.tpl index f8e0f83f..dca5e456 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_exec.ld.tpl +++ b/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_exec.ld.tpl @@ -8,7 +8,7 @@ ENTRY(_start) MEMORY { FLASH (rx) : ORIGIN = 0x${flash_mem_start_address}, LENGTH = 0x${flash_mem_size_address} - RAM (xrw) : ORIGIN = 0x${'{:08X}'.format(int(ram_start_address,16) + 4)}, LENGTH = 0x${'{:08X}'.format(int(ram_size_address,16) - 4)} + RAM (xrw) : ORIGIN = 0x${f'{xheep.ram_start_address()+4:08X}'}, LENGTH = 0x${f'{xheep.ram_size_address()-4:08X}'} } SECTIONS { @@ -17,9 +17,9 @@ SECTIONS { PROVIDE(__boot_address = 0x40000180); /* stack and heap related settings */ - __stack_size = DEFINED(__stack_size) ? __stack_size : 0x1000; + __stack_size = DEFINED(__stack_size) ? __stack_size : 0x${stack_size}; PROVIDE(__stack_size = __stack_size); - __heap_size = DEFINED(__heap_size) ? __heap_size : 0x1000; + __heap_size = DEFINED(__heap_size) ? __heap_size : 0x${heap_size}; /* interrupt vectors */ .vectors (ORIGIN(FLASH)): @@ -70,6 +70,8 @@ SECTIONS { _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ } >RAM AT >FLASH + _lma_vma_data_offset = 0x0; + .power_manager : ALIGN(4096) { PROVIDE(__power_manager_start = .); diff --git a/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_load.ld.tpl b/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_load.ld.tpl index a33ca3dd..9e7b637f 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_load.ld.tpl +++ b/hw/vendor/esl_epfl_x_heep/sw/linker/link_flash_load.ld.tpl @@ -7,47 +7,70 @@ ENTRY(_start) MEMORY { - FLASH (rx) : ORIGIN = 0x${flash_mem_start_address}, LENGTH = 0x${flash_mem_size_address} - RAM (xrw) : ORIGIN = 0x${'{:08X}'.format(int(ram_start_address,16))}, LENGTH = 0x${'{:08X}'.format(int(ram_size_address,16) - 4)} +<%flash_end = 0%> +% for i, section in enumerate(xheep.iter_linker_sections()): + ram${i} (rwxai) : ORIGIN = ${f"{section.start:#08x}"}, LENGTH = ${f"{section.size:#08x}"} + FLASH${i} (rx) : ORIGIN = ${f"{section.start + int(flash_mem_start_address,16):#08x}"}, LENGTH = ${f"{section.size:#08x}"} +<%flash_end = section.end%> +% endfor + FLASH_left (rx) : ORIGIN = ${f"{flash_end + int(flash_mem_start_address,16):#08x}"}, LENGTH = ${f"{int(flash_mem_size_address,16) - flash_end:#08x}"} } + + SECTIONS { /* we want a fixed entry point */ PROVIDE(__boot_address = 0x180); /* stack and heap related settings */ - __stack_size = DEFINED(__stack_size) ? __stack_size : 0x1000; + __stack_size = DEFINED(__stack_size) ? __stack_size : 0x${stack_size}; PROVIDE(__stack_size = __stack_size); - __heap_size = DEFINED(__heap_size) ? __heap_size : 0x1000; + __heap_size = DEFINED(__heap_size) ? __heap_size : 0x${heap_size}; /* interrupt vectors */ - .vectors (ORIGIN(RAM)): + .vectors (ORIGIN(ram0)): { PROVIDE(__vector_start = .); + _lma_text_start = LOADADDR(.vectors); KEEP(*(.vectors)); __VECTORS_AT = .; - } >RAM AT >FLASH + } >ram0 AT >FLASH0 /* Fill memory up to __boot_address */ .fill : { FILL(0xDEADBEEF); - . = ORIGIN(RAM) + (__boot_address) - 1; + . = ORIGIN(ram0) + (__boot_address) - 1; BYTE(0xEE) - } >RAM AT >FLASH + } >ram0 AT >FLASH0 /* crt0 init code */ .init (__boot_address): { KEEP (*(SORT_NONE(.init))) KEEP (*(.text.start)) - } >RAM AT >FLASH + KEEP (*(.text.w25q128jw_init_crt0)) + KEEP (*(.text.w25q128jw_sanity_checks)) + KEEP (*(.text.spi_write_word*)) + KEEP (*(.text.spi_wait_for_ready*)) + KEEP (*(.text.spi_create_command*)) + KEEP (*(.text.spi_set_command*)) + KEEP (*(.text.spi_set_rx_watermark*)) + KEEP (*(.text.spi_wait_for_rx_watermark*)) + KEEP (*(.text.spi_read_word*)) + KEEP (*(.text.memcpy)) + KEEP (*(.text.w25q128jw_read_standard)) /* as this function is used in the crt0, link it in the top, should be before 1024 Bytes loaded by the bootrom */ + KEEP (*(.text.w25q128jw_read_standard.*)) /* sometimes the function is renamed as w25q128jw_read_standard.part */ + *(.xheep_init_data_crt0) /* this global variables are used in the crt0 */ + KEEP (*_bswapsi2*(.text)) /* this function is used in the w25q128jw_read_standard */ + } >ram0 AT >FLASH0 /* The program code and other data goes into FLASH */ .text : ALIGN_WITH_INPUT { . = ALIGN(4); + __text_start = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */ @@ -56,16 +79,17 @@ SECTIONS { *(.srodata*) /* .rodata* sections (constants, strings, etc.) */ . = ALIGN(4); _etext = .; /* define a global symbol at end of code */ - } >RAM AT >FLASH + } >ram0 AT >FLASH0 /* This is the initialized data section The program executes knowing that the data is in the RAM but the loader puts the initial values in the FLASH (inidata). It is one task of the startup to copy the initial values from FLASH to RAM. */ - .data : ALIGN_WITH_INPUT + .data : ALIGN(256) { - . = ALIGN(4); + __data_start = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ _sidata = LOADADDR(.data); + _lma_data_start = LOADADDR(.data); _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */ _ram_start = .; /* create a global symbol at ram start for garbage collector */ . = ALIGN(4); @@ -75,18 +99,20 @@ SECTIONS { __SDATA_BEGIN__ = .; *(.sdata) /* .sdata sections */ *(.sdata*) /* .sdata* sections */ - . = ALIGN(4); - _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ - } >RAM AT >FLASH + } >ram1 AT >FLASH1 + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ - .power_manager : ALIGN(4096) + .power_manager : ALIGN_WITH_INPUT { + . = ALIGN(4); PROVIDE(__power_manager_start = .); . += 256; - } >RAM + } >ram1 AT >FLASH1 /* Uninitialized data section */ - .bss : + .bss : ALIGN_WITH_INPUT { . = ALIGN(4); __bss_start = .; /* define a global symbol at bss start; used by startup code */ @@ -99,7 +125,14 @@ SECTIONS { . = ALIGN(4); __bss_end = .; /* define a global symbol at bss end; used by startup code */ __BSS_END__ = .; - } >RAM + } >ram1 AT >FLASH1 + + _lma_data_end = _lma_data_start + SIZEOF(.data) + SIZEOF(.power_manager) + SIZEOF(.bss); + _lma_vma_data_offset = _lma_data_start - __data_start; + + _lma_text_end = _lma_text_start + SIZEOF(.vectors) + SIZEOF(.init) + SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.power_manager) + SIZEOF(.bss); + _lma_text_vma_offset = _lma_text_start - __vector_start; + /* The compiler uses this to access data in the .sdata, .data, .sbss and .bss sections with fewer instructions (relaxation). This reduces code size. */ @@ -112,7 +145,7 @@ SECTIONS { PROVIDE(__heap_start = .); . = __heap_size; PROVIDE(__heap_end = .); - } >RAM + } >ram1 /* stack: we should consider putting this further to the top of the address space */ @@ -123,5 +156,31 @@ SECTIONS { PROVIDE(_sp = .); PROVIDE(__stack_end = .); PROVIDE(__freertos_irq_stack_top = .); - } >RAM + } >ram1 + + % for i, section in enumerate(xheep.iter_linker_sections()): + % if not section.name in ["code", "data"]: + .${section.name} : ALIGN_WITH_INPUT + { + PROVIDE(__${section.name}_start = .); + _lma_${section.name}_start = LOADADDR(.${section.name}); + . = ALIGN(4); + *(.xheep_${section.name}) + . = ALIGN(4); + } >ram${i} AT >FLASH${i} + + . = ALIGN(4); + _ed${section.name} = .; + _lma_${section.name}_end = _lma_${section.name}_start + SIZEOF(.${section.name}); + + % endif + % endfor + + .data_flash_only : ALIGN(256) + { + . = ALIGN(4); + *(.xheep_data_flash_only) + . = ALIGN(4); + } >FLASH_left + } diff --git a/hw/vendor/esl_epfl_x_heep/sw/vendor/patches/yosyshq_icestorm/0001-Add-flash-prgraner-iceprog-custom-for-heep-with-gpio.patch b/hw/vendor/esl_epfl_x_heep/sw/vendor/patches/yosyshq_icestorm/0001-Add-flash-prgraner-iceprog-custom-for-heep-with-gpio.patch index b325b7bc..1af9cacb 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/vendor/patches/yosyshq_icestorm/0001-Add-flash-prgraner-iceprog-custom-for-heep-with-gpio.patch +++ b/hw/vendor/esl_epfl_x_heep/sw/vendor/patches/yosyshq_icestorm/0001-Add-flash-prgraner-iceprog-custom-for-heep-with-gpio.patch @@ -1,8 +1,43 @@ diff --git a/iceprog/iceprog.c b/iceprog/iceprog.c -index 8ee6443..38e308f 100644 +index 8ee6443..0413697 100644 --- a/iceprog/iceprog.c +++ b/iceprog/iceprog.c -@@ -506,6 +506,7 @@ static void help(const char *progname) +@@ -480,6 +480,34 @@ static void flash_enable_quad() + fprintf(stderr, "SR2: %08x\n", data[1]); + } + ++static void flash_disable_quad() ++{ ++ fprintf(stderr, "Disabling Quad operation...\n"); ++ ++ // Allow write ++ flash_write_enable(); ++ ++ // Write Status Register 2 <- 0x00 ++ uint8_t data[2] = { FC_WSR2, 0x00 }; ++ flash_chip_select(); ++ mpsse_xfer_spi(data, 2); ++ flash_chip_deselect(); ++ ++ flash_wait(); ++ ++ // Read Status Register 1 ++ data[0] = FC_RSR2; ++ ++ flash_chip_select(); ++ mpsse_xfer_spi(data, 2); ++ flash_chip_deselect(); ++ ++ if ((data[1] & 0x02) != 0x00) ++ fprintf(stderr, "failed to set QE=0, SR2 now equal to 0x%02x (expected 0x%02x)\n", data[1], data[1] | 0x00); ++ ++ fprintf(stderr, "SR2: %08x\n", data[1]); ++} ++ + // --------------------------------------------------------- + // iceprog implementation + // --------------------------------------------------------- +@@ -506,11 +534,13 @@ static void help(const char *progname) fprintf(stderr, " -s slow SPI (50 kHz instead of 6 MHz)\n"); fprintf(stderr, " -k keep flash in powered up state (i.e. skip power down command)\n"); fprintf(stderr, " -v verbose output\n"); @@ -10,25 +45,61 @@ index 8ee6443..38e308f 100644 fprintf(stderr, " -i [4,32,64] select erase block size [default: 64k]\n"); fprintf(stderr, "\n"); fprintf(stderr, "Mode of operation:\n"); -@@ -587,6 +588,8 @@ int main(int argc, char **argv) + fprintf(stderr, " [default] write file contents to flash, then verify\n"); + fprintf(stderr, " -X write file contents to flash only\n"); ++ fprintf(stderr, " -a provides file size of the file to program\n"); + fprintf(stderr, " -r read first 256 kB from flash and write to file\n"); + fprintf(stderr, " -R read the specified number of bytes from flash\n"); + fprintf(stderr, " (append 'k' to the argument for size in kilobytes,\n"); +@@ -578,6 +608,7 @@ int main(int argc, char **argv) + bool bulk_erase = false; + bool dont_erase = false; + bool prog_sram = false; ++ bool filesize_mode = false; + int test_mode = 0; + bool slow_clock = false; + bool disable_protect = false; +@@ -587,6 +618,9 @@ int main(int argc, char **argv) const char *devstr = NULL; int ifnum = 0; + bool stop_spi = false; ++ long file_size = -1; + #ifdef _WIN32 _setmode(_fileno(stdin), _O_BINARY); _setmode(_fileno(stdout), _O_BINARY); -@@ -600,7 +603,7 @@ int main(int argc, char **argv) +@@ -600,7 +634,7 @@ int main(int argc, char **argv) /* Decode command line parameters */ int opt; char *endptr; - while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:cbnStQvspXk", long_options, NULL)) != -1) { -+ while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:cbnStQvTspXk", long_options, NULL)) != -1) { ++ while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:a:cbnStQvTspXk", long_options, NULL)) != -1) { switch (opt) { case 'd': /* device string */ devstr = optarg; -@@ -696,6 +699,9 @@ int main(int argc, char **argv) +@@ -648,6 +682,20 @@ int main(int argc, char **argv) + return EXIT_FAILURE; + } + break; ++ case 'a': /* filesize used to program flash */ ++ filesize_mode = true; ++ file_size = strtol(optarg, &endptr, 0); ++ if (*endptr == '\0') ++ /* ok */; ++ else if (!strcmp(endptr, "k")) ++ file_size *= 1024; ++ else if (!strcmp(endptr, "M")) ++ file_size *= 1024 * 1024; ++ else { ++ fprintf(stderr, "%s: `%s' is not a valid size\n", my_name, optarg); ++ return EXIT_FAILURE; ++ } ++ break; + case 'e': /* Erase blocks as if we were writing n bytes */ + erase_mode = true; + erase_size = strtol(optarg, &endptr, 0); +@@ -696,6 +744,9 @@ int main(int argc, char **argv) case 'v': /* provide verbose output */ verbose = true; break; @@ -38,7 +109,46 @@ index 8ee6443..38e308f 100644 case 's': /* use slow SPI clock */ slow_clock = true; break; -@@ -997,22 +1003,59 @@ int main(int argc, char **argv) +@@ -778,7 +829,7 @@ int main(int argc, char **argv) + so we can fail before initializing the hardware */ + + FILE *f = NULL; +- long file_size = -1; ++ + + if (test_mode) { + /* nop */; +@@ -809,7 +860,7 @@ int main(int argc, char **argv) + named pipe, or contrarily, the standard input may be an + ordinary file. */ + +- if (!prog_sram && !check_mode) { ++ if (!prog_sram && !check_mode && !filesize_mode) { + if (fseek(f, 0L, SEEK_END) != -1) { + file_size = ftell(f); + if (file_size == -1) { +@@ -943,6 +994,8 @@ int main(int argc, char **argv) + flash_reset(); + flash_power_up(); + ++ flash_disable_quad(); ++ + flash_read_id(); + + +@@ -968,7 +1021,10 @@ int main(int argc, char **argv) + } + else + { +- fprintf(stderr, "file size: %ld\n", file_size); ++ if(filesize_mode) ++ fprintf(stderr, "provided file size: %ld\n", file_size); ++ else ++ fprintf(stderr, "file size: %ld\n", file_size); + + int block_size = erase_block_size << 10; + int block_mask = block_size - 1; +@@ -997,22 +1053,59 @@ int main(int argc, char **argv) } } @@ -62,7 +172,7 @@ index 8ee6443..38e308f 100644 + size_t len = 0; + uint8_t buffer[256]; + int count = 0; -+ while (true) { ++ while (true) { + rc = getline(&line_buffer, &len, f); + if (rc <= 0){ + if(count > 0){ @@ -107,20 +217,22 @@ index 8ee6443..38e308f 100644 fprintf(stderr, " \r"); fprintf(stderr, "done.\n"); -@@ -1026,6 +1069,12 @@ int main(int argc, char **argv) +@@ -1026,7 +1119,13 @@ int main(int argc, char **argv) // --------------------------------------------------------- if (read_mode) { +- fprintf(stderr, "reading..\n"); + if(stop_spi){ + /* Just to debug reading of values with the logic analyzer*/ + printf("Stoped before writting. Press ENTER to continue\n"); + getchar(); + } + - fprintf(stderr, "reading..\n"); ++ fprintf(stderr, "reading.."); for (int addr = 0; addr < read_size; addr += 256) { uint8_t buffer[256]; -@@ -1037,23 +1086,40 @@ int main(int argc, char **argv) + fprintf(stderr, " \r"); +@@ -1037,23 +1136,40 @@ int main(int argc, char **argv) fprintf(stderr, " \r"); fprintf(stderr, "done.\n"); } else if (!erase_mode && !disable_verify) { @@ -134,7 +246,7 @@ index 8ee6443..38e308f 100644 + int rc, addr = 0; + size_t len = 0; + uint8_t buffer_flash[256], buffer_file[256]; -+ while (true) { ++ while (true) { + rc = getline(&line_buffer, &len, f); if (rc <= 0) break; diff --git a/hw/vendor/esl_epfl_x_heep/sw/vendor/yosyshq_icestorm/iceprog/iceprog.c b/hw/vendor/esl_epfl_x_heep/sw/vendor/yosyshq_icestorm/iceprog/iceprog.c index 38e308f8..0413697d 100644 --- a/hw/vendor/esl_epfl_x_heep/sw/vendor/yosyshq_icestorm/iceprog/iceprog.c +++ b/hw/vendor/esl_epfl_x_heep/sw/vendor/yosyshq_icestorm/iceprog/iceprog.c @@ -480,6 +480,34 @@ static void flash_enable_quad() fprintf(stderr, "SR2: %08x\n", data[1]); } +static void flash_disable_quad() +{ + fprintf(stderr, "Disabling Quad operation...\n"); + + // Allow write + flash_write_enable(); + + // Write Status Register 2 <- 0x00 + uint8_t data[2] = { FC_WSR2, 0x00 }; + flash_chip_select(); + mpsse_xfer_spi(data, 2); + flash_chip_deselect(); + + flash_wait(); + + // Read Status Register 1 + data[0] = FC_RSR2; + + flash_chip_select(); + mpsse_xfer_spi(data, 2); + flash_chip_deselect(); + + if ((data[1] & 0x02) != 0x00) + fprintf(stderr, "failed to set QE=0, SR2 now equal to 0x%02x (expected 0x%02x)\n", data[1], data[1] | 0x00); + + fprintf(stderr, "SR2: %08x\n", data[1]); +} + // --------------------------------------------------------- // iceprog implementation // --------------------------------------------------------- @@ -512,6 +540,7 @@ static void help(const char *progname) fprintf(stderr, "Mode of operation:\n"); fprintf(stderr, " [default] write file contents to flash, then verify\n"); fprintf(stderr, " -X write file contents to flash only\n"); + fprintf(stderr, " -a provides file size of the file to program\n"); fprintf(stderr, " -r read first 256 kB from flash and write to file\n"); fprintf(stderr, " -R read the specified number of bytes from flash\n"); fprintf(stderr, " (append 'k' to the argument for size in kilobytes,\n"); @@ -579,6 +608,7 @@ int main(int argc, char **argv) bool bulk_erase = false; bool dont_erase = false; bool prog_sram = false; + bool filesize_mode = false; int test_mode = 0; bool slow_clock = false; bool disable_protect = false; @@ -589,6 +619,7 @@ int main(int argc, char **argv) int ifnum = 0; bool stop_spi = false; + long file_size = -1; #ifdef _WIN32 _setmode(_fileno(stdin), _O_BINARY); @@ -603,7 +634,7 @@ int main(int argc, char **argv) /* Decode command line parameters */ int opt; char *endptr; - while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:cbnStQvTspXk", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:a:cbnStQvTspXk", long_options, NULL)) != -1) { switch (opt) { case 'd': /* device string */ devstr = optarg; @@ -651,6 +682,20 @@ int main(int argc, char **argv) return EXIT_FAILURE; } break; + case 'a': /* filesize used to program flash */ + filesize_mode = true; + file_size = strtol(optarg, &endptr, 0); + if (*endptr == '\0') + /* ok */; + else if (!strcmp(endptr, "k")) + file_size *= 1024; + else if (!strcmp(endptr, "M")) + file_size *= 1024 * 1024; + else { + fprintf(stderr, "%s: `%s' is not a valid size\n", my_name, optarg); + return EXIT_FAILURE; + } + break; case 'e': /* Erase blocks as if we were writing n bytes */ erase_mode = true; erase_size = strtol(optarg, &endptr, 0); @@ -784,7 +829,7 @@ int main(int argc, char **argv) so we can fail before initializing the hardware */ FILE *f = NULL; - long file_size = -1; + if (test_mode) { /* nop */; @@ -815,7 +860,7 @@ int main(int argc, char **argv) named pipe, or contrarily, the standard input may be an ordinary file. */ - if (!prog_sram && !check_mode) { + if (!prog_sram && !check_mode && !filesize_mode) { if (fseek(f, 0L, SEEK_END) != -1) { file_size = ftell(f); if (file_size == -1) { @@ -949,6 +994,8 @@ int main(int argc, char **argv) flash_reset(); flash_power_up(); + flash_disable_quad(); + flash_read_id(); @@ -974,7 +1021,10 @@ int main(int argc, char **argv) } else { - fprintf(stderr, "file size: %ld\n", file_size); + if(filesize_mode) + fprintf(stderr, "provided file size: %ld\n", file_size); + else + fprintf(stderr, "file size: %ld\n", file_size); int block_size = erase_block_size << 10; int block_mask = block_size - 1; @@ -1018,7 +1068,7 @@ int main(int argc, char **argv) size_t len = 0; uint8_t buffer[256]; int count = 0; - while (true) { + while (true) { rc = getline(&line_buffer, &len, f); if (rc <= 0){ if(count > 0){ @@ -1075,7 +1125,7 @@ int main(int argc, char **argv) getchar(); } - fprintf(stderr, "reading..\n"); + fprintf(stderr, "reading.."); for (int addr = 0; addr < read_size; addr += 256) { uint8_t buffer[256]; fprintf(stderr, " \r"); @@ -1093,7 +1143,7 @@ int main(int argc, char **argv) int rc, addr = 0; size_t len = 0; uint8_t buffer_flash[256], buffer_file[256]; - while (true) { + while (true) { rc = getline(&line_buffer, &len, f); if (rc <= 0) break; diff --git a/hw/vendor/esl_epfl_x_heep/tb/XHEEP_CmdLineOptions.cpp b/hw/vendor/esl_epfl_x_heep/tb/XHEEP_CmdLineOptions.cpp new file mode 100644 index 00000000..947d31ef --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/tb/XHEEP_CmdLineOptions.cpp @@ -0,0 +1,100 @@ +#include "XHEEP_CmdLineOptions.hh" +#include +#include + +XHEEP_CmdLineOptions::XHEEP_CmdLineOptions(int argc, char* argv[]) // define default constructor +{ + this->argc = argc; + this->argv = argv; +} + +std::string XHEEP_CmdLineOptions::getCmdOption(int argc, char* argv[], const std::string& option) +{ + std::string cmd; + for( int i = 0; i < argc; ++i) + { + std::string arg = argv[i]; + size_t arg_size = arg.length(); + size_t option_size = option.length(); + + if(arg.find(option)==0){ + cmd = arg.substr(option_size,arg_size-option_size); + } + } + return cmd; +} + +bool XHEEP_CmdLineOptions::get_use_openocd() +{ + + std::string arg_openocd = this->getCmdOption(this->argc, this->argv, "+openOCD=");; + + bool use_openocd = false; + + if(arg_openocd.empty()){ + std::cout<<"[TESTBENCH]: No OpenOCD is used"<getCmdOption(this->argc, this->argv, "+firmware="); + + if(firmware.empty()){ + std::cout<<"[TESTBENCH]: No firmware specified"<getCmdOption(this->argc, this->argv, "+max_sim_time="); + unsigned int max_sim_time; + + max_sim_time = 0; + if(arg_max_sim_time.empty()){ + std::cout<<"[TESTBENCH]: No Max time specified"<getCmdOption(this->argc, this->argv, "+boot_sel="); + unsigned int boot_sel = 0; + + if(arg_boot_sel.empty()){ + std::cout<<"[TESTBENCH]: No Boot Option specified, using jtag (boot_sel=0)"< + +class XHEEP_CmdLineOptions // declare Calculator class +{ + + public: // public members + XHEEP_CmdLineOptions(int argc, char* argv[]); // default constructor + + std::string getCmdOption(int argc, char* argv[], const std::string& option); // get options from cmd lines + bool get_use_openocd(); + std::string get_firmware(); + unsigned int get_max_sim_time(bool& run_all); + unsigned int get_boot_sel(); + int argc; + char** argv; + +}; + + + +#endif diff --git a/hw/vendor/esl_epfl_x_heep/tb/core-v-mini-mcu-pynq-z2-bscan.cfg b/hw/vendor/esl_epfl_x_heep/tb/core-v-mini-mcu-pynq-z2-bscan.cfg new file mode 100644 index 00000000..f0134765 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/tb/core-v-mini-mcu-pynq-z2-bscan.cfg @@ -0,0 +1,44 @@ +adapter driver ftdi +adapter speed 1000 +transport select jtag + + +# FT2232HQ Adapter Pynq Z2 +ftdi_vid_pid 0x0403 0x6010 + +ftdi_channel 0 +ftdi_layout_init 0x0088 0x008b + +reset_config none + +echo "ftdi setting..." + +set _CHIPNAME riscv +jtag newtap $_CHIPNAME cpu -irlen 6 -expected-id 0x23727093 +jtag newtap arm_dap_0 tap -irlen 4 -expected-id 0x4ba00477 + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid 0x000 + +echo "target created..." + +#log_output openocd_fpga.log + +riscv set_ir idcode 0x09 +riscv set_ir dtmcs 0x22 +riscv set_ir dmi 0x23 + +riscv set_reset_timeout_sec 2000 +riscv set_command_timeout_sec 2000 + +echo "setting preferences..." + +scan_chain + +init + +echo "init routine started" + +halt + +echo "Ready for Remote Connections" \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/tb/ext_bus.sv b/hw/vendor/esl_epfl_x_heep/tb/ext_bus.sv index 74755de3..beed1bcf 100644 --- a/hw/vendor/esl_epfl_x_heep/tb/ext_bus.sv +++ b/hw/vendor/esl_epfl_x_heep/tb/ext_bus.sv @@ -34,14 +34,14 @@ module ext_bus #( input obi_pkg::obi_req_t heep_debug_master_req_i, output obi_pkg::obi_resp_t heep_debug_master_resp_o, - input obi_pkg::obi_req_t heep_dma_read_ch0_req_i, - output obi_pkg::obi_resp_t heep_dma_read_ch0_resp_o, + input obi_pkg::obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] heep_dma_read_req_i , + output obi_pkg::obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] heep_dma_read_resp_o, - input obi_pkg::obi_req_t heep_dma_write_ch0_req_i, - output obi_pkg::obi_resp_t heep_dma_write_ch0_resp_o, + input obi_pkg::obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] heep_dma_write_req_i, + output obi_pkg::obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] heep_dma_write_resp_o, - input obi_pkg::obi_req_t heep_dma_addr_ch0_req_i, - output obi_pkg::obi_resp_t heep_dma_addr_ch0_resp_o, + input obi_pkg::obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] heep_dma_addr_req_i , + output obi_pkg::obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] heep_dma_addr_resp_o, // External master ports input obi_pkg::obi_req_t [EXT_XBAR_NMASTER_RND-1:0] ext_master_req_i, @@ -67,7 +67,7 @@ module ext_bus #( obi_req_t [EXT_XBAR_NMASTER-1:0][1:0] demux_xbar_req; obi_resp_t [EXT_XBAR_NMASTER-1:0][1:0] demux_xbar_resp; - // Dummy external master portp (to prevent unused warning) + // Dummy external master port (to prevent unused warning) obi_req_t [EXT_XBAR_NMASTER_RND-1:0] ext_master_req_unused; obi_resp_t [EXT_XBAR_NMASTER_RND-1:0] heep_slave_resp_unused; obi_resp_t [EXT_XBAR_NSLAVE_RND-1:0] ext_slave_resp_unused; @@ -80,9 +80,17 @@ module ext_bus #( assign master_req[CORE_INSTR_IDX] = heep_core_instr_req_i; assign master_req[CORE_DATA_IDX] = heep_core_data_req_i; assign master_req[DEBUG_MASTER_IDX] = heep_debug_master_req_i; - assign master_req[DMA_READ_CH0_IDX] = heep_dma_read_ch0_req_i; - assign master_req[DMA_WRITE_CH0_IDX] = heep_dma_write_ch0_req_i; - assign master_req[DMA_ADDR_CH0_IDX] = heep_dma_addr_ch0_req_i; + + generate + for ( + genvar i = 0; i < core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS; i++ + ) begin : gen_dma_master_req_map + assign master_req[core_v_mini_mcu_pkg::DMA_READ_P0_IDX+i*3] = heep_dma_read_req_i[i]; + assign master_req[core_v_mini_mcu_pkg::DMA_WRITE_P0_IDX+i*3] = heep_dma_write_req_i[i]; + assign master_req[core_v_mini_mcu_pkg::DMA_ADDR_P0_IDX+i*3] = heep_dma_addr_req_i[i]; + end + endgenerate + generate for (genvar i = 0; i < EXT_XBAR_NMASTER; i++) begin : gen_ext_master_req_map assign master_req[SYSTEM_XBAR_NMASTER+i] = demux_xbar_req[i][DEMUX_XBAR_EXT_SLAVE_IDX]; @@ -93,9 +101,16 @@ module ext_bus #( assign heep_core_instr_resp_o = master_resp[CORE_INSTR_IDX]; assign heep_core_data_resp_o = master_resp[CORE_DATA_IDX]; assign heep_debug_master_resp_o = master_resp[DEBUG_MASTER_IDX]; - assign heep_dma_read_ch0_resp_o = master_resp[DMA_READ_CH0_IDX]; - assign heep_dma_write_ch0_resp_o = master_resp[DMA_WRITE_CH0_IDX]; - assign heep_dma_addr_ch0_resp_o = master_resp[DMA_ADDR_CH0_IDX]; + + generate + for ( + genvar i = 0; i < core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS; i++ + ) begin : gen_dma_master_resp_map + assign heep_dma_read_resp_o[i] = master_resp[core_v_mini_mcu_pkg::DMA_READ_P0_IDX+i]; + assign heep_dma_write_resp_o[i] = master_resp[core_v_mini_mcu_pkg::DMA_WRITE_P0_IDX+i]; + assign heep_dma_addr_resp_o[i] = master_resp[core_v_mini_mcu_pkg::DMA_ADDR_P0_IDX+i]; + end + endgenerate // X-HEEP slave requests generate @@ -122,8 +137,9 @@ module ext_bus #( // show writes if requested always_ff @(posedge clk_i, negedge rst_ni) begin : verbose_writes if ($test$plusargs("verbose") != 0 && heep_core_data_req_i.req && heep_core_data_req_i.we) - $display("write addr=0x%08x: data=0x%08x", heep_core_data_req_i.addr, - heep_core_data_req_i.wdata); + $display( + "write addr=0x%08x: data=0x%08x", heep_core_data_req_i.addr, heep_core_data_req_i.wdata + ); end `endif diff --git a/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/Cache.h b/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/Cache.h new file mode 100644 index 00000000..d9c94b5d --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/Cache.h @@ -0,0 +1,221 @@ +#ifndef CACHE_H +#define CACHE_H + +#include +#include +#include +#include + + +// Target module representing a simple direct mapped cache +class CacheMemory +{ + +public: + uint32_t cache_size_byte = 4*1024; + uint32_t number_of_blocks = 256; + + uint32_t nbits_blocks = 0; + uint32_t nbits_tags = 0; + uint32_t nbits_index = 0; + uint32_t block_size_byte = 0; + + enum { ARCHITECTURE_bits = 32 }; + + std::ofstream cacheFile; + + typedef struct cache_line { + uint32_t tag; + bool valid; + uint8_t* data; + } cache_line_t; + + cache_line_t* cache_array; + + + CacheMemory(): cacheFile("cache_status.log") + { + cache_array = NULL; + } + + void create_cache() { + cache_array = new cache_line_t[number_of_blocks]; + this->block_size_byte = get_block_size(); + this->nbits_blocks = log2(block_size_byte); + this->nbits_index = log2(number_of_blocks); + this->nbits_tags = ARCHITECTURE_bits - nbits_index - nbits_blocks; + printf("bits block %d, index %d, tags %d\n",nbits_blocks, nbits_index, nbits_tags ); + } + + void create_cache(uint32_t cache_size_byte, uint32_t number_of_blocks) { + this->cache_size_byte = cache_size_byte; + this->number_of_blocks = number_of_blocks; + cache_array = new cache_line_t[number_of_blocks]; + this->block_size_byte = get_block_size(); + this->nbits_blocks = log2(block_size_byte); + this->nbits_index = log2(number_of_blocks); + this->nbits_tags = ARCHITECTURE_bits - nbits_index - nbits_blocks; + } + + uint32_t initialize_cache() { + if(cache_array == NULL) { + return -1; + } + // Initialize memory with random data + for (int i = 0; i < number_of_blocks; i++) { + cache_array[i].valid = false; + cache_array[i].tag = 0; + cache_array[i].data = new uint8_t[block_size_byte]; + for(int j = 0; j> nbits_blocks) & mask_index ); + } + + uint32_t get_block_offset(uint32_t address) { + uint32_t mask_block = (1 << nbits_blocks) - 1; + return (uint32_t)(address & mask_block); + } + + uint32_t get_base_address(uint32_t address) { + return (uint32_t)((address >> nbits_blocks) << nbits_blocks); + } + + uint32_t get_tag(uint32_t address) { + return (uint32_t)(address >> (nbits_index+nbits_blocks)); + } + + uint32_t get_tag_from_index(uint32_t index) { + return cache_array[index].tag; + } + + + bool cache_hit(uint32_t address) { + uint32_t index = get_index(address); + uint32_t tag = get_tag(address); + return ( cache_array[index].valid && tag == cache_array[index].tag); + + } + + void add_entry(uint32_t address, uint8_t* new_data) { + uint32_t index = get_index(address); + uint32_t tag = get_tag(address); + cache_array[index].valid = true; + cache_array[index].tag = tag; + memcpy(cache_array[index].data, new_data, block_size_byte); + } + + void get_data(uint32_t address, uint8_t* new_data) { + uint32_t index = get_index(address); + memcpy(new_data, cache_array[index].data, block_size_byte); + } + + void get_data_at_index(uint32_t index, uint8_t* new_data) { + memcpy(new_data, cache_array[index].data, block_size_byte); + } + + uint32_t get_address(uint32_t address){ + uint32_t index = get_index(address); + uint32_t tag = cache_array[index].tag; + uint32_t new_address = (tag << (nbits_index+nbits_blocks)) | (index<get_block_offset(address); + uint8_t* new_data = new uint8_t[block_size_byte]; + this->get_data(address, new_data); + data_word = *((int32_t *)&new_data[block_offset]); + delete new_data; + return data_word; + } + + void set_word(uint32_t address, int32_t data_word) { + uint32_t block_offset = this->get_block_offset(address); + uint8_t* new_data = new uint8_t[block_size_byte]; + this->get_data(address, new_data); + *((int32_t *)&new_data[block_offset]) = data_word; + for(int i=0;iadd_entry(address, new_data); + delete new_data; + } + + bool is_entry_valid(uint32_t address) { + uint32_t index = get_index(address); + return cache_array[index].valid; + } + + bool is_entry_valid_at_index(uint32_t index) { + return cache_array[index].valid; + } + + void print_cache_status(uint32_t operation_id, std::string time_str) { + if (cacheFile.is_open()) { + std::string log_cache = ""; + std::ostringstream ss; + + log_cache+= std::to_string(operation_id) + "): " + time_str + "\n"; + log_cache+= "INDEX | TAG | DATA BLOCK | VALID\n"; + + for(int i=0;inbits_index/4) << std::setfill('0') << std::hex << static_cast(i); + log_cache+= ss.str() + " | "; + ss.str(""); + ss.clear(); + ss << "0x" << std::setw(this->nbits_tags/4) << std::setfill('0') << std::hex << cache_array[i].tag; + log_cache+= ss.str() + " | 0x"; + ss.str(""); + ss.clear(); + for(int j = 0; j(cache_array[i].data[j]); + log_cache+= ss.str() + " | "; + log_cache+= std::string( cache_array[i].valid ? "1" : "0" ) + "\n"; + + cacheFile << log_cache; + ss.str(""); + ss.clear(); + log_cache = std::string(""); + } + } else { + std::cout << "Failed to create the Cache file." << std::endl; + } + } + + /* main memory address + 0x7052 = 'b111_0000_0101_0010' + + cache size = 4KB, + number_of_blocks = 256, thus index is on 8bit + block_size_in_byte = 4KB/256 = 16bytes, i.e. 4 words + + 111: tag + 0000_0101: used as index + 0010: used for block offset , 4bits as 16 bytes + + + get_tag(0x7052) --> 0x7 + get_index(0x7052) --> 0x5 + get_block_offset(0x7052) --> 0x2 + + + */ +}; + +#endif diff --git a/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MainMemory.h b/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MainMemory.h new file mode 100644 index 00000000..984f81cf --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MainMemory.h @@ -0,0 +1,68 @@ +#ifndef MEMORY_H +#define MEMORY_H + +// Needed for the simple_target_socket +#define SC_INCLUDE_DYNAMIC_PROCESSES + +#include "systemc" +using namespace sc_core; +using namespace sc_dt; +using namespace std; + +#include "tlm.h" +#include "tlm_utils/simple_target_socket.h" + + +// Target module representing a simple direct mapped cache +SC_MODULE(MainMemory) +{ + // TLM-2 socket, defaults to 32-bits wide, base protocol + tlm_utils::simple_target_socket socket; + + enum { SIZE = 32*1024/4 }; //32KB word addressable + + int32_t mem[SIZE]; + + + SC_CTOR(MainMemory) + : socket("socket") + { + // Register callback for incoming b_transport interface method call + socket.register_b_transport(this, &MainMemory::b_transport); + + // Initialize memory with random data + for (int i = 0; i < SIZE; i++) + mem[i] = 0xAA000000 | (rand() % 256); + } + + // TLM-2 blocking transport method + virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) + { + tlm::tlm_command cmd = trans.get_command(); + sc_dt::uint64 adr = trans.get_address() / 4; + unsigned char* ptr = trans.get_data_ptr(); + unsigned int len = trans.get_data_length(); + unsigned char* byt = trans.get_byte_enable_ptr(); + unsigned int wid = trans.get_streaming_width(); + + // Obliged to check address range and check for unsupported features, + // i.e. byte enables, streaming, and bursts + // Can ignore DMI hint and extensions + // Using the SystemC report handler is an acceptable way of signalling an error + + if (adr >= sc_dt::uint64(SIZE) || byt != 0 || len > 4 || wid < len) + SC_REPORT_ERROR("TLM-2", "Target does not support given generic payload transaction"); + + // Obliged to implement read and write commands + if ( cmd == tlm::TLM_READ_COMMAND ) + memcpy(ptr, &mem[adr], len); + else if ( cmd == tlm::TLM_WRITE_COMMAND ) + memcpy(&mem[adr], ptr, len); + + // Obliged to set response status to indicate successful completion + trans.set_response_status( tlm::TLM_OK_RESPONSE ); + } + +}; + +#endif diff --git a/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MemoryRequest.h b/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MemoryRequest.h new file mode 100644 index 00000000..c0a7d1c7 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/tb/systemc_tb/MemoryRequest.h @@ -0,0 +1,241 @@ +#ifndef MEMORYREQUEST_H +#define MEMORYREQUEST_H + +#include "systemc" +using namespace sc_core; +using namespace sc_dt; +using namespace std; + +#include "tlm.h" +#include "tlm_utils/simple_initiator_socket.h" + +#include "Cache.h" + +#include +#include +#include +#include + +// MemoryRequest module generating generic payload transactions + +SC_MODULE(MemoryRequest) +{ + // TLM-2 socket, defaults to 32-bits wide, base protocol + tlm_utils::simple_initiator_socket socket; + bool we_i; + uint32_t be_i; + uint32_t addr_i; + uint32_t rwdata_io; + CacheMemory* cache; + std::ofstream heep_mem_transactions; + bool bypass_state = false; + + typedef struct cache_statistics + { + uint32_t number_of_transactions; + uint32_t number_of_hit; + uint32_t number_of_miss; + } cache_statistics_t; + + cache_statistics_t cache_stat; + + SC_CTOR(MemoryRequest) + : socket("socket"), // Construct and name socket + heep_mem_transactions("heep_mem_transactions.log") + { + + cache = new CacheMemory; + cache->create_cache(); + cache->initialize_cache(); + cache_stat.number_of_transactions = 0; + cache_stat.number_of_hit = 0; + cache_stat.number_of_miss = 0; + cache->print_cache_status(cache_stat.number_of_transactions++, sc_time_stamp().to_string()); + + SC_THREAD(thread_process); + } + + + uint32_t memory_copy(uint32_t addr, int32_t* buffer_data, int N, bool write_enable, tlm::tlm_generic_payload* trans, sc_time delay) { + + tlm::tlm_command cmd = write_enable ? tlm::TLM_WRITE_COMMAND : tlm::TLM_READ_COMMAND; + + //first read block_size bytes from memory to place them in cache regardless of the cmd + for(int i=0; i < N; i++){ + trans->set_command( cmd ); + trans->set_address( (addr + i*4) & 0x00007FFF ); //15bits + trans->set_data_ptr( reinterpret_cast(&buffer_data[i]) ); + trans->set_data_length( 4 ); + trans->set_streaming_width( 4 ); // = data_length to indicate no streaming + trans->set_byte_enable_ptr( 0 ); // 0 indicates unused + trans->set_dmi_allowed( false ); // Mandatory initial value + trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); // Mandatory initial value + socket->b_transport( *trans, delay ); // Blocking transport call + + if(bypass_state){ + if(write_enable) + heep_mem_transactions << "Writing to Mem[" << hex << ((addr + i*4) & 0x00007FFF) << "]: " << buffer_data[i] << " at time " << sc_time_stamp() <is_response_error() ) + SC_REPORT_ERROR("TLM-2", "Response error from b_transport"); + } + return N; + } + + + void thread_process() + { + // TLM-2 generic payload transaction, reused across calls to b_transport + tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload; + + sc_time delay_gnt_miss = sc_time(100, SC_NS); + sc_time delay_rvalid_miss = sc_time(100, SC_NS); + + sc_time delay_rvalid_hit = sc_time(20, SC_NS); //as of today, it must be >=20 + + sc_time delay = sc_time(1, SC_NS); + + uint32_t cache_block_size_byte = cache->get_block_size(); + uint32_t cache_block_size_word = cache->get_block_size()/4; + uint8_t* cache_data = new uint8_t[cache_block_size_byte]; + int32_t* main_mem_data = new int32_t[cache_block_size_word]; + uint32_t address_to_replace; + uint32_t cache_flushed; + + while(true) { + + wait(obi_new_req); + + heep_mem_transactions << "X-HEEP tlm_generic_payload REQ: { " << (we_i ? 'W' : 'R') << ", @0x" << hex << addr_i + << " , DATA = 0x" << hex << rwdata_io << " BE = " << hex << be_i <<", at time " << sc_time_stamp() << " }" << std::endl; + + if(be_i!=0xF) { + SC_REPORT_ERROR("OBI External Memory SystemC", "ByteEnable different than 0xF is not supported"); + } + + //if we are writing 1 or 2 to last address, flush cache or bypass + if(we_i && ((addr_i & 0x00007FFF) == 0x7FFC)){ + + if(rwdata_io == 1){ + //FLUSH Cache + heep_mem_transactions << "X-HEEP Flush Cache, at time " << sc_time_stamp() << " }" << std::endl; + uint32_t cache_number_of_blocks = cache->number_of_blocks; + heep_mem_transactions<<"Cache Flushing at time "<is_entry_valid_at_index(i)) { + cache_flushed++; + //if we are going to replace a valid entry + cache->get_data_at_index(i, cache_data); + address_to_replace = cache->get_address_at_index(i); + //write back + memory_copy(address_to_replace, (uint32_t *)cache_data, cache_block_size_word, true, trans, delay); + } + } + heep_mem_transactions<<"Cache Flushed "<< dec << cache_flushed << " entries"<cache_hit(addr_i)){ + + heep_mem_transactions << "Cache HIT on address " << hex << addr_i << " at time " << sc_time_stamp() <get_word(addr_i); + //if Write, writes to cache + if(we_i) + cache->set_word(addr_i, rwdata_io); + else + rwdata_io = main_mem_data[0]; + wait(delay_rvalid_hit); + } + + else { //miss case + + cache_stat.number_of_miss++; + + heep_mem_transactions << "Cache MISS on address " << hex << addr_i << " at time " << sc_time_stamp() <get_base_address(addr_i); + uint32_t addr_offset = cache->get_block_offset(addr_i); + + //first read block_size bytes from memory to place them in cache regardless of the cmd + memory_copy(addr_to_read, main_mem_data, cache_block_size_word, false, trans, delay); + uint32_t index_to_add = cache->get_index(addr_i); + uint32_t tag_to_add = cache->get_tag(addr_i); + + heep_mem_transactions << "Adding to Cache TAG " << hex << tag_to_add << " and index " << hex << index_to_add <is_entry_valid(addr_i)) { + //if we are going to replace a valid entry + cache->get_data(addr_i, cache_data); + address_to_replace = cache->get_address(addr_i); + uint32_t index_to_replace = cache->get_index(addr_i); + uint32_t tag_to_replace = cache->get_tag_from_index(index_to_replace); + + heep_mem_transactions << "Cache Replace address " << hex << addr_i << " with address " << hex << address_to_replace << " due to the MISS at time " << sc_time_stamp() <add_entry(addr_i, (uint8_t*)main_mem_data); + + //if Write, writes to cache + if(we_i) + cache->set_word(addr_i, rwdata_io); + + //now give back the rdata + rwdata_io = main_mem_data[addr_offset>>2]; //>>2 as addr_offset is for byte address, not words + + //wait some time before giving the rvalid + wait(delay_rvalid_miss); + + } + } + } + + heep_mem_transactions << "X-HEEP tlm_generic_payload RESP: { DATA = 0x" << hex << rwdata_io <<", at time " << sc_time_stamp() << " }" << std::endl; + cache->print_cache_status(cache_stat.number_of_transactions++, sc_time_stamp().to_string()); + + obi_new_rvalid.notify(); + + } + } +}; + +#endif diff --git a/hw/vendor/esl_epfl_x_heep/tb/tb.vlt b/hw/vendor/esl_epfl_x_heep/tb/tb.vlt index 31e1d7cd..6ccdab5b 100644 --- a/hw/vendor/esl_epfl_x_heep/tb/tb.vlt +++ b/hw/vendor/esl_epfl_x_heep/tb/tb.vlt @@ -8,6 +8,8 @@ lint_off -rule UNUSED -file "*tb/testharness.sv" -match "*" lint_off -rule UNUSED -file "*tb/ext_xbar.sv" -match "Signal is not driven, nor used: '*" lint_off -rule UNOPTFLAT -file "*tb/ext_xbar.sv" -match "Signal unoptimizable: Feedback to clock or circular logic: 'testharness.ext_bus_i.__Vcellout__ext_xbar_i__slave_req_o'" lint_off -rule UNDRIVEN -file "*tb/testharness.sv" -match "Signal is not driven: 'jtag_tdo_o'*" +lint_off -rule UNDRIVEN -file "*tb/testharness.sv" -match "Signal is not driven: 'ext_ao_peripheral_req'*" +lint_off -rule UNDRIVEN -file "*tb/testharness.sv" -match "Signal is not driven: 'ext_ao_peripheral_resp'*" lint_off -rule SYNCASYNCNET -file "*tb/testharness.sv" -match "*" lint_off -rule WIDTH -file "*tb/testharness.sv" -match "*" lint_off -rule LITENDIAN -file "*tb/testharness.sv" -match "*" diff --git a/hw/vendor/esl_epfl_x_heep/tb/tb_sc_top.cpp b/hw/vendor/esl_epfl_x_heep/tb/tb_sc_top.cpp new file mode 100644 index 00000000..b619d950 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/tb/tb_sc_top.cpp @@ -0,0 +1,342 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#include "verilated.h" +#include +#include "Vtestharness.h" +#include "Vtestharness__Syms.h" +#include "systemc.h" +#include +#include +#include "XHEEP_CmdLineOptions.hh" + +sc_event reset_done_event; +sc_event obi_new_gnt; +sc_event obi_new_rvalid; +sc_event obi_new_req; + + +#include "systemc_tb/MemoryRequest.h" +#include "systemc_tb/MainMemory.h" + + +#define CLK_PERIOD 10 + +SC_MODULE(external_memory) +{ + MemoryRequest *memory_request; + MainMemory *memory; + + sc_in clk_i; + sc_in ext_systemc_req_req_i; + sc_in ext_systemc_req_we_i; + sc_in ext_systemc_req_be_i; + sc_in ext_systemc_req_addr_i; + sc_in ext_systemc_req_wdata_i; + sc_out ext_systemc_resp_gnt_o; + sc_out ext_systemc_resp_rvalid_o; + sc_out ext_systemc_resp_rdata_o; + + void notify_obi_transaction () { + if(ext_systemc_req_req_i) { + obi_new_req.notify(); + memory_request->we_i = ext_systemc_req_we_i; + memory_request->be_i = ext_systemc_req_be_i; + memory_request->addr_i = ext_systemc_req_addr_i; + memory_request->rwdata_io = ext_systemc_req_wdata_i; + } + } + + void give_gnt_back () { + while (true) { + ext_systemc_resp_gnt_o.write(false); + wait(obi_new_gnt); + ext_systemc_resp_gnt_o.write(true); + wait(); + } + } + + void give_rvalid_rdata_back () { + while (true) { + ext_systemc_resp_rvalid_o.write(false); + wait(obi_new_rvalid); + ext_systemc_resp_rvalid_o.write(true); + ext_systemc_resp_rdata_o.write(memory_request->rwdata_io); + wait(); + } + } + + SC_CTOR(external_memory) + { + // Instantiate components + memory_request = new MemoryRequest("memory_request"); + memory = new MainMemory ("main_memory"); + + SC_METHOD(notify_obi_transaction); + sensitive << ext_systemc_req_req_i; + + SC_CTHREAD(give_gnt_back, clk_i.pos()); + SC_CTHREAD(give_rvalid_rdata_back, clk_i.pos()); + + // Bind memory_request socket to target socket + memory_request->socket.bind( memory->socket ); + } +}; + + +SC_MODULE(testbench) +{ + + sc_in clk_i; + sc_out clk_o; + sc_out rst_no; + sc_out boot_select_o; + sc_out execute_from_flash_o; + sc_out jtag_tck_o; + sc_out jtag_tms_o; + sc_out jtag_trst_n_o; + sc_out jtag_tdi_o; + + Vtestharness* dut; + std::string* firmware; + + bool boot_select_option; + unsigned int reset_cycles = 30; + + void make_clock () { + while(1) { + clk_o.write(false); + wait(); + clk_o.write(true); + wait(); + } + } + + void do_reset_cycle () { + //active low + //----- + rst_no.write(false); + + for(int i=0;itb_loadHEX(firmware->c_str()); + } + + void set_exit_loop () { + wait(); + dut->tb_set_exit_loop(); + } + + void make_stimuli () { + + boot_select_o.write(boot_select_option); + execute_from_flash_o.write(true); + jtag_tck_o.write(false); + jtag_tms_o.write(false); + jtag_trst_n_o.write(false); + jtag_tdi_o.write(false); + + std::cout<<"Start Reset Cycle: "<c_str()<get_use_openocd(); + firmware = cmd_lines_options->get_firmware(); + + if(firmware.empty() && use_openocd==false) { + std::cout<<"You must specify the firmware if you are not using OpenOCD"<get_max_sim_time(run_all); + + boot_sel = cmd_lines_options->get_boot_sel(); + + if(use_openocd) { + std::cout<<"[TESTBENCH]: ERROR: Executing from OpenOCD in SystemC is not supported (yet) in X-HEEP"<>1, SC_NS, 0.5); + + Vtestharness dut("TOP"); + testbench tb("testbench"); + external_memory ext_mem("external_memory"); + + svSetScope(svGetScopeFromName("TOP.testharness")); + svScope scope = svGetScope(); + if (!scope) { + std::cout<<"Warning: svGetScope failed"<< std::endl; + exit(EXIT_FAILURE); + } + + + // static values + tb.boot_select_option = boot_sel == 1; + + + // Vtestharness interface + sc_signal clk; + sc_signal rst_n; + sc_signal boot_select; + sc_signal execute_from_flash; + sc_signal jtag_tck; + sc_signal jtag_tms; + sc_signal jtag_trst_n; + sc_signal jtag_tdi; + sc_signal jtag_tdo; + sc_signal exit_value; + sc_signal exit_valid; + sc_signal ext_systemc_req_req; + sc_signal ext_systemc_req_we; + sc_signal ext_systemc_req_be; + sc_signal ext_systemc_req_addr; + sc_signal ext_systemc_req_wdata; + sc_signal ext_systemc_resp_gnt; + sc_signal ext_systemc_resp_rvalid; + sc_signal ext_systemc_resp_rdata; + + + + tb.clk_i(clock_sig); + tb.clk_o(clk); + tb.rst_no(rst_n); + tb.boot_select_o(boot_select); + tb.execute_from_flash_o(execute_from_flash); + tb.jtag_tck_o(jtag_tck); + tb.jtag_tms_o(jtag_tms); + tb.jtag_trst_n_o(jtag_trst_n); + tb.jtag_tdi_o(jtag_tdi); + + tb.dut = &dut; + tb.firmware = &firmware; + + dut.clk_i(clk); + dut.rst_ni(rst_n); + dut.boot_select_i(boot_select); + dut.execute_from_flash_i(execute_from_flash); + dut.jtag_tck_i(jtag_tck); + dut.jtag_tms_i(jtag_tms); + dut.jtag_trst_ni(jtag_trst_n); + dut.jtag_tdi_i(jtag_tdi); + dut.jtag_tdo_o(jtag_tdo); + dut.exit_value_o(exit_value); + dut.exit_valid_o(exit_valid); + dut.ext_systemc_req_req_o(ext_systemc_req_req); + dut.ext_systemc_req_we_o(ext_systemc_req_we); + dut.ext_systemc_req_be_o(ext_systemc_req_be); + dut.ext_systemc_req_addr_o(ext_systemc_req_addr); + dut.ext_systemc_req_wdata_o(ext_systemc_req_wdata); + dut.ext_systemc_resp_gnt_i(ext_systemc_resp_gnt); + dut.ext_systemc_resp_rvalid_i(ext_systemc_resp_rvalid); + dut.ext_systemc_resp_rdata_i(ext_systemc_resp_rdata); + + ext_mem.clk_i(clk); + ext_mem.ext_systemc_req_req_i(ext_systemc_req_req); + ext_mem.ext_systemc_req_we_i(ext_systemc_req_we); + ext_mem.ext_systemc_req_be_i(ext_systemc_req_be); + ext_mem.ext_systemc_req_addr_i(ext_systemc_req_addr); + ext_mem.ext_systemc_req_wdata_i(ext_systemc_req_wdata); + ext_mem.ext_systemc_resp_gnt_o(ext_systemc_resp_gnt); + ext_mem.ext_systemc_resp_rdata_o(ext_systemc_resp_rdata); + ext_mem.ext_systemc_resp_rvalid_o(ext_systemc_resp_rvalid); + + + + // You must do one evaluation before enabling waves, in order to allow + // SystemC to interconnect everything for testing. + sc_start(1, SC_NS); + + + VerilatedVcdSc* tfp = nullptr; + tfp = new VerilatedVcdSc; + dut.trace(tfp, 99); // Trace 99 levels of hierarchy + tfp->open("waveform.vcd"); + + // Simulate until $finish + while (!Verilated::gotFinish() && exit_valid !=1 ) { + // Flush the wave files each cycle so we can immediately see the output + // Don't do this in "real" programs, do it in an abort() handler instead + if (tfp) tfp->flush(); + // Simulate 1ns + sc_start(1, SC_NS); + } + + if(exit_valid == 1) { + std::cout<<"Program Finished with value "<< exit_value <close(); + tfp = nullptr; + } + + + exit(exit_val); + +} diff --git a/hw/vendor/esl_epfl_x_heep/tb/tb_top.cpp b/hw/vendor/esl_epfl_x_heep/tb/tb_top.cpp index 956b77d6..7dd4757e 100644 --- a/hw/vendor/esl_epfl_x_heep/tb/tb_top.cpp +++ b/hw/vendor/esl_epfl_x_heep/tb/tb_top.cpp @@ -10,26 +10,10 @@ #include #include +#include "XHEEP_CmdLineOptions.hh" vluint64_t sim_time = 0; - -std::string getCmdOption(int argc, char* argv[], const std::string& option) -{ - std::string cmd; - for( int i = 0; i < argc; ++i) - { - std::string arg = argv[i]; - size_t arg_size = arg.length(); - size_t option_size = option.length(); - - if(arg.find(option)==0){ - cmd = arg.substr(option_size,arg_size-option_size); - } - } - return cmd; -} - void runCycles(unsigned int ncycles, Vtestharness *dut, VerilatedFstC *m_trace){ for(unsigned int i = 0; i < ncycles; i++) { dut->clk_i ^= 1; @@ -42,12 +26,11 @@ void runCycles(unsigned int ncycles, Vtestharness *dut, VerilatedFstC *m_trace){ int main (int argc, char * argv[]) { - unsigned int SRAM_SIZE; - std::string firmware, arg_max_sim_time, arg_openocd, arg_boot_sel, arg_execute_from_flash; - unsigned int max_sim_time; + std::string firmware; + unsigned int max_sim_time, boot_sel, exit_val; bool use_openocd; bool run_all = false; - int i,j, exit_val, boot_sel, execute_from_flash; + Verilated::commandArgs(argc, argv); // Instantiate the model @@ -59,59 +42,24 @@ int main (int argc, char * argv[]) dut->trace (m_trace, 99); m_trace->open ("waveform.vcd"); - arg_openocd = getCmdOption(argc, argv, "+openOCD="); - use_openocd = false; - if(arg_openocd.empty()){ - std::cout<<"[TESTBENCH]: No OpenOCD is used"<get_use_openocd(); + firmware = cmd_lines_options->get_firmware(); - arg_max_sim_time = getCmdOption(argc, argv, "+max_sim_time="); - max_sim_time = 0; - if(arg_max_sim_time.empty()){ - std::cout<<"[TESTBENCH]: No Max time specified"<get_max_sim_time(run_all); - arg_boot_sel = getCmdOption(argc, argv, "+execute_from_flash="); - execute_from_flash = 1; + boot_sel = cmd_lines_options->get_boot_sel(); if(boot_sel == 1) { std::cout<<"[TESTBENCH]: ERROR: Executing from SPI is not supported (yet) in Verilator"<jtag_tms_i = 0; dut->jtag_trst_ni = 0; dut->jtag_tdi_i = 0; - dut->execute_from_flash_i = execute_from_flash; + dut->execute_from_flash_i = 1; //this cause boot_sel cannot be 1 anyway dut->boot_select_i = boot_sel; dut->eval(); @@ -172,6 +120,7 @@ int main (int argc, char * argv[]) m_trace->close(); delete dut; + delete cmd_lines_options; exit(exit_val); diff --git a/hw/vendor/esl_epfl_x_heep/tb/tb_util.svh.tpl b/hw/vendor/esl_epfl_x_heep/tb/tb_util.svh.tpl index ece91031..2aafa4e8 100644 --- a/hw/vendor/esl_epfl_x_heep/tb/tb_util.svh.tpl +++ b/hw/vendor/esl_epfl_x_heep/tb/tb_util.svh.tpl @@ -6,8 +6,8 @@ // Task for loading 'mem' with SystemVerilog system task $readmemh() export "DPI-C" task tb_readHEX; export "DPI-C" task tb_loadHEX; -% for bank in range(ram_numbanks): -export "DPI-C" task tb_writetoSram${bank}; +% for bank in xheep.iter_ram_banks(): +export "DPI-C" task tb_writetoSram${bank.name()}; % endfor export "DPI-C" task tb_getMemSize; export "DPI-C" task tb_set_exit_loop; @@ -16,9 +16,7 @@ import core_v_mini_mcu_pkg::*; task tb_getMemSize; output int mem_size; - output int num_banks; mem_size = core_v_mini_mcu_pkg::MEM_SIZE; - num_banks = core_v_mini_mcu_pkg::NUM_BANKS; endtask task tb_readHEX; @@ -31,11 +29,11 @@ task tb_loadHEX; input string file; //whether to use debug to write to memories logic [7:0] stimuli[core_v_mini_mcu_pkg::MEM_SIZE]; - int i, stimuli_counter, bank, NumBytes, NumBanks; + int i, stimuli_base, w_addr, NumBytes; logic [31:0] addr; tb_readHEX(file, stimuli); - tb_getMemSize(NumBytes, NumBanks); + tb_getMemSize(NumBytes); `ifndef VERILATOR for (i = 0; i < NumBytes; i = i + 4) begin @@ -71,43 +69,34 @@ task tb_loadHEX; release x_heep_system_i.core_v_mini_mcu_i.debug_subsystem_i.dm_obi_top_i.master_wdata_o; `else - - stimuli_counter = 0; -% for bank in range(ram_numbanks_cont): - for (i = 0; i < NumBytes / NumBanks; i = i + 4) begin - tb_writetoSram${bank}(i / 4, stimuli[stimuli_counter+3], stimuli[stimuli_counter+2], - stimuli[stimuli_counter+1], stimuli[stimuli_counter]); - stimuli_counter = stimuli_counter + 4; +% for bank in xheep.iter_ram_banks(): + for (i=${bank.start_address()}; i < ${bank.end_address()}; i = i + 4) begin + if (((i/4) & ${2**bank.il_level()-1}) == ${bank.il_offset()}) begin + w_addr = ((i/4) >> ${bank.il_level()}) % ${bank.size()//4}; + tb_writetoSram${bank.name()}(w_addr, stimuli[i+3], stimuli[i+2], + stimuli[i+1], stimuli[i]); + end end % endfor -% if ram_numbanks_il != 0: - for (i = 0; i < NumBytes / NumBanks; i = i + 4) begin -% for bank in range(ram_numbanks_il): - tb_writetoSram${int(ram_numbanks_cont) + bank}(i / 4, stimuli[stimuli_counter+3], stimuli[stimuli_counter+2], - stimuli[stimuli_counter+1], stimuli[stimuli_counter]); - stimuli_counter = stimuli_counter + 4; -% endfor - end -% endif `endif endtask -% for bank in range(ram_numbanks): -task tb_writetoSram${bank}; - input integer addr; +% for bank in xheep.iter_ram_banks(): +task tb_writetoSram${bank.name()}; + input int addr; input [7:0] val3; input [7:0] val2; input [7:0] val1; input [7:0] val0; `ifdef VCS - force x_heep_system_i.core_v_mini_mcu_i.memory_subsystem_i.gen_sram[${bank}].ram_i.tc_ram_i.sram[addr] = { + force x_heep_system_i.core_v_mini_mcu_i.memory_subsystem_i.ram${bank.name()}_i.tc_ram_i.sram[addr] = { val3, val2, val1, val0 }; - release x_heep_system_i.core_v_mini_mcu_i.memory_subsystem_i.gen_sram[${bank}].ram_i.tc_ram_i.sram[addr]; + release x_heep_system_i.core_v_mini_mcu_i.memory_subsystem_i.ram${bank.name()}_i.tc_ram_i.sram[addr]; `else - x_heep_system_i.core_v_mini_mcu_i.memory_subsystem_i.gen_sram[${bank}].ram_i.tc_ram_i.sram[addr] = { + x_heep_system_i.core_v_mini_mcu_i.memory_subsystem_i.ram${bank.name()}_i.tc_ram_i.sram[addr] = { val3, val2, val1, val0 }; `endif diff --git a/hw/vendor/esl_epfl_x_heep/tb/testharness.sv b/hw/vendor/esl_epfl_x_heep/tb/testharness.sv index fc216e7b..e9a2cd3c 100644 --- a/hw/vendor/esl_epfl_x_heep/tb/testharness.sv +++ b/hw/vendor/esl_epfl_x_heep/tb/testharness.sv @@ -21,6 +21,17 @@ module testharness #( inout wire boot_select_i, inout wire execute_from_flash_i, +`ifdef SIM_SYSTEMC + output logic ext_systemc_req_req_o, + output logic ext_systemc_req_we_o, + output logic [ 3:0] ext_systemc_req_be_o, + output logic [31:0] ext_systemc_req_addr_o, + output logic [31:0] ext_systemc_req_wdata_o, + + input logic ext_systemc_resp_gnt_i, + input logic ext_systemc_resp_rvalid_i, + input logic [31:0] ext_systemc_resp_rdata_i, +`endif input wire jtag_tck_i, input wire jtag_tms_i, input wire jtag_trst_ni, @@ -37,7 +48,9 @@ module testharness #( import reg_pkg::*; import testharness_pkg::*; import addr_map_rule_pkg::*; + import core_v_mini_mcu_pkg::*; + localparam AO_SPC_NUM = 1; localparam SWITCH_ACK_LATENCY = 15; localparam EXT_XBAR_NMASTER_RND = USE_EXTERNAL_DEVICE_EXAMPLE ? testharness_pkg::EXT_XBAR_NMASTER : 1; localparam HEEP_EXT_XBAR_NMASTER = USE_EXTERNAL_DEVICE_EXAMPLE ? testharness_pkg::EXT_XBAR_NMASTER : 0; @@ -74,6 +87,23 @@ module testharness #( logic [EXT_PERIPHERALS_PORT_SEL_WIDTH-1:0] ext_periph_select; + logic iffifo_in_ready, iffifo_out_valid; + logic iffifo_int_o; + + // Im2col SPC interrupt signal + logic im2col_spc_done_int_o; + + // External DMA slots + logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] ext_dma_slot_tx; + logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] ext_dma_slot_rx; + + assign ext_dma_slot_tx[0] = iffifo_in_ready; + assign ext_dma_slot_rx[0] = iffifo_out_valid; + if (core_v_mini_mcu_pkg::DMA_CH_NUM > 1) begin + assign ext_dma_slot_tx[core_v_mini_mcu_pkg::DMA_CH_NUM-1:1] = '0; + assign ext_dma_slot_rx[core_v_mini_mcu_pkg::DMA_CH_NUM-1:1] = '0; + end + // External xbar master/slave and peripheral ports obi_req_t [EXT_XBAR_NMASTER_RND-1:0] ext_master_req; obi_req_t [EXT_XBAR_NMASTER_RND-1:0] heep_slave_req; @@ -85,12 +115,12 @@ module testharness #( obi_resp_t heep_core_data_resp; obi_req_t heep_debug_master_req; obi_resp_t heep_debug_master_resp; - obi_req_t heep_dma_read_ch0_req; - obi_resp_t heep_dma_read_ch0_resp; - obi_req_t heep_dma_write_ch0_req; - obi_resp_t heep_dma_write_ch0_resp; - obi_req_t heep_dma_addr_ch0_req; - obi_resp_t heep_dma_addr_ch0_resp; + obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] heep_dma_read_req; + obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] heep_dma_read_resp; + obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] heep_dma_write_req; + obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] heep_dma_write_resp; + obi_req_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] heep_dma_addr_req; + obi_resp_t [core_v_mini_mcu_pkg::DMA_NUM_MASTER_PORTS-1:0] heep_dma_addr_resp; obi_req_t [EXT_XBAR_NSLAVE-1:0] ext_slave_req; obi_resp_t [EXT_XBAR_NSLAVE-1:0] ext_slave_resp; reg_req_t periph_slave_req; @@ -99,10 +129,6 @@ module testharness #( reg_pkg::reg_req_t [testharness_pkg::EXT_NPERIPHERALS-1:0] ext_periph_slv_req; reg_pkg::reg_rsp_t [testharness_pkg::EXT_NPERIPHERALS-1:0] ext_periph_slv_rsp; - // External xbar slave example port - obi_req_t slow_ram_slave_req; - obi_resp_t slow_ram_slave_resp; - // External interrupts logic [NEXT_INT_RND-1:0] intr_vector_ext; logic memcopy_intr; @@ -125,6 +151,12 @@ module testharness #( .X_MISA(fpu_ss_pkg::X_MISA) ) ext_if (); + // External SPC interface signals + reg_req_t [AO_SPC_NUM-1:0] ext_ao_peripheral_req; + reg_rsp_t [AO_SPC_NUM-1:0] ext_ao_peripheral_resp; + + logic [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0] dma_busy; + always_comb begin // All interrupt lines set to zero by default for (int i = 0; i < core_v_mini_mcu_pkg::NEXT_INT; i++) begin @@ -132,6 +164,8 @@ module testharness #( end // Re-assign the interrupt lines used here intr_vector_ext[0] = memcopy_intr; + intr_vector_ext[1] = iffifo_int_o; + intr_vector_ext[2] = im2col_spc_done_int_o; end //log parameters @@ -142,6 +176,7 @@ module testharness #( $display("%t: the parameter X_EXT is %x", $time, X_EXT); $display("%t: the parameter ZFINX is %x", $time, ZFINX); $display("%t: the parameter JTAG_DPI is %x", $time, JTAG_DPI); + $display("%t: the parameter EXT_DOMAINS is %x", $time, core_v_mini_mcu_pkg::EXTERNAL_DOMAINS); $display("%t: the parameter USE_EXTERNAL_DEVICE_EXAMPLE is %x", $time, USE_EXTERNAL_DEVICE_EXAMPLE); $display("%t: the parameter CLK_FREQUENCY is %d KHz", $time, CLK_FREQUENCY); @@ -155,6 +190,7 @@ module testharness #( end `endif + // X-HEEP system x_heep_system #( .COREV_PULP(COREV_PULP), .FPU(FPU), @@ -236,12 +272,14 @@ module testharness #( .ext_core_data_resp_i(heep_core_data_resp), .ext_debug_master_req_o(heep_debug_master_req), .ext_debug_master_resp_i(heep_debug_master_resp), - .ext_dma_read_ch0_req_o(heep_dma_read_ch0_req), - .ext_dma_read_ch0_resp_i(heep_dma_read_ch0_resp), - .ext_dma_write_ch0_req_o(heep_dma_write_ch0_req), - .ext_dma_write_ch0_resp_i(heep_dma_write_ch0_resp), - .ext_dma_addr_ch0_req_o(heep_dma_addr_ch0_req), - .ext_dma_addr_ch0_resp_i(heep_dma_addr_ch0_resp), + .ext_dma_read_req_o(heep_dma_read_req), + .ext_dma_read_resp_i(heep_dma_read_resp), + .ext_dma_write_req_o(heep_dma_write_req), + .ext_dma_write_resp_i(heep_dma_write_resp), + .ext_dma_addr_req_o(heep_dma_addr_req), + .ext_dma_addr_resp_i(heep_dma_addr_resp), + .ext_ao_peripheral_req_i(ext_ao_peripheral_req), + .ext_ao_peripheral_resp_o(ext_ao_peripheral_resp), .ext_peripheral_slave_req_o(periph_slave_req), .ext_peripheral_slave_resp_i(periph_slave_rsp), .external_subsystem_powergate_switch_no(external_subsystem_powergate_switch_n), @@ -249,7 +287,11 @@ module testharness #( .external_subsystem_powergate_iso_no(external_subsystem_powergate_iso_n), .external_subsystem_rst_no(external_subsystem_rst_n), .external_ram_banks_set_retentive_no(external_ram_banks_set_retentive_n), - .external_subsystem_clkgate_en_no(external_subsystem_clkgate_en_n) + .external_subsystem_clkgate_en_no(external_subsystem_clkgate_en_n), + .ext_dma_slot_tx_i(ext_dma_slot_tx), + .ext_dma_slot_rx_i(ext_dma_slot_rx), + .ext_dma_stop_i('0), + .dma_done_o(dma_busy) ); // Testbench external bus @@ -260,28 +302,28 @@ module testharness #( .EXT_XBAR_NMASTER(EXT_XBAR_NMASTER), .EXT_XBAR_NSLAVE (EXT_XBAR_NSLAVE) ) ext_bus_i ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .addr_map_i (EXT_XBAR_ADDR_RULES), - .default_idx_i (SLOW_MEMORY_IDX[LOG_EXT_XBAR_NSLAVE-1:0]), - .heep_core_instr_req_i (heep_core_instr_req), - .heep_core_instr_resp_o (heep_core_instr_resp), - .heep_core_data_req_i (heep_core_data_req), - .heep_core_data_resp_o (heep_core_data_resp), - .heep_debug_master_req_i (heep_debug_master_req), - .heep_debug_master_resp_o (heep_debug_master_resp), - .heep_dma_read_ch0_req_i (heep_dma_read_ch0_req), - .heep_dma_read_ch0_resp_o (heep_dma_read_ch0_resp), - .heep_dma_write_ch0_req_i (heep_dma_write_ch0_req), - .heep_dma_write_ch0_resp_o(heep_dma_write_ch0_resp), - .heep_dma_addr_ch0_req_i (heep_dma_addr_ch0_req), - .heep_dma_addr_ch0_resp_o (heep_dma_addr_ch0_resp), - .ext_master_req_i (ext_master_req), - .ext_master_resp_o (ext_master_resp), - .heep_slave_req_o (heep_slave_req), - .heep_slave_resp_i (heep_slave_resp), - .ext_slave_req_o (ext_slave_req), - .ext_slave_resp_i (ext_slave_resp) + .clk_i (clk_i), + .rst_ni (rst_ni), + .addr_map_i (EXT_XBAR_ADDR_RULES), + .default_idx_i (SLOW_MEMORY_IDX[LOG_EXT_XBAR_NSLAVE-1:0]), + .heep_core_instr_req_i (heep_core_instr_req), + .heep_core_instr_resp_o (heep_core_instr_resp), + .heep_core_data_req_i (heep_core_data_req), + .heep_core_data_resp_o (heep_core_data_resp), + .heep_debug_master_req_i (heep_debug_master_req), + .heep_debug_master_resp_o(heep_debug_master_resp), + .heep_dma_read_req_i (heep_dma_read_req), + .heep_dma_read_resp_o (heep_dma_read_resp), + .heep_dma_write_req_i (heep_dma_write_req), + .heep_dma_write_resp_o (heep_dma_write_resp), + .heep_dma_addr_req_i (heep_dma_addr_req), + .heep_dma_addr_resp_o (heep_dma_addr_resp), + .ext_master_req_i (ext_master_req), + .ext_master_resp_o (ext_master_resp), + .heep_slave_req_o (heep_slave_req), + .heep_slave_resp_i (heep_slave_resp), + .ext_slave_req_o (ext_slave_req), + .ext_slave_resp_i (ext_slave_resp) ); logic pdm; @@ -301,7 +343,7 @@ module testharness #( always_ff @(negedge clk_i) begin tb_cpu_subsystem_powergate_switch_ack_n[0] <= x_heep_system_i.cpu_subsystem_powergate_switch_n; tb_peripheral_subsystem_powergate_switch_ack_n[0] <= x_heep_system_i.peripheral_subsystem_powergate_switch_n; - tb_memory_subsystem_banks_powergate_switch_ack_n[0] <= x_heep_system_i.memory_subsystem_banks_powergate_switch_n; + tb_memory_subsystem_banks_powergate_switch_ack_n[0] <= x_heep_system_i.core_v_mini_mcu_i.memory_subsystem_banks_powergate_switch_n; tb_external_subsystem_powergate_switch_ack_n[0] <= external_subsystem_powergate_switch_n; for (int i = 0; i < SWITCH_ACK_LATENCY; i++) begin tb_memory_subsystem_banks_powergate_switch_ack_n[i+1] <= tb_memory_subsystem_banks_powergate_switch_ack_n[i]; @@ -320,12 +362,12 @@ module testharness #( `ifndef VERILATOR force x_heep_system_i.core_v_mini_mcu_i.cpu_subsystem_powergate_switch_ack_ni = delayed_tb_cpu_subsystem_powergate_switch_ack_n; force x_heep_system_i.core_v_mini_mcu_i.peripheral_subsystem_powergate_switch_ack_ni = delayed_tb_peripheral_subsystem_powergate_switch_ack_n; - force x_heep_system_i.core_v_mini_mcu_i.memory_subsystem_banks_powergate_switch_ack_ni = delayed_tb_memory_subsystem_banks_powergate_switch_ack_n; + force x_heep_system_i.core_v_mini_mcu_i.memory_subsystem_banks_powergate_switch_ack_n = delayed_tb_memory_subsystem_banks_powergate_switch_ack_n; force external_subsystem_powergate_switch_ack_n = delayed_tb_external_subsystem_powergate_switch_ack_n; `else x_heep_system_i.cpu_subsystem_powergate_switch_ack_n = delayed_tb_cpu_subsystem_powergate_switch_ack_n; x_heep_system_i.peripheral_subsystem_powergate_switch_ack_n = delayed_tb_peripheral_subsystem_powergate_switch_ack_n; - x_heep_system_i.memory_subsystem_banks_powergate_switch_ack_n = delayed_tb_memory_subsystem_banks_powergate_switch_ack_n; + x_heep_system_i.core_v_mini_mcu_i.memory_subsystem_banks_powergate_switch_ack_n = delayed_tb_memory_subsystem_banks_powergate_switch_ack_n; external_subsystem_powergate_switch_ack_n = delayed_tb_external_subsystem_powergate_switch_ack_n; `endif end @@ -360,20 +402,45 @@ module testharness #( .exit() ); - assign mux_jtag_tck = JTAG_DPI ? sim_jtag_tck : jtag_tck_i; - assign mux_jtag_tms = JTAG_DPI ? sim_jtag_tms : jtag_tms_i; - assign mux_jtag_tdi = JTAG_DPI ? sim_jtag_tdi : jtag_tdi_i; - assign mux_jtag_trstn = JTAG_DPI ? sim_jtag_trstn : jtag_trst_ni; + assign mux_jtag_tck = JTAG_DPI ? sim_jtag_tck : jtag_tck_i; + assign mux_jtag_tms = JTAG_DPI ? sim_jtag_tms : jtag_tms_i; + assign mux_jtag_tdi = JTAG_DPI ? sim_jtag_tdi : jtag_tdi_i; + assign mux_jtag_trstn = JTAG_DPI ? sim_jtag_trstn : jtag_trst_ni; - assign sim_jtag_tdo = JTAG_DPI ? mux_jtag_tdo : '0; - assign jtag_tdo_o = !JTAG_DPI ? mux_jtag_tdo : '0; + assign sim_jtag_tdo = JTAG_DPI ? mux_jtag_tdo : '0; + assign jtag_tdo_o = !JTAG_DPI ? mux_jtag_tdo : '0; + + // External xbar slave example port + obi_req_t slow_ram_slave_req; + obi_resp_t slow_ram_slave_resp; + +`ifndef SIM_SYSTEMC assign slow_ram_slave_req = ext_slave_req[SLOW_MEMORY_IDX]; assign ext_slave_resp[SLOW_MEMORY_IDX] = slow_ram_slave_resp; +`else + + obi_req_t ext_systemc_req; + obi_resp_t ext_systemc_resp; + + assign ext_systemc_req_req_o = ext_systemc_req.req; + assign ext_systemc_req_we_o = ext_systemc_req.we; + assign ext_systemc_req_be_o = ext_systemc_req.be; + assign ext_systemc_req_addr_o = ext_systemc_req.addr; + assign ext_systemc_req_wdata_o = ext_systemc_req.wdata; + + assign ext_systemc_resp.gnt = ext_systemc_resp_gnt_i; + assign ext_systemc_resp.rvalid = ext_systemc_resp_rvalid_i; + assign ext_systemc_resp.rdata = ext_systemc_resp_rdata_i; + + assign ext_systemc_req = ext_slave_req[SLOW_MEMORY_IDX]; + assign ext_slave_resp[SLOW_MEMORY_IDX] = ext_systemc_resp; +`endif generate if (USE_EXTERNAL_DEVICE_EXAMPLE) begin : gen_USE_EXTERNAL_DEVICE_EXAMPLE +`ifndef SIM_SYSTEMC obi_pkg::obi_req_t slave_fifoout_req; obi_pkg::obi_resp_t slave_fifoout_resp; @@ -389,14 +456,14 @@ module testharness #( // External xbar slave memory example slow_memory #( - .NumWords (128), + .NumWords (8192), .DataWidth(32'd32) ) slow_ram_i ( .clk_i, .rst_ni, .req_i(slave_fifoout_req.req), .we_i(slave_fifoout_req.we), - .addr_i(slave_fifoout_req.addr[8:2]), + .addr_i(slave_fifoout_req.addr[15:2]), .wdata_i(slave_fifoout_req.wdata), .be_i(slave_fifoout_req.be), // output ports @@ -404,6 +471,7 @@ module testharness #( .rdata_o(slave_fifoout_resp.rdata), .rvalid_o(slave_fifoout_resp.rvalid) ); +`endif parameter DMA_TRIGGER_SLOT_NUM = 4; @@ -417,17 +485,50 @@ module testharness #( ) dma_i ( .clk_i, .rst_ni, + .clk_gate_en_ni('1), + .ext_dma_stop_i('0), .reg_req_i(ext_periph_slv_req[testharness_pkg::MEMCOPY_CTRL_IDX]), .reg_rsp_o(ext_periph_slv_rsp[testharness_pkg::MEMCOPY_CTRL_IDX]), - .dma_read_ch0_req_o(ext_master_req[testharness_pkg::EXT_MASTER0_IDX]), - .dma_read_ch0_resp_i(ext_master_resp[testharness_pkg::EXT_MASTER0_IDX]), - .dma_write_ch0_req_o(ext_master_req[testharness_pkg::EXT_MASTER1_IDX]), - .dma_write_ch0_resp_i(ext_master_resp[testharness_pkg::EXT_MASTER1_IDX]), - .dma_addr_ch0_req_o(), - .dma_addr_ch0_resp_i('0), + .dma_read_req_o(ext_master_req[testharness_pkg::EXT_MASTER0_IDX]), + .dma_read_resp_i(ext_master_resp[testharness_pkg::EXT_MASTER0_IDX]), + .dma_write_req_o(ext_master_req[testharness_pkg::EXT_MASTER1_IDX]), + .dma_write_resp_i(ext_master_resp[testharness_pkg::EXT_MASTER1_IDX]), + .dma_addr_req_o(), + .dma_addr_resp_i('0), .trigger_slot_i('0), .dma_done_intr_o(memcopy_intr), - .dma_window_intr_o() + .dma_window_intr_o(), + .dma_done_o() + ); + + simple_accelerator #( + .reg_req_t (reg_pkg::reg_req_t), + .reg_rsp_t (reg_pkg::reg_rsp_t), + .obi_req_t (obi_pkg::obi_req_t), + .obi_resp_t(obi_pkg::obi_resp_t) + ) simple_accelerator_i ( + .clk_i, + .rst_ni, + .reg_req_i(ext_periph_slv_req[testharness_pkg::SIMPLE_ACC_IDX]), + .reg_rsp_o(ext_periph_slv_rsp[testharness_pkg::SIMPLE_ACC_IDX]), + .acc_read_ch0_req_o(ext_master_req[testharness_pkg::EXT_MASTER2_IDX]), + .acc_read_ch0_resp_i(ext_master_resp[testharness_pkg::EXT_MASTER2_IDX]), + .acc_write_ch0_req_o(ext_master_req[testharness_pkg::EXT_MASTER3_IDX]), + .acc_write_ch0_resp_i(ext_master_resp[testharness_pkg::EXT_MASTER3_IDX]) + ); + + im2col_spc im2col_spc_i ( + .clk_i, + .rst_ni, + + .aopb2im2col_resp_i(ext_ao_peripheral_resp[0]), + .im2col2aopb_req_o (ext_ao_peripheral_req[0]), + + .reg_req_i(ext_periph_slv_req[testharness_pkg::IM2COL_SPC_IDX]), + .reg_rsp_o(ext_periph_slv_rsp[testharness_pkg::IM2COL_SPC_IDX]), + + .dma_done_i(dma_busy), + .im2col_spc_done_int_o(im2col_spc_done_int_o) ); // AMS external peripheral @@ -441,6 +542,22 @@ module testharness #( .reg_rsp_o(ext_periph_slv_rsp[testharness_pkg::AMS_IDX]) ); + // InterFaced FIFO (IFFIFO) external peripheral + iffifo #( + .reg_req_t(reg_pkg::reg_req_t), + .reg_rsp_t(reg_pkg::reg_rsp_t) + ) iffifo_i ( + .clk_i, + .rst_ni, + .reg_req_i(ext_periph_slv_req[testharness_pkg::IFFIFO_IDX]), + .reg_rsp_o(ext_periph_slv_rsp[testharness_pkg::IFFIFO_IDX]), + // DMA slots + .iffifo_in_ready_o(iffifo_in_ready), + .iffifo_out_valid_o(iffifo_out_valid), + // Interrupt lines + .iffifo_int_o(iffifo_int_o) + ); + addr_decode #( .NoIndices(testharness_pkg::EXT_NPERIPHERALS), .NoRules(testharness_pkg::EXT_NPERIPHERALS), @@ -557,7 +674,9 @@ module testharness #( assign ext_master_req[testharness_pkg::EXT_MASTER0_IDX].wdata = '0; assign memcopy_intr = '0; + assign iffifo_int_o = '0; assign periph_slave_rsp = '0; + assign im2col_spc_done_int_o = '0; end endgenerate diff --git a/hw/vendor/esl_epfl_x_heep/tb/testharness_pkg.sv b/hw/vendor/esl_epfl_x_heep/tb/testharness_pkg.sv index 58e202ce..e26afd7a 100644 --- a/hw/vendor/esl_epfl_x_heep/tb/testharness_pkg.sv +++ b/hw/vendor/esl_epfl_x_heep/tb/testharness_pkg.sv @@ -7,12 +7,14 @@ package testharness_pkg; import addr_map_rule_pkg::*; import core_v_mini_mcu_pkg::*; - localparam EXT_XBAR_NMASTER = 2; + localparam EXT_XBAR_NMASTER = 4; localparam EXT_XBAR_NSLAVE = 1; //master idx localparam logic [31:0] EXT_MASTER0_IDX = 0; localparam logic [31:0] EXT_MASTER1_IDX = 1; + localparam logic [31:0] EXT_MASTER2_IDX = 2; + localparam logic [31:0] EXT_MASTER3_IDX = 3; //slave mmap and idx localparam logic [31:0] SLOW_MEMORY_START_ADDRESS = core_v_mini_mcu_pkg::EXT_SLAVE_START_ADDRESS; @@ -29,7 +31,7 @@ package testharness_pkg; }; //slave encoder - localparam EXT_NPERIPHERALS = 2; + localparam EXT_NPERIPHERALS = 5; // Memcopy controller (external peripheral example) localparam logic [31:0] MEMCOPY_CTRL_START_ADDRESS = core_v_mini_mcu_pkg::EXT_PERIPHERAL_START_ADDRESS + 32'h0; @@ -38,11 +40,28 @@ package testharness_pkg; localparam logic [31:0] MEMCOPY_CTRL_IDX = 32'd0; // External AMS Peripheral - localparam logic [31:0] AMS_START_ADDRESS = core_v_mini_mcu_pkg::EXT_PERIPHERAL_START_ADDRESS + 32'h001000; + localparam logic [31:0] AMS_START_ADDRESS = core_v_mini_mcu_pkg::EXT_PERIPHERAL_START_ADDRESS + 32'h01000; localparam logic [31:0] AMS_SIZE = 32'h100; localparam logic [31:0] AMS_END_ADDRESS = AMS_START_ADDRESS + AMS_SIZE; localparam logic [31:0] AMS_IDX = 32'd1; + // External InterFaced FIFO (IFFIFO) Peripheral + localparam logic [31:0] IFFIFO_START_ADDRESS = core_v_mini_mcu_pkg::EXT_PERIPHERAL_START_ADDRESS + 32'h02000; + localparam logic [31:0] IFFIFO_SIZE = 32'h100; + localparam logic [31:0] IFFIFO_END_ADDRESS = IFFIFO_START_ADDRESS + IFFIFO_SIZE; + localparam logic [31:0] IFFIFO_IDX = 32'd2; + + // External Simple Accelerator Peripheral + localparam logic [31:0] SIMPLE_ACC_START_ADDRESS = core_v_mini_mcu_pkg::EXT_PERIPHERAL_START_ADDRESS + 32'h03000; + localparam logic [31:0] SIMPLE_ACC_SIZE = 32'h100; + localparam logic [31:0] SIMPLE_ACC_END_ADDRESS = SIMPLE_ACC_START_ADDRESS + SIMPLE_ACC_SIZE; + localparam logic [31:0] SIMPLE_ACC_IDX = 32'd3; + + // External im2col SPC Peripheral + localparam logic [31:0] IM2COL_SPC_START_ADDRESS = core_v_mini_mcu_pkg::EXT_PERIPHERAL_START_ADDRESS + 32'h04000; + localparam logic [31:0] IM2COL_SPC_SIZE = 32'h100; + localparam logic [31:0] IM2COL_SPC_END_ADDRESS = IM2COL_SPC_START_ADDRESS + IM2COL_SPC_SIZE; + localparam logic [31:0] IM2COL_SPC_IDX = 32'd4; localparam addr_map_rule_t [EXT_NPERIPHERALS-1:0] EXT_PERIPHERALS_ADDR_RULES = '{ '{ @@ -50,7 +69,18 @@ package testharness_pkg; start_addr: MEMCOPY_CTRL_START_ADDRESS, end_addr: MEMCOPY_CTRL_END_ADDRESS }, - '{idx: AMS_IDX, start_addr: AMS_START_ADDRESS, end_addr: AMS_END_ADDRESS} + '{idx: AMS_IDX, start_addr: AMS_START_ADDRESS, end_addr: AMS_END_ADDRESS}, + '{idx: IFFIFO_IDX, start_addr: IFFIFO_START_ADDRESS, end_addr: IFFIFO_END_ADDRESS}, + '{ + idx: SIMPLE_ACC_IDX, + start_addr: SIMPLE_ACC_START_ADDRESS, + end_addr: SIMPLE_ACC_END_ADDRESS + }, + '{ + idx: IM2COL_SPC_IDX, + start_addr: IM2COL_SPC_START_ADDRESS, + end_addr: IM2COL_SPC_END_ADDRESS + } }; localparam int unsigned EXT_PERIPHERALS_PORT_SEL_WIDTH = EXT_NPERIPHERALS > 1 ? $clog2( diff --git a/hw/vendor/esl_epfl_x_heep/util/MakefileHelp b/hw/vendor/esl_epfl_x_heep/util/MakefileHelp index dc5f2901..8e072d0a 100755 --- a/hw/vendor/esl_epfl_x_heep/util/MakefileHelp +++ b/hw/vendor/esl_epfl_x_heep/util/MakefileHelp @@ -1,8 +1,7 @@ #!/bin/bash - -FILE=Makefile RULE_COLOR="$(tput setaf 6)" SECTION_COLOR="$(tput setaf 3)" +SSECTION_COLOR="$(tput setaf 5)" VARIABLE_COLOR="$(tput setaf 2)" VALUE_COLOR="$(tput setaf 1)" CLEAR_STYLE="$(tput sgr0)" @@ -17,13 +16,14 @@ echo "" TARGET_REGEX="^[a-zA-Z0-9%_\/%-]+:" SECTION_REGEX="^##\s*@section\s*(.*)$" +SSECTION_REGEX="^##\s*@subsection\s*(.*)$" DOCBLOCK_REGEX="^##\s*(.*)$" PARAM_REGEX="@param\s+([a-zA-Z_]+)(=([^\s]+))?\s*(.*$)?" COMMENT="" PARAMS="" PARAMS_DOC="" -cat $FILE | while read line +cat $FILE_FOR_HELP | while read line do # do something with $line here if [[ ! -z $line ]] @@ -31,7 +31,11 @@ do if [[ $line =~ $SECTION_REGEX ]] then SECTION_NAME=$(echo $line | sed -e "s/^##\s*@section\s*\(.*\)$/\1/g") - echo "$SECTION_COLOR$SECTION_NAME$CLEAR_STYLE:" + echo "$SECTION_COLOR$SECTION_NAME:$CLEAR_STYLE" + elif [[ $line =~ $SSECTION_REGEX ]] + then + SECTION_NAME=$(echo $line | sed -e "s/^##\s*@subsection\s*\(.*\)$/\1/g") + echo "$SSECTION_COLOR $SECTION_NAME:$CLEAR_STYLE" elif [[ $line =~ $TARGET_REGEX ]] then # if there is no comment for this target, we don't display it in the docs to keep private targets hidden diff --git a/hw/vendor/esl_epfl_x_heep/util/generate-makefile-help b/hw/vendor/esl_epfl_x_heep/util/generate-makefile-help deleted file mode 100755 index 30e4893c..00000000 --- a/hw/vendor/esl_epfl_x_heep/util/generate-makefile-help +++ /dev/null @@ -1,2 +0,0 @@ -help: - util/MakefileHelp \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/util/mcu_gen.py b/hw/vendor/esl_epfl_x_heep/util/mcu_gen.py index e8c012f8..c187bf54 100755 --- a/hw/vendor/esl_epfl_x_heep/util/mcu_gen.py +++ b/hw/vendor/esl_epfl_x_heep/util/mcu_gen.py @@ -18,6 +18,9 @@ from mako.template import Template import collections from math import log2 +import x_heep_gen.load_config +from x_heep_gen.system import BusType +import math class Pad: @@ -30,13 +33,25 @@ def remove_comma_io_interface(self): def create_pad_ring(self): + # Mapping dictionary from string to integer + mapping_dict = { + 'top' : 'core_v_mini_mcu_pkg::TOP', + 'right' : 'core_v_mini_mcu_pkg::RIGHT', + 'bottom' : 'core_v_mini_mcu_pkg::BOTTOM', + 'left' : 'core_v_mini_mcu_pkg::LEFT' + } + + mapping = '' + if self.pad_mapping is not None: + mapping = ', .SIDE(' + mapping_dict[self.pad_mapping] + ')' + self.interface = ' inout wire ' + self.name + '_io,\n' if self.pad_type == 'input': self.pad_ring_io_interface = ' inout wire ' + self.io_interface + ',' self.pad_ring_ctrl_interface += ' output logic ' + self.signal_name + 'o,' self.pad_ring_instance = \ - 'pad_cell_input #(.PADATTR('+ str(self.attribute_bits) +')) ' + self.cell_name + ' ( \n' + \ + 'pad_cell_input #(.PADATTR('+ str(self.attribute_bits) +')' + mapping + ') ' + self.cell_name + ' ( \n' + \ ' .pad_in_i(1\'b0),\n' + \ ' .pad_oe_i(1\'b0),\n' + \ ' .pad_out_o(' + self.signal_name + 'o),\n' + \ @@ -45,7 +60,7 @@ def create_pad_ring(self): self.pad_ring_io_interface = ' inout wire ' + self.io_interface + ',' self.pad_ring_ctrl_interface += ' input logic ' + self.signal_name + 'i,' self.pad_ring_instance = \ - 'pad_cell_output #(.PADATTR('+ str(self.attribute_bits) +')) ' + self.cell_name + ' ( \n' + \ + 'pad_cell_output #(.PADATTR('+ str(self.attribute_bits) +')' + mapping + ') ' + self.cell_name + ' ( \n' + \ ' .pad_in_i(' + self.signal_name + 'i),\n' + \ ' .pad_oe_i(1\'b1),\n' + \ ' .pad_out_o(),\n' + \ @@ -56,7 +71,7 @@ def create_pad_ring(self): self.pad_ring_ctrl_interface += ' output logic ' + self.signal_name + 'o,\n' self.pad_ring_ctrl_interface += ' input logic ' + self.signal_name + 'oe_i,' self.pad_ring_instance = \ - 'pad_cell_inout #(.PADATTR('+ str(self.attribute_bits) +')) ' + self.cell_name + ' ( \n' + \ + 'pad_cell_inout #(.PADATTR('+ str(self.attribute_bits) +')' + mapping + ') ' + self.cell_name + ' ( \n' + \ ' .pad_in_i(' + self.signal_name + 'i),\n' + \ ' .pad_oe_i(' + self.signal_name + 'oe_i),\n' + \ ' .pad_out_o(' + self.signal_name + 'o),\n' + \ @@ -195,13 +210,14 @@ def create_pad_ring_bonding(self): self.pad_ring_bonding_bonding += ' .' + self.signal_name + 'oe_i(' + oe_internal_signals + '),' self.x_heep_system_interface += ' inout wire ' + self.signal_name + 'io,' - def __init__(self, name, cell_name, pad_type, index, pad_active, pad_driven_manually, pad_skip_declaration, pad_mux_list, has_attribute, attribute_bits): + def __init__(self, name, cell_name, pad_type, pad_mapping, index, pad_active, pad_driven_manually, pad_skip_declaration, pad_mux_list, has_attribute, attribute_bits, pad_layout_index, pad_layout_orient, pad_layout_cell, pad_layout_offset, pad_layout_skip): self.name = name self.cell_name = cell_name self.index = index self.localparam = 'PAD_' + name.upper() self.pad_type = pad_type + self.pad_mapping = pad_mapping self.pad_mux_list = pad_mux_list if('low' in pad_active): @@ -225,6 +241,12 @@ def __init__(self, name, cell_name, pad_type, index, pad_active, pad_driven_manu self.is_driven_manually = pad_driven_manually self.do_skip_declaration = pad_skip_declaration + self.layout_index = pad_layout_index + self.layout_orient = pad_layout_orient + self.layout_cell = pad_layout_cell + self.layout_offset = pad_layout_offset + self.layout_skip = pad_layout_skip + if(len(pad_mux_list) == 0): self.signal_name_drive.append(self.signal_name) self.pad_type_drive.append(pad_type) @@ -285,12 +307,18 @@ def write_template(tpl_path, outdir, outfile, **kwargs): def main(): parser = argparse.ArgumentParser(prog="mcugen") - parser.add_argument("--cfg", + parser.add_argument("--cfg_peripherals", "-c", metavar="file", type=argparse.FileType('r'), required=True, help="A configuration file") + + parser.add_argument("--config", + metavar="file", + type=str, + required=True, + help="X-Heep general configuration") parser.add_argument("--pads_cfg", "-pc", @@ -380,7 +408,7 @@ def main(): logging.basicConfig(level=logging.DEBUG) # Read HJSON description of System. - with args.cfg as file: + with args.cfg_peripherals as file: try: srcfull = file.read() obj = hjson.loads(srcfull, use_decimal=True) @@ -404,47 +432,21 @@ def main(): outfile = args.outfile + config_override = x_heep_gen.system.Override(None, None, None) + if args.cpu != None and args.cpu != '': cpu_type = args.cpu else: cpu_type = obj['cpu_type'] if args.bus != None and args.bus != '': - bus_type = args.bus - else: - bus_type = obj['bus_type'] + config_override.bus_type = BusType(args.bus) if args.memorybanks != None and args.memorybanks != '': - ram_numbanks_cont = int(args.memorybanks) - else: - ram_numbanks_cont = int(obj['ram']['numbanks']) + config_override.numbanks = int(args.memorybanks) if args.memorybanks_il != None and args.memorybanks_il != '': - ram_numbanks_il = int(args.memorybanks_il) - else: - ram_numbanks_il = int(obj['ram']['numbanks_interleaved']) - - if ram_numbanks_il != 0: - log_ram_numbanks_il = int(log2(ram_numbanks_il)) - - if not log2(ram_numbanks_il).is_integer(): - exit("ram interleaved numbanks must be a power of 2 instead of " + str(ram_numbanks_il)) - else: - log_ram_numbanks_il = 0 - - if ram_numbanks_il != 0 and bus_type == 'onetoM': - exit("bus type must be 'NtoM' instead 'onetoM' to access the interleaved memory banks in parallel" + str(args.bus)) - - if ram_numbanks_cont + ram_numbanks_il < 2 and ram_numbanks_cont + ram_numbanks_il > 16: - exit("ram numbanks must be between 2 and 16 instead of " + str(ram_numbanks_cont + ram_numbanks_il)) - else: - ram_numbanks = ram_numbanks_cont + ram_numbanks_il - - ram_start_address = string2int(obj['ram']['address']) - if int(ram_start_address,16) != 0: - exit("ram start address must be 0 instead of " + str(ram_start_address)) - - ram_size_address = '{:08X}'.format(ram_numbanks*32*1024) + config_override.numbanks_il = int(args.memorybanks_il) if args.external_domains != None and args.external_domains != '': external_domains = int(args.external_domains) @@ -454,6 +456,12 @@ def main(): if external_domains > 32: exit("external_domains must be less than 32 instead of " + str(external_domains)) + + + xheep = x_heep_gen.load_config.load_cfg_file(pathlib.PurePath(str(args.config)), config_override) + + + debug_start_address = string2int(obj['debug']['address']) if int(debug_start_address, 16) < int('10000', 16): exit("debug start address must be greater than 0x10000") @@ -503,7 +511,51 @@ def len_extracted_peripherals(peripherals): ao_peripherals = extract_peripherals(discard_path(obj['ao_peripherals'])) ao_peripherals_count = len(ao_peripherals) + dma_ch_count = ao_peripherals["dma"]["num_channels"] + + if int(dma_ch_count, 16) > int('256', 16) or int(dma_ch_count, 16) == 0: + exit("Number of DMA channels has to be between 0 and 256, excluded") + + dma_ch_size = ao_peripherals["dma"]["ch_length"] + # Number of master ports for the dma subsystem + num_dma_master_ports = ao_peripherals["dma"]["num_master_ports"] + if int(num_dma_master_ports, 16) > int(dma_ch_count, 16) or int(num_dma_master_ports, 16) == 0: + exit("Number of DMA master ports has to be between 0 and " + str(dma_ch_count) + ", 0 excluded") + + # Number of masters for each slave of the DMA NtoM xbar + num_dma_xbar_channels_per_master_port = ao_peripherals["dma"]["num_channels_per_master_port"] + if (int(num_dma_xbar_channels_per_master_port, 16) > int(dma_ch_count, 16) and int(dma_ch_count, 16) != 1) or int(num_dma_xbar_channels_per_master_port, 16) == 0: + exit("Number of DMA channels per system bus master ports has to be between 0 and " + str(dma_ch_count) + ", excluded") + + if (int(num_dma_master_ports) > 1): + # Computation of full_masters_xbars + temp_full_masters_xbars = math.floor(int(dma_ch_count) / int(num_dma_xbar_channels_per_master_port)) + if temp_full_masters_xbars < int(num_dma_master_ports) and temp_full_masters_xbars * int(num_dma_xbar_channels_per_master_port) == int(dma_ch_count): + full_masters_xbars = temp_full_masters_xbars - 1 + else: + full_masters_xbars = temp_full_masters_xbars + last = int(num_dma_xbar_channels_per_master_port) * full_masters_xbars + + # Array initialization + array_xbar_gen = [0] * int(num_dma_master_ports) + + # Computation of the number of xbar channels for each master port + for i in range(int(num_dma_master_ports)): + if i < full_masters_xbars: + array_xbar_gen[i] = int(num_dma_xbar_channels_per_master_port) + else: + array_xbar_gen[i] = min(int(dma_ch_count) - last, int(dma_ch_count) - last - (int(num_dma_master_ports) - i - 1)) + last = last + array_xbar_gen[i] + + if (sum(array_xbar_gen) != int(dma_ch_count) or 0 in array_xbar_gen): + exit("Error in the DMA xbar generation: wrong parameters") + + dma_xbar_array = ", ".join(map(str, array_xbar_gen)) + else: + if (int(num_dma_xbar_channels_per_master_port) != int(dma_ch_count)): + exit("With 1 master port, the number of DMA channels per master port has to be equal to the number of DMA channels") + dma_xbar_array = "default: 1" peripheral_start_address = string2int(obj['peripherals']['address']) if int(peripheral_start_address, 16) < int('10000', 16): @@ -519,29 +571,13 @@ def len_extracted_peripherals(peripherals): flash_mem_start_address = string2int(obj['flash_mem']['address']) flash_mem_size_address = string2int(obj['flash_mem']['length']) - linker_onchip_code_start_address = string2int(obj['linker_script']['onchip_ls']['code']['address']) - linker_onchip_code_size_address = string2int(obj['linker_script']['onchip_ls']['code']['lenght']) + stack_size = string2int(obj['linker_script']['stack_size']) + heap_size = string2int(obj['linker_script']['heap_size']) - if int(linker_onchip_code_size_address,16) < 32*1024: - exit("The code section must be at least 32KB, instead it is " + str(linker_onchip_code_size_address)) - linker_onchip_data_start_address = string2int(obj['linker_script']['onchip_ls']['data']['address']) - if (obj['linker_script']['onchip_ls']['data']['lenght'].split()[0].split(",")[0] == "whatisleft"): - if ram_numbanks_il == 0 or (ram_numbanks_cont == 1 and ram_numbanks_il > 0): - linker_onchip_data_size_address = str('{:08X}'.format(int(ram_size_address,16) - int(linker_onchip_code_size_address,16))) - else: - linker_onchip_data_size_address = str('{:08X}'.format(int(ram_size_address,16) - int(linker_onchip_code_size_address,16) - ram_numbanks_il*32*1024)) - else: - if ram_numbanks_il == 0 or (ram_numbanks_cont == 1 and ram_numbanks_il > 0): - linker_onchip_data_size_address = string2int(obj['linker_script']['onchip_ls']['data']['lenght']) - else: - linker_onchip_data_size_address = str('{:08X}'.format(int(string2int(obj['linker_script']['onchip_ls']['data']['lenght']),16) - ram_numbanks_il*32*1024)) + if ((int(stack_size,16) + int(heap_size,16)) > xheep.ram_size_address()): + exit("The stack and heap section must fit in the RAM size, instead they takes " + str(stack_size + heap_size)) - linker_onchip_il_start_address = str('{:08X}'.format(int(linker_onchip_data_start_address,16) + int(linker_onchip_data_size_address,16))) - linker_onchip_il_size_address = str('{:08X}'.format(ram_numbanks_il*32*1024)) - - if ((int(linker_onchip_data_size_address,16) + int(linker_onchip_code_size_address,16)) > int(ram_size_address,16)): - exit("The code and data section must fit in the RAM size, instead they takes " + str(linker_onchip_data_size_address + linker_onchip_code_size_address)) plic_used_n_interrupts = len(obj['interrupts']['list']) plit_n_interrupts = obj['interrupts']['number'] @@ -590,7 +626,7 @@ def len_extracted_peripherals(peripherals): pad_name = key pad_num = pads[key]['num'] - pad_type = pads[key]['type'] + pad_type = pads[key]['type'].strip(',') try: pad_offset = int(pads[key]['num_offset']) @@ -601,6 +637,11 @@ def len_extracted_peripherals(peripherals): pad_active = pads[key]['active'] except KeyError: pad_active = 'high' + + try: + pad_mapping = pads[key]['mapping'].strip(',') + except KeyError: + pad_mapping = None try: pad_mux_list_hjson = pads[key]['mux'] @@ -631,6 +672,31 @@ def len_extracted_peripherals(peripherals): except KeyError: pad_keep_internal = False + try: + pad_layout_orient = pads[key]['layout_attributes']['orient'] + except KeyError: + pad_layout_orient = None + + try: + pad_layout_cell = pads[key]['layout_attributes']['cell'] + except KeyError: + pad_layout_cell = None + + try: + pad_layout_offset = pads[key]['layout_attributes']['offset'] + except KeyError: + pad_layout_offset = None + + try: + pad_layout_skip = pads[key]['layout_attributes']['skip'] + except KeyError: + pad_layout_skip = None + + try: + pad_layout_index = pads[key]['layout_attributes']['index'] + except KeyError: + pad_layout_index = None + pad_mux_list = [] for pad_mux in pad_mux_list_hjson: @@ -656,13 +722,13 @@ def len_extracted_peripherals(peripherals): except KeyError: pad_skip_declaration_mux = False - p = Pad(pad_mux, '', pads[key]['mux'][pad_mux]['type'], 0, pad_active_mux, pad_driven_manually_mux, pad_skip_declaration_mux, [], pads_attributes!=None, pads_attributes_bits) + p = Pad(pad_mux, '', pads[key]['mux'][pad_mux]['type'], pad_mapping, 0, pad_active_mux, pad_driven_manually_mux, pad_skip_declaration_mux, [], pads_attributes!=None, pads_attributes_bits, pad_layout_index, pad_layout_orient, pad_layout_cell, pad_layout_offset, pad_layout_skip) pad_mux_list.append(p) if pad_num > 1: for p in range(pad_num): pad_cell_name = "pad_" + key + "_" + str(p+pad_offset) + "_i" - pad_obj = Pad(pad_name + "_" + str(p+pad_offset), pad_cell_name, pad_type, pad_index_counter, pad_active, pad_driven_manually, pad_skip_declaration, pad_mux_list, pads_attributes!=None, pads_attributes_bits) + pad_obj = Pad(pad_name + "_" + str(p+pad_offset), pad_cell_name, pad_type, pad_mapping, pad_index_counter, pad_active, pad_driven_manually, pad_skip_declaration, pad_mux_list, pads_attributes!=None, pads_attributes_bits, pad_layout_index, pad_layout_orient, pad_layout_cell, pad_layout_offset, pad_layout_skip) if not pad_keep_internal: pad_obj.create_pad_ring() pad_obj.create_core_v_mini_mcu_ctrl() @@ -681,7 +747,7 @@ def len_extracted_peripherals(peripherals): else: pad_cell_name = "pad_" + key + "_i" - pad_obj = Pad(pad_name, pad_cell_name, pad_type, pad_index_counter, pad_active, pad_driven_manually, pad_skip_declaration, pad_mux_list, pads_attributes!=None, pads_attributes_bits) + pad_obj = Pad(pad_name, pad_cell_name, pad_type, pad_mapping, pad_index_counter, pad_active, pad_driven_manually, pad_skip_declaration, pad_mux_list, pads_attributes!=None, pads_attributes_bits, pad_layout_index, pad_layout_orient, pad_layout_cell, pad_layout_offset, pad_layout_skip) if not pad_keep_internal: pad_obj.create_pad_ring() pad_obj.create_core_v_mini_mcu_ctrl() @@ -716,6 +782,11 @@ def len_extracted_peripherals(peripherals): except KeyError: pad_active = 'high' + try: + pad_mapping = external_pads[key]['mapping'] + except KeyError: + pad_mapping = None + try: pad_mux_list_hjson = external_pads[key]['mux'] except KeyError: @@ -737,6 +808,31 @@ def len_extracted_peripherals(peripherals): except KeyError: pad_skip_declaration = False + try: + pad_layout_orient = external_pads[key]['layout_attributes']['orient'] + except KeyError: + pad_layout_orient = None + + try: + pad_layout_cell = external_pads[key]['layout_attributes']['cell'] + except KeyError: + pad_layout_cell = None + + try: + pad_layout_offset = external_pads[key]['layout_attributes']['offset'] + except KeyError: + pad_layout_offset = None + + try: + pad_layout_skip = external_pads[key]['layout_attributes']['skip'] + except KeyError: + pad_layout_skip = None + + try: + pad_layout_index = external_pads[key]['layout_attributes']['index'] + except KeyError: + pad_layout_index = None + pad_mux_list = [] for pad_mux in pad_mux_list_hjson: @@ -762,13 +858,13 @@ def len_extracted_peripherals(peripherals): except KeyError: pad_skip_declaration_mux = False - p = Pad(pad_mux, '', external_pads[key]['mux'][pad_mux]['type'], 0, pad_active_mux, pad_driven_manually_mux, pad_skip_declaration_mux, [], pads_attributes!=None, pads_attributes_bits) + p = Pad(pad_mux, '', external_pads[key]['mux'][pad_mux]['type'], pad_mapping, 0, pad_active_mux, pad_driven_manually_mux, pad_skip_declaration_mux, [], pads_attributes!=None, pads_attributes_bits, pad_layout_index, pad_layout_orient, pad_layout_cell, pad_layout_offset, pad_layout_skip) pad_mux_list.append(p) if pad_num > 1: for p in range(pad_num): pad_cell_name = "pad_" + key + "_" + str(p+pad_offset) + "_i" - pad_obj = Pad(pad_name + "_" + str(p+pad_offset), pad_cell_name, pad_type, external_pad_index, pad_active, pad_driven_manually, pad_skip_declaration, pad_mux_list, pads_attributes!=None, pads_attributes_bits) + pad_obj = Pad(pad_name + "_" + str(p+pad_offset), pad_cell_name, pad_type, pad_mapping, external_pad_index, pad_active, pad_driven_manually, pad_skip_declaration, pad_mux_list, pads_attributes!=None, pads_attributes_bits, pad_layout_index, pad_layout_orient, pad_layout_cell, pad_layout_offset, pad_layout_skip) pad_obj.create_pad_ring() pad_obj.create_pad_ring_bonding() pad_obj.create_internal_signals() @@ -784,7 +880,7 @@ def len_extracted_peripherals(peripherals): else: pad_cell_name = "pad_" + key + "_i" - pad_obj = Pad(pad_name, pad_cell_name, pad_type, external_pad_index, pad_active, pad_driven_manually, pad_skip_declaration, pad_mux_list, pads_attributes!=None, pads_attributes_bits) + pad_obj = Pad(pad_name, pad_cell_name, pad_type, pad_mapping, external_pad_index, pad_active, pad_driven_manually, pad_skip_declaration, pad_mux_list, pads_attributes!=None, pads_attributes_bits, pad_layout_index, pad_layout_orient, pad_layout_cell, pad_layout_offset, pad_layout_skip) pad_obj.create_pad_ring() pad_obj.create_pad_ring_bonding() pad_obj.create_internal_signals() @@ -818,21 +914,20 @@ def len_extracted_peripherals(peripherals): total_pad_list.append(last_pad) kwargs = { + "xheep" : xheep, "cpu_type" : cpu_type, - "bus_type" : bus_type, - "ram_start_address" : ram_start_address, - "ram_numbanks" : ram_numbanks, - "ram_numbanks_cont" : ram_numbanks_cont, - "ram_numbanks_il" : ram_numbanks_il, - "log_ram_numbanks_il" : log_ram_numbanks_il, "external_domains" : external_domains, - "ram_size_address" : ram_size_address, "debug_start_address" : debug_start_address, "debug_size_address" : debug_size_address, "ao_peripheral_start_address" : ao_peripheral_start_address, "ao_peripheral_size_address" : ao_peripheral_size_address, "ao_peripherals" : ao_peripherals, "ao_peripherals_count" : ao_peripherals_count, + "dma_ch_count" : dma_ch_count, + "dma_ch_size" : dma_ch_size, + "num_dma_master_ports" : num_dma_master_ports, + "num_dma_xbar_channels_per_master_port" : num_dma_xbar_channels_per_master_port, + "dma_xbar_masters_array" : dma_xbar_array, "peripheral_start_address" : peripheral_start_address, "peripheral_size_address" : peripheral_size_address, "peripherals" : peripherals, @@ -841,12 +936,8 @@ def len_extracted_peripherals(peripherals): "ext_slave_size_address" : ext_slave_size_address, "flash_mem_start_address" : flash_mem_start_address, "flash_mem_size_address" : flash_mem_size_address, - "linker_onchip_code_start_address" : linker_onchip_code_start_address, - "linker_onchip_code_size_address" : linker_onchip_code_size_address, - "linker_onchip_data_start_address" : linker_onchip_data_start_address, - "linker_onchip_data_size_address" : linker_onchip_data_size_address, - "linker_onchip_il_start_address" : linker_onchip_il_start_address, - "linker_onchip_il_size_address" : linker_onchip_il_size_address, + "stack_size" : stack_size, + "heap_size" : heap_size, "plic_used_n_interrupts" : plic_used_n_interrupts, "plit_n_interrupts" : plit_n_interrupts, "interrupts" : interrupts, diff --git a/hw/vendor/esl_epfl_x_heep/util/structs_gen.py b/hw/vendor/esl_epfl_x_heep/util/structs_gen.py index f815de76..3c776b42 100644 --- a/hw/vendor/esl_epfl_x_heep/util/structs_gen.py +++ b/hw/vendor/esl_epfl_x_heep/util/structs_gen.py @@ -1,4 +1,5 @@ import hjson +from math import ceil import string import argparse import sys @@ -297,7 +298,7 @@ def add_registers(peripheral_json): n_bits += count_bits(f["bits"]) # computes the number of registers needed to pack all the bit fields needed - n_multireg = int((count * n_bits) / int(peripheral_json["regwidth"])) + n_multireg = ceil((count * n_bits) / int(peripheral_json["regwidth"])) # generate the multiregisters for r in range(n_multireg): diff --git a/hw/vendor/esl_epfl_x_heep/util/structs_periph_gen.py b/hw/vendor/esl_epfl_x_heep/util/structs_periph_gen.py index c737370c..79608eea 100644 --- a/hw/vendor/esl_epfl_x_heep/util/structs_periph_gen.py +++ b/hw/vendor/esl_epfl_x_heep/util/structs_periph_gen.py @@ -1,6 +1,9 @@ import hjson import structs_gen +# Path to the dma file +dma_file_path = "./sw/device/lib/drivers/dma/dma_structs.h" + # Path to the header_structs template template_path = "./sw/device/lib/drivers/template.tpl" @@ -40,6 +43,26 @@ def scan_peripherals(json_list): add_peripheral(p, json_list[p]["path"]) +def format_dma_channels(file_path, new_string): + + try: + # Read the contents of the file + with open(file_path, 'r') as file: + content = file.read() + + # Replace 'DMA_START_ADDRESS' with 'new_address' + updated_content = content.replace('#define dma_peri ((volatile dma *) DMA_START_ADDRESS)', new_string) + + # Write the updated content back to the file + with open(file_path, 'w') as file: + file.write(updated_content) + + print("DMA channel has been successfully updated.") + + except FileNotFoundError: + print(f"The file {file_path} does not exist.") + except Exception as e: + print(f"An error occurred: {str(e)}") # for i in range(len(JSON_FILES)): # print("{}\n{}\n{}\n\n\n".format(PERIPHERAL_NAMES[i], JSON_FILES[i], OUTPUT_FILES[i])) @@ -64,4 +87,7 @@ def scan_peripherals(json_list): # "--peripheral_name", PERIPHERAL_NAMES[i], "--json_filename", JSON_FILES[i], "--output_filename", OUTPUT_FILES[i]] - ) \ No newline at end of file + ) + + new_string = "#define dma_peri(channel) ((volatile dma *) (DMA_START_ADDRESS + DMA_CH_SIZE * channel))" + format_dma_channels(dma_file_path, new_string) \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/util/test_all.sh b/hw/vendor/esl_epfl_x_heep/util/test_all.sh index 60d45a28..99ad0084 100755 --- a/hw/vendor/esl_epfl_x_heep/util/test_all.sh +++ b/hw/vendor/esl_epfl_x_heep/util/test_all.sh @@ -174,7 +174,7 @@ SIMULATOR='' declare -a LINKERS=( ) # Simulation timeout to prevent apps from running infinitely -SIM_TIMEOUT_S=120 # This time, in seconds, was chosen empirically. +SIM_TIMEOUT_S=240 # This time, in seconds, was chosen empirically. # Prevent the re-generation of the mcu and the simualtion model on every # execution by changing DEBUG to 1 @@ -338,7 +338,7 @@ sed 's/is_included: "no",/is_included: "yes",/' -i mcu_cfg.hjson if [ $DEBUG -eq 0 ]; then # The MCU is generated with several memory banks to avoid example code not fitting. - make mcu-gen MEMORY_BANKS=3 EXTERNAL_DOMAINS=1 + make mcu-gen X_HEEP_CFG=configs/testall.hjson EXTERNAL_DOMAINS=1 if [ "$SIMULATOR" != "none" ]; then # Make the simualtion model @@ -348,6 +348,14 @@ if [ $DEBUG -eq 0 ]; then echo -e "${WHITE}Building simulation model $SIM_MODEL_CMD ${RESET}" echo -e ${LONG_W} + if [ "$OPT" == "1" ] && [ "$SIMULATOR" == "questasim" ]; then + # Perform optimization + SIM_MODEL_CMD=${SIM_MODEL_CMD}"-opt" + echo -e ${LONG_W} + echo -e "${WHITE}Optimizing simulation model ${RESET}" + echo -e ${LONG_W} + fi + make $SIM_MODEL_CMD fi fi diff --git a/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/__init__.py b/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/__init__.py new file mode 100644 index 00000000..c1a6b006 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/__init__.py @@ -0,0 +1,4 @@ +from .system import XHeep +from . import system +from . import load_config +from . import ram_bank \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/linker_section.py b/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/linker_section.py new file mode 100644 index 00000000..1f5fe468 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/linker_section.py @@ -0,0 +1,80 @@ +from dataclasses import * +from typing import Optional + +@dataclass +class LinkerSection(): + """ + Object representing a section in the linker configuration. + + If the end address is set to `None` it will be infered in the building process. + """ + + name: str + """ + The name of the section + + The name can be anything that does not collide with section names used by the linker, + except code and data that are used to configure the size of the code and data part. + code and data do not only contain the actual .code and .data section but other related sections. + """ + + start: int + """The start address""" + + end: Optional[int] + """The end address""" + + def __post_init__(self): + self.check() + + def check(self): + """ + Does basic type checking and sanity checking. + + - Checks the type of all members + - Checks that the name is not empty + - Checks that the start address and size are positive + + :raise TypeError: when the type of a member is not the correct ine. + :raise ValueError: when the name is empty or start or size are negative + """ + if type(self.name) is not str: + raise TypeError("name should be of type str") + if type(self.start) is not int: + raise TypeError("start should be of type int") + if type(self.end) is not int and self.end is not None: + raise TypeError("end should be of type int") + + if self.name == "": + raise ValueError("name should not be empty") + if self.start < 0: + raise ValueError("start address should be positif") + if self.end is not None and self.end <= self.start: + raise ValueError("end address should be bigger than the start address") + + @staticmethod + def by_size(name: str, start: int, size: int) -> "LinkerSection": + """ + Creates a Linker Section by it's size rather than end address. + + :param str name: the name of the section + :param int start: the start address + :param int size: the size of the section + :return: the linker section + :rtype: LinkerSection + """ + if type(name) is not str: + raise TypeError("name should be of type str") + if type(start) is not int: + raise TypeError("start should be of type int") + if type(size) is not int: + raise TypeError("size should be of type int") + + return LinkerSection(name, start, start + size) + + @property + def size(self) -> Optional[int]: + """The size in Bytes""" + if self.end is not None: + return self.end - self.start + return None \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/load_config.py b/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/load_config.py new file mode 100644 index 00000000..1c2da738 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/load_config.py @@ -0,0 +1,293 @@ +import importlib +from pathlib import PurePath +from typing import List, Optional, Union +import hjson + +from .linker_section import LinkerSection +from .system import BusType, Override, XHeep + +def to_int(input) -> Union[int, None]: + if type(input) is int: + return input + + if type(input) is str: + base = 10 + if len(input) >= 2: + if input[0:2].upper() == "0X": + base = 16 + input = input[2:] + elif input[0:2] == "0o": + base = 8 + input = input[2:] + elif input[0:2].upper() == "0b": + base = 2 + input = input[2:] + + return int(input, base) + return None + + +def ram_list(l: "List[int]", entry): + """ + Parses the hjson ram bank configuration in continuous mode. + + :param List[int] l: the list where bank sizes in kiB should be added + :enrtry: the entry to be parsed. It should be a list an integer or an continuous dictionary + :raise RuntimeError: when an invalid configuration is processed. + """ + if type(l) is not list: + raise TypeError("l should be of type list") + + if type(entry) is int: + l.append(entry) + return + + if type(entry) is list: + for i in entry: + ram_list(l, i) + return + + if type(entry) is hjson.OrderedDict: + num = 1 + if "num" in entry: + if type(entry["num"]) is not int: + raise RuntimeError("if the num field is present in ram configuration it should be an integer") + num = entry["num"] + + if "sizes" in entry: + for _ in range(num): + ram_list(l, entry["sizes"]) + return + else: + raise RuntimeError("dictionaries in continuous ram configuration sections should at least have a sizes entry") + + raise RuntimeError("entries in ram configuration should either be integer, lists, or dictionaries") + + + +def load_ram_configuration(system: XHeep, mem: hjson.OrderedDict): + """ + Reads the whole ram configuration. + + :param XHeep system: the system object where the ram should be added. + :param hjson.OrderedDict mem: The configuration part with the ram informations. + :raise TypeError: when arguments do not have the right type + :raise RuntimeError: when an invalid configuration is processed. + """ + if not isinstance(system, XHeep): + raise TypeError("system should be an instance of XHeep object") + if type(mem) is not hjson.OrderedDict: + raise TypeError("mem should be of type hjson.OrderedDict") + + for key, value in mem.items(): + if type(value) is not hjson.OrderedDict: + raise RuntimeError("Ram configuration entries should be dictionaries") + + section_name = "" + if "auto_section" in value and value["auto_section"] == "auto": + section_name = key + + t = "continuous" + if "type" in value: + t = value["type"] + if type(t) is not str: + raise RuntimeError("ram type should be a string") + if t != "continuous" and t != "interleaved": + raise RuntimeError(f"ram type should be continuous or interleaved not {t}") + + if t == "interleaved": + if "num" not in value or type(value["num"]) is not int: + raise RuntimeError("The num field is required for interleaved ram section and should be an integer") + + if "size" not in value or type(value["size"]) is not int: + raise RuntimeError("The size field is required for interleaved ram section and should be an integer") + + system.add_ram_banks_il(int(value["num"]), int(value["size"]), section_name) + + elif t == "continuous": + banks: List[int] = [] + ram_list(banks, value) + system.add_ram_banks(banks, section_name) + + + +def load_linker_config(system: XHeep, config: list): + """ + Reads the whole linker section configuration. + + :param XHeep system: the system object where the sections should be added. + :param hjson.OrderedDict mem: The configuration part with the section informations. + :raise TypeError: when arguments do not have the right type + :raise RuntimeError: when an invalid configuration is processed. + """ + if type(config) is not list: + raise RuntimeError("Linker Section configuraiton should be a list.") + + for l in config: + if type(l) is not hjson.OrderedDict: + raise RuntimeError("Sections should be represented as Dictionaries") + if "name" not in l: + raise RuntimeError("All sections should have names") + + if "start" not in l: + raise RuntimeError("All sections should have a start") + + name = l["name"] + start = to_int(l["start"]) + + if type(name) is not str: + raise RuntimeError("Section names should be strings") + + if name == "": + raise RuntimeError("Section names should not be empty") + + if type(start) is not int: + raise RuntimeError("The start of a section should be an integer") + + if "size" in l and "end" in l: + raise RuntimeError("Each section should only specify end or size.") + + end = 0 + if "size" in l: + size = to_int(l["size"]) + if size is None: + raise RuntimeError("Section sizes should be an integer") + if size <= 0: + raise RuntimeError("Section sizes should be strictly positive") + end = start + size + + elif "end" in l: + end = to_int(l["end"]) + if end is None: + raise RuntimeError("End address should be an integer") + if end <= start: + raise RuntimeError("Sections should end after their start") + else: + end = None + + system.add_linker_section(LinkerSection(name, start, end)) + + + + +def load_cfg_hjson(src: str, override: Optional[Override] = None) -> XHeep: + """ + Loads the configuration passed as a hjson string and creates an object representing the mcu. + + :param str src: configuration content + :param Optional[Override] override: configs to be overriden + :return: the object representing the mcu configuration + :rtype: XHeep + :raise RuntimeError: when and invalid configuration is passed or when the sanity checks failed + """ + config = hjson.loads(src, parse_int=int, object_pairs_hook=hjson.OrderedDict) + mem_config = None + bus_config = None + ram_address_config = None + linker_config = None + + for key, value in config.items(): + if key == "ram_banks": + mem_config = value + elif key == "bus_type": + bus_config = value + elif key == "ram_address": + ram_address_config = value + elif key == "linker_sections": + linker_config = value + + if mem_config is None: + raise RuntimeError("No memory configuration found") + if bus_config is None: + raise RuntimeError("No bus type configuration found") + + ram_start = 0 + if ram_address_config is not None: + if type(ram_address_config) is not int: + RuntimeError("The ram_address should be an intger") + ram_start = ram_address_config + + system = XHeep(BusType(bus_config), ram_start, override=override) + load_ram_configuration(system, mem_config) + + if linker_config is not None: + load_linker_config(system, linker_config) + + system.build() + if not system.validate(): + raise RuntimeError("Could not validate system configuration") + return system + + + +def _chk_purep(f): + """ + Helper to check the type is `PurePath` + + :param f: object to check + :raise TypeError: when object is of wrong type. + """ + if not isinstance(f, PurePath): + raise TypeError("parameter should be of type PurePath") + + + +def load_cfg_hjson_file(f: PurePath, override: Optional[Override] = None) -> XHeep: + """ + Loads the configuration passed in the path as hjson and creates an object representing the mcu. + + :param PurePath f: path of the configuration + :param Optional[Override] override: configs to be overriden + :return: the object representing the mcu configuration + :rtype: XHeep + :raise RuntimeError: when and invalid configuration is passed or when the sanity checks failed + """ + _chk_purep(f) + + with open(f, "r") as file: + return load_cfg_hjson(file.read(), override) + + + +def load_cfg_script_file(f: PurePath) -> XHeep: + """ + Executes the python file passed as argument to cinfigure the system. + + This file should have a function config that takes no parameters and returns an instance (or subclass) of the XHeep type. + The script can import modules from the util directory. + The script should not have side effects as it is called multiple time in the current makefile. + + :param PurePath f: path of the configuration + :return: the object representing the mcu configuration + :rtype: XHeep + :raise RuntimeError: when and invalid configuration is passed or when the sanity checks failed + """ + _chk_purep(f) + + spec = importlib.util.spec_from_file_location("configs._config", f) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + + return mod.config() + + + +def load_cfg_file(f: PurePath, override: Optional[Override] = None) -> XHeep: + """ + Load the Configuration by extension type. It currently supports .hjson and .py + + :param PurePath f: path of the configuration + :param Optional[Override] override: configs to be overriden + :return: the object representing the mcu configuration + :rtype: XHeep + :raise RuntimeError: when and invalid configuration is passed or when the sanity checks failed + """ + _chk_purep(f) + + if f.suffix == ".hjson": + return load_cfg_hjson_file(f, override) + + if f.suffix == ".py": + return load_cfg_script_file(f) + + raise RuntimeError(f"unsupported file extension {f.suffix}") \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/ram_bank.py b/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/ram_bank.py new file mode 100644 index 00000000..20f043eb --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/ram_bank.py @@ -0,0 +1,133 @@ +from dataclasses import * + +def is_pow2(n: int) -> bool: + """ + check if n is a power of two + + :param int n: number to be checked + :return: True if n is a power of two + :rtype: bool + """ + return n > 0 and (n & (n-1)) == 0 + + + +class Bank(): + """ + Represents a ram bank + + :param int size_k: size in kiB + :param int start_address: start address of the bank, in interleaved mode it should be the start address od the whole group + :param int map_idx: index in the global address map. Has to be unique. Interleaved mode banks should have consecutive indices. + :param int il_level: number of bits used for interleaving. + :param int il_offset: position in interleaved bank group if in any else 0. Should be consistent with map_idx. + :raise TypeError: when parameters don't have the right type. + :raise ValueError: when size_k isn't a power of two. + :raise ValueError: when start_address is not aligned on size. + :raise ValueError: when il_offset is to big for the given il_level(). + """ + def __init__(self, size_k: int, start_address: int, map_idx: int, il_level: int = 0, il_offset: int = 0): + if not type(size_k) is int: + raise TypeError("Bank size should be an int") + + if not type(start_address) is int: + raise TypeError("Start address should be an int") + + if not type(map_idx) is int: + raise TypeError("map_idx size should be an int") + + if not type(il_level) is int: + raise TypeError("il_level should be an int") + + if not type(il_offset) is int: + raise TypeError("il_offset size should be an int") + + self._size_k: int = size_k + self._start_address: int = start_address + self._map_idx: int = map_idx + self._il_level: int = il_level + self._il_offset: int = il_offset + + # check if power of 2 + if not is_pow2(self._size_k): + raise ValueError(f"Bank size {self._size_k}kiB is not a positive power of two") + + if self._il_offset >= 2**self._il_level: + raise ValueError(f"il_offset is to big for an il_level of {self._il_level}") + + mask = 0b11 + if not self._start_address & mask == 0: + raise ValueError(f"start_address is not aligned on word size") + + + #TODO: Validate start address + + self._end_address = self._start_address + self._size_k*1024 * 2**self._il_level + + def size(self) -> int: + """ + :return: the bank size in Bytes + :rtype: int + """ + return self._size_k * 1024 + + def name(self) -> str: + """ + :return: the bank name + :rtype: str + """ + return str(self._map_idx-1) #TODO: do something better + + def start_address(self) -> int: + """ + :return: the start address + :rtype: int + """ + return self._start_address + + def end_address(self) -> int: + """ + :return: the end address + :rtype: int + """ + return self._end_address + + def map_idx(self) -> int: + """ + :return: the index used in global bus + :rtype: int + """ + return self._map_idx + + def il_level(self) -> int: + """ + :return: the number of bits used to choose the bank when it is in an interleaved group else 0 + :rtype: int + """ + return self._il_level + + def il_offset(self) -> int: + """ + :return: the position of the bank in an interleaved group. + :rtype: int + """ + return self._il_offset + +@dataclass +class ILRamGroup(): + """ + Dataclass to represent information about interleaved memory banks group. + """ + + start: int + """start address of the group""" + + size: int + """size of the group""" + + n: int + """number of banks in the group""" + + first_name: str + """name of the first bank""" + \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/system.py b/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/system.py new file mode 100644 index 00000000..09e4a855 --- /dev/null +++ b/hw/vendor/esl_epfl_x_heep/util/x_heep_gen/system.py @@ -0,0 +1,430 @@ +from copy import deepcopy +from dataclasses import dataclass +from typing import Generator, Iterable, List, Optional, Set, Union +from enum import Enum +from .ram_bank import Bank, is_pow2, ILRamGroup +from .linker_section import LinkerSection + +class BusType(Enum): + """Enumeration of all supported bus types""" + + onetoM = 'onetoM' + NtoM = 'NtoM' + + +@dataclass +class Override(): + """ + Bundles information that can be overriden in the XHeep class. + """ + bus_type: Optional[BusType] + numbanks: Optional[int] + numbanks_il: Optional[int] + + + +class XHeep(): + """ + This object represents the whole mcu. + + An instance of this object is also passed to the mako templates. + + :param BusType bus_type: The bus type chosen for this mcu. + :param int ram_start_address: The address of the first ram bank. For now only 0 is tested. Defaults to 0. + :param Optional[Override] override: configs to be overriden + :raise TypeError: when parameters are of incorrect type. + """ + + IL_COMPATIBLE_BUS_TYPES: "Set[BusType]" = set([BusType.NtoM]) + """Constant set of bus types that support interleaved memory banks""" + + + + def __init__(self, bus_type: BusType, ram_start_address: int = 0, override: Optional[Override] = None): + if not type(bus_type) is BusType: + raise TypeError(f"XHeep.bus_type should be of type BusType not {type(self._bus_type)}") + if not type(ram_start_address) is int: + raise TypeError("ram_start_address should be of type int") + + if ram_start_address != 0: + raise ValueError(f"ram start address must be 0 instead of {ram_start_address}") + + self._bus_type: BusType = bus_type + if override is not None and override.bus_type is not None: + self._bus_type = override.bus_type + + + self._ram_start_address: int = ram_start_address + self._ram_banks: List[Bank] = [] + self._ram_banks_il_idx: List[int] = [] + self._ram_banks_il_groups: List[ILRamGroup] = [] + self._il_banks_present: bool = False + self._ram_next_idx: int = 1 + self._ram_next_addr: int = self._ram_start_address + self._linker_sections: List[LinkerSection] = [] + self._used_section_names: Set[str] = set() + + self._ignore_ram_continous: bool = False + self._ignore_ram_interleaved: bool = False + + if override is not None and override.numbanks is not None: + self.add_ram_banks([32]*override.numbanks) + self._ignore_ram_continous = True + if override is not None and override.numbanks_il is not None: + self._ignore_ram_interleaved = True + self._override_numbanks_il = override.numbanks_il + + + def add_ram_banks(self, bank_sizes: "List[int]", section_name: str = ""): + """ + Add ram banks in continuous address mode to the system. + The bank size should be a power of two and at least 1kiB. + + :param List[int] bank_sizes: list of bank sizes in kiB that should be added to the system + :param str section_name: If not empty adds automatically a linker section for this banks. The names must be unique and not be used by the linker for other purposes. + :raise TypeError: when arguments are of wrong type + :raise ValueError: when banks have an incorrect size. + :raise ValueError: if the name was allready used for another section or the first and second are not code and data. + :raise ValueError: if bank_sizes list is empty + """ + + if self._ignore_ram_continous: + return + + if not type(bank_sizes) == list: + raise TypeError("bank_sizes should be of type list") + if not type(section_name) == str: + raise TypeError("section_name should be of type str") + if len(bank_sizes) == 0: + raise ValueError("bank_sizes is empty") + + banks: List[Bank] = [] + for b in bank_sizes: + banks.append(Bank(b, self._ram_next_addr, self._ram_next_idx, 0, 0)) + self._ram_next_addr = banks[-1]._end_address + self._ram_next_idx += 1 + + if section_name != "": + self.add_linker_section_for_banks(banks, section_name) + # Add all new banks if no error was raised + self._ram_banks += banks + + + + + def add_ram_banks_il(self, num: int, bank_size: int, section_name: str = "", ignore_ignore: bool = False): + """ + Add ram banks in interleaved mode to the system. + The bank size should be a power of two and at least 1kiB, + the number of banks should also be a power of two. + + :param int num: number of banks to add + :param int bank_size: size of the banks in kiB + :param str section_name: If not empty adds automatically a linker section for this banks. The names must be unique and not be used by the linker for other purposes. + :param bool ignore_ignore: Ignores the fact that an override was set. For internal uses to apply this override. + :raise TypeError: when arguments are of wrong type + :raise ValueError: when banks have an incorrect size or their number is not a power of two. + :raise ValueError: if the name was allready used for another section or the first and second are not code and data. + """ + if self._ignore_ram_interleaved and not ignore_ignore: + return + + if not self._bus_type in self.IL_COMPATIBLE_BUS_TYPES: + raise RuntimeError(f"This system has a {self._bus_type} bus, one of {self.IL_COMPATIBLE_BUS_TYPES} is required for interleaved memory") + if not type(num) == int: + raise TypeError("num should be of type int") + if not is_pow2(num): + raise ValueError(f"A power of two is required for the number of banks, got {num}") + if not type(section_name) == str: + raise TypeError("section_name should be of type str") + + first_il = self.ram_numbanks() + + banks: List[Bank] = [] + for i in range(num): + banks.append(Bank(bank_size, self._ram_next_addr, self._ram_next_idx, num.bit_length()-1, i)) + self._ram_next_idx += 1 + + self._ram_next_addr = banks[-1]._end_address + + if section_name != "": + self.add_linker_section_for_banks(banks, section_name) + # Add all new banks if no error was raised + self._ram_banks += banks + + indices = range(first_il, first_il + num) + self._ram_banks_il_idx += indices + self._ram_banks_il_groups.append(ILRamGroup(banks[0].start_address(), bank_size*num*1024, len(banks), banks[0].name())) + self._il_banks_present = True + + + + def add_linker_section_for_banks(self, banks: "List[Bank]", name: str): + """ + Function to add linker sections coupled to some banks. + :param List[Bank] banks: list of banks that compose the section, assumed to be continuous in memory + :param str name: the name of the section. + :raise ValueError: if the name was allready used for another section or the first and second are not code and data. + """ + if name in self._used_section_names: + raise ValueError("linker section names should be unique") + + self._used_section_names.add(name) + self._linker_sections.append(LinkerSection(name, banks[0].start_address(), banks[-1].end_address())) + + def add_linker_section(self, section: LinkerSection): + """ + Function to add a linker section. + :param LinkerSection section: Linker section to add. + :param str name: the name of the section. + :raise ValueError: if the name was allready used for another section or the first and second are not code and data. + """ + + if not isinstance(section, LinkerSection): + raise TypeError("section should be an instance of LinkerSection") + + section.check() + + if section.name in self._used_section_names: + raise ValueError("linker section names should be unique") + + self._used_section_names.add(section.name) + self._linker_sections.append(deepcopy(section)) + + + + def bus_type(self) -> BusType: + """ + :return: the configured bus type + :rtype: BusType + """ + return self._bus_type + + def ram_start_address(self) -> int: + """ + :return: the address of the first ram bank. + :rtype: int + """ + return self._ram_start_address + + def ram_numbanks(self) -> int: + """ + :return: the number of banks. + :rtype: int + """ + return len(self._ram_banks) + + + + def ram_numbanks_il(self) -> int: + """ + :return: the number of interleaved banks. + :rtype: int + """ + return len(self._ram_banks_il_idx) + + + + def ram_numbanks_cont(self) -> int: + """ + :return: the number of continuous banks. + :rtype: int + """ + return self.ram_numbanks() - self.ram_numbanks_il() + + + + def validate(self) -> bool: + """ + Does some basics checks on the configuration + + This should be called before using the XHeep object to generate the project. + + :return: the validity of the configuration + :rtype: bool + """ + if not self.ram_numbanks() in range(2, 17): + print(f"The number of banks should be between 2 and 16 instead of {self.ram_numbanks()}") #TODO: clarify upper limit + return False + + if not ("code" in self._used_section_names and "data" in self._used_section_names): + print("The code and data sections are needed") + return False + + for l in self._linker_sections: + l.check() + + ret = True + old_sec: Union[LinkerSection,None] = None + + for i, sec in enumerate(self._linker_sections): + if i == 0 and sec.name != "code": + print("The first linker section sould be called code.") + ret = False + elif i == 1 and sec.name != "data": + print("The second linker section sould be called data.") + ret = False + + if old_sec is not None: + if sec.start < old_sec.end: + print(f"Section {sec.name} and {old_sec.name} overlap.") + + start = sec.start + found_start = False + found_end = False + for b in self._ram_banks: + if found_start: + if b.start_address() > start: + print(f"Section {sec.name} has a memory hole starting at {start:#08X}") + ret = False + found_end = True + break + else: + start = b.end_address() + + if sec.start >= b.start_address() and sec.start < b.end_address(): + found_start = True + start = b.end_address() + + if sec.end <= b.end_address() and sec.end > b.start_address(): + found_end = True + break + + if not found_start: + print(f"Section {sec.name} does not start in any ram bank.") + ret = False + + if not found_end: + ret = False + print(f"Section {sec.name} does not end in any ram bank.") + + old_sec = sec + + return ret + + + + def ram_size_address(self) -> int: + """ + :return: the size of the addressable ram memory. + :rtype: int + """ + size = 0 + for bank in self._ram_banks: + size += bank.size() + return size + + + + def ram_il_size(self) -> int: + """ + :return: the memory size of the interleaved sizes. + :rtype: int + """ + size = 0 + for i in self._ram_banks_il_idx: + size += self._ram_banks[i].size() + return size + + + + def iter_ram_banks(self) -> Iterable[Bank]: + """ + :return: an iterator over all banks. + :rtype: Iterable[Bank] + """ + return iter(self._ram_banks) + + + + def iter_cont_ram_banks(self) -> Iterable[Bank]: + """ + :return: an iterator over all continuous banks. + :rtype: Iterable[Bank] + """ + m = map((lambda b: None if b[0] in self._ram_banks_il_idx else b[1]), enumerate(self._ram_banks)) + return filter(None, m) + + + + def iter_il_ram_banks(self) -> Iterable[Bank]: + """ + :return: an iterator over all interleaved banks. + :rtype: Iterable[Bank] + """ + m = map((lambda b: None if not b[0] in self._ram_banks_il_idx else b[1]), enumerate(self._ram_banks)) + return filter(None, m) + + + + def has_il_ram(self) -> bool: + """ + :return: `True` if the system has interleaved ram. + :rtype: bool + """ + return self._il_banks_present + + + + def iter_il_groups(self) -> Iterable[ILRamGroup]: + """ + :return: an iterator over the interleaved ram bank groups. + :rtype: Iterable[ILRamGroup] + """ + return iter(self._ram_banks_il_groups) + + + + def iter_linker_sections(self) -> Iterable[LinkerSection]: + """ + :return: an iterator over the linker sections + :rtype: Iterable[LinkerSection] + """ + return iter(self._linker_sections) + + + + def iter_bank_numwords(self) -> Generator[int, None, None]: + """ + Iterates over the size of the ram banks in number of words. + + :return: Generator over the sizes + :rtype: Generator[int, None, None] + """ + sizes = set() + for b in self._ram_banks: + if b.size() not in sizes: + sizes.add(b.size()) + yield b.size() // 4 + + def build(self): + """ + Makes the system ready to be used. + + - Aplies the overrides for the interleaved memory as the normal memory needs to be configured first. + - Sorts the linker sections by starting address. + - Inferes the missing linker section ends with the start of the next section if present. If not it uses the end of the last memory bank. + """ + if self._ignore_ram_interleaved: + sec_name = "" + if self.ram_numbanks() > 1: + sec_name = "data_interleaved" + self.add_ram_banks_il(self._override_numbanks_il, 32, sec_name, ignore_ignore=True) #Add automatically a section for compatibility purposes. + + + self._linker_sections.sort(key=lambda l: l.start) + + old_sec: Optional[LinkerSection] = None + for sec in self._linker_sections: + if old_sec is not None: + old_sec.end = sec.start + + if sec.end is None: + old_sec = sec + else: + old_sec = None + if old_sec is not None: + if len(self._ram_banks) == 0: + raise RuntimeError("There is no ram bank to infere the end of a section") + old_sec.end = self._ram_banks[-1].end_address() + \ No newline at end of file diff --git a/hw/vendor/esl_epfl_x_heep/x-heep-tb-utils.core b/hw/vendor/esl_epfl_x_heep/x-heep-tb-utils.core index 05b75ba5..0caaea00 100644 --- a/hw/vendor/esl_epfl_x_heep/x-heep-tb-utils.core +++ b/hw/vendor/esl_epfl_x_heep/x-heep-tb-utils.core @@ -14,7 +14,10 @@ filesets: - example:ip:gpio_cnt - example:ip:pdm2pcm_dummy - example:ip:ams + - example:ip:iffifo - example:ip:i2s_microphone + - example:ip:simple_accelerator + - example:ip:im2col_spc files: file_type: systemVerilogSource @@ -22,6 +25,9 @@ filesets: files: - hw/ip_examples/slow_memory/slow_memory.vlt - hw/ip_examples/ams/ams.vlt + - hw/ip_examples/iffifo/iffifo.vlt + - hw/ip_examples/simple_accelerator/simple_accelerator.vlt + - hw/ip_examples/im2col_spc/im2col_spc.vlt - tb/tb.vlt file_type: vlt @@ -67,6 +73,11 @@ filesets: - tb/tb_top.cpp file_type: cppSource + tb-sc-verilator: + files: + - tb/tb_sc_top.cpp + file_type: cppSource + targets: default: &default_target filesets: @@ -75,13 +86,17 @@ targets: - tool_verilator? (uartdpi) - tool_modelsim? (systemverilog_only_uart) - tool_vcs? (systemverilog_only_uart) + - tool_xcelium? (systemverilog_only_uart) - tool_verilator? (files_verilator_waiver) - tool_verilator? (remote_bitbang_dpi) - tool_modelsim? (systemverilog_only_simjtag) - tool_vcs? (systemverilog_only_simjtag) + - tool_xcelium? (systemverilog_only_simjtag) - tool_modelsim? (cypress_flash) - tool_vcs? (cypress_flash) + - tool_xcelium? (cypress_flash) toplevel: - tool_modelsim? (tb_top) - tool_vcs? (tb_top) + - tool_xcelium? (tb_top) - tool_verilator? (testharness) diff --git a/hw/vendor/eslepfl_x_heep.lock.hjson b/hw/vendor/eslepfl_x_heep.lock.hjson index 04dcb944..c62e55c8 100644 --- a/hw/vendor/eslepfl_x_heep.lock.hjson +++ b/hw/vendor/eslepfl_x_heep.lock.hjson @@ -8,7 +8,7 @@ { upstream: { - url: https://github.com/esl-epfl/x-heep.git - rev: df569a88fc7eaa447645262f0d3a76dd22c519f7 + url: https://github.com/Luigi2898/x-heep.git + rev: 83f1563fd4894787167b27099006c8b1b042d3d1 } } diff --git a/hw/vendor/eslepfl_x_heep.vendor.hjson b/hw/vendor/eslepfl_x_heep.vendor.hjson index 1b336093..655e0a58 100644 --- a/hw/vendor/eslepfl_x_heep.vendor.hjson +++ b/hw/vendor/eslepfl_x_heep.vendor.hjson @@ -7,8 +7,8 @@ target_dir: "esl_epfl_x_heep", upstream: { - url: "https://github.com/esl-epfl/x-heep.git", - rev: "df569a88fc7eaa447645262f0d3a76dd22c519f7", + url: "https://github.com/Luigi2898/x-heep.git", + rev: "83f1563fd4894787167b27099006c8b1b042d3d1", }, patch_dir: "patches/esl_epfl_x_heep", diff --git a/sw/applications/mmul_os/4x4/bitstreams b/sw/applications/mmul_os/4x4/bitstreams new file mode 100644 index 00000000..4e32db09 --- /dev/null +++ b/sw/applications/mmul_os/4x4/bitstreams @@ -0,0 +1,2 @@ +kmem: 0x0, 0xf01c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +imem: 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x850d0000, 0x0, 0xa4081ff4, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0x850d0000, 0x0, 0x0, 0xc80000, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa5081ffc, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0xab0000, 0xd0000, 0x8780001c, 0x0, 0xf0000, 0x0, 0x0, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x0, 0x0, 0xa5081ffc, 0x91c00000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8a0d0001, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xab0000, 0xd0000, 0xd0000, 0x87800018, 0xf0000, 0x0, 0x0, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x7a180010, 0x0, 0x0, 0x0, 0xa5081ffc, 0x91c00000, 0x7a180004, 0x0, 0x5a080010, 0x8a0d0001, 0x7a181ff0, 0x1a181ffd, 0xd0000, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x820d0000, 0x0, 0xa4080004, 0x0, 0x91c00000, 0x0, 0x5080000, 0x0, 0x820d0000, 0x0, 0x820d0000, 0x2080000, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x2080000, 0x0, 0x0, 0x0, 0x5080000, 0x820d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa5081ffc, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x820d0000, 0x0, 0x3080000, 0x0, 0x820d0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa5081ffc, 0x0, 0x91c00000, 0x0, 0x43180000, 0x0, 0x830d0000, 0x0, 0x830d0000, 0x4080000, 0x840d0000, 0x0, 0xab0000, 0xd0000, 0x0, 0x0, 0xf0000, 0x87800010, 0x8a0d0001, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x0, 0x0, 0xa4080004, 0x91c00000, 0x7a181ffc, 0x0, 0x0, 0xd0000, 0x7a180010, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x850d0000, 0x0, 0xa4080004, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x830d0000, 0x0, 0x2080000, 0x0, 0x830d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x3a080010, 0x0, 0x0, 0x0, 0x4080000, 0x830d0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x800005, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x0, 0x800003, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa508000c, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0x840d0000, 0x0, 0x800002, 0x0, 0xab0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x7a180010, 0x0, 0x0, 0x0, 0xa4080004, 0x91c00000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x820d0000, 0x0, 0xa4080004, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \ No newline at end of file diff --git a/sw/applications/mmul_os/4x4/out.sat b/sw/applications/mmul_os/4x4/out.sat new file mode 100644 index 00000000..d661655a --- /dev/null +++ b/sw/applications/mmul_os/4x4/out.sat @@ -0,0 +1,477 @@ +T = 0 +LWD R2 +LWD R2 +LWD R2 +LWD R1 +LWD R1 +LWD R2 +LWD R2 +LWD R2 +LWD R2 +LWD R1 +LWD R2 +LWD R2 +LWD R2 +LWD R2 +LWD R1 +LWD R2 +T = 1 +NOP +NOP +NOP +SADD R2, ZERO, ZERO +SADD R2, ZERO, ZERO +NOP +NOP +NOP +NOP +SADD R2, ZERO, ZERO +NOP +NOP +NOP +NOP +NOP +NOP +T = 2 +NOP +NOP +NOP +BEQ R2, R1, 28 +SADD R2, ZERO, ZERO +NOP +NOP +NOP +NOP +NOP +NOP +NOP +NOP +NOP +NOP +NOP +T = 3 +NOP +NOP +NOP +NOP +BEQ R2, R1, 24 +NOP +NOP +NOP +NOP +NOP +NOP +NOP +NOP +NOP +NOP +NOP +T = 4 +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +SADD R3, ZERO, ZERO +T = 5 +NOP +NOP +NOP +NOP +NOP +NOP +NOP +NOP +NOP +BEQ R2, R1, 16 +NOP +NOP +NOP +NOP +NOP +NOP +T = 6 +NOP +NOP +LWI R0, R2 +NOP +NOP +NOP +NOP +LWI R0, R2 +LWI R0, R2 +SADD R2, R2, 1 +NOP +NOP +NOP +LWI R0, R2 +NOP +NOP +T = 7 +NOP +SADD R0, ZERO, RCT +NOP +SADD R0, ZERO, RCB +SADD R0, ZERO, RCB +NOP +SADD R0, ZERO, RCT +NOP +NOP +SADD R0, ZERO, RCB +NOP +SADD R0, ZERO, RCT +SADD R0, ZERO, RCT +NOP +SADD R0, ZERO, RCB +NOP +T = 8 +SADD R0, ZERO, RCB +NOP +NOP +NOP +NOP +SADD R0, ZERO, RCB +NOP +NOP +NOP +NOP +SADD R0, ZERO, RCB +NOP +NOP +NOP +NOP +SADD R0, ZERO, RCB +T = 9 +LWI ROUT, R2 +NOP +NOP +NOP +NOP +LWI ROUT, R2 +NOP +NOP +NOP +NOP +LWI ROUT, R2 +NOP +NOP +NOP +NOP +LWI ROUT, R2 +T = 10 +NOP +SADD ROUT, ZERO, RCL +NOP +SADD ROUT, ZERO, RCR +SADD ROUT, ZERO, RCR +NOP +SADD ROUT, ZERO, RCL +NOP +NOP +SADD ROUT, ZERO, RCR +NOP +SADD ROUT, ZERO, RCL +SADD ROUT, ZERO, RCL +NOP +SADD ROUT, ZERO, RCR +NOP +T = 11 +NOP +NOP +SADD ROUT, ZERO, RCL +NOP +NOP +NOP +NOP +SADD ROUT, ZERO, RCL +SADD ROUT, ZERO, RCL +NOP +NOP +NOP +NOP +SADD ROUT, ZERO, RCL +NOP +NOP +T = 12 +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +SMUL ROUT, R0, ROUT +T = 13 +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +SADD R3, R3, ROUT +T = 14 +NOP +NOP +SADD R2, R2, 4 +NOP +SMUL ROUT, R1, 16 +NOP +NOP +SADD R2, R2, 4 +SADD R2, R2, 4 +NOP +NOP +NOP +NOP +SADD R2, R2, 4 +SMUL ROUT, R1, 16 +NOP +T = 15 +SADD R2, R2, RCB +NOP +NOP +NOP +NOP +SADD R2, R2, RCL +NOP +NOP +NOP +NOP +SADD R2, R2, RCB +NOP +BEQ ZERO, ZERO, 5 +NOP +NOP +SADD R2, R2, RCL +T = 16 +NOP +SADD ROUT, ZERO, R2 +NOP +NOP +NOP +NOP +SADD ROUT, ZERO, R2 +NOP +NOP +NOP +NOP +SADD ROUT, ZERO, R2 +SADD ROUT, ZERO, R2 +NOP +NOP +NOP +T = 17 +SADD ROUT, -12, RCT +SADD R2, R2, 16 +SADD ROUT, -4, RCB +NOP +NOP +SADD ROUT, 4, RCT +SADD R2, R2, 16 +SADD ROUT, -4, RCB +SADD ROUT, -4, RCB +NOP +SADD ROUT, 4, RCT +SADD R2, R2, 16 +SADD R2, R2, 16 +SADD ROUT, 12, RCB +NOP +SADD ROUT, 4, RCT +T = 18 +NOP +SADD ROUT, R2, -16 +NOP +SADD ROUT, -4, RCB +SADD ROUT, -4, RCB +NOP +SADD ROUT, R2, -16 +NOP +NOP +SADD ROUT, 4, RCT +NOP +SADD ROUT, R2, -16 +SADD ROUT, R2, -16 +NOP +SADD ROUT, 4, RCT +NOP +T = 19 +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +SWI R3, ROUT +T = 20 +NOP +NOP +NOP +NOP +SMUL ROUT, R1, 4 +NOP +NOP +NOP +NOP +SMUL ROUT, R1, -4 +NOP +NOP +NOP +NOP +NOP +NOP +T = 21 +NOP +NOP +NOP +NOP +NOP +SADD ROUT, ZERO, RCB +NOP +NOP +SMUL ROUT, RCT, RCR +NOP +NOP +NOP +NOP +NOP +NOP +NOP +T = 22 +NOP +NOP +NOP +NOP +SADD ROUT, RCB, 16 +NOP +SADD ROUT, ZERO, RCL +NOP +NOP +NOP +NOP +SADD ROUT, RCR, 16 +NOP +NOP +NOP +NOP +T = 23 +SADD R2, R2, RCB +NOP +SADD R2, R2, RCB +NOP +SADD R2, R2, 1 +SADD R2, R2, RCL +NOP +SADD R2, R2, RCL +SADD R2, R2, RCR +SADD R2, ZERO, ZERO +SADD R2, R2, RCR +NOP +BEQ ZERO, ZERO, 3 +SADD R2, R2, RCT +NOP +SADD R2, R2, RCT +T = 24 +NOP +NOP +NOP +NOP +SMUL ROUT, R1, -16 +NOP +NOP +NOP +NOP +SMUL ROUT, R1, 16 +NOP +NOP +NOP +NOP +NOP +NOP +T = 25 +SADD R2, R2, RCB +NOP +NOP +NOP +SMUL ROUT, ROUT, -3 +SADD R2, R2, RCL +NOP +SADD ROUT, ZERO, RCR +SADD R2, R2, RCR +NOP +SADD ROUT, ZERO, RCL +NOP +NOP +SADD R2, R2, RCT +NOP +NOP +T = 26 +NOP +NOP +NOP +NOP +SADD R2, ZERO, ZERO +SADD ROUT, ZERO, RCL +SADD ROUT, ZERO, RCB +NOP +SADD ROUT, ZERO, RCT +NOP +NOP +SADD ROUT, ZERO, RCT +NOP +NOP +NOP +NOP +T = 27 +NOP +SADD R2, R2, RCB +SADD R2, R2, RCB +SADD R2, R2, 1 +NOP +NOP +SADD R2, R2, RCL +SADD R2, R2, RCL +SADD R2, R2, RCT +NOP +SADD R2, R2, RCR +SADD R2, R2, RCR +SADD R2, R2, RCT +BEQ ZERO, ZERO, 2 +NOP +SADD R2, R2, RCT +T = 0 diff --git a/sw/applications/mmul_os/cgra_bitstream.h b/sw/applications/mmul_os/cgra_bitstream.h new file mode 100644 index 00000000..92eb977f --- /dev/null +++ b/sw/applications/mmul_os/cgra_bitstream.h @@ -0,0 +1,14 @@ +#ifndef _CGRA_BITSTREAM_H_ +#define _CGRA_BITSTREAM_H_ + +#include + +#include "cgra.h" + +// Kernel 0 => NULL +#define TRANSFORMER 1 + +static uint32_t cgra_kmem_bitstream[CGRA_KMEM_SIZE] = { 0x0, 0xf01c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; +const uint32_t cgra_imem_bitstream[CGRA_IMEM_SIZE] = { 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x850d0000, 0x0, 0xa4081ff4, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0x850d0000, 0x0, 0x0, 0xc80000, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa5081ffc, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0xab0000, 0xd0000, 0x8780001c, 0x0, 0xf0000, 0x0, 0x0, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x0, 0x0, 0xa5081ffc, 0x91c00000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8a0d0001, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xab0000, 0xd0000, 0xd0000, 0x87800018, 0xf0000, 0x0, 0x0, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x7a180010, 0x0, 0x0, 0x0, 0xa5081ffc, 0x91c00000, 0x7a180004, 0x0, 0x5a080010, 0x8a0d0001, 0x7a181ff0, 0x1a181ffd, 0xd0000, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x820d0000, 0x0, 0xa4080004, 0x0, 0x91c00000, 0x0, 0x5080000, 0x0, 0x820d0000, 0x0, 0x820d0000, 0x2080000, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x2080000, 0x0, 0x0, 0x0, 0x5080000, 0x820d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa5081ffc, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x820d0000, 0x0, 0x3080000, 0x0, 0x820d0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa5081ffc, 0x0, 0x91c00000, 0x0, 0x43180000, 0x0, 0x830d0000, 0x0, 0x830d0000, 0x4080000, 0x840d0000, 0x0, 0xab0000, 0xd0000, 0x0, 0x0, 0xf0000, 0x87800010, 0x8a0d0001, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x0, 0x0, 0xa4080004, 0x91c00000, 0x7a181ffc, 0x0, 0x0, 0xd0000, 0x7a180010, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x850d0000, 0x0, 0xa4080004, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x830d0000, 0x0, 0x2080000, 0x0, 0x830d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x3a080010, 0x0, 0x0, 0x0, 0x4080000, 0x830d0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x800005, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x0, 0x800003, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa508000c, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0x840d0000, 0x0, 0x800002, 0x0, 0xab0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x7a180010, 0x0, 0x0, 0x0, 0xa4080004, 0x91c00000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x820d0000, 0x0, 0xa4080004, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + +#endif // _CGRA_BITSTREAM_H_ diff --git a/sw/applications/mmul_os/main.c b/sw/applications/mmul_os/main.c new file mode 100644 index 00000000..2d9a386f --- /dev/null +++ b/sw/applications/mmul_os/main.c @@ -0,0 +1,294 @@ +/* + ******************* +******************************* C SOURCE FILE ******************************* +** ******************* ** +** ** +** project : HEEPsilon ** +** filename : main.c ** +** version : 1 ** +** date : 01/10/23 ** +** ** +***************************************************************************** +** ** +** Copyright (c) EPFL ** +** All rights reserved. ** +** ** +***************************************************************************** +*/ + +/***************************************************************************/ +/***************************************************************************/ + +/** +* @file main.c +* @date 01/10/23 +* @brief An application to run a matrix multiplication. +* +*/ + +/****************************************************************************/ +/** **/ +/* MODULES USED */ +/** **/ +/****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "transformer.h" +#include "cgra_bitstream.h" +#include "cgra_x_heep.h" +#include "performance.h" + +// For interrupt handling +#include "csr.h" +#include "handler.h" +#include "rv_plic.h" +#include "rv_plic_regs.h" +#include "hart.h" + + +/****************************************************************************/ +/** **/ +/* DEFINITIONS AND MACROS */ +/** **/ +/****************************************************************************/ + +// Size of the input buffer for the CGRA +#define CGRA_COL_INPUT_SIZE 4 + +/****************************************************************************/ +/** **/ +/* PROTOTYPES OF LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + +// Matrix multiplication using the standard three loops +void mmulSoftware(int32_t * output); +// Fill input matrixes with numbers +void fillMatrixInputs(); +// Handler for the CGRA interruption +void handler_irq_cgra(uint32_t id); +// Record the cycle number at the start +void kcom_perfRecordStart( kcom_time_diff_t *perf ); +// Record the cycle number and compute the total cycles +void kcom_perfRecordStop( kcom_time_diff_t *perf ); +// Show the performance metrics +void showPerformance( kcom_perf_t* kperf, int full); +// Print a matrix +void printMatrix(int * matrix, int rows, int cols); + +/****************************************************************************/ +/** **/ +/* GLOBAL VARIABLES */ +/** **/ +/****************************************************************************/ + +// Performance variable +static kcom_perf_t kperf; + +// Plic controller variables +volatile bool cgra_intr_flag; + +// CGRA variables +static cgra_t cgra; +static uint8_t cgra_slot; + +// CGRA input and output buffers +static int32_t cgra_input[CGRA_N_COLS][CGRA_COL_INPUT_SIZE] __attribute__ ((aligned (4))); + +// Input and output matrixes +int32_t matrixA[ROWS_A*COLS_A]; +int32_t matrixB[ROWS_B*COLS_B]; +int32_t matrixC[ROWS_C*COLS_C]; +int32_t outSW[ROWS_C*COLS_C]; + +/****************************************************************************/ +/** **/ +/* LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + +void main() +{ + fillMatrixInputs(); + + // Init timer + timerInit(); + + // Enable and reset the CGRA performance counters + cgra_perf_cnt_enable(&cgra, 1); + cgra_perf_cnt_reset( &cgra ); + + if(ROWS_C < CGRA_N_COLS || COLS_C < CGRA_N_ROWS){ + kcom_perfRecordStart(&(kperf.time.sw)); + mmulSoftware(matrixC); + kcom_perfRecordStop(&(kperf.time.sw)); + } else { + + // Initialize the CGRA + kcom_perfRecordStart(&(kperf.time.load)); + initCGRA(); + kcom_perfRecordStop(&(kperf.time.load)); + + // Prepare the input vector for the CGRA + kcom_perfRecordStart(&(kperf.time.input)); + // Col 0: &B[0][0], nItLoopColsC, &A[0][0], &C[0][3] + cgra_input[0][0] = &matrixB[0]; + cgra_input[0][1] = COLS_C/CGRA_N_ROWS; + cgra_input[0][2] = &matrixA[0]; + cgra_input[0][3] = &matrixC[3]; + // Col 1: &C[1][0], &B[0][1], nItLoopsColsA, &A[1][0] + cgra_input[1][0] = &matrixC[COLS_C]; + cgra_input[1][1] = &matrixB[1]; + cgra_input[1][2] = COLS_A; + cgra_input[1][3] = &matrixA[COLS_A]; + // Col 2: &A[2][0], &C[2][1], &B[0][2], nItLoopColsC + cgra_input[2][0] = &matrixA[2*COLS_A]; + cgra_input[2][1] = &matrixC[2*COLS_C+1]; + cgra_input[2][2] = &matrixB[2]; + cgra_input[2][3] = COLS_C/CGRA_N_ROWS; + // Col 3: nItLoopRowsC, &A[3][0], &C[3][2], &B[0][3], + cgra_input[3][0] = ROWS_C/CGRA_N_COLS; + cgra_input[3][1] = &matrixA[3*COLS_A]; + cgra_input[3][2] = &matrixC[3*COLS_C+2]; + cgra_input[3][3] = &matrixB[3]; + kcom_perfRecordStop(&(kperf.time.input)); + + // Set CGRA kernel L/S pointers + kcom_perfRecordStart( &(kperf.time.reprogramCols) ); + for(int col_idx = 0 ; col_idx < CGRA_N_COLS ; col_idx++){ + cgra_set_read_ptr ( &cgra, cgra_slot, (uint32_t) cgra_input[col_idx], col_idx ); + } + kcom_perfRecordStop( &(kperf.time.reprogramCols) ); + + // CGRA Execution + kcom_perfRecordStart( &(kperf.time.cgra) ); + cgra_intr_flag = 0; + cgra_set_kernel( &cgra, cgra_slot, TRANSFORMER ); + // Wait until CGRA is done + while(cgra_intr_flag==0) { + wait_for_interrupt(); + } + kcom_perfRecordStop( &(kperf.time.cgra) ); + + + // Software + kcom_perfRecordStart(&(kperf.time.sw)); + mmulSoftware(outSW); + kcom_perfRecordStop(&(kperf.time.sw)); + + checkErrors(); + } + + showPerformance(&kperf, 0); + + return EXIT_SUCCESS; +} + +// Check if the SW and CGRA executions give the same result +void checkErrors(){ + int errors = 0; + for(int i = 0; i < ROWS_C*COLS_C; i++ ){ + if(outSW[i]!=matrixC[i]){ + errors++; + } + } + printf("\rErrors: %d\n", errors); + + if(errors>0){ + printMatrix(matrixC, ROWS_C, COLS_C); + } +} + +// Initialize the CGRA +void initCGRA(){ + // Init the PLIC + plic_Init(); + plic_irq_set_priority(CGRA_INTR, 1); + plic_irq_set_enabled(CGRA_INTR, kPlicToggleEnabled); + plic_assign_external_irq_handler( CGRA_INTR, (void *) &handler_irq_cgra); + + // Enable interrupt on processor side + // Enable global interrupt for machine-level interrupts + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + // Set mie.MEIE bit to one to enable machine-level external interrupts + const uint32_t mask = 1 << 11;//IRQ_EXT_ENABLE_OFFSET; + CSR_SET_BITS(CSR_REG_MIE, mask); + cgra_intr_flag = 0; + + // Load kernel + cgra_cmem_init(cgra_imem_bitstream, cgra_kmem_bitstream); + + cgra.base_addr = mmio_region_from_addr((uintptr_t)CGRA_PERIPH_START_ADDRESS); + // Select request slot of CGRA + cgra_slot = cgra_get_slot(&cgra); +} + +// Fill matrix inputs +void fillMatrixInputs(){ + for(int i = 0; i < ROWS_A; i++){ + for(int j=0; j < COLS_A; j++){ + matrixA[i*COLS_A+j] = (i*COLS_A+j+1)%100; + } + } + + for(int i = 0; i < ROWS_B; i++){ + for(int j=0;j < COLS_B; j++){ + matrixB[i*COLS_B+j] = (i*COLS_B+j+1)%100; + } + } +} + +// Software matrix multiplication +void mmulSoftware(int32_t * out){ + for(int i = 0; i < ROWS_A; i++){ + for(int j=0;j < COLS_B; j++){ + for(int k=0; k < COLS_A; k++){ + out[i*COLS_C+j] += matrixA[i*COLS_A+k]*matrixB[k*COLS_B+j]; + } + } + } +} + +// Print matrix +void printMatrix(int * matrix, int rows, int cols){ + for(int i = 0; i < rows; i++){ + printf("[ "); + for(int j=0; j < cols; j++){ + printf("%d ", matrix[i*cols+j]); + } + printf("]\n"); + } +} + +// Interrupt controller variables +void handler_irq_cgra(uint32_t id) { + cgra_intr_flag = 1; +} + +// Display the performance values +void showPerformance( kcom_perf_t* kperf, int full){ + printf("\rA:%dx%d, B:%dx%d\n", ROWS_A, COLS_A, ROWS_B, COLS_B); + printf("\rSw: %d\n", kperf->time.sw.spent_cy); + if (full){ + printf("\rLoad: %d\n", kperf->time.load.spent_cy); + printf("\rProgram cols: %d\n", kperf->time.reprogramCols.spent_cy); + printf("\rInput: %d\n", kperf->time.input.spent_cy); + printf("\rCgra: %d\n", kperf->time.cgra.spent_cy); + } + int32_t overhead = kperf->time.input.spent_cy + kperf->time.reprogramCols.spent_cy + kperf->time.load.spent_cy; + //printf("\rOverhead: %d\n", overhead); + printf("\rTotal cgra: %d\n", overhead + kperf->time.cgra.spent_cy); +} + + + +/****************************************************************************/ +/** **/ +/* EOF */ +/** **/ +/****************************************************************************/ diff --git a/sw/applications/mmul_os/mulSoftware.py b/sw/applications/mmul_os/mulSoftware.py new file mode 100644 index 00000000..fe38a9e4 --- /dev/null +++ b/sw/applications/mmul_os/mulSoftware.py @@ -0,0 +1,51 @@ + +def crear_matriz(filas, columnas): + matriz = [[i*columnas + j + 1 for j in range(columnas)] for i in range(filas)] + return matriz + +def mostrar_matriz(matriz): + for fila in matriz: + print(fila) + +def multiplicar_matrices(matriz_a, matriz_b): + resultado = [[0 for _ in range(len(matriz_b[0]))] for _ in range(len(matriz_a))] + + for i in range(len(matriz_a)): + for j in range(len(matriz_b[0])): + for k in range(len(matriz_b)): + resultado[i][j] += matriz_a[i][k] * matriz_b[k][j] + + return resultado + + +def main(): + filas_a = int(input("Ingrese el número de filas para la matriz A: ")) + columnas_a = int(input("Ingrese el número de columnas para la matriz A: ")) + + filas_b = int(input("Ingrese el número de filas para la matriz B: ")) + columnas_b = int(input("Ingrese el número de columnas para la matriz B: ")) + + if columnas_a != filas_b: + print("No se pueden multiplicar matrices con estas dimensiones.") + return + + # Crear matrices A y B + matriz_a = crear_matriz(filas_a, columnas_a) + matriz_b = crear_matriz(filas_b, columnas_b) + + # Mostrar matrices A y B + #print("\nMatriz A:") + #mostrar_matriz(matriz_a) + + #print("\nMatriz B:") + #mostrar_matriz(matriz_b) + + # Multiplicar matrices A y B + matriz_resultado = multiplicar_matrices(matriz_a, matriz_b) + + # Mostrar resultado + print("\nResultado de la multiplicación:") + mostrar_matriz(matriz_resultado) + +if __name__ == "__main__": + main() diff --git a/sw/applications/mmul_os/performance.c b/sw/applications/mmul_os/performance.c new file mode 100644 index 00000000..421d39be --- /dev/null +++ b/sw/applications/mmul_os/performance.c @@ -0,0 +1,62 @@ +#include "performance.h" + +// For the timer +#include "rv_timer.h" +#include "soc_ctrl.h" +#include "core_v_mini_mcu.h" + +// Timer +static rv_timer_t timer; + +void kcom_perfRecordStart( kcom_time_diff_t *perf ) +{ + timeStart( perf ); +} + +void kcom_perfRecordStop( kcom_time_diff_t *perf ) +{ + timeStop( perf ); +} + +void timeStart( kcom_time_diff_t *perf ) +{ + perf->start_cy = getTime_cy(); +} + +void timeStop( kcom_time_diff_t *perf ) +{ + perf->end_cy = getTime_cy(); + perf->spent_cy += perf->end_cy - perf->start_cy; +} + +uint64_t getTime_cy( ) +{ + static uint64_t out; + rv_timer_counter_read( &timer, HART_ID, &out ); + return out; +} + +//Initialize the timer +void timerInit() +{ + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + uint32_t freq_hz = soc_ctrl_get_frequency(&soc_ctrl); + + mmio_region_t timer_0_reg = mmio_region_from_addr(RV_TIMER_AO_START_ADDRESS); + + rv_timer_init( timer_0_reg, (rv_timer_config_t) { .hart_count = 2, .comparator_count = 1 }, &timer ); + + rv_timer_tick_params_t tick_params; + + // The same frequency is provaided to get one tick per cycle. + rv_timer_approximate_tick_params( freq_hz, freq_hz, &tick_params ); + rv_timer_set_tick_params(&timer, HART_ID, tick_params); + + // Juan: see if i cannot remove this! + rv_timer_irq_enable(&timer, HART_ID, 0, kRvTimerEnabled); + rv_timer_arm(&timer, HART_ID, 0, 1); + + rv_timer_counter_set_enabled(&timer, HART_ID, kRvTimerEnabled); + +} \ No newline at end of file diff --git a/sw/applications/mmul_os/performance.h b/sw/applications/mmul_os/performance.h new file mode 100644 index 00000000..b7e17578 --- /dev/null +++ b/sw/applications/mmul_os/performance.h @@ -0,0 +1,62 @@ +#include +#include "cgra.h" + +typedef long int kcom_time_t; +typedef kcom_time_t kcom_param_t; + +typedef struct +{ + uint32_t cyc_act; + uint32_t cyc_stl; +} kcom_col_perf_t; + +typedef struct +{ + kcom_time_t start_cy; + kcom_time_t end_cy; + kcom_time_t spent_cy; +} kcom_time_diff_t; + +typedef struct +{ + kcom_time_diff_t sw; + kcom_time_diff_t cgra; + kcom_time_diff_t load; + kcom_time_diff_t input; + kcom_time_diff_t output; + kcom_time_diff_t reprogramCols; + kcom_time_diff_t bitstream; +} kcom_timing_t; + +typedef struct +{ + kcom_col_perf_t cols[CGRA_N_COLS]; + kcom_col_perf_t cols_max; + uint32_t cyc_ratio; // Stored *CGRA_STAT_PERCENT_MULTIPLIER + kcom_timing_t time; +} kcom_perf_t; + +typedef struct +{ + kcom_param_t sw; + kcom_param_t conf; + kcom_param_t cgra; + kcom_param_t repo; +} kcom_run_t; + +typedef struct +{ + kcom_run_t avg; + uint32_t n; + uint32_t errors; + uint8_t *name; +} kcom_stats_t; + +#define HART_ID 0 + +void timerInit(); +uint64_t getTime_cy( ); +void timeStop( kcom_time_diff_t *perf ); +void timeStart( kcom_time_diff_t *perf ); +void kcom_perfRecordStop( kcom_time_diff_t *perf ); +void kcom_perfRecordStart( kcom_time_diff_t *perf ); \ No newline at end of file diff --git a/sw/applications/mmul_os/transformer.h b/sw/applications/mmul_os/transformer.h new file mode 100644 index 00000000..7fe11944 --- /dev/null +++ b/sw/applications/mmul_os/transformer.h @@ -0,0 +1,16 @@ +#ifndef _STIMULI_H_ +#define _STIMULI_H_ + +#include +#include "cgra.h" + +// C multiple of 4x4 + +#define ROWS_A 16 +#define COLS_A 16 +#define COLS_B 16 +#define ROWS_B COLS_A +#define ROWS_C ROWS_A +#define COLS_C COLS_B + +#endif // _STIMULI_H_ diff --git a/sw/applications/trans_versasense/SYLT-FFT b/sw/applications/trans_versasense/SYLT-FFT new file mode 160000 index 00000000..c6f58caa --- /dev/null +++ b/sw/applications/trans_versasense/SYLT-FFT @@ -0,0 +1 @@ +Subproject commit c6f58caa8d3d01c622768b5c66a0be1d7953235b diff --git a/sw/applications/trans_versasense/addNormC.c b/sw/applications/trans_versasense/addNormC.c new file mode 100644 index 00000000..31828e28 --- /dev/null +++ b/sw/applications/trans_versasense/addNormC.c @@ -0,0 +1,71 @@ +// +// Created by alireza on 10/6/23. +// + +#include "addNormC.h" + + + +// Function implementations +AddNormalize createAddNormalize(int seq_len, int input_dim, quant_bit_width *weight, quant_bit_width *bias) { + AddNormalize addNorm; + addNorm.seq_len_ = seq_len; + addNorm.input_dim_ = input_dim; + addNorm.weight_ = weight; + addNorm.bias_ = bias; + // Initialize other fields as needed + return addNorm; +} + + + + +void normalize(AddNormalize *addNorm, quant_bit_width *input, quant_bit_width *input_normalized) { + for (int i = 0; i < addNorm->seq_len_; i++) { + quant_bit_width *input_ptr = input + i * (addNorm->input_dim_); + quant_bit_width *input_normalized_ptr = input_normalized + i * (addNorm->input_dim_); + + int sum = 0; + for (int j = 0; j < addNorm->input_dim_; j++) { + sum += *input_ptr; + input_ptr++; + } + + input_ptr = input + i * (addNorm->input_dim_); + quant_bit_width mean = (quant_bit_width)((float)sum / (float)addNorm->input_dim_); + + int64_t variance = 0; + for (int j = 0; j < addNorm->input_dim_; j++) { + variance += MUL_HQ((*input_ptr - mean), (*input_ptr - mean)); + input_ptr++; + } + + variance = SHIFT(variance); + float variance_float = (float)variance / (float)(addNorm->input_dim_); + variance_float = variance_float / (float)(1 << NUM_FRACTION_BITS); + float sd = sqrtf(variance_float); + float sd_inv = (float)(1 / (sd + 0.00001)); // prevent zero divide! + quant_bit_width sd_inv_int = (quant_bit_width)(sd_inv * (1 << NUM_FRACTION_BITS)); + + input_ptr = input + i * (addNorm->input_dim_); + input_normalized_ptr = input_normalized + i * (addNorm->input_dim_); + + for (int j = 0; j < addNorm->input_dim_; j++) { + *input_normalized_ptr = (quant_bit_width)MUL((*input_ptr - mean), sd_inv_int); + *input_normalized_ptr = (quant_bit_width)(MUL((*input_normalized_ptr), addNorm->weight_[j]) + addNorm->bias_[j]); + input_ptr++; + input_normalized_ptr++; + } + } +} + +void add(quant_bit_width *input, quant_bit_width *to_be_added, int seq_len, int input_dim) { + int32_t sum; + for (int i = 0; i < seq_len * input_dim; i++) { + sum = input[i] + to_be_added[i]; + if ((quant_bit_width)sum != sum) // In case of overflow in 16 bits + input[i] = (sum > 0) ? INT16_MAX : INT16_MIN; + else + input[i] = (quant_bit_width)sum; + } +} diff --git a/sw/applications/trans_versasense/addNormC.h b/sw/applications/trans_versasense/addNormC.h new file mode 100644 index 00000000..c2132867 --- /dev/null +++ b/sw/applications/trans_versasense/addNormC.h @@ -0,0 +1,26 @@ +// +// Created by alireza on 10/5/23. +// + +#ifndef FVLLMONTITRANSFORMER_ADDNORMC_H +#define FVLLMONTITRANSFORMER_ADDNORMC_H + + +#include +#include +#include "math.h" +#include "param.h" + +typedef struct { + int seq_len_; + int input_dim_; + quant_bit_width *weight_; + quant_bit_width *bias_; +} AddNormalize; + + +AddNormalize createAddNormalize(int seq_len, int input_dim, quant_bit_width *weight, quant_bit_width *bias); +void normalize(AddNormalize *addNorm, quant_bit_width *input, quant_bit_width *input_normalized); +void add(quant_bit_width *input, quant_bit_width *to_be_added, int seq_len, int input_dim); + +#endif //FVLLMONTITRANSFORMER_ADDNORMC_H diff --git a/sw/applications/trans_versasense/cgra_bitstream.h b/sw/applications/trans_versasense/cgra_bitstream.h new file mode 100644 index 00000000..014ee6b8 --- /dev/null +++ b/sw/applications/trans_versasense/cgra_bitstream.h @@ -0,0 +1,12 @@ +#ifndef _CGRA_BITSTREAM_H_ +#define _CGRA_BITSTREAM_H_ + +#include + +#include "cgra.h" + + +static uint32_t cgra_kmem_bitstream[CGRA_KMEM_SIZE] = { 0x0, 0xf01c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; +const uint32_t cgra_imem_bitstream[CGRA_IMEM_SIZE] = { 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x850d0000, 0x0, 0xa4081ff4, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0x850d0000, 0x0, 0x0, 0xc80000, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa5081ffc, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0xab0000, 0xd0000, 0x8780001c, 0x0, 0xf0000, 0x0, 0x0, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x0, 0x0, 0xa5081ffc, 0x91c00000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8a0d0001, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xab0000, 0xd0000, 0xd0000, 0x87800018, 0xf0000, 0x0, 0x0, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x7a180010, 0x0, 0x0, 0x0, 0xa5081ffc, 0x91c00000, 0x7a180004, 0x0, 0x5a080010, 0x8a0d0001, 0x7a181ff0, 0x1a181ffd, 0xd0000, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x820d0000, 0x0, 0xa4080004, 0x0, 0x91c00000, 0x0, 0x5080000, 0x0, 0x820d0000, 0x0, 0x820d0000, 0x2080000, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x2080000, 0x0, 0x0, 0x0, 0x5080000, 0x820d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa5081ffc, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x820d0000, 0x0, 0x3080000, 0x0, 0x820d0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa5081ffc, 0x0, 0x91c00000, 0x0, 0x43180000, 0x0, 0x830d0000, 0x0, 0x830d0000, 0x4080000, 0x840d0000, 0x0, 0xab0000, 0xd0000, 0x0, 0x0, 0xf0000, 0x87800010, 0x8a0d0001, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x0, 0x0, 0xa4080004, 0x91c00000, 0x7a181ffc, 0x0, 0x0, 0xd0000, 0x7a180010, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x850d0000, 0x0, 0xa4080004, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x830d0000, 0x0, 0x2080000, 0x0, 0x830d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x3a080010, 0x0, 0x0, 0x0, 0x4080000, 0x830d0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x800005, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x0, 0x800003, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa508000c, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0x840d0000, 0x0, 0x800002, 0x0, 0xab0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x7a180010, 0x0, 0x0, 0x0, 0xa4080004, 0x91c00000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x820d0000, 0x0, 0xa4080004, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + +#endif // _CGRA_BITSTREAM_H_ diff --git a/sw/applications/trans_versasense/data_cpp/array_output.h b/sw/applications/trans_versasense/data_cpp/array_output.h new file mode 100644 index 00000000..6e5f8182 --- /dev/null +++ b/sw/applications/trans_versasense/data_cpp/array_output.h @@ -0,0 +1,4803 @@ +int32_t prototypes[32] ={-1394, -5770, -6778, 762, 4001, -653, -5906, -20, 1220, 3795, -73, -3028, 635, -448, 7677, -6204, 5745, 3112, 1206, -1120, -3618, 1076, -649, 943, -3896, 2462, 4658, 2494, 3996, 1220, -1144, -1013, }; +int32_t STFT_rand_out[5008] = { + -12926, + -13872, + -27384, + -9514, + 16213, + -2431, + -29203, + 22796, + -13520, + -24530, + -1523, + -22165, + 6477, + -23668, + -32732, + 6528, + -20306, + -12571, + -5238, + -32626, + -32234, + -24604, + -25164, + -23058, + -284, + 22733, + 13211, + 30060, + 18770, + 14117, + -24215, + -20438, + -23294, + -23461, + -24059, + -30987, + 23538, + -18331, + -26582, + 26174, + 20, + -17686, + 14638, + 7688, + -28912, + -31479, + -4877, + -9303, + -25054, + 12141, + -30938, + -524, + 15610, + -20836, + -7851, + 14700, + 9746, + 31669, + -7502, + 1309, + 29525, + 3044, + -18198, + -15137, + -19411, + -14748, + -360, + -14208, + 956, + -1978, + -29616, + 29686, + -18651, + 6835, + 22417, + 11981, + -30352, + -4294, + 15146, + 15946, + -8216, + -2676, + -25568, + -22291, + 24059, + 28953, + -1211, + 20453, + -15372, + 15895, + -13367, + 8986, + -4597, + -24977, + 3325, + -2151, + 8144, + -22983, + -10167, + 24625, + -14559, + -9138, + 26672, + -5194, + 17718, + 24553, + -12199, + -26118, + -27912, + -15155, + -28038, + 4660, + -31609, + -14976, + 29967, + 26386, + 1921, + -5581, + -32130, + 28884, + 31773, + -30010, + -13952, + 12436, + 7435, + 31562, + -6612, + -20653, + 1799, + 29773, + -17425, + 7086, + 21604, + -15587, + 7938, + -12378, + 15944, + -28828, + -29045, + 12192, + 30536, + 27413, + -3130, + 15968, + 24829, + -19012, + -15131, + 30818, + -12319, + 20688, + 2459, + 11630, + 10578, + -13135, + 16621, + 23622, + -27873, + -128, + -8153, + -7040, + -3606, + 17172, + 16609, + 19012, + -20002, + 29911, + -23373, + -7789, + 24490, + 29616, + -19123, + -553, + 29523, + -27481, + 18250, + 28582, + 25602, + 29650, + 711, + 28687, + 25094, + -9118, + 21846, + 4730, + -12093, + 23850, + -13120, + 17772, + -18230, + -6716, + 14165, + 5818, + -11610, + -7149, + -29858, + -21764, + -5007, + 22148, + -15056, + -12084, + 29091, + -14694, + -20469, + -9607, + 31452, + 7223, + 27291, + -28384, + 10091, + -22522, + -32301, + -3436, + 2894, + -11292, + 21662, + 14254, + -24221, + -1471, + 11612, + 31030, + -32011, + -15252, + 10322, + 19696, + -16379, + 4097, + 25235, + -4789, + 18162, + 8046, + 9464, + -20778, + -16502, + 8426, + 9249, + -28464, + 7466, + -14803, + 4080, + -31337, + 27890, + 1109, + -18359, + 391, + 15794, + 15523, + -6939, + 9040, + 29810, + -25918, + -8188, + -32473, + -15855, + -15203, + 12229, + 12970, + 29248, + 15769, + -11288, + 3980, + 4350, + 10360, + 26227, + -16574, + -24206, + -6505, + 22774, + -7700, + -23171, + -11802, + 26384, + 829, + 14673, + -6318, + 29972, + 14680, + -22102, + -7816, + -13898, + 5003, + -4263, + 189, + -19916, + -30573, + -8535, + 14572, + -9936, + -26676, + 3818, + 19551, + 30529, + -21036, + 8479, + -8020, + -20934, + -25849, + 14758, + -17965, + -629, + -22446, + 1018, + -20110, + 16369, + 20661, + -5079, + 7605, + 15698, + 10295, + -17857, + 28680, + 30879, + -28659, + 16006, + 22443, + -12548, + 1079, + -1265, + -28915, + -12687, + 2561, + -13443, + 23795, + -24009, + 26699, + 19807, + -3974, + 3819, + -30149, + -13138, + 25042, + 12139, + -18304, + 26972, + -1278, + 4375, + 1559, + 21023, + 3144, + -19398, + -26570, + -30278, + 32403, + -32387, + -1201, + 31541, + 17157, + 22523, + 18062, + 21859, + 20875, + -28203, + 935, + -3875, + 13172, + -32117, + 32384, + -18546, + 17175, + 11073, + 14237, + -4578, + 11500, + 20778, + -23597, + -13751, + -9037, + -840, + -8845, + 2111, + -17705, + 4320, + 12398, + 7115, + -10940, + 12479, + -11251, + -8914, + 31198, + -31652, + 32222, + -21006, + -25725, + -15830, + 24105, + 15855, + -3554, + 9600, + 26493, + -28575, + -1343, + -16665, + -10363, + -17524, + 19543, + 7643, + -18020, + 103, + -5280, + -13700, + 21561, + 27066, + -8114, + -31694, + -1871, + -17244, + 18003, + -17684, + -14058, + 17243, + -32338, + -5711, + 25414, + -29426, + -17471, + 22764, + -31461, + -28346, + 18427, + 29733, + 21327, + 7675, + -16185, + -21765, + 23937, + 4319, + 30560, + -24889, + 22803, + 28266, + 5135, + -7171, + 12306, + 7275, + -11087, + -13001, + -25855, + -17021, + 19691, + -32077, + 12594, + -16956, + 13447, + -26358, + -28094, + 21711, + -2822, + 13881, + -2024, + 944, + -1531, + 7536, + -11819, + 17016, + 1231, + -19096, + 31141, + -8695, + -12215, + 18540, + 27486, + -13423, + 18368, + 31866, + -7847, + -27840, + -20034, + 17794, + -30598, + 5252, + 13117, + 8254, + 20551, + 22681, + -17080, + -23734, + -1381, + 22104, + -24321, + 23290, + 14593, + 30678, + 8077, + 5683, + 30824, + -26447, + -28041, + -7579, + 5396, + -25382, + -30830, + 16697, + -5651, + -5669, + 25066, + 7923, + -8602, + -7568, + 1428, + 2086, + 9646, + 9921, + 10236, + -32042, + -30188, + -26716, + -10819, + 29027, + 2685, + -17932, + 1562, + -23341, + 23106, + 25932, + -24468, + -31981, + -8134, + -7668, + -6548, + -26611, + -8569, + 13345, + -20035, + -13303, + -14140, + 15907, + -16570, + -27988, + 31993, + -2213, + 11074, + -2180, + 9844, + 27811, + -20876, + -10509, + 24415, + -19322, + -8885, + -15411, + 29585, + -6993, + -21218, + -22845, + 5612, + 27716, + 8629, + -25219, + 10020, + -14034, + -21978, + -22960, + -14756, + -1675, + -11142, + -22732, + -26001, + 2092, + -1875, + 12030, + 9584, + -22989, + -4438, + -8482, + 30341, + -26973, + -8167, + -1178, + 12006, + 11545, + 13723, + -10590, + -5866, + -3215, + 12424, + -3375, + 18216, + -16570, + 16557, + -20582, + 15267, + 15055, + 18366, + 25221, + -23012, + -2653, + 7591, + -28861, + -31688, + 20146, + -22097, + -12879, + -5398, + -1418, + 14383, + -4150, + 23361, + -1390, + 3437, + 32363, + 15952, + -1668, + -19674, + 3769, + -32241, + 28821, + 13149, + -20898, + -1144, + -2525, + -24219, + 5802, + -17669, + 8417, + 26592, + -32499, + 17422, + -16415, + -23919, + 25813, + -28040, + -22601, + 1468, + 14163, + -22315, + -19399, + 9767, + 4165, + -19977, + 20448, + -22779, + 27858, + -1766, + 190, + -29823, + -16505, + -312, + 17984, + -9076, + -5499, + 29803, + 15855, + 6888, + -8312, + 3644, + 11457, + 4317, + -17444, + 3618, + -16483, + -8324, + -6687, + 8008, + -3434, + -23048, + 27919, + 2579, + -29502, + -20626, + 21824, + 20815, + -1169, + -1207, + -22279, + 18567, + -15192, + -23546, + 9365, + 15236, + -22584, + 24237, + -6775, + -1604, + -29255, + 8637, + -30992, + -10225, + 2020, + 20887, + 19804, + -28826, + -30072, + 28908, + -4411, + 32426, + 7164, + 5822, + -1725, + 20672, + 16917, + -6359, + 3500, + -13522, + -8914, + -6762, + 20743, + -30579, + -20477, + -20467, + 11558, + -6449, + -20306, + -21134, + 15487, + -15471, + -24053, + -29166, + -1315, + 17110, + -15244, + 22264, + -13565, + -26278, + -16028, + -26056, + -6350, + -12235, + 21483, + -23531, + 19358, + 7130, + -32059, + 23141, + -24415, + 19150, + -15109, + -17892, + -6297, + -28771, + 16209, + -4271, + -26537, + -16272, + 11591, + -14254, + -32254, + 15310, + 823, + 7398, + -24978, + 14571, + -29863, + -24431, + -4741, + -22409, + 14211, + -15800, + -25283, + 18678, + 21516, + 1306, + 21711, + 6212, + 22652, + 3211, + 20137, + 3614, + 4884, + -8760, + 12156, + 8736, + -23901, + -7654, + 29454, + -28701, + 1372, + -30274, + 9245, + -4131, + 12660, + 24430, + 11885, + -3583, + -31465, + -19075, + -26439, + -27444, + 7611, + 25711, + 28562, + -10350, + -25209, + -44, + -246, + 23005, + -11649, + 15978, + 10954, + -32007, + 31528, + 9957, + -8472, + -2969, + 29444, + 18342, + 10286, + 15607, + 11175, + 3868, + -873, + 9145, + 27836, + -19491, + -3923, + 20283, + -15474, + 4602, + -10544, + 13227, + -18799, + -3933, + 8526, + -4283, + 20362, + 7916, + 19902, + -20909, + -27935, + -16588, + -10018, + -8697, + 14099, + 20353, + 8114, + -4313, + -4726, + -31223, + 5311, + -17836, + 3798, + -20855, + -22384, + 3853, + 31386, + -18671, + -20161, + -20365, + 7828, + 6194, + -17876, + -3789, + -12482, + 26049, + 30756, + 1624, + -23607, + -67, + 8234, + 9945, + 21991, + 16088, + -10949, + -12993, + 27470, + 10589, + -12914, + -20814, + -31527, + 12612, + -22618, + 30076, + 7623, + -1373, + 14940, + -15277, + 6239, + -5248, + 28330, + -5719, + 12498, + 20128, + 5951, + -27017, + -13972, + 14154, + -17057, + 27704, + 10260, + -21510, + 25282, + -19133, + 12855, + 4603, + -2540, + -23034, + -3444, + 6267, + -2050, + 20400, + 12632, + 20652, + -7784, + 28608, + -4574, + -15647, + -20918, + 8063, + 1380, + -22462, + -19797, + -16678, + -25455, + 13116, + -4254, + 13772, + -14514, + -21073, + 32215, + -21643, + 2234, + -14166, + 5989, + 25081, + 18193, + -8935, + -26880, + -21512, + 14120, + 26288, + 21949, + 5976, + 18263, + -19562, + -28544, + -25557, + -16054, + 19987, + -28919, + -23450, + -13752, + -142, + 18948, + 8016, + 17683, + 26106, + 7900, + 17129, + -8502, + 22918, + -222, + 25286, + -31723, + 29414, + 8981, + -5933, + -14804, + 27957, + -6932, + 30146, + 8780, + 29280, + -23551, + -19465, + 29136, + 9737, + 9423, + -22144, + 16994, + -19030, + -21959, + -20516, + 31318, + -15165, + -1926, + -4519, + -9911, + -27268, + -23693, + -30088, + -15882, + -17362, + -13610, + -21459, + 11450, + -20001, + 806, + 27803, + -1592, + -1921, + 30491, + -9089, + 13199, + 3121, + -12552, + -19748, + 5034, + 26832, + -7364, + 24822, + -1228, + 29969, + -17341, + -13771, + 15422, + -23654, + 30519, + -19522, + -7411, + -32217, + -7186, + -8460, + 24164, + -24242, + -15575, + -8817, + -16770, + -18115, + 12774, + 7283, + 11895, + 26604, + 13813, + 24503, + 4648, + -23794, + -23563, + 1540, + 14755, + -3952, + 11669, + -28719, + -25955, + -11327, + -15954, + 28998, + 9472, + -2640, + 13752, + 6110, + -32635, + 3994, + 1154, + 1062, + 19389, + -18507, + -18595, + -24942, + 25435, + -16418, + 12937, + 4484, + -9292, + 1542, + 25323, + 23974, + -851, + -13385, + 17634, + 3767, + -29321, + -23743, + 12892, + -11911, + -28602, + -15306, + 8265, + 25090, + -12893, + -11284, + 6771, + 19534, + -27508, + -13654, + 26431, + -14797, + -26522, + 25373, + -25186, + 26339, + -29076, + -21156, + -7491, + 662, + 14570, + 4017, + 4956, + 5625, + -2291, + 20084, + -6322, + 4178, + -1086, + 2845, + 11984, + 29728, + 28445, + -6334, + -22894, + 11882, + -31932, + 14479, + -8273, + -22357, + 16418, + 9629, + 14494, + -5474, + 2004, + -28421, + -7633, + -32593, + 14649, + -27248, + -25416, + 31207, + -10867, + 17056, + 9328, + -11393, + -15548, + 14491, + 7193, + 8976, + 32698, + -10663, + 15576, + 13468, + -7233, + 32191, + -24578, + -29265, + 13724, + -7798, + -21982, + 29458, + -16695, + -5112, + 30116, + -18229, + 32256, + -31105, + 10366, + 17352, + -19409, + -22627, + 26489, + -3397, + -13120, + 5892, + -12133, + -20494, + -17438, + -12904, + 20632, + 4620, + -3188, + 13035, + 9271, + -20508, + -15582, + 30194, + -3896, + -5875, + 17087, + -4642, + 2596, + -30774, + -28169, + -12836, + -29601, + -31933, + 7529, + 31727, + 23804, + -18745, + -25360, + -31984, + -20007, + 18958, + 25051, + -22946, + 13954, + -3433, + 5338, + -13253, + 9474, + -31657, + -21383, + -16332, + 3791, + -25995, + -26720, + 31381, + -2767, + -5544, + -18210, + 9802, + 2893, + 16027, + -25458, + 2588, + -30748, + 31841, + 31772, + -947, + 24253, + -16747, + -27878, + -11711, + -11232, + -30461, + -19297, + 7754, + -3692, + -28623, + -6470, + 25003, + -3018, + -2635, + 22110, + -21204, + 28172, + 24245, + -6436, + 5789, + 5033, + 18757, + 32734, + -6412, + 6661, + -26348, + 23245, + 19742, + 12484, + -29770, + 13231, + -19778, + 32134, + 30432, + 1711, + -1405, + -25460, + 20952, + -14839, + 14822, + 15058, + 387, + -8587, + 24075, + -26810, + 6238, + 3087, + 13858, + -8076, + -8035, + 28295, + -16319, + 32422, + -30336, + 29680, + 31549, + -3440, + -4836, + -24867, + -32580, + -16642, + -452, + -20522, + -11479, + 30274, + 25331, + -26794, + -12126, + 26384, + 4575, + -19603, + 27754, + 10030, + 11025, + 22409, + -20910, + -31261, + 6739, + 28485, + -31870, + 8008, + -32301, + 12501, + -21350, + 4827, + 8191, + 19014, + -5042, + 30378, + 15269, + -19243, + -7606, + 17847, + 4758, + -28221, + 24883, + -935, + 16814, + 19882, + -20138, + 6773, + -3465, + 15568, + 28970, + 27063, + -16146, + -4845, + -31466, + -23032, + 19539, + -19938, + 15081, + -19168, + -1772, + -20222, + 30477, + -15124, + 31138, + 29244, + -23799, + -1787, + -2402, + 2557, + 18066, + 21665, + 273, + 31356, + 24961, + -46, + -12004, + 22075, + -8247, + -22658, + 3319, + -20544, + -4627, + 21400, + -22468, + -4218, + -4614, + 32165, + 25085, + 24403, + 22056, + -5335, + 12221, + 4260, + -417, + 13161, + -11078, + -17987, + 30601, + 21746, + -3520, + 26524, + 29752, + -27132, + 5990, + 32151, + -28731, + -15158, + -12955, + -7175, + 12408, + -25179, + 13039, + 30575, + 6485, + 10091, + 4122, + 16561, + 15636, + 31879, + 20431, + 23641, + 2404, + -6978, + 1578, + 9882, + 15805, + -7268, + -8295, + 24751, + -16216, + -29265, + 6953, + -21638, + -760, + 15418, + 4705, + 10795, + 8484, + 9889, + -6534, + -26313, + 27547, + 23684, + 3051, + 29529, + -27271, + -14230, + 19598, + 16194, + 24811, + 9440, + 25198, + -13487, + -14366, + -14562, + -32019, + -20376, + 6307, + 31016, + -5684, + -12805, + 6899, + -32462, + -30377, + 6821, + -17468, + -15733, + -16858, + -9126, + 3805, + -8481, + -9922, + -117, + 19734, + -16565, + 13779, + -6598, + -22387, + -24676, + -6234, + 20923, + -31234, + -16711, + -24038, + -1650, + 25237, + -26163, + 14190, + -31528, + 22845, + -133, + -11481, + 1716, + -18717, + 28610, + 27821, + -15811, + 5921, + -26800, + -20475, + 8153, + 31161, + -15123, + 21737, + -17815, + 14942, + -8443, + -21714, + -19606, + -8758, + -2079, + 26819, + -16295, + 17875, + 3373, + -30090, + -20194, + -12153, + -6294, + -11457, + 3804, + -18013, + 26677, + -20561, + -20336, + -8213, + -12333, + -15033, + -20595, + -31189, + 1283, + 19090, + 12396, + -29655, + -16352, + -3835, + -16440, + 8393, + -16612, + 1450, + -7001, + -9612, + 20154, + 17629, + -21591, + 17749, + -21899, + 21434, + 20021, + 29224, + -23647, + 185, + -191, + -16313, + 28093, + 17988, + -28836, + -3361, + -1386, + 28917, + 18232, + 16934, + 30349, + -6187, + -21134, + -7227, + 4033, + 14959, + -22372, + 27307, + 15990, + 19888, + -30699, + 17069, + 5906, + -4745, + 22618, + 14868, + -5606, + -1017, + 5562, + -27631, + 2481, + 5119, + 16043, + -27820, + -6079, + -5943, + 26107, + 25053, + 30820, + -759, + -16771, + -19788, + 31293, + -7162, + -27354, + -13649, + 155, + -17202, + -15240, + -1641, + -21481, + -12221, + -30597, + -20401, + -29140, + -19725, + -28582, + -25561, + -29107, + -2794, + -11570, + -30295, + -25985, + -7807, + 13084, + -15407, + 13442, + 202, + -2920, + 27874, + -5452, + 32741, + -30999, + 20572, + -24423, + -2415, + -20483, + -6413, + 876, + 11308, + -8414, + 15965, + -13322, + 5015, + 4706, + 18947, + 29163, + 11125, + -20537, + -4709, + -24051, + 9000, + 17059, + -1815, + -31878, + 27531, + 17528, + -27836, + -7625, + 7321, + -21740, + -5938, + -25584, + -5971, + -32148, + -1936, + 22922, + -12822, + 16481, + -6077, + -2273, + 22957, + 28305, + -24327, + -20094, + -4520, + 14459, + 972, + 5493, + 18475, + -13063, + 21889, + -679, + 1106, + 22522, + -2734, + -1198, + -2633, + 1317, + -4737, + -9640, + 13005, + 7024, + -17304, + -26394, + 25019, + 5444, + 3160, + -4999, + 6061, + -498, + -4481, + 1786, + -29772, + 32393, + -5596, + 25671, + 14186, + 2319, + 26050, + -6425, + -23896, + -4901, + -27879, + 32547, + -19513, + 2201, + 16490, + -25466, + 6285, + 994, + -29623, + 1833, + 11296, + -13319, + -20454, + 30177, + 15710, + -32632, + 25127, + 30476, + 20218, + 9461, + -29997, + -16963, + -23392, + -29425, + 18800, + 11219, + 26983, + -31389, + 4104, + 24180, + -29356, + -2413, + 12084, + -637, + -1825, + 14935, + -19850, + 21759, + 22121, + 31784, + 5356, + 6279, + -20646, + 28671, + 18718, + 22659, + -9645, + -22867, + -27881, + -21000, + -22657, + 12444, + 6057, + -18890, + -14043, + 31001, + -29905, + 17887, + -10259, + -12294, + -24960, + -1395, + -1157, + -8299, + 18921, + 3132, + 27654, + 21021, + 32136, + 2292, + 15440, + -11878, + -24477, + 23384, + 11933, + 17924, + -11417, + -8881, + -7822, + -5662, + 1593, + 16171, + 28351, + 2099, + 28841, + 24173, + 9810, + 9446, + 30137, + -20304, + 28473, + 17544, + -10134, + -3219, + 31770, + 31700, + 19544, + -31513, + 10438, + 31105, + -510, + -17349, + 22193, + 26059, + 7061, + -1689, + -17780, + 9807, + -13457, + 32393, + 21934, + -7312, + 17552, + -20754, + 32109, + -12839, + -898, + 6463, + 25300, + -31702, + 13125, + 30947, + -16251, + 11241, + -31266, + -5503, + -31661, + 5316, + -24120, + 10330, + -11867, + 21681, + 32191, + -17765, + 9369, + 17110, + 15606, + 3328, + -31637, + 27046, + 3030, + 7312, + 11952, + 4350, + 6489, + 5357, + -18712, + 10434, + 7297, + -31474, + -8823, + -2061, + 15652, + 26916, + 3038, + 7204, + -2310, + 19032, + -405, + 30578, + -1841, + 16450, + 12313, + -15007, + 11867, + 30545, + -12509, + -23742, + -26152, + -25285, + -30891, + -9211, + 11895, + -14880, + 31183, + -8641, + -23833, + -31766, + 26667, + 23204, + 5919, + 23271, + 14702, + 19800, + 8336, + 21746, + 5668, + -14442, + 27718, + 13952, + -19565, + -16659, + -9324, + -26704, + 16520, + 2974, + 28763, + -31368, + 6866, + 10416, + 3057, + 14025, + -8811, + 619, + 7600, + -25045, + -81, + -15465, + -11178, + -21075, + -12590, + 9501, + 31377, + 13410, + -9971, + -11188, + 10408, + 18138, + 5441, + -8825, + 18634, + 242, + -6605, + 13494, + -6136, + 6221, + -18334, + 28717, + 8741, + -8591, + -18127, + -24926, + 5281, + 16456, + -24039, + 31477, + -21823, + -28908, + 26881, + 17063, + 11654, + -3806, + -32517, + 24636, + -17608, + 3563, + 18138, + 19514, + 4358, + 26422, + -31235, + 23556, + -23839, + 3188, + 8263, + -21065, + -19511, + -16428, + 15497, + -28022, + 3681, + 7575, + -5352, + -31470, + -904, + 13316, + -19449, + 23769, + 9114, + -15688, + 11921, + -2610, + 27056, + 30059, + -17766, + -461, + -2870, + 23002, + -13091, + -30710, + -3534, + -1615, + 2580, + 3166, + 20755, + -9085, + 10071, + -5996, + -22927, + -17783, + 21295, + 5436, + -6437, + 21464, + -20568, + 5687, + -10828, + 16960, + 16510, + 28260, + 4799, + -13820, + -22612, + 28801, + 32681, + 13272, + 27252, + 9994, + -11780, + -31239, + -6851, + 25434, + 17553, + -1306, + 14951, + 5478, + 14976, + -1291, + 27260, + -32600, + -24062, + 16891, + -26644, + -30453, + -1786, + 30624, + -2646, + -1889, + 6830, + 5280, + -25530, + 6703, + 19001, + -5247, + 11836, + -20542, + 2402, + -27979, + -29783, + 28854, + -17897, + 4450, + -6557, + 2534, + -26972, + 16775, + -22731, + -11158, + -9611, + 14091, + 11472, + -1801, + 22504, + 31496, + 23097, + 25120, + -13196, + -2926, + -30323, + 8116, + 11505, + -509, + -28817, + 18990, + -18969, + -10958, + -4868, + 18581, + 14899, + -97, + -29526, + 5061, + 32196, + 16508, + 15451, + -6057, + 21308, + -1808, + -28786, + 7039, + -21809, + 19356, + -16322, + 21801, + -27471, + -20285, + 8652, + -32439, + 23847, + 8729, + 19337, + -2706, + -31427, + -7567, + 15163, + 22443, + 3373, + -3519, + 4776, + 20993, + -12421, + 15805, + 13629, + 31494, + -25541, + -14912, + -21798, + -9385, + -31338, + -20114, + 30086, + -19046, + 569, + -12252, + 2680, + 13519, + 12913, + 20305, + -8343, + 3182, + -12645, + -27965, + -17266, + 19136, + -17735, + -19427, + -11582, + 5715, + -28660, + 28449, + -12008, + 28814, + 11800, + -24586, + -9964, + -17098, + -6883, + 32513, + 31076, + 12619, + 25007, + 16428, + -30987, + -16570, + -13140, + -4056, + -8683, + 22422, + 208, + -16498, + -4531, + -32511, + -23287, + -12511, + -12433, + -31960, + -18573, + -3116, + 20104, + -3302, + 8548, + 24761, + 11213, + 20581, + 26263, + -4523, + -6473, + -10026, + -23572, + -9292, + 20864, + 25639, + -20082, + -26970, + -8308, + 27823, + 31067, + 17360, + -2758, + 3722, + -8347, + -17822, + 27735, + -4058, + 11843, + -32569, + -8252, + -1406, + -20351, + 8444, + 13985, + 26823, + 17660, + 32537, + -3677, + 28147, + 6109, + -5323, + -5793, + -30753, + 313, + -6707, + -21434, + 13641, + 4593, + -5632, + -22032, + -12483, + -6846, + 29034, + 30200, + 3101, + -15596, + -15094, + 19396, + -902, + 5036, + 29210, + 8068, + -15588, + -6043, + -20025, + 6912, + 9485, + -10708, + -30148, + 16681, + -1480, + -914, + 15105, + -24048, + -23765, + -6351, + 10038, + 4744, + 28175, + -24604, + -17364, + 6433, + -24708, + 30363, + -11092, + 17307, + 30540, + 29292, + -8397, + -6026, + -18586, + 29260, + 9928, + 8926, + -29773, + -13907, + -14884, + -13470, + -10786, + 19573, + -1714, + -25584, + -5443, + -8193, + -30559, + -15812, + 29924, + 16933, + -29354, + 18494, + 13350, + -12685, + 18233, + -22180, + -25246, + 12614, + -14097, + -8289, + 1329, + -31409, + -12292, + -17050, + 18571, + -15497, + 32723, + -13907, + -19051, + 8854, + 20432, + 8895, + 30182, + 19490, + 3454, + 9296, + -4091, + -15856, + -31574, + 17032, + -28902, + 12291, + 22389, + 18365, + -18574, + -6823, + 8805, + -20616, + 4663, + -18946, + 13686, + -7551, + -19608, + 5996, + -17428, + 26255, + 26197, + 16942, + 9765, + -13583, + 11899, + 25401, + 32683, + -13685, + 29907, + -4591, + 20788, + 21856, + 24716, + -10040, + 31265, + 6997, + 27902, + 14429, + 19369, + 9664, + 283, + -12522, + -7197, + 13710, + -18276, + -20190, + 32329, + -31009, + 4458, + -14973, + -30533, + -30667, + 1219, + 7916, + -485, + 477, + 7397, + 8486, + 27823, + -18173, + -9924, + 25537, + -32390, + 12502, + 562, + 5523, + 2371, + -22045, + 25743, + -21455, + -19475, + -25795, + -32092, + 12595, + 23011, + -26185, + -27878, + 5730, + -29166, + -17077, + -20903, + 30397, + 29820, + -27627, + 15004, + -9696, + -12844, + 17280, + 3392, + 613, + 17529, + -31720, + 31964, + -22389, + -13007, + -27026, + 16474, + 2249, + -25043, + -23958, + 30946, + -12701, + 14311, + 7795, + -319, + 22662, + -32752, + -29149, + -25287, + -23718, + -13398, + 16705, + 4169, + 25506, + -29676, + 19942, + 8073, + -20889, + -25380, + -13437, + -24469, + 17744, + 12443, + -26467, + 30174, + -16684, + -26036, + -2121, + 11099, + 32008, + -13011, + -5703, + 10300, + 32364, + -20320, + -1108, + -20071, + 3726, + 15847, + -19846, + 15702, + 5437, + 21086, + 11306, + 31330, + 27044, + 30063, + -20659, + -18308, + -18229, + -31678, + 23102, + 31472, + -26485, + -19490, + 27158, + 3055, + -12970, + 15460, + -25964, + -1160, + -1480, + 21531, + -22358, + -32206, + 26121, + -23327, + 15822, + 12144, + 7861, + -9521, + 21118, + -30738, + -23460, + 9866, + 21720, + -23795, + -8807, + -25378, + 14641, + 9294, + 25501, + -32184, + -13288, + -18761, + -16494, + -32718, + -2645, + 13093, + -15519, + 24309, + -31699, + 1867, + 13615, + -9399, + -13578, + -29782, + 29679, + -21606, + -23140, + -31663, + -10985, + -2504, + -9184, + -25727, + -16582, + -13986, + 13046, + 11030, + 23113, + -25104, + -24538, + -16495, + 20754, + -31778, + 8608, + -1388, + -20146, + 14492, + 21394, + 21898, + -30159, + -23096, + -5640, + -12332, + 7882, + -13263, + -5703, + -11651, + 14111, + -9480, + 5539, + -23748, + -2357, + -22046, + -171, + 5236, + 9434, + 29683, + 1945, + 253, + 25846, + 19547, + 19369, + -17846, + -32478, + 17807, + 2195, + -4161, + -20586, + -10912, + 18650, + -7489, + -1873, + -22273, + 1411, + -18507, + -28923, + 24204, + 19456, + 7597, + 4597, + -5759, + -4795, + 30603, + 24010, + 11561, + -17946, + 24722, + 21301, + 7988, + 29551, + 6020, + -2676, + 10560, + 9739, + 14063, + 26914, + 5968, + 11042, + -21400, + 6278, + 2492, + 17347, + 16957, + -19172, + -27089, + 3363, + 14138, + -1231, + -32119, + -28040, + 18692, + -30250, + -1046, + -24636, + -27551, + -21287, + -13492, + 9955, + -16134, + -8631, + 28960, + -22670, + -10181, + -29227, + 2839, + -4446, + -26937, + 18411, + 16727, + 13226, + 16686, + 15364, + -22699, + 9478, + 6706, + 5071, + 12121, + -13331, + 25719, + -7867, + -8897, + 16422, + -7745, + -20635, + -15099, + 5728, + 30778, + 30371, + 6197, + 2508, + -25005, + -32640, + 13677, + -8523, + 28560, + -26013, + -4131, + -23329, + 15893, + -15707, + -6417, + 27365, + -7596, + 13670, + -10387, + 31439, + 20281, + -1065, + -17265, + 21415, + -4257, + -28864, + -19174, + 31007, + -25626, + -16170, + -25369, + 30362, + -12129, + -24970, + -11437, + -13794, + 16369, + -28930, + -8049, + 10540, + -20444, + -14602, + 9688, + 30656, + 9650, + -28726, + 31705, + 3895, + -28377, + 22778, + 21644, + -32489, + -1838, + -21788, + -1860, + 10465, + 2452, + 28774, + -29482, + 29754, + 22402, + -11603, + -32263, + -19885, + -20766, + -3914, + 7944, + -3088, + -20244, + 4423, + 31954, + -11080, + 15660, + 27860, + -7946, + -17478, + -18745, + 22932, + -18461, + -2431, + -7941, + -4933, + 3461, + -24455, + 15495, + 2182, + -6371, + 15268, + 25098, + 29884, + 18369, + 32109, + -2116, + 1036, + 13165, + 16965, + 13964, + -29307, + 21521, + -14078, + -17109, + -11791, + -8531, + -12171, + 3143, + 26382, + 30068, + 29017, + 25144, + 15083, + -12794, + -17955, + -25167, + -20515, + 19397, + -26157, + -31219, + 10553, + 4473, + 31278, + -19575, + 29119, + 27062, + 26960, + -21790, + 15328, + -7874, + 20539, + -29196, + 15541, + 3562, + -22275, + -11569, + -4989, + -11971, + -26025, + 682, + 10572, + 30798, + 28789, + -27517, + 7116, + 12200, + 824, + 32215, + 2947, + -10973, + 4331, + 7018, + -12469, + -13945, + 24913, + 15446, + 18146, + -21493, + -647, + 15304, + 18031, + 5142, + -1459, + -20671, + 9251, + -5207, + -3506, + -8505, + -32055, + 8094, + -28371, + -728, + 16437, + 25810, + 3165, + 10704, + -1559, + 5628, + -13422, + -15529, + 17678, + 14201, + 19386, + 3176, + 32187, + 2998, + 10738, + 4659, + 29248, + 10925, + 28420, + -30329, + 3736, + 9414, + -225, + -28089, + 11563, + -30476, + 7823, + 19755, + -19897, + 11009, + 31573, + -12567, + 12559, + -28919, + 6268, + 32012, + 10868, + -13321, + 26684, + 446, + 4515, + -2198, + -21277, + -13932, + -21164, + 7105, + 7889, + 20604, + 18721, + -15983, + 4578, + 3373, + 28065, + 21217, + 5774, + 1582, + 11856, + -27364, + 30627, + 31958, + 30936, + 26937, + 26079, + 22684, + -756, + -2001, + -11192, + 30812, + -4651, + -29460, + 9186, + -17831, + 4172, + 20484, + -31477, + 26656, + -17874, + -19952, + -23873, + -23325, + -26322, + 26977, + -13572, + 30378, + -4137, + -22003, + 7307, + -10046, + 23616, + -8584, + -2981, + 15313, + -22993, + -8689, + 6925, + 16352, + -22256, + 26936, + -31734, + -1902, + 28187, + 10042, + 8477, + 9923, + -1463, + 4896, + 9262, + -10316, + 1436, + -5245, + -2646, + -2287, + -26848, + -17603, + -24628, + 21392, + 25278, + -30847, + 19093, + -11197, + -19462, + -4538, + -11440, + -24280, + -24937, + -1381, + -1851, + 12850, + 1618, + 18426, + -21496, + 5292, + 23006, + -31329, + 24962, + 13005, + -7111, + 25007, + 21609, + -30581, + -16550, + 11038, + -8902, + 9773, + 13151, + -10772, + 2872, + 535, + 28977, + -7380, + 27685, + 27285, + -13468, + 8564, + -28486, + 25747, + -2007, + 11620, + 7808, + -30333, + -31454, + -9808, + 26075, + -10350, + 2450, + -23155, + 16331, + -11755, + 27688, + -18900, + -13797, + -29936, + -21668, + 10597, + -12089, + -14117, + 7868, + 5223, + -8849, + 16724, + -13663, + 713, + -12277, + -23956, + -3507, + -7914, + 28959, + 8617, + -29221, + -24897, + -22862, + 12132, + 5629, + -13648, + -11061, + 2824, + -8463, + 28542, + -22975, + -5975, + 9738, + 12120, + -30051, + 1128, + -1124, + -10629, + -26791, + 26293, + 25979, + 7626, + -15184, + -25175, + 23580, + 18285, + 7365, + -21688, + 25431, + -24972, + -11731, + -4868, + 28092, + 11300, + -14095, + 26955, + 31975, + 21723, + 2829, + 2795, + -24282, + -21332, + -23157, + -26240, + 20519, + -1709, + 15181, + -1430, + -21861, + -25094, + 14061, + -1934, + -9880, + 5352, + 29582, + 8033, + 22486, + -28762, + -6396, + 30612, + 8146, + -26141, + 23534, + -26055, + 3901, + -7402, + -9390, + 5725, + 14835, + 21368, + -25530, + 14556, + 30181, + -4371, + -23837, + -4004, + 14433, + -22422, + 1477, + -6363, + 1073, + -15040, + -8411, + 5838, + -1810, + 29826, + -24271, + 19039, + 11529, + 19458, + 23864, + -12640, + -22754, + 21138, + 934, + -5392, + 32187, + 24113, + 4447, + 17581, + 16187, + 31660, + 13069, + -18917, + -19194, + -26040, + 10600, + -31356, + 483, + 21817, + -29563, + 3251, + -26775, + -16627, + -24894, + 30894, + 25368, + 10133, + -29935, + -6434, + -2043, + 17591, + -7988, + -7402, + -10244, + 19370, + -12838, + 9649, + 30218, + -15436, + -24219, + -15648, + -22519, + -6935, + -7349, + 8799, + -2906, + -11429, + -20975, + -12087, + 25699, + 4715, + 15671, + 11640, + -5432, + 14774, + -12632, + 10004, + 21838, + 19177, + -5007, + 5202, + -21448, + 17899, + 32741, + -2928, + -29422, + -556, + -3339, + 1794, + -26910, + 31039, + -23384, + 7060, + -2267, + 17245, + -15842, + -32310, + -16436, + -11819, + 30957, + 13364, + 23888, + -31887, + -15152, + 32708, + -3065, + -29768, + -24135, + 5028, + 7992, + -28140, + -17074, + 2047, + -25760, + -6689, + 7437, + 22569, + -8681, + 9169, + 18585, + 27476, + -21264, + -14395, + 26128, + 14336, + -19778, + 17930, + 18385, + 5881, + 18099, + -5331, + -27646, + -27425, + 10683, + 30659, + -4472, + -15327, + 8781, + -8356, + -26789, + 12166, + 3889, + -22524, + 20478, + 27284, + 30353, + 6939, + 14015, + 23540, + -28410, + 2228, + -20263, + 24573, + -4217, + 32364, + 26185, + 32624, + -29472, + 10420, + 13781, + 7853, + 16422, + 7160, + -31960, + 280, + -14628, + 26779, + -26397, + 23611, + 24301, + -1879, + 10762, + 2380, + -7577, + -31843, + 29576, + 14238, + -9402, + -29679, + -11368, + 249, + 7535, + 21091, + -29998, + -10722, + 6003, + 28560, + -26939, + -10261, + -1633, + -6648, + -25954, + -27325, + 28140, + -28407, + -9466, + -15409, + 9808, + 3865, + -28355, + -5639, + 6560, + -15154, + 5169, + 11393, + -14431, + -15128, + 9247, + 9855, + -7614, + 26087, + 10439, + 6860, + 12605, + 21964, + -4567, + 31056, + 9973, + 23890, + 17259, + 9133, + -4993, + 31296, + -11294, + 7852, + 30093, + -17820, + 22848, + -6270, + 15523, + 28777, + -12550, + 23327, + -16757, + 14673, + 8014, + -22209, + 21947, + -13630, + -7832, + 11750, + -2130, + 4903, + -28941, + 22137, + 27338, + 29667, + -15806, + -16570, + 24799, + -929, + -11553, + 17739, + -22114, + 15187, + -16496, + -13073, + 11003, + 32671, + 23036, + 30190, + -11854, + 30422, + 673, + -15546, + -9882, + -24854, + 1269, + -26931, + 13687, + 14822, + 31198, + -22006, + -9413, + 20976, + -3602, + 20535, + -17726, + -13362, + -16687, + -28044, + 30299, + -27440, + 29000, + 17712, + -21049, + 23138, + 6592, + 17981, + -15969, + -8922, + -19433, + 19194, + -5185, + -11004, + 6600, + 19658, + -27323, + -21275, + 4879, + 30219, + -14986, + 3347, + -19769, + 31016, + -3246, + 20305, + -10468, + 31886, + 22978, + 19981, + 791, + 2229, + -16464, + -24170, + 21871, + -32004, + -24898, + -31690, + -1597, + 19708, + 2303, + -9114, + 29056, + 26524, + 32511, + 4352, + 7153, + -19674, + -29289, + 29723, + 10527, + 7337, + 30778, + -11169, + -10539, + -16132, + 6374, + 9404, + -15557, + 27513, + 25523, + 19139, + 6066, + -27930, + -18815, + -2275, + -3784, + -23, + 25083, + -6867, + -5690, + -5844, + 7569, + -14550, + -16648, + -12726, + 23041, + 3254, + -16206, + -14363, + 20774, + 26912, + -1861, + 15259, + 26088, + -23412, + -17287, + 21708, + 28426, + -18025, + -14780, + 16643, + -17353, + 20883, + 32133, + 1787, + -28525, + -28947, + -16338, + -17647, + 14082, + 32461, + 3989, + 32327, + 23769, + -31236, + -2262, + -16340, + 4356, + -5660, + -2186, + -29968, + 8170, + 31959, + -13507, + -10624, + 6089, + -18826, + 13324, + 5051, + 1142, + 11135, + 4451, + -20266, + 24324, + 30967, + -17719, + -12968, + 12953, + -24243, + -19818, + 22189, + 3534, + -25620, + 30352, + -30803, + -28773, + -19204, + 10030, + -4503, + 3971, + 10334, + 7407, + -17231, + -4636, + -17812, + 18819, + -15455, + -18127, + -9568, + -18800, + 5408, + 14234, + 17902, + 7068, + 25935, + 15403, + 2250, + 491, + -2786, + -25182, + -17189, + 3969, + 28999, + -1811, + -1322, + -14310, + -26807, + -25413, + -31700, + -25269, + -22921, + -8655, + 29454, + -24496, + 15552, + 883, + -13263, + -7236, + 11155, + 4681, + -1254, + 17935, + 25920, + 25586, + 20850, + -31218, + -29184, + -3887, + -993, + 7023, + 8483, + -28251, + -22655, + 29936, + 17033, + -24953, + -11401, + 30889, + 1798, + -5823, + 8147, + -15642, + 2867, + 7387, + 13206, + 8843, + 5977, + -26286, + 18253, + -11075, + -12287, + -30043, + 23806, + -6984, + -32094, + -6512, + 4827, + 7895, + 19841, + -10587, + -29033, + 27452, + 137, + 20520, + 3423, + 5854, + 11132, + -28819, + 12476, + 20719, + 26618, + -28690, + -6518, + -15341, + -8257, + -26315, + 6070, + -29803, + 31414, + 3179, + -4199, + 22469, + -26201, + -2022, + -3948, + 2333, + -16690, + -29336, + 11852, + -1411, + 9927, + 23312, + -19363, + 25344, + 17285, + 28300, + 31867, + -24391, + -14534, + 1762, + -1892, + 24135, + -14060, + -27733, + 4781, + 26548, + -18356, + -6463, + 29271, + 31188, + -12093, + 21719, + 21433, + 22161, + 21336, + -24752, + -496, + 28461, + 31954, + -16683, + 30633, + 4929, + -18627, + 24494, + 16386, + -20340, + -32460, + -10186, + -8979, + -26954, + -28624, + -17496, + 4274, + -4464, + 31949, + -22183, + -28694, + -27390, + -5140, + 4139, + 22447, + 17426, + 6330, + 12709, + -30172, + 324, + -10989, + 25247, + 524, + 24605, + 2892, + -17124, + -20586, + -25768, + 16674, + -26489, + -20432, + 3843, + -24273, + 16176, + 5752, + 16252, + -25818, + -32585, + -6786, + -24292, + 10967, + -13315, + 22982, + 31268, + -27812, + 6361, + 4412, + -2514, + -30880, + -26725, + 11005, + -28625, + 255, + 8641, + -19485, + -29328, + -29504, + 6152, + 28287, + 19427, + 17836, + 26188, + -31446, + 27331, + -14649, + 31518, + -13463, + -20200, + -22214, + 4400, + -9133, + -17530, + -5602, + -18148, + -15914, + -8394, + 19806, + -11227, + -24543, + 21153, + -14415, + 15184, + -3157, + 5135, + -20545, + -27172, + -1304, + -736, + 21164, + -31964, + 236, + 31398, + 20428, + 32643, + -15865, + -9117, + 9907, + -7091, + -1168, + 6550, + -9911, + 24926, + -17448, + -18033, + -22047, + -2248, + 5818, + 17096, + 2319, + 28713, + 17647, + 20071, + -8974, + 9467, + -10231, + -7553, + -3414, + -29149, + -4596, + 22673, + 8820, + 19354, + 10929, + 16044, + -17697, + 25121, + 9801, + -20583, + 26049, + -12069, + 12841, + 21062, + -19480, + -25913, + -26564, + -12011, + 30033, + -5204, + -11884, + 8347, + -7577, + -24098, + -16289, + 25664, + -21118, + 7682, + 26638, + 5318, + -3836, + 29311, + -160, + 30554, + -18779, + -23860, + 17085, + 277, + -8864, + -22609, + -22714, + 30884, + -20073, + -13394, + -5284, + -20648, + -833, + -5458, + 19186, + 13527, + 3479, + 6035, + -27270, + 18262, + 2327, + 6819, + 2679, + -29424, + -28080, + 13168, + 24892, + 25920, + 25203, + -17662, + -32516, + -28710, + -4557, + 19685, + -22622, + 4173, + 18686, + -19130, + 25652, + 32156, + -10585, + -11038, + -19583, + -31713, + -16913, + 16900, + 22646, + -25904, + 8386, + -5170, + -20261, + 6877, + 30864, + 26389, + -30602, + -8905, + -8803, + 27772, + 18626, + -25532, + -13984, + 1686, + -11136, + 5124, + 15510, + -18965, + 23930, + -12223, + -5932, + 17360, + -26459, + -15155, + 19932, + -26149, + 23267, + 10434, + -20354, + -28300, + 16515, + -31861, + -15085, + 23789, + -32575, + -27584, + -25770, + 9839, + -18370, + -28529, + -27862, + 25331, + 30138, + -28925, + -31229, + 20783, + 32523, + 17643, + -22040, + 29411, + 21484, + 18135, + -1245, + -10417, + -24807, + -24211, + 21891, + -28959, + -24633, + 14433, + -15239, + 6930, + 10036, + -20577, + 25681, + 16055, + 21738, + -24297, + -29909, + -7935, + 29356, + -23121, + -17544, + -27141, + -29746, + -28192, + 2053, + 28531, + 30601, + -7522, + -6060, + -23986, + 944, + 15242, + -32164, + -26318, + -3675, + 3143, + 12690, + -25461, + 19611, + -14118, + 7314, + -13543, + 7714, + -25508, + 28862, + -12051, + 32594, + 9691, + -29190, + 18444, + 12482, + 32350, + -10739, + 29427, + 1093, + -1117, + -21686, + -25362, + 20355, + 19957, + -16069, + 8173, + -962, + -7188, + 5109, + 24735, + 10053, + 17202, + 15162, + 5563, + 26942, + 10881, + 2250, + 12148, + 28196, + 17345, + 5006, + 13527, + -28531, + 29765, + 20220, + 17016, + 19436, + -12309, + -13906, + -24504, + 2599, + 21971, + 6049, + 21806, + 11662, + 28713, + 23033, + -6319, + -7004, + 19855, + -12675, + 3242, + -21589, + -29060, + -20720, + 5696, + 6467, + 15158, + -13791, + 6767, + 13048, + -16413, + 528, + 15506, + 24900, + 24513, + -14158, + -191, + 19261, + -18956, + -32621, + -25598, + -10325, + -16735, + 31200, + 21969, + 6872, + 30221, + 8461, + -24684, + -16046, + -29805, + -27925, + -25783, + 2442, + -5249, + 23407, + 16125, + -8204, + 12649, + -13026, + 1522, + -9539, + 4990, + 5784, + -3401, + 20710, + 21026, + -3774, + -3332, + -8476, + 23882, + 18702, + 22509, + 24852, + 21858, + 18036, + 11642, + -16853, + 2772, + 20653, + -22781, + 18122, + 22903, + 7682, + 1976, + -981, + -32262, + 348, + 4002, + -26202, + -17161, + 7261, + 8469, + -18437, + 2392, + 3364, + 5935, + -17196, + -30873, + 23667, + 11279, + 23440, + -32308, + 14427, + 4121, + 11050, + -8888, + -15100, + -12424, + 11204, + -29412, + -31451, + 5750, + -30633, + -830, + -5194, + 3464, + 22298, + -14517, + 3029, + 30735, + -11386, + 26180, + -7546, + -17816, + 15052, + -584, + 20201, + -12173, + -1770, + -17053, + 6334, + -1933, + 30676, + 26435, + -3878, + -16053, + 16698, + -7156, + -13392, + -3441, + 16174, + -30323, + -10477, + 26337, + 32066, + -28685, + -10890, + -20228, + 25107, + 3637, + 26911, + -17584, + 22506, + 3029, + 12387, + 21367, + -23844, + -30053, + -11777, + 7412, + 28777, + 13906, + 5226, + 17378, + 4882, + -14831, + -281, + -6193, + -27769, + 22032, + -32738, + 6100, + 3055, + -1080, + 3110, + -9934, + 20046, + 31464, + 24608, + -23051, + -10433, + -3605, + 5098, + 18041, + 9892, + 10215, + 31297, + 4880, + -21235, + -5237, + 4058, + -9186, + 26693, + 12023, + 2071, + -2544, + -28374, + 8017, + -4882, + 20240, + 12450, + 5102, + 29336, + -2023, + 31405, + 21260, + 27210, + 15541, + 22815, + 26372, + -43, + -18272, + -32646, + -3153, + -26195, + 3891, + 28717, + -4456, + 18365, + 29947, + -31716, + -17896, + 21573, + -190, + 16982, + 26928, + 25565, + 18763, + -2930, + -15822, + 571, + 20918, + 218, + -23365, + 18108, + 18919, + 26618, + 12055, + -8654, + -22169, + 2425, + 9782, + 13745, + 9414, + 863, + 3494, + 15610, + -24518, + 18053, + 26742, + 915, + -3285, + -29283, + -10292, + 26309, + -10935, + -26353, + -19439, + 29141, + -26052, + -12563, + -20875, + 10559, + -4367, + 1643, + 29375, + 27995, + -27063, + 32475, + 4497, + 4625, + -165, + -24069, + -22805, + -17281, + 549, + 17378, + 32149, + 3350, + 30397, + -15359, + 1376, + 5956, + -24807, + 21336, + 31935, + 30016, + -2603, + -18750, + 6106, + -17829, + -24196, + 28825, + 21131, + -21512, + -15936, + -14002, + -27599, + -3465, + -8021, + 17469, + 26146, + -9544, + -10950, + 18089, + -3073, + -7201, + 14933, + 28764, + -13903, + -4224, + -1827, + 20195, + 28220, + 20980, + 10238, + -2236, + -18762, + 17090, + 6769, + 31393, + -7483, + 886, + 23061, + 586, + -10262, + -32210, + -9870, + -32168, + -5196, + 15063, + 17303, + 6568, + 23220, + 3743, + -13883, + -4982, + -16495, + 9102, + -4573, + 13585, + -1532, + 17278, + 10255, + -605, + -2326, + 11505, + -12061, + 8175, + -29246, + -19816, + 20237, + -12680, + 22645, + 14709, + -2202, + -27591, + 13372, + 1980, + -795, + 12610, + 26575, + -8916, + 10899, + 32208, + -2241, + -10182, + 29498, + 14360, + -14879, + 4230, + -30434, + -3017, + -29321, + -10866, + -23683, + -7034, + -13141, + -27811, + 10185, + -10215, + 20492, + -20810, + 18202, + 31113, + 16160, + -6946, + -11682, + 28623, + 21630, + 20082, + 21865, + -32115, + -27274, + 27265, + -17526, + 17544, + 19465, + -16982, + 19707, + -15171, + -32179, + -24888, + 6039, + -31519, + -19985, + -17876, + -32632, + 1502, + 23273, + -19262, + 13131, + -4045, + 31959, + -27645, + -17506, + 4314, + 14570, + -5303, + -12313, + -12825, + -32475, + 6409, + -19032, + -10265, + -25443, + -24772, + -30683, + 9487, + -799, + 19791, + -797, + 8958, + 18410, + 16566, + -11063, + 7944, + 5878, + 5116, + 29000, + -31794, + -21015, + -2435, + -4233, + 11161, + -27439, + -8026, + 17337, + 9577, + -16860, + -17958, + -26397, + -23450, + -18343, + -18058, + 30446, + 18392, + -27634, + 31784, + 31393, + 32474, + -15104, + 31111, + 5344, + -16222, + -11282, + 24784, + -19582, + 18050, + 26475, + 5956, + -7837, + -19562, + 6463, + 32354, + -12577, + 8476, + -21573, + -31934, + 11834, + 3328, + 8526, + -11414, + 8126, + 19011, + -370, + -9109, + -25222, + 3142, + -6360, + -2082, + 14631, + -768, + -5816, + -31896, + 30709, + -6757, + -3471, + -21460, + -22459, + -21634, + 17498, + -17097, + 22691, + -13047, + 10624, + 8663, + -4977, + 31485, + -20960, + 1994, + -8778, + -2511, + 9503, + -32652, + -13975, + -28871, + 23411, + 24928, + -19231, + -2157, + 15663, + 30406, + 11435, + 9406, + -29697, + -3593, + 23188, + 18669, + -29593, + 25423, + -4865, + -7792, + 16792, + -21, + 30225, + -32020, + -3080, + 9714, + -22535, + -12995, + 15222, + -6281, + 7546, + -5444, + 10597, + 12345, + -20786, + 15355, + 5559, + -13133, + -1124, + 24319, + 19976, + 8649, + -2788, + 30159, + -8563, + -5145, + -25556, + -27310, + 22362, + -21020, + -8183, + -13650, + -22760, + 29563, + 10343, + 27236, + 31383, + -14883, + -8623, + -27570, + -17901, + 14, + 1823, + 25543, + 10345, + -17708, + 27569, + 2782, + 13589, + -22176, + 21059, + -28037, + -15619, + -9815, + 3525, + 24300, + -16126, + -29824, + -31068, + -1985, + -22850, + 18777, + -259, + -13696, + -22766, + 29488, + 6279, + -4442, + 31066, + -18923, + -10316, + 31721, + -13504, + 15775, + -24268, + 19888, + -22213, + -14299, + 7362, + -16221, + -27338, + -26287, + 1926, + 8792, + 26882, + 8627, + -7825, + 3660, + 19540, + -21838, + 24479, + 4289, + -25547, + -27538, + 23973, + -3876, + -28812, + -32376, + -18819, + -12868, + -4954, + -14322, + -29188, + -31148, + -10744, + 14785, + 8596, + 9330, + -25950, + 30333, + -20667, + -13499, + 23058, + 22842, + -3903, + -27493, + -22960, + 15024, + 19269, + -20932, + 14956, + -1989, + -26621, + 5320, + -16655, + -12986, + -12409, + -955, + 19404, + 30463, + 43, + 8419, + -24757, + 24615, + -21443, + 7408, + -4306, + -27433, + -14483, + -30115, + -23892, + 430, + 3589, + -5288, + -21, + -28991, + -28686, + 32721, + -18648, + 6865, + -7301, + -2033, + 30587, + -6814, + -26972, + -12451, + -13316, + -24353, + 11902, + -30958, + 15789, + -3630, + -3510, + 12138, + -6632, + 24678, + 14886, + 22026, + 16099, + 30781, + -2298, + 16298, + 3016, + -5435, + -32757, + -24106, + -9206, + 4715, + 12340, + 29423, + 28937, + 32111, + 1914, + 11692, + 19649, + -3719, + 22708, + -16573, + 19086, + 30158, + -29339, + -18642, + -9884, + -30469, + 20657, + -8414, + -30270, + 6257, + 7562, + -24389, + -31204, + -2410, + 1104, + -30585, + -13739, + 17744, + 3716, + -23546, + -9838, + -1195, + 2342, + 9729, + 9966, + -27503, + -3093, + 27960, + -22520, + 6146, + -29070, + -25396, + 30557, + 4637, + 31010, + 31516, + 11107, + -5095, + 27666, + 18556, + -8829, + 18211, + -18429, + -8768, + 14451, + 11867, + -10547, + 16388, + 10943, + 31737, + -12215, + -30181, + 31382, + 9073, + 31672, + -5733, + 22814, + 6202, + 14943, + -8238, + 14743, + -362, + 32001, + 21108, + 7627, + -10237, + -4093, + -22336, + 11554, + -347, + -27292, + -2835, + -28301, + -29891, + 19109, + 12051, + 27846, + 13804, + -1690, + 26402, + -21843, + -29160, + 18990, + -20997, + 14015, + -29243, + 27524, + -26881, + 22790, + -32595, + 27260, + 5020, + -21825, + 11866, + 28126, + 12486, + 6880, + -15966, + 27871, + 15036, + 30696, + 20369, + -24187, + 9101, + 19901, + -28563, + 31831, + -9023, + -10291, + 1359, + -3228, + 12297, + -25731, + -21019, + 14115, + 17892, + 18492, + 7790, + -27265, + -15383, + -15342, + -31969, + 28627, + -23689, + 31894, + 8910, + 181, + 29409, + -6435, + 2320, + -30854, + -15001, + 32181, + -5275, + -7917, + -16348, + -11614, + -2258, + -11292, + 11118, + 14064, + -17620, + -14531, + -4248, + -29614, + -7728, + 898, + 16048, + 7588, + -1094, + -27044, + 13650, + -15727, + 12887, + 31350, + 30967, + 6272, + -798, + 25293, + -8243, + 10571, + 28576, + -13109, + 12881, + 32301, + 22432, + 15379, + -15076, + -29832, + -20275, + 11016, + 437, + -12897, + -19306, + -32448, + -3203, + -19655, + 12602, + -21651, + 1403, + 17143, +}; \ No newline at end of file diff --git a/sw/applications/trans_versasense/data_cpp/data.cpp b/sw/applications/trans_versasense/data_cpp/data.cpp new file mode 100644 index 00000000..4e7efc7a --- /dev/null +++ b/sw/applications/trans_versasense/data_cpp/data.cpp @@ -0,0 +1,104 @@ +#include "stdint-gcc.h" + +int32_t pos_embedding[1936] = {-1383, 964, -5839, -3654, -5069, 4064, -1907, -3855, -3658, -8857, 316, -1245, -3385, 1368, -2997, 13377, 7049, -1252, 2205, -219, -1524, -1316, 4386, 3600, 244, 6103, 1171, 2736, -222, -10278, 728, -1065, 297, 490, 2032, 4887, 4769, -2205, -2950, 3033, 1045, -84, -924, -9504, 871, 6262, -6855, -7938, 3453, -1851, 2541, 741, 10731, 1307, 2100, -4055, -1536, 5267, -2867, -2898, 1939, 25, 3560, 3399, -2064, 139, -1077, 4781, -8273, -6488, 403, 439, 1265, 8417, -106, -211, -4182, 3988, 6307, 104, 3200, -2645, 2750, 1677, 5047, 1988, -368, 784, 2920, 1074, -3975, 322, 2831, -2976, -1221, 4132, -8774, -3231, -3688, -1704, 6092, 4813, -2799, -686, 6206, 460, 10634, 6885, -3182, 5878, 920, -1219, 461, 2684, -2039, -7031, -5283, -6447, 5388, 490, 692, -1467, 28, -72, -766, 6259, 2560, 9225, -6087, -4768, -285, 933, -5913, 6449, 840, -2466, 1073, 2144, 2515, -2408, -7375, 7211, -1006, 1794, -9011, -5, 2908, 3234, 891, -2127, 2135, 1420, -1477, -820, 486, 2927, 2929, -6034, -4795, 6535, 981, 1943, -2114, 112, 1866, 3449, 114, 4353, -3075, 722, 8027, -2035, -2310, 1004, -1842, 766, -193, -4143, -468, -10321, -641, -4879, -58, -4413, -6004, 1211, 2336, -7301, -2585, -2329, -2014, -9458, -2424, -2518, -2531, -1006, -11344, -79, 579, -2929, -3784, -115, 1487, 338, -6021, 6798, -3510, -1279, -584, 4754, 4306, 6089, 5313, -7733, -5283, -1086, -4182, -10, 1619, 7458, 4068, 3304, -3974, -2321, -3290, 1892, 4567, 3601, 3791, 6113, -2470, -1036, 3080, 2368, -84, -365, -3006, 2347, -2591, -3977, -5959, 1168, 475, -7409, 4234, -3694, -3462, -2384, -1386, 6249, 2631, -3582, -2584, -3016, -4120, -3507, 6681, 9170, -512, 2289, 437, -7173, -4825, -7726, -3024, 3, -152, 2356, -125, -793, 1257, 11753, 841, 689, -5175, 525, -30, 2126, 399, 4477, -6030, -8924, 6246, 2527, 4445, 3728, 3477, -4071, -2582, 265, 2704, 4541, 4935, -4722, -661, 2167, -1137, 4947, 484, -7557, 2390, -604, 5174, -1680, -7771, 5151, -2544, 4752, -5385, -5953, 6899, 1995, -3538, -1964, -2005, -2899, -3806, -2889, -875, -6668, 2421, 7852, -4135, 3480, -2472, 1312, -372, -1592, -4654, 2972, 6772, -1416, 1550, 956, 858, -2759, 3268, -2765, -4870, -2471, -794, 679, -6719, -659, -159, -987, -247, -3032, -1714, 232, -1652, -3874, -919, -7050, -1827, -5084, -771, -4296, 3897, -3539, 3699, 7776, -7566, 1318, -3243, -2937, -3200, 4591, 5992, -2227, -1440, 112, 4378, 5404, -8718, 279, -1468, -10044, 2330, -4613, -4171, 344, 3440, 8488, -3674, 51, 1177, 2204, -716, -1666, -1899, -2359, 4873, -2739, 1130, 1508, 492, -4401, 7262, -369, -4263, -383, -833, 4751, -292, 2986, -3862, 5871, 1335, 280, 2117, -4211, -2144, -2733, 1554, 2206, -3493, -6634, 491, 3879, 2548, 1455, 4467, 1138, 2686, 3161, 16872, -5, 1346, -7243, -3078, 757, 76, 647, 3155, -7469, 5539, -4297, 2788, -2706, -824, 9735, 227, -164, 1836, -2907, -902, 3414, 9070, 448, -365, 3590, 1785, 3155, -4327, 1762, -192, 5660, -4526, -2613, -5665, 4197, -7165, 6556, -575, -2809, 9670, -1455, 3162, 5698, -2530, 6970, -1283, 2194, 3080, 5368, -2841, 1661, -3814, 734, 2233, 1298, -2275, 2558, -663, 337, -1486, 5124, -4945, -705, 2226, 3647, 3922, -1636, -3246, -1121, 5034, 6748, 1672, -7449, 4429, 7100, -2473, 7379, -947, 96, 883, -571, 5956, 2154, -4363, -5640, 483, 4663, 4230, -1531, 4186, 8916, 2290, 2685, -3635, -2636, -10375, -359, -763, 3008, 1932, -3181, 4049, -2683, -1566, 218, 1499, -4272, 8315, -5687, -3909, -10107, -2763, 49, 4835, -3659, 5096, 2762, 1572, -1215, -1102, 1778, -304, -3823, -7065, -3514, 842, 1533, 3766, 7351, 2417, -4943, 3180, -1947, 1386, -76, 3659, -998, -3692, 1470, -4130, -4735, -920, -3834, -142, -1852, 1681, 1398, -1615, -395, -5920, 1152, 2867, -8946, -1574, -4741, 2136, 2927, -3393, 1605, 1767, 624, -161, -9984, -9672, -1855, -1974, 2349, -7959, 8138, 405, 3118, -5967, -400, -2649, 1157, 5872, 3428, 3737, -1628, 1432, 319, -1607, 1023, -2374, 3938, 1798, -3673, 1438, 3258, -753, -1809, 5015, 4319, -5591, 8596, 1887, -4751, -4368, 2422, -1443, -134, -788, -21, -2064, 1963, -10361, -3825, -3084, 10016, 2496, 7829, -1263, 10488, -6681, -2736, -3243, -2854, -5366, 4789, 3023, 5010, -1605, 818, 3508, 4327, 1620, 5211, 1638, -1602, -6396, -1011, -4742, -2177, -769, -7017, -5381, 6374, -434, 5859, -1740, -3273, -1150, -272, -4498, -1411, 3119, -2595, -3171, 2275, 4851, -2317, 9149, -5869, -470, -6065, -5685, -3181, -3491, 2468, 1930, -3545, -4076, 4313, -2524, -3857, -800, -2219, 3414, 477, -968, -2669, -3937, 7518, -421, -2605, -230, -2500, 1462, -3009, 1442, 3465, -1343, -4661, 9064, -1488, 2426, 4510, 5118, -6978, -8568, -3232, -803, 1624, -3680, -2136, -3299, -5547, -4491, -6242, 1845, 5622, -710, 3020, 5498, -3608, 1922, 1233, -851, 623, 1153, 2165, -5331, 5668, -4262, 6967, 5474, -86, 3346, -2149, 1429, 1485, 4000, 2078, 1875, 5851, -3715, 4393, 1652, 1144, 5240, 728, 1415, -864, 3615, 1811, 3974, -92, 4902, -8521, -4400, -627, 675, -3433, -3801, -2291, 3850, -6717, 0, -3766, -5335, -5421, -3057, 3809, -5880, 1665, 378, 4789, 3382, -5372, 4777, -1177, 329, -4118, -724, -6930, -1720, -1816, 436, 7447, -533, 4725, -2361, -1161, -3119, 4255, 8766, -1131, 22, 1182, 3252, 4970, -3812, -5076, 971, 7043, -2200, -4456, 3164, 707, -6497, -5324, -218, 9741, -6039, -8101, 6605, 6995, 2298, -10900, -9604, 14083, -2495, 1095, 6337, 1553, 636, 2874, -2222, -2863, 3775, 4896, 8593, -1049, -760, 1582, -720, 54, -1277, -493, -2055, -4673, 2164, -5176, -8766, 3986, 538, 1980, 3639, -5559, 2434, -6174, -2313, -933, 2087, 5489, 1018, -3362, 2350, 8964, 3414, -2611, 5676, -6438, -441, 4548, -3126, 454, 4305, -6046, -1526, 8867, -2809, -3597, 4805, 2720, 5284, -3439, -4167, -1973, -6302, -2436, 693, 2798, -3159, -3125, -1843, -9666, -2709, 6212, -2448, -2614, 9744, 7912, -2084, 6710, -519, -3216, -2973, 339, -1878, 5720, 1510, 3180, 2514, -516, -6191, 8129, -1176, 2473, -1280, -5885, 1885, 2574, 3670, -3595, 5584, 2165, -6515, 5554, -23, 9021, -1911, -881, 465, -2769, -1336, 4516, 781, 1487, 826, -239, 3450, -4089, 312, 4057, -1917, -4253, 2178, 3868, 2352, -96, 3171, 1883, -4054, 7586, -11703, -329, 4425, -6981, 5046, 3208, -4103, -112, -1376, 4341, -2181, -2487, -892, -589, 271, 3055, -346, -137, 741, 2066, 6128, 2551, -4083, -6775, -1311, -4114, 1237, 3796, -616, 3564, 352, -4720, -765, -1952, -3557, 4101, -1777, 4274, 887, 295, 951, -3343, -646, 5854, 4607, -1567, -3609, -4403, 6565, -7334, 109, 1943, 2694, -3486, 2950, -515, 2109, -4209, -3735, -7865, 324, -7742, 8839, 2293, -3205, -2644, 295, 1396, 861, -2310, -6156, -1106, 802, 3566, 486, -1692, 5686, 1646, -1695, 769, 2990, 5526, -2497, -3342, -533, -3074, -5231, 5510, 936, 4001, -324, 4587, 10056, 4353, 1130, -421, 674, -6294, 1722, 2558, 4, -2187, 6847, 2125, -6077, 2690, -719, 2561, 4669, -2845, 5001, 2939, -7002, 2354, 742, 2684, -799, -4004, -5759, 2889, -4625, -6648, 1569, 735, -553, 6963, 2696, 2508, -8183, 5055, -1470, 4075, -5437, -7301, 1969, 2904, 134, -4279, 6075, -1524, 355, -3125, 10803, 1276, -1346, 3689, 794, 742, 1634, 3327, 2022, -3683, 3090, 7283, 1861, -4229, 7780, 3606, -238, -4646, 5503, -2117, -1909, 1908, 6075, -6532, -1732, 5579, 3041, -3126, 4348, 4055, 692, -753, -4153, -1657, 2367, 6320, -235, -9175, -3784, -615, 2829, 2843, -2256, -1470, -5818, -6843, -196, -151, 1301, 2017, -4884, -203, 9959, -4350, 462, 3320, 4236, 1534, -4264, 699, 1578, 3318, 4140, 4835, 1014, -440, 8480, 1889, -706, -1703, 7888, -4966, 2139, 283, -2559, -1652, -1207, 999, 5663, 3620, -9024, 1337, -331, 4966, 1586, -5856, 6659, 4837, -3025, 1162, 204, -2217, -2655, -3015, 3457, -415, -10613, 4144, 4124, -2337, 4753, -2210, 6730, 5633, -4650, 6065, 1790, 4687, 1802, 5954, 3767, 1889, 3277, 1196, -3345, -50, -582, -976, 1391, 4427, -2472, 10868, 1423, -4134, 1687, 616, -5144, 3766, 7614, -3716, -2228, 8223, -4436, -49, 4142, 6244, 2533, 1008, 3650, 3387, 2705, 228, -1405, 1866, -2994, 6573, 6639, 2522, 892, -6028, -7974, -1034, -2814, -5937, -1890, -5217, -7161, -11827, 1492, -355, 5499, -1280, 6, -5161, -3852, 2855, -353, -2529, 999, -5875, 540, 690, 2957, 2639, -5606, 3065, -912, -8014, -2138, 11664, -2999, 3785, -3479, -443, 5357, 3674, 6408, 7416, -2708, -3874, 1420, -8040, 123, -5179, -1861, -68, 2909, 2095, 398, 3777, 2569, 10516, -3511, -10, -4321, -4616, 1167, -8103, 3211, -8598, -1242, -3099, 521, 3416, -4465, 1157, -5550, -219, -164, 3618, 795, -2932, -2417, -3135, 3185, -4072, -229, -5254, -9385, -2973, 7064, 1924, 6405, -2424, 2374, 3312, 1684, 46, 2385, 788, 6867, 1158, 1092, -1723, -3498, 1711, 106, -958, -2024, -2930, 8257, 7091, -1887, -2165, -1379, -4090, 3170, -1518, -1696, -461, -95, -1146, -3041, -486, -1225, 2840, 2454, -535, 4306, 4365, 1027, -7522, 6268, -3390, 1507, -4160, 3606, 4296, 844, 6481, 5322, 845, 1058, -2461, -770, 5714, -1310, 2248, -2115, 8250, -729, -3421, 4037, -2574, -1750, 5356, -6683, -4439, -2797, -5302, -5110, 398, -3725, -2597, 2897, -2513, 1987, -416, -2444, 6916, 349, -1110, -4154, -4623, 53, 3865, -993, -8210, -651, 1280, -4261, -4337, -7605, 2074, -413, -2321, 837, -2882, -3536, 8512, -3100, -751, -1466, -1352, -3046, 833, -538, -378, -5832, -2967, 3981, -608, -274, 39, 1911, -811, 6059, 1289, 6744, -3978, -2821, 2813, 3185, 1641, 4621, -5059, 5139, -4251, 7102, 2009, 4088, 13455, 3158, 2023, 845, -2790, -6827, -7613, 2793, 362, -2562, 7864, -4174, 2552, 30, -2629, -8870, 6764, 478, -2226, 1224, 1911, 2986, -6839, 750, -4442, 43, -4298, 2500, 1377, 4444, -1386, -903, 5267, 3429, 3397, -128, -314, -1175, 557, -1281, 3879, -6261, -2378, -4673, -4546, -9533, -434, -1251, 4867, -478, 6570, 1638, -6200, 2489, 1825, -3280, 2302, 529, 808, -1079, -932, -7550, 308, 5501, -2490, -1262, -503, 2525, 5519, -1882, -1477, -86, -9414, -1875, 3709, 9345, 696, -580, -4114, 3784, -1469, -2308, -7687, 7726, -5358, 2180, 198, -4601, 6568, -846, -743, 602, 3768, -8464, -2305, 1505, 3102, -1882, 1882, 2084, -5905, 10953, 1874, 4433, -4212, 9862, 845, -1182, 2011, -3850, -3034, 1874, 4546, 4268, 481, 5882, 2178, -797, 636, 195, -2742, -6500, -172, 6924, -2807, 1402, 1809, 4814, -6196, -4112, -489, 4513, -788, -1141, -1066, 6471, -366, 3895, -7083, -2192, -936, -4171, -3834, -2427, 60, -2176, 1471, -7225, 1075, -4612, 2404, 923, -6865, 3175, -2994, 3791, 3837, 4112, -2837, -2407, -1790, -135, -2982, 756, 2905, -3754, 3142, 4695, -4753, 3775, -3668, 2878, 58, 1401, -6116, -3778, -835, -1237, 4451, -486, -5649, -2662, -1359, 2480, 764, 6716, 1520, -3423, 3565, 6528, -5598, -2577, -5838, 3809, 4273, -5191, -6151, 856, -3401, 1877, 181, -3391, 6397, 521, 2696, -729, 2447, -2357, 71, 393, -4286, -3678, -3804, 202, 2483, -1495, -567, -351, -5601, 4345, 727, 2205, -446, -1712, 4245, -555, 2319, -1229, -4391, 1198, 3343, 6352, -3041, 3530, 2555, -2491, 3267, 5197, 7241, -5418, -196, -6974, 4126, -6772, -1952, -1254, 4365, -856, -7301, 2039, -3488, -1819, -5129, -8144, 1046, 9050, -2252, 3089, 1116, -3244, 3722, -6500, -2682, 6899, 999, -6970, 4962, 1942, -155, 205, 1988, 2059, -7244, 8643, -2080, -11003, -3558, 6445, 4859, 5428, 2292, 67, -996, 6220, 3174, -276, -9762, -1324, 1566, 3728, -677, 3279, -2624, 2045, 2832, -6470, 1538, -1687, -3169, -2649, -7823, -1285, 4916, 1915, 8069, -955, 3076, 5247, 6909, -1496, 6131, -4841, 8632, 495, -755, -1478, -1746, -5553, 6564, -2779, -3504, 639, -5842, 1703, 1079, 2635, 2315, 1960, -9291, 531, -1071, -1838, -2918, -399, 2394, -8068, -720, 31, -1530, -1179, 65, -4719, 5641, -1551, 5440, -2457, 6268, -5913, 3913, -6646, 188, -6885, 2757, -3601, 3880, -3979, -1443, 1375, -2572, -1632, 2321, 5070, -2172, 731, 481, 1710, -5181, 8850, -931, -3332, 3141, -1414, -2568, -3533, 728, -1683, 206, 907, 5058, 2523, -158, -1465, 1969, -5960, -1139, -7207, 991, 2704, -8160, -2148, -4477, 4621, -5992, 2561, -2189, 5366, 2138, 2017, -2125, -844, -6806, 3850, 3987, 2856, 2990, -6767, -2315, -721, -205, -672, -2231, -617, 4268, 4988, -1234, -2918, 5121, 4651, -2067, 629, 655, 2305, 490, 990, 598, 4562, 3404, 3903, -5174, 7998, -8369, -7167, -1066, 5288, -2154, 5324, -1541, -620, -3439, -4516, 6180, -8012, -1858, 1175, -2675, -2835, -3610, -7460, 10522, 3595, -4464, 1727, 2719, -2989, -2425, 2312, 1535, -2001, -4046, 3982, -3749, -1536, 2144, -68, 284, 1545, -2459, -6920, -2683, 3627, -1356, -188, 2040, 3459, 33, 6605, -1418, 5162, 2430, -1030, 3098, }; +int32_t cls_token[16] = {1579, -8312, -1543, 5366, -5637, -2872, -787, 5773, -2441, 5560, -195, -1606, -1795, -6080, 1247, 219, }; +int32_t to_patch_embedding_layer_norm1_weight[400] = {4133, 4145, 3757, 3886, 3959, 4157, 3936, 3941, 4085, 3902, 4116, 4193, 4064, 4147, 4075, 4082, 4012, 4029, 4116, 3960, 4010, 3944, 4027, 4086, 3719, 3979, 4088, 4002, 4053, 3642, 3885, 3881, 4070, 3980, 3861, 4118, 3899, 4082, 4035, 3967, 3992, 3993, 3975, 3960, 4044, 4026, 3964, 4104, 4141, 4203, 4335, 3950, 4260, 4394, 4250, 4142, 4046, 4265, 4355, 4162, 4026, 3882, 4271, 4276, 4216, 3970, 3983, 3922, 4114, 3907, 4105, 3924, 3986, 4032, 4059, 4209, 3959, 4090, 4356, 3975, 4122, 3986, 4208, 4332, 3799, 4094, 4119, 4180, 3884, 4095, 4133, 4137, 3932, 4225, 4114, 4111, 4032, 3875, 4169, 4247, 4040, 4016, 3875, 4170, 3953, 4202, 3919, 4007, 4077, 4003, 4305, 3842, 4027, 4056, 4142, 4325, 4154, 4097, 3973, 4237, 4355, 4214, 3867, 4227, 3953, 4371, 4289, 3955, 4040, 4009, 4349, 4107, 4081, 3992, 4066, 4087, 4143, 3998, 4267, 4175, 4172, 4379, 4104, 3944, 4301, 4158, 4079, 4004, 4215, 3903, 3995, 4349, 4114, 4170, 4144, 3863, 4146, 4371, 4222, 4055, 3768, 4143, 4415, 4017, 3835, 3989, 4230, 4134, 3999, 4111, 4047, 4056, 4048, 3949, 4234, 3900, 4057, 3988, 4199, 4106, 4042, 3996, 4172, 3837, 4434, 3947, 4334, 4126, 3984, 4289, 4126, 4312, 4083, 4108, 4197, 4109, 4378, 4341, 4190, 4026, 4163, 4292, 4392, 4021, 4034, 4101, 4160, 4278, 4369, 3999, 3936, 4324, 4048, 4162, 4044, 3925, 4438, 3960, 4227, 3866, 4002, 4304, 4042, 4232, 4019, 4004, 4256, 4206, 4115, 4146, 4098, 4208, 4202, 4077, 4139, 3819, 4197, 4112, 4082, 4096, 4123, 4186, 4242, 3938, 3958, 3854, 4033, 3863, 4125, 3973, 4049, 4200, 4256, 4168, 3976, 4109, 3891, 4326, 3963, 4095, 3989, 4003, 3975, 4060, 3839, 4141, 4158, 3988, 4027, 3942, 4172, 3919, 3789, 4114, 3849, 4044, 4072, 4189, 4027, 3988, 4126, 4168, 4252, 3919, 4101, 4337, 4444, 4213, 4265, 4097, 4241, 4310, 4159, 3999, 3960, 4176, 4212, 4061, 4151, 4209, 3865, 4062, 4143, 4250, 4240, 3844, 3949, 4000, 4163, 3924, 4031, 4240, 3901, 4130, 4081, 3980, 4027, 4228, 4179, 4012, 4004, 4040, 4259, 3998, 4100, 4036, 4036, 4179, 3997, 4013, 3999, 4269, 3892, 4237, 3970, 4001, 4144, 3987, 4286, 4028, 3876, 4163, 4167, 4266, 4089, 3886, 3843, 4096, 4022, 4139, 3774, 3958, 4185, 3968, 3734, 3858, 3944, 3847, 3897, 4437, 3900, 4063, 4092, 4064, 4184, 4036, 3915, 4042, 4022, 4221, 4130, 3789, 4108, 4215, 4273, 3804, 3838, 3820, 4098, 4179, 3893, 4165, 3959, 4077, 4066, 3950, 4334, 4204, 3915, 3767, 4120, 4262, 4153, 3926, 4022, 3947, 4106, 4003, 3883, 3666, }; +int32_t to_patch_embedding_layer_norm1_bias[400] = {-181, -150, -345, -240, -156, -149, -228, -310, -125, -193, -139, -95, -144, -184, -125, -137, -225, -204, -98, -170, -13, -175, -169, -127, -341, -168, -8, -182, -261, -380, -104, -230, -161, -206, -269, -152, -96, -4, -246, -37, -138, -182, -33, -64, 9, -50, -201, 66, 108, 50, 51, -30, 117, 88, 32, 40, 5, 73, 92, 7, -126, -116, 87, 86, 78, -51, -135, 5, 48, -15, -3, -54, -132, 77, -78, 44, -12, -133, -116, -105, 60, -27, -108, -166, -119, -68, -6, -132, -102, -68, 29, 94, -23, 58, -51, -35, -61, -28, 4, -114, -232, 9, -89, 23, -29, 46, -44, -122, 78, -82, 53, -36, 47, 62, -86, 50, 35, 90, 5, -70, 69, 105, 3, 113, -38, 42, -69, 2, 131, -44, 53, -59, -18, -111, -97, -18, -91, 9, -97, -53, -121, -103, -6, 42, -30, -55, -39, -11, 121, 8, -32, -27, 20, -58, 54, -76, -13, -34, -80, 83, -37, -57, -59, -4, 42, 97, -90, -39, 19, -59, 44, -68, 115, 80, -65, 13, 54, -46, 109, -21, -47, 11, -23, 136, 56, -34, -30, -40, -29, 47, -71, -89, -16, 112, -95, -71, -114, -57, 79, -70, -81, -76, -106, -18, -53, -66, -53, -52, -116, -127, -50, -104, -70, -36, 41, -56, -110, 104, -62, 132, -40, -73, -54, -24, -21, 37, -40, -59, -3, -65, -28, -87, -69, -37, 83, 40, -38, -35, -61, 59, -59, -72, -92, 118, -4, 36, 29, 133, -64, 135, 9, -33, 69, -76, 74, -28, 52, 68, 108, 95, -77, 156, 191, 69, 130, -58, 88, 141, -12, 89, -39, 256, 158, -6, 61, -118, 75, -15, -21, 99, -115, 205, -21, 50, 121, -88, 110, -40, -19, -30, -57, 110, 140, 152, -37, -56, 123, 128, 151, 87, 53, 95, -35, 89, 98, 91, 154, 25, 83, 6, 145, 102, 99, 186, -14, 51, 39, 103, 124, 140, 114, 130, 81, 120, 157, 129, 160, 152, 169, 144, 111, 104, 51, 11, 43, 156, 74, 234, 13, 193, 130, -45, 159, -14, 102, 205, 125, 137, 43, 169, 306, 142, 87, 182, 136, 216, 166, 198, 142, 88, 233, 165, 195, 49, 192, 104, 37, 200, 17, 189, 36, 134, 192, 224, 76, 272, 170, 180, 146, 85, 130, 69, 189, 142, 163, 142, 111, 130, 251, 186, -30, 128, 149, 264, 144, 72, 200, 147, 131, 210, }; +int32_t to_patch_embedding_linear_weight[6400] = {-173, 179, -273, -237, 19, 323, 124, -8, -4, -42, 39, -70, -3, -226, 215, -34, -120, 218, -189, -275, 21, -86, 42, 92, 209, -149, 196, 180, 164, -87, 49, 54, -54, 66, -83, 102, 32, 118, 140, -60, -96, -33, -165, -97, -141, -163, 34, 208, -214, 108, 22, -126, 151, -120, -195, 88, 21, 35, 157, -22, -12, -191, 82, 89, 183, 252, 17, -22, 206, -29, 22, 57, 40, -82, -285, 98, 46, 52, -16, 165, -125, 181, -157, -105, -129, 329, -88, 193, 218, -133, -27, 85, 294, -133, -127, -40, 114, 68, 18, -162, -98, 166, -117, -18, 74, 59, 92, -40, 56, -200, 122, -163, 199, -62, -49, 106, -136, 184, 136, -64, 52, -164, -255, 115, -58, 162, 245, -40, 34, -19, -127, -342, -173, 220, -44, 171, 124, -198, -144, -127, 27, 219, 7, -176, 314, -18, -43, 69, 75, 138, -23, 118, 163, -35, 69, 100, 208, 65, 126, 149, 100, 210, -48, -106, 9, 41, 43, -3, 43, -297, -324, -96, -51, 47, 126, 5, 116, 360, -299, -36, -50, 148, -155, 242, 64, -130, 69, -48, 210, -165, 54, 142, -59, 101, -64, -264, 80, -13, -111, 223, -145, -159, 47, -87, 141, 196, 57, -183, -11, 300, -304, -50, -157, 122, 34, -19, -83, -170, 70, -41, 12, -44, -60, -122, -85, 69, 38, -107, -205, -58, -122, 100, 155, -300, -175, -11, 326, 120, 131, -174, 152, 104, -46, -72, 122, -19, -161, 138, 61, -76, -343, -88, 176, -103, 148, -188, -129, 282, 65, -34, -61, 91, 111, 38, 114, -19, 95, 50, 206, -33, -113, 81, 323, -45, -34, -164, -122, 253, 186, 102, -5, -244, 88, 181, -58, 195, -30, -18, 155, 107, -108, -267, 72, -23, 125, 65, -204, -254, -238, 96, 159, 228, 71, 13, 223, 3, -192, -176, -65, -151, -115, 213, 122, 8, -130, 66, 144, 208, 63, -140, 193, -90, 104, -189, -59, -146, -39, -185, 172, 138, -264, -217, -88, 39, 39, 42, -61, 194, 123, -57, 156, 0, -172, -132, -221, -197, -165, 80, 110, -95, 50, 52, 244, 41, -58, -107, 145, 203, 212, 204, 112, -91, 45, -22, -26, -51, 34, -152, -205, 239, -88, -122, 203, -85, -69, -43, -190, -202, -248, 7, 189, 103, 137, 133, -63, 42, -115, 68, 129, 184, -192, 176, -118, 86, -1, 90, 210, 37, -40, 135, -45, -164, -175, 70, 283, 232, -219, -81, 66, -85, -171, 40, -67, 310, 164, -66, 32, -64, -64, -52, 172, -128, -229, -156, -273, 208, -107, -196, -176, 355, 43, -19, 48, 155, 74, -145, -28, -83, -128, 15, -101, -37, -54, 103, 278, 194, 154, -161, -342, 8, -187, -34, -149, 175, -73, -153, -1, -303, -197, -180, -29, -75, 9, -157, -75, 157, -66, -130, 112, -68, -26, 10, 117, 138, -104, -189, -81, 38, 138, 149, -52, -30, 110, -93, 153, -62, -116, 189, -67, -67, -94, -94, 17, 45, 122, -158, 177, 166, 101, 105, 52, 140, -115, -7, -184, -85, -249, 98, 19, 233, -100, 198, -165, 6, -73, -183, -133, 196, -146, 231, 42, -266, 70, -104, 50, -80, 281, -171, -331, -9, 168, -98, 177, 201, -234, -103, 79, -96, 112, -38, 170, 36, -86, 201, -132, 137, -9, 34, 105, 75, -234, -69, -34, -193, 78, -236, 205, -169, 96, -48, -191, 55, -261, -52, -100, -15, -261, 24, -68, -304, -137, -296, 240, -164, 185, -182, -111, -93, 149, -194, 264, -46, -231, -16, 168, 36, -202, -47, -68, -22, 69, -129, -157, -118, 251, 40, 0, 89, -44, 117, -149, -10, -241, 89, -199, -124, -32, 146, -178, 157, 64, -285, 11, 38, -75, -46, -83, -75, 159, 32, -141, 42, 196, -159, 43, -164, -143, -6, 23, -149, -263, -75, -223, -44, 15, -220, 94, 86, -157, 104, -62, 74, -249, -46, -210, 4, -253, 126, 104, 32, 60, 64, 266, -67, -87, 149, -87, 222, 24, 66, -40, 215, -20, 143, -77, 1, -33, 165, -16, -109, 49, -142, -4, -9, 154, 163, 9, -198, -177, 40, -27, 102, 171, -158, 128, 122, 203, -8, -163, -18, -20, -102, 190, 137, 37, -143, -97, 71, 0, 49, -174, -31, -124, -165, 106, 93, 123, -117, 44, -250, -306, 72, -93, 193, -33, -62, -94, 208, 88, 271, -74, -127, 237, -187, -189, -22, 68, 219, -145, 54, 153, 185, -118, -157, 52, -40, -169, 107, -163, 117, 10, 109, -303, -33, 179, 35, 63, 2, 41, -167, -6, 46, -175, -94, 144, 195, 60, -2, -157, 185, -250, -49, -170, -204, -103, -32, -46, 163, -96, -232, -64, 206, 273, -166, -227, -127, -12, -14, -248, -98, -145, 440, -51, 48, 212, -426, 140, 275, 314, -190, -270, -342, -139, 95, -110, 298, -114, -93, 16, 253, 150, -110, 390, 282, 180, -162, 121, 90, -170, 72, -83, 150, -353, -119, -5, 341, -89, 100, 61, 58, 1, 58, -203, -85, -28, 174, -126, -44, -31, -18, 12, 170, -88, -354, 326, 19, -1, -223, -124, -175, -270, 43, -54, 73, -345, 90, 19, 171, -40, -251, 332, 245, 259, -14, -85, -418, -299, 125, -324, 123, -124, 475, 153, 349, 205, -154, 290, 37, 45, -230, -81, -178, -215, 335, 40, 230, -357, 310, -126, 269, 58, -334, 131, 101, 254, -141, -235, 7, -240, 30, 35, -22, -147, 183, -16, 22, -100, -138, 154, -4, -158, 46, 154, -301, -147, -85, 155, -97, -275, 68, 84, 160, 151, -319, 105, 230, -179, -41, -105, -23, -445, 463, -29, -24, -255, 53, -256, 349, -126, -481, 341, 224, 239, -322, -302, -98, -143, 170, -279, 78, -369, 124, 106, 379, -65, -202, 393, 148, -31, 25, -257, -260, -217, 80, 35, 119, 1, 191, -242, 87, 342, 19, -120, -80, 241, -29, -76, -314, 1, -125, -219, 76, -167, 65, 3, 281, 24, -17, 22, -131, 295, -81, 80, -116, -56, -51, 148, -231, 80, 232, 28, 74, -219, -231, 383, 165, 165, -122, -124, 66, -237, 357, 1, 318, -54, 391, -175, 353, -331, -405, 247, 40, -27, -38, 86, -286, -118, 306, -253, 235, -210, 153, -77, 158, -217, -229, 177, 345, 145, 66, 29, -100, 30, 78, -155, 115, -13, 193, -136, 250, -6, -98, -10, -90, 112, 25, -141, -107, 71, -27, -156, 101, -137, 5, 65, 45, 23, -100, -15, -24, 151, 161, 80, -155, 250, -107, 40, -82, 127, 201, -110, 26, -257, 22, 154, -109, -13, -108, 95, -81, 14, -46, -278, 45, -130, 132, 94, 205, -57, -65, -42, 120, 273, 174, -8, -103, -170, 201, -323, 24, -205, 274, 49, 151, 39, -38, 43, 139, -92, -239, -203, 160, -41, -99, -9, -33, 89, 311, 125, 136, 31, -311, 64, 44, 168, -124, -45, 97, 155, 131, 33, 90, 211, 229, 155, 51, -27, 61, -229, -16, -166, 13, 256, -85, -69, -208, -125, 31, -174, 134, 266, 51, -182, 87, 98, -266, -75, 140, -39, -21, -70, 52, -230, -159, -113, -47, -17, -114, -101, -52, 216, -70, 88, -134, -306, -153, -56, 27, -294, 195, -114, -30, 17, 167, -14, 154, -62, -187, -246, 256, -154, 116, 76, 62, -133, -302, 237, 212, -25, 55, -65, -402, -140, 271, -144, -256, -117, -135, -160, 174, -27, -30, 193, 6, -118, 217, -177, -111, -148, 80, -6, 259, 249, -190, 226, -5, -133, -272, 180, 218, -133, -196, 200, 226, -8, -30, -163, 76, 271, 195, 28, -218, 44, 77, 153, 74, 48, -100, -69, 501, -408, -465, 15, 212, -400, 14, 196, -245, -36, 65, 7, 236, 267, -91, 228, 215, -49, -24, -133, 233, -121, -180, 13, -63, -266, -171, 79, -208, 52, 177, -430, -222, 51, 204, -65, -151, -83, -96, -124, -120, -276, 54, 20, -160, 204, 288, -350, -181, 14, 63, 4, 167, 200, -82, -104, 226, 167, 58, -47, 82, 47, -166, -114, 227, -217, -307, -342, 222, 88, 57, -26, -61, -30, -53, -52, -155, -46, -169, -263, 489, -78, -174, -117, 383, -120, 50, 350, -197, 5, -40, 220, 18, 138, -250, 479, 66, 91, 121, 70, -38, -25, -30, -128, -78, 73, -39, 63, -19, 154, -88, -254, -90, 150, 1, 76, 259, -271, -83, -86, -10, -77, 83, 26, -49, 158, 224, 26, -21, 24, 17, 192, 107, 280, -337, 91, 375, -147, -155, -224, -165, -25, -18, -204, 212, -191, -97, -198, 85, 42, 76, 17, -292, -19, -2, 200, -220, -81, -147, -412, -87, -45, -146, -28, 143, -206, -67, -32, -85, 79, -225, -57, 76, -78, -115, 60, 154, -159, 163, 197, 167, 25, -344, 67, -24, -36, 85, -298, 166, -209, 124, 37, -245, 222, 171, 153, 54, -143, -48, -53, -84, -41, 16, -193, 74, 24, 219, -78, -13, 146, -6, 208, -32, 214, -190, 217, 162, -32, -131, -246, -68, -163, 222, -219, 165, 113, 174, -198, -126, -21, -27, 59, 124, -165, -183, 62, -260, 93, -123, -66, -362, 349, 167, -79, -255, -165, 16, -249, 33, 64, 43, -281, 10, -295, -2, 114, 271, -300, 76, 156, 292, -146, 162, 49, -186, -123, -62, 163, 73, 95, 59, 235, -148, 48, -140, 236, 97, -293, -12, 213, -230, -266, 156, 192, 276, 206, 31, -149, 29, -84, -82, -16, 49, 87, 135, 290, -181, -121, 63, 111, -260, -131, 101, 26, 74, 57, 72, -166, -134, 33, 39, -144, 0, 29, -231, -93, 87, 282, -4, -401, 100, 293, 217, 146, -40, -168, -61, -19, 226, 46, -57, 102, 333, -213, 181, -159, 239, -167, -189, 68, 373, -270, 205, 287, -244, 29, -164, 117, -246, 236, -212, 191, 133, -31, -190, -13, 239, -67, 220, 9, -57, -230, 85, 21, 102, 158, 50, 21, 90, 140, 147, 179, 182, -65, -162, 18, 153, -103, 49, 35, -204, -94, 168, -32, -55, -69, 91, 159, -65, 94, -53, 120, -176, 102, -170, -28, 133, 1, 56, -181, -32, 260, -114, 138, -22, -412, 55, -106, -82, -166, -37, -256, 34, -222, 168, -79, -8, -54, -122, 176, 189, -242, -8, 38, 64, -132, 33, 120, -83, -122, 99, -103, -323, 256, 184, 90, -276, 51, -46, -42, 340, -145, -1, -42, -80, 58, 125, -53, 105, 32, 89, 142, -101, 132, 125, 208, 193, 137, 56, -238, -12, -205, 13, -169, -97, -30, 51, -269, 97, -141, -90, 231, -266, 191, -113, 86, -21, -72, -97, 99, -110, 180, -232, 98, 177, -208, -84, -86, -46, -61, 148, -49, 320, -32, 227, -334, 98, 88, 35, 38, 46, -360, -176, 73, -91, -121, -146, 9, 22, 75, 256, -42, -285, 346, 241, 81, -69, -89, -5, -386, 219, 218, -77, -171, 98, -226, 204, 97, -33, -112, 152, 152, 34, 66, 119, -155, -199, 43, 130, -137, -44, -96, 82, -288, -136, 180, 67, 58, 240, -51, -101, 89, 76, -165, -18, 136, 163, 147, 207, -95, -269, 174, 176, -33, 7, -154, 34, 31, 75, -125, -131, 170, 93, -5, 4, -255, -115, 28, -94, -301, 115, -40, 222, 64, -253, 17, -361, 297, -179, 34, -122, -332, -498, 281, 146, 81, -278, -275, -391, -361, 191, 223, -101, -58, 252, -214, 112, 303, -63, 104, 77, 83, -6, 261, 69, -349, 239, 101, 17, -165, -216, -167, -42, 214, -158, 43, -76, 196, -192, -289, -128, -184, 198, -114, 185, -211, 175, 193, -2, 42, 261, -80, -165, 59, -100, -91, -102, -10, 96, -207, -315, -50, 122, 73, 68, 25, 283, 43, 53, -269, 315, -203, 78, 271, -252, 254, -237, 276, -168, -30, -139, 91, -524, 353, 229, 57, -60, -142, -120, -139, 219, -241, 245, -152, 68, 18, 123, -110, -320, 281, 100, 94, -293, 137, 79, -199, 243, -207, 369, -253, 46, -218, -91, -102, -115, -243, -60, 208, 198, -75, 57, 190, 198, -45, -201, -9, -41, 151, 98, -128, -259, 201, -44, 148, -109, 113, -111, 66, 174, -262, 215, -231, 232, -61, 174, -299, 182, -137, -75, 8, 164, 17, 133, -65, -230, -86, -109, 27, -206, 6, 41, 46, -317, 478, 341, 236, -222, 232, -178, -364, 430, -294, 250, -320, -201, -10, 23, 124, 308, 72, -229, -361, 21, 459, 86, -109, -87, 81, 121, -40, -47, -2, -456, 50, 43, -181, 18, 150, -103, -124, 83, -96, 62, 188, -96, 53, -207, -160, -115, -81, -9, 272, -59, -43, 28, -176, 19, 103, 20, -150, -92, -52, 106, -100, 250, 2, -92, -80, -190, -220, -14, 237, -166, -25, -163, 175, -183, 239, -42, -23, 4, 439, -583, 218, 202, 110, -80, 443, -129, -302, 113, 154, -186, -221, -109, 8, -34, 41, 227, -91, -144, -77, 59, 159, 269, -36, 78, 290, -352, 152, -351, -88, -82, 261, -65, -69, 73, -90, 173, 403, 191, 157, -55, -106, -167, -20, -267, 102, -97, -53, 276, -127, -53, -155, 159, -99, -71, 90, -168, 150, -247, -75, 80, -235, -60, -57, 24, 17, -178, 96, 71, 187, 101, -97, 66, 192, -313, 211, -257, -349, -104, 251, 110, 38, 214, 378, -169, 154, 88, 233, 114, 34, -13, 48, -105, -173, -229, 30, 70, -119, -12, -167, 240, 139, -86, 214, -45, 185, -14, 325, -8, 240, -272, 183, 148, -4, 8, -260, -30, 75, -113, 3, -142, 35, -289, 2, -163, -137, 0, -361, 155, 6, -194, -268, 359, 145, -108, 299, -257, 134, -44, 273, -23, -218, -84, 36, 385, -189, -269, -151, -45, 27, 114, 125, 148, 136, -150, 91, -251, -310, 188, -184, 115, -332, -88, -139, 89, 200, 274, 301, 15, 14, -16, 122, 6, -111, -399, -73, 356, -280, -103, -216, 119, -56, 158, 364, -175, 40, -239, 365, -225, 284, -136, 81, 12, 67, 9, 22, 157, -28, 240, 102, 167, -27, -290, 261, -138, 166, -265, -110, 114, 7, 252, -175, -84, 137, -44, -19, 41, -277, 21, 82, 209, 21, -140, -231, 378, -54, -203, -112, 365, 29, 221, 160, -320, 52, 3, 364, 115, -10, -74, -104, 274, -264, -235, -243, 104, -48, 357, 191, -34, -95, 98, -56, -223, -225, -131, -64, 69, -95, -44, -1, -155, -94, 0, 318, -249, -150, -84, -4, 4, -182, 109, -28, 162, 27, 105, -15, -50, -9, 50, 83, -335, 142, -197, 150, 11, -19, -5, 65, -415, 220, 342, 294, -116, 23, -71, -63, 87, -228, -17, 80, -44, -340, 242, 32, 191, 211, 127, -160, -160, 37, -133, 135, 88, 79, -59, -25, -39, -188, -78, -119, 0, 16, -201, -128, -22, 51, 205, 203, -251, 55, -68, 139, -213, 57, -194, 89, 143, -474, -147, -11, 215, -80, 10, 483, -289, -150, -102, 402, -64, 199, 92, 89, 74, -32, -19, -82, -39, 30, 315, 160, -190, 46, -287, -29, -401, -124, -363, 145, 379, -251, -80, -198, 123, 64, 200, 139, -314, 131, -168, 274, -175, -17, -56, 74, -237, 399, -4, 77, -194, -69, -225, -175, 220, 88, -68, -72, 189, -183, 57, -90, 104, 45, 77, 23, -30, 34, 245, 32, -195, -78, 9, -6, 126, -20, -48, 129, -4, -185, -77, -126, 106, 235, 104, 426, 31, 20, -284, -41, 172, -66, -98, 84, 373, -314, -14, -207, 90, -31, 359, 299, -430, -48, -280, 430, -229, 122, -257, 16, 360, -122, -226, -7, 332, 2, -61, 393, -208, 48, -257, -4, 70, -135, -152, 30, -188, -33, 162, 90, 24, 89, -147, 123, 221, -219, 105, -231, 67, -141, 68, -151, -95, 78, 152, -117, 5, 78, -312, 72, -86, 77, 102, 46, -7, 93, 209, -19, 123, -276, 218, 63, 184, -116, 13, 302, -95, -30, -169, 141, 71, -137, -58, 291, 356, -220, -165, -56, 144, 298, 156, 262, -250, -88, 33, 444, -421, 74, -504, 153, 59, -3, -20, -179, 58, -266, -160, 256, -217, -209, 60, -26, 64, 190, 11, -116, -36, 5, 18, 100, -111, -164, -197, 136, -5, 32, 19, -13, 28, -95, 201, -166, -177, -132, 273, 45, 60, 41, -72, -60, 64, -261, 165, 44, 86, 152, 205, 64, 371, -359, 1, 235, 109, 66, 54, 102, -121, 97, 71, 202, 22, -268, -198, 94, 123, -164, -106, -264, 18, 307, -108, -5, -209, 149, 279, -20, -235, 312, -34, -47, -77, 0, -136, -78, -73, 262, 133, 90, -191, 18, 17, 210, 84, 227, 0, -135, 138, -106, -124, -26, -125, 0, 123, 135, 60, 185, -230, 295, -524, -214, -158, -99, -137, 201, 84, -204, -170, 151, -142, -41, 94, -43, 135, -121, 274, -3, -114, 36, -194, -89, 140, 161, 3, 147, 38, 239, -238, -30, 91, 114, -197, 126, -186, -83, -100, 128, 198, 10, -154, 57, 48, -232, 155, -210, 348, 37, -83, -130, -85, 3, 15, -13, -307, -138, -28, 48, -28, 58, -26, 26, 177, -27, 61, -100, 91, -81, 434, -211, -47, -101, 42, -92, -68, -6, -324, 270, -162, 296, -227, -208, -115, 26, -97, 159, -142, -114, 60, 108, 189, 158, 109, -63, -39, -165, -80, -222, -97, -22, -105, 108, 83, 76, -43, 116, -48, 177, 195, 237, -73, -95, -361, 154, -186, 185, 38, -54, -88, 10, -34, 191, 225, 53, 14, -63, 183, 41, -166, -26, -154, 45, -300, 267, 65, 196, -13, -244, -54, 60, 221, 162, 1, -144, 358, 5, 242, -241, -56, 207, -172, 68, 226, -44, 24, -149, -174, 293, -346, 218, -298, -73, 68, 197, -24, -127, -47, -77, 65, 35, -150, 139, -218, -55, -267, -30, -107, 182, 166, 103, 121, -172, 160, -121, 90, 19, -86, 153, 210, -88, -188, 51, -277, -198, -20, 107, 23, -304, -154, -166, -35, -32, 35, 266, -42, -243, -176, 223, -282, -49, -382, 12, -90, 60, 228, 25, -65, 61, 113, -115, 55, -10, 54, -67, -20, -88, 110, 46, -367, 416, 400, -84, -2, 160, -258, -325, 301, -10, -93, -286, 42, -435, 8, -1, -31, 6, 241, 89, -97, 122, 81, 21, -3, -101, -77, -297, -110, 68, -92, -46, 317, -59, -308, -152, 72, 253, 332, 231, -370, 15, 13, 413, -143, -71, -169, -17, 15, -217, 82, -70, -75, 277, -13, -59, 68, 165, -80, 260, -12, 172, -332, -350, 72, -90, -24, -114, 169, 108, 121, 190, 57, -26, -83, 4, 24, -317, -132, -5, -94, 456, 278, 57, -108, 35, -43, -176, 158, 372, -98, -339, -270, -190, -220, 220, 290, -266, -206, -64, -41, -141, -117, -18, -327, 96, -117, 106, -8, 17, 100, -139, 105, -455, -354, -210, 78, 110, 56, 276, -312, 151, -78, 387, -14, -96, -422, -140, 133, -50, 140, -109, -171, -22, 50, 131, 101, -48, 310, -29, 42, 45, -193, -239, -20, 274, -98, 229, 16, 142, -100, 43, 119, 165, 73, -83, 11, -413, 54, 63, 211, -158, 59, -197, 63, 243, 88, -8, -228, 401, -273, 69, -212, -14, -167, 128, 104, -152, -365, -98, 67, -117, 348, 124, -12, -7, -115, 193, -123, 6, -279, -49, 371, -328, -340, -126, -28, 241, 98, 101, -317, 155, -108, 176, -166, 36, -494, 69, 296, -345, -282, 43, 121, 113, 189, 402, -338, -142, -49, 193, -279, 156, -75, -254, -118, 218, 151, 28, -95, 72, -197, -206, 52, 172, 363, -26, -153, 25, -257, 82, 293, -72, 128, -227, -135, 87, 50, -101, -80, 328, -90, 131, 54, 92, -325, 197, 148, -329, -25, 24, -202, 37, 94, 128, -156, -284, 189, 109, -138, -28, -158, 195, 389, -373, -160, -15, 81, 223, 308, 210, -183, 184, 31, 121, -50, -15, -287, 40, 178, -461, -201, -28, 359, 280, 143, 228, -155, -85, 10, 138, -297, 140, -414, 76, 121, 100, 132, -226, 53, 187, 41, -145, -142, 149, 124, 178, -328, -72, -207, 254, 117, -233, -1, -44, -131, 0, 91, 139, -113, 82, -35, 239, -93, 22, -172, 317, 107, 120, 29, -158, -129, -363, 110, 238, 111, 86, -159, 13, -36, 112, 67, 137, 271, -191, -127, -218, -76, 131, -7, 28, -30, -10, 143, -40, -217, -167, -362, -212, -35, -280, -203, 9, 221, 117, -52, 348, -83, -29, -257, 110, -330, 154, -171, -99, 372, -146, -231, -457, 200, 320, 151, 235, -105, 369, 82, 301, -280, 91, -390, -142, 178, 65, -95, 5, 228, 101, 162, 45, 51, 64, -12, 202, 1, -138, -181, 271, -188, -175, 102, 25, 92, -81, 132, -26, -217, 108, -95, 96, -115, -100, -88, -336, 221, -319, -213, -399, 80, 195, 165, 154, 110, 179, 17, 312, -418, -147, -353, 73, 104, -59, -130, -276, 197, 170, -42, 151, 65, 319, 122, 107, -27, 244, -101, -101, 165, -72, -248, -237, -230, 185, 263, 225, -225, 107, 175, 122, 234, -21, -6, -112, -116, 186, 66, -152, -70, -73, 59, -40, 77, -26, -228, -141, 197, -200, 22, 41, -17, -158, 162, -35, 75, 268, 198, 96, 15, 10, 19, 77, -156, 0, -277, -40, 486, -302, -359, -201, 349, 285, 301, 149, -104, 132, -256, 260, -178, -151, -475, -6, 14, -81, 39, -108, -159, 175, -164, 180, 242, -90, -30, 51, -215, 146, 225, 136, 305, -45, -111, -49, 18, 297, 122, 156, -326, -197, -3, 9, 112, 153, -334, 221, -196, -97, 19, -54, -199, -92, 28, -179, -105, -139, 230, -6, 115, -143, -102, -91, 214, -42, 27, -321, -40, 145, 39, -141, 114, -57, -287, 173, 67, -16, -158, -106, 130, -286, -393, -191, 211, 196, 80, 368, -338, -79, -141, 334, 200, 79, -316, -64, 140, -64, 39, -114, 115, 17, -46, 186, -127, 37, 16, -3, -230, 5, 38, 384, 210, -360, -255, 155, 28, 149, 289, 69, -72, -25, -139, 53, -119, 69, -83, 180, 164, -118, -107, -100, -55, 27, 150, 260, 75, 29, -262, -100, -193, -31, 12, 25, 5, 179, 100, 23, -3, 35, 160, 25, 192, 102, -65, -182, -234, 50, -113, 131, -24, -270, -163, 4, 88, 155, 223, 160, -171, 95, -280, 391, -28, -301, -172, -64, 275, -202, -35, -20, 356, -15, -35, 167, -57, 112, -197, 280, -325, -75, -119, 196, 110, -320, -116, 93, 130, -43, 67, 171, -38, 84, 61, 99, 22, 56, -33, -264, 362, -250, -96, 32, 139, -72, 209, 81, -76, 176, -76, 43, -213, -136, -201, -173, 126, -21, -62, -246, -105, 381, 339, 94, -111, 243, 153, 13, -227, -181, 159, 253, 200, -48, 0, -202, -34, 181, 196, 92, -296, 161, -256, 269, -277, 171, -192, 23, 301, -61, -135, -137, 291, 358, 303, 67, -183, 118, -82, 50, -280, -6, -223, 40, 206, -160, -160, -159, 85, 233, -9, 155, -173, 96, 165, 57, -149, 117, -173, 107, -33, 202, 202, 223, 95, 338, 73, -246, 264, 113, -75, -230, -321, -208, 168, 94, 74, -58, 105, -49, 220, 209, -154, 124, 15, 184, 50, -29, 0, -85, -54, -192, -93, -369, -252, -199, 30, 15, 9, -55, -229, 88, 334, 188, -104, 101, 53, 39, 215, -312, -153, -124, 8, 216, 67, 72, -13, 113, -342, 285, -68, 150, -222, -1, 209, 0, -58, -194, 187, 81, -62, 269, -203, 161, -5, 150, 77, 127, -46, 268, 90, -54, -4, -31, -275, 253, 69, -284, 149, -111, 81, -262, -212, -277, -111, 57, 242, -188, 55, -217, -20, 432, 154, 21, 69, 207, 94, 166, 78, -71, -181, 45, 64, -198, -40, -179, 71, 71, 28, 56, -262, 158, 358, -158, -103, 87, -199, -118, 284, -308, -174, 178, 155, 165, 13, 157, -88, 150, -139, 121, -132, 50, -151, -59, 4, 151, -14, -199, -174, 185, 94, -71, 24, 29, 117, 56, 354, -244, -10, 229, -70, -94, -13, 351, 202, -13, -128, 57, -77, -121, 6, 21, -139, 142, -159, 111, 73, 24, -14, -54, 78, 95, -85, 4, -64, -97, 97, -202, 87, 123, 190, -37, -172, 18, 51, -176, -335, 147, 66, 130, -1, 227, 143, -11, -2, 101, -187, 146, -114, 87, 39, -118, -8, 209, -37, 90, 231, 82, 73, -115, -153, 63, -179, -111, 83, -130, -356, 146, 181, 22, 119, 142, -15, 169, -225, -42, 233, 59, -204, 183, 59, -15, 36, 162, -141, 55, -29, -260, 33, -13, 144, -190, -27, -21, 120, 287, -74, 152, -86, 78, -42, 76, 138, -22, 8, 153, 300, -6, -67, 126, -88, 98, 312, -59, -312, -30, 25, 233, -18, 79, -263, -144, -15, 154, 203, 75, -291, 202, -62, 48, 117, 19, -274, 174, -188, -268, 298, 277, 209, -63, -146, -319, -5, -188, 126, -221, -115, 158, -140, 43, 85, -32, -154, 3, 213, 105, 308, 256, -119, 171, -236, -139, -171, 117, -19, -34, -168, 2, -23, -100, -250, -166, 41, -158, -119, -101, 82, -64, -256, -25, -53, 151, 224, -231, -47, 26, 66, 188, 58, 129, 122, -23, 91, -25, -150, -230, 208, 141, -34, 28, -50, 8, 117, 139, -77, 205, -213, 199, -122, 142, 344, -213, -477, 44, -117, -107, 351, 311, 112, -84, 274, -355, 80, 112, -149, -61, -85, 1, -15, -141, 38, 292, -82, -4, 155, 88, 132, -10, -35, -31, -260, 206, 62, 186, -90, 25, 79, -196, 204, -62, 173, -12, 208, -158, -21, -172, 49, 3, -109, -85, 230, -51, 28, 245, -202, 70, -349, 122, -185, -26, -309, -254, -66, -133, 221, 29, -225, -109, -199, 101, 93, 145, 26, -64, -161, -135, 181, -16, -49, 286, 177, 106, -210, 40, -241, 8, 169, -32, 25, -150, -5, 46, -62, 271, -250, 130, 143, 204, 43, 81, -49, -102, -63, -26, 247, -58, 200, 0, -27, 46, 30, 202, 169, -111, -164, 57, -53, -227, -117, -74, -93, -78, 77, 50, 201, -191, 68, -183, -165, -48, 124, 98, 306, 16, -177, 89, -181, -102, -204, 290, -186, -46, -93, 176, 314, 167, -110, -32, -194, 89, 145, 314, -154, -78, 292, -96, 93, -127, -128, 133, -108, -139, -44, 238, 53, -127, 126, 329, 116, 112, -173, -233, -124, 133, -1, -199, -60, 204, -55, 170, 168, -62, -45, 149, 129, 229, -75, -126, -154, 233, -119, 41, 44, 183, -121, 195, 149, 30, 61, -137, -69, 6, -264, 129, -98, 207, 172, -14, -390, -341, 199, 155, -71, -174, -121, 149, -37, 189, -1, -42, -122, -18, -104, 89, 103, -142, -89, 173, 146, -169, 136, -102, -165, 30, -106, -49, -108, -216, -81, 109, 6, -142, 203, 285, -38, -31, -183, 133, -3, -155, -158, -21, -24, 143, -108, -291, -209, -15, 87, 261, 215, 86, -236, -149, -38, -169, 1, -142, -216, 184, -155, -94, -141, 49, 77, 136, 66, 84, 159, -90, 176, -48, 0, -5, -87, 5, 104, -71, -335, -131, -157, -118, -98, 228, -164, 207, -202, -3, -5, 72, -256, -40, 22, 99, -172, -9, -471, 278, -10, -7, 19, 138, -242, -47, -152, -217, -51, -124, 422, -351, -51, -336, 146, 16, -11, 21, -222, 19, -233, -8, -186, 57, -116, 224, 16, -151, -174, -6, 155, -101, 320, 73, -71, -186, 145, 213, -120, 186, -234, 31, -97, -10, 225, -79, -265, 166, -133, -207, -18, -20, 122, -18, -246, 138, 90, 38, -4, -256, 27, -292, -134, -31, 45, 209, -245, 132, -374, 254, -310, -108, -247, 48, -23, 143, 116, -200, -177, 352, 144, 1, 262, 166, 50, -192, -14, -309, 47, -68, 289, -185, -5, -199, 240, 175, 231, 73, -280, 101, -464, 322, -410, 190, -127, 28, -21, 9, -92, 8, 117, -134, -10, 72, -263, -322, 74, -177, -134, 80, -199, 59, -81, 112, 49, 34, -46, -68, -201, -39, 337, -11, -98, -237, -155, 69, 89, -333, 338, 88, -36, -408, -90, -64, 91, 263, -41, 193, -123, -31, -338, -70, -49, 33, -535, 211, 351, 102, -468, 46, -232, -58, 603, 355, 330, -287, 270, -402, 232, 174, 223, -348, 66, 52, 5, 361, 139, 85, -128, 197, -240, -9, -195, 0, -370, 352, 178, -91, 6, 290, 156, -213, 184, 445, -149, -508, -32, 142, -21, -9, -368, 46, 240, 89, -16, -96, 169, -51, 242, -148, -153, 149, 49, 97, -294, 101, 18, -200, 216, -23, 155, -278, -197, 75, 155, -115, -147, 199, 143, 138, -185, 154, -178, 64, -236, 351, 223, -163, -474, 286, 61, -160, 161, -24, 413, -508, -102, -111, 255, -81, -263, 122, 266, -42, -109, 147, -176, -156, 309, -23, 41, -10, 118, -188, -95, 160, -249, -205, -155, 148, -239, -47, 169, 143, 114, -217, 144, -132, 6, 101, 105, 104, 90, 51, -93, 30, -100, -111, -83, 223, -182, 112, 26, -18, -151, -174, -44, -168, 214, 59, 35, -195, -253, 186, 13, 13, 8, 452, 348, 23, -141, -89, -192, -102, -455, 283, -57, -122, -35, -16, -157, -178, 15, -39, 224, -405, 78, -185, 215, 258, -256, -224, -13, 28, 123, 41, 25, 81, 139, 139, -1, -148, -34, 141, 211, 276, -139, 20, 78, 126, 46, -196, -120, 39, -114, -157, 46, -228, 355, 35, 148, 162, -305, 13, 362, -86, -141, 23, 23, -188, 286, -84, 209, -302, 171, -331, 135, -128, 81, 99, 146, -104, -97, 35, 108, 91, -62, 118, 133, 108, -69, 107, -57, 144, -371, 115, 132, -3, 19, 211, -46, -164, -57, -56, 9, 73, 97, -138, -29, 61, 169, -32, -116, -29, 106, 96, -12, 111, -295, -52, 102, 106, 110, -3, -126, -163, -326, 365, 11, -57, -93, 141, -364, -193, 297, -18, 1, -147, 23, -113, 142, 58, -274, 343, 86, 115, -225, 6, -86, -73, 158, 129, 8, -191, 179, -54, 316, -83, -168, -165, -108, -90, -24, 2, 212, -131, -37, 183, -117, 140, 89, 241, 143, 98, -50, 34, 215, -61, -267, 317, -118, -151, -110, -68, 201, -60, -254, 94, -87, -113, 126, -12, 113, -126, -55, -44, 79, 175, 92, 205, 193, 215, 22, 92, -128, -326, -261, 297, 293, -21, 78, -36, -259, -81, 53, 205, 1, 41, -102, -152, 44, -119, 85, -68, 0, 56, 144, -16, -35, 154, -25, 207, -124, -20, -170, 40, -56, -114, 139, 221, -108, 123, -230, -131, 125, -33, 142, 55, 314, -130, -70, 192, 31, 254, -414, 223, -26, 169, -202, 98, 168, -21, 216, 96, 191, -22, -98, 98, 117, 182, 105, 197, -9, -38, -157, 97, 193, 85, -125, -227, 55, -21, 109, 6, -56, -223, -219, 291, 246, -140, -205, 43, -24, -255, 85, -136, 141, -36, -17, 14, 294, -236, 179, -27, 46, 48, 115, 170, 106, -17, -186, 259, -150, 18, -157, 64, 121, -190, -60, -182, 80, -66, -73, -67, -171, 196, -168, 119, 297, -150, 168, 323, -29, 127, -139, 114, 19, -65, -288, 233, 7, -25, 161, 126, 27, 101, -57, -101, 11, 257, -331, 220, 163, 101, -9, 157, -14, -317, 189, 48, 43, -189, -128, 145, -172, -141, -59, 278, 296, -82, 135, -62, -137, 104, 300, -95, 145, -32, 32, -271, 134, -59, 9, -23, -151, 186, 0, -11, -156, 103, 174, 81, 87, -188, -14, -304, 155, 135, 50, -32, 254, -160, -256, -228, -248, 128, 147, 117, 105, -16, 100, -105, 119, 57, -171, 158, 0, 30, -189, 110, 40, -201, 171, -39, -65, -9, 184, 245, 35, -114, -273, 398, 211, 29, -41, 37, -116, -156, 137, 31, 121, -376, -98, -137, 123, -87, -168, 41, -41, 7, -76, -25, 45, -136, -184, -139, -3, -18, 127, 179, 152, 116, -164, 76, -46, 150, -120, 123, -192, -195, 67, 97, -211, -8, -72, -251, 188, -24, -163, -98, 136, 153, 95, 54, -181, -162, 303, -117, 277, -89, -84, 129, 147, 25, -116, 262, -29, -118, -235, 177, -107, -59, 51, 296, 122, -5, 81, 81, 119, -15, -168, 267, 344, 30, -162, -61, -303, -192, 225, -135, 173, -13, 220, -257, 239, 53, -12, -110, -89, 82, 27, -382, -33, -183, 10, -72, -272, -146, -26, 55, 188, -172, -230, 12, -136, 65, -32, -61, -276, -140, 243, 102, -5, -94, 88, -92, 31, 102, -77, -81, 267, -31, -29, 40, -300, -150, 3, 136, 74, -181, 66, -192, -61, 110, -323, 293, 262, -129, -224, 226, -302, -135, 263, 103, -115, -44, 297, 166, -109, -54, 82, -80, 129, 6, 34, 23, -4, 32, -25, -180, 18, 43, 213, -139, -41, -18, 26, -208, -216, -66, 206, -457, 169, 131, -224, -110, -229, 268, 12, 14, -281, -3, 93, 13, -8, -136, -119, 245, 106, -42, 152, 293, -42, 100, 44, -127, 133, 256, -130, 22, 55, -56, -70, -225, -196, -108, 23, -37, 90, -191, 71, -51, -27, -99, -164, 311, 313, -217, 154, 109, -142, -82, 0, 142, 188, -134, -126, 167, 82, 192, -110, -25, 1, -134, 25, 0, -218, -273, -49, 49, 375, -155, -103, 144, 222, 109, 84, -100, -521, -101, 41, -353, 472, 73, -210, -83, -350, 379, -96, 40, -206, 165, -145, 163, -129, 7, -116, 47, -244, -5, 125, -155, 49, 69, 92, -129, 83, -60, 13, -43, 194, 138, -143, -3, 4, -58, -195, 3, -59, -104, 166, -1, -119, -207, 62, -146, 129, -85, 127, 5, 136, 228, -143, 102, -154, 151, -237, 213, -213, 6, -349, 112, 279, 183, -199, 87, -13, 65, -22, 88, -14, -188, 23, -356, 185, -154, 357, -301, -398, -191, 45, -155, 38, 5, -377, 3, -139, 119, 59, -26, -162, -40, -92, 157, 59, 9, -106, 50, -42, -24, 113, 388, 113, -179, 10, -89, 193, -42, -78, 20, 226, 220, 45, 199, 104, 105, -42, -89, 292, 20, 78, -98, 37, -227, 100, 49, 131, -95, 197, 85, -21, -108, -68, -127, 128, -67, 78, 41, -44, 72, -176, 22, 368, 15, -280, 57, -113, -61, 254, 76, 222, 41, 212, 10, 68, -194, 57, -214, -27, -135, -49, -200, -65, 46, 2, -172, 219, -65, 116, 167, 24, -94, 39, 210, 310, -162, 19, 56, -79, 51, 305, 113, -152, -46, 76, -327, 171, -15, -46, 82, -153, 17, 10, 80, -164, -159, -18, -126, -4, 80, 94, 12, 197, -179, -54, 135, -147, -187, -108, -63, 136, -173, 116, 102, 219, 94, 159, 49, 89, -115, -140, 208, 324, 230, 9, 146, 3, -244, 84, 131, 114, -328, 122, 84, 96, -206, -253, -60, 26, 104, 124, 98, -142, 74, 83, -63, 160, -123, 21, 93, -93, -41, -29, 132, 61, 153, -47, -147, 9, 58, 35, 165, 112, 69, -13, -231, 171, -47, 90, 158, -25, 47, -132, 36, 214, -164, -224, -17, 9, 83, -82, 134, -153, -116, -48, 76, -173, -219, -106, -15, -77, -198, 21, -202, 161, -132, 28, -68, 137, -54, -76, 74, 63, 240, 1, -232, -229, 46, 226, -103, -190, -117, -85, 130, -71, -143, -89, 196, 99, 18, -169, -147, -114, -145, -85, -50, 48, -43, 115, 130, 48, -224, -402, 535, 529, 2, -64, 181, -160, -73, 488, 17, -69, -461, 52, -249, 389, -365, -89, 46, -233, -242, -119, -119, 199, -88, 16, 85, 0, -130, -156, -154, -198, -172, -192, 100, 13, 98, 149, -306, -18, -6, 197, 80, 105, 64, -71, 58, -1, -141, 8, -73, 111, 130, -260, 21, -95, -257, 161, 118, 9, -278, -96, 149, 148, 37, 87, 102, -225, 181, 13, -120, -272, 147, -90, -223, 290, 213, 258, -42, -4, 180, -434, 122, 56, 199, -340, -58, -184, -117, 145, 129, 42, -313, 220, -62, 89, -362, 1, -235, 26, -152, -19, -27, -207, 202, 11, 90, 130, 295, -18, -263, -320, 28, 97, -4, -97, -154, 169, -342, -102, -168, -75, 78, -8, 32, 181, -210, 26, -95, -149, 149, 240, 83, 76, 33, -212, -67, -9, 26, 2, -124, 151, 39, 231, -144, 104, 136, -110, 71, 145, -64, 86, 83, -177, 2, 152, 119, 226, 153, 113, 358, -183, 111, 366, 330, -70, -143, -87, -283, 245, -266, -142, -89, 270, -201, 357, -286, 219, 114, -164, -76, 210, -91, -1, 240, 105, 382, -164, -102, -142, -92, -171, -18, 79, -131, 66, -240, 55, -118, 24, 22, 85, 13, 64, 134, -64, -27, -85, 41, -102, 164, 114, 130, 24, 120, -212, -153, 29, -131, 0, -147, 42, -42, 269, 32, -288, -40, 239, 234, -172, 256, 22, -191, -103, -272, 230, -210, 377, 125, 340, 32, -193, 383, 220, 383, -47, -200, -121, -132, 269, -59, -42, -282, -3, 140, 217, 101, 70, 28, -168, -28, 45, 104, 83, -190, 69, -68, -58, 18, -4, 109, -61, -174, -80, 144, 12, 36, 69, 22, 155, 4, -63, 275, -151, 209, -6, -63, -72, -142, 49, -85, -34, 117, -82, -184, -134, -93, 7, -6, 159, -255, 73, 94, 138, 104, -87, 240, 193, 259, -108, 117, 111, -240, 193, -37, 105, -15, 172, 116, -98, 63, -296, 33, 21, 286, -122, -292, -353, -195, 323, -38, 170, -138, 95, 68, -39, -74, 185, 129, 133, 11, 70, -13, 180, -64, -74, -108, 173, -53, -11, 281, 77, -145, -39, 230, 270, 99, -44, -225, -166, -155, 334, 215, 120, -202, -159, -320, 77, -340, -148, 170, -1, -161, -125, -8, -56, -105, -90, 144, 73, -59, -259, 215, -76, -250, -212, 17, -117, 73, -63, -80, -167, -98, 101, 145, -73, -107, 294, -173, 111, -11, -271, 106, 206, 173, -130, -192, -95, -1, 85, -111, 123, -25, 12, 37, 105, -149, -89, 103, -43, 26, -252, 171, 31, -24, 21, -21, -111, -40, -39, -136, -68, 140, -260, 452, 305, 218, -366, -42, -236, -70, 404, 140, -51, -349, 21, -287, 334, -301, -308, 336, 227, -222, -231, -62, -208, -135, 153, 62, 34, -271, 17, 52, 163, -284, -154, -44, -182, -24, 245, 120, 64, -8, -98, -49, 307, -77, 233, -102, -102, -33, -42, -96, -12, -127, -108, 13, -66, -23, -55, 36, -298, -155, -13, -103, 3, 151, 107, -72, -44, -68, 177, 312, 197, 227, -248, 108, 86, 244, -299, -21, -300, 47, -414, 427, 291, 123, -82, 148, -185, -44, 114, 27, 141, -307, 73, -324, 200, -144, -72, 348, 10, -47, -80, 222, 154, -297, 54, 119, 40, -6, 54, -90, -16, -72, 83, 177, -138, 81, 0, 123, -277, 137, -185, 72, 167, -36, 153, 30, 23, 248, 249, 67, 48, 253, 189, -88, -143, 193, 52, -154, -143, -12, 122, 90, -152, -109, 83, -86, -94, -180, -31, 124, 146, -48, -123, 27, 123, -147, -128, -78, -139, -60, -236, 201, 30, -122, -84, -61, 79, -128, 194, 0, -6, -196, 0, -211, 360, -179, -128, 70, 44, -158, -109, -128, -10, -144, 176, -87, 132, 0, -49, 117, -225, -240, 117, -44, -5, 145, -8, -38, -158, 99, 57, 73, 32, 112, 70, 19, -186, 16, -107, 124, -48, 2, -143, -70, 5, 105, -94, -124, 99, 129, -76, -179, -88, }; +int32_t to_patch_embedding_linear_bias[16] = {227, -68, -2, -126, -99, -174, -84, 74, -6, 99, -139, 80, -62, -140, 83, -7, }; +int32_t to_patch_embedding_layer_norm2_weight[16] = {3971, 4588, 4419, 4328, 3995, 4153, 4080, 3987, 4099, 4443, 4075, 3864, 4214, 4134, 4104, 4276, }; +int32_t to_patch_embedding_layer_norm2_bias[16] = {132, -148, 57, 34, 72, -70, -116, -26, -76, 79, -190, 10, -46, 57, -30, 204, }; +int32_t transformer_layers_0_0_norm_weight[16] = {4052, 4657, 4613, 4245, 4042, 4415, 4086, 4275, 4240, 4498, 4285, 4081, 4387, 4184, 4302, 4580, }; +int32_t transformer_layers_0_0_norm_bias[16] = {80, -54, 40, 214, -203, -129, -101, 57, -177, 57, -56, -281, -36, 219, -182, 92, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_Q_H0[64] = {-568, -962, 189, -868, -562, 692, 858, 407, -818, -814, 262, -471, 1273, 623, -384, 338, -321, -114, -723, 913, -697, 294, -35, -123, -264, -331, 509, 129, 184, 595, 16, -677, -348, 313, -401, 679, -798, 378, -145, 190, 618, -246, 776, 801, 974, 570, 842, -29, -685, 721, 640, 87, -612, -939, 890, -225, 522, 70, -514, 927, 990, 825, 114, -893, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_Q_H1[64] = {640, 166, -336, 542, 491, -1105, -458, -497, 20, -292, 989, -578, -438, 699, -855, 724, 901, 119, -824, 607, 1135, 1478, -883, -673, -923, -897, 445, 395, -782, 260, 591, 327, 970, -1386, 631, 281, -121, -721, 109, 203, 74, 106, 593, 1065, 857, -728, 761, -620, -558, 765, -514, 587, -489, -144, 839, -142, -270, 415, -757, 288, 305, 1302, -249, 247, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_Q_H2[64] = {-1419, 962, -640, 252, -124, -585, -573, 363, 218, 537, 461, 201, -502, 636, 804, -1101, 434, 91, -595, -67, -209, -257, 132, 782, -55, -268, -36, -205, -1225, 1346, 648, -933, 360, 693, -726, -675, 1319, 324, -601, -707, 234, 687, 630, 769, 323, -334, -855, 135, -410, 330, -330, 739, -812, -33, -356, -471, 689, -841, 242, -763, -1304, 937, 743, -440, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_Q_H3[64] = {-1060, 1048, 444, 53, 299, -1202, -112, -899, 1136, 226, 103, -466, 653, 104, 151, -131, -910, 333, 104, -1167, -337, -744, -291, 445, -339, -916, 64, -170, -569, 334, -1016, 803, -782, -18, 583, -961, 304, -358, 725, 244, -567, -128, -370, 950, 536, -757, 290, -506, -365, -1083, 685, -1292, 555, -640, -304, 840, 919, -707, 665, -777, 781, 909, 869, 882, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_K_H0[64] = {339, 84, 743, 513, 937, -490, 499, -304, 1092, 299, 522, -95, -850, -672, -565, 107, -47, -401, 196, 1062, -158, -507, 736, -381, -249, 768, -185, -849, -107, 483, 520, -997, -234, -945, 1008, -44, 674, -34, -388, -817, 289, 988, -652, -446, -603, 226, 427, 582, -422, 37, 474, -103, 561, 198, 113, 520, 150, 37, -857, 1162, -361, -122, -909, 596, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_K_H1[64] = {587, -190, 215, -264, -1101, -633, 784, 643, 562, 794, -31, 134, -75, 572, -551, 233, -162, -1081, 780, -472, -588, 170, 1040, -1217, 805, 505, -961, -23, 457, 730, -77, 117, 771, -422, -811, -611, 622, 678, 554, -690, 435, 403, -904, 91, -350, -398, -563, -750, 352, -406, -22, 667, 468, -1362, 395, -764, 132, -553, -612, 61, -284, -933, -340, -561, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_K_H2[64] = {399, -840, -111, -768, -787, 925, 1041, 579, -842, 1107, -195, -454, -1018, -673, 330, -1015, 554, 339, 389, 461, 579, -387, -826, 465, -1171, 274, -94, 518, 899, -878, -986, 258, -406, 199, -487, -577, -1264, 1126, -283, -1205, -1311, -101, 970, 79, 183, -108, -499, 980, 122, 110, -163, -25, 767, -718, -836, -838, 839, 120, -734, 789, -324, 119, -159, -411, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_K_H3[64] = {585, 567, -262, -561, -166, 469, 155, -56, -512, 839, -519, 859, -225, 693, -983, -707, 395, -196, -574, 63, 3, -162, -1000, -962, 248, 335, 1235, -284, 994, 727, -475, -891, -428, -817, -598, -1159, 526, 715, -232, -742, -191, -21, 65, 1479, 84, 389, 658, 385, 674, 729, 169, 221, 7, -27, 811, 841, -1080, 645, 14, -1033, -1146, -472, -74, 265, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_V_H0[64] = {356, -364, 862, -1113, -938, 408, 1437, 968, 987, 664, -411, -881, 756, 768, -795, 77, 326, 481, -714, 196, -110, -215, 106, 621, -812, 542, 213, 1043, -188, -725, -266, -114, 785, -690, 427, 627, 1001, 796, -752, -410, -760, -304, 129, 1112, 62, 805, -1030, 382, -1195, -1002, 855, 1261, 1026, -281, 57, -850, 763, 77, 738, -135, 1189, 65, -1168, 617, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_V_H1[64] = {536, 374, 293, 992, -103, -576, -463, -1069, -605, 1261, 597, -599, 643, -622, 268, 603, 712, 373, -455, 8, 760, -1245, -460, 201, 1035, 731, 955, 626, -131, -759, 43, -722, -817, -398, 168, 999, 474, 150, 639, -148, -359, -493, -551, 339, -737, 825, -827, -86, -681, 474, 757, -1097, -858, -351, 372, -792, -44, -609, -879, 540, 286, 701, 875, 406, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_V_H2[64] = {764, 345, -422, -624, 1231, 99, -640, -1501, -301, -900, 283, 1233, -1172, 202, 1417, -498, 544, 858, 106, 761, 381, -695, -1310, 63, 651, -635, 946, 848, 999, 198, 84, -923, 1050, 851, -766, -870, -854, -29, 999, 47, -538, -926, -208, 448, 898, 61, -418, 1075, 429, -731, -414, -264, -538, 892, 876, 667, 311, -928, -294, 449, -854, 53, 670, -212, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_V_H3[64] = {-944, 62, 621, 124, -535, -149, 709, 95, 1129, 832, -644, 656, 547, 233, -187, 737, -793, 821, 16, -558, 129, -235, -896, 491, 753, 42, 343, 894, -531, -820, 518, -426, -787, 3, -398, -1120, 1170, 1063, -813, -105, -78, -135, 248, -263, -351, -172, 224, -430, -1072, -956, 331, -6, -221, -602, -34, 0, 913, -859, -110, -512, 1154, 657, -630, 8, }; +int32_t transformer_layers_0_0_fn_projection_weight[256] = {-402, -1077, -244, -103, 318, -176, 766, -1187, -866, 337, 1127, 451, -280, -1007, -185, -704, 654, 854, 369, -532, 565, -666, 1063, 433, 312, 232, 211, 846, 273, 115, -969, 847, -514, 236, -588, 549, -298, 759, -253, 1035, 6, -854, -445, -1030, -204, -85, -398, -307, 785, 142, -1233, -991, 496, 512, -675, -12, 172, 11, -1111, -633, 573, 502, -201, 322, -391, 248, -499, -56, -559, -305, -527, 629, 315, 130, -98, -248, 172, 148, 36, -337, 494, 353, 696, 517, 187, -1141, 985, -1041, -1095, 86, -29, 626, -1129, 678, -357, 67, 557, 291, -223, 493, -797, -561, 1218, -793, -542, 266, 275, 229, -637, -993, 965, 673, -884, 707, -19, -635, -663, -730, 87, 528, -179, 1047, -677, 1117, -854, -716, -700, 234, -970, 807, -180, -116, 1006, -13, -1029, -40, 182, 390, -1164, -858, 584, -453, 202, -765, 821, 362, -337, -572, 40, 20, -963, 525, -390, -743, 990, -432, 156, -54, 629, 666, -252, 461, 486, -5, 762, -728, 3, -742, -741, 1112, 1431, 1199, -676, -393, 403, -522, -474, -760, 508, -904, -265, 203, 78, -1096, -852, 587, 113, -680, 171, -308, -231, -484, -210, -463, 635, -561, -1093, 140, 509, -767, -329, 120, 518, 396, 280, -194, -414, 772, -697, -104, 218, 260, -105, 210, 1339, -369, -991, 856, 977, -735, 664, 306, 405, -156, -290, -772, -732, 594, -101, 930, -1060, 1133, 977, -515, -736, -390, 1010, 118, -351, -652, 74, -553, 216, -609, 289, -209, 1004, 930, 462, 171, 755, -914, -686, -185, -616, -648, }; +int32_t transformer_layers_0_0_fn_projection_bias[16] = {-840, -92, -107, 118, 323, -361, 278, -5, 135, 300, -784, 540, -15, 380, 771, 648, }; +int32_t transformer_layers_0_1_norm_weight[16] = {3913, 4457, 4086, 4198, 3935, 4065, 4044, 3934, 3956, 3983, 4205, 3852, 4319, 4076, 4119, 3967, }; +int32_t transformer_layers_0_1_norm_bias[16] = {-176, -178, -255, 86, 151, -163, -161, -8, 155, -133, -118, 180, -206, 30, -113, -222, }; +int32_t transformer_layers_0_1_fn_ff1_weight[64] = {-269, 879, 417, 125, -1042, 562, 825, 151, -22, 941, 340, 837, -99, -941, -81, -34, 779, -802, -170, 98, -331, -642, 898, 694, -266, 574, -677, 748, -770, -37, 501, -738, 539, -756, 846, -539, 380, 724, -628, 795, 1144, 372, 525, 499, -257, -2, -298, -356, -821, -8, 829, 852, 205, 290, -229, 201, -910, -991, -340, 841, -610, 961, 227, 151, }; +int32_t transformer_layers_0_1_fn_ff1_bias[4] = {-143, -827, -308, 129, }; +int32_t transformer_layers_0_1_fn_ff2_weight[64] = {305, -252, 1555, 1351, -1680, 1389, 1229, -741, -1475, 285, -203, -1095, -1407, -1403, -1965, 1256, -273, -533, -1, -1734, -417, 176, -253, 1055, -326, -525, -1, 343, -413, 309, -1034, -1608, -1219, -547, -472, -663, -1628, -1026, -56, -1330, 673, 451, -900, -1720, 2030, 607, 1103, -1915, 1853, 911, -939, 398, 21, 15, 1670, -409, 378, -1568, 1405, 1371, 933, -759, 545, -2014, }; +int32_t transformer_layers_0_1_fn_ff2_bias[16] = {837, -1010, 736, 2060, 1857, -1132, 728, -1052, 947, 1603, 1612, 1908, 1519, 508, -1745, -1202, }; +int32_t transformer_layers_1_0_norm_weight[16] = {3943, 4401, 4285, 4286, 4112, 4059, 4094, 4023, 4156, 4435, 4079, 4136, 4219, 4111, 4081, 4076, }; +int32_t transformer_layers_1_0_norm_bias[16] = {-44, -53, 85, 19, -34, -44, 71, -39, 40, 66, -63, 14, 27, -106, -87, -76, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_Q_H0[64] = {495, 600, -127, -357, 489, 355, 41, 97, 758, -317, 99, -403, 730, 452, -27, 354, -495, 997, 387, -732, -742, 475, 67, -193, 464, 305, -691, 995, 902, 1007, -985, -300, -608, 939, -555, 527, 454, -789, 77, 203, 550, 130, 912, 756, 104, 733, -477, -462, -25, 816, -253, -828, -407, 607, -1024, 458, -159, -75, -422, -327, 772, -845, 661, 673, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_Q_H1[64] = {-780, -895, 1016, -316, 1036, -767, 839, -289, -582, -1437, 46, -283, -830, 69, 661, 720, 925, -302, -908, -185, -771, 486, 460, -953, 327, -491, -209, -21, 210, -935, -445, 117, 541, -967, 810, -458, -985, -328, -38, 647, 456, 982, -64, -586, -155, 738, -358, 85, -536, 5, -210, 168, -628, 278, -280, 13, -793, 687, 18, -27, -340, 178, 258, -977, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_Q_H2[64] = {-397, -371, 571, 275, -30, 516, 642, 475, 831, 781, -398, -383, -510, 210, -543, 47, -637, 293, 625, -645, 40, -892, -734, 402, -172, -431, 7, -150, -549, 512, -208, 249, -527, -433, 922, 769, -788, -851, 328, 370, -51, 214, -971, -639, -809, 119, 54, 694, 746, -331, -515, 64, -894, 340, -713, -372, 540, -418, 924, 572, 1071, 882, 877, -633, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_Q_H3[64] = {476, -152, -876, 172, -361, -748, -636, -123, 162, -616, -504, 793, 661, 27, 626, 102, -518, 900, 891, -508, -848, -553, 519, 101, 122, -683, -204, 986, 44, 263, 421, -1069, 811, -302, 909, 942, 864, 478, -225, -1105, -470, 4, 387, 537, 133, 434, -6, -780, 301, 739, 1092, -834, -1072, 173, 106, 480, 981, -1, -672, 1039, -32, -769, -809, -673, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_K_H0[64] = {-536, -105, 457, -372, -36, -789, 776, -669, 705, -386, -480, -493, -216, 652, -161, -285, 385, 1026, -222, 268, -761, -564, 815, 991, -417, -308, 967, -141, 950, -843, -774, 222, -9, -387, 466, 539, -385, 108, 569, 873, 607, 184, -627, -371, 92, 143, 355, 885, 141, 339, 397, 598, -574, 500, 226, 716, 449, 328, 820, -210, 614, -841, -650, -881, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_K_H1[64] = {487, 12, -424, -75, 464, 210, 601, -479, 874, -114, 421, 630, 621, 563, 671, -886, 856, -783, 351, 676, 1263, -231, 1, -862, 609, 307, -259, -737, 649, -552, 811, -851, 764, -42, -780, -1011, -595, 521, -447, -604, -581, 286, -718, 184, -32, 81, -644, 927, -789, -145, 864, 638, -400, 675, -935, -786, 1144, -920, -702, 755, -341, -782, -596, 566, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_K_H2[64] = {339, 539, 363, -56, -218, 918, 616, -856, -651, 992, -167, 175, 652, -456, -927, 539, -234, -846, -502, 924, 457, -677, -48, 41, -224, 685, -994, -17, -373, 766, 1014, -845, 509, -554, -878, 187, 824, 437, 871, 410, 1037, 18, 459, -666, 496, 360, -294, 407, 245, 266, -455, -167, -1086, -133, -739, 1113, 462, -910, 764, 1087, 238, -358, -725, -713, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_K_H3[64] = {-909, -289, 660, -80, -802, 331, 600, 430, -889, 182, 205, -1121, 799, 211, 337, -537, 1094, -867, 396, 415, 806, 787, 683, 530, 240, -442, 73, -203, 433, 326, 802, 184, 1048, 362, 49, -755, 903, 970, 491, -289, -807, -123, -625, -826, -348, -711, 943, -872, 369, 459, -610, -780, -902, 865, -479, 952, 251, 723, 10, 137, 110, 432, 545, 827, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_V_H0[64] = {-904, -972, 395, -281, 1346, 1215, 17, -994, -340, 936, -382, -125, -644, -779, -546, 815, 142, 820, 98, 552, -377, 959, 1113, 123, -221, -107, -964, -219, 206, 648, 834, -596, -35, 431, 658, 398, -1069, -140, -465, -39, 455, 824, -75, 420, -270, -55, 619, -394, -685, 548, 194, -23, 38, 815, -786, 474, 684, 318, -763, 593, -655, -618, -263, 251, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_V_H1[64] = {550, 404, -867, -355, 1129, -344, -759, 403, 203, 811, 891, 674, 433, 812, 428, 68, -321, 344, -725, 560, 425, 801, 653, -328, 60, 269, 427, -15, -159, 367, 235, -599, 8, -1167, -239, -594, -544, 871, 675, 78, 607, 621, -244, -492, 415, 668, 1004, -170, 961, -1137, -717, 1007, 228, -242, 508, 511, -703, 429, 800, 807, 826, -723, 855, 790, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_V_H2[64] = {137, -567, -524, -1077, -226, -320, -619, -639, -215, 351, 297, -193, 280, -282, 92, 700, 987, -271, 103, -408, 138, -763, -252, -592, 890, 463, 961, -740, -487, 323, 233, -639, -752, -186, 124, -984, -70, 996, 194, 663, 72, 109, 382, -590, 948, 98, -885, -1018, -411, -896, 847, 478, 16, 0, -861, 876, -875, -176, -784, 30, -797, -803, -906, 896, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_V_H3[64] = {523, -54, 650, 319, 905, -162, 443, -845, -509, 320, -1008, -984, -99, 709, -64, -938, 175, -357, -351, 40, 777, 340, 1157, -867, -689, 733, 553, -237, 721, -1006, -476, -684, -446, -31, -974, 214, 469, -240, -1137, -233, 285, 528, 266, -798, 538, 786, 438, -717, 586, -872, -901, 1040, 137, -19, 215, -995, -446, -870, 675, 139, 103, -691, -115, -573, }; +int32_t transformer_layers_1_0_fn_projection_weight[256] = {-961, -497, -218, -462, -752, 764, 182, -416, 43, -295, -1317, -752, 990, 758, 595, 383, -297, 299, -272, -565, -953, -338, -303, 1186, 1256, 504, -455, 329, 353, -416, 202, 446, -869, 19, -776, -409, 959, 382, -5, 278, 503, 440, 209, 407, 410, 406, -331, 877, 463, 721, 65, -135, 293, -336, 674, -687, -1054, -331, -225, -675, -963, 710, 728, 790, -392, 108, -834, 300, -154, 767, 401, 421, -820, 246, -236, -957, 669, 358, 483, 60, 249, 66, 1149, -828, -539, 332, 57, -1235, 282, 268, 978, 216, -830, -553, -541, 279, -214, -340, 977, -249, 205, 70, -401, -502, 17, 1231, 634, 390, -937, 15, -798, -473, 50, -277, -825, 504, 79, 163, -647, -875, -860, 161, -256, -936, 594, -491, -403, -47, 643, 316, -778, 1075, -1066, -1276, -590, -713, 888, 114, 749, -78, -257, 103, -363, 247, -128, 40, 1004, 152, 639, 171, -485, -1083, 70, 342, 903, 569, -606, 472, -894, -585, -682, 488, -726, 169, 16, -905, -906, -734, 796, 697, -527, 807, -1091, -911, -320, -791, 718, 622, 475, -343, 853, 769, 884, 564, -1171, -59, 180, 14, 288, -1012, 1087, -518, -549, 777, 576, 765, -356, 945, 640, -174, 238, 281, -341, -889, 1007, 311, 40, -45, 633, -584, 1091, -101, -801, -483, -527, 411, 164, 457, 365, 19, 209, -542, 114, 352, -625, 590, 666, -706, 1037, -388, -993, -373, 240, -343, -914, 856, 956, 617, 982, -140, 371, -455, 208, 973, 133, 652, -646, 344, 297, -880, -97, 271, -380, -219, 827, 596, }; +int32_t transformer_layers_1_0_fn_projection_bias[16] = {-736, 309, -43, -180, -220, -446, 37, 54, 389, -788, 1114, -969, -17, 10, 286, 852, }; +int32_t transformer_layers_1_1_norm_weight[16] = {4083, 4051, 4008, 4127, 3974, 3860, 4095, 4052, 3996, 4005, 4114, 4195, 3983, 4097, 4071, 4004, }; +int32_t transformer_layers_1_1_norm_bias[16] = {137, -2, 135, 87, 127, -139, -134, -96, 67, 14, -108, -63, -78, 31, 15, 53, }; +int32_t transformer_layers_1_1_fn_ff1_weight[64] = {-127, -843, -176, -862, -255, -382, -561, 758, -943, -676, -585, -721, -737, -526, -519, -110, 481, 81, -122, -888, 358, 455, 170, 527, 336, 86, 266, 133, 896, 362, 806, -114, -894, -490, -7, 55, -544, 938, 456, -382, 987, -919, 127, 210, 427, -677, 788, -316, 776, -675, 152, 89, -813, -174, -14, 274, 317, -26, 399, -560, -367, -255, 649, -1004, }; +int32_t transformer_layers_1_1_fn_ff1_bias[4] = {90, -953, 421, -933, }; +int32_t transformer_layers_1_1_fn_ff2_weight[64] = {-1042, -1584, 1737, 504, -1780, 1348, 536, -1647, -1350, 839, -1377, 663, 455, -1985, -1640, 1642, 1730, -960, -1286, -54, -1541, 714, 971, 579, -69, 1795, -831, -1040, 1600, -382, -1386, 245, 1170, 1367, -210, 904, 1794, -1331, -524, -1304, 84, 743, 593, -621, -1397, -1482, 1047, -849, -1283, -1557, 911, 218, -1263, -1694, 1757, 1760, 812, 762, 1568, 1882, -1391, 1405, -244, 478, }; +int32_t transformer_layers_1_1_fn_ff2_bias[16] = {-1109, -350, -895, 2006, 686, -472, 1124, 1903, 1174, -405, -1500, -440, -422, -142, 1269, -836, }; +int32_t transformer_layers_2_0_norm_weight[16] = {4135, 4645, 4316, 4215, 4243, 4415, 4186, 4002, 4224, 4214, 4305, 4162, 4319, 4117, 4437, 4432, }; +int32_t transformer_layers_2_0_norm_bias[16] = {-10, -219, 118, -51, 66, -61, 16, 57, 4, 67, 27, 112, 24, -177, -70, 114, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_Q_H0[64] = {750, 642, 712, 102, -275, -314, 514, -1305, 48, 907, 72, -639, -859, -1227, -96, 131, -174, 771, 585, -694, 1109, -192, -60, -1356, 95, -133, -539, -295, -1002, 421, -649, 590, 403, 1025, -703, 311, 867, 275, -77, -759, 624, -841, -753, -297, -807, 129, 827, -804, -772, 63, 894, -59, -512, -206, 425, 657, 431, -1100, -646, 1259, -1036, -1045, 252, 1058, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_Q_H1[64] = {-101, 525, -497, -703, 267, -890, -574, 202, 304, -567, 1090, -181, -37, -245, -262, 545, -260, 686, -634, -882, 1059, -247, -562, -1061, -944, -143, 1018, -218, -608, -752, -127, 623, 467, -1114, -92, -355, -635, 947, 626, 710, -41, -864, -216, 275, -567, 834, -282, -558, -925, 848, 565, -826, 129, -724, 323, -1025, 681, 725, -81, -38, -463, -653, 1066, -210, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_Q_H2[64] = {-1000, -805, 417, -430, -467, 482, -643, 174, 646, -165, -599, 93, 65, -1101, 230, 546, -172, -758, -61, -837, 974, 408, -104, -727, -296, -456, -186, -148, -786, 216, -490, -825, 362, 932, -340, 816, 142, 20, -125, -1072, 390, -69, -839, 806, 830, -740, -407, -804, 1087, 182, 602, -206, -283, -331, -868, 454, 758, -753, -277, 266, -147, 297, -885, -669, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_Q_H3[64] = {890, -862, -125, -582, -1112, -1234, 52, -854, -742, -485, 26, -1324, 767, -304, 274, 490, 285, -878, -741, -904, -46, 536, -1020, -689, 33, 434, 481, -13, 67, -67, -28, 798, 162, 915, -629, 766, -1016, -907, 705, -1195, 1089, 399, -878, -55, -212, -838, -19, -777, 207, -357, -446, 28, 210, -1012, 500, 196, -409, 121, 470, 957, 885, -742, -227, 284, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_K_H0[64] = {196, -857, -988, -250, 851, 1125, 256, 246, -13, -115, 43, 444, -62, 5, 196, 922, 603, 803, 7, -895, 225, 886, -688, 262, -355, -427, 167, 47, -220, -688, 373, -63, 36, 672, 524, -170, 675, 562, -1017, 662, -648, -36, -1136, 523, -305, 50, 303, 147, 246, -676, -142, 524, 327, 584, -688, -1043, 1089, -277, 414, -934, 798, 883, 1051, -572, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_K_H1[64] = {893, 528, -509, -849, 255, -684, -717, 423, 113, -646, -210, -702, -66, 1028, -1014, -219, -40, -803, -291, 773, -187, 46, 954, 809, -872, 516, 833, -855, -848, 835, -481, 54, -295, 326, 904, 732, 338, 604, 78, -733, 129, 699, 498, 835, -949, 376, -955, -820, -618, 1033, 981, -643, 906, -534, -1152, 65, -322, 66, -274, 926, -558, -402, -926, -78, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_K_H2[64] = {1036, 778, -513, 648, 42, 482, -147, 968, 12, -521, -380, 241, 982, 639, -959, -558, -511, 941, 56, -425, -745, 546, -937, 670, 819, -652, 739, -106, -552, -691, 445, -287, 30, -36, -715, -196, 884, -637, 0, 586, -230, 692, -169, -1036, 9, 548, 426, 797, 300, -356, -648, -432, 1287, -533, -110, -604, 835, 396, 466, -484, -443, 443, 421, -29, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_K_H3[64] = {-1028, -82, 553, 856, -861, -129, 600, -637, 300, -239, 141, -296, 443, 358, 949, 498, -736, 977, 339, 225, -1016, -994, 330, -1120, 1007, 178, -78, 1380, -459, -932, 620, -454, -671, -885, -617, -1051, 1021, -378, 542, 1186, 512, 608, -809, 418, 153, -173, -46, -342, -1247, -413, 461, -858, 482, -234, 593, 168, -638, -919, -2, -734, -703, -717, 275, 1043, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_V_H0[64] = {-569, -735, 276, 102, -180, 537, -520, 1212, 789, -363, 25, -565, 952, 177, 147, -941, -448, -1023, 433, -198, 197, 686, 450, 217, 498, 850, 455, -791, 992, 707, 544, -393, 914, 631, -407, -221, 131, 614, 619, 430, 710, -753, -270, 347, 115, 834, 648, -138, -386, -1090, -122, 758, 753, 488, -639, 843, 35, 193, -708, 1173, -499, -677, -894, -551, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_V_H1[64] = {189, 384, -576, 584, 707, -516, -1085, 81, -652, 809, 849, 929, -834, 725, 256, -568, -77, 932, 4, 445, -174, -238, -718, -991, 539, -472, -577, -951, -1016, 229, 73, 838, 980, -710, -18, 111, -583, 916, 1046, -814, 551, 95, 777, -46, 975, 27, 252, 362, -772, -863, -803, 496, 855, 100, -481, 357, 577, 945, 630, 44, 712, -157, -147, 1142, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_V_H2[64] = {668, -279, 884, 126, -1152, -408, 994, -84, 549, -356, -363, -365, 596, -513, 305, -212, 175, 181, -1146, -1, 588, 511, 147, 231, -751, -28, 129, 877, 385, 904, -362, -628, -290, -366, -1028, -102, 909, -942, 1006, 653, 454, -908, 1069, -462, 1201, -227, -847, -775, -1091, 75, -924, 178, 87, 519, 431, 287, -411, 100, 605, -926, 593, -438, -588, 618, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_V_H3[64] = {496, 644, 748, 90, 519, 492, 816, -402, -44, -1013, -886, -581, 880, 744, -302, 821, -992, 729, -44, -493, -1191, -137, 352, 950, 342, -211, 347, -1036, 125, -31, 912, 313, -1230, 354, 356, -195, 220, -693, -1152, 538, 1248, -1006, 152, -822, -541, -813, 12, -269, -863, -739, -438, -650, -250, 770, 240, 195, -813, 411, 597, 1034, -114, -202, 777, -162, }; +int32_t transformer_layers_2_0_fn_projection_weight[256] = {-250, -616, -353, -787, 606, 329, 1043, 644, 827, -65, 841, 68, -804, -131, 515, 298, 594, 611, 284, -40, -72, -695, 564, -25, -141, -9, -936, 100, 318, 1101, -899, -442, 755, -919, -439, 111, -58, -1232, 34, 191, -666, 651, -416, -578, -160, -1101, 927, 786, -1151, 834, -830, 143, -180, 381, -887, 812, 755, -287, -1322, 98, 629, 499, 917, 957, 261, 509, -1001, -522, -102, -106, -48, -816, -161, -516, 345, 373, -881, 1022, -493, 648, 1124, -152, -542, -293, -708, -46, 779, -106, -1112, 1022, -634, 145, 401, -1117, -374, 775, -378, -672, 956, -497, 798, -1060, 359, -1384, -853, 802, 1090, -431, -391, -659, -931, 348, 565, 363, 395, -576, -696, 206, 157, 741, 253, -57, 848, -844, -828, -758, 621, -122, -565, 1162, 834, -754, -840, -883, 464, -1167, -816, 670, 613, 272, -459, -529, -585, -854, -559, 925, 240, 1169, -413, -69, -1001, 513, 571, -426, 359, 319, 612, -510, -580, -707, 391, 896, 354, -1138, 922, 943, 115, -252, 36, 225, -326, 598, -232, 828, -678, 621, 582, 930, -1020, 375, -504, -157, -669, -629, 577, -491, 312, 701, -909, -779, -159, 95, -738, 806, 1109, 64, -398, -15, 1345, -1061, -833, 827, 756, -223, 460, -359, -417, -114, 719, -1035, -180, -515, 124, 428, -975, 993, 533, -1178, 966, -308, 575, -908, -113, -656, -439, -547, -542, -343, 1116, -219, -704, 32, -184, -1065, -794, 784, 247, -762, -59, 35, -98, 387, 100, 593, 748, 564, 413, 453, -306, -254, 7, -255, -889, 814, -766, -481, }; +int32_t transformer_layers_2_0_fn_projection_bias[16] = {194, 93, 543, 448, -911, -445, 195, -40, 634, 876, 754, -1012, 50, 857, -446, -108, }; +int32_t transformer_layers_2_1_norm_weight[16] = {4070, 4054, 4113, 4250, 4054, 4081, 4083, 4181, 3917, 4167, 4225, 4116, 4074, 4125, 4118, 4086, }; +int32_t transformer_layers_2_1_norm_bias[16] = {42, 64, -32, 110, 137, -170, 140, 80, -43, -16, 168, -178, 100, 6, 44, -66, }; +int32_t transformer_layers_2_1_fn_ff1_weight[64] = {-874, -1079, -163, 736, -294, -562, -500, 987, 108, 568, -363, -934, -409, -573, -1048, -366, 277, -902, 259, 602, -45, 983, 366, 811, -394, -751, -662, -964, -400, -240, -967, -749, 166, 599, -648, -608, 618, 609, -928, -602, 56, -852, -818, -343, -398, 671, 187, 523, 906, -568, 602, 1123, 788, 123, 297, 817, -692, -732, -585, 704, 1029, 787, -902, 971, }; +int32_t transformer_layers_2_1_fn_ff1_bias[4] = {267, 470, -574, -399, }; +int32_t transformer_layers_2_1_fn_ff2_weight[64] = {1877, 1625, -992, -1629, -1178, -1784, 4, -1248, 905, 507, 1721, -4, 1659, 420, -527, 1624, -482, 1213, -223, 1858, -200, -1466, -160, 330, 1406, 396, -1566, 1945, -1635, 733, -1490, -1626, 404, -1409, -268, 1645, 1503, 1635, -1849, 1682, -1379, 1453, -465, 666, 593, -578, 1630, -747, -1665, -1625, 436, -1834, -1397, 1706, -1779, 42, -96, -1266, -1052, 1321, -1843, 128, -1722, 1636, }; +int32_t transformer_layers_2_1_fn_ff2_bias[16] = {-473, -1167, 1703, 46, 113, 609, -1347, 396, -303, -1647, -449, -372, 176, -1396, 1388, -966, }; +int32_t transformer_layers_3_0_norm_weight[16] = {4331, 4371, 4459, 4169, 4329, 4301, 4145, 4299, 4294, 4423, 4268, 4098, 4104, 4173, 4155, 3944, }; +int32_t transformer_layers_3_0_norm_bias[16] = {-9, -50, -35, -36, 149, -24, -70, 75, 0, 43, 35, -47, -72, 36, 13, 91, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_Q_H0[64] = {812, -991, -1033, 164, -795, 579, -348, 766, 1070, 162, 149, -447, 298, -560, 489, -455, -458, 1003, 28, 1178, -74, 572, 1063, -531, 288, -656, 52, -852, 268, -340, 554, 363, -261, 534, -24, -513, -736, 186, -265, -656, -131, -1131, 917, -628, -624, -829, 190, 508, -405, 31, 991, -533, 728, 1148, 761, -174, -792, -169, 356, 52, 950, 90, -723, 659, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_Q_H1[64] = {417, 44, -833, 344, 124, 505, 217, 114, -753, -223, 59, 506, 404, 796, 326, -824, 45, -937, -647, -1044, 367, 197, -42, 101, 914, -45, 768, 244, 988, 114, 388, 165, 502, -169, 880, 852, -46, -1099, -445, 420, 903, 508, 945, -334, 729, -605, 8, -69, 950, 0, 277, 227, -321, -251, 636, 393, 441, 75, 269, -270, -713, 662, -916, -227, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_Q_H2[64] = {-625, -372, 134, 911, -887, 1167, -760, 713, -72, 576, 108, -1107, -353, -550, 605, -319, -229, 136, 335, 688, 221, -610, 366, 98, -380, -125, -61, -205, -432, 389, 110, 286, 1046, 550, -314, -243, 626, -699, -397, -950, 806, 553, -298, -1018, 713, 74, 860, 746, 348, -952, -293, 440, 797, -396, -340, -810, 182, 1001, 47, 626, 734, 45, -284, -563, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_Q_H3[64] = {1082, 533, -719, 574, 747, -378, 72, -655, 244, -372, -790, -465, -449, -305, 970, 536, 218, -626, 396, -1083, -413, -840, 679, -186, -650, 865, 721, -883, 882, -1084, 614, -783, -846, 623, 94, 490, 1052, -340, -1226, -483, -16, -382, 717, 491, -780, -723, -848, -613, 345, 648, -319, -34, -72, -347, 989, -457, 377, -805, -29, 734, 973, 791, 861, -764, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_K_H0[64] = {-521, 858, 454, -495, 916, 442, -168, 604, 411, -89, 999, 1, -96, 421, 95, 197, -129, -822, 103, 866, -480, 714, -342, 656, -813, -974, 231, -1000, 783, -582, -154, -1051, -942, -760, 788, -81, -396, -102, 270, 72, 1116, -755, -832, 101, 1, -476, 195, 308, -144, -1003, -811, 813, -853, 1089, -738, -198, -100, 252, 935, 526, 115, 513, 18, 735, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_K_H1[64] = {-918, -29, 832, 896, -778, 564, -148, 730, -237, 85, 834, 823, -836, 820, 575, 638, 661, 140, -132, 629, -1014, 82, -486, -571, 994, -457, 1027, 346, 445, -634, -202, 487, 587, 25, 580, 854, -154, -265, -46, 733, 728, 507, -780, -448, -367, -229, 937, 305, 293, -1028, 445, -37, -608, -867, 512, 240, 230, -243, -412, -676, 930, 645, -19, -602, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_K_H2[64] = {-77, -1040, 122, 316, -714, 687, -1048, -1038, 982, -600, -161, 541, -937, -978, 541, 656, 134, -443, -314, -18, 239, 44, 138, -596, -403, 588, 715, 958, 812, -651, -300, 441, -765, 319, -127, -1081, 385, -228, -45, -405, 134, -655, 949, -141, -850, 513, -829, 466, -601, -76, 280, 217, 155, -150, 1085, 409, -572, 165, 818, 548, -504, -663, -25, -151, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_K_H3[64] = {-822, -987, 500, 498, -380, 118, 296, -875, -428, 525, 721, -948, -96, -220, 952, -534, -1220, -182, -802, -290, 53, 825, -687, -910, 930, -42, -265, -297, 1184, -688, -121, -414, 524, -856, -476, 496, 631, 134, 1193, -132, 486, -166, 691, 1058, 274, -1097, -921, 388, 993, -9, -933, 525, -20, -405, -604, -828, 207, -280, -1049, 406, 872, -153, 134, -7, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_V_H0[64] = {883, 284, 1094, -584, -1043, 1291, -1017, 538, 1181, -826, 537, -743, 1056, -1051, 1065, -347, 947, -152, -36, -529, -394, -532, 143, -447, 819, 768, 375, -626, 107, 1032, -154, 691, 845, 1047, -224, 931, 1173, -396, -983, -455, 16, -1076, -83, 121, -988, 816, -291, 72, -1167, -783, 823, -605, 196, -86, -857, 738, -495, 625, -374, -571, 128, -985, 844, 796, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_V_H1[64] = {-121, -695, 45, -12, 29, 145, 226, 781, -515, 970, 780, 1133, -311, -960, 447, 445, 896, -274, 519, -1066, -274, -909, 923, 193, 246, 733, -661, 1113, -95, -1037, -874, -375, 807, -375, 333, -1144, 290, -112, -464, 1003, -578, -207, 751, 1000, 582, -342, 641, 775, -672, 604, -283, 834, 8, -312, -856, -454, 326, -226, -11, -959, 70, 1098, -225, -777, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_V_H2[64] = {800, -780, 659, 436, 608, 983, -692, -810, 1055, 209, -284, 989, 203, -579, -376, 84, -312, -39, 309, 272, -631, -387, 500, -413, 866, 99, 322, -723, -751, 811, 635, 257, -571, 521, 454, -915, 239, -332, 381, -897, 1141, 265, 813, 83, 105, 243, -431, -597, -886, -987, -1014, -252, -271, -94, -218, -324, -948, 846, 376, -282, -851, 724, -920, 601, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_V_H3[64] = {-539, 136, 319, -1137, 523, -281, -164, 890, -243, -237, -195, 331, 203, 862, -165, 188, 480, -509, 632, -963, 98, -30, -1019, 1024, -732, -486, -843, -480, -458, -729, 528, 728, -402, -495, -697, 1208, 689, -417, 308, -1250, 809, -878, 772, -534, 648, -420, -677, -614, 230, 167, -953, 828, -357, 801, 752, 1045, -868, 305, 622, 1084, -482, 809, 990, 825, }; +int32_t transformer_layers_3_0_fn_projection_weight[256] = {342, 5, -248, -706, 551, -1138, -335, -803, -1059, -259, 550, -227, -212, -948, 336, -347, 724, 0, -258, -610, 104, 853, -1145, 801, 45, -122, -296, -960, 979, -164, 227, -633, 291, -29, 331, -570, -899, 539, 166, -885, 666, -86, 227, -209, 44, -1134, 439, 556, 428, -932, 165, 517, 13, 135, -735, 917, 412, 6, -317, -426, 450, 310, 11, 70, -476, -749, -107, 792, -254, 818, -650, 707, -400, 687, 222, 431, -284, -826, 120, 150, -819, -614, -974, -859, 345, 367, -32, -770, -762, 372, 1068, 352, -201, 500, 166, -592, 665, -217, 231, 366, 564, 47, -268, -925, 1011, -851, 371, 688, -1137, 740, 918, -1041, 971, 42, 914, -1073, -248, 73, 271, -1088, 335, 392, -633, 626, 233, 825, 398, -790, 157, 1155, 441, -655, 356, -920, 699, -145, -525, 955, 180, -23, 97, 817, -420, -964, 1096, -19, -195, -12, 843, 359, -504, 273, 655, -269, 438, 373, -546, -25, 663, -717, -136, -276, 938, 78, -921, -687, 740, -459, -1038, -826, 965, -535, 352, 804, 894, 293, -451, 707, 613, 768, -1007, -1111, 410, -671, -224, 418, 773, 388, -242, -517, 908, 3, -794, 179, -520, 518, -565, -638, -300, 55, 888, 790, 754, -689, -561, 358, 723, -21, -528, 557, 1065, -476, -312, -544, -658, 803, -328, -464, -309, -778, -558, 298, 299, 445, -143, 526, 1111, -49, -762, -721, -224, -158, 529, 1242, -545, -287, -974, -391, 603, 743, -589, -1132, 55, 661, 757, 273, -1212, 1374, 396, -276, -975, -866, -192, -78, 168, -164, }; +int32_t transformer_layers_3_0_fn_projection_bias[16] = {-513, 807, 27, 109, 381, 633, 651, -345, -188, -948, -40, -1119, 69, -344, 610, -562, }; +int32_t transformer_layers_3_1_norm_weight[16] = {4014, 4033, 3946, 3968, 4029, 3985, 4117, 4068, 4052, 4005, 4190, 4268, 4082, 4047, 4155, 3996, }; +int32_t transformer_layers_3_1_norm_bias[16] = {114, -8, 39, -134, -76, -28, -5, -45, -16, 95, 69, -148, 162, 32, 143, -74, }; +int32_t transformer_layers_3_1_fn_ff1_weight[64] = {45, -294, -338, -514, 405, -861, -371, 974, 831, 195, -815, 159, -8, -783, 753, 635, -125, 722, 314, 472, -678, 633, 911, -906, 948, -593, -502, 602, 482, 1182, 18, -479, -804, 954, 458, 242, -300, 779, -731, 989, 108, -1102, -456, -82, 914, -716, 923, 673, -451, 517, -480, -898, -279, 521, -213, 1045, -1039, 728, -1044, -504, 824, -374, -136, 480, }; +int32_t transformer_layers_3_1_fn_ff1_bias[4] = {420, -528, 708, 556, }; +int32_t transformer_layers_3_1_fn_ff2_weight[64] = {-1264, -245, -243, -1258, -1099, -1898, -832, -1786, -91, -535, 338, 531, 99, 47, 1132, -293, 1776, -1641, 1705, -1170, 1156, 1020, -187, -1538, -652, 147, -962, -721, 748, -398, -1670, -84, 1373, 389, -1031, -329, 520, -615, -769, 1458, 1650, 1183, 1178, -137, -775, -271, -1281, -1755, 1191, -1755, -561, -1893, -104, 833, 1300, 1269, 1925, 1248, -225, 316, 1618, -1789, 479, -958, }; +int32_t transformer_layers_3_1_fn_ff2_bias[16] = {170, -517, 322, 1989, -502, 37, -357, 766, 1958, -45, 1673, -1260, 1175, -1481, -1355, 818, }; +int32_t mlp_head_layer_norm_weight[16] = {4039, 4009, 3972, 4135, 3957, 4168, 4133, 4187, 4009, 4196, 4210, 4267, 4051, 4053, 4018, 3976, }; +int32_t mlp_head_layer_norm_bias[16] = {-17, 24, 34, 16, -13, -23, -17, 16, 1, -62, 29, -4, 6, 46, 47, -28, }; +int32_t mlp_head_linear_weight[256] = {-400, 764, -464, -564, 75, -317, 351, -609, -341, -736, 55, 467, -747, 464, -536, 11, -341, 380, 479, -292, 53, 351, -332, 245, 155, -579, 630, 827, 727, 483, -86, 108, 213, 752, -431, 437, 649, -37, 685, 776, 793, -899, 934, 175, 432, -808, -868, 652, 337, 186, -967, -417, 839, -193, -764, 361, -577, 497, 103, 29, 709, 472, 390, -606, -656, -616, -69, -770, 191, -494, 187, 355, 687, -821, -806, 283, 407, -555, -704, -244, 293, -970, -991, 380, 67, 390, 291, 35, 677, 337, -688, -817, 332, 688, 115, -779, 759, 534, 1055, 544, -116, -636, -247, -774, -784, -208, -659, 704, 557, 19, -829, 373, -758, -1026, -1167, 763, 885, -721, -593, -330, 864, 108, -561, 49, 217, -543, 154, -191, 121, -393, 365, 39, 803, 558, -218, 55, 207, 304, -657, -35, -421, 416, 483, 446, 703, 943, 692, -200, -8, 13, 895, -533, 740, -906, -911, -388, 582, -75, -1053, 767, 540, -323, 452, -414, -781, 723, 942, 1029, -920, 937, 884, 1034, 698, 554, -1068, 265, 816, 549, -8, -511, -490, -485, 385, 399, 523, -225, -770, 248, -263, 463, -796, 920, 392, -447, 302, -81, 528, -831, 62, 885, 86, -591, -37, -233, -211, -441, 837, 72, -598, 370, 45, -481, 671, 651, 781, -823, -731, 754, -199, -540, -639, -364, -318, 723, 485, 423, -650, -648, -909, 197, -795, 824, 336, 546, 837, 201, -398, -653, 219, -537, 809, -402, -652, -289, -437, 160, 122, -485, -203, -50, 731, -353, 805, -87, 878, -517, }; +int32_t mlp_head_linear_bias[16] = {-54, 918, 756, -770, 1018, -2, -846, 44, 784, -104, -384, -203, 212, -628, -94, -97, }; + +// Total 14512 parameters \ No newline at end of file diff --git a/sw/applications/trans_versasense/data_cpp/signal.cpp b/sw/applications/trans_versasense/data_cpp/signal.cpp new file mode 100644 index 00000000..0f18a419 --- /dev/null +++ b/sw/applications/trans_versasense/data_cpp/signal.cpp @@ -0,0 +1,5 @@ +#include "stdint-gcc.h" +//int32_t STFT_out[48000] ={15022, 16390, 15545, 7388, 9791, 14435, 15910, 14934, 8889, 9029, 12589, 14368, 13003, 9548, 6344, 9857, 11479, 9461, 8476, -1914, 9560, 7842, 5972, 6077, 3300, 9683, 6443, 5918, 4306, 3938, 8512, 3724, 5741, 5023, 2931, 7275, 3649, 5604, 5232, 3039, 7640, 5448, 5155, 3191, 4248, 7282, 5707, 3886, -1395, 4874, 5392, 5566, 307, 3140, 5102, 5513, 5713, 2597, 3891, 5867, 6802, 5914, 4893, 3388, 6861, 6592, 6289, 5121, 3314, 7333, 4961, 6907, 3998, 3581, 7119, 1288, 7340, 1455, 3347, 6134, -4195, 7221, -649, 2575, 4133, 1906, 6413, 1158, 1360, 639, 3608, 4810, 1664, -862, -2161, 4537, 2477, 1308, -3721, -2389, 5307, 903, -4, -555, -6878, 5826, 1113, -906, 1167, -1543, 5776, 1199, 1884, 1762, 149, 4966, 11, 3047, 1390, -386, 3716, -5616, 2671, -203, 74, 2832, -1861, 1678, -2604, 1596, 1292, 161, 1333, -2384, 1575, -3881, 818, 667, -1833, -390, -1812, 1707, -740, -1805, -3086, -694, 1426, -453, -1980, -790, -124, -648, 361, -3457, 42, 1155, -1014, 791, -13091, -656, 812, 379, 1297, -3332, -2853, -1853, -235, 1618, -420, -3919, -2006, -4401, 1689, 1044, -2273, 275, -565, 1635, 1800, -2376, 792, 2138, 1102, 1969, -2561, 237, 2818, -543, 1624, -310, -1249, 2136, -4400, 904, 920, -3606, 71, -6615, -81, 501, -2837, -1532, -4246, -1490, -2411, -879, -159, -3977, -4394, -7388, -319, -37, -4141, -10580, -1874, -1163, -1711, -3155, -3770, -1572, -3881, -5011, -826, -3183, -2875, -10316, -4701, 956, -4547, -3369, -6280, -4795, 1932, -4555, -2151, -4832, -7088, 2278, -4062, -1050, -4362, -9139, 2188, -5250, -628, -4430, -6307, 1816, -7122, -665, -4281, -3722, 1238, -4499, -856, -3217, -2790, 465, -2960, -1433, -2147, -3077, -434, -3195, -2783, -1981, -2941, -1212, -5049, -5353, -3217, -1690, -1498, -5065, -11050, -3855, -942, -1402, -2999, -6061, -1383, -1013, -1582, -2083, -3332, -275, -1903, -2508, -2036, -2211, -841, -4324, -4298, -2542, -2304, -3922, -6944, -6426, -3393, -3771, -7282, -2375, -9088, -4619, -7090, -2152, -895, -13285, -6205, -9679, -953, -1090, -7111, -6943, -7333, -1160, -2657, -5178, -6399, -4361, -2748, -5439, -4401, -5331, -2684, -7849, -7725, -4121, -4253, -2323, -6348, -6897, -3765, -3744, -2985, -4222, -5344, -3340, -3952, -4292, -6316, -3943, -3635, -5099, -5501, -6581, -3258, -5395, -8104, -6121, -2890, -3694, -8349, -8938, -7267, -2405, -5253, -6570, -6183, -8317, -3901, -6728, -6160, -6023, -6129, -6730, -5623, -7081, -8065, -5117, -7618, -3654, -5993, -12612, -5517, -6372, -2633, -5248, -9541, -6669, -4810, -2844, -6076, -6778, -7488, -5029, -4130, -6289, -5302, -5846, -9132, -5152, -5290, -5980, -4321, -6877, -5027, -5471, -8488, -3290, 10948, 5340, 9881, -583, -1529, 10281, 3184, 9400, 6255, -1363, 7983, 1790, 7839, 8319, -1213, 2985, 5766, 4578, 8716, -1201, 5806, 5972, -7468, 8093, 239, 7278, 3992, 2631, 6914, 2658, 7007, 3013, 4259, 6183, 4335, 5657, 4920, 4879, 6103, 5026, 5172, 5662, 5285, 5893, 4883, 5509, 5524, 5613, 5378, 4402, 4184, 4538, 5872, 4553, 4309, 3084, 2519, 6053, 4412, 4533, 5541, 2182, 5884, 5410, 4304, 6269, 3345, 4957, 5653, 3045, 5565, 3276, 3046, 4418, 1028, 4272, 2407, 595, 1213, 734, 3636, 1612, -1021, -9, 1479, 3416, 1031, -324, 1364, 1998, 3255, 94, 588, 973, 1467, 3470, -317, 408, -256, -1566, 3966, 176, -148, -1555, -5910, 4403, -381, 149, -3399, -1218, 4406, -3162, 1043, -3706, -2034, 3699, -6969, 1255, 13, -2967, 2095, -928, 675, 2541, -309, -742, 1059, -55, 3772, 276, -5152, 1483, -1167, 3918, -918, -2310, 600, -2456, 3234, -4253, -629, -1699, -803, 2143, -8360, -748, -4480, 187, 920, -4510, -2796, -5722, -657, -732, -2852, -6555, -8562, -5101, -1617, -1578, -3238, -2751, -2692, -76, -473, -1770, -1006, 672, 1164, 146, -1307, -1054, 1972, 1728, -76, -1108, -747, 2401, 1777, -1105, -617, 737, 2292, 1237, -496, 491, 1494, 1811, -216, 1202, 1623, 1157, 1162, -1153, 1656, 2217, -332, 552, 898, 776, 2074, -3098, -150, 2083, -258, 1096, -4664, -1276, 2076, 269, -817, -3732, -2660, 1252, 403, -3595, -2332, -3627, 139, -804, -5568, -652, -4610, -491, -4906, -5112, 12, -5653, -40, -5243, -4091, -766, -6220, 444, -1562, -3606, -3645, -7870, -40, -1055, -4503, -10695, -8347, -1875, -1973, -6634, -7025, -5321, -3534, -3721, -6422, -10405, -3470, -2072, -5833, -8296, -6307, -2409, -1348, -8634, -8763, -3250, -1734, -1712, -13134, -3935, -2113, -1132, -2943, -10088, -2782, -1927, -552, -3587, -7851, -3207, -2420, -210, -2134, -5907, -4824, -3031, -288, -1175, -4432, -6584, -2800, -678, -1292, -3739, -5705, -2132, -1039, -2508, -3901, -3854, -1624, -1437, -5728, -4955, -2528, -1266, -2274, -7524, -5831, -2232, -1272, -3370, -2624, -5012, -3195, -2200, -3783, -947, -4277, -4836, -4802, -3420, -488, -3943, -4317, -5543, -2886, -691, -4040, -4122, -3597, -2892, -1142, -4925, -6452, -3758, -4002, -1519, -5252, -10060, -5054, -4808, -1904, -3326, -4930, -4535, -2874, -2275, -1642, -3491, -3392, -1585, -2128, -765, -3125, -2599, -1366, -1867, -687, -3101, -1848, -2227, -2471, -1521, -3092, -1584, -4873, -5110, -4002, -3221, -2450, -8948, -5746, -11796, -3989, -5450, -4673, -2300, -3014, -6275, -6993, -3629, -1265, -1233, -13060, -3994, -3325, -1129, -1401, -6473, -2795, -2634, -856, -3122, -4984, -1852, -2143, -668, -4531, -4954, -1543, -2277, -1158, -4444, 8135, 6088, 8626, -4024, 9938, 7329, 6317, 8147, 3034, 9253, 4904, 6099, 7090, 5534, 7062, 4788, 5168, 5821, 5756, 2868, 6323, 4576, 3219, 3312, 1833, 6494, 3735, 3133, -3194, 4473, 5760, 1781, 5247, 3503, 5033, 4322, 154, 5491, 4139, 2895, 2112, -1883, 5106, 3344, 1160, 567, -8604, 5398, 2834, 5248, 2441, -1097, 6168, 3530, 5936, 4900, 904, 6690, 4608, 5104, 6129, 2446, 6590, 5040, 5192, 6005, 3385, 5551, 4266, 6075, 4500, 3096, 3111, 1873, 6379, 1400, 1015, -337, -2432, 6535, -3148, -6312, 1153, -3379, 6387, -4178, -2431, 1960, -3097, 5323, -2846, -282, 1735, -1790, 2714, -1477, 1123, 1114, 483, -5178, -288, 2408, 349, 2279, -962, 828, 2867, -310, 3205, 602, 1651, 2089, 248, 3324, 1195, 1919, -836, 1723, 2724, 2721, 1435, -8160, 2498, 1506, 3795, -83, -1480, 2126, 141, 3702, -2304, -1676, 632, -186, 2139, -1688, -2840, -452, 758, 749, -1085, -1050, 84, 1955, 2587, -1448, -667, 47, 2776, 3314, -1334, -1973, -584, 3074, 2871, -1128, -4037, -927, 2914, 2029, -1831, -4223, -893, 2430, 1750, -3735, -1903, -725, 1721, 2124, -4438, 91, -814, 695, 2326, -1846, 1159, -718, -1112, 1779, -605, 1229, 953, -4285, 161, -1077, 226, 2278, -2549, -3196, -1597, -1233, 2448, -61, -10037, 1326, -207, 1631, 1238, -5459, 2800, 1173, 597, 1719, -2662, 2475, 1064, 234, 1395, -1008, 22, -931, 85, 225, -520, -10125, -1692, -101, -2013, -1056, -3239, -169, -365, -5623, -1918, -2721, -886, -713, -4148, -1070, -4144, -4883, -992, -3366, -504, -5371, -7334, -1451, -4299, -1722, -5860, -5572, -2058, -2407, -3307, -5420, -9669, -1902, -626, -800, -3278, -4000, -1470, -465, 514, -2492, -1965, -1758, -2323, 435, -3628, -1768, -2921, -5922, -956, -9229, -2309, -4942, -927, -4084, -4407, -2502, -9038, 836, -8231, -2095, -2284, -5389, 1066, -5365, -1906, -1985, -2756, 264, -3891, -3017, -2226, -2262, -1447, -4557, -4960, -3502, -3466, -3976, -11280, -5981, -3511, -5119, -4299, -3848, -5230, -2657, -3228, -2919, -1482, -4701, -3847, -1903, -2750, -1004, -4962, -9136, -1535, -4156, -1487, -5918, -5496, -1578, -9790, -2332, -7666, -4300, -1746, -6635, -2932, -11718, -5430, -1928, -3956, -3045, -13570, -7603, -2016, -3785, -2822, -9656, -7021, -2159, -4384, -2470, -5004, -4553, -2859, -3625, -2045, -2525, -3046, -5049, -2807, -1748, -1425, -2589, -10651, -3267, -2273, -1223, -2394, -5327, -4768, -4832, -1712, -1883, -4089, -3759, -6611, -2592, -1631, -4451, -2098, -3778, -2317, -1688, -4707, -1511, -4370, -1104, -1674, -5347, -1880, -7616, -511, -1990, -8962, -3392, -5659, -637, -3117, -7329, -6851, -5500, -1134, -4374, -4297, -12628, -9453, -1507, -3914, -3602, -7923, -7498, -4224, -5554, -4353, -4133, -2129, -3878, -7270, -2473, -2452, -1737, -3507, -7586, -2008, -2512, -2831, -2846, -5254, -3025, -3418, -5986, -2821, -3714, -5611, -3744, -7985, -2808, -3010, -13840, -2935, -6763, -2277, -2991, -6283, -2459, -7017, -2183, -3789, -3468, -3366, -5831, -3055, -6182, -2980, -5755, -4109, -5251, -13347, -4226, -3284, -3689, -9905, -6728, -7062, -1040, -4341, -6515, -5290, -10547, -88, -4173, -4287, -5037, -9538, 15, -3219, -3665, -4580, -5533, -670, -3366, -3725, -4293, -3755, -2433, -5426, -3616, -4979, -3342, -5897, -10483, -3418, -6809, -4226, -5644, -6907, -3888, -7436, -6950, -4348, -6768, -4698, -5425, -7290, -5661, -11547, -4637, -4024, -4705, -7820, -7789, -5294, -3717, -3606, -4001, -4241, -7811, -4602, -2791, -2423, -2364, -6255, -6510, -1775, -2276, -1164, -5607, -6340, -1017, -3077, -580, -7866, -4238, -901, -4310, -652, -11726, -3115, -1541, -5083, -1309, -10766, -3063, -2977, -5072, -2160, -5334, -3219, -5153, -4673, -2549, -2761, -2681, -5813, -4537, -2539, -1887, -2418, -4519, -5214, -2776, -1955, -2947, -4445, -6446, -3623, -2344, -4213, -5961, -6591, -5118, -2949, -6336, -7215, -6457, -7136, -4560, -9194, -6317, -7439, -9810, -7339, -9647, -7399, -9089, -8084, -5084, -8196, -10603, -8142, -4773, -4006, -6529, -5264, -6082, -3144, -4962, -5245, -3482, -4467, -2991, -7160, -4667, -3534, -3485, -4536, -5624, -4729, -5032, -3222, -8808, -4191, -5173, -6219, -3555, -16024, -4330, -5943, -5030, -4186, -8660, -6684, -6669, -4314, -4229, -3671, -7971, -6376, -4176, -3187, -1670, -3458, -5898, -4030, -2731, -1236, -1895, -5622, -3478, -3836, -1952, -1883, -5111, -2565, -7553, -3555, -3115, -4399, -1740, -7056, -5274, -5062, -4108, -1482, -5186, -5586, -5718, -5093, -2065, -5623, -4664, -4970, -9301, -3493, -7925, -3350, -3927, -8207, -4928, -13647, -2286, -3205, -5647, -5288, -11389, -1695, -3351, -5048, -5436, -10277, -1476, -4273, -3759, -5299, -11084, -1462, -3966, -2469, -4478, -12156, -1510, -2701, -2149, -3377, -9283, -1412, -2234, -3086, -2832, -6406, -1068, -2636, -6186, -3387, -5200, -747, -3812, -10087, -5553, -4196, -911, -5894, -5260, -12137, -2698, -2137, -8129, -4371, -9214, -1973, -5654, -7221, -4905, -7118, -2635, -11761, -6359, -5793, -7149, -5285, -7383, -5904, -6008, -8398, -8178, -8107, -5657, -6536, -9448, -5544, -5874, -6363, -8914, -8639, -5672, -4566, -8413, -10223, -8665, -9040, -4611, -8140, -6790, -7995, -9845, -5443, -6600, -5701, -5196, -5562, -6064, -6901, -5391, -3432, -4047, -5589, -10634, -4751, -2899, -3579, -5435, -9912, -4255, -3442, -3902, -5816, -6228, -4453, -4620, -5031, -6518, -5566, -5374, -5341, -6901, -8805, -6416, -7360, -5643, -8714, -17696, -8138, -11290, -6006, -9255, -12064, -8799, -7964, -6673, -10575, -9542, -7865, -5755, -8615, -10922, -5114, -7102, -4998, -11781, -6158, -3484, -4628, -2421, -3126, -2497, -6789, -5250, -4794, -4449, -4410, -7477, -9881, -6436, -5064, -3607, -3449, -4608, -4046, -5613, -2139, -2217, -2871, -2510, -6822, -1828, -2235, -3843, -2185, -5537, -2152, -3064, -6329, -3289, -4432, -2550, -4718, -4122, -6236, -4556, -2730, -8599, -3320, -6537, -4686, -2432, -7789, -4202, -4618, -4608, -2175, -3777, -6026, -3566, -6205, -2668, -2263, -7801, -2576, -13093, -4308, -2029, -9251, -1785, -4928, -7375, -3049, -8052, -1709, -2944, -9674, -6259, -5386, -2760, -2434, -9137, -6066, -4239, -5655, -2581, -6472, -3521, -4001, -10908, -3366, -5255, -3280, -3305, -4920, -6014, -6907, -4092, -2406, -3021, -9081, -10022, -4709, -2289, -2635, -3189, -5011, -4448, -3296, -3604, -1475, -4570, -4321, -5646, -6025, -1196, -5631, -5608, -5570, -5345, -1726, -3948, -8925, -3247, -3919, -2528, -2846, -4629, -2085, -3725, -3203, -2884, -1340, -1892, -3501, -3959, -2956, 213, -2570, -3436, -5344, -3247, 385, -3672, -4179, -7922, -4596, -782, -4517, -4623, -10663, -5247, -3613, -5710, -4269, -7357, -3805, -8204, -7537, -4200, -4774, -3261, -3386, -9210, -3521, -3260, -4029, -1266, -10245, -2801, -2777, -6779, -618, -8283, -3242, -3408, -5810, -806, -5770, -5696, -4816, -2843, -1404, -3474, -12002, -4835, -2324, -2230, -1947, -5336, -3635, -4445, -3446, -1253, -3757, -2754, -9328, -5841, -1357, -3536, -2539, -2725, -13317, -2351, -3881, -3123, -1220, -7147, -4485, -4898, -4220, -1221, -5824, -7862, -8392, -5317, -2285, -6768, -11502, -7970, -6846, -4558, -7862, -6879, -3544, -8386, -8920, -5639, -3193, -1802, -5582, -16426, -4403, -1478, -1162, -3322, -11213, -4289, -1030, -1320, -2236, -7203, -4753, -1637, -2259, -2066, -5910, -5082, -3287, -4154, -2592, -7050, -4526, -5607, -7379, -3425, -5504, -4246, -5552, -9774, -4065, -2373, -5163, -4380, -8617, -4242, -1009, -7160, -3989, -7901, -3963, -876, -8081, -4222, -6692, -3726, -1778, -6391, -4630, -5593, -4172, -3764, -4734, -4670, -5500, -5797, -7407, -4288, -4354, -7442, -8769, -8786, -5317, -4301, -11498, -6984, -5990, -8221, -4744, -5009, -4564, -5757, -9903, -4512, -3263, -3106, -7633, -8076, -3552, -3447, -2234, -11771, -6541, -3325, -5117, -1930, -12667, -4415, -4296, -5804, -2117, -11981, -2877, -7575, -5708, -2684, -12463, -2311, -10012, -7172, -3786, -17520, -2856, -5074, -5329, -5509, -11698, -4665, -4276, -3556, -6559, -7320, -4445, -5423, -3139, -6032, -4982, -2432, -6815, -3515, -5233, -3675, -1834, -5983, -4451, -4885, -3100, -2452, -6053, -5609, -4813, -3412, -3794, -7398, -6187, -4484, -5126, -5070, -8555, -5637, -4332, -8942, -6059, -7890, -4903, -4780, -8156, -5664, -6966, -5044, -5826, -7445, -4759, -6094, -6121, -7366, -8944, -5258, -4845, -7107, -8586, -12286, -7313, -4354, -6859, -8099, -16158, -6273, -5653, -6242, -7236, -8803, -5182, -11020, -6046, -6956, -5479, -6656, -1536, -2950, -4414, -6079, -3604, -1428, -2411, -7541, -5139, -1848, -1324, -2361, -9913, -4836, -1486, -1298, -2802, -4591, -3959, -2406, -1573, -3744, -2758, -1712, -4194, -2495, -5418, -2422, -42, -5054, -4591, -9189, -3442, 459, -3980, -9195, -8925, -4492, -230, -2899, -11097, -5822, -3678, -2121, -2792, -12465, -5374, -3936, -5487, -3382, -10965, -6491, -4860, -13201, -3897, -6980, -8176, -4223, -4575, -4537, -5943, -7331, -4482, -2722, -5484, -5427, -5826, -5564, -2821, -5674, -5105, -4386, -3766, -4394, -4608, -5164, -2664, -1603, -5443, -3593, -4710, -1555, -639, -4933, -2796, -3042, -1221, -1098, -6719, -1430, -1246, -1225, -3395, -11421, -447, -162, -1211, -8133, -7246, -627, 167, -1171, -4891, -10083, -2175, -139, -1219, -3020, -7058, -4571, -1084, -1635, -2768, -4466, -3412, -2470, -2518, -4109, -4079, -1188, -3285, -3544, -6015, -4011, 137, -3802, -3376, -4381, -3608, 518, -4965, -1353, -3572, -3037, -126, -7139, 168, -4533, -3447, -1934, -13471, 690, -7204, -6408, -3553, -5680, 417, -9220, -8269, -2607, -3936, -222, -8050, -5319, -2079, -4119, -761, -4771, -4550, -1746, -4482, -1413, -3437, -3790, -1023, -3611, -2864, -3832, -3177, -620, -2645, -4979, -5815, -2643, -652, -2136, -4731, -10493, -2648, -695, -2344, -4163, -10081, -3430, -880, -3418, -4701, -6001, -2792, -1648, -5340, -4910, -4263, -1434, -2959, -6768, -3486, -3360, -1291, -4215, -5259, -2557, -2870, -2715, -5327, -4127, -2717, -2591, -6908, -7188, -3928, -3565, -2566, -9345, -9250, -4424, -3837, -3153, -6026, -6089, -5596, -3329, -4823, -4115, -4029, -5332, -3093, -7403, -2244, -3228, -3730, -3423, -6394, -1321, -3169, -3120, -4030, -4822, -1391, -3856, -3352, -4019, -4452, -2389, -6223, -4162, -3507, -5531, -3885, -11595, -5537, -3763, -9584, -4454, -7117, -6049, -5539, -11492, -4732, -8537, -4404, -6531, -8904, -4400, -6582, -2673, -5208, -8826, -2727, -2659, -1747, -5819, -5655, -2061, -1277, -1705, -9453, -4239, -3059, -1187, -2241, -10353, -4868, -6682, -1802, -3158, -5447, -8286, -8509, -2649, -4713, -3619, -12757, -5460, -3539, -4764, -3014, -12636, -4901, -4068, -3348, -2840, -8742, -5394, -4270, -3392, -2768, -4667, -6856, -5074, -5305, -2984, -3324, -7579, -6296, -6783, -3459, -3532, -4949, -5979, -5328, -4029, -5532, -2721, -5319, -5970, -4667, -14849, -1369, -6133, -10401, -5585, -6837, -790, -12638, -8761, -7334, -5777, -937, -6287, -6741, -9955, -8368, -1808, -3420, -7326, -12278, -8497, -3363, -2912, -8770, -16695, -5559, -4951, -4095, -8610, -13416, -4846, -5025, -7435, -7926, -11937, -3580, -4428, -9001, -6381, -11803, -2464, -4303, -6744, -4580, -13182, -2617, -4979, -6343, -3508, -14602, -4359, -6610, -6657, -3260, -15423, -8127, -8838, -6860, -3720, -14890, -7968, -8299, -6477, -4389, -9173, -6467, -6679, -6249, -4327, -7138, -6132, -6455, -6392, 992, 7886, 7836, 5707, 2952, 5763, 7674, 7512, 5744, 3131, 7257, 7047, 6697, 5594, 2840, 6944, 6137, 5861, 5029, 1656, 6387, 5254, 5171, 4191, 1669, 6716, 4499, 4157, 3252, 2364, 6445, 3756, 2809, 2540, 1949, 4670, 3162, 2233, 3092, 910, 3710, 3344, 2679, 4147, 410, 5517, 4146, 3327, 4671, 452, 6178, 4380, 3727, 4620, 2149, 6053, 3711, 3627, 3805, 4693, 5401, 2486, 3007, 1193, 6237, 3584, 1501, 2138, -2809, 6624, -1377, 1312, 1430, 1631, 5874, -740, 1336, 1335, 2278, 3788, 1232, 544, 1760, 1376, -797, 984, -1787, 1610, 858, -4456, -16, -4421, 402, 1445, -841, -510, -1344, -1367, 1905, -616, -34, -459, -2302, 2253, -1120, 504, -1942, -2912, 2376, -1730, 720, -3838, -5891, 1875, -2627, 388, -695, -5800, 806, -4711, -673, 741, -1852, 50, -11015, -2310, 1308, -789, -233, -8245, -3429, 1893, -426, -743, -6045, -3855, 2501, -212, -1327, -3983, -5484, 2535, -521, -2006, -2393, -6745, 1562, -1584, -3385, -1364, -4140, -858, -3071, -6674, -598, -3454, -2410, -4007, -10510, -171, -4255, -203, -4907, -4974, -243, -6219, 582, -5832, -3180, -1018, -8783, -28, -4707, -1608, -2965, -5414, -2510, -3392, -581, -7330, -3019, -3582, -2700, -677, -6955, -1847, 35, -2277, -1773, -3219, -1611, 1252, -2376, -2733, -1083, -2530, 694, -4002, -2387, -716, -5145, -2053, -9433, -1461, -2429, -5676, -2719, -10283, -1021, -1831, -3878, -761, -5449, -1362, 475, -3664, -1287, -2617, -1862, 915, -3556, -2383, -2085, -1446, 149, -2817, -670, -4159, -375, -472, -2112, 394, -5643, 323, -35, -1757, 248, -2140, 192, 320, -1983, -1029, -1086, -983, -22, -2932, -3865, -1238, -3894, -1474, -4558, -9183, -1959, -7920, -3368, -5977, -7833, -2767, -2841, -1495, -4291, -6174, -3929, -1107, -176, -2147, -2464, -4110, -851, -181, -1039, -299, -2417, -2003, -1071, -1016, 578, -2123, -5311, -1919, -1861, 617, -3951, -4696, -2089, -1896, 235, -9294, -2333, -2652, -733, -288, -6439, -1996, -4479, -339, -1155, -4501, -2973, -7503, -1126, -2682, -2749, -3114, -5895, -3277, -4758, -822, -1788, -4046, -8511, -7487, 437, -1922, -3277, -7813, -5958, 551, -5066, -3319, -4848, -2147, -756, -6046, -3552, -4780, 106, -3455, -2730, -2710, -5057, 1332, -4293, -3013, -1523, -5034, 1646, -4528, -6230, -887, -6935, 891, -6414, -9181, -812, -4640, -1659, -7119, -6210, -1117, -2365, -14029, -5370, -6259, -1621, -1609, -3314, -5115, -7142, -1958, -1108, -2256, -7398, -7089, -1758, -994, -2106, -4836, -5489, -1371, -1982, -2098, -2545, -3927, -1402, -4561, -3066, -2233, -3486, -2416, -7078, -4875, -3155, -4911, -5524, -4643, -4758, -5020, -7861, -12217, -3992, -3582, -9911, -4628, -6038, -4259, -2813, -6597, -3333, -5671, 4431, 6956, 4647, 3404, 3214, 3330, 6394, 4445, 4636, 4919, -2018, 4626, 3869, 5670, 6749, 174, 1203, 3186, 5540, 7498, 1979, -3313, 3158, 4216, 7309, 89, 504, 3878, 1072, 6525, -7332, 2160, 4371, 83, 5384, -1885, 2720, 4121, 2851, 3793, -2387, 2886, 3245, 3140, 2596, -131, 3575, 2615, 2064, 2369, 2750, 4385, 2649, 2541, 1643, 4474, 4335, 2717, 3876, 2216, 5069, 3125, 2641, 4261, 3761, 4424, 1483, 2251, 3750, 4483, 2485, 1454, 1283, 2464, 4432, 1067, 1443, 85, 569, 3826, 2180, 401, 47, -1340, 3066, 2822, -1339, 182, -2231, 2563, 2587, -1558, -920, -2301, 1920, 1218, 336, -3313, -1700, 683, -1842, 1950, -4908, -599, -386, -1289, 2887, -5087, -836, 463, 149, 3227, -887, -4338, 1261, -594, 3167, 1502, -1816, 1038, -2955, 2939, 2548, 680, 327, -2472, 2629, 2745, 1043, 51, -1627, 2053, 2212, 948, -302, -2321, 933, 785, 1074, -1594, -3706, -838, -1956, 601, -3409, -3084, -3032, -6554, -656, -3464, -1611, -4914, -7763, -1656, -4244, -1174, -4880, -6737, -1234, -2011, -1233, -4355, -3618, -340, 526, 47, -5364, -1510, -318, 1544, 1463, -7198, -750, -1860, 1727, 1828, -5679, -1416, -7268, 1307, 931, -6528, -3862, -4626, 11, -1518, -4014, -6626, -1510, -2411, -4306, -437, -6696, -397, -3961, -3760, 1004, -6606, -513, -3297, -2746, 1013, -5990, -1930, -2778, -663, -172, -11236, -2111, -3063, 473, -2169, -4851, -144, -4907, 464, -3009, -1982, 781, -8275, -439, -1982, -1424, 776, -9936, -1390, -912, -1763, 71, -6078, -531, -87, -1362, -1265, -4817, 709, 402, -298, -2933, -7191, 1147, 411, 464, -3762, -5416, 641, -36, 858, -3242, -3244, -878, -725, 974, -2772, -4068, -3062, -1369, 786, -3532, -4200, -3880, -2030, 165, -5898, -1956, -3455, -3426, -1106, -5290, -1439, -3346, -6797, -3430, -3721, -2194, -3895, -5475, -7296, -2447, -2540, -5088, -2472, -7216, -1279, -1260, -6922, -1288, -5455, -683, -66, -6827, -1382, -4648, -376, 376, -4007, -2543, -4856, -190, 93, -2386, -3378, -5880, -477, -515, -2070, -2682, -4918, -1273, -1178, -3491, -2129, -3087, -1615, -2334, -12014, -1948, -2105, -1411, -4243, -2991, -1997, -1792, -1734, -8766, -470, -2496, -1876, -2784, -5016, 104, -3838, -1877, -4591, -1105, -731, -6301, -1746, -9082, 199, -3223, -8534, -2817, -6844, -58, -8548, -7309, -10561, -3983, -1936, -10120, -5995, -3376, -3673, -4603, -20985, -4612, -1454, -2665, -1776, -7189, -3343, -2512, -930, -299, -4932, -3211, -7404, -583, -305, -4692, -4774, -3010, -1973, -1335, -5472, -5595, -369, -4883, -2031, -6404, -3584, 783, -3635, -1048, -6310, -2819, 852, -2206, -154, -5323, -1834, -93, -1718, 30, -4480, -626, -1947, -1728, -541, 4174, 4649, 8112, 4717, 10466, 5280, 6423, 7948, 6862, 10222, 6501, 8002, 7664, 8295, 9563, 6769, 8408, 7456, 8429, 8561, 6127, 7730, 6905, 7644, 7034, 5048, 5903, 5514, 5941, 4594, 4185, 2543, 3305, 2660, 982, 3149, -888, 1426, -2564, -1865, 1011, 1471, 735, 1166, -1159, -5527, 2616, -306, 1632, 314, -106, 3024, -43, -844, 734, 2930, 3341, 2467, -2478, 2614, 3788, 3719, 3345, 2597, 4789, 2812, 3667, 2827, 4269, 5884, -511, 3317, 2219, 4869, 6290, 1704, 3473, 2860, 4963, 6365, 3274, 3591, 3308, 4690, 6044, 2644, 2936, 2953, 4056, 5092, -557, 1584, 1968, 2995, 3317, -4360, 179, 891, 1167, 815, 452, -215, 513, -2135, 86, 1319, 299, 907, -1288, 765, 870, 155, 1373, 1199, 403, 686, -2036, 1276, 2295, -1164, 1208, -6659, 115, 2607, -2310, 701, -1110, -2708, 2307, -1258, -1150, -328, -2530, 1467, -1410, -736, -1907, -296, 883, -2029, -52, -5263, 495, 1564, 553, -1306, -5543, 797, 2156, 1991, -3684, -3848, 1128, 1951, 1912, -3782, -1034, 1249, 1359, 895, -5389, 388, 952, 1349, 218, -6377, 657, 576, 1456, 759, -2880, 335, 729, 494, 1309, -1657, 478, 1458, -2099, 866, -473, 1422, 2292, -1460, -620, -50, 1993, 2768, -94, -1113, -2239, 1399, 2583, -751, -410, -4992, -1336, 1481, -2172, -510, -476, -3462, -839, -1211, -841, -618, -17, -2638, -555, 273, -3499, 496, -876, -1009, 1572, -1315, -297, 196, -2170, 2027, -228, -1264, 454, -3745, 1439, -1464, -2322, 81, -4717, -381, -5409, -4077, -907, -4231, -3575, -11310, -5445, -2337, -2910, -8052, -6921, -5310, -4192, -1845, -13976, -4606, -4917, -4348, -2024, -8954, -3415, -5146, -1546, -3490, -8070, -3267, -5532, -149, -4645, -5821, -3369, -4589, 86, -4673, -3846, -4033, -4557, -413, -2522, -2014, -7275, -7793, -1331, -262, -1161, -6355, -4242, -2505, 707, -1661, -2821, -1515, -4093, 563, -3620, -1675, -1146, -6469, -473, -6858, -1510, -2831, -7219, -1769, -5947, -1635, -7801, -5863, -2385, -4331, -2407, -5390, -5883, -3613, -4909, -5852, -2773, -7221, -9159, -8695, -6468, -1251, -7432, -3003, -8598, -3055, -955, -3342, -265, -7250, -2386, -2007, -710, 612, -7422, -1428, -3766, 347, 364, -4521, -496, -3947, -144, -697, -1507, -547, -3434, -2881, -2096, 292, -1598, -3256, -5414, -2594, 965, -3239, -3247, -2169, -2317, 652, -4359, -2603, -1742, -3337, -557, -4459, -1171, -2509, -10715, -2786, -4692, -227, -3927, -3425, -7108, -6957, -226, -4770, -818, -4731, -6172, -1041, -2897, -248, -2449, -1775, -2384, -1771, -697, -2684, -90, -5076, -1110, -1802, -6855, 99, -9796, -337, -4902, -5453, -1061, -2976, -36, -5415, -2246, -3853, -1317, -549, -918, -1705, -3747, -2112, -4001, -3034, -4635, -4213, -1260, -3727, -2473, -2438, -6982, -367, -3185, -1593, -982, -4534, 264, -2079, -1182, -222, -2747, 483, -2456, -1750, 35, -2512, 388, -5304, -3164, -88, -2206, 140, -4527, -3982, -532, -1428, -144, -2873, -3008, -1346, -1345, -365, -3984, -1784, -2639, -2397, -697, -6265, -1517, -3277, -2307, -1651, -4134, -2354, -1553, -288, -3640, -3791, -3550, 65, 652, -3861, -4141, -3568, 950, 228, -2067, -2900, -2781, 1302, -1954, -1289, -2053, -2108, 1342, -6273, -1345, -1988, -2096, 1204, -4779, -1906, -1653, -3694, 637, -5027, -1988, 82, -10105, -1492, -629, -486, 2110, -1648, -3002, 1882, 1459, 3378, 657, 1358, 2660, 2603, 3623, 1185, 2820, 2130, 2627, 2740, 637, 2565, 365, 1434, 560, -235, 841, -2650, -1067, -3141, -370, -1308, -5821, -3575, -5607, 47, -1692, -6442, -2726, -5532, -168, -2738, -4904, -1480, -7712, -1903, -4340, -3564, -672, -11754, -6389, -3800, -3243, -417, -5924, -5494, -2953, -3758, -816, -4087, -4188, -2255, -4726, -1998, -3790, -4542, -1674, -5694, -3952, -5810, -5381, -1442, -6169, -5589, -7299, -5101, -1910, -5950, -4971, -2468, -4109, -3935, -6223, -3510, -1109, -4084, -12610, -7526, -2798, -1748, -4875, -2691, -6655, -3009, -5180, -3571, -299, -4560, -3222, -5909, -1531, 345, -3402, -2278, -3277, -663, -382, -2929, -1166, -3916, -1028, -2305, -2012, -494, -7351, -2594, -3089, -610, -250, -8475, -5069, -3070, -48, -487, -5563, -7464, -4932, -943, -1479, -3054, -7030, -5903, -3367, -3876, -1946, -5475, -4377, -2021, -7366, -2306, -4082, -4492, -563, -4662, -4219, -2805, -3707, -1053, -3735, -9693, -2621, -1912, -4055, -3845, -8011, -3894, -912, -8948, -3433, -5298, -6418, -661, -3656, -2446, -5489, -10928, -1071, -2590, -1764, -7680, -8049, -2208, -2121, -1662, -6862, -3920, -4199, -1926, -2121, -4885, -2611, -7311, -2486, -3145, -4183, -2502, -6901, -3554, -5151, -3631, -2937, -4649, -4186, -7162, -2699, -4051, -3461, -4742, -5468, -2078, -6172, -2738, -5050, -5448, -2188, -5573, -2471, -5332, -7820, -3023, -4144, -2849, -8141, -9531, -4575, -4189, -3847, -6521, -7025, -4941, -5784, -4681, -3328, -4626, -2908, -10587, -4944, -2513, -3434, -1903, -8857, -6083, -3079, -3631, -2184, -6619, -7385, -4605, -4939, -3503, -7520, -4832, -5781, -5437, -4992, -16740, -3000, -5635, -4065, -5684, -7742, -2005, -6065, -2885, -6214, -5278, -1464, -7700, -2155, -7036, -4340, -1287, -9068, -1918, -8916, -4106, -1409, -10187, -2433, -8882, -4859, -1646, -9359, -4090, -7672, -7479, -1849, -6429, -6578, -10293, -11893, -2146, -5860, -5821, -9577, -9527, -2889, -7698, -5002, -5400, -10978, -4290, -10471, -5225, -4621, -9688, -5863, -8450, -5468, -6029, -7785, -7006, -10558, -5211, -9458, -7926, -8354, -10826, -5036, -5769, -9321, -8951, -3863, -401, -4910, -2323, -2099, -3046, -1484, -5082, -3636, -4300, -1990, -3768, -3293, -6039, -2892, -1020, -3385, -4360, -10286, -1381, -255, -1195, -8361, -4200, -844, 278, 114, -2769, -1775, -811, 435, 634, -894, -1206, -1477, -8, 381, -142, -2189, -3598, -1427, -717, 335, -4704, -8123, -5223, -2835, 417, -4946, -7597, -6079, -6358, -351, -3272, -5801, -2029, -7051, -2202, -2890, -3212, -1142, -3754, -3082, -3662, -1664, -2077, -2099, -2011, -3470, -1050, -5634, -1766, -1891, -1794, -940, -8934, -2247, -2760, -858, -1262, -3438, -2825, -4027, -444, -2366, -964, -2952, -3780, -62, -4754, 1092, -744, -1225, 785, -3777, 2671, 1289, 547, 1815, -1385, 3401, 2002, 1037, 2102, -919, 3093, 1419, 302, 1159, -2604, 1611, -615, -1667, -1151, -6590, -1305, -4651, -4417, -2579, -2497, -5931, -3787, -3795, -2262, -1112, -6328, -1578, -2133, -2192, -1282, -5249, -492, -1608, -1433, -1872, -5463, 56, -2829, -1033, -1877, -6735, 108, -8921, -1287, -2722, -7527, -461, -2687, -1650, -8005, -5833, -1891, -802, -2093, -3565, -4344, -4628, -1311, -2714, -996, -3912, -7108, -4596, -2647, -767, -3612, -5606, -7922, -2412, -2013, -1807, -5153, -3394, -3264, -3955, -187, -5528, -2571, -5326, -4593, 284, -4498, -2853, -4618, -4179, -632, -2208, -3530, -2875, -3441, -3109, -724, -4099, -2419, -2947, -2721, -181, -4229, -3471, -2999, -1022, -361, -3709, -7384, -3834, -599, -967, -3015, -8685, -5134, -711, -1899, -2887, -5903, -3554, -765, -3358, -3166, -5754, -1923, -714, -3785, -2993, -5364, -1627, -914, -2953, -2677, -4464, -2332, -1681, -3383, -2699, -3035, -3388, -3309, -3892, -3248, -1738, -3700, -6108, -2633, -5378, -1179, -2604, -4500, -2448, -6191, -1404, -1393, -2437, -4005, -3079, -2358, -977, -2288, -5299, -2310, -4056, -1572, -3908, -3726, -3124, -5777, -3196, -5321, -2909, -5437, -4515, -4846, -3710, -2791, -11497, -2689, -5536, -3021, -3005, -9364, -1774, -7165, -3170, -3541, -5741, -2088, -5895, -4048, -4716, -2782, -4370, -4907, -6604, -7144, -759, -6454, -7052, -7518, -8122, 162, -3555, -4903, -4158, -5895, 171, -3090, -2152, -3245, -5270, -458, -3873, -1626, -3560, -5052, -1399, -4831, -2721, -3192, -3680, -2242, -6011, -5172, -1962, -2520, -2037, -8181, -5573, -1320, -2241, -1316, -8217, -4278, -1378, -2414, -1338, -6014, -3858, -2009, -2515, -2295, -5196, -4232, -3320, -2881, -3690, -5759, -4847, -5692, -3846, -4289, -8306, -4073, -8223, -5282, -3679, -16164, -3100, -6849, -6858, -3166, -9936, -3173, -6371, -6714, -3424, -8925, -4364, -5933, -6648, -3920, -7339, -6037, -4464, -9019, -3779, -6133, -6647, -3996, -10396, -3640, -6068, -6735, -5136, -8205, -3995, -6796, -7047, -8061, -8816, -4599, -6902, -7482, -10407, -11258, -4973, -5821, -7887, -7805, -11952, -5019, -5191, -8094, -3997, -1225, -1726, 455, -2235, -1923, -1850, -2943, 550, -3777, -1445, -2087, -3342, -100, -5814, -1953, -2336, -3153, -1103, -4142, -2632, -4684, -3320, -1695, -2613, -2901, -8141, -4337, -1264, -1490, -2999, -2810, -6058, -562, -465, -3671, -2464, -7398, -133, 2, -5802, -5233, -7651, 29, -553, -6365, -4151, -6733, -20, -2718, -6204, -1790, -5319, -477, -5304, -14004, -1346, -5160, -1726, -2391, -5560, -1932, -7949, -4745, -808, -3556, -3041, -3434, -9599, -338, -2007, -3100, -831, -3094, -916, -500, -1744, -360, -1619, -2268, -816, -956, -1394, -1788, -2899, -8095, -2464, -3479, -2063, -2920, -96, -6021, -2134, -158, -528, 2698, 497, 628, 1616, 1838, 3059, 2030, 1896, 2141, 2847, 1232, 1605, 1912, 1225, 2745, -8986, -425, 926, -1296, 1901, -483, -2512, -753, -2453, 956, 843, -1462, -2673, -1688, 9, 95, -537, -4408, -2272, -2437, -1608, -347, -5766, -2994, -5430, -3559, -711, -6027, -2730, -1048, -6876, -1160, -5132, -2448, -191, -9054, -1174, -3723, -2641, -1234, -7680, -999, -2339, -3458, -3787, -4533, -1345, -1551, -4958, -4962, -1365, -2678, -1656, -4757, -4839, -255, -4576, -3032, -2895, -6716, -603, -5046, -6251, -2278, -6261, -1986, -4877, -5405, -3344, -5445, -3752, -4363, -3169, -7274, -8626, -5077, -4816, -2093, -8234, -4423, -6048, -8315, -1521, -5655, -2150, -7367, -4908, -1421, -4987, -2215, -8890, -2915, -1900, -3782, -4512, -8844, -3645, -2610, -2110, -11768, -7070, -6387, -2648, -642, -5088, -5925, -2978, -2638, 160, -3597, -6593, -1333, -4099, 112, -3402, -10426, -1467, -8395, -890, -3571, -6303, -2852, -3149, -3120, -4245, -3113, -4508, -964, -7471, -4544, -1674, -5138, -434, -8217, -3670, -1793, -6248, -1070, -7179, -3860, -3207, -11460, -2975, -7530, -5558, -2942, -8060, -6450, -4451, -7461, -2403, -5962, -4914, -1935, -10274, -3799, -6274, -3149, -605, -5873, -6762, -4510, -3147, -166, -3850, -6233, -2935, -4624, -373, -4159, -5653, -2806, -7555, -1092, -5467, -7347, -3662, -11322, -2169, -5232, -6273, -4987, -12250, -1931, -6186, -3310, -6732, -12012, -704, -11559, -2685, -8575, -6899, -460, -3157, -3793, -10286, -3554, -1608, -737, -6339, -9748, -1825, -4462, -94, -7832, -6802, -1348, -6603, -749, -7260, -7043, -2270, -5405, -2259, -6798, -13103, -5551, -4543, -3056, -6387, -5503, -8667, -4196, -3570, -6220, -3738, -5031, -5614, -4747, -6335, -4764, -4838, -14754, -2743, -6782, -10976, -6079, -6492, -839, -8010, -3814, -6350, -4274, -270, -10839, -1667, -4784, -3521, -885, -8579, -1418, -3388, -3149, -2850, -6281, -2455, -2546, -3133, -7300, -6330, -4263, -2585, -3700, -11042, -7839, -5477, -3646, -4679, -6705, -5640, -5430, -5216, -5187, -4908, -3996, -4950, -5622, -5062, -3597, -3962, -5171, -5520, -5080, -3056, -5109, -6746, -6170, -4909, -3343, 12256, 8004, 12464, 10904, 8416, 11661, 8838, 11745, 10292, 7837, 9829, 9223, 9416, 8226, 5859, 6696, 8767, 5290, 3434, 1111, 2977, 8757, 4969, 1397, -464, 2108, 8772, 5794, 2522, 410, 3623, 7901, 5356, 2679, -1019, 5245, 5907, 2704, 4437, 2837, 6340, 1941, -1646, 4585, 4770, 6369, -1679, 2483, 2553, 5902, 5187, 2214, 1437, -1825, 6887, 4304, 3741, 84, 2872, 7698, 4748, 5084, 4322, 4584, 8097, 3880, 6081, 5659, 4890, 7818, 404, 6185, 5249, 4249, 6527, -7291, 5006, 2951, 2881, 3497, -5240, 2206, -4488, 1561, -9294, -62, 927, -185, 1006, 283, 2058, 2088, 1229, 656, 1421, 2252, 1775, 1014, 258, 2453, 1699, 199, 430, -287, 3213, 2191, -2181, -57, -1054, 2911, 3325, -3151, -687, -1903, 1542, 3738, -1571, -2331, -1605, -940, 3089, 510, -6440, -368, -8987, 1177, 1854, -1607, -59, -1887, -1725, 2033, 1828, -1407, 592, -2381, 864, 3501, -5873, 1064, -2537, -1580, 3845, -3362, 542, -1505, -2445, 2886, -229, -405, 220, -2483, 444, 1400, -1286, 1392, -3217, -2656, 2135, -1229, 2661, -1199, -1080, 1981, -101, 3840, 256, 738, 747, 983, 4422, 182, 1386, -1648, 1393, 4214, -1355, 859, -838, 572, 3078, -2979, -575, 1179, -2779, 1287, -2136, -2727, 2186, -603, 978, -480, -6706, 2734, 2007, 1252, 808, -2298, 2885, 2142, 482, 891, -647, 2223, -222, -882, 48, -1264, 701, -928, -1442, -453, -2690, 1267, 2068, -781, -1361, -3028, 2620, 2817, -385, -2744, -5865, 2610, 2421, -936, -733, -3840, 1366, 1544, -2087, 10, -1101, -272, 683, -2789, -693, -877, -801, 163, -3096, -1309, -2391, -582, 299, -3274, -1850, -6029, 58, 616, -2384, -4761, -7028, 879, 179, -883, -6516, -4411, 1277, -1468, 34, -2535, -2780, 952, -4018, -129, -857, -2165, 261, -4386, -1751, 839, -3254, 107, -2568, -3835, 2081, -8946, 80, -1732, -2107, 2452, -4218, -605, -3095, -1867, 1838, -2078, -1614, -6924, -5828, -12, -2580, -2200, -2167, -3131, -2820, -2926, -3767, -1126, 719, -1176, 479, -6279, -2542, 2094, 49, 2495, -2044, -5879, 2347, -592, 3243, -1135, -5126, 1748, -3047, 3057, -3205, -4156, 138, -1356, 2208, -7246, -1605, -2387, 720, 1134, -3015, 104, -1286, 1267, 413, -3284, 616, 176, 843, 110, -6889, 398, 697, -193, -436, -11669, -33, 829, -1605, -2037, -10863, -448, 101, -2500, -5866, -5674, -1045, -2758, -2960, -12132, -2950, -1885, -5134, -5512, -10490, -2075, -2092, -2006, -4752, -10492, -2218, -1038, -1937, -3669, -4559, -1907, 129, -3237, -4189, -2470, -812, 589, -2988, -1045, -2067, -276, -42, -1464, 325, -2838, 109, -2212, -1060, 380, -3663, 1003, -7791, -1896, 621, -2976, 1814, -2913, -403, -258, 8045, 9550, 7186, 501, 120, 7325, 8675, 6888, 1718, -160, 4903, 5702, 5722, 2833, -1728, 3467, 5928, 3912, 3925, -1514, 5284, 7940, 4257, 4699, 1072, 4933, 8041, 4843, 5014, 3906, 1122, 6909, 4358, 5019, 5623, 1005, 5540, 3590, 4792, 6091, 4076, 4906, 3947, 3907, 5549, 3769, 3762, 4786, 890, 4882, 741, 1371, 5631, -291, 4994, 728, 1159, 6304, 4450, 4886, 3321, 2554, 6345, 5797, 3780, 3904, 2829, 5709, 5579, 1185, 3568, 1699, 4629, 4263, -2447, 2989, -2181, 3142, 3186, 129, 2449, -5138, 1168, 3525, 1168, 1787, -1819, 195, 3274, 742, 1218, -663, 1042, 1324, -866, 1954, 1364, 1572, 1662, -4443, 3379, 2084, 1684, 4019, -8671, 4064, 1194, 1955, 4407, -4026, 3688, 230, 2287, 3023, -2688, 2463, 1878, 2236, 1119, -1896, 1342, 2899, 2547, 2351, -1459, 192, 2690, 3911, 2889, -558, -3703, 1611, 4897, 2077, 1155, -4453, 1426, 4812, 253, 2535, -1286, 2192, 3359, -1729, 3156, -1705, 2219, -457, -1692, 2994, -4273, 1368, -6251, -398, 2085, -4517, -325, -1626, 744, 1019, -1348, -3731, -2295, 1545, 1093, 732, -3623, -5882, 1875, 1617, 2194, -270, -4617, 1827, 2031, 3166, 506, -916, 1703, 1981, 3615, -387, 1276, 1579, 173, 3603, -2179, 2473, 1186, -3435, 3314, -2054, 2724, 140, 1652, 3011, 491, 2149, 1076, 2844, 2872, 2244, 1128, 3283, 1936, 2805, 2588, 349, 3957, -821, 2510, 1202, -190, 2950, -1257, 1734, -4619, -1319, 204, -250, 544, -1348, -2007, 294, -875, -352, 1091, -997, 1688, -2024, -425, 1248, -1371, 1668, -855, -262, 382, -5691, 956, 510, -302, -817, -2914, 1049, 907, -595, -1920, 502, 1943, 448, -821, -2724, 1601, 2352, -661, -746, -3330, 1475, 2140, -2026, -671, -4629, 392, 1396, -2031, -648, -7270, -1545, -146, -264, -553, -5524, -5040, -3276, 1055, -589, -3499, -9133, -5950, 1530, -979, -2698, -4207, -2716, 1158, -1913, -2031, -4130, -1612, -210, -3641, -1409, -6419, -2059, -2883, -5326, -565, -1954, -4178, -5976, -4314, 748, 198, -8769, -5558, -2953, 1516, 195, -7740, -4682, -1797, 1192, -2740, -4010, -3483, -331, -413, -5649, -2104, -2098, 1117, -2120, -1314, -1318, -954, 2108, -357, -1250, -1381, -306, 2503, 958, -537, -1893, -644, 2144, 961, 741, -1843, -2192, 590, -137, 519, -1748, -1145, -2490, -1252, -1332, -2488, 606, -797, -2951, -2477, -3125, 1038, 190, -3824, -112, -2300, 779, -1038, 313, 1460, -1318, 19, -3384, 1074, 2146, -964, -1678, -3315, -616, 2249, -1141, -4332, 867, -1709, 1865, -1088, -9021, 3321, 629, 1195, -654, -782, 4100, 1998, 1048, -939, 2199, 3533, 2857, 1285, -2908, 3349, 1691, 3051, 932, 8460, 8764, 11352, 9229, 2753, 7994, 8949, 10816, 8749, 4209, 6432, 8797, 9288, 7514, 4087, 3028, 7763, 7221, 6280, 2883, 4307, 6429, 6286, 6063, 5151, 7170, 5960, 7057, 6742, 5915, 7885, 5807, 7424, 7641, 5033, 6634, 4701, 7023, 8459, 3040, 2317, 292, 6300, 8670, 1377, 4805, 1482, 5279, 7906, 2178, 6627, 4124, 3261, 6187, 1619, 6761, 5003, 2385, 4000, -1840, 6090, 5749, 4444, 149, 435, 4690, 5625, 4623, 68, 1056, 2124, 4213, 2140, 3875, -22, -3026, 2354, -1857, 4641, 1532, -8310, 1683, 2757, 4313, 3311, -7519, 872, 3382, 3707, 4183, -6729, -44, 2501, 2651, 4306, -3805, -1024, 1050, 4, 4095, -3055, -2232, 319, -2462, 4125, -2696, -1606, 834, 1370, 4268, -2410, -1369, 1480, 2791, 4182, -2101, -3471, 1399, 2977, 3828, -1520, -10223, 1, 2121, 3192, -775, -2869, -4311, -529, 2125, -186, -1618, -5470, -6680, 279, -352, -75, -2436, 917, -2823, -2656, 1519, -1145, 3016, -804, -4637, 1827, 182, 3785, 2504, 898, 1495, 964, 3725, 4232, 2812, 2149, 1390, 2948, 4710, 3434, 2418, 1520, 1436, 4089, 3316, 1374, 1283, -1088, 2899, 2824, 1657, 994, -7632, 2226, 2433, 2951, -5, -3054, 1144, 2270, 2699, -55, 100, -2935, 1379, 725, 3089, 1043, -1725, -2073, -2755, 4658, 399, 1008, -1394, -4091, 4839, -2461, 1439, 629, -1411, 3963, -2723, 695, -1442, -2145, 2462, 299, -1740, -1715, -2818, 1113, 1355, -2852, 2143, 2129, 732, 1797, 736, 2904, 3268, 1169, 2289, 1744, 1974, 1867, 1005, 2571, 1211, -754, -5190, -349, 2287, -231, -8360, 810, -1871, 1834, -1632, -3091, 2122, -1322, 2495, -2923, -1269, 1075, -755, 3536, -2198, -695, -2012, -865, 3776, -238, -991, -3860, -1450, 2933, 160, -2163, -644, -2220, 1230, -1354, -3734, 1575, -2364, 379, -5293, -4967, 2724, -1855, 144, -3369, -5844, 2915, -1599, -1240, -2022, -5521, 2148, -1625, -2487, -1109, -3257, 70, -1427, -1644, 471, -1981, -5198, -595, -705, 1684, -2131, -6811, 346, -443, 2197, -3951, -6458, 798, -2139, 1940, -8099, -3504, 634, -5089, 805, -6176, 47, 469, 671, -1372, -7883, 1266, 1254, 2689, -5451, -5118, 975, 2109, 3192, -9195, -643, -664, 2208, 2548, -3472, 822, -3077, 1423, 640, -719, 902, -5188, 621, -3357, 1233, 509, -7465, 1372, -8998, 2263, 412, -1372, 1921, -3528, 2170, 457, 1163, 1371, -1897, 689, 419, 2608, 199, -990, -2223, 406, 3461, -518, -285, -1417, 524, 3722, -721, -471, -59, 846, 3468, -3, -2518, -219, 1216, 2950, 769, -6634, -1664, 1267, 2254, 1212, -4126, -3522, 954, 1146, 1796, -4887, -2688, 562, -252, 2150, -5063, -1078, 15, -607, 1798, -1354, 64, -2422, 1217, -1222, 2356, -549, -826, 1359, 46, 2528, 77, 703, 1093, 540, 2047, 385, 1584, 810, 575, 906, 905, 1793, 607, -30, -280, 928, 1335, 127, -2231, -579, 524, 372, -1104, -3372, -1242, 594, -759, -2885, -1276, -2669, 1271, -2051, -1787, -2151, 731, 1607, -3941, -142, -2902, 2755, 1031, -2410, 257, 526, 3356, 338, 368, -416, 1648, 3127, 1169, 1554, -883, 1187, 2447, 1919, 1349, 35, -355, 1505, 2010, -49, 491, -1493, 290, 1885, -1012, -189, -706, -1402, 1835, -653, -1342, 414, -4049, 1445, -1380, -835, 1399, -2753, -656, -1061, 407, 2389, 328, -5594, 1578, 1699, 3256, 1557, 1803, 3104, 2721, 3595, 1262, 3600, 3538, 2988, 3157, -425, 3530, 3049, 2241, 2007, -2748, 1807, 1702, 292, 913, -2749, -1753, -271, -1737, 416, -410, -2780, -2211, -796, -825, 738, -3053, -3166, 224, -4159, 388, -6781, -1350, 778, -7538, -684, -6021, 40, 794, -8075, -1196, -2613, 194, 186, -5381, -1710, -796, -846, -876, -3076, -2264, 450, -3535, -2173, -2795, -2610, 1111, -3248, -2985, -3229, -2763, 942, -1127, -3091, -2968, -2029, -564, -957, -3445, -2602, -2077, -4367, -1931, -2600, -3586, -4953, -599, -2966, -1270, -6257, -3913, 1906, -3599, -1194, -3077, -125, 2630, -4263, -2647, -1461, 1024, 1879, -4804, -1485, -2161, 636, -401, -5464, 880, -7517, -1091, -1523, -7686, 1802, -3875, -3391, -522, -10960, 1715, -893, -3458, 65, -4600, 963, 83, -1659, 494, -638, -385, 426, -37, 215, 1234, -2347, 531, 777, -961, 1538, -3032, 550, 806, -2996, 382, -1489, 670, 104, -6353, -2430, -72, 764, -1070, -7499, -7218, 711, 512, -2166, -6543, -16015, 894, -116, -4145, -8256, -4972, 799, -1035, -9862, -3472, -1895, 662, -2096, -2376, -442, -683, 312, -2580, -257, 980, -586, -284, -2829, 219, 1468, -997, -665, -3893, -358, 1381, -1313, -924, -5072, -1739, 1043, -1979, -2041, -4316, -4271, 900, -3999, -5376, -3714, -10667, 1246, -9268, -12061, -4294, -2703, 1723, -5847, -6724, -5843, -451, 1670, -3115, -8155, -5466, -5, 553, -2213, -8196, -3675, -928, -2179, -2481, -5031, -2801, -2871, -5236, -2656, -4252, -2905, -3313, -4565, -1879, -5726, -3708, -2167, -4952, -1631, -9692, -4346, -1480, -4648, -2599, -3388, -4863, -1423, -3280, -5618, -1103, -6256, -2118, -2033, -7619, -369, -4822, -3878, -1391, -3919, -476, -2701, -7312, -1380, -2864, -804, -2024, -5814, -1760, -2468, -1219, -2327, -3750, -2191, -2058, -2263, -2831, -3560, -2300, -2160, -4133, -2731, -4973, -1943, -3298, -4746, -2163, -8332, -1633, -5245, -3793, -1897, -9267, -2145, -4547, -3877, -2678, -7678, -4342, -3610, -5656, -5583, -6145, -6009, -4297, -9752, -11844, -3874, -3231, -9564, 3317, -1712, 2495, -249, -4231, 2333, -4860, 1441, -2319, 472, 214, -2134, 332, -6326, 2920, -5387, -2290, -772, -1964, 3892, -958, -9231, -1652, 802, 3680, 1596, -2025, -1339, 1828, 2542, 1900, 188, -1396, 1656, 1022, 311, 218, -2450, 361, -494, -5238, -143, -2696, -2148, -2685, -3968, 428, -2002, -5779, -3974, -1723, 596, -1375, -7355, -2275, -1966, -382, -1209, -4313, -1981, -1460, -2295, -2147, -1661, -4310, -181, -3322, -3900, 111, -7570, -182, -3673, -3565, 1099, -2872, -1643, -4352, -1997, 1367, -1554, -2401, -4965, -514, 875, -433, -1869, -6022, 566, -330, 1229, -3502, -2602, 1703, -1157, 2667, -3167, -378, 2998, -711, 3240, 137, 101, 3765, -609, 2728, 1359, -902, 3624, -1976, 1083, 1316, -2345, 2389, -8600, -1322, 389, -1026, -309, -758, -3238, -266, 437, -6312, 2126, -4703, 816, 1101, -3475, 3235, -5948, 1770, 967, -999, 3122, -5564, 1828, -395, -227, 1573, -3359, 1194, -5735, 255, -3600, -2273, 303, -2483, 1032, -1824, -2752, -632, 326, 1326, 840, -5005, -1329, 466, 820, 941, -4284, -1794, -1498, -222, -125, -1421, -2664, -5865, -1489, -924, 146, -2813, -1618, -2149, -70, 669, -2351, 367, -1519, 961, -46, -1477, 1177, -1038, 1226, -1699, 628, 1361, -486, 532, -76, 2150, 963, 527, -1000, 1627, 2592, 101, 1346, -1927, 2020, 1908, -700, 1647, -1514, 1653, -332, -1236, 1406, -1411, 1325, -10068, -989, 667, -924, 1690, -1303, 515, -409, -10, 2410, 1293, 1728, -1478, -109, 2706, 2163, 2160, -2210, -2149, 2184, 1921, 1908, -2428, -9430, 658, 573, 1130, -1598, -8966, -2020, -2038, -112, -240, -6766, -3364, -3674, -1602, 690, -1499, -2217, -1771, -1832, 920, 140, -2417, -677, -1264, 421, -87, -4587, -576, -1291, -567, -1831, -8048, -1305, -1898, -875, -4965, -3671, -2780, -2956, 215, -9928, -2334, -4840, -3151, 960, -8429, -2557, -4926, -2364, 391, -4029, -3040, -2353, -2119, -1905, -2826, -2297, -703, -1551, -2284, -3370, -806, -431, -283, -701, -2411, 257, -1976, 712, -781, -110, 523, -5822, 1049, -1996, 1024, 18, -2396, 621, -3525, 1091, -1011, -1452, -564, -4353, 241, -1537, -3027, -1276, -3894, -1498, -1273, -1980, -230, -3036, -4200, -1669, 593, 335, -2142, -8792, -3426, 1475, -195, -1508, -9505, -5679, 1171, -1675, -1465, -6397, -4053, 5, -4040, -2016, -6187, -2771, -1603, -8102, -3353, -6786, -2667, -2941, -7881, -5242, -6067, -3708, -3427, -6175, -3917, -4149, -5051, -3540, -5787, -2668, -2366, -3368, -4009, -4915, -2502, -1633, -1766, -4810, -3513, -2509, -2258, -1212, -5520, -2392, -2325, -4518, -1430, -6411, -2023, -2446, -5615, -2144, -7517, -2545, -2686, -4291, -2848, -6527, -3844, -1880, -4841, -1145, -145, 628, 475, 457, -2957, -10, -1570, 1391, -133, -4206, 52, -6385, 1664, -1805, -3079, 145, -4327, 1253, -3114, -1486, -819, -975, 374, -2454, -1235, -5610, 467, -293, -1797, -3162, -3606, 815, -758, -304, -3796, -1578, 354, -1073, 797, -583, -2625, -499, -771, 551, 92, -2287, -1511, -778, -390, -1734, -786, -2860, -1886, 191, -5805, -598, -3619, -3831, 690, -130, -1444, -1214, -2643, 209, 1606, -3083, 1408, -614, -1114, 2381, -4094, 2906, 633, -6743, 2871, -2164, 3295, 1471, -1532, 2341, -551, 2600, 1803, 1710, -254, -1350, 670, 852, 2520, 1150, -2959, -1344, -3412, 1716, 3180, 1734, 1280, -675, -265, 2878, 3379, 3075, 1577, 593, 564, 3251, 3563, 1385, 2170, 651, 1874, 3033, -583, 2850, 2123, 884, 1686, -4414, 3101, 1837, 1719, -398, -9515, 2822, 99, 2401, -3167, -4597, 1589, -2826, 2676, -4771, -1401, -138, -5814, 2910, -6350, -610, -104, -6063, 3013, -8985, -1488, -619, -3875, 2957, -8283, -2294, -2217, -1501, 3230, -2237, -1782, -1127, 361, 3596, 688, -1570, -753, 1476, 3297, 1530, -1263, -1992, 1754, 1762, 584, -332, -3281, 1156, -2419, -2802, 614, -2246, -349, -3108, -5652, 727, -1032, -2545, -441, -2741, -363, -1151, -3433, -692, -2244, -2517, -3094, -2801, -2605, -2152, -2148, -5145, -2558, -3874, -1905, -258, -4390, -2293, -3149, -1464, 888, -6111, -1497, -3126, -774, 1634, -5495, -650, -2098, -295, 1935, -2774, -379, 67, -790, 1403, -1358, -1010, 1457, -3443, -11, -51, -2306, 1889, -3109, -284, 1057, -4607, 1583, 263, 789, 1584, -6906, 976, 1375, 1056, 1371, -1678, 582, 1247, 544, 460, -635, 136, 304, -188, -774, -1331, -1029, -952, -1160, -2151, -918, -1051, -1310, -2378, -3368, 140, 174, -419, -310, -2190, 673, -106, 227, 1558, -1586, 1039, -2416, -134, 2027, -2991, 893, -6580, -1703, 1269, -6484, -115, -5723, -4105, -856, -2971, -2238, -3554, -6704, -5229, -939, -6743, -2910, -7597, -3618, -429, -10337, -4056, -6796, -1566, -1561, -6673, -4428, -12669, -1216, -7896, -6061, -3668, -2993, -1485, -2882, -5866, -4362, -584, -1137, -280, -6184, -5742, -232, -590, 311, -7151, -6190, -1667, -693, 372, -10047, -5120, -7048, -1029, 73, -10798, -3369, -4997, -1002, -1285, -5770, -2927, -2547, -1148, -2374, -4233, -4789, -2791, -1988, -447, -4173, -8613, -4557, -3999, 457, -4995, -3105, -6255, -7731, -100, -6188, -1730, -7142, -5266, -2370, -6593, -2111, -11767, -3767, -5091, -5145, -3803, -7493, -3824, -2533, -4008, -6733, -4307, -4295, -1719, -4287, -10252, -3294, -4072, -2339, -5571, -8014, -3507, -3417, -3899, -3474, -6660, -4456, -2442, -6205, -1628, -7007, -4803, -1214, -10809, -1319, -8609, -4288, -465, -10738, 11098, 5212, 12300, 10731, -13274, 10442, 6685, 11667, 10185, -5310, 8302, 7186, 9625, 8459, -3020, 3785, 5776, 5462, 5253, -2244, 1023, 3996, -1424, 287, -1736, 2976, 4149, 407, -1784, -605, 3079, 3114, -722, 661, 89, 2958, 784, -5, 1303, 325, 3135, 1756, -86, -672, 1340, 3989, 2726, 137, -26, 2416, 4821, 2709, 1082, 3029, 3017, 4752, 3030, 538, 4385, 3491, 3277, 4047, -3489, 4673, 3810, -348, 4441, -1135, 3980, 3758, 216, 3628, 293, 2357, 3336, 1802, 1749, -2091, 829, 2509, 1505, 768, -891, 395, 811, 631, 636, 1899, 109, -4455, 226, -296, 2648, 168, -1596, -540, -1523, 2391, 272, 1368, -1774, -3220, 1437, 265, 1752, -1880, -5949, -332, 528, 741, -1641, -3799, -3154, 1030, -656, -1690, -2449, -3611, 1340, -1832, -1245, -2534, -2997, 1490, -4817, -374, -2040, -4587, 1682, -2789, -169, -908, -9040, 1674, -187, -1274, -1075, -8328, 1255, 257, -3880, -3698, -4611, 584, -873, -5979, -5615, -2235, 163, -3707, -9433, -1926, -1347, 160, -9210, -7969, -1200, -1870, 103, -12453, -4893, -2052, -4712, -220, -7170, -5432, -4455, -7397, -715, -3549, -7741, -7953, -2554, -1232, -1773, -5242, -5832, -1528, -1503, -1547, -2831, -3492, -2060, -1501, -3042, -1437, -1902, -3381, -1917, -4839, -896, -1487, -4409, -3751, -2231, -1335, -2925, -5361, -9173, -752, -2493, -11578, -7925, -5094, -347, -2519, -3585, -18176, -3398, -604, -1625, -1877, -10374, -3873, -1355, -1285, -2854, -12016, -6563, -2503, -1518, -6327, -12043, -7376, -3559, -2105, -3820, -7938, -4767, -3599, -2760, -2402, -6678, -4353, -3201, -3089, -2845, -6013, -5385, -3098, -2942, -4488, -4418, -8138, -3288, -2847, -6622, -2408, -14394, -3652, -3416, -8079, -1161, -5638, -4190, -4624, -8116, -831, -2668, -4954, -5222, -6976, -1189, -1206, -5770, -5339, -5479, -1860, -828, -5995, -6444, -4132, -2620, -1298, -5463, -7908, -3071, -3510, -2244, -4449, -6470, -2511, -4811, -3266, -3517, -4756, -2817, -6980, -3990, -3400, -4214, -4423, -6924, -3501, -4595, -5061, -7353, -5594, -2586, -6687, -5601, -7305, -5826, -2433, -5014, -4189, -6156, -7004, -3291, -3297, -3931, -4989, -7679, -4740, -2520, -5206, -4326, -7732, -5585, -2025, -5975, -4052, -6323, -7057, -1360, -4578, -2613, -4732, -12016, -683, -3435, -1212, -4410, -7504, -294, -2585, -828, -5621, -6556, -375, -2187, -1415, -5592, -8070, -1032, -2424, -2718, -3489, -9643, -1973, -3028, -4759, -3094, -7536, -2619, -3475, -9114, -5000, -4308, -3469, -3501, -6100, -6687, -2197, -4270, -3029, -3362, -3660, -1111, -3131, -3031, -2650, -3297, -786, -2407, -4677, -3325, -5145, -1064, -3122, -10750, -5078, -6277, -1863, -5590, -9095, -6716, -4257, -3437, -10057, -8470, -7109, -3506, -7310, -10609, -11511, -6290, -2969, -8178, -5305, 1585, 3305, 8481, 3947, -7373, 857, 2438, 7871, 4483, -5163, -1996, -93, 5893, 4989, -1325, -1659, 841, 2403, 4908, 1273, 2099, 2461, 2031, 4779, 2616, 3751, 2638, 2640, 5051, 3061, 4361, 2355, 1685, 5346, 2837, 4441, 2016, 406, 5189, 2082, 4328, 247, 1849, 4410, 1080, 4039, -3195, 3468, 3163, -336, 4027, 2040, 4662, 1497, -3365, 4988, 3859, 5658, -982, 38, 5693, 4172, 5994, -1242, 3006, 5278, 3567, 5174, -822, 4260, 3458, 2747, 2548, -2184, 4354, 706, 2516, 58, -2813, 3520, 445, 2291, 2562, -2896, 2005, 192, 1550, 2941, -4081, 194, -869, 734, 1859, -4434, -1360, -785, 930, 155, -3206, -2027, 300, 1899, -530, -2885, -1699, 1254, 2444, 93, -5182, -1408, 1767, 2207, 423, -10119, -1961, 1778, 1408, -459, -6219, -2644, 1226, 771, -1880, -1894, -2940, 111, 722, -634, 805, -3221, -589, 873, 577, 1830, -1550, 239, 766, 783, 1632, -334, 995, 95, 209, 354, -388, 892, -717, -877, -2339, -1423, -500, -449, -1883, -4972, -3426, -5195, -1, -1938, -2367, -8461, -3421, -187, -1485, -1279, -4852, -866, -240, -1510, -1196, -1826, -1293, 206, -2200, -1447, -684, -4666, -29, -3118, -1524, -475, -6737, -1703, -3556, -973, -677, -4775, -4770, -3481, -59, -841, -4117, -4457, -3387, 502, -1063, -2478, -3343, -3405, 513, -1847, -1872, -2763, -3513, 216, -3158, -1954, -3293, -3491, 6, -1841, -2078, -6307, -3108, -39, -34, -2676, -4200, -3202, -70, 295, -4143, -1613, -4699, 133, -1057, -5056, -933, -8726, 735, -5222, -4775, -1032, -7064, 1143, -6540, -5723, -1051, -4089, 856, -4798, -7549, -1215, -2400, -195, -7213, -5635, -2425, -1542, -1435, -6176, -4819, -4529, -1232, -2289, -3326, -6213, -3064, -863, -4036, -3085, -8323, -2295, -451, -4993, -4715, -5061, -4020, -749, -2752, -3877, -3576, -6565, -1875, -2479, -2051, -3764, -3560, -2217, -3992, -1880, -5381, -3341, -1708, -5812, -3022, -4445, -4321, -1992, -6653, -5129, -2650, -3498, -3241, -5129, -7028, -2528, -2897, -4728, -3051, -5802, -4167, -3519, -5969, -2871, -4319, -7325, -4670, -9996, -4331, -3595, -4791, -4604, -7482, -4786, -3318, -3351, -3509, -5488, -4479, -3763, -3662, -3008, -6282, -6129, -6270, -5514, -3122, -7904, -5156, -9061, -7791, -2629, -5439, -3320, -3932, -5454, -1852, -3039, -2650, -2778, -3742, -1820, -1611, -1754, -3548, -3505, -2607, -1143, -1164, -7063, -4740, -3944, -1745, -1874, -6602, -7379, -5275, -3118, -4641, -2947, -5731, -4220, -3162, -4582, -1783, -3739, -2276, -2644, -2088, -1782, -3252, -1601, -3260, -1424, -2322, -3649, -2494, -4660, -1975, -3063, -4196, -5663, -5993, -3845, -3228, -4619, -8550, -9567, -6095, -2124, -4831, -5158, -8780, -3685, -1638, -4736, -3700, -5019, -2600, -2706, 3707, 2638, 6935, 2367, -409, 2736, 2365, 6486, 3751, 2168, 1377, 1343, 5470, 4876, 3115, 3163, -681, 4488, 4624, 1773, 4089, -697, 2993, 2655, -2576, 3762, 1709, 329, -2962, -906, 2292, 2976, 233, -1112, 746, -870, 3029, 587, -145, 458, -5764, 1947, 2, -1787, -2017, -2262, -4, 430, -2562, -3108, -14, -1930, 1231, -1716, 1821, 1788, -2410, 1649, -1517, 3826, 2804, -1236, 1710, -143, 4544, 3057, -441, 1395, 1775, 4359, 2635, 418, 578, 2847, 3582, 1434, 1425, -1172, 2693, 2857, -1028, 1644, -3601, 1070, 2653, -6563, 865, -687, -76, 2631, -10669, -513, 830, 1328, 2475, -6428, -1739, 525, 1282, 2073, -2958, -2828, -1301, -1020, 1441, -2750, -4133, -3430, -16441, 646, -4168, -2603, -3920, -2047, 242, -486, -225, -4235, -270, 624, 1024, 1000, -3784, 359, 546, 493, 1237, -3623, 640, -679, -2010, 381, -3130, 969, -2732, -3305, -2278, -1646, 1447, -3567, -2123, -7752, -834, 1559, -1510, -2701, -3584, -997, 908, 148, -4190, -2956, -1853, -521, 587, -4177, -3973, -2802, -2053, 103, -3373, -5826, -3259, -2014, -1133, -3022, -7751, -3502, -801, -3851, -2864, -7128, -4058, 12, -6858, -2197, -5368, -4733, -156, -2515, -1500, -4914, -3531, -1289, -1601, -2129, -5401, -1761, -934, -3359, -5833, -5855, -929, 961, -7624, -2855, -4490, -885, 1960, -1611, -733, -2348, -960, 2037, 345, -1164, -1348, -729, 1452, 1044, -3845, -1594, -613, 382, 974, -4552, -3003, -778, -1558, 95, -3389, -5396, -859, -5068, -1692, -3932, -3957, -712, -2859, -2906, -4352, -1844, -920, -1314, -2445, -3971, -1383, -2114, -710, -2151, -3884, -2316, -5126, 123, -1625, -4171, -3896, -7733, 660, -1102, -4685, -3933, -2734, 588, -702, -5475, -3649, -655, 67, -528, -6936, -4077, -101, -1149, -1218, -10007, -4253, -984, -4323, -3259, -7527, -2958, -3909, -5933, -3525, -3866, -1383, -6203, -2006, -1102, -2139, -615, -2993, -907, 107, -2018, -870, -1857, -1267, 143, -3948, -1987, -1685, -2792, -1038, -8334, -3092, -2154, -4408, -3392, -4299, -3602, -3363, -4114, -3630, -3513, -4155, -6059, -3263, -2461, -5321, -4200, -9254, -2273, -2403, -14087, -3900, -5744, -1227, -3193, -4042, -4117, -5267, -476, -3996, -1661, -4803, -7994, -240, -3732, -892, -5842, -10145, -634, -3205, -1265, -7545, -5716, -1846, -2950, -2523, -9839, -4877, -4653, -3034, -3705, -7522, -4084, -5418, -3877, -4613, -4659, -3178, -2218, -5807, -7387, -3785, -3515, -1403, -8260, -11497, -4984, -6182, -2172, -9360, -6346, -6504, -6892, -4239, -7743, -4428, -4122, -4123, -6879, -7008, -3190, -3511, -4579, -10967, -6432, -2575, -3400, -5683, -7842, -4646, -2471, -1945, -3157, -3757, -4293, -2553, -1025, -2473, -2903, -5273, -2585, -1288, -3610, -4283, -4097, -9523, -5943, -2164, -5581, -2444, -7776, -7923, -2002, -6584, -1324, -6893, -10160, -3126, -8249, -1242, -5853, -5730, -6185, -7069, -1318, -4999, -4494, -11606, -4761, -1033, -4625, -4512, -9209, -2764, -895, -4675, -5093, -5432, -2392, -906, -5316, -6753, -2629, -4217, -506, -7343, -12258, -1117, -18640, -111, -9723, -7977, -691, -4660, -501, -6642, -6882, -1346, -3457, -2156, -5205, -9530, -3231, -4659, -6435, -3930, -12152, -6519, -8626, -5634, -3154, -7490, -9589, -6737, -2102, -3723, -7020, -9157, -4072, -731, -5013, -8657, -9415, -2941, -398, -4607, -10880, -9679, -2876, -754, -5311, -14843, -9054, -4567, -1638, -14356, -6364, -8733, -13294, -3056, -4994, -2996, -4463, -5328, -4725, -2286, -1904, -2246, -4056, -4127, -1121, -2429, -1557, -5177, -2582, -734, -4504, -1938, -7300, -2004, -1035, -7966, -3344, -7584, -2366, -1927, -7388, -7014, -5819, -3508, -3280, -5943, -7778, -3259, -5056, -4883, -5403, -3711, -1761, -6577, -5724, -3812, -2815, -1334, -10214, -6432, -2134, -3513, -1800, -7198, -8335, -1299, -5112, -3064, -4323, -6722, -1216, -6206, -5131, -3659, -5068, -1666, -8050, -8021, -4004, -4996, -2605, -8072, -11208, -4015, -6186, -4652, -4438, -10588, -3273, -8792, -9297, -3155, -7707, -2889, -9015, -5467, -3343, -5270, -3625, -6067, -3545, -4613, -3311, -6748, -5065, -2944, -6260, -2057, -9865, -6187, -2925, -7114, -1475, -5008, -6917, -3686, -7323, -1268, -4218, -3167, -5852, -7615, -1271, -4439, -1312, -6944, -8678, -1771, -3908, -680, -4782, -8846, -3161, -3446, -825, -4036, -8856, -5418, -4445, -1466, -4437, -10779, -6813, -5622, -2382, -5802, -4930, -7126, -3128, -3724, -7505, -1874, -8631, -1671, -6449, -8103, -453, -13228, -1267, -9744, -7564, -269, -10195, -1356, -6865, -6983, -1270, -7884, -1598, -7550, -8264, -3377, -6582, -1809, -13209, -10664, -5900, -4933, -2029, -6603, -7333, -6637, -3141, -2649, -4805, -5579, -4607, -2065, -3786, -4159, -4530, -3556, -1958, -4434, -4021, -3946, -3579, -2653, -4115, -5443, -4218, -3204, -3892, -4038, -9143, -6128, -2134, -4915, -5295, -4613, -13797, -1494, -3796, -8152, -2934, -8834, -1618, -2501, -3860, -2776, -7296, -2660, -1837, -2081, -3349, -6771, -4973, -1725, -2184, -4176, -7035, -10012, -2470, -3850, -4867, -10270, -8530, -4484, -7644, -4945, -11567, -5452, -7947, -13246, -4593, -7648, -4465, -13331, -8972, -4690, -7031, -4486, -11865, -9795, -5755, -7391, -4672, -9503, -9418, -6950, -7780, -4682, -16058, -7030, -6089, -6621, -4720, -7791, -5977, -5453, -5265, -4802, -5117, -5921, -6064, -4721, -5110, -5085, -8222, -8408, -4431, -5728, -7469, -7815, -12098, -3763, -6161, -10741, -3895, -8584, -3051, -5790, -8524, -2729, -7566, -2674, -5077, -9058, -3014, -8564, -2654, -4944, -7027, -4310, -8408, -2854, -6054, -5405, -6337, -6067, -3169, -7725, -5604, -8646, -5427, -3730, -6045, -7173, -9349, -5644, -2745, -4435, -3255, -5100, -10319, -2409, -5707, -5709, -3217, -4289, -2904, -8567, -10219, -1759, -1428, -4532, -10403, -10345, -2067, -360, -8814, -11601, -8343, -3550, -360, -6021, -10113, -5433, -2952, -1047, -2621, -6476, -3020, -2146, -2014, -1286, -3590, -1799, -3138, -3347, -1293, -2157, -2028, -4382, -6207, -2485, -2222, -3986, -3157, -6363, -4376, -3953, -6302, -2993, -3178, -4933, -8381, -5066, -4482, -2127, -4846, -12400, -4240, -7919, -2555, -6214, -8454, -3503, -7013, -4322, -5684, -6272, -2668, -4389, -4535, -3199, -3959, -1933, -3414, -2477, -2617, -2243, -1718, -3123, -1327, -3827, -1305, -2294, -2093, -1066, -7001, -1076, -3850, -801, -1632, -8388, -1685, -6329, -498, -2998, -7507, -3648, -5368, -1515, -4982, -7466, -7383, -3325, -2655, -7653, -7390, -5273, -2413, -1555, -14324, -6261, -3707, -2532, -1035, -9651, -4787, -3281, -3732, -1629, -5854, -4420, -3728, -5714, -2317, -4014, -5483, -5742, -5663, -2378, -3529, -7319, -8604, -4638, -3085, -4334, -6198, -5104, -4462, -5674, -6502, -5078, -3689, -4555, -14132, -11050, -5171, -3450, -4259, -13545, -9341, -5933, -3294, -3862, -8457, -5184, -6151, -2572, -4167, -4497, -3611, -5143, -1653, -5473, -3356, -3468, -3974, -1278, -6098, -3895, -4212, -3747, -2331, -4030, -5500, -5145, -5045, -7589, -2336, -6391, -5749, -7203, -4400, -1870, -5463, -6348, -6143, -2208, -2193, -4082, -7322, -4906, -2997, -1735, -2751, -4971, -3830, -7372, -806, -1731, -2704, -3698, -7334, -695, -1307, -1781, -5715, -4778, -1785, -1633, -1760, -9078, -4864, -4826, -2603, -2323, -4936, -5444, -10881, -3398, -3460, -4051, -6080, -4726, -3330, -5913, -4514, -9708, -2940, -3278, -9419, -5049, -7931, -2193, -3486, -4353, -4575, -4653, -2333, -3719, -1933, -3317, -4288, -3790, -4057, -585, -2619, -6018, -6452, -4951, -5, -3009, -13340, -4646, -7322, -224, -4531, -8298, -3373, -11910, -1415, -6536, -5687, -3711, -8413, -4246, -7867, -4259, -5131, -4938, -8504, -10451, -3386, -6804, -2993, -4161, -10671, -3469, -9349, -2556, -2815, -8378, -5085, -9094, -3620, -2359, -9030, -9748, -5670, -6663, -1707, -10671, -5964, -4925, -6982, -1238, -6904, -4084, -6098, -4870, -1593, -4780, -4367, -8449, -4262, -3044, -3837, -7028, -7802, -3321, -5930, -3460, -13684, -7987, -2254, -10288, -3088, -6700, -13398, -1980, -7907, -2537, -5443, -5852, -2529, -5309, -2281, -5477, -3144, -3454, -3354, -2779, -6270, -2284, -3982, -2010, -4131, -8456, -2577, -3993, -1443, -5248, -14405, -3869, -3884, -1780, -5301, -7072, -6484, -3667, -3182, -6687, -4773, -11855, -3411, -6299, -13380, -4030, -9727, -3625, -13249, -6993, -4150, -8273, -5127, -5833, -5646, -4561, -7768, -9798, -3523, -7344, -4823, -7563, -9133, -2409, -13634, -5072, -8797, -8460, -2152, -6157, -5646, -14285, -14051, -2812, -4474, -6838, -10685, -8765, -4529, -4371, -9026, -8921, -7190, -2538, -2793, -5336, -3947, -3232, -2447, -6203, -5527, -1346, -4646, -2657, -11648, -5577, -289, -7774, -3120, -5916, -4942, -409, -4535, -2327, -3789, -3437, -1664, -3652, -1306, -2676, -2158, -4312, -5043, -1433, -2688, -1550, -4704, -12021, -2924, -4046, -1718, -2938, -6369, -5811, -5486, -2140, -2456, -4418, -9238, -4771, -1672, -2623, -5173, -7536, -5012, -1027, -2916, -7563, -5388, -6455, -1047, -3534, -5747, -3857, -6470, -1762, -6188, -4386, -2362, -5764, -3270, -7302, -3486, -1317, -5339, -5938, -2043, -2596, -977, -5002, -5752, -567, -2031, -1364, -5686, -4356, -871, -1595, -2485, -9444, -4559, -3048, -1263, -4310, -9670, -4284, -9537, -1203, -5912, -6224, -3258, -4981, -1598, -5220, -6752, -3456, -3016, -2725, -4270, -13093, -3992, -2290, -3813, -4408, -7856, -1929, -1810, -2808, -6610, -6766, -300, -1490, -1837, -12281, -9620, 182, -1437, -1396, -4540, -5758, -268, -1434, -1067, -2260, -3563, -1245, -1335, -1237, -1190, -3551, -1476, -1500, -2333, -991, -4916, -812, -2049, -2009, -1888, -4600, -483, -2455, -390, -4537, -3079, -788, -2471, -38, -8360, -2618, -1859, -2379, -449, -5758, -2959, -4411, -2219, -90, -6016, -3160, -7765, -2225, 307, -9508, -2980, -4024, -2636, -255, -5505, -3532, -2875, -3524, -1276, -2591, -5988, -3067, -5231, -1555, -1350, -8221, -4186, -8034, -1763, -1154, -3675, -7696, -8156, -2892, -1762, -1783, -8195, -7268, -4659, -2969, -1119, -3649, -6626, -3255, -4262, -1365, -2163, -6289, -1846, -4546, -1670, -1498, -6156, -1979, -4453, -425, -943, -4181, -3783, -5071, 723, -488, -2102, -7526, -5890, 759, -454, -991, -7736, -5490, -412, -1108, -886, -9249, -5507, -2500, -2611, -1753, -11330, -8110, -3541, -4951, -3085, -6498, -11560, -2818, -6163, -3838, -5476, -7744, -1613, -4473, -4503, -4895, -10538, -787, -3815, -4152, -4471, -9289, -772, -5325, -2438, -4617, -7042, -1681, -12156, -1011, -4078, -11124, -3652, -4463, -221, -3429, -6484, -6516, -2117, -224, -4362, -3413, -8298, -1303, -1142, -8465, -2652, -10619, -1620, -3147, -4694, -2958, -9320, -3078, -5244, -2625, -3493, -7538, -4728, -4215, -2782, -3538, -7417, -5557, -4010, -5181, -3169, -3829, -6440, -6266, -8421, -2777, -1878, -4202, -11497, -4542, -2452, -1751, -2812, -4234, -3385, -2148, -2715, -2843, -2160, -3604, -1954, -2837, -3958, -1415, -4855, -2031, -2412, -5695, -1431, -6987, -2535, -2219, -6285, -1866, -8006, -3450, -1908, -5988, -2553, -5303, -4148, -2209, -7158, -3775, -2744, -4606, -3348, -12623, -6204, -1360, -6610, -3959, -7071, -11644, -1069, -13710, -4590, -5496, -9894, -1583, -5968, -8329, -6387, -6163, -2172, -4522, -6894, -9424, -4457, -2212, -4798, -3904, -7938, -4179, -2202, -6264, -3431, -5745, -5168, -2666, -9482, -4409, -5407, -7155, -4061, -10419, -6791, -6801, -8847, -7855, -5501, -8849, -10972, -7787, -7849, 11195, 15123, 10025, 6099, 8571, 11019, 14694, 9644, 5733, 7741, 10391, 13372, 8577, 4369, 4786, 9563, 11038, 6931, 1192, -2344, 9374, 7356, 4436, -3542, 1962, 9099, 3349, 1630, -2046, 1944, 7586, 6115, 2811, -531, 935, 5291, 7372, 2914, 1121, 1036, 6408, 7321, 1143, 1454, 2072, 7296, 6291, 1497, 1177, 3087, 6928, 5468, 3598, 1443, 4050, 5664, 5714, 4290, 2105, 4939, 3856, 6142, 3746, 2319, 5591, 727, 6849, 1885, 1557, 5915, -7395, 7137, -2519, -389, 5801, -1126, 6483, -4415, -2680, 5201, -1921, 4721, -769, -2403, 4188, -739, 1647, -162, -594, 2599, 794, 821, -656, 91, -466, 1178, 2644, -1822, -1098, -11217, 1390, 3262, -1618, -5779, -4820, 1147, 2935, 896, -7053, -5800, -464, 1555, 2522, -6062, -6045, -5268, -1479, 3020, -9656, -3864, -1743, 964, 2638, -5107, -3853, -203, 3374, 1760, -4036, -6396, -1279, 3921, 776, -4029, -16551, -3809, 2968, -236, -3220, -8143, -3589, 368, -1465, -2442, -7889, -10233, -2711, -3780, -2795, -5569, -709, -936, -8300, -5686, -3273, 2446, 737, -3423, -7181, -2279, 3543, 1442, -1155, -2180, -1762, 3392, 861, 137, -815, -746, 2232, -1795, 961, -896, 52, 239, -5979, 1433, -1863, -189, -2099, -897, 1622, -3121, -1718, -3985, 551, 1557, -3537, -2905, -5520, 686, 1261, -2232, -1677, -7394, 27, 715, -885, -1237, -8488, -1059, -213, -377, -2039, -4980, -2121, -1747, -830, -4073, -2595, -3249, -4097, -2325, -6630, -1691, -4229, -7405, -4772, -5486, -2005, -3586, -7187, -7279, -4017, -3260, -3248, -4533, -7752, -3357, -5022, -4191, -3047, -4702, -3228, -5988, -5489, -2174, -3104, -3376, -4316, -6122, -1603, -2904, -3414, -2785, -8958, -1317, -3641, -3062, -2009, -8828, -1351, -4858, -2576, -1824, -4507, -1595, -6319, -2447, -2153, -3322, -1869, -7238, -2943, -2892, -4009, -2192, -6063, -3927, -4048, -7471, -2810, -5060, -5006, -6336, -7996, -4013, -5153, -6513, -12027, -5008, -6226, -6290, -9703, -6730, -4456, -10684, -7420, -12876, -5063, -4618, -8828, -6957, -13355, -4465, -4695, -6007, -6580, -10569, -3031, -4757, -4748, -6951, -6650, -1852, -5345, -4392, -8115, -5484, -1897, -6110, -5073, -11001, -5880, -3632, -5574, -7318, -9674, -5604, -9235, -5218, -9011, -7118, -4163, -8010, -6298, -7697, -7118, -3950, -7467, -7900, -8856, -9572, -5670, -9525, -7093, -9777, -8870, -11966, -4224, -6722, -7543, -6720, -9695, -2019, -7078, -7268, -6368, -8813, -1415, -6884, -7908, -6644, -10736, -2124, -5611, -8390, -6536, -9810, -4488, -4537, -9472, -6533, -7881, -9121, -4070, -12403, -7430, -6232, -5549, -3898, -14521, -8280, -5120, -4089, -3925, -8328, -6393, -5058, -4425, -4379, -6126, -4521, -6278, -5827, -5537, -5533, -3452, -9027, -5927, -8372, -6073, -3144, -11883, -5083, -12795, -7374, -3693, -10706, 7471, 1317, 4615, -14033, 6451, 6761, -946, 3861, 2250, 6218, 4361, 2064, 1361, 3975, 5565, 1245, 4653, -2752, 3802, 4901, 3821, 4949, -1612, 2915, 4689, 5122, 3530, -928, 2833, 4410, 5379, 619, -784, 3273, 3654, 5126, 1850, -228, 3372, 2809, 4595, 4245, 1260, 3195, 2679, 3317, 5555, 3236, 3066, 3585, 2570, 6007, 4835, 3199, 5060, 5802, 5615, 5821, 3574, 6185, 7650, 4281, 6151, 3833, 6600, 8050, 1836, 5719, 3310, 6301, 7191, -1342, 4359, 947, 5430, 4988, -2155, 1953, -4581, 4275, 1230, -1996, -855, 1888, 3139, -1090, -3080, -2669, 3627, 1920, -848, -2718, -4740, 3998, -120, -600, -370, -6840, 3703, -4798, 942, 482, -5468, 3139, -1418, 2099, 270, -1744, 2580, 254, 2134, 83, 206, 1939, -599, 1174, 971, 901, 592, -4386, -109, 2158, 709, -1687, -3201, -668, 2771, -56, -1057, -2015, -653, 2568, -1020, 370, -4131, -1203, 1562, -1873, 813, -8413, -3746, 260, -2548, 481, -4924, -3734, 66, -3146, -998, -6771, -975, 696, -3602, -5177, -5184, -1115, 1081, -3284, -2797, -2198, -5771, 1062, -1997, 6, -1363, -1954, 769, -720, 941, -1541, 928, 396, -202, 718, -2197, 1581, 51, -822, -701, -3020, 1164, -226, -3019, -3831, -3029, 261, -275, -7997, -4819, -2221, -863, -369, -19659, -2074, -2177, -2305, -1211, -8690, -561, -3244, -3692, -3153, -4836, 423, -3537, -3659, -4844, -3733, 1030, -1982, -2668, -3175, -3808, 1179, -958, -1967, -1121, -3089, 819, -892, -1758, -304, -2016, 0, -1850, -1648, -1034, -1839, -1084, -3559, -1352, -3952, -2599, -2187, -4248, -1182, -6726, -3883, -3331, -3728, -1352, -4597, -5022, -4866, -3655, -1972, -5668, -6061, -5979, -4598, -3524, -7075, -7941, -4363, -6821, -7352, -4790, -10153, -3141, -8647, -7694, -4560, -8181, -3059, -8163, -5139, -5967, -6999, -3522, -7499, -4662, -4430, -7789, -3323, -7236, -5095, -2678, -13015, -2370, -8770, -6402, -2326, -8020, -1428, -15172, -5738, -2779, -5912, -718, -6714, -3872, -3293, -6246, -269, -4852, -3756, -3844, -8584, -248, -5726, -6181, -5197, -8974, -895, -9090, -9187, -7961, -7599, -2222, -3604, -4499, -7550, -8094, -3415, -1637, -3358, -5196, -9103, -3766, -1415, -3280, -4638, -8634, -4531, -2375, -3022, -6155, -8514, -6723, -3882, -2388, -12957, -8294, -10702, -4611, -2183, -6208, -6294, -8596, -4624, -3030, -4294, -4482, -6502, -4505, -5533, -4369, -3588, -5140, -4437, -9778, -5678, -3492, -4094, -5129, -8125, -5901, -3924, -3454, -7825, -6824, -5268, -4546, -3504, -13669, -6096, -6415, -5086, -4449, -6758, -6129, -8657, -5754, -5507, -5122, -6649, -5868, -7418, -4495, -4525, -6668, -4849, -10128, -3423, -4501, -6654, -5680, -9210, -3299, -5553, -7664, -8110, -9114, -4008, -9971, -8777, -8515, -9887, -5323, -8213, 2153, 1795, 3912, 3587, 5834, -1016, 1537, 4466, 5109, 5613, 2066, 1108, 5719, 6749, 5662, 4755, 1217, 6345, 7241, 5840, 4602, 781, 5804, 6512, 5032, 2445, -1165, 4060, 4580, 2896, 1283, -330, 1412, 1818, 314, 2223, 989, -1502, -594, 801, 1915, 805, -2466, -1993, 3264, 2110, 52, 1217, -2491, 4804, 3837, -370, 3461, 1191, 5229, 5129, 1590, 4442, 3359, 5230, 5439, 3535, 4021, 3458, 5420, 4640, 4053, 1234, 1504, 5143, 2771, 2996, -656, -252, 3689, 1434, 58, 2848, 505, 725, 1598, -723, 3135, -993, -1702, 1350, 456, 1419, -4105, -508, 626, 15, -3113, -8520, -826, -156, -918, -6508, -1488, -4348, -47, -1237, -2357, 1393, -258, 649, -1318, -869, 2277, 2002, 1054, -1786, 235, 2361, 2321, 970, -2298, 985, 2258, 1436, 338, -2189, 1162, 1883, 110, -861, -1995, 521, 926, -600, -2784, -1977, -1188, -663, -1187, -5786, -2009, -2750, -2117, -1153, -5734, -2331, -1468, -1559, -424, -3789, -3391, -846, -124, -271, -2616, -5094, -1425, 568, -635, -1514, -7855, -2307, 193, -1079, -957, -6199, -1955, -1183, -242, -1688, -1225, -674, -3158, 874, -4361, 557, 144, -2714, 775, -2997, 622, 45, -932, -462, -885, -746, -456, -966, -1615, -916, -3384, 16, -3805, -3124, -3523, -8639, 1030, -4263, -9598, -4733, -6012, 1482, -1416, -4817, -1442, -2525, 1284, -727, -3537, -1493, -2039, 938, -420, -4252, -4997, -2887, 726, -354, -6085, -5058, -2260, 126, -945, -11731, -2710, -1154, -1202, -1769, -7325, -3777, -1094, -2891, -2222, -4635, -9826, -1999, -3706, -3273, -3883, -7014, -3719, -3379, -6908, -5244, -4869, -5933, -2992, -7082, -10324, -5168, -7420, -3277, -4263, -5530, -7436, -7158, -4667, -4579, -4126, -15350, -6271, -7759, -7094, -4505, -11147, -6313, -8923, -7329, -4495, -10853, -8293, -6150, -3947, -3008, -9408, -7699, -4367, -1877, -2408, -9026, -4849, -2898, -1183, -3101, -12385, -3941, -1949, -1875, -4788, -11231, -4544, -1903, -3954, -6879, -9517, -6720, -3039, -5178, -8548, -9850, -8467, -5021, -4193, -7323, -13018, -5354, -5141, -3844, -6560, -9112, -2811, -4752, -4008, -7486, -4419, -1606, -4762, -4680, -7503, -2441, -1777, -4502, -5971, -6081, -1754, -3403, -4646, -6904, -7030, -1869, -5849, -5379, -6375, -17535, -2471, -5899, -5749, -5793, -5734, -3495, -5789, -5025, -5445, -3960, -5428, -6367, -4398, -4889, -4138, -9359, -7064, -5009, -4619, -5597, -7328, -7851, -7654, -5160, -7970, -5438, -9383, -9530, -6483, -9446, -5387, -12105, -8456, -7893, -9236, -6564, -11607, -10606, -7852, -10832, -7544, -11498, -9134, -6662, -15210, -6070, -8433, -6344, -5589, -10395, -4950, -6170, -5338, -4885, -8898, -5055, -5460, -5829, -4232, -8021, -6466, -5481, -9062, -3557, -8159, -9262, -5154, -10191, -3290, -10077, -5350, -5843, -8811, -5320, -9128, -7464, -3738, -10143, -7960, -8100, -9496, -3235, -12739, -9271, -7889, -5974, -4061, -12627, -9218, -7999, -4389, -6014, -9309, -7709, -7663, -4306, -6351, -8323, -6228, -6876, -6256, -4848, -8023, -5981, -6369, -22941, -3874, -7185, -6829, -7207, -7048, -3467, -7086, -8196, -10378, -6642, -3479, -9258, -9857, -7156, -11084, -3651, -9220, -14935, -5104, -7677, -3819, -5829, -12594, -4775, -5058, -4090, -4704, -10755, -5069, -4478, -4545, -4855, -12465, -4925, -4561, -5231, -5501, -8389, -4510, -4559, -6212, -5288, -5943, -4715, -4564, -6756, -4783, -5362, -6670, -5045, -5267, -4956, -6155, -12391, -5872, -3268, -5009, -7774, -4679, -6195, -2051, -4210, -7952, -2658, -5427, -1662, -3561, -6643, -2372, -4257, -1872, -3409, -5854, -3374, -3473, -2318, -3894, -6110, -5644, -3255, -2620, -5374, -7144, -8270, -3633, -2712, -6792, -7214, -7604, -4796, -2792, -5905, -6319, -6949, -7097, -2972, -6274, -5927, -6965, -8726, -3185, -10383, -6426, -6650, -7111, -3338, -7288, -8155, -5905, -6216, -3604, -4812, -10773, -5450, -6311, -4407, -4748, -8935, -5538, -7599, -6173, -6452, -7096, -5857, -10204, -9091, -10233, -5895, -5855, -9265, -11213, -18393, -4744, -5604, -7013, -10177, -15188, -3829, -5427, -5872, -8567, -13044, -3467, -5386, -5846, -7906, -14226, -3806, -5568, -7225, -8231, -15640, -4867, -6064, -7962, -8570, -15315, -6491, -6603, -5666, -8093, -12325, -8361, -6551, -4535, -7626, -8564, -10203, -5893, -4544, -7566, -6681, -10950, -5123, -5408, -7591, -5847, -10538, -4421, -7186, -7343, -5592, -11590, -3902, -11545, -6836, -5673, -13925, -3799, -10239, -6406, -6118, -7636, -4267, -5771, -6545, -7258, -5346, -5225, -3950, -7375, -9963, -4827, -6336, -3422, -8649, -19154, -5777, -7520, -3945, -11323, -9199, -8682, -8992, -5413, -13915, -6826, -13591, -9162, -7564, -8499, -5978, -9332, -7473, -9923, -7084, -6291, -8315, -6112, -12872, -7505, -7801, -8927, -5640, -20680, -9918, -9336, -11811, -6077, -12715, -18131, -8541, -12484, -7082, -9311, -15387, -8505, -8095, -7985, -7318, -16632, -10172, -6551, -8789, -6129, -15036, -11625, -6071, -10040, -5623, -14149, -10038, -5712, -12652, -5786, -8795, -8596, -5150, -17093, -6398, -6442, -7428, -4844, -10921, -6799, -6098, -6908, -5106, -9167, -6896, -7377, -7247, -5934, -9277, -6995, -10019, -8436, -7206, -11837, -6677, -11714, -9005, -8900, -14474, -6423, -10326, -7606, -10715, -8786, -7193, -9644, -7153, -10266, -6949, -9861, -9951, -8611, -9436, -6413, -15358, -10963, -12247, -10379, -6633, -11458, -15410, -11217, -13295, -7154, -11108, -12643, -12588, -9742, -7396, -11499, -9731, -11903, -7479, -7161, -11064, -10301, -8998, -6598, -6914, -11898, -16542, -9630, -6623, -7180, -13601, -11254, -10157, -7547, -8109, -9983, -8363, -6865, -9548, -8945, -8289, -6601, -5682, -12160, -8646, -8391, -5706, -5913, -11865, -8276, -10447, -5925, -6935, -9121, -8354, -7604, -6798, -9462, -6838, -4716, -6822, -6549, -8462, -7693, -4000, -6594, -7895, -6769, -7586, -4973, -6013, -8419, -5617, -7780, -7360, -5270, -5937, -5635, -9492, -7264, -4908, -4523, -7270, -15655, -6850, -5062, -4234, -9884, -13528, -8888, -5614, -4852, -7523, -10928, -7270, -6215, -5311, -6747, -7114, -4923, -6566, -4600, -7739, -4724, -4564, -7040, -4242, -8549, -3727, -5943, -8435, -4850, -7798, -3812, -9394, -9503, -6331, -8229, -4845, -8458, -8618, -8332, -10959, -6702, -8161, -9438, -10704, -9777, -8455, -12745, -8288, -18293, -7542, -8917, -6757, -5409, -10329, -7475, -8013, -4059, -4109, -6316, -7180, -5499, -2730, -3871, -4034, -4328, -3872, -1852, -4352, -2859, -2390, -3590, -1313, -5337, -2758, -1733, -4776, -1285, -6561, -3900, -2343, -8214, -2047, -8071, -6182, -4479, -13300, -4172, -9847, -5768, -6314, -8925, -10777, -7609, -4552, -4439, -8330, -7203, -5519, -4559, -3779, -8590, -5127, -4699, -4959, -4239, -9071, -5260, -4944, -4503, -5149, -10096, -6423, -6439, -3922, -5556, -12913, -7777, -9690, -4341, -5107, -11462, -9815, -12056, -6622, -4521, -7703, -10977, -13298, -11830, -4439, -5979, -7696, -10712, -5605, -5086, -5555, -6830, -6915, -3485, -6244, -6340, -8277, -5108, -2779, -6934, -8530, -14756, -4508, -3014, -6373, -12795, -8122, -4962, -3946, -5447, -20497, -5840, -6385, -5337, -5108, -16593, -5327, -8387, -7255, -5739, -11819, -6191, -10161, -7649, -7019, -10547, -9152, -10066, -5847, -6470, -14486, -10060, -8501, -5217, -5286, -9341, -5770, -7874, -5880, -5256, -5970, -3900, -8430, -7759, -6395, -5144, -3241, -9640, -11092, -7933, -6040, -3405, -10804, -14053, -8638, -9004, -4054, -13237, -11551, -9299, -12484, -5009, -14033, -10711, -9999, -8460, -6175, -9999, -11959, -10288, -7217, -6379, -8146, -14966, -9243, -7447, -6123, -7424, -10787, -8123, -8228, -7030, -7654, -9525, -8109, -7544, -8848, -8383, -10883, -8998, -5887, -8280, -8208, -19806, -10114, -4968, -7492, -8023, -12012, -11740, -5422, -7524, -9341, -8940, -12506, -8279, -6865, -13448, -6894, -7999, -13915, -5800, -15544, -6065, -5780, -8611, -5322, -10285, -6815, -5080, -9507, -5177, -8316, -10562, -5325, -9006, -5229, -8222, -10018, -6044, -6886, -5836, -10249, -6882, -7736, -7052, -6820, -14958, -6880, -13252, -7863, -7128, -11928, -9877, -7676, -7032, -6802, -11699, -13657, -5602, -7377, -6714, -12093, -8943, -5430, -10822, -6575, -10612, -8469, -6471, -9368, -5754, -10230, -9748, -8396, -7060, -5243, -10757, -16112, -9310, -7211, -5730, -10197, -11386, -7731, -8958, -7499, -9370, -9610, -6667, -10252, -10601, -8998, -11204, -6622, -9982, -9833, -8612, -10396, -7354, -10764, -8613, -8016, -8505, -7972, -13083, -8838, -7443, -9133, -7421, -22329, -9933, -7356, -13400, -6717, -12747, -10748, -8053, -11388, -6577, -9403, -10115, -9711, -8863, -6951, -8050, -9368, -13137, -8426, -7709, -8026, -9329, -16157, -9241, -8961, -9285, -10204, -10665, -4364, -6294, -3836, -7219, -9365, -3929, -6002, -5580, -4914, -8936, -4243, -7687, -8215, -4495, -10010, -5284, -8697, -7519, -5838, -12775, -6430, -8266, -7565, -10654, -11040, -7006, -10283, -10751, -9930, -10448, -7897, -13324, -7606, -7022, -9663, -9744, -8958, -4818, -6295, -6927, -10911, -7584, -3691, -5889, -5940, -10517, -7192, -3582, -5363, -7219, -9895, -7168, -4360, -5180, -9619, -8691, -7961, -5198, -5803, -5978, -7237, -10391, -4804, -7380, -4833, -6109, -10396, -4192, -9450, -5547, -5263, -9089, -3209, -10289, -6763, -4585, -6318, -1948, -8639, -6093, -4576, -4159, -1231, -6172, -5231, -5832, -3620, -1236, -4528, -3804, -6468, -4263, -1849, -3621, -2225, -4256, -4723, -2965, -2791, -1475, -3322, -4411, -4578, -1826, -1700, -3905, -4468, -6272, -1273, -2831, -6034, -4816, -5906, -1430, -4717, -8818, -4714, -4902, -2262, -6920, -8330, -4036, -4736, -3635, -8333, -7975, -3348, -5249, -4955, -8431, -7728, -2994, -6889, -5195, -8476, -6570, -3102, -13434, -5928, -9587, -5214, -3852, -6093, -7567, -11295, -4506, -5399, -3752, -5774, -9771, -4808, -6523, -3233, -4852, -8863, -5962, -6095, -3654, -5989, -8809, -6196, -6473, -4103, -7589, -9073, -5738, -7981, -4108, -5257, -8939, -6148, -8299, -4780, -3803, -6527, -6477, -6990, -7861, -3288, -4499, -6232, -6105, -10866, -3259, -3479, -6646, -5314, -6065, -3503, -3374, -7567, -4174, -5087, -3853, -4226, -8037, -3362, -5254, -4256, -6220, -8814, -3278, -6154, -5008, -9116, -10928, -3834, -7891, -6764, -9195, -9869, -4800, -10372, -11778, -8982, -7745, -6119, -11778, -10249, -10527, -7539, -7762, -9666, -7519, -11275, -9557, -9285, -7147, -7933, -10382, -14017, -13071, -6178, -12286, -10424, -9186, -10255, -7514, -11687, -8993, -7492, -6503, -9128, -10698, -7872, -7326, -5508, -4999, -16246, -7830, -8372, -6157, -3467, -8183, -8341, -9524, -8154, -3266, -6474, -8933, -10035, -9500, -3579, -6851, -9384, -10592, -9732, -3931, -8966, -10573, -9352, -10725, -4621, -8411, -12677, -8166, -8141, -5573, -6177, -10671, -6396, -7005, -5019, -5664, -8539, -4903, -7998, -4353, -6129, -7154, -4439, -8108, -5015, -6479, -6239, -4922, -6675, -6239, -7302, -5595, -5903, -7161, -5943, -9650, -5466, -6010, -10543, -6084, -7520, -6087, -5225, -15220, -7054, -5292, -6691, -4902, -11189, -6657, -4647, -6504, -5288, -11743, -5961, -5358, -6616, -6282, -13219, -6286, -7658, -6664, -7806, -14203, -7961, -9002, -6051, -8918, -12693, -12553, -6606, -6071, -8136, -9552, -11452, -5097, -7414, -7769, -7945, -8942, -4260, -9978, -9190, -7114, -9340, -4201, -10764, -13846, -5954, -15349, -5477, -9096, -10039, -4706, -9028, -10172, -7495, -8385, -4112, -5674, -7674, -6897, -8848, -4367, -4294, -4688, -7419, -10627, -5427, -3950, -3679, -8725, -9351, -7109, -4392, -3577, -9706, -6925, -9179, -5632, -4123, -9339, -5498, -11658, -7746, -5061, -8542, -4782, -13051, -8615, -5995, 10207, 11289, 9083, 11137, 8447, 9430, 10944, 8381, 10592, 8026, 7216, 9886, 6198, 8985, 6673, 6633, 8129, 4138, 6584, 4431, 7475, 6153, 5042, 4490, 3804, 6993, 5102, 5109, 3740, 4357, 5154, 4561, 3913, 3153, 3361, 3044, 3469, 1068, 2251, 46, 5734, 1797, -3758, 2245, -1866, 7030, 564, 1773, 1725, 1478, 6789, 625, 3127, -1614, 3713, 6222, 488, 3036, -562, 5623, 5979, 1255, 3515, 3295, 6951, 4547, 3822, 4257, 4597, 7390, -822, 4900, 3891, 4550, 6732, 826, 4401, 2104, 3719, 4627, 2534, 2473, -938, 2962, -219, 1731, -34, -1834, 2546, -1652, 296, -325, -1352, 2012, -161, 110, -52, -1516, 1491, -1138, 1025, -483, -1726, 1399, -1913, 1741, -1410, -987, 1403, -1115, 1689, -1125, -40, 831, -211, 353, 543, -80, -702, -268, -1854, 1470, -1423, -4196, -1443, 1014, 1393, -2236, -3751, -2075, 2777, 588, -92, 156, -1659, 3229, -489, 1328, 1353, -2081, 2877, -1334, 1669, 744, -1109, 1810, -1551, 1024, -2013, 743, 890, -1334, -573, -3908, 1664, 2001, -1130, -2663, -2071, 1890, 2865, -872, -2943, -3700, 1837, 2831, -270, -1210, -6507, 1574, 2720, -90, 239, -577, 784, 2899, -1803, 1098, 983, -818, 2646, -5786, 1519, 789, -3360, 1812, -615, 1551, -667, -9003, 940, 404, 1184, -1470, -3667, 193, -742, 497, -1471, -710, -601, -2693, -262, -4084, 478, -929, -1549, -687, -2203, 1135, -674, -381, -561, 895, 1537, -720, -271, -731, 1593, 1380, -1903, -1418, -2215, 596, 488, -5180, -3958, -6036, -2502, -1253, -8537, -4943, -11206, -5160, -4763, -5640, -3247, -5166, -1946, -7933, -5692, -1330, -1766, -398, -2854, -7819, -79, -219, 665, -1759, -10432, 51, -41, 1234, -2617, -5774, -1231, -1204, 1088, -5262, -3406, -5013, -4180, 88, -4682, -2510, -7221, -6368, -1986, -2630, -2390, -4973, -4483, -5984, -1756, -2469, -4899, -4610, -6454, -1856, -2687, -3228, -6005, -3629, -3222, -3783, -2565, -6734, -2752, -7600, -6444, -3639, -5262, -2601, -7169, -2645, -4663, -2591, -2349, -4601, -60, -3248, -847, -1804, -5712, 1000, -2539, -362, -1421, -7959, 1097, -3055, -943, -1731, -5327, 408, -4410, -1942, -2930, -5813, -1139, -4321, -2170, -3867, -7668, -4112, -3678, -1571, -3272, -4025, -6533, -4260, -973, -2701, -2626, -3591, -6282, -1033, -2514, -2780, -2551, -9603, -1826, -2444, -3987, -2360, -8058, -2500, -2464, -5667, -2311, -6635, -2500, -3015, -6611, -2884, -7232, -2174, -4393, -6850, -3689, -11287, -1442, -5914, -7380, -1876, -8607, -1157, -5547, -5864, -537, -7727, -2009, -4643, -3494, -603, -8298, -4132, -4745, -2530, -1954, -3908, -5005, -6482, -3294, -4320, -2201, -3564, -8216, -7161, -5690, -2257, -2733, -6127, -9394, -4781, -2998, -2583, -3481, -7349, 5426, 7847, 9313, 7297, 4636, 5085, 7058, 8906, 6891, 6119, 4043, 4658, 7771, 5909, 7459, 2156, 2417, 6234, 5217, 7788, -1435, 1624, 5049, 5095, 7408, -7233, -3838, 4569, 4327, 6644, -901, -94, 3901, 1247, 5628, 546, 2292, 3526, -2961, 4485, 1089, 2669, 4078, 1769, 4119, 257, 2406, 3876, 672, 4579, -46, 2191, 2664, 96, 5252, 4383, 2794, 2833, 4355, 5809, 6437, 3970, 3823, 5731, 5659, 6971, 4748, 3719, 5315, 4453, 6348, 4851, 2532, 2791, 2260, 4618, 4379, 1086, -8967, 813, 1747, 3504, 474, 1170, 1665, 656, 2502, -629, 2487, 2435, 1586, 1424, -1338, 2665, 2198, 903, -639, 1323, 2723, 670, -3224, -1740, 2583, 2562, -3183, -2303, 757, 2232, 1425, -3889, 1318, 1349, 528, -629, -666, 2355, 216, -310, 590, -34, 2543, -2223, 1015, 1222, -286, 2181, -3519, 1729, -234, -448, 874, -4004, 1344, -1421, -769, -2573, -5363, -1150, -254, -1731, -6367, -5754, -2257, -787, -1895, -884, -4020, 1781, -3247, -481, 896, -1826, 2605, -3712, -117, 1559, -668, 1196, -2059, -1999, 1519, -1375, -2616, -1751, -10551, 1487, -6260, -456, -2258, -1066, 1966, -3019, 589, -2636, 819, 2356, -1004, 39, -3487, 1438, 2445, -993, -1235, -4447, 1845, 2441, -462, -2703, -3742, 2280, 2201, 496, -1995, -2080, 2322, 1166, 981, -201, 444, 1756, -1499, 868, 431, 1756, 806, -3667, -112, -238, 1637, -78, -1968, -1412, -2136, 109, -646, -3260, -733, -5007, -2825, -1485, -9342, 109, -10058, -5639, -4041, -4338, 254, -9527, -5977, -12869, -2969, 285, -5502, -5068, -4607, -1379, 469, -3507, -3972, -3367, -219, 405, -2348, -2465, -3265, -347, -173, -1863, -1051, -3589, -1807, -931, -1612, -414, -4401, -4781, -861, -1242, -673, -5615, -13421, -194, -944, -1880, -6549, -7062, 327, -1004, -4253, -7672, -4454, 748, -1496, -5510, -13924, -3132, 923, -2578, -3646, -7889, -2116, 404, -5211, -3170, -5116, -1094, -1253, -7590, -3962, -4729, -190, -4422, -3925, -4724, -5366, 176, -4380, -3646, -4135, -5588, -196, -2938, -6095, -2935, -4876, -1312, -2734, -8116, -2162, -4472, -3171, -3102, -10162, -2307, -5976, -5890, -3760, -5903, -3491, -9974, -7713, -4368, -1577, -6112, -5954, -5608, -3784, 30, -7232, -4160, -3885, -2656, 375, -4147, -1974, -3448, -2591, -104, -2696, -669, -4437, -3507, -1342, -2292, -787, -6889, -3156, -3878, -2933, -2172, -8951, -2564, -14786, -4893, -3482, -6806, -3435, -5097, -4805, -2796, -4327, -5656, -3335, -3204, -1890, -3247, -6490, -4428, -3529, -1462, -2997, -4216, -10286, -6461, -1467, -2295, -3052, -2273, -15047, -1709, -1113, -4487, -3, -7242, -1887, -336, -7340, 491, -3356, -2034, -380, -1820, -228, -857, -2469, -1405, -209, -1899, 295, -2879, 9652, 7124, -6527, 7067, 8584, 9372, 7627, 4321, 7288, 8635, 8507, 8128, 6618, 7542, 8691, 6993, 7912, 7318, 7372, 8450, 5156, 7030, 7061, 6655, 7534, 4824, 5754, 6076, 5354, 5562, 5020, 4152, 4597, 3849, 2168, 3748, 1157, 3080, 3905, -862, -888, -4556, 1962, 4386, 440, 1776, 1834, -482, 3628, 2068, 4814, 2591, -2346, 2446, 1044, 6083, 3325, 3300, 3420, -8072, 6245, 4934, 4483, 3509, 1315, 5062, 5033, 2977, 2414, 1922, 1231, 2650, -7803, 3735, 4001, -994, -396, 3097, 4750, 6221, 2117, 3058, 4447, 4182, 6836, 1332, 3289, 3808, 2267, 6175, -2967, 1953, 2041, -705, 4531, -3984, 268, 555, -6472, 2323, -252, -245, 1111, -3071, 1547, 589, 90, 2149, 168, 2513, -158, -521, 2545, 1469, 3099, -3443, -3551, 2239, 1852, 3305, -5347, -5659, 1439, 1681, 3407, -1643, -2718, 664, 1044, 3140, -836, -3775, 451, -421, 1750, -909, -8705, 356, -2317, -2939, -1755, -3895, 55, 313, -1306, -2954, -3244, 290, 2307, 1473, -2253, -2582, 1121, 2993, 1894, -1241, -812, 1586, 2776, 1418, -694, -196, 1431, 1897, 301, -354, -91, 871, 447, -2935, -300, 497, 132, -1759, -1713, -692, 664, -1077, -5634, 1413, -1322, -130, -2534, -9987, 2011, -1774, -1518, 21, -4793, 692, -783, -4924, 2058, -2960, -3722, 1082, -4365, 2653, -2402, -2916, 1796, -616, 2184, -3321, -672, 892, -837, 1125, -5352, -197, -2158, -4373, -104, -2044, -116, -4696, -799, -1885, 108, -455, -3788, 609, -3943, 912, -1172, -5821, -365, -3853, 922, -1494, -10726, -3632, -4144, 351, -1992, -13746, -7281, -6012, -870, -4088, -7003, -8955, -9928, -2215, -10930, -4801, -4130, -9607, -1677, -6667, -4013, -2026, -7841, -1256, -4379, -3478, -2305, -7516, -2244, -2726, -3069, -5169, -7457, -3927, -1566, -3072, -5952, -8071, -4662, -1407, -3683, -3284, -12012, -6466, -2627, -5559, -2466, -8503, -8260, -7049, -12068, -1939, -6263, -5644, -5535, -5532, -1498, -8145, -3326, -1547, -2922, -1460, -8897, -1785, -83, -2035, -1681, -3586, -1615, 262, -2335, -1801, -1720, -3506, 34, -3925, -1776, -1105, -7138, -351, -7320, -2071, -1136, -2049, -1030, -13759, -3510, -1246, -409, -2428, -11366, -7703, -1434, -345, -3435, -6548, -4630, -2223, -1301, -2075, -4725, -2506, -3777, -3015, -810, -3991, -2467, -5095, -5961, -163, -3725, -3751, -5199, -6350, -106, -4025, -4216, -6003, -3078, -822, -4461, -2049, -9318, -1990, -2599, -3994, -206, -8426, -2517, -5395, -3002, 684, -5990, -5066, -4987, -2271, 701, -4272, -9414, -2754, -1898, 125, -2779, -4829, -1562, -1654, -710, -2591, -4261, -1492, -1627, -1909, -3583, -5441, -2417, -2053, -3650, -2863, -2625, -3523, -2894, -4334, -1597, -473, -3340, -4067, -3633, -1699, 232, -2580, -4067, -2308, -3084, -1180, -6092, -4239, -1293, -4354, -36, -2800, -3728, -1102, -5333, 72, -1672, -1911, -1753, -4297, -556, -1852, -986, -3200, -4189, -1704, -2067, -1346, -5424, -6356, -3116, -1528, -2690, -6495, -5987, -3808, -981, -3077, -4233, -4180, -3316, -640, -2510, -2383, -6287, -2277, -429, -2864, -1384, -5192, -1512, -475, -3355, -1349, -966, -1403, -881, -2271, -2630, 389, -1847, -1543, -1237, -4508, 338, -2645, -1930, -979, -2698, -646, -3822, -1645, -1614, -1494, -1975, -5789, -1433, -3747, -1685, -2633, -8070, -1757, -8432, -3345, -3061, -5691, -1998, -3004, -8269, -4698, -4254, -1247, -599, -4812, -2980, -4254, -336, 249, -2421, -411, -4544, -81, -145, -2301, 396, -4487, -860, -1777, -4124, -241, -4998, -3200, -3160, -8355, -2338, -5146, -7469, -2295, -9141, -5032, -3662, -5895, -1874, -5905, -5154, -2514, -5081, -2382, -4328, -6181, -2148, -4711, -4073, -4849, -8862, -2655, -3913, -8250, -4878, -8104, -4369, -3010, -6854, -3375, -5052, -6610, -2190, -4762, -2965, -3345, -5969, -1668, -5101, -3189, -3193, -5337, -1630, -7802, -3245, -4524, -4370, -2125, -8453, -3168, -6898, -3635, -3126, -6650, -3888, -6152, -4153, -4874, -7013, -7049, -4643, -6797, -8176, -7959, -7043, -4792, -14044, -4507, -7943, -3770, -7443, -6466, -1643, -7323, -3277, -7378, -5406, -580, -7269, -4736, -4354, -6025, -960, -8876, -6648, -4096, -7668, -2995, -12681, -3646, -6702, -9556, -6765, -12470, -1753, -6742, -7613, -4703, -9559, -975, -2850, -4852, -3019, -7457, -1062, -1342, -2897, -2641, -6713, -1993, -831, -1659, -2941, -6644, -3833, -972, -1070, -3118, -6411, -6991, -1778, -1119, -3081, -6290, -8705, -2943, -1677, -3203, -7092, -5220, -2945, -2155, -3704, -7188, -3990, -2399, -2346, -4409, -5589, -4399, -2796, -3158, -4166, -5033, -6164, -4740, -5073, -3487, -5275, -8020, -9252, -5519, -3013, -5280, -7049, -6241, -4112, -2602, -5002, -4342, -4485, -3499, -2209, -5353, -2726, -3989, -3586, -1779, -7542, -2447, -3624, -4131, -1538, -10178, -3316, -3414, -4716, -1680, -6510, -4780, -3717, -4943, -1959, -5807, -5592, -4417, -5193, -2187, -6896, -5312, -4970, -5971, -2826, -9528, -4553, -5374, -7619, -4631, -11720, -4032, -6466, -10981, -9776, -9626, -3596, -7883, -7643, -7926, -9450, -3189, -6556, -4514, -5081, -10063, -3555, -5838, -3001, -4330, -5326, -5705, -6934, -2437, -4379, -3222, -13828, -8629, -2534, -4638, -3081, -6308, -7829, -3122, -4884, -4988, -4575, -8347, -4172, -5425, -12266, -3980, -12652, -5641, -6592, -8644, -3517, -9681, -6087, -8262, -6792, -3360, -7437, -5156, -9033, -6179, -3928, -7239, -4846, -7804, -6242, -5451, -7585, -5468, -6124, -7393, -7578, -6948, -6962, -4992, -10180, -8464, -5689, -10150, -5007, -9271, -9298, -5037, -12223, -7211, -6436, -12225, -5674, -6543, -12220, -5783, -11803, -8592, -4992, -5941, -3157, -170, -3957, 419, -2841, -3929, -1142, -4620, -314, -3270, -2281, -2919, -3992, -1859, -5558, -532, -5426, -4294, -4450, -10597, 248, -5391, -4548, -9407, -3583, -35, -3340, -3159, -7880, -1402, -1515, -2693, -2726, -6853, -692, -4796, -3774, -3899, -7827, -1072, -6084, -8339, -5251, -6331, -2497, -3400, -7077, -4072, -4268, -4882, -2502, -4276, -3589, -3245, -7636, -2608, -3600, -4090, -3282, -9546, -3455, -3308, -4841, -4708, -8275, -4656, -2979, -5731, -9120, -5274, -5088, -2714, -6845, -9933, -3065, -4837, -2564, -7328, -5654, -1960, -4820, -2365, -6734, -3859, -2256, -5088, -1539, -5890, -4024, -4679, -4334, -322, -4506, -10133, -2871, -2397, 300, -2445, -3656, -186, -1113, -244, -1247, -620, 543, -552, -2311, -1136, 177, -4, -276, -3337, -1706, -466, -1231, -500, -2301, -2313, -2774, -2075, -2132, -3227, -2650, -6498, -2054, -7939, -3448, -2781, -5073, -1721, -3973, -1305, -3086, -6035, -1765, -1945, -533, -4356, -16899, -2541, -1818, -706, -6369, -5265, -4491, -2578, -1216, -4346, -3699, -10344, -3971, -1983, -3044, -4514, -7241, -6979, -2824, -3433, -10366, -5372, -9833, -3742, -6117, -5688, -5513, -3639, -6728, -9176, -3372, -5632, -1562, -6172, -3954, -3871, -4747, -992, -3247, -2446, -7278, -3462, -1548, -3282, -1876, -5573, -2696, -2417, -4861, -1604, -2894, -2699, -1627, -3137, -1879, -1806, -3529, -636, -1494, -2835, -1315, -5640, -629, -1268, -3994, -1102, -7340, -1609, -2153, -4626, -1179, -3667, -3165, -4117, -4095, -1683, -1811, -4122, -7872, -3229, -2724, -1385, -3690, -10671, -2923, -4360, -2363, -2690, -6183, -3171, -6327, -5682, -2145, -4540, -3834, -6881, -12452, -2398, -4211, -4850, -5589, -7662, -2900, -5063, -5796, -4179, -7179, -2366, -6936, -5940, -3622, -3547, -1541, -6389, -6049, -4282, -2157, -1368, -4364, -7178, -6198, -2702, -2154, -3233, -9029, -6981, -5334, -4461, -2787, -7655, -3614, -9777, -7026, -2835, -5070, -1319, -8361, -4223, -3253, -3094, -448, -9863, -3240, -3538, -2131, -806, -18134, -3532, -2913, -2198, -1992, -9332, -4367, -2200, -3003, -2578, -7431, -5050, -2440, -3693, -2335, -6507, -5188, -4258, -3720, -2648, -5348, -4864, -6207, -3824, -3727, -4056, -4372, -4311, -4385, -5038, -3425, -3762, -4365, -5165, -6263, -3861, -2949, -5523, -5803, -7267, -5535, -2440, -3450, -6491, -6583, -7471, -2905, -2155, -7149, -5838, -7255, -5139, -2232, -6117, -5664, -7448, -9986, -3195, -5670, -6103, -9060, -5480, -4686, -7828, -7515, -11807, -4176, -6412, -10395, -8694, -8353, -4366, -7673, -6264, -7269, -4235, -5007, -7954, -5487, -5539, -2070, -5206, -7984, -5717, -4639, -1338, -5335, -9191, -5433, -4683, -1827, -6415, -13691, -4209, -5045, -3519, -8156, -12743, -3118, -4772, -6756, -6671, -9288, -2765, -4329, -8963, -6039, -8329, -3145, -4475, -6576, -7427, -8702, -3934, -5309, -6314, -5477, -3410, -3167, -66, -2262, -5855, -3498, -5408, -1286, -2858, -5521, -3041, -5328, -4032, -4533, -6361, -2287, -3867, -20243, -4777, -10200, -2155, -2661, -5044, -3543, -9783, -3018, -1798, -4161, -3724, -4886, -4616, -1429, -7303, -5895, -2396, -4869, -1700, -6545, -6492, -949, -3431, -2717, -2493, -2300, -565, -2311, -4681, -1593, -456, -1694, -1798, -8494, -2401, -264, -6883, -1563, -11681, -4056, -1761, -3721, -1230, -5505, -3650, -5053, -947, -821, -2387, -3506, -3741, -358, -624, -405, -3536, -2328, -642, -790, 472, -970, -2018, -1064, -1438, 77, 912, -1657, -583, -2990, -2015, 1734, -664, 340, -4616, -3717, 1779, 565, 722, -2975, -1722, 1200, 1446, 669, -2045, -1682, 17, 1739, 477, -2367, -3931, -1958, 1421, -69, -3265, -7861, -5522, 510, -1234, -3364, -5265, -17262, -914, -2866, -2765, -4489, -7162, -2282, -3834, -2555, -3742, -5362, -3331, -3263, -2447, -3105, -3817, -6616, -3147, -1883, -3630, -2625, -6406, -4667, -1269, -5446, -2050, -2187, -9455, -626, -7359, -1879, -1076, -5427, 148, -6831, -1534, -1283, -2948, 483, -4340, -944, -2099, -2338, -155, -3232, -947, -2821, -3413, -2428, -3920, -2179, -3242, -7184, -12341, -7016, -4100, -3160, -5233, -3558, -14145, -3318, -2490, -3249, -1710, -7597, -2832, -2170, -3325, -1787, -6355, -3936, -2602, -4810, -2898, -5908, -5624, -3795, -8726, -3745, -5841, -3629, -5146, -8145, -4212, -6266, -1858, -3569, -3990, -6194, -5008, -1244, -2718, -2468, -10348, -2920, -1426, -4559, -2215, -7165, -2210, -2518, -10184, -2919, -6182, -3111, -6181, -2783, -4790, -6442, -3864, -3545, -859, -16235, -6619, -1850, -595, -2, -3783, -5489, -641, 56, 310, -930, -3593, -440, -895, -13, -139, -2242, -907, -3589, -963, -691, -2010, -1697, -8947, -1732, -1890, -2865, -1927, -12190, -1474, -2324, -3764, -1104, -6571, -1214, -2128, -3762, -508, -5101, -1675, -1924, -4087, -850, -5613, -2976, -2142, -5175, -2255, -4302, -4548, -3586, -6211, -4518, -3139, -4060, -8390, -5934, -6325, -4610, -2357, -7488, -5683, -6163, -7341, -1213, -4894, -4927, -6371, -2692, -1206, -5002, -3591, -9952, -1444, -3129, -5790, -2942, -8019, -1823, -13260, -5479, -3063, -4223, -3022, -3420, -5042, -3514, -3078, -3803, -1685, -5575, -3754, -3408, -4172, -1592, -8212, -3633, -5294, -4751, -2493, -10080, -3281, -8064, -4468, -4490, -5562, -2984, -6170, -3963, -7899, -4475, -3326, -5320, -4466, -5433, -4894, -5054, -5898, -6387, -3080, -5548, -10698, -6944, -9742, -2464, -5787, -7323, -7028, -11875, -3031, -6788, -4895, -6152, -15868, -3168, -8866, -4532, -5277, -7629, -2080, -10652, -5437, -4903, -5330, -1388, -10577, -7358, -5212, -4795, -1010, -9603, -9015, -6117, -5454, -606, -8182, -9363, -6617, -7009, -517, -6436, -9368, -6261, -6469, -1053, -6020, -8244, -6454, -4848, -2195, 6928, 7161, 7582, 9663, 3009, 6574, 6930, 7288, 8942, 2336, 5736, 5959, 6643, 6362, 551, 4880, 4033, 6077, -2389, 1134, 4115, 3344, 5678, 3457, 2681, 3483, 3649, 5306, 3935, 2660, 2102, 2126, 4541, 2237, 516, -2154, -289, 2802, 3058, -1716, 3671, 2723, 322, 4541, 2205, 5567, 3995, -57, 4703, 3907, 5418, 4148, -1085, 3697, 5001, 3807, 4239, -3546, 1478, 6029, 1668, 4889, 818, -144, 6718, 1282, 5574, 2393, 1204, 6736, 1982, 5516, 2036, 1773, 5835, 1456, 4272, -5, 1474, 3807, -453, 1723, -367, 723, 1272, 1176, 589, 1470, -87, -532, 1951, 1410, 2149, -182, -2145, 820, 1516, 1956, 714, 1835, 1723, 1139, 1227, 1601, 3241, 4201, 697, 407, 1961, 2985, 5495, 625, 86, 1831, 1753, 5665, 644, 258, 1375, 101, 4633, 408, 428, 591, 101, 1964, 73, 586, -1114, 1791, -3599, 341, 1153, -5101, 2327, -3064, 1556, 1648, -5711, 1436, -3218, 2393, 1225, -6239, -1028, -2614, 2159, -112, -3314, -6108, -490, 634, -104, -935, -7254, 1131, -2714, 266, -725, -2490, 2436, -5403, -995, -1625, 141, 3343, -2207, -1860, -1732, 1613, 3657, -1396, -380, -920, 2091, 3269, -2605, -115, -694, 1471, 2147, -8207, -1260, -1161, -634, 487, -5559, -2514, -1353, -5645, -720, -3252, -1475, -1312, -5870, -873, -3397, -1416, -2092, -3917, -921, -4442, -3653, -3683, -3276, -1468, -2817, -6368, -4562, -2547, -2602, -945, -5453, -3824, -2102, -3643, -496, -10197, -3446, -2567, -3957, -1277, -5898, -4932, -4097, -3617, -2940, -3369, -12484, -5700, -3037, -4624, -2317, -5191, -6881, -2797, -4694, -1040, -3485, -9315, -3042, -3857, -200, -3721, -8256, -3425, -3250, -339, -3769, -6949, -3035, -2842, -1585, -1973, -5703, -2145, -2747, -3759, -602, -4099, -1649, -3167, -5274, -249, -3214, -1890, -4350, -6286, -1009, -3009, -3173, -7507, -6186, -3358, -3037, -6044, -9712, -3886, -9717, -2858, -4379, -4317, -3178, -6481, -2575, -1477, -2575, -4203, -5782, -2697, -165, -2142, -5758, -7880, -3698, -55, -2516, -4626, -9078, -6360, -1198, -3214, -4071, -7936, -8296, -3909, -3814, -5051, -7098, -4863, -6324, -4723, -6959, -5957, -3596, -5381, -6863, -5569, -4869, -3771, -5398, -9812, -3639, -3449, -5759, -6330, -7022, -2587, -2509, -9998, -7825, -5322, -2124, -2606, -5872, -7187, -4567, -1959, -3973, -4872, -7178, -4412, -1840, -7693, -6145, -8514, -5065, -1816, -10338, -9791, -6354, -6935, -2090, -5574, -7507, -5249, -10146, -2684, -4477, -6408, -5846, -8380, -3063, -4549, -7633, -7512, -6250, -2611, -4874, -9968, -9417, -5461, -2196, -5033, -10329, -9230, -5494, -2565, -5050, -7495, -7770, -5990, -3404, -4994, -5494, -7295, -6686, -3496, -5244, -5669, -7175, -7101, -3513, -5959, -9259, -6859, -6415, -4417, -6444, -6359, -1981, 7876, 7695, 8495, 8237, -2844, 7481, 7270, 7862, 7545, 1019, 6019, 5665, 6034, 5202, 3039, 2185, 2306, 5340, -953, 3467, -1751, 3379, 6516, -117, 3658, 2522, 4529, 6607, 2003, 4490, 2914, 3987, 5438, 1648, 5270, 2903, 3379, 3369, -873, 5512, 2931, 3175, 1822, -2892, 5008, 2496, 1168, 220, -3019, 3421, 1830, -4198, -2965, -1917, 2406, 1767, 2827, 1174, 509, 4688, 2281, 4282, 2522, -37, 5930, 2738, 4040, 2101, -5544, 6003, 2823, 2793, 766, -3529, 5412, 2160, 1395, -503, -2334, 4763, 194, 657, -1395, -5836, 4156, -4541, -263, -2714, -6537, 2816, -3596, -1707, -728, -2451, -1709, -784, 231, 1996, -855, -251, 214, 1987, 2531, 152, 3082, 342, 2359, 300, 813, 3486, 164, 1775, -2561, 1035, 2136, 271, 621, 2147, 408, -696, 702, -1360, 3150, -1099, -2018, 944, -8521, 3171, 847, -1162, 473, -2446, 3282, 2751, 143, -1128, 31, 3279, 2878, 1415, -2750, 35, 2765, 1139, 2366, 390, -2352, 1736, -3317, 2803, 2860, -7559, 611, -4770, 2225, 4179, -3502, -87, -5472, -484, 4644, -5787, -1006, -3457, -4922, 4405, -4343, -2748, -1305, 943, 3514, -212, -2991, -843, 2521, 2064, 748, -836, -1403, 3056, 516, 233, 886, -1366, 2921, -400, -794, 2005, -3, 1891, -1284, -1647, 2547, 456, -449, -3947, -3161, 2391, -251, -4949, -10357, -2631, 1181, -1484, -7207, -6178, -821, -2308, -2560, -5659, -11313, -580, -5646, -2848, -3473, -2267, -1680, -967, -2630, -2106, 56, -3239, -401, -3008, -2384, 407, -4374, -1663, -3304, -4877, -627, -4487, -4751, -4659, -9247, -2585, -2020, -9640, -8211, -5383, -3012, -327, -11648, -2926, -5704, -2565, 378, -6753, -1507, -7532, -3347, 483, -4807, -2080, -3945, -4303, 264, -4548, -4391, -2012, -3684, -187, -4851, -6521, -1326, -3289, -980, -4349, -5678, -1515, -2131, -2063, -3427, -6038, -2768, -864, -2668, -2829, -7045, -6107, -792, -2995, -2743, -6596, -12351, -2175, -3964, -3177, -5050, -7948, -4977, -3998, -3949, -3822, -7796, -6941, -3381, -4913, -3246, -4481, -7580, -4051, -6255, -3220, -2724, -7102, -5431, -6488, -3589, -2407, -5400, -5885, -4847, -4463, -2929, -4341, -6888, -4257, -6679, -3643, -3892, -5181, -5014, -18357, -3975, -4023, -3273, -6397, -5969, -4322, -4631, -3067, -6547, -3801, -5631, -4851, -4139, -5174, -3317, -8692, -4473, -5120, -3951, -3770, -9338, -4609, -5421, -3673, -4699, -8021, -5558, -6945, -4439, -5838, -9140, -6951, -8590, -6337, -7444, -14789, -8155, -6678, -9408, -9408, -12676, -8249, -5398, -12206, -9098, -11849, -6063, -4893, -14348, -8102, -14796, -3920, -5688, -8043, -8041, -11395, -3023, -9351, -5778, -8808, -9526, -3716, -11085, -4731, -10442, -9287, -7182, -8530, -3985, -15913, -9585, -9185, -10307, -3460, -10567, 6844, 8184, 3420, 5950, 6590, 5716, 7520, 2915, 5650, 5578, 1323, 5655, 1526, 4481, 1420, 2109, 4602, 938, 2294, 15, 4468, 5518, 3231, 2469, 3187, 5793, 5964, 4592, 3694, 3339, 6224, 5655, 4528, 4454, 2352, 5057, 4221, 3430, 5324, 971, 1833, -301, 2190, 5579, 373, 2644, 850, 1098, 4721, 980, 4056, 3616, -1585, 2925, 537, 4012, 4156, -3087, 1117, -3988, 3210, 4093, 1451, -2670, -2487, 1519, 3634, 2380, -613, -810, -2387, 2590, 568, 2761, -6471, -488, 1010, -5312, 3534, 340, 1823, -1565, 1888, 3010, 3257, 1775, -3382, 3422, 2002, 4252, -685, -951, 3397, 1173, 4308, -3154, 168, 2609, -479, 3921, 1052, 588, 1830, -3238, 3553, 2378, 610, 1794, -208, 3373, 2364, 113, 2254, 1288, 3176, 1322, -1241, 2383, 1270, 2722, -950, -4485, 1628, 102, 1826, -5666, -8227, -513, -1899, 410, -4133, -3782, -6552, -905, -1388, -2513, -747, -3604, 1420, -3010, -3860, 972, -216, 2714, -628, -2463, 1139, 963, 3132, 1691, 105, 357, 731, 2731, 2376, 650, 659, -968, 1401, 1577, -86, 1151, -5024, -280, -273, -1284, 615, -7242, 329, -1523, -2322, -285, -1319, 1239, -3131, -4030, -1557, 1273, 1204, -2623, -4930, -4765, 2533, 382, 31, -3846, -2702, 2810, -1149, 1031, -2436, -2306, 2244, -3404, 1046, 817, -8994, 1047, -4395, 638, 2113, -1506, 182, -2293, 232, 1249, 408, 245, -443, 303, -2615, -457, 2, 388, 1146, -1225, -3270, -964, 114, 1823, 69, -1130, -1849, -1146, 1661, -1202, -555, -1365, -2727, 687, -4664, -2784, -860, -4224, -719, -8293, -6623, -1237, -5927, -2521, -5505, -3504, -1674, -4074, -4433, -3443, -3662, -1029, -1584, -4872, -3436, -5480, -604, 87, -4061, -6831, -6373, -954, 895, -2930, -4665, -5970, -1481, 869, -3005, -1678, -6194, -1725, 102, -4007, -1213, -7330, -2515, -1336, -4220, -2492, -4365, -4748, -3634, -3468, -6231, -2036, -8618, -7015, -2416, -10932, -1345, -8476, -5322, -2055, -7350, -2131, -10709, -3277, -3007, -7164, -4938, -10398, -2347, -5087, -6032, -11826, -6451, -1985, -5375, -5476, -6386, -5870, -1782, -5321, -6190, -5095, -7148, -1297, -6906, -7337, -4828, -9918, -793, -7903, -6343, -5432, -7696, -862, -6090, -4809, -7046, -5531, -1731, -4551, -4415, -5858, -5221, -3339, -4088, -5435, -4033, -6463, -4688, -4882, -8282, -4049, -8560, -3891, -6749, -9165, -6707, -8658, -2887, -8564, -7138, -10402, -6502, -2670, -9858, -6370, -4903, -4838, -3343, -10015, -6338, -3947, -4444, -5240, -7141, -7775, -4739, -5188, -6116, -4346, -12681, -6528, -6728, -3824, -2500, -6372, -8095, -9228, -2730, -1680, -4190, -7241, -11071, -2502, -1914, -3767, -4542, -8579, -2851, -3341, -4537, -3365, -7100, -4257, -5807, -6160, -3938, -6677, -8386, -5363, -6487, -5417, -4831, -5399, -3595, -6606, -5220, -4098, -3955, -2996, -6791, -5518, -4339, -2958, -3813, -5029, -4855, -6573, -2456, -5830, -3627, -3990, -10242, -2583, -6572, -3503, -3955, -5694, -3498, -5733, -4531, -4720, -4080, -4973, -6642, -6336, -5565, -3660, -5397, -11244, -7572, -5403, -3796, -4399, -9624, -6943, -4976, -4501, -3341, -7751, -6284, -4998, -6524, -2623, -7953, -6400, -5125, -13720, -2499, -7962, -6581, -4922, -9675, -3201, -6947, -6428, -4554, -8044, -5125, -5239, -7512, -4496, -6154, -8552, -3600, -12902, -5097, -3938, -6733, -2506, -12785, -7219, -2296, -6245, -2448, -8098, -6875, -793, -7453, -4342, -2270, -1398, 579, -2516, -2953, 237, 929, 1489, 27, 266, 986, 1584, 1656, 936, 1345, 322, 829, 893, 681, 786, -1675, -1400, -934, -484, -1650, -4605, -5233, -3661, -2148, -8273, -7098, -7983, -5542, -3463, -6495, -9317, -6325, -6176, -3798, -6445, -10349, -4891, -7107, -3570, -7094, -11108, -4375, -7870, -3322, -4857, -10823, -4363, -8390, -3422, -3691, -7608, -4723, -10417, -4252, -3535, -5257, -5565, -11499, -5773, -3891, -4566, -6740, -9103, -6320, -4558, -5707, -7907, -7989, -6022, -5807, -10570, -8858, -6677, -6372, -7130, -8773, -8440, -6381, -6672, -7034, -6078, -8636, -9076, -6136, -7177, -5651, -8736, -9553, -5450, -7590, -6840, -7336, -5381, -5011, -6630, -14294, -7488, -4801, -4871, -5848, -6136, -10098, -6286, -5008, -6046, -3235, -11529, -8986, -5317, -6412, -2186, -7462, -8587, -5614, -5608, -2127, -5546, -5993, -5602, -4895, -2768, -4953, -3879, -5369, -5200, -4091, -5580, -3164, -5477, -6772, -6470, -7886, -3903, -6183, -9649, -11308, -9200, -6437, -7719, -8945, -10678, -6182, -9302, -11853, -7614, -9572, -5189, -7009, -10482, -7855, -10849, -5754, -6670, -7654, -7960, -10133, -8021, -8450, -7492, -6982, -9424, -10234, -15495, -8411, -6733, -10228, -7509, -11577, -8767, -7567, -9477, -6263, -9487, -9857, -8789, -7763, -6036, -8615, -16894, -9219, -6594, -6453, -7945, -10252, -9583, -5649, -7061, -7302, -7813, -10419, -4963, -7236, -6595, -7004, -10903, -4924, -7947, -6179, -6655, -10453, -5878, -10923, -6142, -6372, -9527, -7202, -14480, -6401, -6149, -9032, -6310, -9481, -6657, -5984, -9602, -5378, -7495, -6427, -5769, -9697, -5650, -6850, -6403, -5592, -7339, -7131, -7150, -7731, -5749, -5664, -8298, -6849, -11449, -6429, -4910, -7086, -6298, -10534, -7720, -4908, -6514, -6999, -10839, -9769, -5924, -6860, -9561, -13612, -11400, -9204, -6920, -14357, -8162, -11150, -11068, -6493, -12766, -6878, -13047, -6942, -6884, -9274, -7453, -15660, -5989, -8558, -7535, -9432, -9547, -6401, -9898, -7434, -14187, -7718, -7893, -9707, -8867, -13166, -7538, -10498, -11141, -10755, -9815, -8900, -12875, -16967, -9262, -9781, -12291, -11937, -15404, -8060, -13327, -13354, -9920, -12630, -7888, -12745, -11948, -8216, -10002, -7989, -8788, -11573, -7404, -9210, -6686, -15004, -3289, -6328, -7919, -10176, -10887, -3489, -4414, -6566, -8259, -9697, -4196, -4142, -5503, -5290, -11864, -5981, -5954, -4598, -5677, -11430, -11060, -14555, -3737, -8789, -6780, -7117, -8086, -3108, -8413, -5414, -4226, -8755, -3056, -6295, -5370, -2921, -10658, -3642, -5938, -5817, -2362, -5959, -4464, -6230, -6351, -2305, -4802, -5318, -5661, -7355, -2605, -4648, -6030, -4788, -8877, -3153, -4318, -5904, -4916, -9187, -3968, -3807, -6158, -6283, -7416, -4581, -3478, -7312, -8938, -5776, -4128, -3614, -8987, -8870, -4994, -3576, -4325, -11480, -8343, -4380, -3152, -4685, -5002, -9948, -2766, -2348, -3502, -1091, -2435, -586, -914, -1095, 924, 162, 874, 420, 766, 1496, 868, 1184, 908, 1411, 666, 95, 131, 390, 762, -1920, -2085, -2922, -845, -1280, -7756, -4454, -16110, -1966, -4698, -6715, -3873, -5983, -2930, -5724, -6404, -2975, -5321, -4831, -4148, -8149, -2771, -6242, -8405, -2985, -11642, -3082, -7557, -10505, -2280, -10096, -3383, -5472, -15643, -2315, -5910, -3512, -4542, -9302, -3544, -4161, -4119, -5871, -6931, -7014, -3807, -6345, -9365, -7016, -10307, -4311, -9961, -7929, -7821, -5691, -5163, -6055, -8191, -8082, -4467, -6171, -4793, -9507, -9009, -4679, -7184, -4796, -7642, -11541, -6390, -7723, -5518, -7267, -10546, -7902, -8212, -6977, -8316, -7941, -5667, -8984, -8527, -8988, -6911, -4411, -8643, -6370, -8980, -7105, -3989, -8007, -4233, -8228, -7891, -4022, -8794, -3315, -6300, -7934, -4546, -11341, -3481, -5193, -7635, -5755, -12427, -4738, -5205, -8025, -8019, -10792, -7259, -5891, -8796, -13258, -7564, -11530, -6159, -9580, -11920, -5757, -17389, -5882, -11718, -8114, -5523, -15594, -6008, -10143, -6180, -6780, -17090, -6855, -7510, -5038, -8817, -11814, -7704, -6483, -4638, -7888, -8637, -7401, -6001, -5064, -6890, -6993, -7147, -5609, -6385, -7082, -6207, -7481, -5691, -7961, -8353, -5988, -7837, -6738, -7876, -11189, -5943, -7604, -9331, -7787, -19199, -5825, -7175, -12307, -8505, -11676, -5962, -6404, -9173, -8273, -9909, -6757, -5111, -8220, -8439, -9529, -8310, -4397, -8781, -9601, -10027, -9518, -4853, -9488, -6396, -11585, -8235, -6822, -10060, -4537, -9577, -6889, -10416, -8115, -4244, -7183, -6916, -8712, -5559, -5065, -6404, -7819, -6786, -4732, -6745, -6723, -6229, -6014, -5754, -8068, -7727, -4706, -6080, -9574, -6889, -9382, -4416, -6628, -7227, -5957, -10909, -4928, -6618, -5124, -6000, -10310, -5733, -5841, -5155, -6098, -9824, -6774, -5344, -7076, -5466, -9382, -8830, -5583, -13008, -5116, -9364, -14598, -6627, -10457, -5703, -10925, -13134, -7897, -9338, -7078, -17766, -11047, -8228, -10926, -7312, -12329, -10043, -8854, -14096, -6377, -9246, -8903, -12360, -12308, -6179, -7824, -7904, -11876, -9138, -6918, -7406, -6685, -7622, -7962, -8100, -8250, -5658, -6581, -8677, -8669, -11653, -5213, -7600, -11726, -9502, -6275, -7459, -7000, -6470, -3903, -4611, -8854, -5266, -3553, -3567, -3870, -4951, -3609, -2416, -4242, -4366, -4804, -3320, -2270, -5967, -6275, -6972, -4166, -3256, -8507, -10171, -12115, -5676, -6261, -8439, -11299, -12043, -7006, -8492, -5927, -10517, -10697, -7794, -4872, -3723, -11855, -6608, -8993, -3744, -2358, -13710, -4703, -11678, -3516, -1921, -10297, -4260, -14057, -3549, -2336, -7447, -5051, -12593, -3527, -3366, -6283, -7371, -9834, -3390, -4634, -6581, -9859, -7409, -3297, -5936, -8880, -6768, -5974, -3285, -6690, -13443, -5505, -5455, -2978, -6634, -11797, -7806, -6402, -2254, -6693, -7806, -5050, -6959, -1229, -6141, -2174, -264, -2380, 89, -2592, 260, 1781, 74, 1016, -20, 921, 2414, 1007, 941, 1072, 9, 1957, 705, -553, 924, -2636, 564, -799, -4597, -202, -5387, -1546, -3587, -7025, -1771, -6066, -3644, -7205, -3911, -3331, -9450, -4568, -8048, -3349, -4854, -7175, -5245, -7936, -3646, -6327, -6008, -6570, -8861, -4621, -11767, -7183, -7459, -9946, -5893, -6739, -11369, -7622, -9559, -5931, -3608, -13936, -8468, -8911, -4742, -2750, -10183, -10097, -8682, -4374, -2987, -9181, -8548, -8794, -5678, -3069, -8990, -5410, -10167, -9059, -2481, -10011, -3681, -11519, -7713, -2240, -12961, -3158, -7402, -7225, -2629, -14315, -3664, -4975, -8061, -3591, -8715, -5158, -3513, -6182, -5211, -6693, -7881, -2674, -4835, -7763, -6634, -13779, -2476, -4538, -10107, -9065, -12637, -3083, -4685, -6531, -13953, -9700, -4730, -4943, -4833, -7463, -8389, -7154, -5426, -5212, -5979, -7985, -7362, -6888, -8907, -5809, -8836, -7039, -10232, -9569, -6110, -10164, -7723, -6606, -5848, -6181, -8551, -9132, -4796, -5085, -5711, -7127, -12411, -5076, -5321, -5106, -7060, -8607, -7079, -7071, -4767, -8634, -5752, -7579, -8468, -4796, -9544, -5016, -6526, -4435, -5263, -7770, -5677, -6851, -2722, -6394, -7830, -5973, -6828, -2351, -7826, -8200, -4993, -5965, -2867, -7129, -6373, -4708, -5973, -3666, -6375, -5292, -5314, -6838, -3734, -7316, -5384, -6269, -7531, -3386, -10330, -6284, -7143, -7886, -3446, -9316, -7264, -8282, -7969, -3961, -8354, -7454, -9326, -7048, -4575, -9967, -6846, -9308, -6015, -5682, -12094, -6182, -9574, -5562, -8455, -10098, -6251, -8823, -5788, -7933, -10115, -7438, -7179, -5798, -6256, -12729, -9670, -6641, -4424, -6670, -16869, -11702, -7349, -3136, -8626, -11379, -12571, -8894, -2706, -10776, -9858, -12632, -10360, -3202, -9852, -9656, -14351, -11892, -4516, -8120, -10112, -9196, -14718, -6029, -7326, -11073, -6167, -20010, -7015, -7571, -13288, -4933, -16628, -8164, -8158, -15866, -4808, -13887, -8859, -8671, -13006, -5320, -12181, -7866, -10275, -11071, -5975, -11702, -6915, -13457, -9700, -6806, -12271, -6528, -11149, -8831, -8396, -13721, -6934, -8250, -8454, -9442, -13972, -9042, -6740, -8719, -7705, -11615, -17335, -6696, -9993, -6648, -9134, -8087, -7929, 11499, 9653, 11787, 11865, 10918, 10750, 9748, 11068, 11240, 10364, 8109, 9531, 8698, 9336, 8658, -392, 8420, 3495, 6224, 6048, 4468, 6188, -2829, 2992, 4944, 4836, 2886, -1034, 852, 4834, 3423, -314, 929, -354, 3400, 2873, -1496, 1653, 65, -323, 689, -2183, 2935, 767, -6658, -226, -1673, 3889, 816, -6654, 5189, 544, 3523, 1694, 727, 7001, 1280, 3374, 3183, 4394, 7543, 2819, 4609, 4414, 6201, 7338, 5335, 5343, 5008, 6784, 6524, 6594, 5248, 4727, 6186, 4964, 6532, 4685, 3373, 4034, 2635, 5338, 4042, 439, -1698, 1519, 3675, 3143, -3463, -868, 1737, 2813, 1237, 612, 987, 1363, 2305, -3363, 2166, 1556, 1643, 2080, -5536, 2433, 1979, 2425, 2309, -3356, 2424, 956, 2375, 2323, -5877, 2676, -9137, 1643, 1847, -2948, 2781, 1636, 1445, 565, -278, 2290, 4161, 1827, -51, 118, 1184, 4603, 2057, 2119, -766, 999, 3517, 1918, 3192, -1961, 1741, 351, 1084, 2772, -5075, 1823, -9009, -3, 1315, -3513, 1715, -3156, 754, 666, -1, 2060, -6758, 1223, 3, 894, 2448, -4417, -629, -2904, 789, 2644, -1501, -4193, -1362, 779, 2463, -342, 741, -280, 657, 1614, 444, 1940, -2432, -386, 302, 300, 1661, -5600, -2648, -116, -1426, 728, -517, -5816, 42, -8691, -478, 1020, -5590, -492, -2680, -2624, 1193, -3778, -1788, 222, -9612, 248, -3523, -2310, 1328, -4828, -1791, -4731, -1546, 1500, -3774, -4803, -6916, -1462, 950, -6641, -4848, -8218, -1770, 222, -7771, -1963, -6686, -921, 557, -3923, -756, -4622, 123, 1229, -2846, -872, -3909, 554, 1169, -2433, -1846, -5745, 413, 243, -2080, -2755, -6614, -278, -1394, -1921, -2331, -1802, -1389, -2957, -2013, -1209, -272, -2419, -2893, -1213, -627, -236, -2201, -2356, -14, -707, -987, -752, -2093, 439, -940, -1989, 234, -1770, 82, -885, -3121, 317, -1690, -747, -680, -4513, -297, -2330, -1287, -546, -7327, -631, -3621, -1505, -658, -4254, -147, -4817, -2767, -1298, -1704, 213, -5047, -6312, -2616, -1171, 99, -4591, -4520, -3856, -2233, -602, -4570, -3047, -4603, -5501, -2062, -4365, -3248, -5468, -13943, -3893, -2743, -3891, -4549, -8014, -5236, -1218, -3439, -4507, -10182, -5271, -339, -2017, -6499, -6396, -3095, 51, -1278, -5234, -4433, -1926, 180, -1582, -4112, -5251, -1997, 117, -3012, -4723, -5486, -2358, -140, -6067, -5077, -2875, -2262, -540, -4332, -4377, -2761, -2777, -1175, -1347, -4245, -6137, -3431, -2252, 198, -5646, -2423, -1844, -3110, 896, -10059, 0, -490, -2063, 662, -7959, 293, -39, -1037, -1028, -5465, -943, -84, -1061, -5569, -3676, -3524, -278, -2353, -4143, -3071, -6214, -1188, -5856, -2726, -4220, -11237, -4123, -9832, -3171, -6078, -4947, -2949, -10897, 1986, 7534, 7994, 8395, 5655, 1586, 6803, 7469, 7696, 4993, 986, 4683, 6042, 5302, 3663, 1176, 4020, 4165, -290, 3540, 1354, 5071, 1972, 1624, 3711, 1165, 4944, -498, 2650, 3436, 1305, 3929, -780, 2245, 3125, 2022, 2784, 1021, 1914, 2896, 2842, 2606, 2544, 1909, 2503, 3458, 2577, 3509, 1162, 2278, 4319, 2777, 4320, -1679, 3341, 5631, 4337, 5485, 591, 4894, 6571, 5188, 6487, 2665, 5846, 6695, 4848, 6546, 2448, 6016, 6031, 3962, 5257, 374, 5518, 4941, 3891, 1946, -1263, 4519, 4092, 3892, -9767, -732, 3047, 3742, 2274, -3403, 28, 1256, 3246, -4496, -6805, 1456, 9, 2179, -172, -5004, 2240, -1027, 1634, -109, -3777, 2227, -2661, 1529, -2955, -4061, 1781, -4333, -54, 227, -4123, 1286, -2738, -3606, 548, -7285, 702, 202, -2746, -36, -1668, -116, 2048, -502, 1178, -760, 320, 3206, 1792, 1855, -4693, 1439, 3944, 3000, 1660, -2152, 1418, 4259, 3060, 927, -29, -23, 4053, 2125, -517, -1139, -1610, 3269, 301, -1313, -3676, -661, 1878, -2420, 858, -3865, 454, -397, -6488, 1913, -3258, 1317, -4907, -6205, 1205, -992, 1933, -2414, -2780, -2487, 70, 2028, 163, -680, -3970, 142, 1003, 843, 334, -195, -40, -3085, 301, 112, -43, -188, -1548, -1011, -1459, -1898, -666, 1611, -2204, -1343, -6526, -1699, 2298, -2599, 591, -7144, -2901, 1715, -1844, 1237, -4046, -3598, 179, -140, 759, -2406, -3075, -2445, 1180, -335, -1952, -1899, -5612, 1415, -1094, -2214, -1360, -1893, 203, -1459, -1069, -1757, 481, -3330, -2097, 752, -2767, 1624, -7473, -1792, 1782, -2900, 1889, -7712, -101, 1912, -2068, 1430, -5585, 1149, 1283, -1498, 397, -866, 1524, 568, -963, -1106, 495, 954, 497, -188, -3461, -19, -412, 139, 324, -10632, -2949, -900, -1303, -35, -4678, -7384, -163, -3549, -1866, -2417, -2039, -90, -4801, -7138, -2238, -767, -899, -3789, -5957, -2726, -570, -2445, -1632, -2991, -2995, -898, -4903, -717, -1806, -1742, -1512, -8493, -1379, -1798, 585, -1549, -5539, -3625, -3504, 1770, -763, -3517, -3105, -8456, 1591, -119, -3114, -1345, -7055, 92, -21, -4398, -782, -9520, -2433, -808, -6538, -902, -6864, -4298, -3229, -2854, -1191, -3592, -3995, -7376, -1294, -667, -3069, -3510, -3439, -1592, -26, -2002, -4369, -1857, -2227, -397, -443, -3309, -1476, -1091, -2056, 221, -1094, -2369, -668, -4218, -5, -716, -6260, -1626, -3114, -970, -2628, -5218, -2561, -1129, -2134, -2523, -2555, -2529, 148, -2205, 324, -2183, -3484, 433, -2391, 994, -2104, -4388, -687, -4433, -147, -1845, -2974, -4487, -13025, -4452, -1215, -1607, -5702, -5079, -4621, -8, -769, -2473, -2682, -1284, 552, -657, -1852, -1952, -775, -338, 3403, 4132, 7641, 778, 5289, 2552, 4145, 7421, 2383, 6068, 4670, 4212, 7130, 4931, 6997, 6328, 4373, 6985, 5898, 7176, 6003, 4155, 6359, 5214, 6490, 3584, 2785, 4682, 2921, 4968, -3986, -778, 1301, -742, 3260, -539, -3989, -6344, -2274, 2502, -875, -1955, -2882, -434, 1798, -3591, -1851, -1994, 1043, 958, 3027, -70, 38, 2360, 1125, 5424, 2700, 1757, 2968, 1329, 6100, 4469, 1807, 2654, 1037, 5305, 4858, -175, 2820, 2749, 2728, 3599, 755, 3658, 4815, -3318, 76, 2620, 3579, 5670, -6116, 599, 2350, 2258, 5308, -2952, 1593, -76, 344, 3740, -1295, 197, -7631, -293, 1431, -414, -2083, -4705, -32, 454, 1193, -1037, -2916, 140, -87, 2307, -23, -1998, -320, -18, 2491, 240, -1222, -2065, 924, 1975, -38, -567, -6414, 1177, 977, -812, -86, -2158, 1569, -272, -2074, 62, 217, 2576, -712, -3867, -198, 1022, 2926, -117, -3578, -924, 905, 2160, -125, -1289, -2054, 12, 982, -1563, -215, -2503, -1765, 993, -6099, -47, -1659, -4728, 1308, -6373, -203, -670, -5335, 1637, -2661, -739, 229, -3261, 1850, -1322, -2303, 947, -1527, 1748, -928, -5554, 1239, 616, 2135, -1827, -11079, 834, 2152, 2999, -5832, -6189, -473, 2630, 3320, -3403, -2728, -1400, 2094, 2477, -572, -1483, -13, 1139, -474, 25, -1786, 1043, 931, -2991, -845, -3318, 1407, 776, 1042, -2630, -4489, 1405, -256, 2424, -987, -2810, 1333, -2287, 2747, 512, -1553, 1549, -5824, 2282, 279, -2049, 1871, -3869, 900, -1724, -5113, 1702, -1201, -1600, -2784, -3388, 568, -172, -2220, -895, -1663, -2290, 292, -362, -418, -2568, -9930, 580, 503, -1227, -7070, -2603, 429, 437, -2729, -5947, -436, -295, -560, -2611, -3597, 571, -1311, -2955, -1634, -2500, 779, -2367, -6798, -1580, -1228, 83, -3626, -2730, -1961, -159, -1607, -4533, -689, -1789, 222, -2814, -4019, 358, -1588, -452, -1013, -4088, 995, -2319, -2726, 767, -6820, 974, -4507, -8398, 1631, -11130, -303, -2578, -6953, 1518, -6724, -3262, -327, -6716, 421, -8780, -1524, 193, -8230, -1594, -5833, 225, -690, -4076, -3241, -2524, 550, -3379, -1911, -2869, -975, 320, -6486, -1262, -3444, -392, -71, -2338, -1737, -7273, -902, -761, -805, -3112, -5322, -3132, -1739, -753, -4756, -3052, -3407, -2524, -1795, -7989, -2173, -957, -2388, -3114, -6050, -1001, -97, -1763, -3563, -1277, -227, -19, -1780, -4053, 280, -333, -629, -3246, -5652, -96, -1690, -2562, -4260, -11515, -3068, -6057, -6844, -1570, -6403, -7864, -5955, -5304, -902, -3614, -3309, -3410, -4326, -2882, -2501, -2023, -1490, -3336, -7164, -1740, -36, 312, -1321, -2026, -1151, 996, 668, -883, -890, -1372, 643, -586, -3064, -910, -3402, -4482, -2190, -1270, -4262, -3070, -4590, -2040, -2520, -946, -3274, -9669, -4249, -9697, -56, -3661, -5978, -4859, -3848, -493, -3439, -3542, -2771, -1509, -504, -3120, -3970, -2516, -560, 163, -2938, -6862, -2398, -958, 411, -2723, -11590, -1025, -3975, 1108, -3014, -6531, 310, -5335, 1975, -3553, -4511, 957, -1340, 1873, -3638, -4597, 887, -704, 258, -5787, -7724, 248, -1979, -4020, -5723, -4889, -576, -6030, -5557, -1752, -1896, -1048, -5583, -3021, -961, -879, -994, -2977, -1828, -2324, -1161, -756, -2567, -894, -8329, -3006, -890, -3048, -336, -2419, -12398, -1434, -2230, 342, 771, -2734, -174, 527, 1344, 2390, -223, 1634, 2317, 2073, 3055, 210, 2246, 2721, 1891, 2870, -912, 1627, 1673, 245, 1928, -3573, -115, -1050, -3564, 507, -6432, -3262, -4038, -2351, -1054, -6372, -8754, -4753, -938, -2769, -7193, -2761, -4473, -1032, -3845, -10328, -1095, -2632, -1692, -3653, -2631, -1126, -2259, -2446, -3893, -256, -2771, -3310, -2791, -4961, 361, -8126, -5707, -2611, -5749, -245, -7360, -6102, -2940, -5490, -1830, -6736, -4501, -4546, -5568, -4055, -6866, -4259, -6523, -5735, -6537, -2456, -3944, -4694, -5152, -6281, -791, -2729, -3326, -5147, -4384, -636, -1952, -3614, -6397, -3150, -1511, -1616, -7073, -4951, -2081, -2980, -1332, -7338, -2755, -1670, -4406, -1259, -3640, -1452, -2662, -5710, -1451, -3615, -261, -5548, -7769, -1585, -5654, 706, -3476, -12844, -1737, -4974, 1109, -1569, -10018, -2414, -4155, 931, -1372, -8834, -4007, -7511, 348, -2417, -19835, -6770, -5193, -391, -4759, -5253, -7132, -1173, -1144, -7689, -1769, -4823, 228, -1928, -6624, -170, -3580, 522, -2723, -5276, 133, -3197, 312, -3832, -5133, -786, -3275, 86, -6741, -5275, -2979, -3246, -15, -9085, -3240, -6076, -2781, -346, -4076, -2116, -6898, -1822, -1476, -2444, -2481, -5099, -863, -3556, -1673, -3676, -3843, -402, -3266, -1569, -4468, -2131, -551, -2215, -3039, -4968, -340, -1284, -2389, -8551, -5841, 652, -2084, -3633, -3304, -6153, 803, -1768, -9006, -1361, -4735, 202, -833, -4478, -1044, -3627, -1151, -16, -1493, -1415, -3147, -3442, 294, -1194, -2076, -3305, -6063, -281, -2926, -2664, -4702, -3915, -1898, -6565, -2405, -6927, -2282, -3991, -4178, -1692, -5166, -2072, -5567, -3102, -1571, -4346, -2848, -8095, -4080, -2244, -5297, -3728, -11771, -6981, -3029, -8705, -3791, -10247, -6713, -3057, -9979, -3672, -6229, -4608, -3131, -5419, -4169, -4738, -3996, -4066, -3853, -5631, -5869, -5689, -6247, -3266, -7684, -20323, -11907, -7206, -2894, -8001, -5255, -3943, -5052, -2472, -5833, -3593, -2379, -3961, -2063, -4117, -4113, -2539, -3763, -1759, -4145, -4780, -3799, -3579, -1678, -7482, -3796, -5995, -3003, -2008, -6027, -3836, -9554, -3075, -3017, -2896, -5702, -14625, -1504, -2360, -3044, -1487, -4265, -3225, -3986, -9075, -3210, -4127, -2464, -6521, -5388, -6423, -916, -408, -6156, -3486, -9355, -571, 552, -4207, -4319, -8203, -1147, 569, -2249, -4905, -6750, -937, -72, -543, -2242, -4041, -863, -1216, 432, 114, -2699, -2014, -3629, 418, 1352, -3433, -2727, -10814, -681, 1366, -6282, -1958, -2590, -2952, -6, -3716, -2224, -513, -6937, -3433, -2625, -4043, -163, -7808, -13572, -3488, -9508, -1117, -3808, -5312, -4816, -6499, -2760, -1250, -3357, -2952, -2767, -2385, 163, -1731, -865, -1248, -1202, 216, -691, -552, -359, -1048, -1285, -1002, -3070, 1192, -999, -682, -3304, -1531, 2877, 478, 1448, -1240, 1840, 3908, 1324, 1752, 1094, 2880, 4142, 771, 68, 1497, 2483, 3577, -1142, -4927, 401, 872, 2279, -3574, -4789, -1818, -1422, 578, -4474, -4161, -2381, -2721, -792, -3274, -4035, -1915, -2841, -1498, -1655, -3202, -2845, -1530, -2122, -731, -4220, -4852, -346, -3911, -488, -8410, -3948, 17, -11601, -1054, -6930, -2428, -223, -4265, -3181, -5540, -1608, -827, -2590, -7168, -6787, -955, -1883, -2828, -1763, -8574, -293, -4050, -3295, 197, -4504, 297, -6437, -3468, 640, -2015, 398, -3753, -4356, 188, -1034, -732, -2281, -6113, -672, -1381, -4975, -1556, -7557, -1508, -2985, -3857, -829, -5404, -2414, -5159, -1358, 231, -3005, -3667, -5494, -1721, 1210, -1657, -2840, -4258, -4395, 1572, -946, -1003, -4242, -6830, 1068, -494, -228, -7851, -4250, -530, -338, -381, -6428, -3621, -3439, -768, -1361, -3066, -4154, -4575, -2020, -3706, -2565, -5873, -4091, -3450, -8764, -3454, -11360, -3994, -2473, -2757, -5121, -9430, -2536, -1171, -226, -6409, -6764, -1856, -666, 1078, -4370, -4805, -2973, -793, 1676, -2813, -3727, -5223, -1648, 1649, -2899, -4746, -2938, -3744, 960, -4358, -6558, -1958, -7719, -587, -4615, -3112, -2844, -8827, -3886, -3787, -1491, -5185, -4575, -6683, -4287, -1159, -6972, -1822, -2712, -6079, -1790, -7969, -556, -1786, -7156, -3885, -6150, -504, -1647, -6708, -10546, -3778, -1648, -662, -6693, -4053, -3151, -2948, 216, -6619, -2100, -4161, -2211, 7, -6241, -2150, -7819, -1901, -1619, -5625, -4201, -9236, -2125, -5359, -4772, -20035, -6203, -1695, -8961, -3936, -4620, -8137, -1423, -7771, -3168, -2625, -7866, -1884, -10407, -2637, -2134, -3678, -2511, -4562, -2875, -2186, -2574, -2759, -1385, -4470, -2603, -2829, -2964, -151, -5713, -3902, -4024, -2960, -285, -4488, -7391, -6273, -2378, -1600, -5924, -6123, -8840, -1575, -4013, -10024, -3258, -8351, -1241, -8567, -3585, -2348, -6904, -2097, -7621, -2694, -2456, -5419, -5432, -2881, -4705, -3130, -4781, -9225, -949, -11217, -3993, -5228, -5395, -421, -3792, -4698, -6520, -6366, -1110, -2417, -5091, -7604, -8282, -3182, -2698, -5569, -7999, -6149, -3058, -1149, -2782, -5494, -1655, -5423, -4878, -2823, -425, -4758, -4616, -5470, -3528, 1229, -4878, -3694, -2318, -7757, 1559, -807, -1796, -428, -3529, 926, 319, -670, 610, -1132, -507, -59, -806, 775, -582, -1285, -1894, -1604, -11, -1141, -280, -4756, -2209, -1942, -1683, 395, -4392, -3263, -5611, -859, 232, -5596, -6205, -10941, 8, -890, -9871, -9277, -6377, 262, -3581, -4485, -3242, -3582, -180, -7947, -3244, -492, -2391, -1929, -2648, -2125, 1089, -2467, -7535, -184, -1467, 1949, -3488, -1853, 927, -1118, 2048, -5434, -232, 1105, 12, 1109, -8568, -1789, 588, 134, -54, -1893, -2458, 90, -2350, 1154, 1134, 1625, 861, -2206, 1874, 2340, 2891, 1827, 813, 1064, 2174, 2645, 2115, 1368, -1399, 752, 1734, 1801, 465, -4924, -1875, 1555, 987, -998, -3232, -5678, 1800, -332, -737, -1065, -4665, 1480, -1490, 7, -36, -2542, 608, -1714, -508, 265, -2403, -86, -2104, -2181, 70, -4109, 53, -2358, -179, -995, -5926, 423, -1358, 1566, -3229, -3574, 424, -385, 1563, -2794, -2277, -289, 57, 211, -1662, -1919, -2226, 214, -608, -2548, -1864, -5770, 128, -489, -5510, -1845, -4538, -522, -1573, -2361, -2327, -3159, -2097, -2126, -19, -3712, -2801, -5200, -529, 895, -4192, -3067, -14878, 331, 844, -2237, -4676, -5338, 164, -106, -889, -10372, -2762, -871, -1700, -574, -4661, -1659, -1252, -2037, -1288, -1745, -1741, -415, -1122, -1881, -221, -2879, -431, -795, -27, 586, -2664, -1936, -1383, 1453, 760, -877, -5747, -3279, 1713, 230, 48, -9848, -6121, 743, -1223, 33, -6267, -4083, -1491, -4338, -683, -3873, -3319, -3890, -10951, -1470, -2171, -4353, -4587, -6234, -1877, -1456, -6665, -4400, -6122, -2562, -1490, -9262, -2215, -8824, -2936, -2028, -5486, -970, -12518, -1587, -2449, -3870, -1006, -5513, -81, -1884, -5070, -1852, -2270, 846, -1583, -9725, -2673, -446, 1035, -2785, -3642, -3626, 299, 384, -4071, -1697, -5615, 0, -845, -1718, -1073, -7410, -1367, -1028, -814, -935, -6894, -3471, -398, -1648, -916, -3548, -6133, -728, -4499, -965, -830, -6958, -2693, -7097, -1111, 409, -3086, -6713, -4160, -1165, 298, -1895, -3881, -2976, -907, -1067, -2241, -1851, -2797, -502, -2215, -3381, -910, -3517, -345, -1448, -4587, -507, -4985, -745, -742, -5417, -460, -4953, -1722, -290, -5442, -719, -2865, -2546, -433, -6672, -1408, -930, -2768, -1687, -15512, -2698, 113, -3871, -4079, -5756, -4240, 71, -8233, -6080, -4337, -4508, -951, -6482, -6111, -5045, -3690, -1837, -3879, -3679, -6100, -3119, -1430, -3633, -2205, -5399, -3187, -1123, -4720, -2134, -4594, -3773, -1525, -7034, -3457, -4808, -4327, -2954, -13724, -6477, -6667, -4058, -6774, -6851, -6498, -11831, -3388, -5873, 4533, 15493, 7130, 11099, 10872, 8971, 15079, 7409, 10372, 10215, 10477, 13792, 7275, 7939, 8110, 10115, 11471, 5974, 2071, 4093, 8807, 7904, 3893, -401, 596, 7640, 6406, 2632, 291, 246, 6353, 7830, 1705, 498, -2133, 5933, 8178, -99, 1669, -1466, 7015, 7495, -3209, 1380, 906, 6642, 5809, -2085, 420, 2649, 3011, 3101, 467, 890, 4060, 2610, 1239, 3134, 2438, 5095, 6134, 4168, 4923, 3666, 5672, 6390, 6574, 5504, 4339, 5666, 5175, 7432, 4771, 4364, 4716, 3611, 6811, 2487, 3671, 2068, 2734, 4441, 897, 2214, -1551, 1422, -1480, 1980, 145, 404, -1713, -829, 1479, -1429, -400, -2830, -620, -980, -1508, -4595, -937, -4509, -5950, -843, -3942, -436, -956, -3109, -86, -2002, -692, 253, -1534, 309, -1370, -1942, -1167, -2427, 197, -874, -4390, -7899, -2739, -461, -450, -4445, -2005, 564, -1706, -673, -4643, 937, 1953, -3334, -2247, -9197, 2447, 1896, -3203, -7384, -2865, 3140, 702, -1405, -4796, -1206, 3044, -1300, -192, -2152, -1597, 2136, -2908, 125, -1193, -3364, 442, -2540, -592, -655, -6300, -1686, -1452, -2733, -319, -2385, -3504, -1146, -6747, -114, 418, -6151, -1916, -7425, -50, 1525, -8056, -3061, -8010, -273, 1413, -4908, -3606, -8036, -740, 45, -4499, -3707, -9333, -1100, -3493, -4605, -2349, -7706, -1075, -5940, -4116, -1488, -4490, -1074, -2420, -4716, -2222, -4322, -1688, -1937, -7574, -5472, -7708, -3210, -2954, -9068, -8547, -8071, -5093, -4749, -6216, -4839, -4324, -4994, -4740, -5370, -4755, -3714, -4619, -3586, -5709, -6445, -4542, -5527, -3203, -6705, -7296, -6022, -7614, -3491, -7190, -5463, -5318, -7737, -3294, -6641, -3769, -3574, -6598, -2733, -6292, -2699, -2511, -6223, -3322, -7125, -2528, -1985, -6367, -6489, -9032, -3192, -1758, -6932, -10492, -10363, -3831, -1862, -7547, -5582, -7436, -3718, -2684, -7591, -4955, -4703, -3850, -5169, -7156, -5282, -3324, -4932, -15759, -6365, -5603, -2636, -7772, -5235, -5242, -5591, -2536, -7604, -3910, -4440, -5019, -3328, -4982, -4552, -4531, -4227, -5154, -4938, -6666, -5498, -4315, -7384, -6805, -10403, -6424, -6270, -8430, -6066, -14886, -5957, -8237, -9381, -4709, -7991, -4773, -6516, -15946, -5086, -4770, -4046, -7510, -8213, -7473, -3115, -3811, -5936, -6036, -13292, -2612, -3598, -3212, -6093, -7140, -2970, -3330, -2197, -7069, -5339, -3798, -3249, -2596, -7484, -4894, -4503, -3658, -4898, -7717, -5436, -4681, -5182, -7703, -9217, -6569, -4421, -10267, -4587, -15266, -5999, -3847, -8154, -4051, -14168, -5103, -3525, -4809, -5255, -9670, -5175, -3853, -3862, -7668, -5919, -5897, -4642, -4121, -8586, -4629, -7287, -5715, -5258, -7177, -5460, -9161, -7852, -7043, -6614, -7702, -10597, -16619, -8897, -6982, -6417, -13152, -8491, -8037, -7590, -5676, -7926, -5771, -7079, 8378, 264, 6883, 11011, 8143, 7556, 1695, 6137, 10467, 7604, 4780, 3511, 3566, 8760, 5905, -1905, 4481, 1645, 5576, 3317, -5876, 4662, 3831, 483, 3090, -657, 4234, 4030, 917, 3836, 2385, 3349, 2513, 2198, 3803, 3375, 2196, -346, 2695, 3488, 3584, 819, -176, 2702, 3452, 2746, 335, -412, 2651, 3857, 1787, 2832, 1422, 3444, 4373, 5252, 4678, 5194, 4458, 4573, 7185, 5288, 6970, 4627, 4164, 7558, 4889, 7263, 3451, 2960, 6666, 3846, 6129, 1351, 758, 4646, 2817, 2960, 2364, -3368, 1865, 2292, -15868, 3155, -5752, -564, 1822, -116, 2577, -2844, -2178, 610, -161, 1399, -2842, -3605, -1454, -690, 520, -2531, -955, -1400, -539, -353, -1441, 1152, -124, -2240, -2051, -868, 1843, 464, -11447, -4585, -824, 1495, 678, -1738, -5301, -1185, 281, 745, -280, -5586, -1797, -1825, 459, -992, -6544, -2607, -5670, -649, -4226, -6437, -4093, -9434, -2416, -5874, -4257, -7643, -4370, -1347, -2625, -2606, -5330, -3094, 283, -2130, -1978, -2963, -3396, 824, -3189, -1573, -2398, -5621, 448, -5830, -798, -2397, -12478, -642, -10395, -161, -1970, -5002, -2176, -11549, -242, -785, -3316, -4916, -7381, -1520, 502, -2597, -9442, -4302, -5125, 1082, -1579, -3107, -2656, -2112, 665, -1043, -2269, -1962, 1021, -494, -1698, -4389, -2045, 2453, -1441, -4094, -4653, -3063, 2833, -2423, -13200, -2195, -5171, 2263, -4770, -6279, -2685, -4206, 699, -11234, -4126, -5226, -2200, -889, -6141, -3336, -2471, -1746, -560, -3305, -3339, -1170, -2899, -506, -3067, -4504, -2083, -7249, -1161, -4422, -7364, -6452, -7606, -1149, -5031, -7721, -5413, -4786, -466, -5029, -5662, -2999, -6071, -230, -5115, -4645, -3330, -11883, -811, -4326, -4105, -5245, -6769, -2428, -3992, -4199, -6936, -6518, -5211, -4770, -5177, -5351, -9277, -5506, -7365, -5638, -2906, -9850, -3555, -18071, -4137, -2140, -6688, -2506, -11084, -3154, -3833, -4152, -2146, -9314, -3232, -7623, -2662, -2270, -6701, -4756, -2688, -2446, -2726, -5357, -10055, -1806, -3670, -3392, -5184, -7186, -3235, -6329, -4180, -5034, -5349, -8245, -7533, -4973, -4501, -5329, -6564, -8702, -5175, -4938, -4572, -3817, -13587, -3909, -6498, -3654, -2700, -8833, -2464, -4797, -3378, -2376, -7217, -1812, -3428, -3628, -2944, -6491, -2063, -3960, -3761, -4608, -6658, -3034, -6518, -2849, -6431, -8580, -3801, -7431, -2009, -6121, -16045, -3344, -5560, -2096, -5897, -10675, -2850, -5160, -3323, -6165, -8817, -3093, -5969, -6089, -6663, -8860, -4081, -8848, -13227, -7866, -10554, -5060, -9306, -10594, -9882, -12794, -4854, -5107, -7765, -7546, -9109, -4704, -3508, -6253, -4799, -6608, -5836, -3334, -5350, -3322, -5327, -9282, -4326, -4660, -2846, -5363, -7109, -5836, -3927, -3251, -7120, -4339, -5865, -3254, -4504, -9555, -3564, -5144, 1256, 8194, 9051, 8438, 6129, 650, 7937, 8480, 7806, 6110, 593, 6913, 6782, 5746, 5680, 1396, 4326, 4193, 1459, 4087, 699, -3885, 2269, -3077, 178, -1300, 2669, 2316, -3257, 1229, -395, 4207, 1878, -348, 2806, -745, 3878, -490, 2326, 2043, -6821, 2190, -9079, 2726, -404, 2215, 355, -1577, 2680, 1752, 5378, 1813, 1864, 4276, 4284, 6994, 4431, 3807, 5208, 5306, 7530, 5770, 4359, 4429, 4896, 6988, 5456, 3166, 388, 2751, 5161, 2708, -623, -360, 3728, 1734, -3842, 1396, 2724, 6103, -350, 2628, 2636, 1996, 6816, -647, 3185, 1600, -2459, 6482, -3023, 2185, -1368, -3164, 5709, -7149, 372, -6559, -756, 4888, -5411, -2287, -12196, -1359, 3713, -2871, -4511, -9419, -3677, 1748, -2653, -5209, -5848, -5567, -924, -4604, -8946, -3825, -3525, -2421, -15332, -4285, -2637, -2461, -1599, -5356, -2543, -1760, -1539, -2080, -2989, -3332, -1242, -553, -7473, -2254, -4298, -1333, 51, -966, -2558, -1966, -1802, 158, 1360, -3677, -1343, -2179, -240, 1463, -4227, -2395, -2938, -1199, -487, -3520, -3483, -4805, -2796, -7193, -2827, -3956, -7252, -5226, -2860, -2057, -5333, -12403, -8461, -1370, -1333, -4898, -4867, -4416, -1209, -1339, -4761, -1651, -1420, -763, -2458, -3962, -610, 30, -99, -4593, -2531, -997, 341, -220, -6698, -3370, -2282, -267, -1783, -5861, -10912, -1765, -1616, -2858, -4350, -3667, -232, -3596, -457, -4035, -2491, -17, -4169, 839, -4041, -4380, -1642, -2772, 1037, -3197, -3931, -6408, -1924, 423, -1948, -1864, -4142, -621, -571, -1301, -2064, -2997, 731, -961, -1589, -4497, -4267, 1250, -926, -2992, -8958, -8864, 917, -1474, -7457, -6750, -7896, 44, -2788, -5957, -6933, -5080, -899, -4510, -2528, -7146, -4167, -1538, -5667, -2113, -6172, -3159, -2182, -5590, -3646, -5813, -2198, -3796, -5537, -7502, -5014, -1999, -8334, -5487, -8382, -4255, -2704, -10080, -4584, -7250, -4315, -4114, -7922, -3508, -7169, -4759, -5307, -12536, -2807, -5831, -4859, -4921, -8245, -2569, -4107, -4743, -4018, -5103, -3040, -3088, -5043, -3730, -3963, -4918, -2810, -6461, -4368, -3629, -10136, -2912, -10574, -6007, -3890, -5810, -3042, -11332, -8360, -4947, -3876, -3399, -7554, -10480, -6989, -3516, -4362, -5965, -12544, -6735, -3533, -5859, -5315, -14505, -4827, -3209, -7345, -5893, -14616, -4171, -3017, -9808, -8271, -13590, -4636, -3677, -14120, -9644, -9215, -6100, -5605, -12666, -8331, -6548, -8048, -7381, -10863, -10016, -5139, -7709, -5938, -6204, -15211, -4551, -6454, -4807, -4875, -8887, -4491, -6128, -3721, -5659, -7500, -4682, -6747, -2556, -7675, -6139, -4864, -7890, -1964, -6667, -4402, -5188, -8256, -2320, -4996, -3710, -6703, -7762, -3806, -4001, -4335, -11670, -7648, -6396, -3930, -6030, -5334, -8387, -8283, -5021, -7927, -3020, -9673, -7495, -8041, -6548, -6351, -4577, -6923, -7329, -8284, -6631, -4061, -7063, -5307, -8390, -6378, -4222, -7515, -4424, -7435, -5524, -5190, -6242, -5340, -6891, -6092, -6443, -4482, -9412, -6512, -8504, -7151, -3780, -6509, -6541, -7944, -7748, -4030, -3881, -7323, -6572, -8041, -5028, -3184, -8845, -7005, -7553, -6481, -3803, -8940, -8206, -6558, -7744, -6040, -6500, -8761, -6037, -7925, -10519, -5080, -9533, -6506, -7240, -9368, -4760, -9287, -8232, -7063, -10010, -4792, -7236, -12589, -7486, -9919, -5057, -5658, -8648, -7374, -7534, -6010, -4564, -5838, -5932, -5664, -6665, -3232, -6002, -4453, -3240, -4373, -1650, -13290, -3202, -865, -1386, -185, -2610, -1208, 688, 185, 948, 143, 530, 1179, 389, 1454, 963, 1243, 482, -607, 1088, 355, 836, -1785, -2522, -295, -1720, -758, -8318, -4503, -2747, -4915, -3800, -5798, -5229, -5997, -5149, -7227, -3822, -5190, -8891, -5027, -5935, -4036, -5501, -11012, -5751, -5296, -5407, -5933, -14699, -6245, -5838, -7147, -5933, -7333, -6323, -7869, -6831, -5364, -5247, -6471, -12393, -6155, -4895, -4878, -6556, -8509, -6499, -4992, -5571, -6484, -6755, -7576, -5429, -6747, -6782, -6913, -8912, -5640, -6000, -7704, -8167, -8864, -5128, -4469, -8921, -8017, -6624, -4493, -4273, -9640, -7406, -5049, -4473, -5991, -9343, -7561, -4418, -5066, -13268, -8643, -6815, -4450, -5720, -8838, -8074, -5190, -4799, -5812, -7425, -8578, -3930, -4919, -5457, -8368, -10504, -3413, -4635, -5151, -10434, -8473, -3847, -4677, -5001, -14928, -6745, -5601, -5846, -4794, -13557, -6224, -9763, -9292, -4507, -10355, -6021, -7168, -9656, -4467, -9557, -6503, -4641, -8241, -5059, -8694, -8687, -3764, -11422, -6437, -8146, -8778, -3950, -7103, -7453, -9133, -6146, -5314, -4463, -7307, -13477, -5448, -8279, -4093, -8118, -10718, -6447, -8181, -5475, -10931, -8180, -10001, -7192, -8322, -15204, -7878, -10771, -9099, -7508, -16281, -8573, -8246, -11432, -6265, -15411, -7892, -8576, -7119, -6237, -10841, -6883, -9984, -5696, -6866, -8892, -7123, -7987, -5549, -7763, -7957, -8032, -6305, -6345, -8954, -7489, -7324, -5799, -7600, -10486, -7290, -6169, -5854, -7392, -9232, -7372, -5691, -6019, -6508, -7284, -7752, -5822, -6340, -6327, -6590, -8314, -6392, -7067, -6831, -6989, -8911, -6713, -8579, -7890, -7869, -9445, -6372, -10999, -9800, -7776, -9341, -6414, -10052, -11851, -7401, -8415, -7597, -8164, -10261, -8170, -7870, -9737, -7401, -10459, -10877, -8278, -9718, -7889, -16067, -13568, -9071, -9638, -9811, -10978, -12213, -8858, -12121, -9877, -8305, -12370, -8594, -13135, -9242, -7339, -8537, -8928, -9409, -11784, -6960, -6211, -9573, -8126, -11065, -7114, -5472, -10652, -8225, -8324, -8287, -5949, -10635, -9908, -8492, -11586, -7270, -8860, -15514, -11024, -18718, -8410, -7806, -11134, -12072, -14639, -8466, -7747, -8489, -10385, -18810, -8197, -8742, -7493, -9563, -13499, -2908, -6699, -7247, -4378, -5073, -3327, -10845, -5664, -6704, -5999, -5316, -12007, -4681, -6668, -8456, -11358, -7040, -4423, -5286, -14984, -5540, -5199, -5265, -5211, -8728, -3696, -4677, -7107, -6611, -6682, -3638, -5055, -7761, -13025, -6529, -4707, -5934, -7805, -8128, -7618, -5980, -6600, -9058, -5764, -8213, -6226, -6227, -8087, -6096, -7454, -6407, -5201, -6920, -7532, -7107, -6511, -4581, -7163, -6288, -7064, -6532, -4870, -6736, -5605, -7004, -7435, -6602, -5552, -6552, -6745, -7886, -12200, -5388, -7769, -6227, -6979, -6980, -5654, -7796, -5688, -6463, -4928, -6064, -6473, -4840, -4803, -5437, -11898, -3453, -2951, -2292, -4249, -3831, -573, -738, -575, -1265, -669, 1261, 600, -18, -52, 336, 1930, 743, -753, -352, -12, 1425, -450, -3087, -2171, -1392, -310, -3143, -7103, -6068, -3344, -3185, -5780, -7571, -8065, -5057, -5027, -6312, -6455, -6798, -6420, -4856, -6105, -4670, -7252, -9081, -4674, -4671, -4106, -7864, -13386, -4465, -4086, -5220, -8621, -10281, -4309, -4242, -8559, -9005, -10797, -4498, -4461, -7752, -8497, -7325, -5414, -4277, -5370, -7797, -5059, -7937, -3897, -4982, -6640, -4296, -11752, -3836, -6238, -6072, -4338, -6354, -4438, -6660, -6407, -4700, -4666, -5675, -4453, -7390, -5256, -4511, -6533, -3547, -8897, -6522, -4832, -6306, -4020, -11184, -10382, -4960, -6389, -5959, -13516, -10335, -6209, -7820, -11066, -12590, -6437, -14322, -12986, -10320, -10129, -5207, -6874, -10885, -6944, -7587, -4943, -4813, -8883, -5362, -5973, -5279, -5283, -7056, -4170, -5508, -6155, -8576, -4767, -3337, -6284, -7542, -11029, -3905, -3103, -7915, -10062, -6884, -4627, -3659, -6884, -16473, -5993, -7170, -5101, -5139, -8567, -5852, -10715, -7398, -4371, -6536, -5670, -11270, -10348, -4382, -5992, -5626, -18778, -9143, -5134, -5752, -6121, -9399, -6596, -6755, -5309, -7402, -6917, -5445, -8929, -5428, -9935, -6312, -5132, -10054, -7106, -10118, -6658, -5255, -9667, -13075, -7099, -6394, -5653, -7872, -8792, -5678, -5288, -6438, -6763, -7146, -5493, -4663, -7384, -6729, -7684, -6347, -4530, -7160, -7379, -9507, -7291, -4559, -6680, -8148, -11206, -6599, -4802, -7142, -8712, -10361, -5839, -5422, -8417, -9661, -8222, -5888, -6181, -9920, -13604, -6597, -6609, -6751, -11337, -11829, -5824, -7493, -7258, -12042, -7840, -5990, -8131, -7717, -10880, -6602, -7278, -8949, -8032, -9651, -6747, -10059, -10509, -8548, -9624, -8103, -13261, -12531, -9616, -10733, -10395, -12730, -10939, -9319, -11676, -10460, -12527, -9983, -8093, -10785, -9309, -12955, -10411, -7973, -9245, -8938, -13295, -9574, -8281, -8789, -9000, -9805, -9090, -8248, -9757, -9125, -7776, -10044, -8898, -9633, -9117, -7390, -9505, -10617, -8342, -8800, -8461, -8786, -12609, -8822, -8115, -10808, -10312, -19216, -11882, -7526, -10971, -18444, -11727, -11604, -7828, -9439, -10460, -9691, -10746, -10399, -8907, -8269, -10319, -6878, -9851, -2641, -8407, -6705, -6866, -10729, -3982, -6529, -7147, -5880, -8550, -8117, -5432, -9053, -5592, -6433, -7111, -4552, -9303, -5849, -4964, -5221, -3781, -6290, -6387, -3769, -5732, -3360, -4621, -6109, -2878, -8342, -3383, -4350, -4191, -2694, -9240, -3989, -5223, -3001, -3438, -6009, -5375, -6996, -3143, -5046, -4195, -6291, -10745, -4699, -6768, -3080, -5204, -10279, -7260, -7703, -2416, -4464, -6950, -7035, -7753, -2151, -4372, -6527, -6596, -7208, -2333, -4532, -8309, -8248, -6634, -3117, -4632, -15361, -9623, -5373, -4999, -4484, -9217, -6905, -4820, -12682, -4436, -6508, -6933, -4762, -5006, -3898, -3783, -3713, -1910, -1481, -1738, -1064, -643, 227, 177, -122, 543, 585, 909, 595, 257, 852, 386, 309, -314, -640, -275, -1112, -1534, -3212, -2963, -3566, -3883, -4501, -7127, -6597, -9483, -7485, -7128, -4571, -7375, -4444, -11865, -7870, -5313, -7155, -3428, -11077, -7770, -9125, -8310, -3381, -7399, -6912, -8765, -11503, -3966, -6346, -6521, -7168, -11360, -5531, -7257, -7706, -7116, -7068, -7660, -12054, -10682, -8340, -5558, -7006, -8854, -9587, -9526, -6069, -6389, -7118, -9337, -5638, -9274, -6453, -8845, -12604, -3441, -10968, -6227, -14733, -10009, -2529, -10137, -5697, -8539, -7247, -2413, -12264, -5425, -8522, -6545, -2854, -6333, -5646, -12419, -7328, -3787, -4279, -6259, -8824, -9771, -4800, -3838, -6481, -7261, -8563, -4664, -4541, -6203, -7890, -6232, -4045, -6420, -6541, -6816, -5547, -3955, -9842, -7972, -5009, -5959, -4435, -10213, -10475, -4682, -6963, -5504, -7886, -11744, -5499, -7792, -7511, -7102, -11514, -5834, -7854, -9814, -7475, -13256, -4957, -7573, -8841, -7927, -13400, -4683, -7644, -7727, -7390, -9887, -5684, -8306, -7013, -6861, -7521, -8562, -10015, -6961, -6447, -5779, -15776, -10543, -8142, -6028, -4576, -14903, -7085, -10275, -5988, -4022, -9449, -6034, -10182, -6406, -4355, -7039, -7576, -10481, -6594, -5971, -6042, -10735, -12139, -6102, -10077, -5147, -6540, -9336, -5684, -13039, -4449, -5644, -7173, -5861, -10946, -4710, -6404, -6152, -6929, -12656, -6287, -6600, -5901, -9247, -8756, -9140, -5629, -6384, -11170, -6098, -9513, -5078, -7412, -10098, -4956, -7975, -4866, -7864, -9491, -4904, -7755, -4930, -7681, -8716, -5856, -9063, -5549, -8024, -7235, -7838, -10883, -6812, -8157, -5775, -11198, -10213, -8346, -7342, -5226, -16470, -8954, -9620, -7158, -5899, -10835, -8071, -10983, -8544, -7222, -10022, -7876, -13422, -12045, -7091, -14439, -8548, -15395, -10606, -6787, -10761, -10332, -12884, -8817, -7185, -8085, -10652, -10287, -8365, -7504, -8403, -8478, -8341, -8698, -7538, -8349, -7415, -7562, -8799, -7687, -6477, -7272, -7897, -8144, -8004, -5823, -7833, -8661, -8029, -8453, -6541, -9320, -8159, -8876, -9742, -9087, -11904, -7116, -10415, -10815, -14632, -10865, -6658, -11041, -7507, -8806, -9105, -6804, -9543, -5818, -7707, 10155, 12746, 13112, 9384, 6364, 9425, 12279, 12488, 8807, 5785, 6856, 10838, 10468, 7169, 4021, -1794, 8320, 6370, 5113, 1089, 3338, 4773, 2049, 3570, -2031, 4578, 1878, 3081, 2124, -3039, 4190, 2224, 1344, 426, -4825, 2790, 3118, -1476, -3958, -4895, 1593, 3326, -3336, -3215, -40, 1441, 2672, -2582, -63, 2254, -2078, 622, -2736, 1020, 3521, -1089, -6869, -1708, 2853, 4154, 1811, 1747, 62, 4384, 4192, 1339, 4130, -49, 4952, 3521, 776, 4507, -2725, 4560, 2308, 2035, 3068, -3883, 3154, 2592, 2099, -2045, -1190, 368, 3919, 780, -955, -1675, -4758, 4235, -493, 1643, -5914, -2613, 3299, -102, 2175, -3555, -576, 1433, 323, 1824, -2409, 554, -344, 524, 616, -3957, 1226, -3936, 628, -124, -3020, 1340, -3346, 361, 1304, -944, 997, 114, -405, 2360, 69, 317, 418, -1152, 2405, 535, -1268, -1198, -1069, 1531, 603, -5980, -5265, -577, -49, 269, -6258, -4021, -918, -1856, -616, -3713, -1023, -2786, -3457, -2425, -4304, 609, -1514, -5701, -4607, -6379, 1493, 253, -5339, -5188, -10266, 1581, 28, -1870, -4916, -5895, 550, -2190, -734, -3085, -3294, -2146, -4314, -1378, -3039, -1655, -2526, -1846, -3501, -6895, -253, -421, -642, -5841, -5964, 766, 65, -417, -6885, -2925, 1104, -557, -677, -3422, -2869, 680, -2226, -977, -1882, -4846, -307, -5870, -1316, -2482, -7492, -1746, -5986, -1963, -3896, -4590, -4094, -2960, -2495, -1718, -4834, -5027, -2262, -2106, -268, -14176, -4192, -2772, -1617, -161, -4262, -5206, -3131, -1845, -1199, -2457, -5959, -2018, -2950, -3579, -2876, -5138, -300, -4511, -8852, -4098, -5770, 1085, -5111, -8511, -4172, -8071, 1678, -4856, -3797, -3774, -9588, 1229, -5366, -1471, -3627, -6087, -643, -7686, -479, -3710, -3453, -3701, -5377, -581, -3755, -2312, -1745, -2660, -1705, -3430, -2398, -620, -1427, -4016, -2901, -3232, -1016, -1039, -7903, -2776, -4205, -2516, -1344, -7185, -3750, -5736, -4869, -2431, -5456, -6694, -7873, -7378, -4341, -5246, -10595, -12277, -6725, -5936, -6069, -6533, -6152, -4723, -5557, -6075, -3954, -2296, -3849, -4801, -4137, -2590, -1009, -4258, -4566, -2724, -2469, -1338, -5936, -5982, -2265, -3786, -3074, -8221, -11402, -2912, -6822, -5872, -8258, -4370, -5367, -4966, -7581, -7360, -2243, -6281, -3751, -6287, -7066, -1808, -2884, -5122, -5047, -6901, -2359, -1531, -9857, -5059, -5925, -3686, -1311, -7128, -6167, -4822, -6161, -1804, -6896, -5863, -4475, -6151, -2600, -9974, -4072, -5347, -3663, -2725, -15938, -3560, -8575, -2717, -1770, -10213, -4551, -7879, -2768, -787, -9373, -4406, -4310, -3255, -205, -9962, -2890, -2963, -3422, 1, -6661, -3392, -2844, -3029, -170, -4916, -8209, -3539, -3108, -942, -4675, -3966, -3962, -3867, -2982, -4586, -1818, -3373, -4092, 7465, 10363, 10751, 7892, -896, 6569, 9725, 10121, 7108, 489, 3261, 7811, 8164, 4473, -38, 1488, 4891, 4774, -1000, -2812, 3807, 1945, 981, -1314, -4478, 3427, -937, 259, -2409, -518, 2267, -4716, 342, -3855, 954, 2702, -1194, -894, -4800, 1416, 3355, 2541, -24, -4117, 1331, 3433, 3956, 950, -5606, 1135, 2957, 4417, -231, -2425, 1451, 1445, 4334, -740, -4, 1960, -2938, 3566, 1676, -36, 2061, -443, 1518, 2270, -1102, 1814, 2329, -4486, 1457, -1257, 1751, 3119, -2316, 873, -678, 2230, 2757, -404, 1232, 550, 2768, 1250, -906, 1095, 1159, 2764, -1686, -2178, 629, 491, 1950, -1012, -2263, 502, -1620, 151, 803, -1032, 320, -5347, -2789, 1188, -332, -302, -9984, -2968, 1024, -469, -936, -8802, -1426, 921, -1322, -874, -4464, -1272, 774, -3355, -300, -1727, -1962, 407, -4289, 192, -290, -2721, -63, -741, 414, -45, -2883, -413, 1133, 417, -1107, -2659, -597, 1776, 49, -3274, -3075, -661, 1373, -1110, -2215, -5329, -642, -89, -3609, -769, -10998, -851, -2524, -9132, -735, -5260, -666, -4873, -5634, -1800, -3680, 670, -5591, -1939, -3299, -4235, 1397, -7483, -350, -4024, -6442, 682, -10761, 74, -5944, -1923, -2142, -4543, 208, -6266, 39, -12373, -2914, 956, -2055, -71, -3681, -2241, 2248, -784, -2158, -2380, -1894, 3287, -867, -2712, -2920, -1889, 3491, -1740, -699, -3844, -2384, 2524, -3659, -485, -2494, -3500, 9, -4356, -2160, -1864, -3123, -1755, -2585, -8293, -2174, -1722, -256, -2470, -4448, -2638, -1516, -185, -4057, -2350, -3833, -3287, -1331, -7535, -2298, -6043, -7242, -2531, -11586, -3140, -4751, -2519, -1968, -9226, -3707, -3978, -1185, -1044, -6128, -3021, -5076, -1576, -888, -4336, -2184, -6571, -3061, -1757, -3834, -2065, -5168, -5343, -3763, -4201, -2827, -3367, -9239, -5769, -4884, -4592, -2241, -8583, -5319, -6652, -7865, -1871, -5208, -5235, -6257, -10939, -1962, -4412, -6054, -2774, -7764, -2222, -5460, -5720, -1289, -4814, -2796, -6417, -5008, -886, -3633, -4235, -4891, -5366, -1022, -4116, -7967, -4810, -6575, -1521, -4923, -11224, -7129, -7925, -2409, -3956, -6990, -17269, -8064, -3622, -3433, -5957, -8662, -6873, -4986, -3865, -5455, -5338, -6159, -7519, -4616, -5257, -3224, -7325, -9523, -4790, -5156, -2448, -9371, -3567, -4489, -5697, -2821, -5314, -1640, -4708, -8441, -3770, -3707, -1381, -6199, -8236, -3921, -3471, -2251, -8708, -4559, -3491, -3836, -3328, -8789, -3216, -3637, -4449, -3813, -9644, -3129, -4424, -5738, -4748, -7124, -3965, -4513, -6723, -5711, -4060, -5275, -3835, -4397, -3995, -2311, -5990, -4048, -3026, -2356, -1567, -5673, -5713, -2770, -1660, -1904, -5196, -10226, -2655, -1716, -3442, -3897, -6594, -1813, -2358, -5478, -2519, -3534, -912, -3236, 2816, 10853, 11130, 7971, 5305, 2639, 10384, 10551, 7334, 5102, 1951, 8983, 8721, 5502, 4500, 472, 6733, 5317, 2994, 3652, -2632, 4136, 846, -685, 2731, -942, 2498, 250, -2235, 1608, 1547, 2032, -817, 2360, 1113, 2142, 1255, -1477, 3248, 2007, 2181, -258, -1515, 2199, 2816, 2574, -934, -2617, -551, 3123, 3037, -17, -2686, 1598, 2910, 3264, 1765, 319, 3044, 1515, 3095, 3165, 1646, 2554, -4918, 2191, 3454, 1129, 531, 1550, 591, 2469, -2124, -1176, 4667, 243, 798, -3351, -1221, 6207, 202, 977, -39, -1104, 6777, -1813, 1461, 366, -318, 6336, -1875, 1209, -607, -15, 4776, 1149, 936, -2417, -791, 2440, 2332, 1056, -3948, -2974, 1560, 2195, 1417, -3292, -8100, 1569, 929, 1661, -1614, -3619, 997, -930, 1448, -901, -1155, -156, -1963, 846, -2205, -348, -1919, -2811, 257, -8398, -214, -3453, -4946, -206, -1537, -170, -7124, -10364, -164, 402, 115, -4540, -12621, 588, 652, 896, -1195, -16424, 900, 60, 1597, -1237, -7107, 278, -1201, 1633, -3867, -3272, -858, -4112, 939, -2844, -900, -1321, -10210, -263, -1175, 454, -1039, -4481, -2017, -716, 561, -736, -6075, -5001, -71, -1380, -522, -4911, -1851, 211, -5301, -51, -100, 645, -415, -538, 199, 1670, 1488, -1398, 29, -730, 1896, 1173, -1821, -2739, -3889, 487, -216, -2279, -6894, -6878, -3666, -2184, -3296, -2486, -6489, -1177, -1264, -4863, -3892, -11466, 696, 258, -4590, -6984, -3988, 744, 570, -2274, -3033, -2936, -16, -459, -1090, -1224, -4081, -1101, -2535, -1339, 120, -7075, -3108, -1752, -3254, 546, -14394, -7204, -355, -3727, -306, -8928, -4062, 58, -1666, -2335, -5461, -2334, 28, -982, -2879, -4177, -2322, -84, -990, -2306, -3866, -3444, -366, -908, -3226, -3878, -5506, -1203, -564, -6448, -4126, -11451, -2910, -152, -8746, -4208, -6954, -3861, 100, -5412, -3887, -4327, -2458, 36, -4128, -4020, -4759, -1580, -462, -3551, -4817, -5465, -1384, -1518, -3568, -5537, -2972, -1548, -2904, -4034, -5937, -1743, -2046, -3334, -4066, -7162, -1717, -2720, -2923, -3738, -10740, -2582, -2337, -2918, -4108, -10690, -4479, -1383, -3176, -5674, -9109, -8246, -1332, -2751, -8263, -9485, -10896, -2741, -2023, -8803, -4645, -7508, -5089, -2009, -7045, -2053, -5038, -2886, -2801, -4004, -1291, -3449, -1253, -3022, -2556, -2207, -3232, -859, -2392, -2889, -4765, -5100, -1269, -2410, -4490, -4375, -12314, -2208, -3197, -4435, -3202, -5109, -3341, -4380, -3450, -3109, -3996, -4346, -6059, -1620, -2968, -4817, -5390, -7471, 117, -2499, -5740, -6338, -5152, 752, -2173, -6120, -6169, -4065, 257, -2365, -8440, -4260, -4972, -1232, -3283, -8427, -2650, -7703, -3235, -5008, -4629, -2540, -7609, -4511, -5536, -3071, -5195, -7715, -2229, -7725, -3696, -1743, -3123, -402, -3041, -2461, -2227, -3511, 82, -1098, -1439, -2126, -3625, -604, -1073, -1291, -1826, -3226, -2174, -2719, -2504, -1520, -3114, -3895, -6905, -3542, -946, -4190, -5272, -7702, -2073, -304, -9118, -7403, -5800, -2159, -127, -4725, -6445, -6421, -5627, -774, -2103, -3377, -9635, -5046, -2299, -1817, -1608, -11314, -1802, -3645, -3641, -607, -7169, -1155, -3617, -5895, -97, -5934, -1594, -3750, -2787, -76, -5338, -2697, -4602, -1917, -767, -3873, -3565, -4736, -2394, -2683, -2203, -2411, -3080, -3139, -8290, -1188, -1566, -2246, -3717, -6051, -1043, -2144, -2269, -4135, -3166, -1736, -4665, -1541, -3420, -2445, -2807, -5714, -428, -1720, -2671, -3901, -3742, -133, -304, -3534, -6730, -4461, -635, 196, -4999, -9280, -10084, -1368, -461, -6250, -3601, -7678, -1850, -2531, -4963, -1718, -6610, -2500, -5824, -3788, -911, -10839, -4332, -5219, -3619, -707, -7788, -9632, -2921, -4230, -945, -5913, -8131, -1636, -5498, -1431, -6064, -7834, -1339, -7316, -1910, -6401, -7193, -1225, -7706, -2012, -5833, -4882, -998, -6730, -1463, -4220, -3883, -1552, -7327, -1007, -3446, -3715, -3291, -9721, -1335, -4379, -4961, -4267, -8177, -2680, -8030, -7886, -4251, -8146, -4898, -11524, -5527, -6364, -9818, -4962, -9179, -4559, -12750, -7549, -3475, -7716, -5543, -10002, -6633, -2922, -5897, -8312, -16142, -5658, -3029, -4932, -15307, -9516, -4894, -3818, -4216, -12433, -8084, -5217, -6432, -3736, -10402, -5130, -4942, -11180, -3459, -8452, -2451, -4563, -6610, -3042, -5685, -1321, -6302, -7019, -2659, -3931, -1369, -14280, -10820, -2711, -3088, -2285, -9053, -9099, -3352, -2633, -3749, -11980, -9436, -4253, -2509, -5009, -8102, -13941, -4320, -3419, -4522, -5168, -12003, -4059, -7399, -3655, -4747, -14360, -4608, -6510, -3954, -5312, -8539, -5475, -3113, -6467, -5601, -6161, -5400, -2508, -12457, -6038, -5294, -5312, -3169, -5293, -7629, -4882, -5578, -4175, -3787, -8540, -4697, -6554, -3984, -4043, -7789, -5165, -8141, -2751, -6578, -7592, -7204, -6154, -2242, -11739, -5629, -15877, -4579, -3361, -5185, -3711, -7014, -3568, -8555, -3553, -2900, -4905, -2461, -5455, -2903, -3147, -4420, -1824, -2925, -2480, -4606, -4717, -2029, -2581, -2166, -8433, -5083, -3066, -3064, -2108, -11378, -5143, -4636, -3586, -2551, -7590, -5327, -5433, -4131, -3709, -8176, -6163, -4356, -4980, -5464, -13694, -8437, -3324, -5727, -7051, -11130, -12397, -3008, -6211, -8993, -9184, -8892, -3231, -7306, -7476, -9969, -7742, -3573, -10203, -4634, -12684, -7927, -3684, -16659, -3624, -17243, -8584, -3813, -9568, -3837, -13002, -8983, -4193, -7514, -4636, -10462, -8864, -4036, -5969, -5485, -8704, -8689, -3081, -4683, -6535, -7310, -7888, -2436, -3996, -7866, -6560, -7437, -2539, -3992, -9937, -6985, -9075, -3531, -4695, -11614, -9521, -14498, -5769, -6377, -8750, -6250, -2388, -2382, -792, -3844, -5568, -4195, -2097, -1896, -4692, -3336, -7965, -2214, -4281, -6960, -2085, -4817, -2960, -4738, -14538, -2011, -4251, -4964, -4203, -9271, -2839, -6000, -9238, -3609, -8753, -4399, -4727, -9798, -2251, -8970, -7127, -2190, -7635, -1894, -5336, -4922, -1187, -6424, -3022, -3667, -2114, -1209, -5803, -5445, -3153, -1059, -1714, -5782, -6155, -2981, -1207, -1976, -6663, -6096, -2844, -2311, -2135, -7195, -8362, -2705, -4110, -3132, -3972, -14535, -2467, -5510, -5792, -1921, -7078, -2310, -4635, -4818, -1135, -5387, -2569, -3822, -2402, -1269, -4121, -3458, -4663, -1609, -2134, -2080, -5044, -10175, -1910, -3693, -420, -7921, -5837, -3250, -6267, 390, -11087, -2919, -5527, -11392, 354, -4261, -2479, -5466, -12193, -474, -1930, -3810, -4357, -7850, -1864, -1383, -4977, -4058, -6027, -2994, -2375, -3743, -3166, -5115, -2870, -4993, -4345, -2099, -4091, -1980, -7257, -8726, -2171, -3207, -1416, -4962, -7049, -4404, -3282, -1581, -2328, -4625, -11970, -4971, -2512, -957, -4192, -3732, -8884, -3966, -954, -4571, -2315, -4916, -3980, -2717, -4787, -2467, -2751, -2466, -10008, -4276, -3237, -1999, -1585, -3612, -3781, -3062, -2151, -1621, -1599, -3895, -2077, -3195, -2708, -1552, -4783, -1739, -5405, -5519, -2732, -5996, -2242, -6747, -8327, -4793, -6178, -3120, -5205, -4868, -6877, -5084, -3574, -4568, -3278, -8116, -4178, -3346, -3155, -2751, -9489, -3357, -2974, -1424, -3687, -8878, -2607, -3122, -724, -7232, -7028, -2531, -4177, -1287, -8077, -4775, -3380, -6154, -3483, -8296, -2786, -5279, -7446, -9742, -7717, -2005, -6688, -8091, -7778, -4203, -2509, -3835, -9854, -6041, -3579, -3402, -2103, -5315, -6127, -4537, -3127, -1887, -2927, -7252, -5946, -3274, -3282, -2280, -8381, -6652, -4967, -7575, -3073, -6001, -7409, -8732, -10256, -5786, -4500, -10375, -14838, -7218, -12124, -4221, -8848, -10338, -7181, -5745, -4837, -5972, -6104, -7131, -3726, -6107, -5315, -4291, -6432, -3057, -7145, -5953, -4118, -5286, -3563, -7131, -7803, -4913, -4846, -5573, -7630, -12685, -4135, -5862, -5860, -8251, -10917, -2629, -9106, -3478, -5686, -7278, -1934, -6210, -2447, -3660, -6232, -1807, -4019, -2351, -2685, -6934, -1713, -3831, -2811, -2361, -10394, -1327, -5543, -3893, -2399, -11271, -924, -12006, -6556, -2697, -8086, -980, -6260, -8052, -3147, -7675, -1867, -3905, -4646, -3523, -8270, -4120, -3468, -3723, -3978, -8272, -9603, -4622, -4360, -5092, -6699, -5698, -8289, -6575, -7691, -4966, -3395, -7250, -13723, -9388, -3800, -2684, -5014, -8438, -5655, -3298, -2890, -4606, -5398, -3834, -3409, -3617, -4354, -4354, -3106, -3951, -4212, -3430, -4542, -3071, -4575, -4677, -2538, -5841, -3489, -4923, -5681, -2124, -8023, -4274, -4900, -7264, -2333, -8982, -5708, -4813, -8796, -3313, -8289, -8689, -5138, -7854, -5175, -8156, -10859, -6117, -5752, -5528, -4471, -2652, -6196, -11727, -8669, -4997, -2925, -1220, -9177, -4889, -4601, -3001, 373, -6932, -2599, -2013, -2167, 571, -6367, -2479, -1175, -1324, -277, -4778, -3825, -2284, -1048, -2049, -2983, -3926, -5524, -1465, -4418, -2204, -2113, -3979, -2658, -6428, -2456, -1106, -2602, -4177, -8465, -3291, -1040, -2746, -4047, -10954, -3643, -1595, -3662, -3529, -5062, -3396, -2253, -5660, -4050, -2701, -3635, -3181, -7993, -5894, -1968, -5269, -5613, -4906, -11586, -2387, -6787, -19755, -3199, -7378, -3991, -3393, -7052, -2632, -4643, -7713, -1496, -6389, -2867, -3961, -5292, -933, -8342, -3994, -3450, -2399, -1669, -13083, -6695, -1822, -1225, -4265, -6013, -7647, -205, -1037, -6638, -3330, -5317, 707, -1597, -4335, -2858, -4621, 846, -2926, -4878, -4668, -4337, 262, -4596, -10910, -8174, -5034, -934, -3779, -6660, -4125, -9053, -2616, -2219, -4445, -2773, -8275, -4516, -1280, -4806, -2834, -5603, -5921, -916, -7097, -3696, -5307, -7555, -1364, -9936, -4798, -5744, -9207, -3079, -8646, -5690, -7252, -5003, -6585, -8770, -6410, -10935, -3488, -5610, -8659, -6744, -9245, -4543, -3736, -6559, -7362, -6667, -9999, -3573, -4302, -8965, -5489, -3734, -5494, -2963, -5703, -5456, -1880, -11408, -2594, -2907, -6858, -1770, -4699, -2890, -1549, -6535, -2640, -2857, -3453, -1154, -4094, -4328, -2189, -4074, -1541, -3391, -7130, -2055, -4605, -2792, -4375, -8446, -2633, -4459, -5634, -6677, -6922, -3739, -4190, -16075, -7423, -5863, -3600, -4931, -5658, -5893, -4679, -3076, -6630, -3613, -3718, -3507, -3927, -7514, -2568, -2615, -2837, -7290, -8002, -1719, -2934, -2845, -6953, -8216, -1143, -4435, -3538, -4074, -8730, -1125, -4456, -5120, -3464, -9807, -1668, -3324, -8996, -4488, -7542, -2334, -3513, -9803, -7113, -5666, -2808, -5626, -6177, -5883, -4286, -3672, -12648, -5514, -4407, -3453, -5572, -8244, -5411, -5150, -3455, -8737, -7283, -4425, -10922, -4379, -13654, -5561, -3741, -5647, -6222, -14264, -3558, -4234, -2762, -6842, -13732, -2974, -6441, -1961, -4929, -7858, -3630, -11656, -2401, -3825, -4479, -4823, -8689, -3994, -3620, -2891, -5125, -7594, -6922, -3746, -2095, -4262, -6938, -10203, -3831, -1822, -3487, -5721, -7810, -4420, -2297, -3764, -5273, -5157, -6377, -3705, -5866, -5856, -3896, -8346, -5827, -11724, -7327, -3817, -6118, -6657, -5614, -9996, -4462, -5188, -5069, -3567, -23608, -5227, -5446, -3785, -2982, -9908, -6383, -6470, -3373, -2828, -7664, -9051, -7122, -3856, -2319, -7283, -14350, -6048, -5148, -1901, -7891, -10559, -5218, -6995, -2190, -8009, -8803, -5223, -9427, -3309, -6301, -8108, -5472, -11170, -5393, -4919, -7391, -5316, -14433, -7828, -4693, -6097, -5145, -7918, -5216, -5792, -4923, -5350, -4639, -3623, -8660, -4158, -5483, -3482, -3677, -8145, -3554, -4932, -3589, -5313, -5483, -2925, -4456, -4440, -9515, -4467, -2589, -4890, 3118, 146, 1330, 6913, -8593, 2225, -2169, 4462, 6442, -5307, 12, -2240, 6211, 5121, -3754, 1312, 1078, 6366, 3616, -3143, 2963, 2155, 5076, 3021, -2276, 3466, 3005, 1414, 2465, -1894, 3025, 3214, -157, 740, -4887, 1293, 2110, 3189, -4219, -2132, -4556, -1005, 3860, -2021, 2117, -988, -6969, 3108, 306, 3776, 2001, -3941, 546, -137, 4468, 2875, -3603, -7925, -958, 4940, 2381, -2086, -131, 1799, 5298, -257, -19, 1104, 3233, 5130, -1436, 755, 202, 3141, 3946, 2103, -996, -1421, 1700, 660, 2879, -1924, -391, -73, -827, 1894, 2690, 319, 1207, 2394, -865, 4090, 511, 2256, 2674, -2225, 3748, 735, 2067, 1310, -805, 1920, 526, 1172, -336, 316, 162, -206, 561, -4199, 1989, 568, -1159, 654, 72, 3204, 150, -3201, 1390, 3714, 3505, -472, -9209, 1725, 4733, 2879, -171, -1469, 729, 4091, 1390, -691, 396, -2601, 1674, -810, -2626, 295, -7749, -4042, -3765, -4460, -1820, -3734, -3146, -8464, -6383, -8245, -1372, -2356, -3271, -5291, -2978, 733, -1947, -1560, -1302, -1978, 1491, -432, -2768, 154, -3479, 940, 126, -7540, 9, -7941, -284, -776, -2313, -1679, -4676, -294, -3182, -1244, -3582, -2537, -44, -2447, -1635, -2579, -1208, -961, -777, -1382, -3078, -74, -3733, -602, -943, -3659, 674, -12982, -1533, -1950, -926, 812, -5139, -3127, -3137, 55, 385, -4789, -4648, -987, -234, 565, -5526, -5624, -483, -47, 1504, -2684, -7560, -1628, 61, 1754, -738, -8574, -1004, -1997, 1217, 92, -2497, 756, -4957, 887, 251, -78, 1558, -1276, 1105, -37, 864, 1478, -1042, 1072, -963, 840, 515, -1753, 612, -3097, 141, -1088, -1256, -163, -5478, -1065, -2240, -1733, -901, -2319, -3035, -2699, -4870, -1569, -198, -5528, -3643, -3113, -3722, 748, -2815, -6049, -748, -8112, 813, -1249, -10768, -477, -1404, 223, -1639, -9965, -1843, 436, -587, -4400, -7743, -5307, 600, -1048, -9887, -4784, -6827, -371, -1397, -3433, -2408, -4764, -1549, -3179, -1722, -763, -4034, -1054, -5471, -2083, 41, -3624, 844, -613, -5535, -199, -3123, 2355, 787, -6442, -1793, -3035, 2846, 197, -1717, -5117, -4639, 2196, -2325, 310, -4472, -17536, 255, -7013, 1172, -1994, -3928, -3289, -9853, 1038, -379, -1702, -10583, -4825, 59, 694, -786, -4575, -2715, -1504, 1229, -290, -574, -2738, -2659, 1129, -455, 1086, -4577, -2561, 147, -1698, 1292, -6912, -2028, -2223, -3573, 147, -4034, -1176, -6949, -4009, -2647, -2021, -691, -7117, -1952, -4681, -1034, -173, -5394, 544, -2675, -487, 966, -1670, 2086, -1898, -583, 1526, 1029, 2718, -1984, -2698, 884, 2329, 2530, -2503, -3246, -933, 2231, 1490, -2589, 810, -2167, 188, -256, -1535, 1951, -1852, 4277, 8809, 8073, 8894, 6117, 3705, 8169, 7263, 8200, 5739, 2140, 6120, 4511, 5897, 4409, 220, 2412, -1604, 1340, 1445, 146, 481, -1372, 1083, -3380, 1598, 78, -303, 1172, -534, 1779, 437, 2339, -180, 102, -96, 3588, 3941, 1896, -338, -7107, 5326, 4951, 4069, -568, -1001, 5674, 5616, 4464, 116, 533, 4623, 5794, 2535, 2085, -90, 2337, 5337, -650, 3534, -2172, 3173, 4030, 3689, 3828, -2848, 4564, 1813, 4696, 3088, -83, 4455, 1995, 3875, 1675, 2758, 3043, 3189, 1410, 215, 4450, 479, 2920, -1555, -385, 4934, -2987, 1382, 245, 524, 4125, -3666, -1159, 1789, 2241, 2386, -582, -2739, 2611, 3599, 3106, 367, 503, 3170, 3851, 4087, -163, 2224, 3834, 2505, 3466, -1465, 2628, 4288, -600, 1277, -2497, 2187, 3945, 1691, 460, -1772, 1456, 2627, 3462, 1714, 507, 977, 1390, 4027, 1833, 2274, 325, 1221, 3987, 747, 3308, -1273, 328, 3319, -1813, 3771, -4158, -1971, 1860, -2041, 3738, -8238, -6137, 140, 549, 3185, -8916, -8056, -245, 1533, 1988, -3807, -2856, 8, 1112, 86, -2567, -1311, 257, -1158, -625, -4053, -884, 724, -8202, 204, -5880, -549, 1493, -3115, -338, -1423, -598, 2289, -2715, -2811, 211, -2133, 2723, -5070, -3071, 611, -8399, 2597, -3161, -2561, 692, -3892, 1767, -1189, -3756, 1144, -1831, -48, -728, -3358, 1838, -1321, -3653, -891, -2556, 2279, -818, -5325, -1002, -2309, 2273, -755, -1921, -970, -3974, 1745, -2182, -462, -1343, -6567, 595, -4975, -109, -2688, -712, 98, -2412, -786, -4322, 515, 930, -1467, -2608, -3287, -363, 881, -3112, -5276, -1939, -1794, -198, -6744, -6453, -1216, -868, -1136, -1844, -4225, -1144, -463, -2293, -40, -2040, -1808, -1214, -5789, 735, -1162, -4271, -3008, -8304, 1061, -1156, -6402, -4590, -6784, 835, -1738, -1396, -3877, -4845, -72, -3918, -375, -3647, -2302, -1608, -8159, -1533, -3457, -957, -3636, -2085, -3981, -2984, -393, -6563, -454, -4316, -2912, -391, -7770, -154, -8634, -3245, -852, -4968, -428, -2861, -3898, -1510, -4373, -1559, 310, -5401, -2226, -5840, -5442, 1388, -5982, -3498, -12001, -6296, 1478, -2471, -6107, -5912, -2775, 1040, -626, -5956, -2526, -2580, 37, -222, -3260, -729, -3968, -2029, -982, -2254, 52, -7660, -4143, -1877, -1721, 0, -9829, -3081, -1249, -993, -278, -7732, -3697, -1019, -611, -13, -9038, -9054, -2074, -485, 538, -3289, -6787, -3741, -897, 1122, -1718, -5178, -3493, -3183, 1177, -2659, -4875, -1197, -3555, -370, -7024, -2896, 359, -1109, -10480, -3403, -1167, 750, -742, -682, -1152, -273, 631, -359, 1694, -417, -631, 967, 650, 2436, -396, -3188, 1408, 1224, 2455, -890, -4362, 1385, 1311, 1974, -2045, 6241, 8127, 8154, 3329, 3450, 5414, 7353, 7504, 4539, 2359, 2893, 4853, 5406, 5810, 1415, -1407, 256, 1137, 6393, 2869, -4026, -1018, -3143, 6315, 2155, 1049, 1256, -932, 5055, -2328, 1888, 2348, -688, 522, 392, 1371, 1929, -161, 1861, -383, 1944, 436, 605, 4813, 1599, 2704, -665, 78, 5335, 4973, 2879, 316, -4132, 4860, 5703, 2508, 552, -2180, 3700, 5143, 1233, -840, 1420, 1344, 4776, -241, -3382, 2340, -973, 4692, 1402, -6939, 1903, 1856, 4098, 2648, -7534, 271, 2871, 3474, 2561, -2175, -3392, 2245, 3982, 1263, 431, -5024, -271, 5016, -803, 2239, -404, -4052, 5332, -1549, 3452, 1413, 285, 4676, -1912, 4399, 2200, 1950, 4041, -4243, 5284, 2722, 2343, 5254, -7932, 5851, 3446, 2058, 6540, -3096, 5792, 3984, 1509, 7012, -79, 5012, 3853, 851, 6625, 1757, 3676, 2829, -245, 5303, 2223, 2010, 665, -2602, 2883, 1032, -577, -3711, -5186, -375, -2619, -5703, -5238, -928, -593, -1219, -2876, -1840, 1076, 1431, 735, -2153, -756, 1646, 2671, 1002, -3381, -237, 951, 2829, 384, -4943, 284, -1173, 1765, -810, -2245, 794, -1385, -1118, -718, -879, 1043, 812, -1580, 712, -1844, 617, 1873, 391, 1316, -2229, -997, 2264, -60, 984, 724, -1524, 2405, -3089, 20, 2026, 1053, 2434, -4403, -739, 2167, 2422, 2259, -839, -659, 1578, 2632, 1650, 247, -828, 419, 1795, 319, -694, -1902, -798, -256, -1868, -4354, -3589, -864, -1973, -3668, -3444, -3657, -939, -447, -4164, -3165, -2500, -2023, 36, -5331, -7651, -2047, -2187, -969, -5920, -3386, -2484, -1053, -2807, -5063, -1625, -3744, -1227, -2107, -4562, -1828, -5324, -3535, -728, -5042, -2414, -4339, -4821, -435, -5803, -1451, -1994, -2642, -1112, -3598, 21, -334, -3353, -2078, -1599, 842, 223, -10118, -2764, -810, 845, -733, -5822, -4143, -1101, -5, -3691, -6578, -4775, -1730, -1606, -2260, -4415, -2597, -1198, -2413, -567, -414, -1047, -116, -1646, -993, 475, -162, 1059, -1526, -3779, -725, 354, 1978, -2684, -12033, -4345, 581, 2077, -5734, -6570, -7242, 245, 967, -9861, -2620, -13415, -1008, -2056, -3860, -341, -4412, -3183, -16484, -1046, 515, -1713, -3196, -5242, 290, 709, -847, -1213, -3672, 196, 859, -581, 130, -2007, -1415, 1056, -926, 842, -1128, -1339, 832, -1558, 1039, -1686, 429, -331, -120, 936, -4188, 662, -2454, 1262, 705, -4660, -622, -3390, 1469, -124, -3031, -3537, -1024, 687, -2587, -4361, -8373, 1268, -716, -3647, -8348, -7906, 2426, -1858, -1745, -2939, -3338, 2563, -1919, -2562, -1240, -1319, 1873, -1528, -8172, -740, -557, 537, -905, -5316, -928, -343, -1343, -382, -3196, -2312, -285, -3772, -710, -2727, -4046, -461, -2665, -536, -163, 1395, -2433, 1451, 700, 744, 289, -3430, 3049, 1103, 669, 769, -1953, 3410, 273, -1166, 1312, 104, 3125, -2569, -3797, 1211, 1460, 2553, -9160, 187, 970, 1832, 1920, -2243, 1512, 854, 1220, 1268, -1188, 946, 536, 262, 486, -2287, -1878, -373, -200, -702, -7091, -6246, -1769, -1183, -2357, -3416, -2110, -2397, -3818, -3072, -1011, -1305, -1881, -3042, -1255, -866, -1461, -1339, -1058, 828, -1576, -1817, -975, -769, 1895, -384, -1716, -768, -1761, 1759, 840, -483, -1031, -4489, 255, 635, 564, -2962, -4338, -2924, -1584, 561, -6641, -1145, -3653, -8057, -1020, -37, -382, -2246, -1516, -6472, 2152, -2088, -1904, 192, -4472, 2868, -3651, -1567, -85, -2669, 2764, 450, -990, -2113, -2535, 2310, 1626, -728, -874, -1695, 1779, 891, -1428, 971, -1296, 972, -2200, -4166, 1114, -1924, -589, -5780, -7825, 221, -2285, -3323, -1691, -3487, -433, -1145, -6073, -230, -2525, 154, -513, -7508, 585, -2832, 982, -1242, -6886, 1164, -3535, 1293, -3821, -2967, 1527, -2951, 1074, -3743, -1304, 1347, -1822, 720, -957, -1811, 494, -1426, 611, -92, -6989, -125, -2038, 500, -931, -3428, -303, -4554, -223, -4165, -768, -1666, -8290, -1602, -9042, -497, -5360, -2436, -1486, -5364, -1441, -9835, -372, -324, -4806, -3517, -7210, 429, -68, -4413, -9929, -2532, 63, -987, -4720, -4172, -1231, -2332, -2607, -7687, -1449, -1587, -10531, -2300, -6691, -997, -1616, -2487, -1538, -2714, -1635, -947, -2399, -1748, -1546, -1794, -870, -4803, -2651, -1760, -1825, -737, -1535, -4039, -2533, -1711, 154, -150, -5934, -2753, -484, 1019, -933, -7073, -2866, 5, 1070, -3637, -5680, -4080, -1145, -109, -2894, -3903, -7681, -5198, -2927, -1149, -3309, -13945, -4640, -7076, -712, -4112, -8977, -2381, -8465, -1063, -5929, -6661, -2103, -10346, -2170, -6951, -5306, -1922, -8416, -3844, -6126, -3923, -918, -6938, -3284, -5098, -1641, 232, -4789, -1976, -5542, -320, 584, -2403, -1930, -9068, -89, -478, -1271, -3167, -8062, -453, -3539, -1173, -4139, -5769, -675, -2442, -1128, -3323, -5757, -424, -655, -992, -3463, -5377, -141, -554, -1804, -4584, -4849, -221, -1415, -3947, -3942, -5664, -758, -2821, -5311, -2857, -7407, -1807, -4706, -4203, -2952, -7839, -3364, -7523, -2643, -4658, -7175, -4285, -10408, -1974, -8684, -5055, -3850, -10031, -3020, -4467, -3341, -3543, -10283, -8030, -2506, -2501, -3456, -9502, -4641, -2462, -2508, -3156, -8393, -1826, -4311, -3506, -2583, -6880, -1017, -10471, -5698, -1943, -5264, -1200, -6114, -8872, -1308, -3958, -2024, -3779, -9555, -714, -3006, -3196, -2756, -7642, -318, -2665, -4451, -2181, -7800, -232, -3248, -5932, -1995, -9862, -387, -5214, -7985, -2473, -5118, -634, -10596, -6671, -590, 828, 1140, 897, -4455, 836, -453, 1020, -805, -8201, 1240, -3314, 1013, -1857, -4285, 878, -10100, 575, -1714, -2248, -534, -4527, -1053, -2108, -1398, -3738, -3428, -5782, -2540, -1106, -8967, -1979, -7322, -2507, -1225, -4764, -375, -5824, -3301, -1909, -188, 210, -5874, -5913, -2966, 2004, 13, -2887, -11871, -3077, 2628, -182, -2256, -7499, -2382, 1941, -20, -2963, -6365, -2134, -214, 85, -3343, -6950, -2664, -5440, -97, -2891, -9609, -4111, -6051, -512, -1859, -6414, -4387, -2835, -991, -1289, -3253, -1811, -2261, -1819, -1961, -2581, -154, -3716, -3708, -4248, -2866, 428, -5957, -4586, -5717, -1388, 250, -1362, -2812, -4076, -46, -232, 202, -2495, -3994, 145, -473, -293, -2952, -5457, -607, -394, -2999, -2029, -5329, -1868, -402, -1902, -730, -2852, -2581, -860, 88, 94, -1471, -1763, -1976, 154, 599, -1287, -409, -3449, -1277, 655, -2383, 311, -2279, -4613, -296, -5104, -67, -199, -7294, -3867, -8220, -1944, 800, -3967, -4647, -7273, -3447, 759, -2999, -810, -6999, -836, -375, -3924, 91, -6887, 602, -3578, -9585, 263, -6229, 989, -4598, -5303, 443, -5622, 594, -814, -1778, 190, -5693, -602, 161, -20, -1138, -6369, -3280, -345, 693, -4110, -7452, -10517, -2039, 522, -6520, -10090, -1877, -3949, -111, -3046, -10215, 153, -3469, -1228, -858, -4303, 197, -3005, -4583, 20, -1881, -1980, -3873, -6635, -204, -969, -12129, -6634, -2248, -1165, -1067, -3411, -14424, -1216, -2162, -1806, -3472, -10512, -1015, -3433, -2713, -8785, -8797, -1523, -4765, -3220, -6674, -6629, -2753, -1521, -3010, -5032, -4341, -2046, 556, -2567, -5564, -2743, -961, 1157, -2728, -4715, -2157, -1369, 577, -3680, -2853, -2554, -3246, -935, -4763, -1830, -3949, -5571, -2846, -4939, -2357, -7216, -5189, -5632, -5028, -5879, -6176, -3218, -5355, -6656, -7252, -2515, -2071, -1519, -8773, -3268, -1159, -1901, 43, -6697, -2751, -1582, -2470, 251, -5832, -3593, -4347, -3784, -472, -4930, -4996, -2333, -5359, -1016, -3163, -5633, 387, -3609, -360, -1554, -4434, 1352, -1620, 357, -653, -2786, 1356, -955, 589, -304, -1947, 814, -1709, 232, -331, -2133, -95, -4579, -960, -981, -3216, -1523, -9511, -3151, -2752, -5009, -4028, -4287, -3325, -6326, -7580, -8835, -2825, -1915, -12577, -9888, -6154, -2438, -1518, -16095, -8728, -4523, -2806, -1754, -12740, -4331, -4205, -4441, -2262, -10771, -1767, -4063, -7782, -2945, -5524, -579, -3885, -4925, -3475, -2923, -415, -3872, -3641, -3227, -1621, -1265, -3880, -3911, -2963, -1030, -3607, -3291, -2867, -3751, -882, -10713, -2529, -1312, -6123, -944, -7948, -2416, -1050, -9084, -1181, -7284, -3032, -2472, -8240, -1961, -10394, -3808, -7257, -8586, -3656, -7317, -4037, -6884, -10044, -5869, -5150, -3836, -5947, -2580, -1817, -63, -1113, -9139, -3509, -732, 2203, -2243, -7660, -666, -399, 3078, -3463, -3819, 709, -1157, 2992, -3260, -3360, 978, -3220, 2087, -1007, -5895, 413, -6009, 198, 468, -7010, -938, -5300, -2032, 601, -3241, -3022, -4062, -1096, -266, -2400, -3961, -3889, -541, -976, -2954, -2619, -4510, -1088, -1482, -3296, -1694, -3411, -1747, -2278, -2002, -1510, -1566, -1565, -2514, -1351, -1842, -731, -667, -2777, -2532, -1939, -895, -195, -2897, -6893, -1062, -1717, -852, -4150, -2542, -28, -2440, -3422, -5473, -890, 332, -3761, -6847, -2396, -1703, -569, -8831, -1617, -2322, -6028, -4802, -1462, 155, -5542, -3449, -3114, 1202, 196, -3242, -1460, 157, 2223, -1741, -982, -1798, 999, 2258, -4027, -504, -2424, 1102, 1597, -309, -858, -1269, 835, 568, 1041, -1503, -573, 96, -538, 860, -2239, -1024, -476, -2009, -584, -3420, -2146, -1219, -4215, -3154, -5719, -2372, -4291, -5754, -5190, -10646, -2435, -8020, -6840, -4674, -10945, -3730, -3218, -7367, -2206, -6945, -6626, -2250, -5292, -295, -4357, -7260, -2140, -4918, 608, -2141, -4577, -3272, -6137, 700, -806, -4059, -8068, -7767, 67, -862, -2626, -6891, -9693, -1233, -2828, -190, -4005, -13823, -3004, -7741, 1078, -2999, -7404, -4510, -6447, 1406, -1940, -6131, -1874, -7410, 1286, -1144, -5664, 323, -9777, 931, -869, -4100, 1027, -5152, 3, -929, -3232, 550, -2988, -2172, -960, -3351, -688, -2065, -5764, -756, -3666, -2056, -1780, -2930, -674, -3646, -3854, -1655, -605, -1363, -3738, -5948, -1755, 749, -3931, -4082, -4189, -2218, 1260, -7893, -3659, -2275, -2730, 775, -2651, -2921, -1098, -2917, -955, -1833, -3719, -945, -3060, -4225, -3916, -10150, -1887, -3949, -4420, -7190, -3920, -2446, -6648, -3020, -2013, -1590, -1372, -9080, -3407, -786, -1784, -739, -6573, -5994, -1196, -4625, -954, -5556, -5302, -2991, -6013, -1596, -3238, -2435, -6571, -2527, -1443, -1401, -1446, -12956, -1688, -623, -692, -1449, -9256, -1925, -434, -936, -2392, -6646, -2804, -1317, -1929, -6513, -7742, -4992, -3521, -3534, -4806, -5703, -11473, -7166, -5587, -1267, -2751, -6370, -6135, -5950, -694, -2614, -5122, -3782, -4633, -1739, -4493, -4723, -2648, -3777, -4008, -2574, -3483, -2485, -3100, -5203, -825, -2691, -3275, -2515, -3061, -688, -2771, -4995, -2296, -1519, -1502, -3411, -4819, -2533, -989, -1955, -4571, -3057, -3199, -1354, -1337, -6963, -2599, -4289, -2705, -1162, -9032, -3603, -5197, -5798, -2242, -8257, -6241, -4827, -14563, -5396, -9561, -8319, -4668, -6812, -10119, -13471, -6541, -5009, -7422, -5365, -9996, -4516, -3651, -8204, -3802, -6835, -2656, -2308, -3295, -3198, -5994, -1602, -2187, -1432, -3289, -6904, -1313, -3172, -1048, -4012, -7904, -1301, -4601, -1706, -5041, -7724, -1318, -5221, 9893, 6950, 9734, 7998, -3265, 9282, 6868, 9246, 7306, -879, 7376, 6226, 7886, 5027, 487, 4021, 4447, 6120, 1103, 1111, 198, 1432, 4432, 1914, 1731, -41, 270, 2231, 2670, 2032, 765, 1266, -1073, 2285, 1999, 57, 2064, -1174, 1420, 1713, -4, 2528, 18, 208, 1011, 2531, 2550, -774, -987, 247, 4302, 2273, -1992, -512, 1069, 5292, 2765, 601, 259, 2656, 5511, 3997, 1922, 615, 3785, 4756, 4676, 1487, 1453, 4497, 2866, 4353, -1937, 1953, 5063, 1640, 2681, -406, 1008, 5555, 2238, -1792, 3028, -2156, 5709, 1660, -707, 4037, -1697, 5139, 1333, 1563, 3710, 144, 3461, 2740, 1301, 2213, 216, 279, 3573, -1012, -915, -575, -2572, 4101, -6155, -5955, -974, 776, 4613, -6417, -2489, -160, 3507, 4596, -3033, -2042, 376, 4807, 3740, -543, -3313, -291, 4973, 2331, 90, -4669, -1893, 4219, 1493, -1212, -3760, -962, 2868, 1060, -4321, -2394, 350, 1828, 136, -1545, -2829, 486, 1568, -150, 91, -6332, -233, 1223, 791, 955, -972, -1221, 404, 1432, 1927, 1262, -538, -576, 1452, 2499, 1585, 1448, -604, 990, 2197, 668, 2686, -106, 401, 527, -548, 2888, -561, 375, -5179, -647, 2015, -2836, 934, -1038, -715, -143, -6899, 1233, 1224, -2034, -4156, -4439, 707, 970, -5586, -6884, -3377, -790, -1534, -10400, -6638, -2846, -2670, -2224, -4720, -4488, -2764, -3121, -458, -2227, -2505, -3033, -2467, -895, -1393, -2155, -2927, -2708, -2651, -2073, -2826, -2188, -5623, -2440, -4684, -3015, -1380, -7691, -1396, -8090, -3008, -1330, -2732, -1107, -4133, -4632, -2552, -1529, -1286, -2098, -8551, -5014, -1830, -1746, -1218, -6037, -4872, -2835, -2461, -1528, -5820, -4374, -3178, -3227, -2825, -7996, -6427, -3596, -3601, -3179, -7516, -5452, -5289, -4098, -2506, -5674, -2494, -6585, -5832, -2239, -5129, -1965, -6739, -7895, -2245, -6075, -3593, -12704, -6431, -2473, -5989, -8011, -5722, -6393, -2616, -3421, -7615, -2983, -6584, -2418, -2383, -7676, -2490, -4175, -2544, -2873, -5523, -3387, -2302, -3566, -4987, -4964, -5383, -1518, -5393, -9860, -6669, -8023, -1758, -6861, -8351, -5303, -8833, -3061, -5485, -5551, -3952, -6464, -5607, -3324, -4449, -4393, -4230, -9981, -2401, -4229, -6714, -2955, -12310, -2517, -4169, -5225, -2739, -8967, -3045, -3946, -2176, -3315, -6666, -3395, -4325, -1027, -3142, -4725, -3617, -6432, -1090, -1997, -3373, -3991, -8417, -1858, -1347, -2983, -4736, -5653, -2642, -1435, -3830, -5918, -4329, -3166, -2324, -6439, -7517, -2801, -3681, -4403, -7189, -8238, -1590, -3374, -9389, -3213, -5115, -866, -2799, -9122, -880, -2473, -394, -3240, -5616, 298, -980, -554, -4377, -4575, 393, -443, -1834, -4171, -5295, -725, -757, -4530, -2532, -10057, -2845, -1725, -8647, -698, 3683, 4463, 1825, -124, 2917, 3531, 4227, 4240, 35, 2671, 2782, 3483, 5662, 524, 2710, 504, 2319, 5436, 1115, 3175, -3508, 963, 3424, 1254, 3130, 543, -871, -2756, 521, 2540, 1362, -2417, 1540, 422, 1314, 82, -1317, 3275, 2037, -1669, -2950, 414, 3145, 2608, -6893, -6719, 2433, 1962, 1679, -5415, -244, 4197, -253, -665, -1236, 3013, 5400, -2164, -3883, 1545, 4445, 5907, -791, -4302, 2164, 4659, 5654, -2012, -1539, 953, 4030, 4641, -1671, 1948, -2540, 3135, 2907, 2284, 4142, -1780, 2362, 508, 3697, 5003, -104, 1246, -2934, 3750, 4673, -57, -356, -7216, 2959, 2988, 324, -1990, -788, 1999, -1190, 1584, -6384, 1481, 1711, -875, 2793, -3376, 1938, 1773, 816, 3392, -910, 903, 1359, -1253, 2831, -1619, 1642, -188, -731, 255, -5239, 3956, -4493, 2828, -8619, -2533, 4856, -4998, 3833, -1001, -1084, 4393, -3073, 3923, 618, -1142, 2651, -4611, 4240, 1265, -881, 210, -5301, 4501, 1122, -499, 193, -4510, 3983, 262, -1048, 1801, -4984, 2540, -291, -2398, 2929, -4414, 757, 537, -2886, 3307, -4481, 103, 1723, -996, 2971, -4340, -56, 2378, 779, 1931, -1460, -617, 2165, 1457, 356, 324, -1165, 1014, 957, -219, 749, -1223, -80, -772, 268, -53, -1566, 7, -3643, 100, -2097, -3244, -380, -5296, -443, -5329, -3409, -1484, -4828, -764, -7308, -397, -2607, -4755, -1428, -5650, 1043, -4558, -3782, -2276, -4608, 1365, -4631, -3248, -2331, -4564, 937, -3603, -4689, -1848, -5570, -114, -4942, -6652, -1041, -8989, -1444, -4558, -4670, -768, -8841, -1623, -2698, -3964, -1574, -4905, -1545, -2709, -3772, -1889, -3496, -2481, -4800, -3080, -487, -3199, -2491, -6607, -2057, -99, -3860, -956, -4339, -1413, -1421, -5906, -119, -5179, -1661, -4126, -6756, -18, -9412, -2886, -3466, -4567, -490, -4385, -3190, -3539, -4647, -1720, -3269, -2601, -6575, -8530, -4143, -4104, -3705, -7531, -6789, -4666, -5399, -6984, -4920, -3645, -2381, -3745, -4689, -3534, -2175, -1047, -1526, -3752, -2596, -1387, -478, -439, -5222, -2893, -1772, -690, -638, -9504, -5060, -3742, -1752, -2606, -5450, -5338, -4699, -3223, -8253, -2526, -2665, -3154, -3203, -3882, -1171, -1418, -2852, -1799, -2719, -769, -956, -3830, -592, -3001, -893, -876, -6593, -122, -2411, -1366, -712, -6676, -453, -1599, -2241, -174, -5179, -1158, -1393, -3593, 190, -8457, -1606, -1738, -5732, -191, -5409, -1791, -2832, -8734, -1571, -1648, -1687, -4201, -8852, -4170, -527, -1602, -4051, -5823, -9139, -730, -1987, -3716, -3907, -11209, -1602, -2843, -3955, -3356, -8787, -2174, -3993, -4651, -3786, -10514, -2840, -4097, -4885, -5179, -7967, -4623, -2429, -3972, -9638, -4419, -2540, -1185, -3861, -8437, -2446, -244, -882, -5374, 2071, 5274, 358, 3097, 2901, 3087, 5290, 179, 2440, 4240, 4286, 5227, 2071, 2279, 5543, 4640, 4868, 3722, 3871, 5615, 4256, 4036, 3915, 4598, 4038, 3599, 2603, 2792, 4107, -820, 2694, 333, 669, 2386, 1352, 545, -2228, -1132, -297, 2616, -4617, 66, -478, 928, 1899, -3609, 2059, 1131, 3144, 3561, -2802, 2953, 1802, 4341, 5646, 176, 3275, 1193, 4703, 6660, 1689, 3389, -406, 4168, 6646, 1494, 3245, -202, 2362, 5312, 546, 2550, 672, -1315, 1314, 539, 1039, 99, -305, -1380, 537, -1736, -2001, 1107, 2170, -629, -4142, -3126, 824, 2788, -3120, -323, -1983, -1179, 3342, -5279, 1431, -1203, -15504, 3500, -8644, 1589, -289, -1264, 2896, -1443, 1085, 870, 683, 1977, 1646, 1753, 1766, 762, 1584, 2523, 2441, 2014, -410, 1828, 1733, 2143, 1665, -2458, 1779, -580, 1122, 1333, -2289, 443, -2330, -694, 1141, -851, -5301, -1406, -4307, 201, -240, -704, -1220, -1759, -349, -231, 1902, -3224, -1091, 1012, -494, 2122, -3760, -3942, 1430, -685, 606, -911, -2434, 572, -741, -1792, -827, 187, -959, -812, -1344, -3080, 1182, -2765, -1219, -396, -2854, 1454, -6097, -2278, 349, -346, 984, -5858, -1832, 586, 208, 185, -3048, -159, 35, -1482, 5, -482, 323, -1365, -9304, -245, 965, -492, -2805, -809, -578, 1008, -2378, -2286, 462, 348, 162, -3310, -1562, -1082, 1163, 61, -1521, -886, -10256, 1089, 201, -321, -304, -1749, 651, -802, -186, -472, -786, 487, -3197, -700, -1998, -2250, 30, -5741, -1330, -5332, -5894, -1304, -5224, -2301, -5321, -7508, -3500, -4848, -4435, -5400, -4138, -5353, -5387, -4648, -5943, -2636, -4929, -5749, -2260, -5960, -2548, -4522, -5910, -1570, -11322, -3391, -4287, -4582, -2262, -5475, -4224, -5056, -2469, -3304, -3208, -5285, -15497, -1671, -2481, -3233, -7761, -3302, -2240, -1290, -4304, -7305, -748, -3313, -959, -4685, -8587, -138, -2873, -1691, -5040, -9775, -750, -2175, -3745, -8771, -4605, -2461, -1900, -7811, -6671, -3613, -5205, -1659, -16669, -3382, -4566, -5873, -1742, -7431, -2962, -7979, -4609, -2757, -3770, -4067, -8369, -3708, -5023, -1628, -5470, -4799, -3005, -7284, -787, -4821, -3364, -3245, -8660, -1205, -3282, -2386, -5394, -21635, -2749, -3176, -1431, -9820, -6374, -4620, -5153, -994, -7799, -3404, -5608, -4621, -1549, -4089, -1986, -5269, -2318, -3083, -733, -1068, -3624, -1497, -3572, 905, -463, -2247, -1346, -2685, 1208, -663, -1894, -1327, -2314, 308, -1739, -2844, -1368, -2315, -1855, -2198, -5478, -1863, -2681, -4685, -2098, -9135, -3094, -4042, -6115, -3475, -7313, -4275, -7120, -11604, -4665, -5881, -3958, -4008, -5829, -2099, -5042, -3526, -1499, -3020, -955, -4614, -3889, -628, -2335, -978, -5090, -5198, -6693, -2397, -2436, -6940, 413, -3124, -1150, -1766, -4277, 569, -1716, -1089, -821, -3726, -133, -1335, -2118, -574, -4771, -1118, -1788, -4533, -1089, -6483, -1203, -3295, -7803, -1687, -7666, -782, -7035, -5120, -1532, -8367, -640, -8173, -3809, -1042, -5039, -758, -4992, -2834, -766, -2795, -1257, -4148, -1562, -1042, -1781, -2915, -3268, -924, -2126, -1678, -6465, -2094, -1358, -3889, -2569, -2978, -1369, -2705, -4702, -4670, -1376, -1192, -2399, -4298, -3541, -1823, -1405, -688, -4292, -1129, -4441, -1744, 165, -4909, -83, -8700, -2234, 64, -6111, -44, -5034, -3463, -1129, -8544, -933, -3916, -5216, -4297, -9496, -3055, -4060, -5058, -6889, -5530, -6880, -5043, -5511, -3563, -3947, -5509, -4620, -9826, -3077, -3703, -4110, -2473, -9109, -3073, -4321, -4340, -1237, -6172, -2252, -4721, -5560, -1206, -4919, -1714, -3427, -5315, -2540, -3081, -2010, -2043, -3547, -5688, -1806, -3034, -1653, -2336, -6185, -1448, -4324, -2606, -1612, -4627, -1750, -5049, -5608, -1617, -4301, -2017, -4837, -10434, -3121, -3926, -1761, -4320, -6408, -8827, -3809, -1742, -3933, -5517, -7753, -4951, -2753, -3445, -5975, -8179, -10358, -5800, -2992, -6739, -8190, -6338, -11959, -2968, -4780, -3609, -3461, -5121, -3250, -2908, -2881, -3423, -3601, -3812, -2465, -4197, -6068, -3341, -5352, -3239, -7876, -8982, -3038, -5348, -4535, -9111, -5954, -1789, -3284, -4922, -5043, -5908, -801, -2898, -4112, -2754, -6412, -731, -4210, -3444, -1365, -6418, -1557, -7601, -3078, -1010, -6761, -2828, -12376, -2903, -2004, -8207, -3801, -7601, -3812, -5223, -8936, -4466, -7246, -7516, -7407, -6897, -5080, -11590, -5389, -3402, -4261, -6361, -6756, -2689, -1936, -2229, -7673, -4149, -1919, -1751, -1495, -5312, -3567, -2082, -2883, -2053, -4058, -3840, -2715, -6105, -3758, -4086, -4213, -3681, -9655, -7278, -5025, -4966, -5049, -5135, -8523, -6913, -6019, -5251, -3028, -3299, -7882, -4942, -4176, -1766, -1731, -6423, -4198, -3960, -1243, -1617, -6221, -5419, -4669, -1382, -2249, -7777, -9966, -5818, -2018, -2800, -11253, -7221, -7299, -2961, -2481, -11771, -6067, -8673, -4298, -1633, -8038, -7159, -8733, -5798, -1147, -5952, -6394, -8592, -4579, -1465, -5627, -4546, -7981, -3215, -2877, -6026, -3884, -7634, -3317, -6058, -4868, -4166, -8562, -4982, -14775, -3836, -5090, -10727, -6290, -6773, -4127, -5961, -10665, -4646, -4232, -6169, -5847, -7353, -4010, -3031, -13470, -5311, -4702, -4576, -2828, -9168, -5029, -3332, -5408, -3340, -7328, -5208, -3058, -5153, -4181, -7644, -6256, -3696, -5304, -5532, -8713, -9250, -4765, -7600, -6878, -7966, -7504, -4952, -13402, -4994, -6511, -4579, -4783, -7267, -3893, -6276, -3691, -5962, -6824, -4245, -7964, -4287, -11713, -9145, -5564, -10924, -6544, -7722, -13292, -6756, -7277, -10999, -4536, -12303, -6903, -6011, -8762, -3384, -8783, -7266, -5094, -1758, 539, -1365, -4791, -4721, -2575, 280, -2241, -2165, -6321, -5738, -745, -3091, -1159, -8461, -5071, -2328, -3748, -1559, -5463, -2303, -4316, -4237, -2643, -4484, -1084, -7260, -4257, -2386, -5808, -502, -9351, -3275, -2278, -5282, -685, -5953, -2327, -4449, -2162, -2211, -4664, -2235, -11079, -874, -6058, -3890, -3257, -3600, -1054, -5523, -3336, -5205, -2252, -3012, -4600, -3611, -4839, -2429, -12304, -6370, -4213, -3251, -3541, -3974, -8535, -3213, -2980, -5442, -2141, -8424, -1759, -4405, -5868, -2593, -9943, -955, -5322, -4002, -5310, -10303, -894, -3296, -3313, -9276, -8628, -1514, -3113, -4392, -6355, -6785, -2784, -5316, -8109, -6109, -6047, -4949, -6070, -7465, -6936, -5086, -6889, -2832, -7369, -6030, -3774, -4208, -1253, -8404, -3820, -3682, -2389, -679, -3868, -2504, -5052, -2034, -1099, -1895, -2037, -4638, -3185, -3038, -868, -2173, -2866, -6430, -9804, -424, -2733, -2356, -7989, -5663, -811, -3507, -2854, -5952, -4975, -1880, -4178, -3808, -6414, -5351, -2707, -4521, -4528, -8718, -2235, -4135, -4597, -4677, -8254, -804, -6268, -4446, -3836, -9373, -640, -2699, -4008, -2669, -9369, -1061, -1315, -3832, -2167, -3958, -1699, -1593, -4476, -2625, -2028, -2486, -3115, -4525, -4117, -1429, -3197, -5245, -3167, -6147, -1533, -3729, -5266, -2557, -5763, -2090, -4646, -4320, -2833, -3939, -3538, -6731, -4405, -3527, -2938, -8177, -7466, -5799, -4107, -3175, -6661, -4212, -7763, -3838, -5107, -3701, -2595, -6778, -3437, -9132, -3471, -2411, -6444, -3854, -5967, -4620, -3650, -7721, -4753, -4224, -4841, -6932, -4576, -5572, -3361, -3391, -7439, -2177, -7651, -2442, -2727, -4821, -1431, -15264, -1812, -3167, -3935, -2009, -9428, -2125, -4544, -3858, -4016, -8822, -3363, -6455, -4417, -8595, -10716, -3291, -9719, -6556, -7831, -9129, -2689, -14961, -11897, -5334, -6140, -4082, -10302, -5638, -4772, -4843, -9858, -6458, -4837, -4478, -4410, -4187, -4183, -5874, -3020, -4188, -2493, -3906, -4757, -1700, -4013, -2692, -5375, -4042, -1573, -4192, -4489, -7997, -4416, -3228, -4402, -8039, -8710, -3564, -6046, -3384, -5108, -7259, -3197, -3036, -2377, -2994, -7188, -4405, -1827, -2444, -2195, -9858, -5077, -1842, -3757, -2257, -9107, -4206, -2181, -6015, -3182, -8494, -4305, -2950, -6589, -4508, -13431, -5429, -4654, -6104, -3609, -6191, -7352, -4738, -6426, -2113, -4235, -6788, -3346, -7461, -1490, -4282, -4553, -3139, -9259, -1646, -5598, -2930, -3924, -11458, -2406, -7733, -2064, -5018, -10187, -3546, -10919, -2177, -5494, -8587, -4725, -11695, -3399, -5475, -7729, -5695, -6528, -5951, -5992, -7138, -6525, -4372, -11951, -6613, -5776, -6964, -4011, -9602, -4965, -4208, -6534, -5737, -7235, -3685, -3411, -5973, -14497, -7473, -3750, -3294, -5934, -5699, -9083, -5165, -3318, -6469, -4112, -8797, -8091, -3206, -7289, -4758, -7385, -13164, -983, -2618, -1430, -6237, -6901, -2444, -3226, -1698, -4829, -7651, -3930, -3933, -2127, -4045, -9454, -3907, -4364, -3061, -5928, -9154, -4016, -4725, -3306, -10267, -6507, -4147, -6880, -2790, -3706, -5966, -4041, -8154, -2811, -1877, -6466, -3886, -4459, -2223, -1488, -7046, -3697, -2987, -1109, -2058, -7563, -3708, -2432, -971, -3695, -8193, -2804, -2787, -2060, -8280, -9323, -1595, -4177, -3683, -6437, -12501, -1280, -6059, -3919, -2800, -11453, -1949, -6527, -3085, -1425, -9891, -3501, -3659, -2804, -1343, -11028, -5985, -1959, -4378, -2792, -6076, -9615, -1845, -9014, -5251, -3560, -11352, -3228, -4238, -3017, -2309, -8728, -5041, -3193, -1803, -1228, -6368, -2893, -4937, -2003, -375, -5447, -749, -9557, -3031, -201, -5586, 505, -3438, -4368, -737, -5887, 1022, -1503, -5542, -1723, -6895, 933, -961, -7023, -2900, -11516, 625, -1297, -12475, -4248, -9750, 605, -2522, -7218, -5872, -6866, 534, -4454, -4463, -8378, -6013, -297, -4135, -4382, -14230, -4859, -2286, -2914, -7407, -9845, -3623, -4097, -2763, -5304, -9005, -3696, -2495, -3462, -2115, -8544, -5963, -1348, -3882, -987, -4457, -7470, -1439, -3310, -899, -2184, -5336, -2739, -3180, -1397, -1390, -5633, -3845, -4027, -2116, -1766, -6484, -3335, -5731, -2782, -2970, -5438, -3612, -7501, -3358, -3969, -4071, -5267, -6485, -3966, -4561, -2938, -8219, -4049, -4750, -6253, -2217, -9780, -2429, -5805, -7919, -1982, -7617, -1792, -7054, -5938, -2146, -6167, -1846, -8343, -5433, -2438, -5843, -1846, -9650, -6905, -2410, -7158, -1193, -9534, -10417, -2000, -12900, -399, -6743, -7047, -1744, -7605, -143, -4190, -4915, -2287, -4745, -836, -2500, -4223, -4594, -3315, -2877, -1744, -4608, -11793, -2157, -6722, -1960, -6021, -5013, -913, -6898, -3122, -7735, -3919, -49, -4869, -4548, -7977, -4797, 55, -4032, -4615, -6303, -6967, -623, -4596, -4538, -4574, -7977, -1834, -6415, -4690, -4360, -7051, -2900, -7709, -3442, -6105, -5977, -3239, -7452, -2039, -4954, -4467, -3367, -4470, -1369, -2568, -3856, -3578, -2824, -1408, -2082, -5095, -3258, -2876, -2106, -3241, -9538, -3047, -4457, -3370, -6342, -6241, -4427, -7243, -4289, -10023, -5125, -7772, -8947, -3484, -8418, -7120, -5262, -7066, -2664, -8736, -10187, -4987, -4961, -2399, -13039, -5705, -7055, -3659, -2047, -8617, -4646, -5492, -3211, -1724, -6067, -4670, -3438, -3741, -2229, -5475, -3997, -2771, -5357, -4129, -5380, -3021, -3085, -7386, -7047, -5142, -2896, -3938, -7699, -6699, -4483, -3973, -5248, -8577, -6873, -3673, -6820, -8722, -9155, -7596, -3153, -15415, -11084, -7236, -7217, -2845, -10475, -6924, -7289, -7188, -2861, -10334, -6502, -11166, -7858, -3324, -9201, -5974, -8784, -9039, -3723, -6916, -4568, -5916, -8996, -3705, -6047, -3705, -5480, -8428, -3879, -6029, -3437, -5810, -8973, -4596, -5666, -3464, -5546, -8858, -5801, -5238, 15165, 2220, 10293, 9886, 8359, 14767, 5638, 9599, 9189, 10163, 13535, 6920, 7288, 6853, 10144, 11358, 6285, 2129, 1303, 9299, 8385, 4271, 475, 1013, 8251, 7587, 1764, 688, 1984, 6512, 8553, 128, -249, -611, 3759, 8828, -867, 256, -6937, 5346, 8283, -328, -509, -264, 6056, 6842, 1506, 1386, 1412, 4279, 4689, 3435, 3697, 2469, -3939, 3292, 4896, 4869, 3037, 1643, 3547, 5663, 5200, 3137, 1847, 4912, 5548, 4834, 2720, -1288, 5655, 4299, 3914, 1229, -7067, 4971, 1763, 2803, -2426, -3092, 2336, 631, 1807, -2942, -2819, -836, 1185, 836, -1536, -5055, 1715, 493, 50, -1759, -1808, 2202, -1063, -527, -2432, -664, 1002, -2089, -1745, -6010, -296, -2271, -1179, -4133, -3901, 1201, -5958, -318, -3961, -898, 2363, -3331, -739, -3644, -745, 2815, -2835, -2475, -6246, -1696, 2777, -3418, -2199, -6704, -874, 2129, -6288, -653, -4689, -13, 121, -6716, -278, -5560, -415, -8130, -1474, -1032, -5326, -1839, -1879, 429, -3153, -3739, -3077, -201, 1026, -7811, -3606, -2202, -740, 728, -17050, -3349, -857, -1628, -260, -9764, -3061, -223, -1872, -1284, -5219, -3867, -554, -3348, -1211, -3364, -4911, -2136, -5185, -949, -3196, -6153, -3803, -4069, -1546, -4273, -11220, -2293, -5814, -3211, -5874, -9225, -1543, -7654, -4453, -6492, -8702, -2022, -3445, -3538, -5984, -11835, -3137, -2778, -3033, -5314, -7909, -4071, -3630, -3184, -5341, -5343, -5856, -4960, -3531, -6565, -3590, -10830, -5853, -3938, -7846, -2905, -4797, -4374, -4549, -6669, -3654, -3344, -2147, -5170, -6659, -4874, -3849, -841, -5242, -9633, -3131, -5622, -363, -4773, -11108, -1937, -7477, -427, -4271, -6912, -1979, -7271, -877, -4149, -5375, -2753, -6536, -2024, -4627, -4488, -3442, -6879, -4657, -5827, -4222, -3640, -8266, -9185, -7401, -4772, -4017, -8267, -7768, -7331, -6096, -5318, -6145, -7204, -6757, -7470, -8929, -4211, -6455, -7478, -7380, -8746, -2915, -6007, -11402, -6159, -5388, -2385, -5302, -10046, -4972, -4620, -2669, -4366, -5827, -4223, -5372, -3708, -4377, -4049, -3955, -7320, -5222, -5567, -3183, -4157, -10406, -6307, -7145, -2926, -4542, -15272, -5720, -7004, -3214, -4562, -9529, -5296, -6641, -4069, -4579, -8847, -6434, -8733, -5309, -5471, -11759, -9022, -9436, -6037, -8163, -10258, -7918, -3794, -5935, -12911, -7705, -6644, -1835, -5753, -8442, -7612, -6550, -1397, -5687, -7383, -8925, -7595, -2077, -5466, -7698, -9273, -9340, -3655, -5085, -7302, -8444, -9286, -6043, -5029, -5724, -8654, -9691, -11093, -5857, -4828, -10089, -13643, -10036, -7491, -4924, -11296, -12769, -6573, -5603, -5821, -10109, -9007, -5561, -4060, -7081, -9241, -7857, -5062, -4361, -8146, -8987, -7778, -4128, -6806, -9337, -8181, -8017, -3304, -13477, -9510, -6888, -7578, -3356, -8468, -7269, -6063, -7039, 8741, 3952, 6975, 8689, 7461, 7965, 4037, 6240, 8235, 7088, 5365, 3753, 3586, 6965, 5982, -709, 2291, -8624, 5319, 4748, -4470, -1068, 620, 4040, 4512, -2797, -1090, 558, 3121, 4183, -367, 1438, -3119, 1993, 3133, -592, 3228, -56, 84, 2502, -3397, 4205, 2057, -3665, 3187, -7182, 4323, 3214, -7878, 4075, 583, 4282, 4808, -2543, 4389, 3794, 4987, 6275, 193, 3820, 5394, 5719, 6925, 1546, 2253, 5734, 5810, 6541, 1361, -167, 4882, 5234, 4868, 613, -2154, 2816, 4206, 1450, 2241, -1280, 161, 2891, 1105, 3465, -94, -137, 982, 2355, 3369, -380, 154, -1515, 1786, 2095, -2752, -326, -166, -31, -185, -7063, -1308, 1459, -1995, -2564, -3374, -2490, 1997, -3375, -4284, -2141, -2608, 1926, -5535, -3928, -2394, -1395, 1648, -6430, -2423, -3605, -709, 1407, -5782, -3505, -4673, -1148, 1209, -7441, -5364, -4258, -3250, 862, -14465, -1560, -2896, -10573, 87, -6434, -360, -1859, -5823, -1257, -4715, -237, -1667, -3697, -2150, -4467, -520, -2329, -2695, -1664, -4289, -1902, -3308, -2223, -1493, -3401, -7242, -3745, -2694, -1736, -3402, -4590, -3741, -4302, -1632, -5902, -1390, -3761, -6770, -1434, -5788, -121, -3823, -8089, -1653, -3119, 547, -3750, -5731, -2427, -3391, 832, -4036, -3416, -3804, -6366, 572, -5602, -2191, -5673, -6006, -681, -10616, -1883, -7549, -4492, -4344, -8372, -2417, -7063, -5091, -6680, -6508, -3977, -5308, -5015, -2084, -6696, -7297, -4537, -3235, -970, -5048, -11384, -4676, -2338, -1043, -3625, -6729, -5139, -2746, -1931, -4086, -4856, -6156, -4940, -3320, -7477, -4850, -11532, -9552, -4050, -10210, -7748, -6825, -6017, -2984, -5601, -10312, -3707, -5121, -1871, -4374, -5851, -3115, -5930, -1696, -4228, -5661, -4027, -6161, -2534, -4901, -7737, -4717, -5627, -4341, -5874, -10902, -3761, -6915, -7455, -6447, -7895, -3654, -18720, -13483, -6889, -6565, -5180, -7222, -9348, -7138, -6865, -9112, -5547, -8639, -6701, -8530, -8968, -6065, -11853, -6201, -8321, -7126, -7279, -10446, -6732, -6220, -6626, -6673, -6152, -9638, -4512, -6631, -6094, -4599, -9879, -3458, -7760, -6785, -4192, -6707, -3481, -12012, -8925, -4470, -6211, -4762, -10526, -11451, -5108, -7719, -7049, -7306, -11076, -5739, -13789, -8367, -6461, -9835, -5993, -8478, -7185, -7141, -8315, -5675, -5652, -6084, -9976, -7564, -5021, -4584, -6254, -17176, -7346, -4589, -4718, -7559, -9942, -7128, -4647, -6373, -9423, -8840, -7063, -4976, -12287, -15035, -9816, -7145, -5328, -7967, -9515, -11203, -6917, -5561, -4906, -6676, -8212, -6556, -4962, -3648, -6157, -6806, -6157, -4169, -3571, -6516, -7052, -5704, -4041, -4950, -6261, -8524, -5911, -4554, -8975, -5784, -10226, -7143, -5486, -8860, -5819, -10541, -7835, -6689, -7483, -6120, -10127, -7749, -7490, -9826, -6313, -10173, -9714, -7104, -11192, 4458, 2870, 7118, 7575, -11243, 3348, 1685, 6636, 7254, -4944, -609, -1185, 5416, 6456, -1588, -1007, 1479, 4418, 5674, 1846, -1635, 2980, 4191, 5048, 4140, -5635, 3251, 3899, 4070, 5286, -975, 2726, 3097, 2906, 5483, -3298, 1238, 1617, 2440, 4715, -1532, -1686, -609, 1671, 2256, 3037, -3160, -3006, -1311, -3579, 5003, 1111, -937, -2107, 2997, 5863, 4373, 1221, 1334, 4453, 5773, 5938, 1434, 2093, 3956, 4642, 5925, -301, 2054, 2136, 2482, 4000, 794, 3022, 2635, 1047, -3405, 2476, 3858, 4138, 880, 467, 2019, 3438, 4503, -16, 1300, -669, 1587, 4082, -466, -1437, -4634, -1483, 3305, -533, -8420, -6667, -6500, 2350, -889, -2601, -5765, -5648, 864, -804, -2077, -1985, -2407, -1520, -198, -1745, -1615, -1994, -1470, 346, -1230, -3470, -2001, -12, 236, -1557, -10862, -1871, 353, -839, -2868, -6024, -2304, -86, -3463, -4276, -3767, -3760, -1369, -9859, -4134, -3319, -5611, -3591, -4525, -3073, -3684, -3931, -4325, -3927, -2727, -4850, -3074, -2305, -7892, -3983, -7513, -5005, -645, -4649, -6189, -13061, -6612, -176, -1450, -2832, -12060, -2315, -1227, -694, -1063, -7551, -1224, -4165, -1451, -781, -4934, -1604, -4534, -3464, -1419, -4606, -2728, -3025, -4085, -2318, -5605, -3903, -2358, -3239, -3209, -5515, -5165, -1846, -3741, -4852, -5936, -7169, -2057, -5461, -7091, -9465, -8962, -3333, -6245, -6562, -7129, -9671, -4477, -6273, -6751, -5552, -11221, -3905, -7579, -9701, -7571, -6112, -4143, -9314, -11239, -9671, -3291, -6937, -9167, -8239, -4276, -1935, -9456, -8446, -5746, -2875, -1615, -5504, -7196, -4037, -2975, -2231, -6170, -5945, -3717, -3918, -3490, -11158, -4926, -4759, -4549, -3561, -4858, -4167, -5523, -4314, -2564, -3533, -3755, -4182, -4855, -2477, -4788, -3605, -3583, -8525, -3652, -11478, -3554, -4205, -6096, -5556, -7369, -3680, -5724, -2706, -6369, -5545, -4411, -7552, -1721, -6916, -6312, -6501, -9040, -2130, -7502, -9788, -11790, -7529, -3799, -6730, -11512, -10105, -6241, -7233, -5022, -7393, -9046, -6171, -8237, -3758, -6358, -8040, -7227, -5758, -3342, -6662, -6714, -10113, -5566, -3729, -8050, -6617, -7486, -7133, -4795, -10028, -7793, -5152, -9578, -6239, -9313, -9877, -4713, -9609, -7260, -7252, -11532, -5531, -9312, -8461, -5703, -11067, -7127, -9298, -11221, -5150, -9746, -8573, -9261, -7140, -6157, -8772, -8980, -9628, -4919, -11494, -8258, -8132, -10059, -4307, -7427, -8265, -6819, -8427, -4611, -4321, -8843, -6113, -6823, -4983, -3504, -9175, -6057, -6212, -4853, -3996, -8911, -5606, -6328, -5217, -5402, -9312, -4622, -7036, -6732, -7241, -10592, -4093, -8669, -7196, -8304, -10786, -4047, -11327, -6214, -7631, -8903, -4054, -8959, -6600, -8118, -8014, -3898, -6536, -8753, -12148, -8668, -3674, -5627, -9694, -9457, -10135, -3660, -6112, -7095, -7659, -4829, -7102, -6498, -5768, -7102, -6936, -6734, -7755, -5765, -7561, -4010, -6378, -10869, -5938, -7981, -2349, -6027, -9615, -5920, -8148, -2201, -6023, -9381, -5366, -7391, -3445, -6148, -9821, -4920, -5938, -6092, -5824, -8314, -5159, -5012, -5167, -5281, -8243, -6280, -5023, -3392, -4739, -11745, -8310, -6182, -3030, -4111, -11193, -10530, -9371, -3623, -3622, -7625, -10460, -15111, -4370, -3745, -6713, -8825, -9433, -4118, -4924, -6975, -8062, -9147, -3587, -7154, -9096, -8549, -11286, -3679, -7569, -12180, -8767, -15624, -4455, -6400, -7286, -7822, -10345, -5084, -4614, -4905, -9334, -7582, -4162, -2134, -2845, -6630, -3609, -2167, -17, -740, -1735, -452, -502, 1187, 862, 480, 1284, 214, 1356, 1522, 1168, 1752, -121, 484, 1039, 556, 972, -1504, -1278, -845, -1431, -1274, -3916, -3357, -4865, -5202, -5812, -7535, -5205, -8171, -12697, -8842, -10191, -6426, -6474, -10853, -7187, -8928, -6003, -6521, -7274, -6582, -9937, -5139, -7692, -6007, -6221, -12284, -5021, -11105, -5926, -5930, -9419, -6087, -10641, -6514, -5528, -7850, -8223, -8236, -7463, -5493, -7054, -9559, -7551, -8722, -6216, -6346, -8339, -8193, -10419, -7790, -6011, -6303, -10805, -11837, -9272, -6640, -4770, -9711, -11618, -9646, -9355, -4113, -7521, -11748, -11232, -9333, -4237, -7380, -13581, -16033, -5474, -4666, -8751, -16529, -14081, -4155, -4990, -11089, -10811, -10738, -4401, -5478, -11609, -8690, -8725, -5911, -6111, -9299, -8324, -8702, -6955, -6697, -7727, -9391, -11741, -6187, -8326, -7471, -11304, -13708, -5902, -16418, -8593, -8898, -9336, -6526, -8725, -11389, -6642, -8172, -7757, -6779, -15746, -5817, -7703, -7228, -7294, -15452, -6349, -7830, -5863, -10127, -14359, -8933, -9199, -5960, -13144, -13676, -12484, -12232, -8559, -10365, -13134, -8452, -10297, -12472, -8164, -12280, -8102, -9018, -8343, -7143, -11929, -10335, -9879, -9266, -7373, -13421, -14360, -10807, -12668, -8397, -14255, -10952, -8965, -8240, -9241, -9871, -10460, -7929, -7171, -9145, -8414, -11568, -7746, -7378, -8297, -8713, -11369, -7947, -6951, -7257, -9695, -10045, -8383, -5811, -6687, -9494, -9430, -8879, -4912, -7073, -9061, -8905, -9013, -4489, -8822, -8683, -8541, -8780, -4744, -10384, -8191, -8858, -8695, -6062, -8407, -8082, -9874, -9036, -9017, -7240, -8356, -11460, -9588, -8399, -6772, -8776, -14374, -9760, -6181, -6490, -9244, -12994, -9444, -5628, -6383, -9540, -9428, -9244, -6381, -6598, -9933, -7944, -9549, -8644, -6929, -11073, -8064, -10229, -13556, -7220, -13279, -10255, -10962, -15329, -7872, -12613, -25624, -11789, -13159, -9007, -9435, -12071, -12529, -9989, -9948, -7981, -11921, -12561, -7856, -9965, -8073, -14185, -12093, -6894, -9528, -9832, -11276, -11549, -6884, -9140, -13116, -9690, -11024, -7704, -8890, -12101, -9682, -10647, -8939, -8893, -11875, -10968, -10730, -9519, -9104, -13947, -13496, -11562, -9776, -9449, -13752, -11391, -13395, -6389, -9624, -16465, -6442, -7466, -6840, -8839, -10579, -6320, -6329, -8537, -9431, -11509, -6801, -5775, -12776, -11379, -15505, -7008, -5151, -9260, -9727, -9754, -6292, -4510, -7001, -7445, -9310, -5955, -4042, -6402, -6402, -11807, -6881, -3903, -7043, -6345, -13333, -10060, -4227, -9048, -7133, -11438, -15372, -5080, -11930, -8676, -8836, -9456, -6219, -8870, -8569, -6909, -7821, -6827, -6598, -6804, -6603, -7425, -6689, -6119, -6132, -7994, -8306, -6495, -7395, -6363, -12395, -10567, -6375, -10852, -6267, -12735, -12963, -6237, -13169, -5422, -8806, -12784, -6011, -8836, -5921, -9344, -7571, -5404, -4695, -11035, -7611, -3635, -3964, -1767, -2650, -2313, -810, -1627, -153, 156, 10, 820, 120, 134, 1037, 737, 1271, 736, -1071, 492, 190, 517, 160, -4510, -1503, -1532, -1610, -1669, -11587, -5463, -4267, -5254, -4741, -8280, -15162, -7212, -6867, -7758, -8927, -12272, -8991, -6882, -7694, -6603, -11110, -9255, -7925, -6672, -4942, -10171, -7343, -9089, -6634, -4274, -9386, -6059, -9577, -6845, -4610, -9093, -6397, -9470, -6499, -6164, -9931, -8640, -9571, -6537, -7640, -13149, -9624, -10646, -7687, -7070, -15768, -7213, -14142, -10798, -7979, -13044, -6278, -11236, -14927, -12957, -15540, -6364, -7963, -10746, -7243, -13890, -7234, -6878, -9893, -5107, -9341, -8881, -7192, -11066, -4954, -7535, -11376, -8430, -12321, -6650, -6869, -15032, -9283, -9100, -14197, -6967, -15599, -7797, -8152, -8514, -7974, -11753, -5950, -9176, -6387, -10935, -9870, -5311, -10894, -6324, -16341, -9195, -6390, -11663, -7128, -10019, -9261, -11025, -11791, -7568, -9002, -9379, -8652, -9165, -7394, -9352, -8714, -6234, -8158, -7802, -9070, -7488, -5989, -9042, -9344, -8042, -6586, -6864, -12293, -10880, -7590, -6404, -8422, -10823, -10168, -7802, -6856, -9588, -7647, -9961, -8530, -7155, -9057, -6166, -11078, -9897, -6731, -8667, -5798, -14226, -12170, -6542, -9721, -6427, -16335, -13202, -7267, -13399, -7961, -11308, -11535, -9159, -17204, -9854, -9240, -10689, -11900, -12876, -11019, -8235, -11085, -12564, -9966, -10665, -7782, -13555, -11505, -8935, -8942, -7669, -14441, -11151, -10175, -7768, -7950, -10255, -12934, -12839, -7580, -8995, -8485, -17870, -11892, -7973, -12074, -7532, -11100, -16350, -7935, -14477, -6916, -9097, -11120, -7431, -9535, -6860, -8405, -8211, -7274, -8373, -7644, -8478, -8013, -7825, -8867, -8892, -9286, -9248, -9057, -10672, -9452, -11033, -9892, -10176, -13720, -10212, -14444, -9741, -10905, -15857, -11506, -18255, -10059, -11254, -11994, -10817, -13174, -10355, -11549, -10362, -10549, -10748, -10769, -14835, -10895, -11818, -9494, -11104, -12061, -14763, -13702, -9219, -11137, -9622, -10427, -15396, -9879, -11703, -9868, -7912, -13792, -11483, -13580, -11679, -7388, -10885, -13456, -23639, -12058, -8362, -9625, -13018, -12653, -11652, -11247, -9247, -11012, -10383, -11355, -17928, -9261, -9521, -10202, -11240, -15208, -9977, -9045, -11615, -12414, -10114, -3970, -8334, -5869, -8970, -9229, -4310, -13488, -5688, -9313, -7789, -4518, -13098, -6176, -6320, -6221, -4871, -11503, -6972, -5298, -5173, -5314, -10167, -8163, -5540, -4841, -5239, -10524, -10875, -6467, -5194, -4537, -9662, -12428, -7536, -6002, -3813, -6677, -8850, -8483, -6964, -3407, -5263, -6918, -9347, -8347, -3453, -4954, -5744, -10223, -10946, -4005, -5209, -5377, -11445, -14886, -4655, -5733, -5939, -11334, -14268, -4448, -6726, -7298, -9502, -10389, -4105, -8853, -8121, -8992, -8542, -4941, -11153, -8126, -9763, -8478, -7911, -8585, -8538, -12136, -8421, -9635, -5953, -6932, -11206, -5318, -5835, -3192, -3692, -4885, -2082, -2022, -652, -966, -1735, -91, 56, 997, 624, -174, 646, 569, 1520, 996, 80, 193, -421, 798, 70, -999, -1448, -3357, -1397, -2473, -3820, -4221, -12012, -4667, -7935, -10437, -7136, -8222, -5044, -15169, -7808, -7900, -8154, -6085, -15738, -6267, -7565, -9659, -9547, -10544, -5693, -7656, -8504, -8180, -8827, -5122, -9644, -6047, -7165, -7995, -4756, -13342, -4937, -8674, -7220, -4943, -8547, -5094, -16086, -6744, -5605, -7958, -6338, -8025, -6950, -6103, -10312, -8173, -6047, -7703, -6154, -11872, -9040, -5874, -8139, -6608, -7372, -8626, -6821, -8573, -7953, -5926, -8458, -8241, -10022, -9390, -6105, -9443, -8828, -12613, -9850, -7899, -11362, -8784, -12567, -12242, -10835, -9466, -9091, -9564, -11749, -9632, -7662, -9057, -7084, -8390, -8928, -7209, -7888, -5694, -8031, -9046, -7896, -7005, -5408, -10131, -8701, -9926, -7092, -6175, -15552, -8263, -14198, -8416, -7737, -10128, -7893, -19648, -12171, -8898, -8567, -6952, -12958, -14097, -9430, -8408, -5916, -8995, -10367, -11185, -9023, -5393, -7523, -10380, -13151, -10173, -5283, -8047, -13643, -9635, -11738, -5285, -10362, -15064, -7977, -12013, -5510, -7585, -10676, -7525, -10252, -6394, -5210, -9757, -7497, -9468, -8360, -4284, -10698, -7487, -10423, -11830, -4265, -12672, -7843, -14152, -16256, -4728, -11014, -8814, -10652, -14344, -5211, -9543, -10244, -8002, -10937, -5613, -8743, -13338, -7280, -9437, -6035, -8430, -14408, -8177, -8749, -6535, -8710, -9385, -11559, -7945, -7557, -9657, -7736, -17573, -7224, -8791, -12450, -7361, -12250, -7151, -7702, -15480, -7544, -10976, -7976, -6557, -10490, -7928, -9773, -9783, -6497, -9302, -9016, -9029, -12423, -7322, -9630, -11402, -8466, -14060, -8830, -10799, -12772, -8346, -11323, -11245, -10842, -13624, -9383, -9700, -15633, -10561, -14654, -11197, -9269, -11468, -10332, -10460, -10194, -8898, -9169, -8613, -8676, -9056, -8087, -8695, -7213, -8226, -8841, -7587, -9421, -6443, -8782, -9153, -8005, -10086, -6048, -10301, -9820, -9972, -9947, -6109, -12165, -10936, -15691, -10654, -6898, -12113, -13707, -12451, -12240, -8843, -11489, -16271, -10362, -10891, -13140, -11680, -10329, -9403, -9133, -14873, -12631, -8537, -8669, -8325, -13261, -13581, -8354, -8244, -8241, -15671, -13412, -9423, 8813, 10397, 10659, 8490, 6718, 8016, 9942, 10005, 7905, 6152, 5336, 8532, 7937, 6131, 4406, 2646, 6102, 4708, 3216, 1406, 3898, 3039, 3748, -79, -1617, 3079, 1561, 2902, -2100, -2952, 1341, 2545, 195, -3053, -11033, 2008, 3509, -1404, -1508, 91, 3027, 3571, -1222, 373, 2781, 2993, 2556, -2068, 1033, 3773, 1180, -249, -3393, 1549, 3892, -1764, -2551, -5508, 3372, 3544, -603, 2574, -5315, 4896, 2781, -1798, 4386, -3700, 5320, 1226, -148, 4572, -3826, 4542, -1227, 1932, 3323, -4813, 2329, 722, 1888, 248, -3533, -2016, 2718, -179, -2923, -978, -4124, 3098, -7186, -240, 829, -3245, 2120, -3145, 966, 1626, -3372, 108, -941, 1235, 1246, -2906, -3208, -446, 1013, -730, -2199, -3670, -1099, 775, -5065, -1910, 888, -3410, 562, -3306, -711, 1797, -3112, -131, -1919, 646, 210, -1290, -1860, -506, 648, -8568, -1965, -5820, 1012, -1470, -2090, -1702, -7525, 1603, -13126, -1030, -82, -2749, 1247, -2015, -1730, -1340, -1634, 414, -49, -693, -8504, -2743, -122, 377, 1062, -158, -7438, -409, -30, 1753, 991, -4883, -600, -115, 826, 387, -4172, -381, 605, -3979, -874, -6606, -627, 1205, -1725, -2647, -4240, -2689, 1415, 1168, -7682, -3140, -14648, 1137, 1515, -4479, -2758, -2630, 193, 427, -1744, -839, -862, -819, -2238, -1687, 103, -714, -218, -9737, -3465, -557, -1492, 439, -5712, -4673, -1832, -2782, 106, -4317, -3455, -177, -3986, -1112, -3988, -2608, 1099, -5197, -2516, -2516, -2493, 964, -5540, -3544, -1251, -3593, -604, -3070, -5482, -744, -7616, -3978, -1337, -12462, -1125, -7786, -8380, -742, -8535, -2774, -4063, -11811, -1018, -7103, -5773, -3582, -5192, -1771, -6211, -6737, -4687, -2416, -2447, -3962, -9365, -5494, -1557, -2921, -2362, -8857, -3950, -1830, -3256, -1536, -4470, -3112, -2783, -2844, -1492, -2905, -3625, -3987, -1998, -2360, -2419, -5022, -5214, -1659, -4169, -2912, -6536, -5247, -2094, -6068, -4404, -12883, -4173, -3040, -5744, -6282, -6009, -3920, -3782, -4821, -8265, -3423, -4906, -4196, -4536, -11284, -3433, -6995, -4462, -4385, -7178, -6038, -8637, -4578, -3974, -5469, -12730, -7578, -4933, -3589, -5236, -6031, -5920, -5391, -3457, -5734, -5707, -5407, -5162, -3782, -6514, -8844, -6256, -4151, -4442, -7372, -9864, -8398, -3579, -5075, -8072, -5520, -11035, -4064, -5974, -7418, -4383, -9173, -5413, -7400, -6295, -4422, -7142, -6321, -8876, -5980, -5285, -6607, -6100, -9986, -6726, -6866, -7026, -5898, -9719, -9170, -9123, -7579, -6793, -8407, -14646, -18011, -8116, -10370, -8259, -10472, -8183, -8928, -11228, -11437, -10430, -5390, -8883, -8491, -7834, -9696, -4587, -7441, -8322, -4980, -7794, -5017, -6123, -8598, -4332, -6821, -6314, -5720, -8598, -4967, -5271, -8158, -6420, -8336, -6520, -3875, -5633, 5939, 7498, 3816, -4110, -683, 4949, 6931, 3325, -2868, 505, 1173, 5324, 1999, -103, -833, 276, 3248, -27, 688, -4897, 2082, 1688, -1912, -381, -3131, 840, -120, -967, -2153, -1680, 262, -8665, -1243, -4695, -1078, 2055, 581, -249, -3880, -118, 2793, 3291, 1934, -1310, 732, 2875, 4391, 2177, -864, 1025, 2300, 4922, -22, 1560, 741, 209, 5020, 664, 3346, 174, -5471, 4348, 3231, 3735, -310, 664, 2497, 3428, 3167, -723, 2976, -596, 1225, 2238, -952, 3683, -853, -10966, 1769, -404, 3105, 129, 580, 2038, 690, 982, 575, 1900, 2110, 1487, -2467, 895, 1792, 1323, 1460, -1122, 695, 1478, -612, 98, -272, -430, 1702, -4604, -3266, -769, -1265, 2188, -9726, -3476, -2752, -435, 2395, -4439, -2936, -3515, -479, 2059, -3641, -4340, -1159, -2214, 1049, -3233, -5523, -933, -5408, -557, -1956, -6331, -3005, -3736, -2091, -1428, -5164, -7148, -1484, -2616, -2569, -6325, -3510, -129, -2039, -5926, -8524, -1105, 286, -1427, -4879, -3383, 539, -554, -1496, -3624, -1878, 1532, -3859, -1822, -4389, -1500, 1812, -6993, -1536, -6968, -1613, 1247, -2806, -1111, -12036, -2403, -315, -3363, -1365, -10198, -5101, -3183, -6179, -2557, -4521, -3642, -10706, -2277, -4067, -1316, -846, -6087, -392, -4254, 2, -513, -3761, -8, -2085, -262, -2486, -3954, -700, 279, -1985, -7065, -7600, -2532, 1410, -3414, -3956, -5137, -6374, 1188, -3260, -3883, -1687, -7568, -775, -4153, -3148, -403, -4011, -7901, -6251, -1121, 12, -2929, -3366, -9076, -538, -175, -3405, -1694, -10890, -1364, -1269, -5414, -2133, -11695, -3369, -3862, -4455, -3469, -13321, -5873, -5912, -2569, -4727, -12900, -7660, -4463, -2150, -5530, -10061, -6325, -4875, -2331, -6140, -8754, -5603, -6225, -2366, -6844, -9310, -7169, -6174, -2398, -8265, -8591, -9419, -5748, -2759, -11208, -6633, -8630, -4414, -3587, -6956, -6090, -11112, -3346, -4689, -5276, -6994, -12638, -3257, -5399, -6281, -8506, -7850, -3844, -4581, -12244, -8998, -5467, -4606, -3000, -7437, -11024, -3982, -5235, -2214, -5741, -14559, -3415, -5922, -2329, -5662, -8330, -3771, -7270, -2936, -5776, -6914, -5191, -9555, -3375, -5683, -7191, -8282, -11319, -2918, -5387, -8629, -11193, -14322, -1951, -4908, -10776, -7617, -10083, -1392, -4472, -11289, -6296, -7170, -1536, -4382, -8472, -6262, -6463, -2432, -4708, -6520, -7024, -7264, -4142, -5191, -5795, -7500, -9399, -6018, -5687, -6166, -6950, -11079, -5344, -6695, -7335, -6520, -9568, -4151, -9366, -7915, -6668, -7892, -3664, -11859, -7509, -7343, -6626, -3604, -8203, -7554, -8792, -5775, -3673, -7738, -8497, -8781, -5335, -3895, -10352, -12172, -6126, -5371, -4573, -10832, -11214, -4691, -5896, -6076, -7233, -7274, -4370, -6438, -8981, -6794, -6313, -4781, -6075, -13189, -8392, -6425, -2794, -5014, 2094, 4062, 775, 920, -1146, 2417, 2589, 4936, 3051, 1403, 3034, -10342, 6765, 3262, 2457, 3411, 2193, 6895, 1430, 2447, 3277, 3251, 5772, -1085, 1645, 2595, 1631, 3600, 407, 163, 1554, 580, 1491, 38, -2249, 561, 2839, 709, 1250, -4808, -409, 3087, 963, 3247, -3035, -3537, 1405, 2691, 3955, 288, -2711, 1159, 3357, 3626, 2891, 2046, 2533, 2067, 2343, 4115, 3543, 1477, 434, -88, 3895, 3370, -3691, 2722, -1088, 1912, 1934, 1207, 3667, 520, -1062, 770, 2300, 4338, 568, 928, 733, 877, 5272, -1201, 1467, -155, -3759, 5542, -4377, 614, -2033, -7205, 4832, -1541, -509, -3463, -4153, 3246, 619, -614, -4077, -3923, 1866, 1284, 58, -3159, -5763, 2323, 970, 376, -1191, -9738, 2746, 571, -167, 163, -2991, 2090, 518, -1675, 606, -1285, -9, -5, -3919, -66, -1182, -4671, -1455, -6022, -2343, -1636, -6281, -3871, -8176, -6628, -825, -2241, -6933, -6604, -3550, 737, -1412, -7588, -3941, -1937, 1675, -2996, -5979, -3184, -1677, 1721, -5206, -4511, -3779, -2436, 861, -2233, -3094, -4685, -4646, -1042, -1167, -1844, -4323, -12324, -5943, -1999, -1198, -3691, -5630, -4199, -7219, -1373, -3991, -2125, -623, -4238, -1845, -4512, 48, 499, -2786, -1957, -3037, 1229, 646, -6367, -2558, -2054, 1263, 280, -2470, -2945, -2372, -233, -556, -172, -2081, -3973, -2944, -1700, -275, -2455, -10596, -1288, -1024, -2207, -5302, -4313, -725, 450, -5139, -15950, -1506, -2403, 849, -4575, -11619, -1381, -5521, 241, -3617, -10848, -3952, -4205, -629, -2762, -9008, -10166, -4152, -1251, -2646, -13814, -3670, -7243, -2545, -4078, -6141, -2909, -7624, -5308, -7177, -4140, -3531, -3071, -7346, -6519, -4223, -4333, -1660, -7726, -5860, -5727, -4502, -1749, -7183, -6056, -7503, -4412, -3281, -4656, -5271, -6772, -4827, -7504, -3650, -3645, -5648, -5674, -9299, -3597, -2461, -5263, -5178, -6334, -3368, -2197, -5509, -3935, -7568, -2920, -2855, -6093, -3293, -11061, -3300, -3975, -6699, -3216, -6724, -5529, -4297, -7015, -3670, -5820, -8424, -3813, -6821, -5098, -6949, -4491, -3662, -6529, -8867, -9136, -3331, -4482, -6795, -12447, -9999, -3576, -6464, -8371, -8162, -10053, -4297, -6243, -11225, -7268, -8150, -4944, -5010, -7377, -7233, -6136, -5842, -5271, -5335, -8012, -5435, -6803, -6653, -4850, -9710, -6171, -6797, -8058, -5448, -11619, -7080, -5864, -8252, -6766, -11448, -5552, -5293, -7839, -8005, -9893, -4396, -5711, -7421, -8020, -8635, -4153, -7208, -6681, -7290, -7992, -4352, -8804, -5837, -7035, -7624, -4365, -8369, -5335, -7635, -7078, -3812, -8074, -5399, -9177, -6562, -2998, -8894, -6445, -13334, -6483, -2447, -9350, -9490, -11962, -6895, -2528, -7762, -14601, -8024, -7449, -3536, -6936, -11336, -7346, -8039, -5960, -7576, -12136, -9686, -7937, -8472, -9287, -3496, -7503, -8433, -8897, -10383, -4426, -5678, -6649, -7783, -6855, -7695, -4832, -4747, -6722, -5148, -7399, -4425, -3662, -6695, -4683, -4367, -4128, -3404, -7448, -5218, -3807, -3883, -3796, -8240, -6667, -4906, -3967, -4597, -8482, -9104, -7851, -4858, -5533, -8476, -10049, -10036, -6751, -6587, -8181, -7837, -7628, -6463, -8581, -7612, -7054, -7060, -4725, -11410, -7441, -7732, -8435, -4225, -7490, -8598, -9807, -9328, -5025, -5693, -12061, -14319, -6423, -7758, -5131, -9252, -16790, -5234, -17193, -4865, -7176, -12803, -5477, -7934, -4707, -6494, -11724, -6881, -6387, -5316, -6151, -11360, -9805, -6221, -7437, -5109, -10351, -13271, -7217, -9062, -3882, -9080, -7205, -10676, -7973, -3569, -9486, -5212, -11092, -9780, -4564, -12814, -4973, -8225, -13128, -7084, -12401, -6159, -7772, -7994, -9596, -10001, -8795, -7764, -6861, -9734, -8743, -13018, -8587, -6936, -10458, -7666, -16832, -13248, -7464, -11157, -6865, -13350, -8835, -8364, -12259, -6464, -10412, -6063, -9754, -10762, -6847, -8698, -5100, -11149, -9803, -8488, -7883, -4924, -10474, -11642, -13066, -7668, -5416, -8495, -11305, -13263, -8182, -6834, -8020, -8702, -9646, -9635, -7661, -9712, -8259, -8472, -10820, -6223, -12439, -8311, -7929, -10802, -5712, -8917, -8296, -8237, -10867, -6521, -6645, -9213, -9927, -9922, -7500, -5195, -10675, -10293, -8680, -6508, -4594, -9877, -8656, -7971, -5540, -4911, -7628, -8495, -7962, -5331, -6144, -6128, -9506, -8988, -5546, -8410, -5828, -10408, -12057, -5777, -11265, -6702, -9785, -14430, -5836, -8674, -8660, -8797, -10904, -5568, -6489, -10644, -8964, -10424, -4712, -5601, -9813, -11439, -11621, -3802, -5747, -8579, -11469, -11915, -3544, -6736, -8169, -8615, -9917, -4222, -7571, -8891, -7903, -9164, -5899, -7390, -11613, -8061, -9634, -7748, -7776, -12381, -8261, -10773, -7733, -10101, -9310, -8382, -11118, -7290, -13743, -8720, -8758, -9523, -7255, -9444, -9833, -9839, -8479, -7638, -8215, -11816, -11469, -8316, -8413, -8325, -11585, -11035, -8254, -8751, -9150, -11193, -9967, -8321, -8034, -10605, -11760, -9553, -9412, -7233, -14406, -11946, -9279, -11210, -6727, -12462, -12255, -8889, -10244, -6605, -8051, -15851, -8480, -9993, -7124, -6429, -14108, -8135, -12885, -8908, -6275, -11362, -7831, -14963, -12904, -7163, -12241, -7476, -10451, -9523, -8431, -23659, -7144, -9732, -8050, -9233, -10722, -6999, -10200, -8585, -9996, -8487, -7020, -11260, -9236, -11182, -8138, -7204, -13736, -8276, -10763, -9119, -7783, -18582, -7917, -9568, -11103, -9010, -14757, -8302, -9259, -14129, -10997, -14171, -8989, -9768, -14633, -13936, -12129, -11061, -10782, -10645, -20938, -10071, -19054, -11648, -9323, -16545, -9286, -10579, -11734, -9386, -14180, -9455, -9479, -11729, -10118, -13190, -10268, -10695, -11622, -11141, -12357, -11626, -14135, -9898, -12644, -12714, -13309, -18135, -8553, -14126, -16128, -13935, -11560, -8260, -13613, -15183, -13687, -5460, -5452, -11196, -9790, -6817, -6056, -5513, -9729, -8527, -7462, -6792, -6547, -8323, -8116, -7521, -7897, -8488, -7397, -7994, -6971, -9023, -9701, -7447, -8062, -7417, -9471, -8606, -8319, -8659, -8879, -9053, -7016, -9132, -9522, -9267, -8717, -5973, -9771, -9712, -8848, -8000, -5820, -10974, -9332, -8454, -7183, -6355, -9140, -9043, -8340, -7705, -7043, -6816, -7799, -9236, -11026, -8276, -5938, -6492, -11037, -13919, -12229, -6516, -6059, -12418, -10092, -11244, -9211, -6435, -12527, -10279, -8786, -16235, -7044, -12617, -10954, -8149, -9443, -7371, -12099, -10423, -6895, -7777, -8077, -10603, -10177, -5797, -6952, -9957, -11431, -8600, -5629, -6369, -10092, -13096, -6683, -6349, -5890, -7907, -8525, -5796, -7962, -5661, -7485, -7186, -5890, -10650, -5852, -9032, -7611, -6651, -9081, -6749, -12763, -8409, -7470, -7463, -9612, -12106, -7683, -7599, -8078, -13115, -12183, -6457, -7475, -9603, -7910, -17086, -5794, -8052, -7818, -7213, -14571, -6190, -9540, -7204, -8812, -11549, -7308, -10768, -8684, -14668, -10139, -7048, -10197, -12322, -13194, -9157, -6602, -9200, -12084, -10056, -8285, -7252, -8627, -12810, -7922, -7328, -8022, -8385, -11429, -6773, -6689, -7771, -8045, -8789, -7003, -6466, -7631, -7573, -8432, -8996, -6556, -8270, -7469, -10263, -11910, -7045, -9701, -8035, -15432, -10726, -7968, -9492, -8998, -12569, -11408, -8956, -7808, -9465, -9476, -11573, -9228, -7152, -8629, -7377, -9487, -8537, -7727, -7552, -6347, -7904, -7637, -10031, -7612, -6232, -6806, -7240, -15664, -9616, -6842, -6692, -7670, -9481, -10893, -8064, -7899, -9089, -7650, -7844, -10338, -9958, -11632, -7788, -6743, -15399, -9672, -14526, -9735, -6879, -9602, -9141, -14182, -9734, -7913, -7734, -9744, -13034, -7855, -10075, -7958, -10335, -12388, -7859, -12946, -10337, -9381, -12022, -9788, -8896, -15956, -8627, -11608, -12881, -7129, -11091, -9218, -11313, -10909, -7331, -9856, -12378, -10599, -9289, -8453, -10636, -14063, -9657, -8366, -7316, -14168, -9587, -9603, -7885, -6435, -12406, -8310, -10827, -7918, -6999, -9890, -8193, -13505, -8799, -8627, -9652, -8718, -16357, -10594, -10108, -11474, -9647, -11601, -9607, -9776, -16771, -10976, -8973, -7534, -8982, -12427, -12469, -7884, -6626, -9249, -10560, -12453, -7916, -6818, -11029, -9956, -11459, -8787, -8394, -14866, -10541, -11158, -10044, -12984, -16609, -13795, -11623, -11747, -11577, -15079, -15484, -11876, -18280, -9348, -13700, -10976, -11500, -12031, -9298, -12239, -9985, -10336, -9195, -9849, -11672, -10390, -9080, -8701, -9727, -10923, -11246, -8823, -9799, -8697, -8961, -9886, -9284, -12383, -7919, -7485, -7816, -9307, -15202, -8285, -6939, -6696, -9471, -12960, -10168, -7129, -6570, -10868, -10858, -11686, -7784, -7360, -12979, -9968, -10203, -8744, -8974, -13473, -9813, -9332, -10319, -11144, -14184, -10010, -8908, -14214, -12825, -16374, -10464, -8726, -12654, -12828, -21747, -11321, -8842, -9372, -12247, -13544, -12614, -9218, -9057, -9536, -11694, -10012, -10812, -9707, -14010, -13820, -12716, -10251, -6857, -14040, -13994, -9343, -12918, -5936, -9919, -10056, -7413, -13393, -6025, -8555, -6813, -6237, -9227, -5917, -9202, -5305, -5587, -7527, -5636, -14629, -4851, -5726, -6898, -6312, -9374, -5153, -6618, -7181, -8660, -6488, -5724, -7500, -8430, -12088, -5575, -6115, -7335, -8971, -12970, -5820, -6878, -5845, -7404, -11189, -7265, -9106, -4676, -6434, -8058, -11195, -11526, -4566, -6239, -6886, -12075, -9203, -5535, -6462, -6907, -8017, -8769, -7501, -6576, -7458, -6817, -9307, -10182, -6217, -8087, -7065, -9381, -14000, -5790, -9111, -7695, -9273, -14013, -5530, -9469, -6265, -7964, -8628, -5245, -7611, -5366, -6227, -6624, -4801, -6887, -6173, -5867, -6126, -4380, -8080, -8235, -7523, -6694, -4270, -12832, -8111, -10652, -7851, -4643, -11482, -8314, -8778, -9029, -5509, -8708, -8613, -9667, -9666, -6783, -7574, -6763, -15752, -8621, -8420, -6630, -5875, -10426, -7571, -11014, -5964, -6041, -8652, -7110, -16756, -6136, -6739, -7334, -7024, -8682, -7497, -7024, -6649, -7826, -6229, -9272, -6467, -6947, -10813, -5450, -9178, -6030, -7863, -13031, -5848, -9559, -6195, -8376, -10567, -7039, -11033, -7016, -8152, -13587, -8136, -12396, -8158, -7953, -11075, -9305, -14775, -8235, -8296, -6976, -9759, -12712, -8007, -9244, -5595, -7951, -10772, -9307, -8603, -5583, -7666, -10898, -11411, -6726, -6690, -9241, -12558, -9605, -5889, -8239, -9273, -16695, -9047, -6261, -8320, -8281, -12356, -8355, -7796, -8204, -9367, -9069, -6581, -10290, -9000, -12092, -7293, -5492, -12402, -10646, -11428, -6309, -5349, -13143, -13503, -11224, -5961, -5992, -12181, -11390, -11425, -6118, -6902, -10596, -9237, -9379, -6499, -6978, -10052, -9085, -7620, -6983, -6004, -9964, -10892, -6877, -7917, -4814, -9631, -13976, -6852, -9618, -4085, -10410, -10403, -7118, -11857, -4145, -16169, -9094, -7372, -14266, -5161, -10884, -9700, -7793, -11879, -7035, -8524, -12626, -8692, -9682, -7916, -8797, -15806, -9044, -8925, -7578, -11683, -11961, -8553, -8639, -8371, -13669, -11163, -8835, -8225, -10796, -11336, -10129, -9206, -7826, -11944, -11962, -8899, -9312, -7680, -11506, -13009, -8766, -11443, -7934, -14209, -11887, -9428, -15040, -8677, -16195, -10058, -9453, -9580, -9204, -11942, -8270, -9110, -7994, -8292, -11405, -7274, -9576, -7425, -7484, -11145, -7187, -10667, -7253, -7809, -10004, -7976, -10382, -7373, -9628, -9389, -9718, -9708, -8018, -13756, -9756, -13145, -10434, -10148, -25925, -11243, -16287, -13292, -19021, -16248, -14065, -11228, -23071, -9222, -13028, -12224, -9445, -14471, -7451, -13009, -9687, -8828, -11633, -7669, -19763, -8689, -8807, -10563, -9429, -13228, -8834, -9196, -10590, -11230, -10881, -9994, -9838, -10660, -10238, -10778, -11866, -10049, -10486, -9334, -11957, -12076, -9901, -10670, -9106, -15188, -10807, -10374, -11336, -9513, -16229, -10619, -11442, -12249, -10440, -12259, -12338, -11888, -11873, -11920, -8255, 8218, 8518, 4703, 137, -5140, 7753, 8166, 5106, 540, -3250, 6287, 7108, 5555, 791, -1631, 3470, 5348, 5428, 570, 1156, -2180, 2995, 4792, 899, 3233, -668, 588, 3980, 1142, 3964, 991, -1786, 3029, -304, 3094, 702, -8279, 1340, -3512, -478, -1112, -2044, -2134, 1037, -733, -2611, 604, -2068, 3033, 1683, -1222, 1844, 96, 3771, 1510, 67, 2656, 175, 4017, 111, 1671, 3035, -950, 3948, -1754, 2724, 2612, -511, 3152, -2003, 2721, 832, 1060, 745, -727, 1420, -4550, 1752, -1065, -971, -2190, -886, 1588, 2265, -2517, -4913, 1840, 1015, 3345, -3708, -1224, 2726, 1227, 2817, -8670, -906, 2485, 2340, 982, -2849, -1446, 1054, 3226, 62, 537, -684, -2201, 3490, -115, 1737, -56, -7898, 3096, -4738, 1778, -982, -6826, 2077, -1031, 828, -3160, -10160, 152, 2222, -1483, -1212, -4060, -4423, 3118, -5594, 248, -2787, -2026, 2878, -3903, 324, -3570, 406, 1755, -1324, -124, -2496, 719, -230, -71, 80, -720, 417, -1210, -232, 469, -854, 1272, 220, -1195, 159, -4591, 2291, 1101, -1698, -765, -3671, 2406, 1309, -821, -1862, -197, 1487, 1173, 791, -3180, 112, -262, 591, 1361, -5797, -1610, -1179, -998, 493, -6925, -5420, -742, -4666, -1194, -1936, -3467, -1125, -7554, -890, 178, -2146, -2983, -3930, -629, 876, -2217, -5998, -2068, -2152, 306, -2729, -7022, -1218, -7188, -2206, -3760, -5448, -1174, -7687, -10954, -4143, -3419, -1516, -5093, -3138, -2143, -1985, -2057, -4052, -2775, -1117, -1170, -2641, -2138, -5550, -995, -1224, -2670, -735, -9578, -567, -2007, -2219, -342, -7692, 524, -3086, -1683, -948, -7077, 1296, -5370, -1194, -2221, -3256, 1257, -4950, -1069, -3383, -1472, 233, -1693, -1771, -4892, -1180, -1980, -419, -3866, -6621, -2138, -5474, -156, -6157, -4795, -4213, -5127, -339, -4524, -3590, -6570, -3194, -780, -4325, -3557, -8074, -2608, -1703, -5544, -4800, -8634, -3328, -3206, -6749, -7973, -8729, -5125, -3443, -7786, -7871, -10310, -6026, -2155, -10906, -7845, -13434, -5541, -1414, -10743, -15660, -9978, -4354, -1374, -6485, -6403, -8967, -2751, -1939, -3752, -4951, -9769, -1632, -2963, -1807, -5986, -10566, -1131, -3689, -669, -9595, -13136, -1276, -3427, -415, -12170, -10248, -2242, -3000, -1194, -7320, -5671, -4156, -2917, -3317, -4703, -3638, -4702, -3214, -6274, -3608, -2845, -3237, -3756, -5799, -3894, -3093, -2684, -4211, -6050, -5378, -4583, -3074, -4323, -7715, -6447, -7930, -4186, -4257, -7771, -5940, -12505, -5731, -4563, -6867, -5028, -13601, -5859, -5985, -5732, -4149, -8554, -4586, -10478, -4734, -3890, -6391, -4026, -10602, -4790, -4268, -6069, -4167, -7309, -6658, -5053, -6613, -4131, -6262, -15018, -6338, -8256, -3866, -5088, -7044, -8316, -12071, -4221, -4230, -5000, 5922, 2877, -2652, 7225, -1942, 5515, 2353, 3865, 6686, 1766, 4165, 730, 5510, 4940, 3051, 1358, 904, 5010, 2671, 2092, -5564, 2646, 2289, 3628, -1862, -4151, 2909, 607, 4154, -5251, -1857, 1644, 3858, 3041, -1910, 10, -602, 4972, 1045, -3599, 1195, 605, 4873, 810, -9585, 1429, 2420, 3718, -155, -2336, 1055, 3117, 1407, -5780, -222, 808, 2803, 890, -817, 1013, 1218, 2085, 3289, 1366, 1234, 2027, 2761, 4672, 1799, 198, 3034, 3583, 5051, 1359, -1866, 4040, 3129, 4518, 319, -2769, 4706, 813, 3008, -854, -1545, 4699, -3603, 235, -113, -1184, 3630, -1158, -2969, 2063, -2284, 709, -774, -662, 3467, -4019, -992, -2120, 629, 3772, -6185, 1582, -4819, 128, 3272, -7246, 1865, -11520, -1190, 3004, -2061, 812, -2624, 278, 2945, -906, -60, -184, 1228, 1770, -859, 174, 294, 611, -203, 858, 249, -1086, -1130, 369, 2022, 241, -1940, -1573, 174, 1316, 853, 929, -1203, -2489, -2748, 1830, 2295, -2578, -11287, -3262, 2455, 2604, -3068, -6488, -1289, 2326, 2428, -89, -5309, -4264, 1290, 1918, 846, -5271, -4314, -320, 742, -190, -8586, -2029, -1024, -1542, -4638, -9557, -2594, -476, -4319, -4176, -6330, -1582, 565, -4829, -1713, -7113, 14, 1462, -5858, -2051, -10818, 631, 1639, -10144, -3800, -2388, 300, 683, -5406, -5103, 539, -1099, -2281, -2988, -3971, 1757, -3044, -12130, -3151, -2522, 1792, -3792, -3819, -4758, -1578, 714, -4145, -3659, -3347, -1303, -1851, -4225, -5126, -1984, -1914, -7118, -4073, -6039, -1921, -3745, -4571, -3449, -5360, -3066, -4057, -3408, -2754, -3995, -5962, -2056, -3713, -2999, -3494, -8482, -1508, -4204, -3874, -4233, -7004, -2412, -4300, -3411, -6686, -7724, -5074, -4663, -2566, -11435, -8951, -9769, -6523, -2522, -4694, -8805, -5417, -11164, -3203, -2571, -9365, -3728, -7995, -4366, -2390, -9768, -3197, -6963, -5469, -3829, -5474, -3229, -6954, -5628, -4607, -3508, -4104, -6926, -5201, -3017, -3258, -6781, -6688, -5292, -1676, -4259, -8702, -5994, -6273, -442, -6137, -8217, -5305, -7539, 275, -8081, -8464, -5335, -7354, 147, -8731, -3499, -5803, -6249, -888, -7789, -2032, -5607, -5626, -2776, -5259, -2924, -6184, -5689, -5352, -4394, -5429, -9887, -5982, -8624, -5787, -2827, -11662, -5790, -12709, -12312, -1539, -7007, -5155, -13300, -9568, -1918, -4272, -4926, -10232, -7642, -3585, -2757, -5668, -7063, -6153, -6748, -2676, -6399, -5254, -5138, -17375, -4308, -5488, -4550, -5500, -8419, -9177, -5281, -4523, -7549, -5931, -6620, -6823, -4509, -7848, -5396, -5237, -11409, -4001, -5616, -6506, -6804, -9460, -3360, -5102, -6861, -10260, -7357, -3247, -6051, -4702, -6499, -6841, -4070, -8027, -3936, -5306, -6850, -6079, -8982, -4609, -5490, -7067, -9131, -7701, -6456, -6575, -7263, 7862, 3577, -3578, 6519, 8233, 7387, 3047, -265, 6189, 8002, 5799, 1670, 1362, 5358, 7334, 2052, 840, 1291, 4485, 6244, -1155, 1285, -128, 3838, 4508, 3300, 1833, -1630, 2803, 2706, 4122, 2146, -633, 1071, 4250, 3709, 1664, 733, 1908, 5011, 3086, 48, 1542, 2952, 3427, 2686, -1076, 1275, 2652, -882, 1801, -599, -870, 1956, 3469, -227, -932, -10134, 1353, 4678, -4543, -2031, 84, 400, 4984, -3068, -3364, 2172, 945, 5524, 86, -5368, 2475, 1878, 5646, 1514, -4784, 1380, 1394, 5202, 1857, -1441, -806, -1002, 4984, 1045, 477, -635, -4379, 4954, -1648, 1641, 644, -2797, 4288, -3253, 2644, 972, -1322, 3020, 397, 3596, 687, -101, 2814, 1834, 4182, 349, 33, 3996, 2236, 4101, 852, -964, 4939, 1990, 3145, 1720, -2451, 5058, 1103, 1231, 1760, -3097, 3923, -603, -635, 322, -2722, 262, -3038, -1189, -4472, -2620, -1060, -2899, -2015, -3919, -3436, 2012, -984, -1798, -597, -2320, 1947, 383, -902, 216, 171, 124, 1242, -747, -309, 1428, -2713, 1657, -1183, -2483, 1433, -3601, 1756, -1977, -7766, 72, -2811, 1657, -2306, -10583, -3253, -2841, 1340, -2238, -6886, -4297, -3968, 519, -1825, -2592, -2136, -5200, -1223, -213, -715, -1543, -4770, -2527, 325, 291, -1608, -3019, -1503, -1502, 1062, -2140, -1168, -526, -6645, 1322, -3678, -154, -132, -1217, 627, -7430, -550, -1186, -480, -1285, -4158, -3529, -5876, -1895, -3438, -2063, -7058, -5493, -3733, -3336, -2027, -2192, -3358, -3342, -3693, -3797, -2182, -4358, -3690, -4396, -7597, -4956, -6387, -3553, -4124, -8527, -3015, -6323, -2577, -4534, -6396, -614, -4495, -3322, -6881, -3609, -8, -3697, -7313, -9857, -2506, -696, -4470, -5693, -9221, -3224, -2436, -6633, -4554, -7967, -5896, -3135, -4783, -6263, -6039, -5094, -2310, -2602, -6682, -6548, -3167, -2169, -1943, -6395, -13476, -2639, -2628, -2692, -6610, -7486, -2796, -3263, -5452, -3570, -5008, -3103, -4128, -14413, -2148, -4189, -2920, -5986, -6298, -2296, -3889, -2034, -9934, -5030, -3815, -3879, -1032, -9400, -5194, -6892, -3773, -352, -10041, -6318, -11567, -3246, -68, -11535, -8678, -11611, -2635, -19, -9312, -9926, -10994, -2358, -75, -16555, -8034, -10548, -2571, -458, -5942, -7471, -10320, -3233, -1499, -3288, -7675, -10172, -3883, -3313, -2820, -7216, -10202, -3874, -5729, -3540, -5958, -9375, -3945, -8679, -3976, -4982, -6867, -4869, -14072, -4032, -4766, -5660, -6485, -12797, -5370, -5521, -6325, -7500, -10770, -7950, -7705, -9406, -7495, -9962, -5439, -14339, -7057, -8173, -7902, -3887, -8710, -4512, -9782, -6912, -3828, -6140, -3589, -7110, -7707, -5054, -5275, -3751, -5350, -11512, -8205, -5413, -4861, -5301, -10081, -12683, -6424, -6305, -6681, -6900, -8432, -8580, -7125, -8259, -5725, -8012, -8535, -8108, -5274, -4485, -4669, -8641, -6926, -6248, -6259, -5340, -11387, -7950, -6505, -7441, -6765, -6574, -10861, -6476, -5437, -8423, -4254, -15479, -7169, -4629, -8620, -3606, -12207, -9201, -5047, -7602, -3747, -8709, -11083, -6616, -6982, -3893, -6456, -10302, -9628, -7076, -3962, -5050, -8471, -12842, -7508, -4693, -4689, -7345, -11734, -6814, -6884, -5827, -7439, -11003, -5609, -12702, -10190, -7761, -10101, -5059, -13157, -9423, -6792, -8744, -5142, -9739, -6426, -5961, -7578, -5798, -7210, -5659, -6137, -6867, -7190, -5969, -5808, -7719, -6570, -8674, -6533, -6466, -11384, -6787, -10674, -10207, -6446, -6049, -8001, -9156, -4805, -4379, -2756, -6357, -4016, -2200, -2543, -1038, -3515, -1868, -1601, -1907, -492, -2414, -1319, -2497, -2527, -1066, -2857, -2123, -4310, -4353, -2907, -4978, -4412, -4906, -5775, -6566, -9626, -8518, -5234, -5106, -10306, -12933, -10710, -6888, -5272, -8755, -11421, -11443, -8847, -6832, -9574, -10006, -14369, -8444, -8294, -12115, -10349, -17059, -8218, -6559, -12109, -12793, -14743, -8958, -5232, -10175, -11258, -13735, -8599, -5377, -8724, -9164, -15455, -7532, -7007, -8339, -8083, -13265, -7816, -9196, -8268, -7815, -11564, -9832, -9775, -6952, -7926, -13187, -13063, -10765, -5906, -7782, -15584, -12379, -10490, -6108, -8448, -12091, -9122, -7745, -7751, -11906, -13267, -7103, -6600, -10677, -10751, -17622, -6265, -7042, -12941, -9065, -14011, -6049, -8883, -9876, -10813, -20246, -5982, -9756, -7965, -14369, -10195, -5954, -8426, -8195, -13464, -7762, -6066, -7427, -10571, -16908, -7728, -6619, -6541, -17431, -10379, -10433, -8506, -5986, -12697, -9069, -11079, -12715, -6155, -8603, -9403, -7391, -8120, -7531, -6590, -9741, -6131, -6525, -10710, -5535, -10606, -5838, -6682, -8170, -4985, -13638, -6081, -7904, -6235, -4881, -13114, -6427, -9614, -6178, -5447, -11671, -6425, -10083, -7648, -6948, -11728, -6684, -8257, -10462, -9234, -10779, -8225, -6923, -12661, -10619, -9710, -13744, -6671, -16022, -11446, -9270, -10943, -7321, -12995, -13079, -9065, -8320, -8063, -9957, -11276, -9036, -7934, -8312, -9468, -8819, -9467, -8590, -8967, -10645, -7828, -10501, -9496, -10112, -11590, -8063, -11299, -8770, -10139, -10255, -8887, -10595, -7676, -9236, -9306, -8792, -9146, -7960, -8973, -8622, -8151, -7974, -10602, -10019, -8011, -7899, -7927, -14595, -12994, -7918, -8135, -9534, -10919, -13005, -8829, -9017, -14014, -12278, -11690, -11613, -9955, -15600, -15036, -12645, -19515, -9337, -14409, -10368, -12627, -13603, -8850, -15890, -9811, -10021, -14068, -9407, -16778, -11374, -8387, -13052, -10373, -14304, -14554, -8023, -11012, -10984, -11336, -16887, -9066, -10720, -12363, -9353, -14030, -11340, -11317, -15637, -8510, -12135, -12642, -11503, -16126, -8884, -12226, -13096, -11769, -12705, -10963, -14302, -13279, -13499, -9957, -19172, -16625, -12660, -15562, -8688, -13533, -15111, -11206, -13165, -8805, -11767, -13777, -10342, -11808, -10262, -11397, -12807, -10458, -6477, -8783, -9156, -7244, -9578, -6328, -9733, -13536, -7400, -7805, -7936, -9056, -8489, -8789, -6259, -11497, -8573, -7079, -7972, -5792, -7806, -8781, -7542, -4974, -6663, -6561, -8910, -10156, -3840, -9021, -7269, -8634, -12588, -4296, -11760, -9368, -8887, -8988, -6455, -9678, -11606, -9632, -8275, -8061, -6691, -10323, -9533, -9416, -6173, -4993, -7891, -9118, -12433, -5687, -4293, -6883, -9419, -16123, -6407, -4190, -7167, -9529, -14934, -8109, -4288, -8700, -7897, -9795, -12745, -4326, -12059, -6700, -7222, -10335, -4404, -16733, -6277, -6233, -6387, -5099, -11768, -5417, -6268, -5291, -8062, -6109, -3571, -5826, -6571, -8834, -2852, -1710, -3620, -8090, -3887, -1178, -580, -1986, -3856, -2366, -779, -430, -1643, -2432, -2403, -1609, -1343, -2671, -2818, -3680, -3795, -3377, -4520, -4806, -5870, -7664, -6535, -4420, -8343, -7916, -15536, -10653, -4084, -12695, -9889, -11828, -13098, -5003, -9736, -11340, -8721, -12170, -7176, -7383, -8885, -7056, -10148, -10846, -7232, -7236, -6012, -8370, -17930, -8908, -6677, -6057, -7995, -20861, -13738, -7012, -7767, -9371, -11406, -14260, -7883, -13412, -16421, -7421, -10815, -8644, -11246, -10137, -5665, -9564, -9488, -9443, -7578, -5485, -9463, -9239, -9567, -7295, -6693, -9922, -7080, -9377, -8432, -8617, -7936, -5892, -8845, -9031, -9569, -6097, -6073, -8837, -8300, -9826, -5514, -7909, -9189, -8287, -8081, -5938, -13439, -9856, -8392, -6871, -6969, -11578, -10508, -7797, -7008, -8090, -9814, -9997, -7225, -8278, -9567, -10223, -9397, -7195, -10334, -11868, -10981, -8329, -7907, -12488, -10352, -11151, -6826, -9507, -13503, -9198, -11249, -6094, -11238, -11431, -9771, -11613, -6580, -9476, -9627, -10380, -12747, -9020, -7275, -8856, -10247, -13736, -16003, -6086, -8414, -11570, -11831, -8566, -5962, -8008, -16748, -11574, -7193, -7054, -8048, -14475, -13484, -7650, -9263, -8539, -11817, -12244, -8730, -9245, -8822, -10515, -10283, -8339, -8075, -8612, -9537, -8883, -7938, -7841, -8409, -8677, -7755, -8264, -8050, -8787, -7793, -7192, -8081, -8359, -10367, -7308, -6991, -7332, -8931, -14232, -8007, -6797, -7132, -9800, -13835, -11501, -6596, -7893, -9831, -11601, -12887, -6679, -9853, -9139, -11078, -8894, -7338, -11703, -8684, -11386, -8556, -8925, -10719, -8095, -12223, -9890, -12600, -10678, -7601, -13352, -10997, -14219, -12580, -7914, -14900, -10834, -10587, -17160, -9606, -17509, -11831, -9792, -14535, -14620, -15935, -13545, -10180, -13387, -14109, -12626, -11733, -11259, -12852, -11649, -10359, -9112, -13805, -10874, -12114, -8940, -7478, -11162, -8905, -13014, -8389, -7070, -8300, -7873, -12301, -8759, -7897, -7516, -7945, -11441, -9479, -9758, -8260, -9257, -10055, -8912, -11370, -10436, -12243, -9002, -8078, -11958, -13352, -17471, -8733, -8008, -12959, -11729, -16054, -8775, -8649, -14557, -9828, -16015, -8934, -9793, -14432, -9459, -15591, -9838, -11052, -12957, -10547, -15496, -12015, -11458, -12524, -12694, -8230, -7691, -5468, -9481, -8670, -9001, -7408, -5868, -8990, -6591, -9581, -7771, -6956, -7195, -6580, -10393, -7327, -8931, -6473, -7471, -7970, -5549, -11685, -6128, -7159, -7631, -4150, -11748, -5513, -7929, -9741, -3795, -10485, -4303, -17918, -8069, -4614, -8971, -3127, -7586, -6064, -6814, -7951, -2698, -5489, -5580, -10569, -7771, -3189, -5469, -5785, -11898, -7226, -4466, -6865, -6114, -10132, -6694, -6073, -9733, -6129, -6873, -7455, -7364, -13436, -5859, -5163, -9935, -8014, -13410, -5672, -4931, -11197, -8088, -11952, -5759, -5908, -8516, -8227, -10857, -6700, -7381, -6294, -7948, -7578, -7593, -6226, -4093, -5630, -4017, -4501, -4020, -2154, -3361, -1993, -2598, -2742, -1072, -1949, -1330, -2120, -2586, -1063, -1517, -1931, -2742, -3767, -2267, -2219, -3885, -4222, -6305, -5003, -4359, -7515, -6275, -6329, -9340, -7607, -12642, -7451, -5676, -9219, -6602, -13829, -5922, -6883, -7370, -5890, -10794, -4729, -10218, -5433, -6630, -9067, -4538, -15278, -4265, -8349, -8557, -5277, -15622, -4066, -8880, -8228, -7025, -17999, -4908, -8895, -7876, -9730, -20204, -6995, -10528, -7947, -8986, -15609, -11480, -8558, -8529, -6973, -14060, -13132, -6336, -9480, -6072, -14891, -8563, -5576, -9787, -5940, -12477, -6978, -5672, -9075, -6201, -9322, -6417, -6451, -8859, -6523, -7573, -6467, -7443, -9016, -6973, -6791, -7238, -7352, -8515, -7959, -6689, -8750, -7373, -7939, -9814, -6907, -8398, -8020, -7907, -11790, -7184, -6899, -8017, -8015, -10770, -7572, -6198, -8602, -7580, -9305, -7928, -6155, -12835, -6869, -8482, -8451, -6730, -11413, -6489, -8152, -9575, -7862, -8206, -6709, -8087, -8522, -9050, -7654, -7533, -7890, -6803, -9935, -8072, -8451, -7253, -6535, -11353, -8295, -8740, -6322, -7893, -15348, -7725, -8988, -5476, -11460, -13262, -7221, -9483, -4995, -10780, -10224, -7251, -9437, -5058, -8963, -8837, -7649, -9570, -5841, -9093, -8473, -8169, -11427, -7607, -10154, -9463, -9020, -13397, -10596, -9380, -11766, -10451, -10172, -10965, -8168, -11446, -11564, -8940, -9038, -8329, -11145, -11019, -8637, -7810, -10112, -13124, -9888, -8452, -7159, -12460, -13661, -8969, -8120, -7365, -11740, -11131, -8617, -7994, -9199, -10800, -9901, -8864, -8338, -18405, -9328, -9597, -9573, -8683, -9092, -8348, -10440, -11231, -8532, -7338, -8315, -13288, -13336, -8470, -7996, -8943, -11069, -10472, -9040, -11538, -10138, -8492, -9458, -10575, -12131, -12718, -7794, -10389, -12879, -10330, -17404, -8374, -12979, -12355, -11566, -15374, -10212, -15777, -12279, -12726, -16126, -12892, -15051, -17251, -12160, -15098, -11206, -13405, -13200, -12773, -12624, -9967, -12677, -10384, -12458, -10770, -10191, -12112, -9969, -12304, -9488, -11298, -11629, -10552, -12837, -9005, -12997, -11904, -11543, -11254, -9555, -14936, -12024, -13036, -10176, -11863, -16570, -11122, -14227, -10661, -18824, -15736, -10527, -14187, -13092, -11981, -10996, -10305, -17064, -21464, -10450, -9195, -11056, 4273, -1175, 9553, 9450, 3052, 4463, 3879, 9185, 8848, 3751, 3691, 5671, 8199, 6996, 2976, -6, 5626, 6835, 3747, -666, 792, 4574, 5106, -1149, 3063, 2037, 4190, 3092, -4209, 3800, -358, 4688, 1661, -2811, 2384, 554, 4827, 2424, -2806, 1978, 2707, 4521, 3968, -690, 2707, 2711, 3757, 4130, 2386, 1913, 2064, 2494, 2508, 3667, 712, 2465, 1624, -715, 3416, 4000, 3141, 2531, -43, 2698, 6322, 3113, 4058, 1241, 3628, 7327, 2097, 4876, 2277, 4319, 7299, 1273, 4438, 3268, 3504, 6323, 1854, 3006, 3946, 376, 4314, 1023, 3672, 4062, -5035, 714, -3398, 4912, 3429, -584, -8156, -3245, 4998, 1886, 697, -982, 327, 4263, -1023, 1589, 1056, 3814, 3295, -5086, 2308, 1972, 5817, 2295, -2104, 3082, 2652, 6521, 377, -467, 3600, 3493, 6229, -3459, -114, 3379, 4039, 5186, 1078, -559, 2118, 3913, 3637, 3134, -594, -248, 2957, 1526, 3430, -111, -1222, 986, -1358, 2163, -472, 56, -2241, -835, -1865, -2532, 1237, -4694, -594, -748, -9471, 2363, -695, -6239, 2071, -3963, 3385, 1107, -315, 2712, -1725, 4066, 1139, 2838, 1943, -850, 4185, 385, 3798, -1034, -810, 3729, 409, 3633, -3631, -1834, 2835, 188, 2725, 946, -4437, 1381, -1223, 1115, 1704, -6992, -1534, -2586, -1552, 193, -4345, -4134, -2019, -2514, -5752, -3653, -1077, -1083, -444, -2084, -4006, -412, -207, 462, -456, -2819, -1217, 425, 537, -907, -1298, -3329, 342, 278, -2320, -650, -6489, -974, -53, -2929, -765, -4640, -4479, -814, -2364, -1373, -2710, -9811, -2690, -2639, -2160, -1708, -7460, -5063, -4249, -3165, -1116, -6249, -2842, -5023, -4942, -960, -3882, -1322, -3471, -8502, -1330, -3190, -894, -2532, -9041, -1644, -3392, -1071, -1851, -6633, -1087, -3902, -1602, -1002, -5609, -598, -5119, -2438, -522, -4698, -1066, -6220, -3522, -1088, -4180, -3025, -5845, -4633, -3574, -4309, -9354, -5815, -5317, -8883, -4318, -4059, -5763, -4295, -4753, -3956, -1188, -5059, -3028, -5161, -4196, -282, -4459, -2775, -9570, -4659, -623, -4394, -3602, -6541, -2769, -1731, -5262, -4933, -5054, -1102, -2424, -8236, -4875, -4457, -759, -1695, -5776, -4752, -4278, -1699, -657, -3225, -5190, -6168, -3979, -402, -2833, -3816, -9388, -7674, -1212, -3869, -2747, -4540, -11357, -3107, -5078, -3168, -3531, -8642, -5995, -4722, -5514, -4313, -5362, -8466, -3742, -12373, -6390, -3513, -7445, -3093, -5643, -8647, -2786, -5096, -3357, -3478, -8699, -3144, -3019, -4871, -3100, -8418, -4030, -1802, -7819, -4520, -8160, -3842, -1386, -9033, -9826, -8837, -3438, -1593, -5964, -4630, -9426, -3444, -2068, -3661, -1901, -7578, -3273, -2546, -2794, -963, -6642, -3195, -3431, -3491, -1447, -6127, -3465, -3316, -6683, -3872, -5921, -3687, -2004, -9602, 6954, 9472, -4937, 4408, 9914, 6202, 9072, -277, 4177, 9310, 3917, 7959, 2087, 3212, 7388, 683, 6428, 3014, 2072, 3868, 582, 4826, 3459, 2377, 1248, 2628, 3240, 3879, 2178, 2305, 3044, 2265, 4056, 802, 3017, 977, 2908, 4021, -218, 2782, -1481, 3752, 3866, 9, 1238, 1895, 3814, 3406, -734, -1246, 2452, 2890, 2862, -2419, -2154, 1980, 744, 2974, 458, -160, 2350, -3684, 3764, 1833, 1209, 2987, -188, 4442, 1831, 1820, 3272, 3009, 4590, 1979, 2915, 3663, 4306, 4297, 2743, 3739, 4182, 4135, 3864, 3231, 3347, 4460, 2066, 3431, 3057, 1366, 4330, -4188, 2732, 2029, -2450, 3903, 673, 1244, 597, -4712, 3501, 1868, -1737, 1065, -6321, 3025, 1724, -4798, 2014, -4691, 2115, 726, -4126, 2091, -2153, 873, -214, -4141, 2340, 833, -948, 3005, -788, 3695, 2866, -1217, 4662, 580, 4650, 3917, 1403, 4843, 599, 4670, 4315, 2157, 4046, 1278, 4078, 4281, 968, 2668, 1969, 3638, 3946, -3127, 868, 1315, 3439, 3449, -3484, -1794, -954, 2896, 2900, -913, -7509, -3831, 2195, 2366, -124, -8891, -3278, 2169, 1966, 447, -9929, -2773, 2353, 1726, 974, -7235, -4046, 1859, 1446, 1041, -4166, -4206, 167, 963, 362, -4972, -2035, -4366, 733, -1274, -4793, -1814, -2747, 1230, -3148, -1473, -3520, -65, 1452, -1912, -365, -4497, 161, 630, -1234, -1045, -2661, -1458, -1577, -2481, -4519, -1881, -2648, -5054, -7214, -6705, -1632, -918, -5935, -5615, -2820, -1622, -958, -7067, -2567, -3478, -2015, -3264, -8679, -1535, -8165, -2000, -5201, -6614, -1732, -1751, -1280, -3369, -6594, -3178, 554, -656, -3463, -5552, -6775, 1130, -171, -4938, -3561, -8282, 471, 41, -5423, -2609, -2999, -1300, -94, -3325, -2318, -1368, -3745, -379, -1975, -2221, -1283, -5095, -900, -1983, -2245, -2265, -4743, -2068, -3757, -2644, -3826, -3992, -4546, -8374, -3572, -5080, -4028, -10704, -6822, -3868, -5142, -5987, -4616, -6468, -2488, -4351, -9791, -2110, -7995, -1434, -3764, -4731, -1066, -5576, -1032, -3972, -3632, -1165, -2801, -647, -4636, -4538, -2905, -1633, -126, -4203, -4911, -9326, -1965, -14, -3423, -3255, -5919, -3705, -551, -3487, -2473, -5154, -6023, -1571, -4266, -2469, -9219, -7353, -2958, -4869, -2960, -9120, -8008, -5357, -5053, -3932, -6637, -6305, -7577, -4855, -5276, -6676, -3559, -5508, -3928, -8032, -5416, -1765, -4957, -3400, -7311, -3173, -977, -5631, -3807, -3876, -1883, -1052, -7343, -5107, -2784, -1889, -2034, -7426, -6933, -2888, -2758, -3039, -5105, -7268, -3435, -3180, -1892, -4394, -6583, -3779, -3925, -902, -5305, -7276, -4089, -6806, -1123, -7841, -8526, -5036, -5094, -2829, -12767, -7115, -6830, -3640, -4196, -6814, -6351, -5633, -5165, -2616, -4037, -7365, -3552, -12596, -2570, -3857, 5615, 3635, 5008, 8307, 8560, 5276, 3327, 4031, 7670, 8181, 4450, 2321, 1492, 5751, 7141, 3678, 319, 2251, 3453, 5936, 3177, -3642, 2484, 2769, 5359, 2469, -8211, 83, 1311, 5080, 1111, -4452, -710, -1942, 4119, -1054, -5164, 75, -988, 1760, -2503, -5947, -2624, 1559, 2341, -664, -399, -3492, 2666, 4350, 1598, 1249, -3523, 2324, 4896, 3228, 1656, -2654, -128, 5228, 4019, 2532, 406, -2052, 5724, 3668, 2788, -39, 2565, 5583, 1650, 1405, -870, 3978, 4515, -2496, 933, 2143, 3757, 2798, -1109, 2023, 2958, 2232, 2025, -625, 1457, 2016, 114, 2601, -1397, 894, 15, -1423, 2450, -2000, 2236, -1643, -11317, 1123, -1329, 2933, -2148, -170, -824, 557, 2647, -1452, 2212, -2245, 2466, 1557, -1140, 2175, -1229, 3422, -218, -1811, -164, 581, 3061, -2526, -3445, -5945, 1800, 1065, -5835, -5227, 176, 2800, -702, -8766, -4097, 2096, 3326, 706, -3323, -2528, 2868, 3305, 365, -1412, -980, 3057, 3440, -2261, -908, 566, 2721, 4059, -3183, -1116, 1551, 1749, 4440, -1772, -1045, 1894, 359, 4158, -2445, -643, 1789, -242, 3144, -4745, -967, 1530, -193, 1520, -4033, -2696, 1308, -892, 52, -2012, -5652, 978, -2084, 18, -1076, -4025, 301, -647, -37, -1324, -2462, -748, 993, -756, -4055, -1989, -1544, 1716, -216, -4336, -1713, -798, 1934, 646, -734, -585, 182, 1874, 632, -120, 181, 146, 1506, 245, -1036, -461, -1386, 874, 294, -1857, -2886, -4885, 226, 715, -1534, -4240, -3475, -156, 764, -1498, -4122, -2271, -228, 6, -1893, -7978, -2968, -98, -1350, -2696, -7527, -3951, 161, -2049, -4314, -4112, -2768, 377, -2023, -6945, -2920, -1353, 292, -2319, -8120, -2399, -663, -146, -3012, -6529, -2890, -708, -576, -3730, -5428, -5567, -1452, -537, -4195, -5525, -6484, -3160, -453, -4817, -7842, -2593, -7125, -1080, -5487, -7095, -1935, -11674, -2918, -3832, -3255, -3267, -7803, -5583, -1555, -1853, -3193, -4682, -4558, -248, -2116, -1765, -1967, -3151, 143, -4549, -2223, -635, -3122, -199, -11564, -4887, -375, -5590, -1244, -3692, -4172, -974, -6671, -3216, -1978, -1813, -2305, -2030, -4099, -1808, -942, -4570, -619, -1963, -2460, -1148, -8696, -699, -693, -2703, -2454, -6312, -2090, -404, -2307, -4238, -5549, -5742, -910, -2557, -4134, -8368, -6972, -1986, -3818, -4147, -5337, -2869, -2843, -5667, -5483, -2721, -1442, -2606, -6727, -5661, -2118, -1262, -2025, -6217, -4312, -2781, -2241, -1803, -5391, -4079, -3978, -4918, -2132, -5481, -4602, -4163, -8880, -3134, -7374, -4419, -3967, -5455, -4967, -8361, -3621, -3249, -4093, -6857, -4338, -2503, -1548, -3482, -6420, -2519, -1318, -657, -3514, -4889, -2151, -979, -1116, -5343, -2908, -3067, -2029, -3077, -8158, -1527, -6560, -5790, -3832, -2206, -4127, -3399, -4292, -4940, -4974, -2793, -2362, -2653, -10980, -5415, -3649, -2321, -1871, -4721, -2919, -4537, -2595, -2070, -2139, -2575, -1729, -2704, -3356, -1931, -3305, -753, -2510, -6063, -3729, -5163, -1706, -2349, -9383, -5256, -11377, -5034, -2566, -7340, -2712, -5787, -9046, -3593, -6261, -1699, -3302, -9886, -6186, -6696, -1792, -2738, -7512, -8622, -9946, -2511, -3281, -3572, -4661, -8071, -3873, -4912, -2319, -2313, -4209, -6451, -7637, -2129, -1412, -2828, -5466, -7336, -2281, -2182, -2979, -2911, -6517, -2539, -6309, -4981, -2174, -6412, -2590, -4489, -7737, -3255, -4516, -1907, -1229, -3607, -5026, -1662, -835, -276, -1725, -2208, 222, -152, -496, -1159, -920, 934, -298, -1543, -1731, -1278, 570, -1511, -3107, -3860, -2520, -665, -4148, -5063, -9601, -3563, -2338, -7677, -6647, -9347, -5738, -4128, -5612, -6055, -8722, -11473, -5027, -4799, -5335, -10194, -3950, -3216, -5976, -4666, -6511, -2263, -1858, -11547, -3776, -4016, -2056, -1812, -6608, -3305, -3151, -2510, -3001, -3221, -3992, -3655, -3160, -3823, -2022, -7049, -4559, -3915, -3231, -2280, -10880, -4556, -4119, -3716, -3862, -5402, -5662, -3493, -5324, -6761, -3992, -12154, -3430, -4389, -10854, -3634, -7926, -4819, -3306, -7653, -3998, -6180, -8424, -3646, -7246, -5270, -5766, -6096, -5140, -8179, -8096, -4530, -3860, -7042, -4222, -14070, -3643, -3048, -7790, -2448, -6400, -3436, -2945, -7516, -2289, -3818, -3584, -3237, -8134, -3080, -2611, -3866, -3720, -8361, -3900, -2253, -4413, -4300, -4948, -5062, -2574, -5451, -4891, -3104, -9966, -3473, -6412, -4902, -2675, -7509, -4489, -6146, -4202, -3286, -5122, -4607, -6019, -3941, -4588, -5910, -4538, -6926, -4744, -5937, -9521, -5491, -8071, -6459, -6309, -11466, -8106, -7592, -7168, -5891, -9960, -11277, -5992, -5987, -5797, -9214, -8528, -4722, -4286, -6720, -6405, -6920, -4206, -3205, -6913, -3869, -6418, -4041, -3431, -4272, -2550, -7061, -4052, -5496, -2653, -2424, -7305, -4873, -5290, -2181, -3493, -5061, -7351, -2919, -2649, -5876, -3521, -9266, -2294, -4077, -10095, -2802, -7212, -2773, -5907, -8717, -2538, -7541, -3682, -5534, -5626, -2788, -11674, -4209, -5122, -4904, -3801, -7671, -4054, -5863, -6040, -5899, -5640, -3933, -6746, -7308, -9937, -6103, -4673, -7159, -6200, -11302, -8101, -6783, -8030, -6107, -10018, -8576, -9051, -8822, -7101, -11354, -9780, -10360, -7996, -7714, -12917, -14236, -12235, -6338, -6552, -11621, -9197, -7458, -5166, -4849, -8419, -7984, -6006, -4844, -3899, -6185, -7370, -5861, -5552, -3962, -5079, -6536, -5921, -7571, -5142, -4988, -5869, -5594, -8610, -7533, -6242, -5003, -4945, -7103, -8357, -10606, -4213, -4411, -7081, -6808, -6725, -4030, -4417, -8126, -6290, -3779, -4559, -5224, -8156, -7091, -2724, -5747, -6887, -7593, -10336, -2890, -7675, -7564, -7008, -10528, -9120, -3096, -4727, -4287, -7491, -4825, -4498, -3189, -5400, -5052, -2316, -9808, -3096, -4647, -2070, -1095, -6897, -3549, -5188, -1297, -802, -4170, -4566, -6792, -1008, -1259, -3154, -7079, -7195, -699, -2081, -2734, -15953, -4835, -883, -3234, -2323, -6262, -3110, -1629, -6398, -2055, -4209, -3242, -2189, -8191, -2449, -3915, -5945, -2211, -3292, -3650, -4302, -8079, -2289, -1759, -5461, -3952, -6295, -2647, -1335, -7280, -3541, -8559, -3380, -1636, -6264, -3789, -13940, -5077, -2738, -4418, -4242, -9014, -9489, -4759, -3781, -4495, -5163, -5181, -6342, -4922, -5022, -3683, -2458, -8291, -7631, -6580, -4346, -1075, -8462, -2754, -4878, -3071, -243, -2870, -537, -1919, -316, 204, -1089, 0, -670, 949, 296, -995, -644, -856, 1038, -27, -2143, -1944, -2630, 177, -943, -3767, -2880, -7857, -1420, -2684, -4335, -3313, -6982, -3321, -5534, -4204, -3754, -4830, -5405, -9695, -4094, -4340, -5866, -8479, -13551, -3983, -5277, -8131, -10593, -13952, -3253, -5526, -5080, -10748, -15480, -2255, -3728, -3198, -8577, -12923, -1884, -2381, -2588, -6205, -8805, -2267, -2100, -3295, -5584, -7718, -2484, -2385, -6230, -5795, -5552, -1869, -2196, -8137, -4130, -3618, -1475, -1783, -4668, -2520, -3253, -1644, -2018, -3820, -2332, -4373, -2114, -3077, -3941, -3940, -5092, -2411, -4569, -4179, -8094, -3619, -2672, -4884, -4497, -4430, -2644, -4021, -3878, -5995, -2571, -2405, -8544, -3126, -13961, -2273, -2688, -7916, -2867, -5187, -2779, -3384, -6460, -2694, -2522, -3542, -4525, -8638, -2424, -1563, -4042, -6247, -15573, -2544, -1488, -4321, -7301, -10773, -3226, -1982, -4677, -5448, -7491, -3714, -2968, -4713, -3784, -4511, -3859, -4348, -4788, -3045, -2910, -4707, -5446, -6259, -3197, -2664, -6729, -5219, -8369, -4314, -3598, -10067, -4589, -5702, -6900, -4468, -14336, -4819, -4702, -15129, -3976, -12010, -5059, -4953, -8456, -3869, -11674, -3651, -5724, -6693, -4473, -12949, -2778, -7384, -6712, -4823, -12265, -3244, -8545, -6116, -4636, -12510, -5433, -7265, -4422, -4448, -10423, -12733, -7066, -3619, -3561, -7027, -7660, -6530, -3902, -2370, -5509, -5134, -6155, -4675, -1971, -5581, -4506, -7476, -5309, -2794, -7460, -5683, -10713, -6690, -5356, -12984, -11029, -9099, -8566, -9806, -12260, -7688, -7849, -6230, -7807, -9346, -5945, -8325, -4902, -7786, -6910, -7009, -8612, -5072, -9369, -5536, -10069, -6354, -6591, -10282, -5508, -8597, -4974, -9521, -9013, -7028, -7475, -4960, -12767, -7785, -11313, -6752, -6424, -12740, -7696, -11893, -5091, -9821, -12027, -8870, -7707, -3872, -8602, -12424, -10914, -5108, -3573, -6720, -12253, -11214, -3706, -4009, -6618, -10520, -8551, -3648, -4646, -8112, -8389, -6121, -5259, -4687, -12149, -7513, -4632, -10013, -3921, -11291, -8555, -4036, -8911, -3076, -9212, -12275, -4365, -7671, -2822, -8690, -8791, -5970, -9197, -3530, -8578, -6469, -5236, -4781, -6658, -2943, -1061, -7932, -4475, -8167, -934, -1390, -5860, -2757, -4476, -89, -2212, -2857, -2192, -2450, 167, -3011, -1371, -1832, -1663, -238, -3480, -972, -1294, -1547, -1734, -4059, -1244, -897, -1830, -3042, -5447, -1757, -863, -2291, -1205, -7176, -2443, -1068, -2025, -309, -6780, -3996, -1493, -1345, -773, -7187, -6478, -2689, -1326, -2301, -8534, -3977, -5782, -2000, -3862, -7084, -2219, -12366, -2773, -4157, -5134, -1684, -8569, -3243, -4514, -3676, -1609, -7788, -3766, -5119, -3547, -1606, -7236, -4041, -5522, -4209, -2205, -8857, -3681, -5065, -3096, -4882, -10267, -5416, -4456, -2720, -5063, -4605, -5564, -5785, -5154, -1789, -1874, -728, -5549, -5346, -1221, -874, 786, -2209, -2249, -2372, -1341, 650, -767, -1850, -3870, -3180, -695, -403, -3195, -3004, -5858, -2351, -602, -6531, -2624, -7577, -2869, -893, -7728, -3960, -8577, -3177, -1114, -5156, -6189, -9822, -3652, -1729, -4802, -4580, -9729, -3535, -3155, -6991, -3884, -9499, -3153, -4561, -8089, -3763, -8259, -3177, -3769, -5249, -3167, -6487, -3448, -2869, -6451, -2904, -5645, -3415, -2875, -6168, -3025, -5571, -2856, -3942, -2709, -3116, -6335, -2206, -6728, -1971, -2853, -8948, -2071, -11805, -3066, -1838, -12433, -2644, -6024, -5840, -967, -6445, -3627, -4214, -8153, -878, -4446, -4481, -3426, -6547, -1549, -3317, -5099, -2609, -5216, -2762, -2450, -5268, -1988, -4438, -4504, -1871, -4618, -2094, -3854, -7470, -1826, -3355, -2869, -3289, -17753, -2802, -2154, -3651, -2710, -7254, -5823, -1379, -3810, -2387, -4293, -7421, -1022, -3262, -2595, -2864, -4888, -984, -2695, -3096, -2603, -5210, -1266, -3076, -3220, -3347, -6868, -1982, -5280, -2894, -3896, -7007, -3145, -17998, -2759, -3266, -7738, -4097, -6380, -3554, -3183, -10779, -3979, -4415, -6024, -4240, -12735, -3976, -3511, -9161, -6071, -12265, -5311, -2484, -10379, -6941, -7090, -10284, -1505, -12420, -5684, -4708, -7921, -1099, -7151, -3929, -4140, -4845, -1423, -7725, -2906, -5352, -4079, -2415, -10884, -2767, -9575, -4751, -3868, -4996, -3267, -11989, -7115, -5006, -3391, -3812, -11979, -10810, -5188, -3586, -3784, -8891, -6382, -5441, -5553, -3438, -5727, -3479, -5894, -12436, -3191, -4619, -2024, -5517, -7064, -3122, -4018, -1711, -4483, -4948, -3381, -3236, -2307, -3707, -4471, -4159, -2468, -3365, -3586, -4439, -5249, -1958, -4202, -4446, -4159, -5909, -2016, -4686, -7049, -3815, -5830, -2881, -5316, -8985, -3897, -5727, -4315, -6894, -6111, -4099, -6446, -5802, -10967, -5680, -3778, -8126, -8852, -12693, -6969, -3660, -9269, -11311, -8799, -8984, -4230, -10135, -6885, -6827, -8416, -4706, -12410, -6134, -6142, -7269, -4802, -11045, -6734, -6913, -6875, -5306, -7901, -7838, -8307, -6747, -5268, -6268, -8514, -7424, -6007, -4627, -6013, -7963, -6595, -4887, -4943, -6881, -6893, -6953, -4348, -6424, 8312, 5887, 763, 6240, -363, 8294, 6155, 1032, 5545, -1258, 8007, 5877, 1907, 2928, -1251, 7048, 3746, 3572, -1938, 911, 5242, -371, 4533, 2396, 1978, 3126, 3069, 3923, 2713, 1787, 2172, 4094, 719, 14, 481, 3186, 4027, -121, -4285, 838, 4514, 3804, 2625, 180, 2550, 4919, 3657, 2521, 1067, 3483, 4582, 3362, 258, 2969, 3998, 4482, 2739, -6911, 4973, 4239, 4254, 3194, -2381, 5869, 4139, 2316, 4698, -612, 5539, 3654, -2238, 5395, -864, 3736, 2454, 913, 5114, -2219, 274, -5, 1216, 4154, -2132, 1318, -2522, -67, 2602, -1085, 2215, -2412, 131, -283, -886, 1268, -4026, 1186, -8097, -1710, -1149, -6953, 1561, -4291, -3347, -4797, -2354, 1522, -1303, -3727, -6138, -433, 1412, 133, -2083, -4125, -87, 815, -292, 172, -1455, -1082, -27, -3173, 1392, 845, -3508, 747, -2476, 1285, 1824, -1900, 1521, -1280, 820, 1686, 181, 1523, -4127, 1264, 491, 504, 1582, -1000, 1071, -3544, -907, 1450, 2030, -655, -2890, -3654, 3, 2817, -492, 659, -651, -4158, 2016, 1441, 818, 725, -10322, -840, 1979, -1194, -2, -8915, -5398, 1183, -1790, -2223, -6956, -2149, -1520, -56, -1105, -3460, -2442, -10631, 261, -303, -1559, -3357, -1627, -200, -1439, 167, -1243, -98, -570, -2185, 1208, 270, -178, -341, 51, 1412, 678, -1143, 5, 1425, 1216, -292, -1832, -159, 1825, 1256, -3538, -1494, -1115, 1555, 1587, -1977, -404, -2659, 1059, 1717, 80, 665, -3520, 841, 1159, 162, 792, -3107, 657, -448, -835, -464, -2113, 58, -3922, -1838, -3144, -1636, -806, -10528, -1556, -2638, -2444, -1534, -4173, -477, -1284, -3701, -2217, -3028, 311, -1290, -1968, -2833, -2955, 532, -2286, -406, -2998, -3034, 207, -3360, 179, -3012, -2639, -619, -2785, -62, -3928, -1952, -1977, -1827, -1392, -7686, -1681, -4262, -1592, -5592, -9053, -1987, -8758, -2354, -5422, -6045, -2718, -7035, -4539, -1752, -6965, -3828, -5662, -10232, -853, -7632, -5907, -6125, -6723, -855, -6549, -8259, -5978, -3467, -1133, -6529, -4785, -4562, -2279, -1386, -6847, -3401, -3669, -2823, -1427, -7821, -3833, -3606, -6032, -1374, -8088, -6000, -4148, -7704, -1368, -5769, -7785, -4977, -4936, -1565, -4181, -5556, -6132, -5997, -2140, -3599, -3794, -7335, -13081, -3091, -4133, -2413, -7218, -7692, -4501, -5860, -1528, -6840, -6739, -7249, -6578, -1438, -8422, -8001, -17811, -5284, -2387, -10105, -7352, -7847, -4947, -4342, -5643, -6214, -7228, -6386, -5210, -4781, -7105, -8778, -13916, -4956, -6509, -11004, -8787, -7620, -5986, -13650, -7198, -9389, -6170, -8564, -12574, -5441, -18478, -7578, -14813, -12988, -5656, -9929, -14786, -9762, -8635, -6950, -8535, -8450, -6373, -7771, -7891, -9058, -5077, -5412, -8878, -7258, -9097, -3639, 1446, 4870, 5496, 3432, 778, 2169, 4055, 4926, 2644, 1374, 2487, 1165, 2583, 1077, 1593, 1238, -9366, -4050, 2166, 1722, -1745, -4241, 2422, 3098, 2608, -1709, -11737, 3101, 2365, 2776, -656, -3138, 698, 90, 1600, -336, -1552, 42, 1775, 821, 87, -2168, 3276, 3289, 2542, -194, -1324, 4464, 2620, 4013, -3154, 646, 5129, 658, 5289, -802, 2092, 5542, 3390, 6094, 2705, 3242, 5233, 4793, 6071, 3909, 3952, 3664, 4131, 5190, 3726, 4040, -489, 463, 3738, 2159, 3503, -3730, 867, 2626, -1511, 2218, -177, 3882, 2668, -891, -258, -454, 4726, 2825, 821, -1874, 271, 4810, 2074, 230, -1089, 2122, 4593, -88, -2783, -2625, 2683, 4179, -4117, -7287, -3032, 1897, 3611, -3947, -3767, -1114, 377, 3060, -3057, -3805, -1994, 650, 2579, -4042, -6118, -6273, 1787, 1891, -5161, -6898, -5117, 1980, 863, -4271, -2408, -6868, 696, -89, -3863, -556, -3126, -4108, -359, -1906, 282, -431, -1615, -145, 439, 855, 479, 930, -166, 1445, 1122, 957, 828, -616, 1130, 775, 1433, -1303, -1174, -415, -162, 1415, -1521, -1711, -2517, -798, 37, -129, -1913, -2753, -848, -5232, -1012, -1887, -1764, -1762, -2590, -3901, -2498, -512, -2482, -429, -2118, -3514, 660, -1072, -597, -614, -4241, 1327, -790, -1868, -22, -3086, 1275, -2170, -2804, 433, -738, 732, -5131, -1557, 660, 408, 493, -6968, -83, 401, 317, 544, -3263, 920, -609, -882, 79, -592, 1584, -2882, -2961, -889, 747, 1898, -6333, -3936, -1213, 1066, 1671, -4477, -3040, -1196, 501, 605, -3687, -2741, -2076, -948, -1863, -3725, -3608, -3615, -3514, -8203, -2846, -5675, -4626, -7676, -5780, -2051, -5646, -4864, -7906, -4712, -1879, -4707, -4460, -8375, -6614, -2083, -5367, -4632, -16250, -14775, -2613, -7158, -5467, -7373, -10453, -3500, -9096, -6113, -6672, -12921, -4584, -8025, -7107, -9112, -8602, -5586, -6671, -8545, -6273, -4569, -6001, -6944, -6493, -3572, -3106, -5768, -6814, -5466, -2070, -2986, -5942, -6051, -6991, -1191, -3900, -7742, -5497, -10539, -980, -5624, -12196, -4103, -5565, -1540, -7062, -9523, -2878, -3827, -2988, -7111, -10643, -2372, -3418, -5831, -7249, -6598, -2449, -3770, -9218, -7702, -3064, -2873, -4524, -5252, -7390, -1470, -3361, -5234, -3699, -6322, -1108, -3863, -5805, -3796, -5425, -1798, -4517, -5806, -5718, -5233, -3353, -5104, -5088, -8064, -5966, -4350, -5365, -4661, -4926, -7452, -3960, -5678, -4644, -3868, -8402, -3993, -6276, -4768, -4497, -7430, -4679, -6686, -5100, -6680, -6008, -5367, -6348, -5765, -9584, -5354, -5330, -5759, -6800, -8074, -5635, -5118, -5631, -8313, -6312, -6572, -5525, -6352, -9706, -5356, -8122, -6676, -8115, -9754, -5232, -11807, -8113, -11082, -8604, -5830, -12132, -9036, -11127, -6709, 6577, 2520, 4753, 4151, -6277, 5589, 1368, 4321, 3621, 3271, 1874, 1192, 3362, 3087, 5773, -3867, 3437, 3263, 3753, 6554, 33, 4131, 3884, 3777, 6045, 1716, 3607, 3956, 2241, 4189, 2850, 2007, 3377, 1367, 1161, 1951, -1589, 2473, 3501, -395, 715, -2136, 1248, 4026, 2129, 3597, 349, -3343, 2390, 4017, 5389, -34, 904, 1934, 3345, 6038, 2492, 4607, 4228, -325, 5722, 4891, 5595, 3828, 4094, 4293, 5306, 4624, -1214, 5181, 1633, 3550, 792, 2721, 3531, 821, -5316, 717, 4457, 1230, 1080, 1384, 2685, 3550, 4020, -580, 2553, 2205, 205, 4954, -2816, 1369, 590, -8658, 4742, -1698, -1211, -629, -6616, 3828, -646, -3831, -237, -7037, 2574, -273, -4698, 467, -3754, 2042, -103, -5349, 849, -1731, 1984, 182, -8257, 951, -381, 1267, -129, -15880, 728, 94, 47, -1664, -9613, -14, -844, -405, -4780, -6293, -1484, -3930, -408, -5712, -3936, -4110, -1411, -383, -5165, -3535, -12188, 935, -295, -5321, -4553, -5474, 1539, -921, -1715, -3578, -2731, 969, -1541, 604, -1873, -1981, -490, -371, 1661, -1224, -2605, -2349, 191, 1867, -915, -4072, -4724, -641, 1362, -614, -5444, -7437, -1715, 46, -997, -7221, -4130, -770, -2305, -2440, -4308, -2677, -259, -4370, -3465, -1358, -2415, -715, -2586, -2698, -199, -2647, -834, -516, -1834, -588, -2857, -569, 258, -1793, -2251, -2194, -1192, -898, -1937, -2191, -852, -2583, -7152, 351, -1356, 102, -3698, -2950, 1852, -1932, 359, -6144, -1220, 1854, -2172, 55, -6653, -2009, 546, -1185, -340, -2419, -4113, -1290, -1150, -478, -1239, -6890, -2098, -2300, -959, -1842, -9870, -3081, -3299, -2614, -4334, -6524, -5286, -2315, -6323, -8689, -6324, -7051, -1389, -9340, -7912, -11485, -6039, -1331, -5992, -8125, -7089, -4737, -2125, -3981, -10595, -4020, -4177, -3806, -3357, -10943, -3272, -5259, -6807, -3837, -5883, -3671, -7274, -11253, -4242, -4281, -4544, -3604, -11765, -3483, -4209, -5169, -1853, -10870, -3008, -4896, -5876, -1572, -6055, -3923, -5510, -7833, -2223, -4625, -8226, -5841, -12540, -3583, -5274, -6509, -6567, -8375, -5407, -8003, -3287, -8715, -6207, -7424, -13138, -2446, -9753, -5663, -9630, -15199, -2672, -7218, -6661, -6037, -12704, -3539, -6174, -10491, -3939, -8698, -4719, -5061, -8431, -3339, -7629, -5801, -3775, -6080, -3854, -8518, -6103, -3128, -5811, -5276, -7916, -5332, -3191, -6563, -6015, -7152, -4632, -3752, -7412, -5063, -9671, -4680, -4701, -7650, -4302, -9953, -5723, -6167, -7995, -4104, -6363, -8287, -8535, -10190, -4399, -5858, -9631, -15346, -16341, -5128, -6659, -6771, -9534, -9119, -6612, -7005, -5858, -6761, -7614, -10632, -5834, -6800, -5861, -5931, -9280, -4667, -11591, -5616, -4315, -6135, -4309, -8330, -5613, -3928, -5865, -4985, -5460, -6193, -6200, -8553, -6508, -7937, -3343, -9220, -7479, -7092, -7098, -3815, -7377, -7211, -10560, -7407, -4573, -4819, -7566, -10829, -9354, -4967, -4005, -9157, -7836, -11251, -4939, -4060, -12517, -7841, -9124, -5106, -4032, -9702, -9763, -8266, -5876, -3708, -8169, -12969, -8955, -7321, -4019, -8001, -13153, -12277, -7778, -5533, -8327, -10652, -9170, -6266, -8421, -8485, -7668, -6262, -5238, -12272, -9176, -5981, -5445, -4819, -11447, -10176, -5855, -6189, -5005, -9051, -7100, -7117, -8724, -5961, -11311, -5790, -8166, -15544, -6816, -9360, -5149, -8190, -8935, -5866, -9914, -6606, -9288, -12789, -10198, -444, -785, 22, -512, -111, 3825, 3700, 4011, 3732, 4105, 5934, 5876, 6050, 5867, 6151, 6562, 6530, 6678, 6554, 6749, 5860, 5810, 6005, 5934, 6042, 3714, 3491, 3871, 3867, 3881, -362, -1720, -451, -332, -462, -8244, -5334, -9966, -11060, -13928, -14965, -3825, -7231, -7838, -7538, -14237, -5644, -11454, -9635, -12447, -11333, -7218, -10735, -7740, -14281, -7785, -7484, -7030, -8134, -10768, -7984, -8501, -5343, -10237, -8640, -10149, -11186, -5127, -16213, -8201, -9637, -11594, -6077, -11188, -8957, -7394, -11445, -8346, -8459, -9894, -6577, -12171, -11157, -7507, -9402, -7244, -8254, -10331, -7807, -8790, -9451, -6069, -11115, -9174, -9743, -15000, -5165, -15623, -9049, -13810, -14946, -4951, -14153, -7619, -17394, -12244, -5271, -10076, -7398, -15090, -10956, -6246, -8342, -8767, -16558, -10643, -7892, -8455, -11276, -11013, -12434, -9863, -11098, -10564, -8306, -14245, -11683, -14496, -10210, -7352, -10358, -11766, -9902, -11844, -7797, -8521, -9587, -9240, -12672, -9598, -7539, -8180, -10056, -9348, -11558, -6969, -8082, -10771, -7471, -10510, -7045, -8843, -10586, -6675, -9127, -8457, -8768, -9414, -6932, -8309, -12611, -7940, -7554, -8612, -8127, -10569, -7552, -6501, -11995, -8345, -8661, -7566, -6721, -11127, -8660, -8710, -7776, -8403, -9893, -9024, -10124, -8184, -9859, -9545, -8899, -13021, -8806, -8623, -9544, -8291, -12631, -9539, -8508, -10086, -8184, -10718, -11079, -9891, -10988, -8798, -9846, -15501, -12770, -12005, -9506, -9090, -11859, -16988, -13076, -9577, -8205, -10545, -15281, -12434, -9458, -7601, -10825, -15101, -10698, -9846, -7697, -9290, -15813, -9752, -11370, -8616, -8167, -14591, -9649, -15588, -9597, -8495, -15462, -9906, -14673, -9892, -9926, -20536, -9793, -11426, -11057, -10986, -12734, -9231, -10131, -14054, -10780, -10743, -8703, -9892, -13703, -10864, -10543, -8545, -10911, -13096, -11370, -11418, -9104, -13976, -11827, -11626, -12918, -11025, -13271, -9958, -11491, -14768, -15232, -11312, -9615, -11615, -13200, -12779, -11637, -10649, -12531, -11272, -11775, -13881, -10788, -13604, -10618, -12568, -17230, -9775, -13103, -10832, -13373, -17598, -9893, -12065, -11959, -13262, -15866, -11391, -11454, -14518, -13114, -14350, -13728, -11407, -14804, -13246, -14622, -13285, -11845, -13064, -12030, -18307, -11760, -12159, -12305, -10412, -15123, -6324, -9477, -9400, -7057, -5710, -6352, -8487, -9278, -5078, -6096, -6298, -7707, -8482, -4442, -8448, -5661, -7246, -8358, -4752, -12692, -5302, -6206, -10007, -5788, -7182, -6166, -4983, -13270, -7494, -5273, -8510, -4454, -10594, -9438, -4780, -10193, -4690, -8615, -10919, -5125, -11052, -5489, -7798, -13036, -5854, -12236, -6499, -7745, -7401, -6635, -10632, -7170, -7794, -4840, -7557, -11145, -7431, -7733, -3910, -8096, -11765, -8948, -8494, -4135, -6962, -9891, -12542, -10049, -5225, -5766, -10963, -10163, -8393, -7226, -7008, -9025, -7379, -6072, -8597, -9535, -13454, -7980, -10483, -10619, -10454, -524, -357, -673, -521, -913, 3774, 3850, 3806, 3801, 3726, 5896, 5951, 5941, 5949, 5967, 6539, 6579, 6562, 6618, 6666, 5850, 5857, 5818, 5968, 6006, 3680, 3600, 3535, 3900, 3852, -704, -1039, -1074, -41, -442, -20425, -13137, -8880, -7008, -7180, -7676, -7249, -9812, -10616, -7360, -10279, -5481, -10821, -11285, -6744, -11031, -5069, -9065, -12055, -6518, -9991, -6225, -8756, -16333, -8667, -10592, -8419, -8312, -11250, -10011, -12191, -13430, -7967, -10377, -10608, -12739, -13080, -6812, -11457, -12300, -13509, -10314, -6313, -16158, -13876, -18989, -8759, -6995, -16806, -12813, -11600, -7944, -8763, -18811, -7810, -8523, -8087, -8626, -13671, -5455, -7530, -9310, -6986, -10603, -4667, -7855, -10926, -6627, -10213, -5114, -9406, -10426, -7630, -10276, -6652, -10178, -9082, -9365, -9640, -9105, -8955, -8049, -10069, -9361, -12141, -8768, -8044, -10018, -10155, -15871, -8742, -9890, -9962, -13161, -22128, -8200, -13833, -10789, -16792, -13824, -8273, -10713, -12965, -14624, -10183, -8548, -10172, -10605, -20387, -7962, -7851, -11897, -8350, -13740, -6838, -7172, -13924, -7292, -11677, -6817, -7315, -12211, -6859, -11522, -8153, -8547, -10846, -6858, -11643, -11284, -10893, -10119, -7332, -10993, -11217, -11394, -10115, -8360, -10006, -9632, -11033, -10993, -9848, -9822, -9397, -11758, -12169, -11656, -11314, -9647, -10253, -11377, -15028, -17323, -9926, -8792, -9976, -15320, -14192, -10389, -8646, -9355, -11446, -12505, -11423, -9549, -9778, -10204, -13602, -12870, -11143, -11814, -10021, -18248, -12820, -12849, -14717, -10517, -16157, -11201, -13626, -10610, -12078, -13136, -9927, -13163, -8579, -14304, -11833, -9257, -12540, -7856, -12246, -10955, -9144, -12407, -8209, -10861, -10350, -9797, -13195, -9967, -10891, -10379, -11896, -15556, -14905, -11801, -11591, -19418, -16477, -13344, -11845, -15351, -14372, -14073, -11411, -10850, -18659, -12416, -13199, -12060, -10790, -15823, -12264, -12718, -14280, -12046, -18986, -12902, -11598, -15084, -12664, -17066, -13984, -10396, -15153, -11569, -16303, -14781, -9857, -17401, -11389, -22830, -13452, -10185, -27068, -12151, -13558, -11746, -11330, -16623, -13653, -11224, -11074, -13063, -14198, -16091, -10707, -11621, -15303, -13355, -14189, -11493, -13829, -17195, -14040, -11965, -13852, -18027, -14642, -17286, -11045, -17219, -15206, -12429, -22284, -10583, -15085, -14255, -5111, -8181, -6549, -4897, -8234, -8490, -18312, -7810, -5765, -17195, -9800, -10653, -8301, -7841, -9189, -8646, -14834, -8803, -9710, -7281, -9213, -10024, -8625, -9340, -7338, -8926, -7689, -7824, -9330, -9147, -8812, -8023, -6553, -11359, -13026, -9700, -9056, -5691, -13529, -8406, -8745, -9062, -5610, -9201, -6813, -7212, -9078, -5853, -7526, -6881, -7424, -9496, -6434, -7064, -7710, -9464, -9887, -8019, -8062, -9180, -11192, -8688, -9004, -14243, -11558, -10074, -6315, -7134, -10315, -9984, -10918, -5924, -6393, -10145, -11123, -9806, -6673, -6775, -7294, -7563, -10028, -6767, -6627, -6054, -8211, -673, -269, -153, -410, -462, 3658, 3899, 3790, 3794, 3863, 5808, 6013, 5839, 5920, 5990, 6444, 6660, 6471, 6571, 6643, 5689, 5989, 5790, 5895, 5987, 3325, 3884, 3647, 3761, 3929, -1754, -187, -639, -440, 50, -8211, -8616, -11834, -10163, -5789, -7590, -10466, -8996, -13313, -6715, -11943, -10600, -9727, -8406, -6591, -9097, -9376, -8364, -7190, -6668, -9015, -8462, -8907, -8539, -6303, -8460, -7343, -9806, -10953, -6011, -7663, -6472, -10571, -9496, -6413, -6880, -6655, -11790, -8082, -7031, -6522, -8223, -11268, -8737, -7692, -7118, -10117, -11663, -12041, -8448, -9533, -9593, -15313, -12392, -9478, -18602, -8816, -11429, -8895, -12054, -11179, -8822, -9217, -7784, -14643, -9564, -9603, -8496, -7855, -9020, -8861, -10482, -8191, -8705, -7733, -9082, -10202, -8062, -11167, -8627, -11604, -8907, -8473, -16546, -10658, -11858, -7812, -9627, -9355, -8890, -8190, -7538, -10633, -7706, -7730, -6849, -8080, -9108, -7559, -8057, -6720, -9112, -7655, -8306, -9830, -7647, -9889, -7064, -9763, -12763, -10007, -9471, -7045, -11985, -12538, -15469, -8243, -7479, -13782, -13003, -15736, -7151, -8434, -12474, -20353, -12992, -6507, -9800, -11537, -12301, -10376, -6345, -10815, -11652, -9995, -9366, -6590, -10528, -12500, -9541, -10271, -7098, -9549, -13197, -9750, -10632, -7794, -8985, -12956, -10146, -8248, -8486, -9275, -12169, -11215, -7216, -8669, -10398, -11343, -13727, -7454, -8569, -11756, -11006, -18229, -8521, -8946, -12224, -11114, -19315, -9737, -10248, -12077, -11015, -19702, -10458, -12370, -12977, -10475, -14351, -10803, -11973, -16841, -9938, -11685, -11222, -10314, -13740, -9705, -10829, -11841, -9569, -11818, -10113, -11856, -11386, -9666, -11946, -12096, -16134, -10401, -10214, -12794, -20737, -13145, -10467, -10065, -13294, -10923, -11149, -11854, -9264, -13455, -8919, -11022, -12777, -9041, -13589, -8787, -12370, -11861, -9846, -15421, -10085, -14716, -11869, -11867, -17826, -12719, -11822, -12688, -15281, -12752, -15662, -10433, -12735, -18034, -11246, -19506, -10818, -12305, -15670, -11170, -13583, -11790, -12741, -14857, -11642, -11180, -10749, -14781, -16906, -11816, -10866, -9400, -21844, -15369, -11386, -12020, -8669, -18289, -11859, -10840, -13480, -8294, -17206, -10414, -10607, -13398, -8217, -16096, -10103, -10802, -13232, -8573, -14197, -10582, -11426, -13681, -9469, 13787, 14482, 4978, 9252, 11837, 13142, 13944, 4781, 8623, 11115, 11041, 12305, 4122, 6636, 8769, 6500, 9549, 4653, 3113, 4014, 364, 6117, 5897, 1273, -1449, 4622, 4026, 5912, 1807, -4079, 4377, 4233, 4397, 762, -2972, 2131, 4306, 2088, -94, -1821, 731, 3764, 2965, 2827, 2767, 3262, 3394, 4029, 4634, 4859, 3406, 3613, 4412, 5302, 5672, 1375, 4227, 4558, 5029, 6061, -3400, 4918, 4488, 3616, 6377, -5761, 5197, 3982, 355, 6282, -1053, 4744, 2957, 363, 5315, 1144, 3424, 2115, 2646, 3131, 1395, 1044, 2637, 3056, 656, 956, -3300, 3401, 2110, 1208, 105, -6609, 3508, 681, 1312, -4040, -3827, 2964, 2051, 978, 1360, -3994, 2019, 3680, 1426, 4160, -4790, 653, 4368, 1589, 4987, -2691, -1786, 4311, 977, 4326, -936, -2880, 3675, -26, 1433, -152, -260, 2708, -1196, -3895, -336, 944, 2077, -1140, 1532, -1804, 1016, 2018, -230, 1660, -1298, -2, 1662, -783, -759, 725, -2655, 492, -2131, -5217, 1363, -4750, -1417, 88, -5661, 1034, -2778, -3746, 1317, -4242, 311, -3574, -8503, 817, -373, -340, -2916, -7619, -68, 2394, -443, 58, -4328, 1397, 3818, -149, 1292, -2863, 2312, 3943, -590, 1294, -1452, 1738, 2645, -2903, 176, -1242, -587, -913, -3009, -2557, -3482, -6100, -3543, -97, -9954, -8191, -6916, 150, 820, -8630, -3025, -6507, 1377, 444, -7535, -2068, -5282, 1773, -1119, -5293, -1568, -3256, 1565, -4468, -4636, -860, -2027, 631, -6159, -6005, -239, -1157, -1430, -4037, -5551, 152, -397, -5342, -3689, -2472, 10, 41, -3431, -3131, -596, -819, -40, -1561, -2261, 413, -2281, -549, -1152, -1936, 780, -3916, -1306, -1405, -1886, 549, -3835, -2180, -1917, -1818, -387, -2792, -3422, -2357, -2055, -2215, -2501, -6241, -2373, -2782, -4704, -3033, -8393, -2033, -4217, -6929, -4108, -6246, -1681, -8068, -11620, -5597, -7465, -1732, -6024, -6720, -8259, -13971, -2807, -3209, -4535, -10705, -11232, -6537, -2961, -4340, -6189, -8549, -6525, -4973, -5306, -4475, -6917, -3450, -8409, -6693, -4114, -8079, -3555, -4950, -7082, -4463, -11262, -6691, -4196, -5694, -5222, -4124, -9836, -4855, -3625, -6954, -1699, -5164, -4765, -1928, -14286, -663, -4169, -4080, -956, -6668, -472, -3927, -4223, -808, -4050, -927, -4054, -4659, -1518, -3273, -2043, -4659, -4806, -2857, -3485, -4026, -5012, -5753, -3289, -4506, -7114, -4157, -8458, -2383, -6814, -8776, -3046, -10124, -1919, -9729, -8006, -2438, -8481, -2476, -7223, -8942, -2651, -8119, -4495, -6713, -10699, -3729, -9751, -9391, -8462, -9084, -4869, -12085, -14189, -11420, -7217, -4537, -9290, -6958, -10445, -5602, -3890, -8713, -2884, -7885, -5075, -4081, -6824, -993, -5433, -6297, -5445, -6813, -581, -4298, -11537, -8013, -10279, -1352, -4068, -9035, 8985, 6518, 7563, 8877, 9046, 8234, 6594, 7027, 8347, 8532, 6331, 5677, 5772, 6952, 6924, 5024, 981, 5111, 5260, 4061, 3806, 2037, 5742, 3558, 440, 967, 4386, 6629, 2409, -783, -883, 3656, 7114, 1283, -349, 2952, 2413, 7141, -2137, -67, 5129, 3158, 6509, -1857, 1100, 5734, 3958, 4491, -2596, 2334, 5404, 4255, -814, -4981, 2856, 5080, 4016, 3871, 763, 3031, 5362, 3360, 5969, 2332, 2827, 5563, 3133, 6510, 2666, 2052, 5428, 3497, 6210, 2579, 1018, 5290, 3136, 5414, 2374, 388, 5181, 962, 4383, 1588, 226, 4666, -8481, 3193, -1021, -410, 3159, -2200, 1715, -119, -2705, -842, -2369, 539, 2781, -10846, -1682, -8065, 649, 3237, -2652, 2167, -6821, 272, 1411, -187, 3126, -4139, -1393, -1419, 809, 2593, -188, -2666, 1660, 526, 549, 1751, -2642, 2880, -2175, -3542, 2355, -1774, 3630, -3843, -7162, 2117, -33, 4132, 594, -10058, 1187, 935, 3783, 1152, -5997, -1100, 903, 2279, -742, -2986, -9530, -343, -685, -1943, -1738, -800, -4534, -5764, -203, -1451, 1532, -3386, -6807, -385, -1934, 2482, 154, -5475, -748, -492, 2676, 1176, -4795, -405, 1741, 2257, 901, -4046, -832, 3050, 1426, -528, -2648, -2209, 3695, 768, -3119, -495, -2869, 3888, 478, -7138, 1492, -1466, 3557, -528, -7174, 2892, -1106, 2438, -2650, -3884, 3745, -2364, -20, -2147, -2024, 4007, -3977, -5755, -2340, -122, 3501, -3717, -2271, -6275, 838, 1949, -2174, -28, -2191, 445, -1442, -698, 540, -615, -1399, -6006, -537, -92, -1203, -4365, -1382, -2154, -1656, -2113, -3715, -389, -7872, -2267, -1547, -2291, -928, -3354, -1762, -1495, -2020, -2464, -599, -1845, -2575, -2336, -4021, 372, -2314, -4497, -2622, -4010, 282, -2952, -6128, -2952, -3405, -535, -3805, -5759, -4534, -3411, -1497, -3776, -4343, -9672, -3453, -2263, -3392, -3115, -3355, -2792, -3364, -4273, -2577, -1414, -2260, -5289, -5577, -3117, -1496, -2341, -8298, -4319, -5022, -3242, -2912, -10586, -3495, -6735, -4189, -3526, -8272, -2519, -5886, -3111, -3694, -6397, -1252, -4882, -4093, -3443, -5273, -804, -4317, -8079, -3204, -5308, -1356, -5169, -5436, -3218, -6950, -2610, -7845, -5021, -3555, -7503, -3948, -7689, -5972, -4387, -6617, -5066, -6911, -3284, -5760, -8977, -5918, -6541, -1693, -5689, -10069, -5800, -5469, -1504, -3599, -6215, -5202, -4553, -2416, -2353, -5588, -4994, -3747, -4273, -2588, -5373, -5430, -3370, -6208, -5044, -4717, -6317, -4029, -6065, -5950, -4743, -6737, -6835, -5706, -3061, -5988, -6782, -8754, -7073, -2705, -8530, -6424, -4552, -7345, -4113, -12075, -5777, -3244, -3463, -6001, -15697, -6055, -2947, -1629, -6014, -9874, -7633, -2862, -1191, -6825, -7375, -9082, -2771, -1903, -6828, -6079, -12057, -3123, -3750, -5684, -5858, 7254, 3780, 5352, 8324, 7066, 7171, 3086, 5094, 7895, 6213, 6727, 851, 4354, 6526, 3843, 5390, -2087, 3193, 4117, 3207, 2262, -2314, 1654, 2565, 3126, 2013, 745, -46, 3361, 1325, 4042, 3062, -104, 3836, 2767, 4176, 3288, 1227, 4010, 3783, 3360, 1017, 1727, 3485, 2176, 2138, -2184, 1294, 1347, -6664, 531, 1541, -80, -1763, 1195, -1041, 2582, -3103, -380, 1419, -1732, 2633, 1146, -1351, 1509, -3214, 1956, 3383, 707, 3109, -4593, 393, 3552, 2910, 2673, 1140, -2294, 1842, 3182, 2083, 3269, -1350, -478, 1649, 4232, 3696, 858, 1509, -3165, 5058, 2523, 1699, 2458, -4177, 4411, -2484, 2717, 2408, -2617, 2814, 58, 3860, 2037, -6038, 2143, 3316, 4150, 1901, -3622, 2863, 4118, 3282, 2190, -1326, 3523, 3616, 979, 2192, -1138, 3638, 1956, -3769, 1246, -1925, 2589, -1005, -4772, -664, -3082, 144, -4808, -5487, -1236, -3921, 1631, -3920, -4314, -289, -1963, 3125, -997, -878, 536, 568, 3125, 1100, -87, 1132, 2375, 2481, 2173, -588, 916, 3384, 1815, 2460, -1252, -670, 3538, 1108, 2340, -1871, -4154, 2703, 850, 1950, -2672, -4339, 499, 1269, 1169, -3861, -2132, -4124, 1562, 169, -6132, -261, -2596, 1437, -843, -2396, 722, -781, 871, -1632, -1151, 484, -292, -168, -807, -2771, -188, -270, -1242, 784, -14377, 384, -752, -1214, 1457, -2334, 652, -2146, -1095, 669, -88, -423, -4151, -2159, -1953, 663, -2218, -4541, -2894, -2170, 348, -3093, -5154, -892, -404, -488, -3708, -4906, 109, -283, -802, -2311, -3105, -386, -1719, -713, -1343, -2995, -2943, -6075, -972, -1948, -5119, -4035, -6812, -2209, -3295, -11489, -1136, -4506, -5033, -2868, -7918, -847, -5278, -7842, -2304, -3639, -2461, -4408, -11924, -2104, -1206, -4600, -2108, -7483, -1639, -277, -4610, -1091, -4659, -1884, -464, -3838, -1260, -5409, -3828, -1361, -2961, -2613, -11108, -7331, -2289, -3521, -5412, -5253, -5834, -2362, -7268, -7961, -3699, -5927, -1680, -7667, -6690, -4054, -7101, -1061, -4319, -6204, -4494, -5229, -805, -4567, -6323, -4150, -3547, -893, -8945, -6568, -4867, -2577, -1066, -7158, -7404, -8847, -2021, -890, -4696, -10328, -8292, -2006, -644, -5885, -7639, -5119, -2603, -1086, -10119, -4971, -4890, -3480, -2684, -5412, -4289, -6038, -4012, -5439, -4182, -4826, -6486, -4081, -6591, -4286, -6108, -5920, -4195, -6369, -4245, -8101, -5814, -4660, -6888, -4094, -8298, -5812, -5539, -7734, -4961, -5751, -5919, -6810, -8659, -8082, -4912, -6634, -7885, -10439, -10783, -5265, -8314, -7614, -11534, -7287, -5005, -10458, -6328, -7728, -6504, -3880, -9864, -5156, -6502, -6430, -3550, -9472, -4517, -7652, -6597, -4643, -8696, -4595, -11083, -7127, -7788, -6724, -5271, -8046, -8521, -10178, -5892, -5092, -6057, -10780, -9513, -5852, -2958, -4130, -5138, -9591, -4239, -4771, -4595, -3537, -7593, -4988, -6791, -6457, -3617, -5186, -9184, -8984, -9752, -5332, -3757, -9695, -8023, -9904, -8192, -3567, -7496, -5663, -6636, -10251, -4988, -10139, -4265, -5209, -8259, -7312, -10026, -4064, -4842, -5919, -6798, -9178, -5491, -4279, -5506, -4718, -6877, -7453, -4436, -4938, -5641, -10793, -7051, -8165, -5146, -6237, -5783, -3706, -5657, -6567, -6163, -7552, -5332, -4544, -7934, -4428, -7473, -7132, -2816, -3669, -7263, -5272, -6182, -5161, -8287, 1297, 1380, 382, 427, 1207, -5695, -8279, -4121, -8316, -6680, 8561, 8618, 8700, 8553, 8437, 13004, 13007, 12983, 12916, 12893, 15159, 15134, 15101, 15057, 15049, 15814, 15765, 15745, 15709, 15700, 15123, 15045, 15056, 15018, 15001, 12934, 12800, 12884, 12824, 12786, 8481, 8155, 8507, 8337, 8234, -6212, -3159, -3672, -8783, -6067, 355, 1573, 140, 692, 704, -6870, -5118, -3656, -13381, -7976, -3363, -8489, -2432, -4041, -3085, -13187, -6128, -4945, -14447, -7311, -7663, -3928, -4995, -7782, -6564, -11356, -5002, -6850, -10812, -11615, -6916, -5388, -8674, -8337, -12006, -7994, -4573, -8011, -5441, -11762, -8180, -4139, -6462, -4421, -16667, -10089, -4886, -7481, -4405, -7607, -13750, -5921, -8591, -4365, -5118, -9873, -7548, -9934, -5196, -5328, -8781, -10656, -14920, -6792, -7727, -9037, -11447, -11389, -8594, -14847, -9884, -10947, -8958, -9617, -6934, -9289, -10973, -8780, -9326, -5223, -7221, -8742, -8512, -9119, -5599, -6083, -6824, -7067, -9787, -7035, -6014, -5755, -6035, -12388, -7980, -7264, -5557, -6080, -13525, -8373, -10795, -6081, -7427, -10104, -7020, -11727, -7375, -11093, -7431, -5927, -8775, -8995, -13316, -5955, -5824, -8544, -9358, -9168, -5567, -6647, -11194, -9332, -7582, -5880, -8291, -12999, -10338, -6506, -6668, -9652, -8827, -10795, -6129, -8010, -10285, -7865, -9139, -6920, -9528, -11676, -7471, -8425, -8858, -9571, -11366, -7427, -8712, -10255, -9618, -10512, -8751, -8954, -9471, -11316, -11523, -14983, -9112, -8722, -16038, -13343, -10452, -10208, -9099, -11641, -9484, -7683, -10772, -11344, -9792, -7278, -7034, -11116, -15446, -10288, -6693, -7359, -16187, -12218, -11828, -7788, -7894, -9483, -11724, -10789, -12571, -8252, -6930, -13333, -10655, -11221, -8965, -6238, -12123, -12075, -8249, -10092, -6645, -9684, -12421, -8088, -9963, -7965, -8294, -11999, -9632, -8837, -10239, -7443, -12000, -13315, -8706, -11505, -7439, -12416, -14043, -10646, -10071, -8528, -13571, -10865, -15017, -8877, -10497, -11921, -8804, -11247, -7730, -13069, -10791, -7478, -11828, -6398, -15423, -12001, -7192, -20448, -5201, -16101, -13201, -8376, -13641, -4585, -14289, -9748, -13001, -13041, -4645, -11616, -8328, -11523, -14627, -5170, -11110, -8451, -8356, -13502, -5950, -12049, -9883, -7761, -10373, -7152, -12526, -12659, -8455, -8713, -9156, -11939, -16142, -9589, -8459, -12138, -11687, -14965, -9961, -10498, -4366, -6670, -6268, -6777, -7229, -6131, -9281, -8240, -7699, -8929, -7196, -10164, -9029, -7444, -11207, -7603, -9629, -8669, -5848, -6033, -7414, -11634, -7184, -5213, -4398, -8612, -8062, -6308, -5370, -3304, -13810, -6177, -7408, -4579, -2825, -7811, -5579, -7973, -3825, -3546, -6430, -4992, -8108, -3809, -4781, -4527, -4429, -6506, -4269, -4491, -4848, -3487, -4891, -7768, -3571, -7588, -2584, -3465, -8846, -7026, -5220, -5205, -4060, -11604, -5445, -2622, -4630, -3540, -3661, -13629, -16253, -13092, -4810, -7932, 231, 618, -82, 543, 843, -6248, -7054, -4917, -3788, -8231, 8605, 8622, 8675, 8654, 8498, 12929, 12970, 12956, 12954, 12918, 15061, 15099, 15067, 15070, 15063, 15710, 15741, 15699, 15705, 15706, 15022, 15042, 14988, 14999, 15003, 12839, 12842, 12761, 12787, 12794, 8398, 8357, 8181, 8271, 8320, -6355, -9827, -5114, -8031, -11445, 742, 449, 897, 548, -492, -6196, -9566, -10589, -7494, -5073, -8525, -3144, -3699, -3026, -2223, -5070, -7672, -10938, -5874, -3889, -3862, -8293, -8123, -6864, -3393, -7232, -5562, -14238, -6677, -5029, -8078, -4318, -11472, -7169, -5990, -6359, -5438, -12955, -9248, -7282, -4699, -6061, -8298, -7138, -7975, -4437, -5255, -4977, -7199, -7408, -4404, -5040, -4346, -6498, -8164, -4424, -5932, -5922, -6287, -13094, -5022, -6947, -8673, -7353, -11799, -6385, -7265, -8889, -6892, -9465, -7244, -8190, -8641, -5854, -8326, -7533, -11441, -8925, -6478, -7704, -8121, -12430, -8424, -8580, -8303, -8555, -9459, -7952, -11706, -10874, -8801, -7781, -7932, -11601, -11746, -9392, -6681, -8702, -9492, -10771, -8897, -6269, -11134, -7989, -10751, -7531, -6453, -13250, -7211, -8926, -7404, -7610, -10312, -7486, -7607, -8600, -12793, -8181, -8674, -7479, -10202, -9162, -6921, -8904, -7697, -11286, -6098, -6608, -7722, -7804, -11937, -5398, -6998, -6592, -8510, -11931, -6006, -7656, -5732, -10168, -11643, -7700, -7865, -5153, -9670, -11404, -9945, -7621, -4734, -7718, -11938, -10592, -7930, -4469, -6955, -14370, -10031, -9183, -4556, -7329, -15667, -10284, -10498, -5050, -8892, -12373, -11084, -10118, -5802, -11839, -10744, -9393, -8932, -6557, -10599, -9939, -8174, -8555, -6929, -8379, -9147, -8371, -9724, -6772, -7539, -8646, -9213, -12563, -6454, -7698, -9055, -8331, -11230, -6225, -8717, -10672, -6809, -10830, -6241, -10608, -14785, -6331, -14765, -6812, -12383, -14279, -7241, -12980, -8388, -10530, -11516, -10115, -9969, -11681, -8633, -11517, -17696, -8967, -17098, -7730, -9999, -15671, -8469, -13164, -7734, -8058, -16219, -8806, -10957, -8309, -7622, -12298, -10108, -10766, -8402, -8250, -10221, -11010, -13232, -7994, -8410, -9360, -11065, -14546, -7912, -7768, -9280, -10873, -10923, -7989, -7800, -10287, -9905, -10087, -8439, -9129, -12060, -9325, -10332, -10265, -12743, -9949, -9270, -9962, -11686, -19639, -8180, -9033, -9152, -9150, -14519, -7532, -8746, -9194, -8408, -10822, -6541, -4087, -5366, -7217, -12242, -8318, -3539, -5595, -5565, -10054, -10115, -3416, -6678, -5715, -9487, -10487, -3463, -9138, -5286, -11194, -7805, -3598, -8649, -4087, -14458, -5912, -3513, -5294, -3330, -15491, -5595, -2995, -4509, -2842, -9703, -5078, -2744, -5044, -2878, -6441, -4684, -3510, -5504, -3700, -5324, -5093, -4428, -5770, -3850, -7746, -5534, -4368, -9431, -3672, -6965, -5120, -3532, -8148, -3980, -5835, -12972, -4140, -6914, -7836, -3209, -4326, -4421, -2653, -4978, -4388, -5867, -4333, -6509, -8827, 759, 1307, 1420, -92, 441, -7569, -6729, -8428, -3816, -5727, 8547, 8521, 8509, 8797, 8689, 12911, 12937, 12918, 13017, 12962, 15045, 15072, 15054, 15101, 15063, 15687, 15707, 15695, 15716, 15688, 14985, 14996, 14991, 14996, 14973, 12773, 12778, 12783, 12769, 12751, 8257, 8274, 8289, 8231, 8207, -5729, -13222, -9847, -7725, -6606, 365, -216, 347, 366, 774, -5794, -4154, -13970, -10100, -11214, -3024, -1610, -5056, -3311, -4302, -8556, -5486, -9925, -10494, -10449, -8816, -15377, -7035, -9377, -10897, -9692, -6966, -10351, -7962, -7623, -6415, -5614, -6263, -6224, -6176, -8085, -6004, -8928, -7974, -8482, -8961, -6683, -15713, -8733, -11044, -8909, -9524, -9595, -6530, -10027, -9220, -16761, -7156, -6052, -9278, -8183, -10191, -6519, -8056, -10499, -7503, -8314, -6524, -9726, -8568, -7912, -7454, -6168, -7788, -6564, -8006, -7323, -6360, -6623, -5660, -7513, -8958, -7956, -6270, -5558, -7624, -12761, -8830, -6275, -5664, -9072, -13250, -8080, -6211, -5807, -11441, -10268, -8066, -6481, -6255, -11688, -8512, -8791, -7602, -6731, -9345, -7804, -8950, -9074, -6544, -7603, -7631, -7568, -9252, -6544, -6215, -7159, -6531, -8562, -7341, -5194, -6266, -6163, -8140, -8458, -4865, -5520, -6092, -7987, -7760, -5326, -5329, -6243, -7926, -6852, -6405, -5870, -6721, -8345, -7595, -7663, -7234, -7119, -10125, -10775, -8350, -8534, -7286, -16410, -8787, -7965, -7840, -7968, -12117, -7281, -7110, -7247, -9360, -9899, -8670, -6584, -7114, -10510, -9248, -13548, -6732, -6288, -10753, -9136, -8383, -7539, -5229, -10635, -9847, -7519, -8798, -4756, -9004, -10133, -9215, -10716, -5047, -7250, -7926, -15045, -11737, -6079, -6478, -6366, -13869, -9279, -7261, -6801, -6041, -12884, -8079, -7599, -8272, -7054, -12862, -8067, -7855, -10268, -10148, -11724, -8568, -8570, -10879, -14031, -10273, -8699, -9357, -11814, -9495, -8848, -8366, -10098, -12661, -8400, -7876, -8351, -10997, -11791, -8652, -7701, -8922, -10359, -10201, -9356, -8575, -9593, -9505, -8288, -9822, -11194, -10080, -11126, -7323, -10529, -21742, -10828, -10949, -7205, -11905, -11172, -12073, -7210, -7450, -13675, -9491, -14562, -6110, -8045, -13884, -9622, -13397, -6723, -9438, -11220, -11368, -11545, -9052, -12156, -10030, -16389, -12288, -12561, -18890, -10493, -15268, -16791, -11629, -15410, -12913, -14502, -14921, -11217, -12042, -19888, -28647, 13098, 8550, 12481, 11510, 6595, 12477, 8828, 11738, 10975, 6030, 10405, 8846, 9290, 9300, 4418, 5407, 8596, 4699, 6340, 3498, 4144, 8868, 3899, 2446, 4495, 6787, 8970, 2932, 1036, 4904, 6608, 8465, 1355, 3923, 4740, 4907, 7665, 1149, 4657, 4591, 551, 6910, 744, 2513, 4346, 634, 6196, 1842, -279, 3940, 3736, 5306, 2460, 4698, 3741, 4214, 4093, 2261, 6028, 3943, 2999, 3252, 2051, 5861, 4558, -1126, 3221, 2513, 4490, 5250, -2272, 2371, 2501, 2731, 5767, 1238, 375, 1447, 3380, 5850, 1900, 2377, 1045, 3946, 5011, 2334, 3950, 2051, 3233, 2580, 3282, 3982, 2613, 1159, 159, 3710, 2869, 2481, 487, 1210, 3661, 1243, 1716, 2588, -657, 4677, 1926, -421, 3542, -546, 5690, 3141, -7300, 3727, 2018, 5486, 2751, 1503, 3443, 2021, 4042, 1177, 3537, 2839, 305, 2858, 2208, 3935, 2313, -2395, 2622, 2907, 3506, 1766, -2201, 820, 1286, 2877, 816, -25, -2138, -2230, 2460, -253, 1158, -185, 2089, 2181, -948, 1834, -429, 3619, 1837, -1815, 2181, -2963, 3555, 1253, -3382, 1436, -7497, 2318, -221, -1989, -2519, -3937, 466, -5658, -553, -383, 130, 109, -2147, -554, 2605, 1478, 993, 944, -327, 2950, 1038, 1962, 1665, 621, 1470, -1293, 2675, 1147, 637, -1902, -6527, 2557, -113, -766, -2756, -2414, 1072, -1280, -3066, -1732, 176, -407, -1687, -1358, -1275, 1793, 1532, -1903, 714, -738, 2727, 2283, -2128, 1424, -1013, 2830, 1480, -1826, 1085, -2187, 1872, -748, -1223, 504, -1724, -540, -3577, -1331, 302, -372, -3290, -3077, -2456, -212, 453, -1665, -2179, -2590, -1244, 769, -958, -2758, -1194, -2220, 646, -1298, -5466, -206, -3085, 298, -2484, -13396, 244, -3976, -448, -5072, -6577, 67, -3844, -1491, -15234, -3075, -866, -2785, -1116, -7562, -1541, -2665, -2528, -294, -7910, -1687, -5553, -3298, -160, -10161, -3578, -10016, -3192, -472, -3439, -5625, -9486, -2319, -951, -1201, -4550, -9342, -2459, -1431, -458, -4420, -6978, -3757, -1541, -854, -3911, -4840, -6298, -1450, -2480, -2853, -3829, -7433, -2031, -5517, -2518, -2354, -5552, -3672, -8558, -2856, -980, -3831, -4039, -6818, -3270, -177, -2357, -3496, -4436, -2980, 111, -1947, -5155, -3473, -2306, -187, -2633, -5752, -3380, -2078, -1182, -3664, -3089, -3429, -2692, -2826, -3918, -2817, -3812, -4573, -4250, -3465, -4590, -5220, -9117, -4231, -3124, -8516, -7993, -11830, -4338, -3576, -11939, -7717, -7077, -4823, -4840, -12315, -4104, -4608, -4103, -4752, -7408, -1875, -3730, -3127, -3489, -5600, -790, -4849, -3237, -3361, -3940, -662, -9472, -4932, -4740, -2668, -1493, -4366, -5298, -7908, -2498, -3603, -2126, -3150, -9119, -3642, -8609, -1767, -2772, -5899, -6106, -6767, -2754, -4208, -3280, -5059, 6690, -8153, 10131, 7048, -919, 6500, -1237, 9535, 7554, 1466, 5763, 2689, 7584, 8134, 2435, 4781, 4620, 3350, 8012, 1830, 5661, 5048, 658, 7105, 778, 6783, 4105, 3704, 5783, -74, 6618, 2593, 4285, 5187, 720, 5186, 2589, 3617, 5421, 1199, 4084, 2423, 1579, 5335, -518, 3879, 2804, -894, 4502, 692, 1989, 4329, 1791, 2961, 3354, 1889, 5035, 3692, 1175, 4608, 4214, 4861, 3955, 476, 5123, 4452, 4207, 2604, 1752, 4949, 2423, 3388, 1864, 3468, 3937, -2942, 2577, 4006, 4407, 2053, 2979, 2078, 5120, 4232, -451, 4465, 1539, 5069, 2721, -2834, 4398, -366, 4056, -1059, -4394, 3825, -1555, 2553, -3650, -4648, 3783, 984, 1518, 220, -2108, 4223, 1564, 1432, 1126, -416, 4287, 927, 1765, 985, -266, 3353, 180, 1171, 1319, -1422, 700, 323, -1087, 2497, -1730, -3577, 986, -4078, 3156, -379, -145, 804, -5633, 3189, 347, 692, -838, -2836, 3184, 591, 372, -3742, -1062, 3175, 815, 775, -4880, -1859, 2491, 1139, 1429, -2167, -6691, 487, 1412, 1693, -494, -3217, -4289, 1377, 2490, -297, -193, -6386, 972, 3451, -977, 1287, -4593, 571, 3687, -1970, 2053, -4635, 521, 3061, -3478, 2249, -3130, 572, 2009, -2216, 1942, -2060, 642, 1428, 431, 1191, -2079, 677, 1189, 1781, 15, -3089, 122, 430, 2063, -996, -816, -1523, -2164, 1360, -575, 1708, -3664, -6231, -374, 368, 2832, -4666, -355, -2308, 889, 2960, -3159, 1093, -1614, 588, 2495, -820, 1216, -287, -1047, 1888, -233, 463, 180, -5792, 1396, -1210, -1699, -456, -5831, 827, -1932, -4360, -1542, -3116, -181, -1081, -1611, -1293, -2754, -1835, -1012, -752, -892, -3009, -3416, -1665, -1331, -1022, -3744, -2976, -2081, -3307, -1008, -5304, -1919, -2296, -6978, -599, -9515, -1543, -2617, -2689, -324, -5503, -2134, -2837, -849, -552, -2105, -4034, -2991, -641, -1427, -987, -9344, -3313, -1334, -3026, -1507, -5572, -3958, -2143, -3900, -4232, -2728, -4591, -2131, -2097, -11497, -1606, -4683, -1188, -635, -4314, -772, -4588, -392, -95, -3143, 504, -5553, -420, -401, -3153, 1642, -12972, -1425, -1560, -3376, 2085, -5530, -3346, -3278, -3476, 1682, -3339, -6006, -4696, -2954, 318, -3931, -8714, -4326, -1709, -2490, -3776, -10887, -1777, -777, -10400, -1479, -12866, -745, -686, -5189, -826, -8513, -1537, -1478, -4025, -1742, -7835, -3353, -2888, -5665, -3837, -6347, -2788, -3952, -17953, -6267, -4056, -2692, -4012, -4997, -8544, -3186, -4337, -4604, -2943, -5270, -3660, -6473, -9815, -2948, -2994, -3978, -7759, -4141, -4830, -1837, -2409, -9588, -365, -8098, -1245, -1044, -7724, 1152, -7450, -1150, -518, -3907, 1373, -5088, -1650, -941, -1635, 501, -2392, -2714, -2385, -835, -1466, -920, -3973, 8763, 8553, -1506, 9043, 5045, 8329, 7818, 4856, 8679, 5189, 7124, 5235, 6475, 7547, 4899, 5539, -2724, 5978, 5518, 3051, 4243, 1960, 3948, 2257, -764, 3257, 2827, 3653, -4867, 3192, 1750, 1546, 4642, -1789, 4821, -503, -1688, 4092, 759, 4430, -877, -10154, 1867, 814, 540, 675, -6481, 292, -964, 1989, 2501, -5274, 1801, -2428, 5702, 3249, 984, 1939, -1699, 6847, 2841, 3143, 325, -4114, 7089, 2120, 3203, -449, -1716, 7005, 1932, 879, 1514, 1679, 6616, 1470, -1494, 1524, 2209, 5686, 383, 1209, -1306, 129, 4051, -917, 274, -2145, -4903, 1958, -3227, -10316, 421, -2018, 2525, -6570, 1371, 165, -7468, 4230, -1425, 3275, -1489, 652, 4741, 506, 3377, -3377, 3027, 3845, 1603, 2098, -3518, 3347, 845, 2379, -1130, -505, 2476, -1302, 2437, -2395, 1055, 832, 1731, 1313, -13, 1424, -1240, 1930, -1705, 66, 1181, -2536, -493, -10492, -1451, 1033, -3839, -1341, -10204, -4003, 1254, -2854, 2599, -4882, -4488, 1321, 1188, 3988, -429, -2851, 976, 3064, 4135, 1534, -2062, 521, 3641, 3510, 2383, -2765, 362, 3398, 2477, 2512, -4557, 551, 2803, 1501, 1934, -2537, 731, 2299, 1677, 334, -1009, 638, 1833, 3102, -2805, -1109, 447, 969, 4139, -2513, -2382, 332, 160, 4254, -556, -4855, 342, 1225, 3384, 230, -9011, 901, 2469, 1469, 344, -1342, 1682, 2800, -1616, -299, 1071, 1871, 2211, -4908, -1796, 1832, 1146, 841, -4058, -3723, 1510, -467, -884, -1918, -4119, 501, -1711, -2314, -531, -2890, -225, -1369, -3129, -539, -2156, -60, -1479, -3522, -2704, -2097, -308, -2167, -4943, -4489, -2310, -2024, -1823, -6980, -1326, -2668, -4405, -951, -3549, -759, -3620, -2580, -708, -1778, -1286, -4578, -2603, -1275, -1417, -1385, -4056, -6586, -2563, -2143, -1543, -3927, -5338, -3925, -3430, -2858, -3746, -2880, -4848, -3057, -6455, -3291, -3926, -5108, -1669, -7064, -3807, -11714, -3433, -786, -2551, -3780, -5750, -2579, -553, -530, -2358, -3964, -3609, -1075, 313, -1908, -4017, -7855, -2455, 274, -2862, -4266, -6328, -4246, -274, -4876, -3763, -3283, -5502, -747, -4153, -2845, -1491, -8382, -1394, -2877, -2209, -403, -9169, -2948, -2452, -2235, -95, -4587, -3623, -1834, -3028, -594, -2742, -2108, -1247, -4172, -2123, -1891, -1002, -1352, -4534, -5646, -1920, -289, -2096, -4388, -7798, -3139, -214, -3092, -5273, -5865, -6345, -1249, -3905, -8090, -9013, -7257, -4051, -3610, -4638, -7809, -5399, -7985, -2443, -2722, -4250, -5762, -4407, -1562, -2710, -3316, -6933, -2448, -1343, -3403, -2966, -9019, -1554, -1776, -3475, -3180, -8528, -1840, -2636, -4344, -4117, -2747, -3535, -3723, -9379, -4126, -312, -3640, -5202, -6598, -3572, 711, -1680, -6312, -3807, -3978, 831, -1188, -4245, -4310, -7584, -1936, -2416, -3598, -3759, -6397, -1902, -1112, -4363, -2385, -4368, -2542, -971, -7739, -1412, -4526, -2295, -1956, -5969, -909, -9751, -1952, -3951, -3203, -1013, -5079, -2482, -5007, -2823, -1841, -2115, -3485, -3893, -4508, -3042, -1813, -3944, -2476, -8390, -3065, -3524, -3411, -1102, -5568, -2684, -5474, -2825, -289, -5226, -3652, -2696, -2998, -310, -5345, -8172, -1250, -4284, -1246, -3334, -6708, -857, -7354, -2712, -2274, -3151, -1019, -9777, -2957, -2140, -2087, -1432, -5676, -2471, -2637, -2178, -2087, -3877, -2453, -4159, -3341, -3348, -3197, -2388, -7626, -5980, -5700, -3484, -2026, -4123, -5319, -5244, -4475, -1800, -1513, -2944, -2875, -4371, -1973, -696, -2443, -2122, -3853, -2977, -1062, -3546, -2808, -4503, -5683, -1769, -6391, -4870, -4615, -6658, -1760, -9873, -6902, -2950, -4382, -1757, -8724, -7033, -1944, -4151, -2451, -6731, -8317, -1880, -5179, -3833, -5847, -8860, -2768, -5707, -5330, -5913, -6610, -4725, -4401, -5875, -6154, -6022, -5516, -3292, -6049, -6410, -6349, -4202, -2875, -6326, -6422, -5028, -3904, -2945, -6690, -5428, -4164, -4081, -3296, -7285, -3982, -5411, -4086, -4066, -7589, -3160, -9155, -4876, -6195, -8635, -3481, -6154, -7075, -13717, -17795, -5003, -5407, -6101, -4434, -6576, -5973, -6237, -4436, -2085, -3952, -5654, -5689, -4266, -1523, -3278, -7182, -4895, -5054, -2485, -4046, -8509, -5342, -6065, -5898, -5987, -3994, -6742, -6265, -7377, -5848, -2032, -6876, -4901, -3902, -4456, -1474, -5497, -3380, -3330, -4201, -2127, -4147, -2510, -4583, -4967, -4416, -3244, -1952, -8653, -6811, -11506, -3228, -1339, -6706, -10673, -7462, -4530, -996, -4300, -9813, -5660, -7329, -1301, -3779, -7764, -4954, -5833, -2200, -4394, -8093, -4546, -4186, -3206, -5595, -9355, -4807, -4028, -4239, -6176, -8076, -5462, -4511, -6117, -5945, -6543, -5732, -4528, -9712, -5220, -5844, -5094, -4086, -9797, -4710, -5940, -3813, -4005, -6182, -4521, -7039, -3016, -4075, -4228, -3924, -8014, -2996, -3576, -3577, -3383, -6866, -3434, -3182, -3886, -3540, -6838, -3964, -3752, -4418, -4241, -8312, -4467, -5897, -4328, -4970, -7845, -4810, -10414, -4067, -5665, -7341, -5217, -8887, -4270, -6873, -8852, -6348, -9758, -5437, -10058, -9898, -8191, -11707, -8987, -10901, -9673, -6973, -7642, -9459, -6637, -15261, -6045, -7429, -5868, -5225, -6272, -7219, -10226, -4687, -5036, -3421, -10001, -13849, -4330, -5559, -2544, -8478, -12205, -4389, -6394, -3113, -7046, -11090, -4939, -7445, -5228, -6198, -9975, -6280, -9031, -9711, -5579, -11368, -6788, -10330, -11091, -5669, -10241, -4890, -8679, -8822, -6936, -7734, -3785, -6695, -7786, -7611, -6787, -3772, -5455, -7664, -6296, -6440, -4766, -5136, -8690, -6163, -5953, -6939, -6212, -9519, -7597, -5168, -8792, -10846, -8362, -11220, -4762, -7115, -7982, -8059, -14884, -5349, -6460, -5340, -4174, -1237, -4037, -530, -4954, -4174, -2522, -3614, -994, -6100, -2920, -3954, -2632, -2247, -9287, -1616, -4426, -2914, -4583, -5939, -845, -4044, -3528, -6908, -2561, -797, -4028, -2921, -4638, -1136, -1577, -4795, -2614, -3579, -1038, -3496, -5431, -3322, -3708, -2270, -7766, -4628, -3843, -4251, -5138, -7506, -3381, -3110, -4437, -7679, -4581, -2569, -2639, -4356, -7414, -3575, -2247, -2931, -4870, -6583, -3313, -2108, -3925, -6622, -4064, -3390, -1943, -5490, -7479, -2462, -3729, -1799, -7472, -5139, -1960, -4159, -1785, -11648, -3484, -2290, -4479, -1986, -10230, -2910, -2944, -5338, -2099, -6642, -4165, -4211, -8715, -1448, -5782, -8041, -8232, -8483, -722, -5205, -3221, -5106, -4944, -913, -4297, -1544, -3085, -3364, -2204, -3838, -1820, -3118, -1824, -2690, -3507, -4098, -3537, -968, -1757, -2774, -21301, -3335, -1385, -1588, -1829, -4718, -2810, -3704, -1814, -1186, -3376, -2211, -21827, -1887, -1290, -4445, -2342, -4557, -2236, -2360, -8339, -3652, -3064, -2763, -3372, -6379, -6009, -3624, -2998, -2490, -4106, -8994, -6324, -3087, -2093, -4128, -13751, -9152, -2466, -3083, -7281, -11801, -4567, -1805, -4833, -8001, -10322, -3041, -2281, -3630, -4067, -9236, -3017, -4560, -1911, -3684, -8263, -4517, -10479, -1119, -5675, -6364, -10327, -20358, -1023, -10732, -4767, -6247, -8368, -1528, -4746, -4216, -2983, -4246, -2913, -2574, -4841, -1884, -2734, -6145, -1727, -7198, -2100, -2697, -11135, -1772, -7530, -3580, -3827, -7508, -2708, -4040, -6147, -6024, -7296, -4290, -2445, -7961, -8740, -5872, -4995, -2092, -7900, -10261, -4057, -5117, -2828, -5617, -9008, -3259, -6224, -4583, -4048, -7363, -3309, -7746, -6672, -3700, -7212, -4105, -7622, -9777, -3554, -8676, -6131, -6578, -5873, -2582, -10892, -12501, -5608, -2886, -1768, -7949, -6930, -5185, -2165, -1734, -4853, -4810, -5409, -3225, -2563, -3271, -4393, -6393, -6190, -4328, -2921, -4492, -5464, -6662, -6721, -3605, -4504, -2806, -5473, -7027, -5113, -4566, -1484, -5975, -6032, -6411, -5262, -1418, -7516, -5429, -5497, -7180, -2201, -8448, -5025, -4215, -8562, -2727, -7362, -4902, -3800, -7443, -2685, -6053, -5415, -4525, -7229, -3456, -5082, -6395, -6904, -6703, -5888, -4365, -6522, -9974, -5301, -7193, -3975, -5716, -6555, -4081, -6234, -4262, -4815, -4722, -3544, -8030, -5932, -4538, -3835, -4174, -10042, -12196, -5802, -3681, -7210, -5852, -8365, -11229, -4208, -10922, -4575, -6589, -6415, -5101, -5875, -4948, -7750, -4057, -6052, -5357, -6997, -11230, -3570, -7159, -6148, -12133, -7698, -3994, -8878, -6703, -11760, -4551, -4813, -13831, -7419, -7405, -2793, -5913, -12081, -9096, -5796, -2280, -7953, -9445, -8924, -5801, -2982, -14337, -9974, -7061, -6966, -4944, -8875, -10837, -5828, -7896, -8018, -6489, -8304, -5412, -7048, -8014, -6504, -6799, -5686, -6278, -6303, -8279, -6485, -6170, -6540, -5936, -5547, -3390, -4884, 313, -2275, -5205, -3825, -4419, -712, -6002, -6433, -4252, -3189, -2211, -7314, -9619, -4710, -2507, -3601, -3322, -6767, -6094, -2362, -3490, -2405, -4586, -10020, -2379, -3266, -2906, -3675, -10631, -2392, -4206, -4625, -3173, -8286, -2611, -5431, -5448, -2849, -8566, -3250, -4016, -2558, -2961, -7528, -4419, -2752, -883, -4098, -5385, -6192, -2356, -731, -8262, -3910, -8129, -2542, -2219, -5083, -2952, -5691, -3190, -5673, -1978, -2423, -2901, -4317, -4986, -924, -2528, -1423, -5413, -3747, -850, -3729, -1128, -4775, -3680, -1003, -7519, -2264, -3471, -3324, -746, -8795, -6607, -2657, -2284, -461, -4480, -6069, -2310, -1272, -796, -3395, -3008, -2363, -836, -1808, -3736, -3082, -2986, -1026, -2795, -5576, -5211, -4724, -1269, -3337, -11530, -5590, -9675, -898, -3985, -7161, -3814, -7127, -399, -4453, -4459, -3717, -4424, -272, -4145, -3612, -4997, -3564, -698, -3620, -3438, -7013, -3593, -2199, -3800, -3317, -8395, -4469, -7607, -5528, -3399, -7366, -5659, -4618, -14263, -3532, -5910, -5974, -1672, -5954, -2692, -4889, -4994, -1074, -3646, -1954, -3507, -3351, -1526, -3297, -2598, -2770, -2700, -2589, -3889, -6451, -3521, -3070, -4159, -4155, -5944, -6990, -3590, -6149, -3818, -2166, -9168, -4215, -7917, -3963, -1372, -4878, -6426, -7147, -4834, -2278, -3570, -10798, -4734, -5753, -5726, -2839, -6221, -3579, -5617, -9161, -2446, -4039, -3903, -4882, -4570, -2575, -2848, -5119, -4334, -4000, -2973, -2471, -5503, -4278, -4478, -2937, -2861, -6736, -4598, -5032, -2978, -4320, -9367, -4628, -6017, -4192, -10281, -4014, -4672, -8068, -5377, -5145, -1725, -5761, -10937, -3245, -2092, -688, -4328, -10058, -1908, -1239, -363, -1743, -6145, -1607, -1582, -580, -715, -4074, -2175, -2512, -1221, -956, -3665, -3863, -3144, -2089, -1971, -5056, -4436, -3419, -2881, -2545, -9684, -2025, -3608, -3396, -2396, -12097, -994, -3362, -3588, -2442, -10976, -1438, -2872, -3295, -3008, -11353, -3386, -2753, -2876, -4564, -8431, -7063, -3675, -2700, -9427, -7128, -8582, -6544, -2614, -7480, -6192, -8026, -6297, -2497, -4253, -4874, -8420, -3969, -2731, -3707, -3623, -8860, -3467, -4105, -4764, -2854, -8585, -3975, -7415, -5983, -2595, -7169, -4972, -5572, -5020, -2861, -5735, -6013, -3911, -4773, -3655, -5287, -7482, -3890, -5173, -4776, -6153, -10354, -4815, -4027, -5856, -7702, -8618, -6613, -2938, -6685, -6564, -6505, -8551, -3061, -7454, -5335, -5890, -6235, -4488, -8389, -5273, -6417, -4250, -6685, -7292, -6254, -8490, -3528, -7534, -5091, -8071, -16270, -3670, -8866, -3933, -8751, -10555, -4230, -13174, -3898, -7635, -7917, -5234, -11510, -4896, -6785, -6733, -6968, -9992, -6789, -6312, -6186, -6140, -10876, -9400, -6279, -6354, -4174, -14447, -13489, -6691, -7307, -3387, -9865, -9254, -7337, -6874, -3650, -8955, -6250, -8217, -5054, -4855, 6703, 3204, 1586, 6835, -3668, 6345, 2720, 1801, 6394, -1134, 5365, 1177, 1741, 5107, 1061, 4119, -2197, 898, 3222, 2289, 3167, -8615, 284, 1169, 2993, 2409, -2027, 1073, -2036, 3106, 1086, -1293, 1938, -5374, 2331, 547, -1753, 2523, 5, 797, 1067, -24, 2946, 1931, 656, -1071, 1855, 2833, 2952, 2201, 1457, 3108, 1416, 3439, 3749, 4705, 4256, -32, 3213, 5112, 5749, 5414, 2752, 1872, 5989, 5477, 6280, 3819, -160, 6105, 4546, 6504, 2810, 1047, 5312, 3980, 5820, -433, 1945, 3821, 3567, 3844, 2125, 1419, 2976, 2419, -320, 3857, 176, 2403, 1613, 164, 3877, -1456, -24, 2528, 1172, 2732, -3532, -1812, 2889, -517, 1047, -144, -435, 2003, -408, 292, 1904, -883, -362, 1147, -1093, 2728, 1437, -5296, -94, -8915, 2993, 2659, -7021, -10282, 1091, 2931, 1639, -4613, 811, 3232, 2468, -3024, -2828, 2863, 3548, 1460, 1274, 126, 3568, 2711, -394, 3262, 1813, 3683, 1363, -4406, 3223, 2242, 3312, 403, -1225, 1673, 1474, 2497, 23, 1854, -1056, -1611, 1466, 825, 3183, -2861, -3901, 473, 1839, 3504, -5223, 1113, -398, 1868, 3128, -6163, 2229, -1538, 795, 2285, -3406, 1855, -2338, -252, 1237, -3807, 544, -276, -252, 395, -4846, -970, 948, -1082, -25, -2043, -860, 533, -2352, -229, 9, 484, -1634, -993, -505, 1165, 1547, -3511, -590, -974, 1707, 2050, -2970, -2518, -1589, 1697, 2108, -5249, -2631, -2542, 1152, 1867, -7052, -177, -3760, 137, 1291, -3246, -75, -3836, -1175, 229, -3124, -2183, -2316, -2709, -1316, -3948, -6511, -993, -4539, -3187, -2271, -6249, -588, -4778, -5457, -695, -10341, -1169, -3864, -4383, 156, -7273, -2097, -4081, -2309, 567, -4283, -1895, -5611, -1484, 490, -3179, -1638, -6577, -1538, -352, -2336, -2480, -5376, -2014, -2253, -1795, -4154, -4983, -2025, -3769, -2038, -3711, -5141, -1714, -2523, -3799, -2234, -4715, -2128, -1522, -9073, -1593, -3986, -4264, -1285, -7244, -1632, -3726, -5375, -2149, -8677, -1852, -4676, -1688, -4917, -7194, -1826, -8096, -492, -12282, -2964, -1637, -7885, -1091, -6994, -2175, -1556, -5414, -3828, -5926, -3777, -1687, -4540, -20328, -5444, -8621, -1951, -4144, -6359, -4912, -3849, -2310, -4653, -5526, -4968, -2186, -2929, -6903, -5798, -5746, -2091, -4192, -8093, -5356, -6310, -2948, -6581, -5592, -4002, -6308, -4391, -7763, -5412, -2773, -7445, -5002, -6596, -8029, -2051, -14411, -4477, -7266, -10649, -1923, -8147, -4639, -10554, -7352, -2289, -6031, -5873, -13132, -8828, -3032, -6298, -7359, -9153, -7857, -4502, -7934, -7195, -6047, -4379, -7915, -9677, -5741, -4285, -3318, -9178, -9480, -4826, -3693, -3636, -5388, -7589, -5189, -4258, -4850, -4741, -5690, -7230, -6325, -6145, -6763, -4460, -9858, -11254, -6214, 1293, 6143, 1369, 3002, -6919, 2589, 5625, 2395, 2359, 1396, 3514, 3919, 3497, -60, 4035, 2884, 548, 3781, -7328, 5095, 458, -776, 3353, -198, 5134, 590, 749, 2328, 1795, 4407, 3217, 1141, 412, 2568, 3058, 4693, 983, -4580, 2762, 858, 5438, 119, -3118, 2391, -2306, 5534, 1281, -1659, 1589, -3437, 5182, 4135, -72, 1068, -106, 5599, 5719, 3958, 1330, 2715, 6580, 6093, 5937, 1590, 3934, 6784, 5487, 6334, 1391, 3827, 6024, 4268, 5213, 2532, 2476, 4725, 2996, 1936, 4331, -143, 3626, 1903, -1202, 5311, -3511, 2869, 75, 1116, 5583, -4604, 1661, -5912, 358, 5407, -3736, -1659, -312, -3236, 4889, -4575, -6926, 993, -10314, 4077, -4774, -2910, -919, -8073, 3183, -3574, -2594, -1749, -4815, 2386, -4578, -223, 2025, -402, 1379, -3131, 1151, 3552, 1653, -307, -1652, 1588, 4067, 2550, -1863, -2704, 1634, 3913, 2716, 128, -4038, 1601, 3233, 2298, 1743, -976, 1691, 2509, 1212, 2014, 106, 1861, 2459, -545, 910, -530, 1893, 2695, -1881, -2392, -3240, 1653, 2586, -1497, -7493, -4522, 1314, 1810, -577, -1369, -554, 1343, -279, -149, -17, 1383, 1717, -1704, -736, -337, 2342, 1784, 1357, -2468, -1523, 2672, 1083, 2579, -4590, 301, 2526, -625, 2299, -4465, 2389, 1926, -3639, 566, -2154, 3378, 857, -5484, -3344, -534, 3636, -375, -2516, -12965, 58, 3478, -860, -379, -4807, -35, 3069, -38, 1062, -567, -587, 2468, 1059, 1903, 1600, -1397, 1548, 1590, 2101, 2320, -1832, -55, 1443, 1640, 1993, -2134, -1309, 726, 561, 1127, -3168, -521, -312, -1202, 354, -4864, -373, -945, -4005, -663, -6055, -1355, -869, -4117, -2990, -5865, -3041, -902, -2457, -8170, -5027, -4746, -1442, -2935, -10249, -4432, -5016, -2340, -7190, -6067, -4864, -4258, -3037, -6829, -2751, -6363, -3300, -3169, -4239, -1698, -5350, -2072, -3388, -5548, -2701, -3534, -1137, -4792, -7117, -7722, -2995, -814, -8137, -3626, -6399, -3808, -1096, -7043, -2003, -4058, -6258, -1518, -6399, -1569, -4900, -9322, -1486, -6839, -2077, -8802, -7117, -1405, -5116, -3519, -8928, -5047, -1596, -3431, -5787, -5447, -4194, -1928, -2840, -6319, -3920, -4545, -2079, -3631, -4603, -3377, -5533, -1722, -6507, -3148, -3755, -5508, -1590, -10105, -2108, -5016, -5074, -2436, -9812, -1715, -6540, -5372, -4575, -11719, -2270, -6622, -6098, -6740, -5126, -4204, -5991, -7256, -5343, -3221, -8612, -5590, -9812, -4101, -3040, -8594, -5369, -9472, -3783, -4275, -6415, -5323, -8459, -4783, -6485, -5315, -5352, -9788, -9495, -5953, -4822, -5571, -10721, -6150, -5775, -5135, -6381, -10666, -3189, -8294, -6049, -7777, -12603, -2586, -7554, -6878, -8223, -10970, -3410, -5760, -6977, -5866, -9642, -5563, -6499, -6528, -4094, -9282, -9337, -8436, -6019, 6460, 8585, 6506, -1671, 2320, 6263, 7904, 6607, 4638, 4738, 5687, 6070, 6838, 6771, 5155, 4927, 4654, 6804, 7110, 3835, 3991, 3955, 5957, 5941, 436, 2319, 1879, 3752, 2813, -1564, 1025, -2462, 1189, 481, -1290, 1768, -6966, 2144, 1278, -4873, 1698, -2827, 2060, 2646, -3446, 695, -839, 2309, 5169, 1280, 485, -121, 3583, 6523, 3448, 1856, 216, 3940, 6911, 4334, 2638, 242, 2952, 6260, 4036, 2291, -887, -240, 3493, 2322, 858, -4898, -6552, 1023, -1619, -2154, -1399, -694, 5282, -1276, -6278, 670, -750, 6114, 394, -1566, 783, -2170, 5681, -62, -1027, -185, -2775, 5170, -2306, -3586, -1760, -3144, 4729, -7322, -3833, -3287, -1245, 3711, -19766, -589, -3358, -222, 2242, -8093, 27, -3191, -970, 1022, -4243, -1122, -3548, -3359, 209, -3298, -4685, -2986, -5363, -298, -4225, -7646, -1347, -5386, -964, -8173, -6611, -132, -5248, -1823, -6344, -5415, 315, -4457, -999, -2598, -2179, 144, -3868, 105, -1560, -1501, -509, -3549, 279, -2197, -2952, -1794, -3053, -246, -3620, -5376, -3607, -2577, -1222, -2705, -4183, -4144, -3278, -3791, -1762, -2836, -2395, -6206, -5145, -1087, -2115, -305, -1526, -1274, 104, -2627, 818, 929, -498, 781, -4614, 704, 1460, -1142, 253, -4524, -603, 434, -2681, -2192, -2584, -777, -2499, -5398, -5049, -1574, 712, -11590, -2509, -2376, -1586, 1435, -3710, -250, -3423, -1846, 1829, -1418, 701, -2715, -487, 2131, -1248, 1073, 867, 716, 1818, -3331, 1106, 2047, 902, 523, -12523, 682, 1608, 253, -1466, -6181, -499, -528, -912, -1687, -5199, -2605, -6409, -2194, -639, -4671, -4952, -5239, -3145, -138, -4332, -7433, -3721, -3566, -337, -4663, -12593, -5254, -3552, -1391, -4762, -7195, -8644, -3370, -3758, -4647, -6089, -5053, -3458, -6957, -4791, -6491, -3648, -4299, -5356, -4950, -5986, -4012, -6366, -4894, -5337, -4762, -5765, -9859, -5770, -6680, -4250, -7849, -8077, -6539, -8993, -4049, -7880, -5595, -7021, -7878, -3440, -7817, -4289, -9246, -6359, -2550, -7828, -3690, -14931, -5444, -2002, -6701, -3536, -8096, -4238, -2251, -5883, -3852, -7104, -3132, -3703, -6021, -5128, -8187, -2707, -7868, -6281, -9567, -9829, -3158, -8433, -6121, -7803, -9826, -4530, -4120, -6513, -4211, -8745, -6605, -2590, -7734, -3280, -8554, -8064, -2129, -8656, -3965, -8337, -8232, -2411, -7856, -6265, -5359, -8473, -3191, -6319, -7133, -3973, -8603, -3961, -5119, -5602, -4297, -8081, -4038, -4657, -4597, -5804, -7912, -3391, -5386, -4008, -6926, -8704, -2602, -7435, -4229, -8161, -11275, -2156, -7266, -5466, -9710, -14398, -2307, -7574, -7933, -7565, -8732, -3190, -11110, -10776, -7046, -7437, -4874, -5258, -8394, -8759, -8230, -6787, -3350, -6713, -15560, -10338, -6749, -3291, -6291, -10373, -10250, -6686, -8081, -3861, -7544, -12242, -5296, -4990, -3638, -6283, -9534, -4842, -4384, -3611, -6077, -7659, -5782, -4796, -3644, -6173, -6376, -8535, -5620, -3851, -5851, -6373, -7229, -7298, -4720, -5509, -7419, -6000, -7694, -6763, -5797, -6459, -6692, -5630, -10988, -6929, -4902, -7763, -4236, -14770, -8883, -4496, -7651, -3452, -10059, -11134, -5015, -7245, -3129, -8703, -10550, -5908, -5993, -3172, -8592, -8335, -6287, -4910, -3536, -8320, -7303, -6516, -4655, -4341, -7341, -6919, -7810, -5046, -6037, -7272, -6556, -9608, -5551, -10399, -8040, -6681, -8608, -5595, -11077, -7942, -7533, -8245, -5352, -7727, -7381, -8621, -9242, -5506, -7582, -6260, -8946, -12264, -6541, -9181, -4954, -6697, -9602, -8278, -11606, -4501, -5073, -6425, -8221, -10750, -5169, -4816, -5116, -7345, -8677, -7055, -5554, -4801, -7546, -6583, -8102, -6044, -5165, -9019, -5398, -6459, -5659, -6100, -11315, -5408, -5590, -5940, -7048, -10794, -6623, -5433, -7994, -6872, -9456, -8768, -5395, -11278, -6691, -8343, -10468, -5121, -8059, -7592, -7063, -9210, -4766, -7158, -9540, -5863, -7060, -4729, -7870, -9096, -5170, -6140, -5375, -10321, -6839, -5354, -6402, -6812, -17832, -5637, -6724, -7307, -7519, -9106, -5496, -8705, -7919, -6604, -7291, -6224, -7896, -8120, -6267, -7301, -7367, -7235, -7994, -6827, -8576, -7996, -7929, -7577, -8062, -10179, -7451, -9083, -7175, -9730, -10866, -6625, -8186, -7108, -10845, -10002, -6490, -6085, -7891, -10350, -8082, -6925, -4784, -9322, -9988, -7385, -7246, -4706, -9306, -9214, -8374, -7127, -6081, -8930, -7544, -11900, -6299, -9353, -8191, -6706, -12636, -5464, -8912, -7071, -7185, -9948, -5367, -7078, -7114, -8801, -8905, -6146, -6768, -9244, -9259, -7689, -7835, -6756, -14682, -8430, -6448, -10286, -6334, -9283, -8936, -5805, -10398, -6232, -8215, -11595, -5907, -8780, -6925, -9266, -12734, -6654, -8245, -8377, -13011, -10854, -7601, -9180, -10070, -16819, -9726, -8044, -13164, -10194, -12386, -8277, -8308, -11393, -8966, -11102, -7739, -9389, -8107, -7966, -9149, -8758, -12630, -7110, -7712, -7642, -12974, -16843, -7381, -8716, -7506, -12816, -12094, -8807, -12294, -9444, -9445, -12427, -11430, -13088, -13175, -9000, -11861, -13592, -11056, -8018, -9609, -8138, -13507, -13650, -6437, -9416, -6223, -13215, -10254, -6645, -8461, -5572, -11994, -7187, -8797, -8068, -5900, -11103, -6167, -12028, -8353, -7192, -10938, -6353, -8272, -9002, -9690, -9898, -7507, -7329, -9624, -12416, -8870, -9500, -8506, -10184, -12048, -9132, -11676, -11289, -10610, -13399, -10614, -12017, -9963, -10329, -17632, -12277, -10225, -9342, -10059, -11794, -12810, -8551, -11024, -11152, -9739, -10594, -7666, -13738, -16279, -9015, -8973, -7541, -10362, -14029, -8803, -8840, -8188, -8717, -11141, -8518, -10270, -9868, -8657, -10411, -8097, -13847, -13647, -9581, -10752, -7837, -17834, -19148, -9836, -12529, -7931, -20091, -13792, -9977, -11735, -8497, -13887, -12597, -5991, -3744, -8902, -11410, -8909, -5391, -4875, -9033, -8824, -11574, -4686, -7483, -10082, -6786, -9772, -4221, -8386, -11713, -5534, -7215, -4427, -7160, -11370, -5162, -6295, -5663, -6160, -9608, -5567, -4910, -8094, -5465, -8462, -6479, -3906, -10248, -5571, -7955, -7540, -4028, -12081, -6664, -7881, -8728, -5443, -11211, -8168, -8236, -8905, -8792, -8369, -8285, -8463, -7148, -12392, -7433, -7569, -6835, -6183, -8421, -7292, -7064, -5297, -6863, -7661, -6998, -7198, -5058, -10533, -8750, -6326, -8437, -5922, -10417, -12173, -5678, -11215, -5797, -7091, -13441, -5301, -12537, -4946, -6199, -9546, -5184, -10470, -5456, -6234, -8400, -5204, -9073, -7572, -6855, -8838, -5254, -8304, -8123, -8270, -9406, -5340, -6641, -7515, -10446, -8337, -5466, -4801, -9911, -9273, -7318, -5471, -4036, -10924, -7826, -6955, -5336, -4542, -5788, -7617, -7424, -5559, -6493, -4346, -7735, -8804, -6796, -10525, -4645, -7064, -9692, -8022, -24960, -6532, -6083, -8804, -5864, -12193, -8419, -5556, -7612, -4576, -9891, -7835, -5563, -6365, -4740, -9331, -8463, -5905, -5533, -6383, -9772, -10027, -6335, -5503, -10656, -11335, -8994, -6706, -6632, -12304, -14695, -8003, -7338, -10125, -8839, -10698, -8142, -9166, -11785, -8201, -8931, -8256, -12605, -7731, -8399, -9187, -7673, -13029, -6747, -8740, -10575, -6812, -18001, -7123, -9667, -10123, -6003, -8773, -8340, -10541, -9335, -6346, -6194, -9319, -7978, -8672, -9434, -5109, -9667, -6188, -7126, -11739, -4909, -10658, -5687, -6117, -7850, -5786, -12360, -6263, -6042, -7688, -7843, -10842, -7874, -6553, -7756, -7997, -9353, -10055, -7000, -6986, -6754, -9075, -10057, -6836, -6558, -6460, -9185, -8933, -6373, -6269, -6889, -9051, -8414, -6409, -6204, -7961, -9056, -8596, -7465, -7027, -9355, -10020, -9444, -9167, -9397, -10302, -13686, -10432, -8710, -12956, -12171, -13586, -10825, -7945, -10608, -20602, -9473, -11381, -8347, -9115, -11084, -8096, -11883, -9886, -8625, -9771, -8113, -11845, -12840, -9157, -11089, -9648, -13506, -17357, -11322, -15611, -10725, -12426, -12935, -11703, -15018, -8182, -9198, -11329, -8610, -14320, -6861, -8047, -12005, -7322, -9497, -6595, -8139, -16254, -7258, -7208, -7013, -8970, -11442, -7916, -6760, -8093, -10028, -9065, -8420, -7990, -10361, -10859, -9035, -7877, -11779, -17250, -11230, -11400, -7004, -17858, -11925, -11498, -11424, -6944, -12917, -9719, -12969, -8998, -8374, -11280, -9195, -13799, -8777, -12118, -10145, -9121, -10062, -10183, -12353, -10403, -9174, -8311, -11381, -11711, -11370, -9726, -7643, -9668, -11575, -10860, -10616, -7382, -8398, -9651, -10141, -9582, -7492, -7666, -8988, -10232, -7922, -8451, -7308, -10074, -11430, -7321, -10715, -7654, -12915, -12854, -7852, -10677, -9120, -11435, -11781, -9380, -8932, -12507, -9987, -11731, -11085, -9085, -16788, -10218, -12420, -11560, -12065, -13337, -11069, -11049, -11568, -15013, -12380, -10784, -10065, -11213, -10293, -11080, -10060, -10459, -10470, -4645, -7279, -8322, -10262, -8200, -7235, -10412, -8067, -11503, -7272, -7172, -11788, -8851, -12891, -5541, -5762, -10109, -10237, -24390, -5888, -5896, -11184, -11610, -11714, -8864, -8080, -13501, -12644, -10258, -8987, -10534, -9757, -11648, -13154, -6682, -6602, -7124, -11465, -13310, -6786, -5208, -5621, -14978, -9388, -9169, -5411, -4955, -14351, -8002, -12895, -7435, -4944, -10748, -6909, -8310, -12699, -5243, -9682, -6661, -7229, -8543, -5389, -9297, -7954, -7459, -6961, -5349, -9556, -11466, -8024, -6584, -5736, -11375, -10080, -9118, -6553, -7427, -10460, -7665, -10338, -6999, -11786, -7307, -6465, -8590, -8550, -13963, -5895, -6046, -7109, -10132, -14164, -4839, -6536, -6678, -7674, -8115, -3733, -8272, -7110, -6862, -6329, -3312, -11836, -8294, -7997, -6689, -3960, -10943, -9089, -9066, -8144, -5551, -8517, -7720, -8118, -8383, -6593, -7131, -6316, -8435, -8351, -6436, -6196, -5747, -9933, -9374, -7091, -5701, -5978, -9258, -11383, -10144, -5677, -6655, -7256, -11110, -12618, -5888, -6986, -5780, -10439, -7687, -5980, -6480, -4776, -8935, -6403, -6059, -5546, -4204, -6751, -6283, -6454, -4842, -4038, -5731, -6589, -7155, -4825, -4279, -5682, -6878, -7933, -5746, -5162, -6189, -7117, -9120, -7767, -7193, -6874, -7464, -11775, -10395, -9418, -7089, -8237, -10760, -10105, -8380, -6914, -10549, -8362, -8312, -8602, -7812, -14282, -7759, -7345, -11042, -11655, -9857, -8144, -7312, -13243, -12635, -9634, -8513, -7797, -12732, -10126, -12235, -8198, -8174, -13280, -8696, -11478, -8139, -8563, -13062, -7110, -10727, -9314, -9222, -17312, -6665, -13161, -12697, -10077, -11454, -7278, -14893, -13504, -12326, -7911, -8250, -8763, -11000, -13215, -6521, -8694, -6221, -10134, -9276, -6203, -8828, -5189, -10501, -7422, -6533, -9168, -5264, -13122, -6549, -7343, -9686, -6382, -14479, -6508, -8844, -10154, -9085, -10108, -7377, -10863, -10607, -17692, -8197, -9145, -10507, -11689, -9599, -7331, -11922, -10398, -11527, -8239, -7226, -16751, -13203, -9232, -9399, -7455, -11164, -13717, -8828, -13202, -7527, -8539, -11117, -11690, -10044, -7620, -6948, -11590, -12705, -8974, -7925, -6103, -12496, -8686, -10038, -8381, -6360, -10878, -8348, -12467, -8828, -8132, -9960, -9718, -13730, -8801, -11835, -9764, -10661, -11965, -8838, -14391, -9139, -10330, -10710, -9810, -12038, -7957, -10940, -10779, -11834, -8383, -7025, -12421, -11755, -13472, -6596, -6669, -12898, -13153, -14344, -6041, -6955, -12086, -15793, -14101, -6451, -7941, -11562, -21332, -10627, -8039, -9853, -12192, -22607, -8947, -11731, -13727, -15488, -17383, -8963, -12440, -17614, -16423, -13197, -10609, -11382, -13433, -12505, -11141, -13491, -14398, -12776, -11681, -10186, -13165, -16676, -12033, -11957, -10227, -11562, -13239, -11000, -11789, -11349, -10535, -13464, -10916, -10743, -12834, -10362, -12974, -11947, -10160, -12579, -11610, -13058, -12664, -10771, -12170, -16505, -12734, -11097, -13525, -11957, -12217, -10174, -9629, -13331, -11881, -9968, -8909, }; +//int32_t position_embedding[1936] ={196, -7348, -7382, 1712, -10706, 1192, -2694, 1918, -6099, -3297, 121, -2851, -5180, -4712, -1750, 13596, 9600, 3479, -260, -4836, 1525, 4241, -2302, 4529, -900, 3399, -6545, -1652, 3663, -9180, 4876, 3043, -2909, -1064, 4044, 3782, 9062, 1131, -11358, 1565, -1527, -360, -8696, -9012, 1582, 12600, -3776, -1521, 5412, 2481, 1324, -4161, 13922, 5353, -4342, -1956, -1648, 2128, -11661, -6865, 6676, 3476, 3854, 8205, -6787, 6070, -2006, 2531, -13202, -4385, 2898, 2619, 7081, 7595, -1546, -9370, -2303, 2956, 6760, 5943, 4413, 4207, -3058, -4963, 6809, 5599, 3394, 460, 6411, -4390, -2761, -3172, 9835, -7277, -1952, 1675, -7690, 3179, -9750, -7583, 5347, 10512, -1649, 1281, 11435, -5484, 9637, 3355, 1422, 1506, 4282, -3563, 1374, 3387, 1124, -8658, -2358, -4699, -4142, 490, -3377, -2415, -7181, -1534, -597, 12306, 5111, 16385, -4726, -7888, 2951, 81, -2326, 7865, -5223, -6500, -3798, 4601, -3666, -618, -11033, 12947, -534, 10781, -9595, 6606, -209, 130, 1359, 3264, -4327, 2847, -302, -4247, -8282, 402, 7925, -2107, -2138, 8384, 2522, 6636, -777, 96, 3798, 8934, -10498, 2998, -1701, 4036, 4295, -6322, -4076, -118, -4425, 7939, -127, 2611, -3533, -13055, 776, -1126, -7048, -2041, -1031, -2451, -1461, -15072, 1542, 185, 22, -8805, -4022, 348, -5263, -5852, -8468, 6756, -3619, -4270, 2868, -5721, -4657, -3375, -2366, 7595, -591, 2305, 1837, 4089, 7194, 1445, 9971, -5729, -11176, -188, -6837, -3708, -7535, 8617, 3044, 10526, -2912, 2707, -5639, -671, 7353, 2677, 6239, 9202, -9854, -3893, 834, 2775, -7384, -2147, -2039, 9885, 1003, 3164, -7241, 6396, -3139, -10976, 8473, 1252, -10979, -1952, -134, 1954, -4129, -6521, -129, 1874, -234, -675, 1052, 14765, 896, 2509, 1602, -1855, -13043, -10309, -2265, 2743, -4266, -2706, 836, 2445, 512, 18564, 2667, 7664, -10884, -4509, -1825, 5502, -2222, 8628, -1803, -15446, 5921, -1472, 11098, 4316, 5132, -7807, -2586, 5918, -2599, -2611, 3376, 2489, -1817, 4732, 3388, -1536, -1365, -10085, 8422, -2155, 6762, -2014, -8955, 4150, 439, 4460, -1990, -2740, -1333, 349, -8757, -2081, -7922, -4516, -3423, 3926, -4, 1547, 979, 9047, -6177, 568, 1446, 6488, -6201, -2358, -7308, -391, -349, -4329, 2976, 8472, 5717, 2301, 5198, 1549, -3488, -6818, 896, 5382, -12555, -320, -1272, -1351, -11423, -5350, 114, 5480, -1229, 109, 2501, -11900, -944, 5306, 3113, -6048, -3661, -5327, 1334, 10289, -9589, -2279, -1588, -3509, -6272, 10002, 5967, 5551, -6935, -4327, 2791, 9216, -9959, 4473, 1978, -15959, 2149, -7863, 307, -4521, 9051, 6015, -897, 5300, -6371, -260, -800, 2709, -5341, -110, 9833, -7331, -49, -4877, 6976, -4835, 9914, -3133, -4385, 4190, -5738, -465, 2371, 9339, -7956, 6917, 550, -4353, -6041, -4530, 1078, -264, 7846, 3506, -3651, -6858, -126, 1678, 7383, 6218, -2889, 299, 2333, 651, 7628, -751, 2680, -1033, -2285, 7088, 1915, 3198, -17, -11549, 8693, 814, -2438, -2575, 134, 5825, -10139, -1796, 5422, -328, 3026, 7844, 7875, 151, 5205, 6808, 2670, 7859, -12952, 786, 3422, 7597, -6877, -8084, -5465, 532, -10992, 14251, 8151, -2947, 9253, -2637, 10375, 6905, -6967, 6725, -1279, 6702, -3149, 2110, -6067, -4028, -3569, 3633, 1111, -4331, -1496, 5413, 7091, 1720, -8921, -978, -1209, 829, 255, 1729, 1379, 307, -3612, 6083, 5152, 10108, -1758, -12600, 7086, 10504, -9339, 8476, 213, -3269, -8160, -720, 8930, 7891, 205, -2909, -1424, 2115, 8759, -2722, 4276, 10615, -4849, 1589, -6607, -6358, -16955, -355, 2535, 10376, 4434, 4805, 5135, 1439, -3213, -5002, 5087, 687, 1086, -4681, -2821, -14266, -11179, -2582, 7730, 104, 8271, 6464, 4981, 3696, -5874, -5849, 1397, 1046, -12206, -1665, 2201, -439, -2283, 2989, 6710, 167, 3424, 226, 5465, 1487, -3130, -5497, -2878, 3131, -4859, 1596, 4630, -7875, -3226, -7328, 5413, -1135, 3646, -3147, -4163, 1187, 6921, -4376, -394, 2658, -2362, -2453, -2948, -5, 2681, -9107, -1191, -11249, -9502, 2395, -4479, 5486, -9094, 4493, 2749, 9093, -13265, 1179, -2309, -4304, -943, 763, 7495, 1353, 6170, 5194, -2838, 5307, -6865, -789, 3717, 2676, -3582, 5513, 2849, -6748, -929, -452, -74, 10928, 4100, -2011, -4080, 7555, -5922, -4585, 2941, 5010, -9571, 3639, -7514, -8163, -9381, 6471, 6542, 10530, 1936, 12466, -8631, 2326, -2711, -5686, -3652, 9719, -5176, 4973, 3079, -2078, -3088, -1273, 4810, 7839, 4100, 2226, -10032, -1859, 3094, -588, 3594, -4821, -12113, 4966, -199, 8597, -5230, -9595, -2768, 1170, -7238, 6502, 3566, 1014, -859, -2509, 8922, 5700, 3053, -5515, 2418, -9141, -11804, -6197, -485, 3796, -3860, -249, -3930, 6901, -6496, -10185, 3596, 2732, -1355, 983, -527, -6415, -11871, 5991, 1217, 3176, 1131, 3719, 1786, -4878, 2575, 301, 1830, -1133, 1374, -3349, 164, 3352, -1368, -7919, -7348, 5071, -949, 9665, -510, 1889, -5429, -11519, -367, -329, -4465, 3694, -4588, 2112, 638, -7040, 3411, 6658, -1359, 6764, 1210, -5077, -1410, 11878, -1644, 7113, -1193, 424, -3177, 1180, -1788, -194, 2381, 7231, 583, 12532, -2873, 10938, 499, -1249, 5818, 4605, -4712, 4018, 8740, -4365, -45, -5998, 7774, -12177, -2624, 2729, 3998, -108, -8892, -3748, 5248, -2207, -5953, -1195, -2204, -11208, -7020, -3089, 591, 2701, 3647, 4811, 5174, -793, 1089, -4844, 3268, 42, -8431, -6365, -473, -6021, -7345, 4530, 1754, 9097, 1264, 3335, -4713, 5214, 8575, -4620, 4652, 4686, -5145, 4579, -5352, -7520, -5546, 5278, -1174, 3277, 5639, 6893, -6939, 889, -2533, 4578, -2099, -2107, -1194, 7229, 3163, -12403, -15160, 9385, -1258, 4658, 7070, 6925, 2730, 9222, -5450, -7277, 4427, 10517, 5277, 5046, 3242, -4736, -6004, -4718, 2550, -2531, -1704, -4376, -1463, -4121, -2849, 3464, 2406, 8299, -1272, -5814, 5850, -5042, -7367, -7965, 718, 6263, -2666, 4066, -1047, 10409, 4553, -2990, 13574, -1465, -9180, 5031, -2361, 828, -3184, -9065, -927, 9733, -2748, 1466, 4699, 5731, 6123, -6454, 195, 5271, -14124, -2202, -1832, 2, -12207, -3771, 420, -6557, -1144, 9838, -2994, 821, 5869, 4339, 2391, 11899, -8278, -4483, -2896, -1849, -8299, 5111, 260, 10086, 3929, 5539, -6377, 13205, -3131, -1461, 1465, -207, -6114, 1402, 5214, -7641, -973, -1233, -4298, 9744, 2985, 14273, 143, -2463, -1160, -7427, 6119, 7836, -4500, 921, 2153, -287, -5492, -7355, 322, 8465, -1047, 2054, 497, 10097, 7018, -4490, 2046, 6496, 1872, 3413, -9124, -779, 6169, -6458, 1514, -3490, -10698, 3100, -1862, 2875, 6368, 1318, 658, 1050, 219, 3709, -10295, -2636, -4041, 5012, -61, 4480, -3406, -2850, 302, -7649, 5732, 7661, 7424, 5693, -2459, -7557, -6075, -1802, -11208, 3080, -7096, 6845, 1575, 5391, -2403, -2489, -1433, 2278, 7747, 4970, -13012, -5878, 6852, -9159, -4405, -374, 4644, 948, 8329, 4469, 2672, -812, -5394, -11335, 5476, -1149, 831, 1394, -4572, -5319, -8258, 3435, 1955, -972, -4931, 4098, -362, 10748, -4493, -7594, 7251, 7377, -5753, 5011, 5545, 812, -9204, -5784, 3585, -2369, -2755, 6910, 3144, 9649, 1338, -4350, 8637, 10729, 4980, -2094, 2339, -9914, 4376, 1377, -3161, -9768, 10043, 2351, -5890, 3685, -5198, -198, 9585, -2097, 251, -271, -6207, 2402, -7706, 2448, -2452, 4762, -2401, 8514, -3997, -3465, -1079, -1985, 1855, 12959, -3239, 3580, -7527, -141, -10696, 1692, -1395, -4360, 3321, 8854, -1479, -556, 2118, -6509, 1766, 3286, 6377, 587, 2108, -3565, -4028, -1202, 6234, 10107, 4402, -3022, 1785, 11342, -2046, -8556, 10844, 9710, -6141, -2186, 7498, -6214, -10161, -706, 10836, -3416, 1141, 7550, 10477, -2297, -2264, 2035, 4234, 3055, -8828, 677, 4606, 5708, -8930, -12070, -3840, -1422, 7871, 3303, -1806, 3930, -8954, -14512, -6258, 3705, 2788, 7841, -5298, -2605, 9229, -6623, 6570, -1780, 8058, 2401, 82, 3209, -2819, 5653, 4950, 11482, -815, 2924, 13697, 538, -2681, -6465, 6221, -14698, 4160, -1397, -1421, 3050, -2808, -4229, 8893, 8020, -16289, 2108, 42, 1162, -7427, -6701, 7883, 8297, 1597, 5038, -2443, 931, -4441, -6867, 6905, 3184, -18314, 3272, 3904, -4514, -2738, -3360, 8473, 11965, -1353, 12774, 643, 3839, 3358, 2682, 8232, 6960, -4297, -836, -6527, -1543, -6549, -2445, 586, 11268, 246, 18235, 13, 1016, -1328, -669, -3472, 7036, -1343, -2877, 1927, 4696, -8023, -4754, 8818, 3667, 6334, 7176, 3254, 5146, 5763, -887, 1357, 5270, -12799, 5511, 7894, 830, -3383, -12477, -5669, 1653, -2524, 2412, -7996, -6546, -4264, -8583, 6337, -2213, -802, -2847, 2, -3954, -8564, 604, -1101, -887, 1889, 5294, 2636, 8182, -2383, -2636, -3763, 9006, -3445, -4557, -453, 6281, -10285, 493, 461, -237, 7249, 4140, 2612, 9505, -1959, -3777, 791, -1044, -5313, -5067, -1969, -4218, -5337, -761, 1536, 10589, 4648, 16378, -2512, 1416, -5251, -7837, 5860, -4262, -4829, -9612, -1219, -4834, -8699, 1980, -3450, 6160, -3204, 6195, 3463, 9506, -5485, -8112, -4138, -724, 1512, 918, 1741, -10433, -14466, -6574, 12705, 2220, 11707, -4228, 346, 10643, -2137, -4149, -1762, 5518, 7242, 5374, 1826, -2245, -30, 586, 4427, -10485, -212, -4218, 3951, 8882, 932, 1660, 1355, 2252, 250, -7325, 1686, 2198, -6366, -7720, 853, -3684, 972, 3909, 2243, 7001, -484, -1258, 3933, -1780, 1998, -2576, 3712, -10146, -1859, 694, 4870, 10322, 6968, 2166, -3058, 4834, -3061, -582, -2964, 8615, -4992, 11852, 1768, -9018, 221, -5394, 3845, 5675, -3122, -3868, -1592, -879, -7691, -2872, -424, 2273, -4646, 923, 3113, -4257, -10901, 3142, 4453, 943, -2176, -1475, 1806, 5221, -5723, -12716, 1026, 5810, -7981, 898, -4108, -3235, -9229, -3181, 5933, -3481, 1041, 8501, -8344, 7251, -346, -8282, -3530, 4398, -6469, 331, -1543, -7201, 5033, -3596, 2641, -2910, 5563, 3475, 3365, 8598, 3284, -9382, -1039, 8790, -3126, 4164, 9639, -8403, 4317, -9679, 12168, 1929, 4278, 13619, 2864, 3590, 532, -5407, -4325, -1887, -3285, -443, -2136, 4922, -13579, -1682, 3007, 1898, -5139, 12461, -1291, 3241, 2362, -4873, 4000, -1434, -4710, -4441, -1077, -9310, -3098, -2394, 8959, 2132, 3326, 10103, 7219, 7674, -3532, -3918, 2722, 4192, -7496, 3443, -2661, -5911, -13391, -6098, -6935, 3533, -4270, 9580, -2819, 10422, -1715, -6566, 1072, 7238, -7981, 5947, 6971, -2932, -8276, -6662, -2739, 1783, 7551, -822, 714, 6140, -2272, 1579, -1586, 2848, -4921, -5685, 2468, -4065, 8038, -1181, 3849, -7741, 8319, -4081, 540, -331, 2632, -8020, 3331, 2738, -10207, 10376, 1578, -6226, -7393, 1824, -3637, -2150, 4912, 3303, 97, 7901, -3422, -11877, 11709, 7670, 1157, -1433, 14410, -4035, -5654, -2636, 1646, -3398, 4553, 3448, 1590, 6668, 1229, -631, -639, 7354, -5577, -1004, -4027, -4623, 1226, -6965, 6190, 5682, 6399, -2992, -5282, 4553, -301, -5865, -1087, 5129, 372, -397, 7112, -11645, -7985, -3391, 886, -665, 1259, 3809, -7332, 3309, -5446, -1452, -3214, 7524, -7810, -4991, 6479, -5773, -2147, 504, 8548, -414, -1342, 4170, -2569, -570, 4688, 6138, 2469, 7672, -1794, -4615, 2466, -2698, -1092, -8501, 2056, -9155, -3875, 4456, -5823, 6540, 1286, -5507, 604, 3683, -5865, 1624, 10940, 397, -7894, -3904, 7932, -3332, -1916, -453, 4174, 9373, -8885, -11755, 2603, 1730, -4719, 2118, -3560, 2020, -5513, -828, 4869, 6686, 1224, 2484, -1048, 1258, -6406, -9003, -1844, 7966, -5982, 2834, 257, -12060, -2571, -399, 7284, 2855, 2137, 7453, -228, 8378, -5410, -7611, 2233, 10363, 959, 204, 6403, -2208, -9057, -1205, 10133, 6597, -3193, 1573, -9256, 1178, -1660, 423, 3115, 8276, -10066, -9202, 1808, -1862, -6246, -8949, -9359, 3781, 7604, 6050, 328, -2843, 1670, 5750, -1362, 490, -1824, -1695, -6753, 7309, -2915, -3351, -835, 4938, 1274, 839, 6488, -2967, -6740, -2742, 9887, 9589, -4916, 569, -583, -1105, 1792, -554, -677, -5544, -1202, 9332, 7015, 4194, 847, -5562, 6385, 7952, -13964, 3095, -2044, -4642, -12211, -11113, 803, 6275, 3938, 11288, -3246, 7863, 5390, 1234, -2093, 10643, -7571, 9591, -1187, -6426, -10116, -2729, -1892, 11679, 2705, 383, 5100, 290, -1186, -5636, 3468, 8022, -4437, -7619, 1079, -6484, -5701, -6167, 5154, 2463, -4677, -678, 1465, 2782, -1074, -3588, -1667, 8992, -10088, 5435, -2560, 3760, -13964, 941, -3134, 7520, -5560, 4607, -6430, 7678, -7308, -4429, 6823, -24, -6644, 9550, 8560, -8120, -6287, -1422, 5070, -3360, 10365, -1586, 2224, 2928, -6037, -9535, -4078, 7441, -2257, -2203, 3939, -2139, -854, -1630, 1062, 1906, 910, 510, -6428, 6919, -2506, -12797, -3276, 822, 1002, -2871, 8174, -8013, 47, -2337, 6914, -1141, 1825, -5894, 2829, 9621, -1258, -1760, -7474, 4528, -4157, 4937, 3116, -6704, -6168, 357, 11296, -721, -2325, 4340, 6459, 4289, -4798, -3662, 2985, 6979, -5045, 1388, 7683, -1556, -1681, -8961, 12688, -6371, -5467, 1561, 11487, 169, 5750, -6795, 3916, -2576, -10949, 6332, -7643, -3722, -8052, -6156, -2037, -713, -4781, 15583, 1208, 2386, 460, -923, -1273, 2499, -2653, 2952, -3185, -6835, -5247, -3670, 4576, 2211, 5279, -313, 806, 3856, -12356, -4425, 2318, 4636, -281, 4072, 11650, -4005, 3906, -4887, 10698, -2211, -1905, 191, }; +//int32_t encoder_out[1936] ={-3006, -13563, -12330, 18429, -5740, 7757, -11785, 19611, 5385, -14561, -4444, -13231, -273, -10749, 1769, 14144, 6853, -7264, -3989, 9728, 6174, 14216, -13342, 20866, 8739, -9327, -15258, -12849, 11503, -16206, 6678, 4712, -3368, -10248, -323, 17739, 14650, 9631, -22149, 18791, 8398, -12585, -14408, -19795, 9133, 7335, -2016, 218, 3745, -8689, -3055, 8517, 19150, 15896, -17422, 15479, 8259, -11139, -19673, -16118, 13716, -2489, 4658, 10756, -8425, -1803, -6892, 18482, -7281, 2743, -5683, 20533, 17587, -5318, -5861, -19906, 5187, -1484, 11114, 7230, 228, -6363, -6655, 9139, 10365, 14506, -7711, 16482, 16422, -16187, -11228, -14695, 18943, -13552, 882, 2345, -11537, -6686, -11743, 7935, 7791, 17995, -10134, 17477, 20963, -15352, 3390, -7308, 7919, -5904, 5447, -2132, -1507, -5768, -3574, 4260, 2652, 4375, -17098, 18282, 7600, -16904, -13845, -10678, 3984, 7624, 6440, 18787, -4814, -13887, -3132, 16328, 2480, 14219, -15608, 12369, 9305, -6755, -9780, -9805, -5951, 7635, -752, 10670, -12533, -1822, -5518, 14468, 5185, 10349, -16181, 20586, 11674, -16543, -15452, -10119, 14549, -6957, -6, 9185, -723, -2247, -6201, 13563, 6180, 16249, -20590, 20376, 10058, -7715, -3023, -17945, 3895, -5125, -2581, 8922, -2947, -8726, -6576, 454, 5031, 8435, -17115, 13176, 8105, -15541, -9771, -26546, 11608, -5647, 2820, -7509, -6901, -8206, -9755, 8543, -4364, 13458, -13971, 14118, 14418, -17485, -10573, -13533, 3500, 3417, 1789, 2659, -978, -5582, 1754, 15694, 16021, 4131, -25353, 19627, 4040, -17391, -14517, -908, 8276, 5537, -632, 4351, -5816, -9106, 1921, 17213, 11727, 17095, -21631, 14579, 12311, -9099, -14541, -11745, 4595, 4505, 1362, 3649, -8561, -4528, -7242, 1546, 12875, 10656, -23093, 14368, 9969, -10482, -12326, -17341, 8191, -4029, 394, 1754, -4055, 5990, -5765, 14625, 4312, 6787, -27034, 9123, 10688, -12565, -11754, -11023, 5809, -1559, 1929, 21333, -4137, -3938, -12844, 10591, -577, 14611, -11639, 24979, 7176, -26631, -1815, -11506, 18175, -2329, 7633, -5593, -5884, -4737, -5611, 11342, 7139, 11005, -11085, 19903, 12770, -13858, -8696, -21227, 17759, -8275, 9465, -767, -10777, -3937, -4997, 19747, 3537, 5078, -11440, 19340, 2302, -15039, -12820, -14607, 2856, -841, 3066, 3019, -3662, -1769, -10455, 13468, 4293, 16466, -18227, 16129, 3082, -13989, -7767, -13065, 8357, 2831, 6949, 5188, 3071, -9636, -7742, 5922, 5691, 15255, -25481, 17238, 8637, -13963, -19659, -15803, 6774, 81, -32, 1563, 2272, -18979, -5995, 21439, 8942, 882, -13145, 12693, 12852, -1774, -13667, -12866, 4715, -8892, -4644, 11093, -422, -5046, -10092, 9053, 4390, 18136, -20282, 20232, 11824, -28001, -6060, -18339, 7227, -10905, 11389, 7704, -5617, -4712, -9613, 13707, 2698, 10574, -14994, 15975, 19634, -19674, -6834, -15951, 15005, -10525, 13284, -2557, -7022, -5978, -9209, 13370, 5896, 17525, -17853, 23255, 10249, -15506, -12905, -14879, 7564, -6889, 9077, 4961, -5693, -13709, -3604, 18055, 9899, 13762, -11124, 16051, 12696, -9712, 1954, -12613, 9317, -8709, -1939, 8967, 1074, -7952, -4365, 1336, 14539, 11503, -16097, 14413, 10291, -7622, -18878, -11665, 12678, -6553, 3328, 10297, 6128, -7062, -776, 21889, 6628, 14075, -23131, 19239, 16078, -4247, -13226, -18217, 1223, -3829, -9830, 14185, 7628, -11920, 4644, 13153, 16201, 15229, -17074, 24769, 9515, -4742, -10565, -9459, 1060, -10122, -2606, 3948, -1114, -12072, -5986, 20459, 11262, 9498, -19128, 16965, 9743, -10716, -4806, -8878, 6640, -6002, -2477, 7561, 1982, -2676, -5055, 535, 11206, 21236, -22742, 25469, 9341, -15296, -17869, -11445, 16623, 1860, 1645, -1316, -3186, -7917, 3771, 11779, 10191, 20504, -18291, 20597, 3803, -19284, -25289, -9539, 8301, 5012, 5881, 5836, 423, -9288, -6980, 9044, 9488, 11661, -12011, 13275, 6737, -27917, -19263, -11345, 12851, -6200, 10087, 8955, 805, -7845, -9519, 6972, 5407, 11348, -25740, 15166, 12016, -13473, -11119, -7590, 13181, -6210, 4865, 1932, 1081, -9226, -6301, 8222, 638, 11695, -14984, 17147, 14184, -20129, -11090, -19273, 14319, -6545, 7140, -2883, -7634, -6844, 1066, 10066, 2738, 9623, -11962, 14367, 9260, -13035, -5203, -21472, 9516, -15976, -5773, 1460, -9266, -4569, -13189, 17706, 5167, 17608, -25065, 18705, 8341, -16412, -8140, -8555, 12759, -4921, 7306, 7143, -5731, -4578, -9634, 13517, 8002, 10713, -12955, 22717, 12124, -18190, -5714, -10473, 5509, 5176, 6163, -359, -8158, -2435, -10629, 8846, 6458, 14548, -23898, 22129, 3490, -21086, -17176, -1972, 10069, 4788, 2566, 15234, -10502, -7098, -6553, 8756, 422, 16611, -15354, 21749, 13913, -13106, -9909, -11836, 11777, 2514, 5699, 2834, -9025, -9450, -2209, 14080, 8578, 1880, -21538, 21410, 11247, -3034, -10588, -21030, 5698, -3899, -6210, 8263, 1423, -8707, -5358, 11613, 14847, 15042, -9044, 13159, 12370, -21378, -18525, -16342, 6187, -1641, -1324, 601, -6478, -3701, -10467, 3996, 8764, 12689, -15030, 19272, 9605, -18728, -19845, -3559, 5652, -3275, 1863, 5597, 953, -12340, -1849, 15916, 6577, 6932, -6837, 14165, 10642, -8840, -5685, -19038, -506, -466, 640, 11242, -2583, -8288, -9136, 1140, 3106, 8936, -15763, 19152, 5437, -10478, -6910, -17981, 11343, 596, -535, 9676, -956, -11538, -6862, 27331, 3241, 13859, -10920, 19079, 8564, -10570, -5761, -9812, 7378, 2110, 3067, 13426, -7632, 1378, -4034, 12624, 8594, 11389, -14816, 19965, 20021, -16429, -7859, -18291, 17532, -17084, 1335, 2532, -230, -10488, -12058, 9814, 9352, 7707, -17859, 16019, 7254, -23813, -13478, -12000, 4898, -3686, 4841, 7461, 2075, -11495, -3560, 8605, 9092, 10922, -23374, 13014, 9729, -19426, -15298, -4780, 6518, 3642, 2751, 5038, -7917, -4041, 3806, 10222, 9947, 13664, -18028, 22791, 5628, -20491, -13863, -4558, 4180, -2485, 7495, 8047, -8674, -6502, -7094, 20470, 4307, 5030, -11802, 25527, 13764, -24719, -19127, -150, 2611, -1029, 10121, 7295, -564, -2071, -8611, 7205, 7906, 19158, -4511, 22058, 12822, -15749, -13811, -15922, 10977, -8554, 572, -3316, -3058, -12151, -7466, 17638, 7109, 15570, -11320, 12053, 16600, -16480, -12338, -18142, 7339, 1133, -639, 4681, -2768, 563, 140, 10280, 18510, 7490, -20426, 21980, 7790, -12230, -10133, -20188, 7033, 4754, -724, 3781, 1123, -4142, 542, 6839, 4322, 13990, -27587, 16011, 10164, -13827, -21794, -13802, 6966, -11049, 212, 10254, -5240, -7852, 48, 18922, 7869, 20456, -21871, 15636, 8900, -14475, -15940, -3293, 4716, 4900, 4879, 5831, -10344, 5091, -8364, 12194, 5127, 6790, -17157, 19659, 17195, -20674, -6316, -10681, 818, 5437, 5760, 15987, 26, -12619, -5085, 5931, 11086, 16895, -15453, 17332, 11797, -11451, -12670, -18508, 8468, 2444, -226, 3621, -4802, 518, 1732, 9351, 3782, 13992, -8001, 21509, 2538, -13698, -2189, -17680, 11326, -8055, -7364, 2616, -4362, -5926, 1259, 17264, 6588, 10125, -11527, 23188, 336, -15507, -11028, -5887, 6504, -827, -376, -1999, -1245, -15610, 133, 23226, 13612, 13851, -13972, 12359, 5370, -14127, -16831, -6162, -1943, 1322, 3421, 5663, -5809, -11947, -5660, 15584, 12366, 13584, -25102, 11684, 17176, -21626, -11137, -10079, 10452, -5009, 10119, 5420, -65, -11647, -8754, 3245, 10677, 9533, -12684, 18626, 4942, -17226, -16617, -6602, 7393, -8438, -4143, 6338, -2537, 284, -9020, 5285, 10882, 15554, -17336, 21522, 16400, -11034, -17315, -17011, 11620, -7641, -1386, 8084, -2420, 69, -2624, 10573, 11725, 19946, -5672, 15176, 12457, -22436, -3894, -8411, 4078, -16955, 12734, 4176, -6871, -5084, -10675, 13733, 14814, 6282, -11763, 18189, 5281, -9665, -13267, -7431, 3116, -1217, -1328, 10698, -4987, -11999, -6191, 13751, 6734, 21035, -14470, 21428, 3669, -10964, -18630, -7913, 3893, -11562, 3538, 9623, -2585, -10690, -1158, 8651, 8416, 13162, -4612, 17794, 11025, -16093, -10889, -11824, 14167, 4031, 7210, -1987, -2342, 118, -6577, 4108, 14469, 19290, -20145, 15233, 18126, -18927, -19462, -10776, 17850, -8965, 2825, 8776, 9353, -12187, -6053, 16045, 10053, 11844, -18217, 17431, 14030, -6834, -14632, -22585, 3625, -7252, 9905, 4965, -6913, -6715, -10856, 1146, -4132, 13295, -5848, 22031, 3541, -14635, 853, -16929, 14867, -10080, 10242, 5538, -2911, -5900, -6975, 20120, 9190, 18659, -9922, 19385, 24080, -11026, -9187, -18048, 15138, -20644, 7384, -1591, -3322, -7729, -7178, 7882, 12850, 17169, -29152, 18653, 10324, -11162, -15366, -16757, 15256, 2707, 2295, 7212, -5099, -8408, -8961, 5473, 10208, 11194, -31132, 19405, 14988, -16836, -9705, -13365, 15011, 6886, -322, 15129, -2238, -4700, -2510, 15719, 12068, 15263, -17201, 18006, 5600, -14695, -13099, -10819, 5409, 6557, 1060, 20661, -1231, -8256, -6287, 13102, 1531, 15969, -12840, 14428, 12701, -8763, -15013, -14635, 16024, -1976, 8039, 8323, 1163, -4029, 1295, 13050, 5608, 12345, -22125, 21563, 18581, -11256, -10267, -24770, 3444, -2881, 479, 2431, -8476, -15408, -8011, 6272, 12904, 6282, -12405, 13611, 10172, -15424, -14768, -9625, 4751, -8107, 2882, 6915, 558, -1968, -7735, 11214, 1121, 18832, -16162, 14475, 10584, -7412, -18754, -9101, 6134, -5932, 8014, 5473, -2118, -128, -7230, 8462, 4284, 8683, -19400, 13767, 9541, -19055, -12613, -9168, 5520, 6085, 5818, 19566, -4967, -8263, -10320, 5186, 11308, 5608, -19345, 9650, 10010, -18178, -15500, -7019, 875, 728, -2431, 8600, -489, -1635, -8656, 6244, 627, 9692, -10156, 17995, 10687, -24421, -22420, -16582, 19462, -3430, 14473, -2169, -4748, 299, -5356, 11832, 777, 13351, -1567, 22147, 12026, -13901, -7808, -10741, 13146, -16640, 3079, -3068, 751, -285, -4640, 15415, 6281, 11059, -11255, 11059, 12984, -12162, -13589, -17987, 8424, -8545, 4051, 4753, -1922, -2756, -4453, 12951, 8903, 7796, -10048, 15724, 13579, -23594, -8454, -9019, 10395, 5265, 9772, 3949, -7364, -5175, -6215, 14174, -650, 14808, -12845, 28486, 12197, -19556, -5598, -16908, 11933, 1177, 331, -3723, -3169, -10619, -11448, 11612, 5069, 10765, -16340, 18499, 12963, -15722, -17082, -7403, 10093, -5279, -483, -1019, -2179, -6192, -9761, 138, 4022, 16176, -21635, 17535, 6239, -16161, -19177, -13231, 12251, -9925, 1566, 10893, -14047, -2666, -4217, 5942, -1564, 12132, -16661, 16392, 9506, -19765, -3372, -14345, 10870, -8606, 8542, 4691, -1876, -1064, -1200, 3602, 1012, 16364, -13975, 19559, 20924, -21303, -4196, -21408, 21603, -2487, 7945, 14237, 1470, -5301, -5154, 7858, 792, 6535, -16442, 18356, 9757, -8942, -21051, -11587, 8733, -2330, -4570, 13093, -5873, -6572, -2524, 8223, 7618, 8123, -18128, 12879, 9984, -23137, -11363, -12249, 15711, -3050, 5569, 12160, 4083, -2078, -8447, 9337, 6811, 12941, -19345, 21916, 8262, -18851, -20268, -15872, -1733, -1214, -2670, 11017, -4959, -157, -5468, 6929, 5662, 15289, -18151, 22569, 16912, -15083, -15593, -17894, 5010, -3382, 9746, -40, -5306, -3361, -6415, 16370, 952, 11072, -14498, 11353, 12985, -17035, 618, -11686, 12166, -13891, 12010, -3450, -1176, -9985, -753, 6891, 9043, 11060, -20824, 26305, 11316, -17920, -14594, -9230, 2777, -8907, 6890, 3935, -2320, -2538, -7024, 1691, 16832, 16628, -10460, 15082, 24286, -16158, -13634, -13556, 9365, -9506, 6446, 4493, -3193, -4061, -2893, 13112, 2437, 16475, -16245, 16377, 6162, -18041, -6740, -17056, 14220, 288, 9610, -2208, -8660, -4425, -4622, 8500, 3326, 12309, -10290, 16961, 18099, -23750, -14866, -14424, 8017, -5322, 4468, 3755, -11645, -5534, -10514, 12200, -474, 13851, -19413, 12801, 18684, -17540, -9202, -9935, 15524, -4871, 1224, 3998, -5864, -7892, -1162, 20918, 6517, 14193, -11343, 12942, 14462, -15089, -7462, -19859, 10933, -14142, 98, 3743, -7844, -3084, -3274, 8235, 5354, 10502, -16842, 17912, 22126, -11752, -15506, -15935, 17307, -7699, 1119, -935, 961, -2984, -12227, 813, 6519, 13134, -18401, 19312, 5803, -11180, -14533, -10765, 10838, 366, 1436, 5799, -6026, -9234, -9767, 4700, 524, 16873, -18033, 19048, 10559, -23621, -11091, -10671, 13415, -3442, 3701, 9035, -2814, -2557, -9638, 5850, 6306, 18884, -11488, 18210, 17064, -13909, -16839, -11630, 17459, 1751, -1371, 2436, -11033, -7206, -6848, 14214, 7744, 16099, -20816, 8966, 13109, -14437, -12666, -18172, -3320, -1772, 8626, 7304, 10, -11047, -3896, 21065, 4666, 9300, -11349, 16631, 3824, -5909, -7915, -14171, 7029, -667, 3960, 1565, 2782, -12537, -10300, 11758, 12762, 18572, -15625, 17045, 9661, -11897, -5784, -10756, 5216, -13503, -805, 11559, 3901, -6574, -3466, 6907, 10363, 17436, -26414, 20128, 8295, -17817, -20323, -20804, 7154, 1155, 5136, 13470, -5469, -1455, 807, 15944, 2686, 18128, -17961, 27966, 9550, -18449, -16653, -13179, 4493, 7287, 5197, 760, 1500, -10621, -5921, 7359, 7581, 17717, -17649, 10306, 11416, -18892, -14387, -16829, 13281, -2882, -1957, -351, 1159, -6311, -6635, 10989, 3535, 16933, -22238, 24300, 9058, -7718, -21583, -9173, 2480, 2573, -5305, 4740, -9380, -2832, -9839, 9766, 11385, 8620, -16707, 25052, 17508, -20031, -13020, -12162, 12100, -10151, 12370, -79, -1518, -7732, -9555, 4088, -686, 15800, -13213, 14653, 14378, -13888, -8837, -12851, 8542, -3624, 3106, 1206, -10739, -3570, -5822, 1881, 634, 8596, -9144, 13755, 18369, -20422, -7515, -13588, 15796, -6124, 5742, -5391, -2255, -170, -5938, 12486, -4898, 12070, -15414, 22543, 14595, -19373, -14154, -11389, 18806, -4725, 1237, 4293, 2099, -6089, -9000, 9513, 5640, 14807, -15826, 16983, 18406, -13532, -9893, -21230, 22742, -11495, -2039, 1731, 7707, -9512, 957, 6361, 8277, 5846, -22667, 24396, 3553, -17504, -15340, -16114, 3937, -5080, -2916, 16451, -2466, -7719, -3050, 13639, 2875, 11755, -13224, 19848, 6314, -19502, -12653, -14361, 11483, -3612, 7826, 924, -3683, -6214, -15062, 9777, 4574, 11937, -9206, 19258, 21549, -14860, -2556, -16578, 19355, -8190, 907, 1251, }; +int32_t prototypes[32] ={-1394, -5770, -6778, 762, 4001, -653, -5906, -20, 1220, 3795, -73, -3028, 635, -448, 7677, -6204, 5745, 3112, 1206, -1120, -3618, 1076, -649, 943, -3896, 2462, 4658, 2494, 3996, 1220, -1144, -1013, }; diff --git a/sw/applications/trans_versasense/data_cpp/signal_fft.cpp b/sw/applications/trans_versasense/data_cpp/signal_fft.cpp new file mode 100644 index 00000000..0a6d510e --- /dev/null +++ b/sw/applications/trans_versasense/data_cpp/signal_fft.cpp @@ -0,0 +1,5 @@ +#include "stdint-gcc.h" +//int16_t raw_signal[63840] ={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5849, 4599, 5297, 6397, 5747, 4963, 4620, 3465, 2077, 2170, 2567, 1298, 224, 918, 1134, 70, -1176, -1533, 78, 1668, 1019, 357, 1399, 2719, 2875, 3113, 3791, 3588, 2993, 2855, 2823, 2518, 2054, 1534, 860, -389, -1264, -562, 1080, 2241, 2661, 2351, 1737, 2055, 3061, 2955, 2289, 2336, 2151, 1510, 1127, 606, -153, -422, -454, -1221, -1970, -1413, -298, 909, 1961, 1931, 1654, 2362, 3193, 2845, 2308, 3734, 5038, 3509, 2292, 2940, 3575, 3513, 3498, 5355, 7998, 8626, 7894, 7480, 7145, 6723, 5763, 4679, 4948, 5339, 5245, 5243, 4910, 4141, 4096, 5108, 5209, 4333, 4346, 4077, 2613, 1609, 1184, 901, 431, -316, 208, 1103, 1317, 1968, 1945, 1032, 1340, 2938, 3570, 3053, 3442, 5119, 6528, 6137, 5669, 6507, 7084, 6895, 6640, 6863, 6633, 5728, 5797, 6282, 6061, 5313, 4562, 4310, 4016, 3754, 4358, 4912, 4568, 4439, 4676, 5123, 5417, 4891, 4855, 5804, 5863, 5025, 4791, 4370, 3575, 3600, 3355, 2517, 2197, 2242, 1751, 1445, 1912, 2360, 3166, 4624, 5452, 5575, 6714, 8939, 10366, 10538, 10580, 11097, 11980, 12026, 11472, 11360, 10425, 8238, 7539, 9333, 10745, 10337, 9847, 10492, 10754, 10355, 10923, 11822, 12505, 14193, 16086, 17168, 18432, 19662, 19885, 19388, 19917, 21699, 22569, 21976, 21168, 20377, 19213, 18977, 20876, 22280, 21136, 20103, 20425, 21003, 21743, 21721, 21049, 20909, 20955, 20691, 20009, 18784, 17146, 16232, 15409, 13174, 11056, 10207, 9992, 9412, 8479, 8065, 7894, 7360, 6357, 4829, 3949, 3855, 2811, 1517, 581, -691, -2031, -3121, -3504, -3962, -5158, -5555, -5670, -6859, -7535, -7233, -6869, -6010, -5300, -5781, -6418, -7125, -8381, -9371, -9471, -8972, -8554, -8777, -9076, -8820, -8896, -8819, -8343, -8549, -9153, -9116, -9148, -10496, -11843, -12227, -12749, -13587, -13799, -13327, -13176, -13678, -14113, -14438, -15019, -15753, -16449, -16143, -15676, -16217, -15462, -13743, -13779, -14065, -12564, -10591, -9655, -9212, -8564, -7890, -6956, -6316, -6713, -7017, -6771, -6694, -6403, -6350, -7558, -8371, -8131, -9638, -11930, -11575, -10754, -11631, -13128, -14557, -14878, -14086, -13482, -13214, -13098, -13242, -12869, -12087, -11955, -11531, -10487, -10501, -10855, -10500, -10328, -10252, -9738, -8739, -8154, -8277, -8035, -7748, -8174, -8612, -8631, -8428, -8038, -8024, -9091, -9476, -8662, -9308, -10349, -9563, -8710, -8727, -8508, -7945, -7717, -8212, -9068, -9257, -8640, -7854, -6892, -5905, -5452, -5320, -5762, -6461, -6944, -7980, -8565, -8065, -8405, -9283, -8486, -7376, -7555, -7690, -7060, -6798, -7168, -6926, -7321, -9701, -11275, -11203, -11563, -11730, -10869, -9957, -9163, -7796, -5798, -4732, -5190, -5673, -5138, -4623, -5408, -6481, -6883, -7499, -7387, -5469, -5129, -7158, -7817, -7148, -6878, -7210, -7706, -7435, -6757, -6231, -5823, -5540, -5569, -5712, -5348, -5014, -5819, -6900, -6310, -5204, -5783, -6790, -6958, -7025, -7462, -6961, -5191, -3814, -3894, -4524, -4853, -4823, -4001, -4012, -5785, -7291, -8329, -9425, -10275, -11352, -12781, -13700, -13934, -14429, -15287, -14843, -14035, -14678, -14840, -14011, -14153, -14961, -15037, -14470, -14022, -13910, -14044, -14314, -13802, -13000, -13249, -13768, -13442, -12209, -11192, -11248, -11264, -10793, -10864, -10954, -10327, -10050, -10381, -10620, -10692, -10863, -11190, -10859, -9830, -9275, -9157, -8730, -8352, -8280, -8124, -7930, -8046, -8475, -8786, -8611, -8281, -8509, -8656, -8586, -9117, -9496, -8916, -7935, -7261, -7328, -6744, -5010, -3815, -3676, -5087, -7297, -8405, -7933, -7386, -7712, -7153, -5672, -4975, -5080, -5492, -5970, -6618, -6879, -6568, -7061, -7070, -6009, -5800, -6320, -7189, -8359, -8545, -8225, -8893, -9872, -9030, -7780, -8030, -7998, -7114, -7205, -8469, -8509, -7267, -7623, -7872, -5537, -3448, -3213, -3570, -3242, -2121, -2080, -3313, -4262, -4437, -4728, -5830, -6445, -5600, -5069, -5687, -5322, -4458, -5042, -5821, -5249, -4359, -4159, -4559, -4926, -4565, -4065, -4518, -6069, -6763, -5275, -4518, -5702, -6307, -5730, -5059, -4729, -4972, -5613, -6657, -6904, -5409, -4272, -4174, -3623, -2763, -2910, -2971, -2156, -1677, -1815, -2873, -4257, -4516, -4544, -4971, -4939, -4714, -4510, -4278, -3505, -2372, -2575, -3646, -3727, -3408, -3408, -3220, -2934, -3129, -3519, -3292, -3095, -3232, -3278, -3828, -5033, -5427, -5044, -5495, -6031, -5891, -6129, -5848, -5016, -5547, -6113, -5390, -5900, -6780, -5589, -4797, -5384, -4516, -3560, -4122, -4366, -4059, -3439, -3097, -3794, -4902, -5031, -4596, -5015, -5432, -4991, -4457, -3936, -3412, -3419, -3509, -2561, -1463, -1304, -1267, -1425, -2227, -1970, -612, -303, -1532, -3212, -3506, -3270, -3741, -4225, -4192, -4300, -4206, -2786, -1041, -1215, -2773, -2792, -2059, -2698, -2909, -2498, -3426, -3768, -2399, -1849, -2450, -2703, -2602, -3014, -3240, -2841, -3088, -3759, -3676, -3291, -3646, -4069, -3935, -3920, -3878, -2864, -1419, -1130, -1945, -2812, -2705, -2105, -2381, -3190, -3190, -2605, -2287, -1703, -988, -1219, -1757, -956, 361, 776, 420, -325, -692, -526, -505, -714, -706, 60, 1414, 1542, 391, 644, 1703, 1168, -125, -309, -205, -651, -1037, -1379, -1364, -477, 390, 570, 977, 2175, 2655, 2638, 3066, 3117, 3054, 3498, 3715, 3661, 3816, 3867, 4185, 5564, 6020, 4367, 2936, 3117, 3963, 4029, 3141, 2293, 1434, 463, 618, 1355, 853, -266, -642, -242, 591, 618, -539, -1603, -1630, -832, -752, -738, 124, 355, -188, -245, 555, 1004, 843, 1426, 2020, 1528, 1878, 4052, 4730, 3017, 2534, 3487, 3498, 3669, 4787, 5030, 4616, 4822, 4853, 4776, 5640, 6016, 5025, 3901, 3897, 5536, 6555, 5762, 6268, 7903, 7185, 5356, 5980, 6920, 5042, 3575, 4040, 3793, 3511, 4426, 4038, 3199, 3813, 3966, 3207, 3087, 3799, 3218, 1066, 1225, 3368, 3500, 2488, 2810, 3724, 3722, 3033, 2339, 1615, 485, -859, -1269, -718, -782, -1357, -984, -342, 139, 1213, 2030, 2293, 3060, 4187, 3736, 2823, 3444, 3633, 3184, 3630, 4298, 4220, 3853, 3877, 4185, 4277, 3796, 3366, 3412, 3335, 3234, 3533, 3350, 2255, 1751, 2336, 2835, 1740, -131, -743, -325, -273, -1324, -2983, -3430, -2937, -3045, -2686, -1855, -1134, -325, -323, -990, -633, 491, 334, 114, 1302, 2161, 1952, 2612, 4264, 3467, 1280, 2688, 5130, 4719, 3567, 3873, 4697, 4389, 2920, 2372, 2801, 2579, 2290, 1938, 862, 205, 910, 2316, 2217, 568, 370, 905, 21, -1016, -500, 677, 949, 1108, 1977, 2704, 2762, 2754, 3367, 3232, 2099, 2574, 4164, 4535, 3935, 4300, 5037, 4070, 3128, 3500, 2569, 800, 487, 1223, 1655, 1357, 1022, 1041, 1107, 304, -1069, -755, 97, -482, -1285, -1673, -1667, -1046, -590, -926, -843, 176, 1349, 3045, 4450, 3787, 2493, 2545, 3044, 2705, 2236, 1921, 1680, 1700, 1384, 791, 498, 873, 1823, 1456, -280, -1056, -954, -533, 296, 406, 497, 1139, 410, -429, 595, 41, -1875, -1416, -1091, -1490, -355, 595, -231, -1279, -833, -170, -182, 1080, 1878, 1344, 2197, 3713, 4259, 4677, 5649, 6662, 6920, 6335, 6229, 7327, 8007, 7345, 6985, 7802, 7883, 7103, 7232, 7229, 6498, 6206, 6043, 5473, 5087, 4308, 2605, 2171, 3305, 3415, 2547, 2673, 3735, 3653, 2376, 2591, 2829, 1197, 355, 626, 1119, 1231, 48, -733, 140, 882, 506, 347, 691, 720, 969, 1504, 1481, 1467, 2091, 2958, 3239, 2498, 1734, 2127, 2323, 1180, -553, -2014, -2200, -2117, -2617, -2301, -1393, -1464, -1557, -600, -24, -848, -727, 1180, 2199, 1693, 1593, 3033, 5052, 5942, 5685, 5547, 6170, 6169, 5161, 4219, 3686, 3898, 3787, 2897, 3019, 3403, 3219, 3351, 2953, 3350, 4521, 3324, 1694, 2400, 2760, 1943, 1910, 2298, 2388, 2636, 3200, 3851, 4154, 3213, 2217, 2625, 2145, 854, 1443, 1914, 1013, 1629, 2811, 2300, 2185, 3715, 5150, 5797, 6038, 5772, 4851, 3791, 3311, 3412, 4183, 5533, 5511, 3868, 2999, 3559, 3936, 3198, 2230, 2177, 2365, 1980, 1928, 2397, 1990, 994, 475, 722, 907, 259, -396, -1127, -1462, -1463, -1973, -1732, -582, -820, -1840, -1734, -802, 500, 1408, 1074, 217, 293, 1655, 2588, 1656, 755, 1457, 2243, 2720, 3545, 3506, 2689, 3145, 3689, 2764, 2321, 2722, 2717, 1938, 1523, 1945, 2126, 2304, 2084, 1256, 1311, 1489, 1332, 2118, 2485, 2504, 3658, 3430, 1653, 1156, 1343, 1798, 1933, 872, 230, 486, 1235, 2190, 2460, 2801, 3989, 4549, 3207, 1401, 998, 1383, 1329, 1389, 2118, 2356, 1970, 2368, 3736, 3797, 2635, 2381, 2646, 2620, 2442, 1803, 1195, 1129, 856, 594, 644, 77, -1090, -820, 50, -651, -1727, -2236, -2409, -2290, -2152, -2005, -1600, -1614, -2137, -2218, -868, 1320, 1992, 1545, 1588, 1832, 1992, 1272, 356, 977, 1823, 1215, -142, 120, 1293, 1097, 1237, 2117, 1668, 1006, 1098, 792, 54, -327, -437, -691, -676, -339, 118, 486, 680, -240, -1893, -2077, -1245, -1756, -2514, -1500, -385, -253, -425, -955, -1649, -1751, -1166, -670, -875, -1652, -2254, -2011, -1781, -2499, -3147, -2636, -1289, -365, -752, -1154, -943, -1747, -1621, 412, 969, -244, -807, -382, 15, 321, 674, 472, 266, 791, 914, 1001, 1892, 3094, 2874, 1505, 2140, 4053, 4483, 4020, 4559, 5342, 4205, 3632, 5242, 5336, 3270, 1530, 604, 894, 2134, 3182, 3765, 3378, 3176, 3939, 3173, 1848, 2982, 4162, 2625, 1178, 1856, 2205, 1581, 1337, 846, 71, 236, 692, 122, -660, -103, 1036, 720, 468, 1569, 1512, 920, 1884, 2681, 2215, 2365, 3327, 3962, 4691, 5147, 4422, 3338, 3211, 4071, 4450, 3892, 3434, 3457, 2866, 2254, 2771, 2803, 2440, 2869, 2645, 1944, 2089, 2576, 2634, 2398, 2724, 3029, 2001, 1278, 1560, 988, 413, 949, 1131, 931, 1241, 1564, 2012, 3384, 5019, 5247, 4489, 4731, 5353, 4926, 5667, 6426, 4654, 3479, 4173, 4383, 3557, 3418, 4656, 5653, 5156, 4105, 3548, 3451, 3652, 3370, 1660, -195, 229, 1640, 1362, 754, 1338, 1569, 888, 898, 1250, 359, -923, -1711, -1818, -1392, -1582, -2085, -1769, -1384, -1178, -445, 578, 1597, 2763, 3361, 3103, 2486, 2535, 3325, 2839, 1987, 3064, 4315, 4615, 5050, 4917, 4116, 4189, 3663, 1506, 818, 2619, 3563, 2654, 2088, 2148, 1735, 1283, 1990, 3497, 3745, 2817, 2733, 2761, 1046, -869, -169, 1405, 1063, 464, 891, 1592, 1915, 1672, 1525, 1629, 1044, 872, 1632, 1554, 846, 714, 744, 780, 965, 448, -734, -782, 548, 1318, 1451, 1517, 1031, 616, 1189, 1712, 1149, 650, 578, 573, 432, -647, -1406, -717, 82, 346, 766, 1126, 671, 33, -354, -356, 234, -20, -987, -326, 656, 316, 28, -60, 68, 319, -65, 269, 1759, 1925, 854, 701, 1240, 1650, 2191, 2473, 1857, 686, 31, 37, -520, -1714, -1833, -1317, -2062, -2626, -1732, -1155, -1436, -1514, -1664, -1876, -1398, -950, -181, 1259, 1360, 813, 1755, 3037, 3292, 2752, 1894, 1968, 2757, 2476, 2246, 2614, 2781, 3693, 4666, 3774, 2776, 3195, 4010, 4011, 2838, 1783, 1631, 1718, 1580, 1373, 1603, 2132, 1118, -748, -159, 1689, 1404, 873, 2072, 2619, 1568, 1146, 2164, 3175, 4087, 4701, 4523, 5023, 5873, 6409, 7465, 7663, 6560, 5562, 4259, 2760, 2250, 3191, 4640, 5110, 4673, 4049, 3832, 3362, 2310, 1851, 1487, 381, 336, 1951, 2248, -139, -2022, -1943, -1789, -2290, -2281, -1807, -2447, -3474, -3603, -2874, -1199, -91, -815, -1765, -2034, -2021, -1852, -1924, -2264, -2703, -2514, -1767, -1870, -2230, -2004, -1726, -1834, -2251, -2694, -3100, -3077, -2289, -1141, -261, -27, 626, 1655, 1131, 46, 180, -821, -2901, -3746, -4263, -4340, -3506, -3698, -4008, -2452, -1267, -1334, -433, 1499, 1509, -340, -771, -380, -1004, -1713, -1728, -1303, -862, -1288, -2090, -1960, -1502, -1083, -992, -1628, -1375, -703, -1353, -2680, -3445, -2725, -1102, -1274, -2728, -2437, -2157, -3743, -5407, -5731, -4562, -3585, -4115, -3540, -1365, -411, -14, 646, -287, -1706, -1501, -387, 936, 1677, 260, -1139, -211, 1251, 1597, 1265, 1297, 1536, 1661, 1350, 266, 311, 2366, 2707, 1391, 1623, 2463, 2216, 1903, 1968, 796, -736, 271, 1135, -753, -1840, -1361, -1728, -2465, -1961, -668, -387, -775, -1486, -2401, -1768, -189, 130, -75, 164, -49, -53, 341, 341, 762, 1563, 1395, 491, -321, -1245, -1226, -200, -799, -2257, -1823, -606, -155, -32, -226, -262, 468, 699, -614, -1968, -1947, -943, -753, -1288, -491, 499, 40, -301, 461, 1616, 1595, 304, -1087, -1886, -1293, 52, 470, 67, 178, 1004, 1558, 1595, 1555, 1073, 254, 224, 361, -291, -427, 227, 1047, 2215, 2814, 2044, 1837, 2428, 2004, 1465, 1613, 1074, 466, 759, 271, -1553, -2269, -1015, -285, -1116, -1914, -1747, -1521, -2036, -2939, -3438, -2640, -1515, -2073, -3578, -3557, -2258, -2439, -3276, -2308, -1115, -1286, -1287, -994, -1734, -1615, 512, 1244, -60, 75, 1385, 1240, 520, 887, 1884, 1973, 668, -194, 517, 1823, 2633, 2528, 875, -805, -382, 377, -359, -423, 323, -312, -470, 1071, 1363, 461, 944, 1601, 1112, 645, 718, 842, 984, 1436, 988, -363, -630, -609, -1581, -1674, -1061, -1506, -1113, 74, 815, 1737, 2667, 3008, 1908, 202, -408, -93, -80, -639, -764, -318, 552, 1703, 1588, 156, -1041, -1148, -790, -1921, -3649, -3812, -2357, -1079, -1603, -2245, -1394, 60, 606, 21, 105, 845, 607, 452, 1454, 2231, 1913, 1703, 2153, 2386, 2169, 2305, 3177, 3696, 3201, 2487, 2364, 2503, 3014, 4223, 4684, 4287, 4689, 5097, 4159, 2887, 2231, 1171, 155, 434, 354, -984, -718, 1733, 2034, 1214, 1960, 1080, -434, 634, 1226, 129, 51, 640, 984, 1948, 2080, 1197, 2233, 3614, 2245, 439, 569, 967, 547, -307, -788, -159, 718, 1239, 1456, 1834, 2446, 1721, 333, 678, 589, -1688, -2688, -1802, -1309, -1551, -2502, -3552, -3267, -2742, -3136, -3143, -2903, -3043, -2054, -984, -1741, -2291, -874, 970, 1329, 621, 921, 1796, 1452, 1033, 1299, 1451, 1654, 2487, 3165, 2323, 1305, 1887, 3206, 3727, 3146, 2210, 1431, 1193, 2063, 2984, 2783, 1336, 635, 1784, 2351, 2198, 3020, 3490, 2139, 441, -302, -27, 1373, 2233, 1887, 1438, 818, 1449, 2984, 2642, 2232, 2572, 2124, 2247, 3172, 3989, 4954, 5473, 4893, 4274, 4087, 3639, 3199, 3397, 3208, 1974, 1567, 2552, 3323, 2703, 1514, 1977, 3309, 3136, 2090, 1704, 1295, 58, -648, -163, -202, -831, 410, 1958, 1310, 1034, 2175, 1927, 223, -275, 798, 1514, 1061, 1585, 2804, 3220, 3751, 4550, 4054, 2425, 2201, 3419, 3007, 1221, 1332, 2955, 3232, 2339, 2527, 3721, 4037, 3276, 2928, 2075, -162, -1721, -1703, -805, -88, 19, 601, 908, -169, -984, -1111, -1574, -1569, -580, 21, -143, 59, 1077, 2076, 1730, 789, 772, 958, -303, -1640, -1418, -712, -1137, -2210, -1802, -438, -137, -544, -486, -163, 281, -103, -731, -272, 296, 428, -22, -972, -1659, -1085, -372, -947, -1354, -790, -295, -519, -714, -153, 814, 1076, 483, 231, 633, 1566, 2501, 2159, 1114, 1201, 2194, 2007, 593, 163, 1225, 2115, 1125, -789, -1149, 130, 1007, 329, -1162, -1709, -630, 44, -349, 95, 737, -505, -1922, -1133, 264, 449, 220, 596, 1007, 486, -36, 410, 853, 739, 747, 965, 232, -1050, -710, -106, -1070, -2173, -2312, -1999, -600, 945, 324, -402, 657, 1605, 340, -2419, -3242, -2290, -1854, -1897, -2335, -2793, -2533, -2135, -2191, -2551, -2940, -2251, -1335, -3169, -5287, -4603, -3705, -3495, -2552, -1976, -1571, -190, 427, 123, 412, -580, -1800, -1339, -1578, -2043, -1679, -1678, -1850, -2104, -2798, -2826, -2144, -3019, -4758, -4975, -4600, -4037, -3800, -4540, -3998, -2601, -2284, -2289, -2984, -3621, -3506, -3845, -3880, -2953, -2048, -1782, -2248, -3587, -4905, -4508, -3138, -2767, -3458, -3610, -2521, -1891, -1650, -958, -1595, -2174, -625, -528, -2642, -3533, -3356, -3773, -4602, -4605, -3989, -3956, -3624, -2177, -1102, -927, -1699, -3369, -3861, -2638, -2331, -3469, -3916, -3794, -4157, -4109, -3887, -4732, -5542, -4215, -3720, -5770, -6066, -4859, -5040, -5304, -4225, -3010, -3293, -3676, -2688, -2022, -1526, -214, -289, -1294, -1236, -1056, -823, -403, -284, -436, -1230, -1807, -1881, -1939, -800, -68, -1540, -2767, -2756, -3388, -3740, -3032, -3411, -4212, -3644, -3489, -3716, -3437, -4542, -5311, -3499, -1801, -2127, -2389, -1653, -1204, -876, -400, -480, -401, 234, 677, 707, 361, 608, 1122, 768, 593, 237, -1174, -1823, -968, -747, -1594, -1294, 158, 648, -535, -2148, -2817, -2709, -2857, -3153, -2644, -1987, -2047, -2116, -1779, -1507, -1867, -2995, -3981, -4174, -4737, -5731, -6390, -6401, -4829, -2607, -1378, -976, -405, 220, 161, 598, 1296, 1103, 772, 971, 1107, 1086, 1365, 1304, 1190, 2173, 3113, 3039, 2758, 2875, 2866, 2427, 1948, 1914, 1924, 2213, 3156, 3664, 3111, 1832, 755, 722, 945, 141, -812, -1033, -1203, -916, -356, -1207, -1990, -865, -281, -149, 1474, 1889, 307, -588, -84, -100, -1636, -2308, -997, -464, -1564, -1604, -255, 17, -405, -251, -1386, -2655, -1781, -1409, -2220, -2549, -2841, -2181, -1040, -1807, -3445, -3744, -2730, -1842, -2521, -4395, -5103, -3904, -2366, -2341, -3527, -4152, -3472, -2434, -2079, -1633, -1715, -2608, -2264, -1425, -1200, -880, -680, -606, -626, -397, 371, 653, 138, -527, -21, 1654, 1427, -222, 36, 1394, 1874, 888, -166, 17, 38, -796, -273, 1987, 2206, 33, -611, 85, 277, 854, 1128, 832, 993, 1350, 1508, 2092, 3666, 3459, 1525, 1411, 1900, 1799, 2059, 1827, 1869, 3075, 3035, 1398, 564, 706, 1145, 1668, 1380, 2073, 3775, 3347, 2229, 2189, 1554, 151, -816, -1605, -2371, -1851, -348, 394, -633, -1730, -684, -62, -1260, -895, 524, -59, -1867, -2382, -1591, -1374, -1500, -560, 831, 1427, 2387, 3339, 3371, 3406, 2885, 1940, 2349, 3203, 2124, 326, 218, 1135, 871, -155, -192, 20, -685, -105, 2188, 2227, 909, 1474, 1987, 1753, 2461, 2553, 1104, 139, -49, -1036, -2294, -2194, -2639, -4155, -3528, -1449, -382, 84, 2, -892, -1224, -781, -524, -756, -1134, -639, 182, -232, -325, 938, 1075, 476, 466, -550, -1131, -195, -464, -1623, -2071, -2346, -2682, -3318, -3351, -2415, -2080, -2310, -1238, 26, -1779, -4902, -5247, -3809, -3420, -2637, -837, -949, -2431, -2913, -3122, -3850, -4877, -5340, -4701, -3674, -3064, -2966, -2539, -1531, -996, -662, -303, -216, 421, 1112, 259, -1417, -699, 1768, 1441, -1430, -2661, -1640, -706, -1555, -2922, -3081, -3305, -4432, -4827, -4300, -4475, -4376, -3726, -4686, -6809, -7315, -6624, -6780, -7218, -6529, -5376, -4856, -4600, -4436, -3530, -1916, -1470, -2316, -2250, -1388, -1376, -2204, -2249, -1396, -1324, -2054, -2425, -2640, -3359, -2869, -1347, -1489, -2552, -2327, -783, 758, 1194, 744, 650, 1477, 1518, 754, 757, 906, 1441, 1743, 111, -1282, -1909, -3061, -2856, -2558, -3255, -2834, -2778, -3698, -3179, -2761, -4228, -4958, -3450, -1674, -2170, -3794, -3779, -3041, -3392, -3398, -2633, -2227, -1272, -377, -704, -912, -152, 1468, 2368, 1086, -438, 64, 509, -1161, -1842, 137, 913, -390, -853, -646, -211, -459, -2811, -4465, -4016, -4001, -4843, -6492, -8236, -7942, -6347, -5217, -5334, -4792, -2927, -2167, -1473, -302, -130, -839, -1173, -771, -1159, -1901, -1329, -751, -1471, -2654, -3195, -2527, -1471, -1260, -1533, -1964, -1142, 461, 490, -414, -1239, -2263, -2542, -2171, -3623, -5484, -4126, -1014, -146, -569, 364, 1290, 989, 548, 312, 487, 1283, 2929, 4536, 4145, 3902, 4192, 3012, 1645, 442, -825, -1658, -2378, -2676, -1894, -1665, -2789, -3649, -4180, -4326, -3887, -3363, -2096, -1004, -2596, -4754, -4730, -4295, -4581, -5180, -6391, -7704, -7418, -5164, -3224, -2625, -2420, -1799, -977, -202, 851, 473, -977, -477, 256, -307, 304, 1389, 1640, 2604, 3565, 2368, 324, -649, -365, 702, 953, -926, -3127, -2475, 137, 834, -729, -1933, -1333, -25, -566, -2377, -2628, -2310, -3480, -5163, -5593, -4877, -4057, -3252, -3334, -4766, -4960, -3693, -2827, -2034, -1214, -589, -464, -636, -176, 772, 1536, 2133, 2041, 884, 1148, 1946, 769, 900, 1198, -1351, -2543, -338, 1334, 410, -384, 182, 322, 322, 1190, 1464, -141, -1172, 1123, 2668, 924, -178, 101, -37, -348, -201, -293, -70, 248, -833, -812, 397, -301, -822, 72, -910, -2529, -2056, -1854, -2948, -3380, -2218, -1056, -2666, -4346, -2502, -923, -1930, -2399, -2136, -2674, -4117, -5292, -4758, -4250, -3963, -2767, -1995, -2297, -2125, -1322, -1809, -2880, -2292, -1798, -3652, -4772, -3729, -4385, -6236, -4987, -2567, -3561, -4580, -2905, -3136, -4929, -4936, -4584, -5393, -6250, -5798, -5300, -5846, -5900, -5287, -5520, -5035, -2627, -1826, -3321, -3378, -1722, -1049, -1076, -1533, -3083, -4259, -4543, -4385, -4240, -4584, 470, 568, -697, -2202, -1785, -1240, -1939, -2764, -2575, -2264, -3131, -4303, -5020, -4305, -2088, -1483, -2849, -3352, -2638, -2058, -1469, -759, 175, 428, -474, -1392, -1190, -385, 233, 1285, 1869, 1187, 310, -562, -1561, -411, 2040, 1828, 151, 173, 429, -81, -272, -647, -833, -574, -1384, -2225, -1869, -1982, -2447, -1555, -895, -2600, -4200, -2952, -1578, -3065, -4472, -3734, -3071, -2678, -2811, -4313, -4147, -2366, -1289, -491, -1071, -2810, -3158, -1779, 85, 813, -69, -472, 899, 2066, 1149, -330, 326, 1867, 2325, 1795, 585, 268, 1001, 1685, 1703, 673, -406, -384, 535, 1534, 1274, -519, -1448, -1236, -1422, -1972, -2463, -2516, -2245, -2531, -2758, -2459, -2141, -1764, -643, -169, -1567, -2712, -1725, -216, -430, -995, -298, 606, 557, -344, -978, -599, 9, 402, 294, -944, -1534, -282, 759, -55, -1302, -601, 862, 853, 81, 58, 400, 679, 949, 544, -303, -954, -928, -225, -418, -2025, -3571, -3461, -2195, -1868, -2834, -3101, -1806, -1331, -2361, -3068, -3552, -3569, -1961, 59, 697, 640, 419, 65, 265, 1327, 1732, 214, -238, 2388, 4737, 4110, 2994, 3971, 4626, 3316, 3390, 5572, 6435, 5276, 3990, 4163, 5472, 5518, 4507, 4611, 5278, 5450, 5883, 6780, 6573, 4815, 2902, 2938, 5868, 7149, 3799, 1855, 4710, 6629, 5173, 4104, 4766, 4798, 4419, 5908, 6999, 5215, 3461, 3901, 4902, 4709, 4047, 3494, 2835, 2325, 1291, 92, -534, -315, 387, 554, -542, -2150, -2350, -940, -548, -1483, -1964, -2972, -3792, -3125, -2642, -2495, -2394, -2669, -2442, -1747, -1731, -1287, -710, -1098, -1024, -669, -966, -330, 1440, 2013, 873, 67, 604, 1342, 1372, 757, 186, 517, 1506, 1425, 575, 824, 2087, 3356, 3371, 1654, -160, -938, -852, -1306, -2611, -3185, -2233, -1171, -1297, -1796, -2035, -1921, -1157, -976, -1959, -1826, -844, -1049, -1011, -799, -1369, -1197, 241, 1031, 422, 246, 905, 1381, 2124, 2487, 1169, 276, 324, -1032, -1886, 700, 2419, 307, -950, -750, -1834, -1940, -41, 1172, 50, -1800, -2631, -2012, -1127, -1288, -1856, -2190, -1663, -70, 265, -2003, -4913, -5670, -4117, -2312, -1935, -3877, -4968, -3189, -2142, -3061, -3649, -3428, -2768, -1924, -1711, -2556, -2969, -1396, -780, -3521, -5719, -4675, -2725, -2565, -3857, -3692, -2013, -1133, -1109, -1219, -1595, -1912, -1656, -583, 1227, 1068, -1103, -1925, -1004, -901, -2092, -2600, -1694, -808, -1574, -2829, -2752, -1313, 557, 1286, 1322, 2340, 1757, -885, -2357, -2609, -2665, -2740, -2936, -2762, -2292, -2124, -1610, -379, 950, 1146, -570, -2234, -1186, 152, -1573, -2143, 1566, 3462, 1025, -1031, -1173, -1306, -1182, -453, -740, -2094, -2954, -2204, -559, -325, -1166, -483, 888, 1160, 1203, 660, 179, 1550, 2670, 1609, 75, -679, -206, 985, 1762, 1984, 1816, 749, -671, -497, -731, -2993, -2179, 1550, 2642, 1238, -313, -896, 39, 2140, 2624, 779, 598, 1569, 972, 976, 2241, 2381, 1323, 775, 1169, 1556, 1153, 477, 487, 813, 474, 43, 468, 1357, 1518, 575, -290, -315, 651, 2053, 1608, -782, -2047, -883, 93, -170, -873, -1583, -914, 246, -595, -2424, -1809, 818, 1199, 305, 1003, 723, -877, -1243, -1107, -1722, -2104, -975, 562, 135, -1745, -2283, -1301, -703, -526, -349, -757, -816, 1017, 2433, 865, -436, 967, 2373, 2641, 2613, 1949, 1480, 1959, 3005, 3446, 2316, 1843, 3664, 4485, 3231, 1874, 2087, 3696, 4811, 3801, 1703, 826, 699, 884, 1142, 348, -352, 243, 1389, 2132, 1560, 122, 228, 1735, 2327, 1855, 1010, 1165, 2789, 3788, 2619, 880, 1156, 2552, 3195, 3029, 2349, 2012, 2121, 2425, 3026, 3099, 2365, 2361, 2841, 2710, 1866, 1181, 1833, 2933, 3292, 3767, 3732, 2123, 1307, 2364, 1988, 611, 1099, 1794, 2194, 2355, 982, 844, 2388, 2090, 127, -762, 208, 1216, 1376, 221, -1090, 624, 2620, 1303, 314, 601, 136, 17, 1256, 2060, 1052, 243, 1132, 2296, 2489, 1615, 520, 166, 1136, 2424, 2038, 493, 13, 904, 1201, 489, 1272, 3018, 2565, 298, -1347, -1874, -1768, -1532, -2216, -2655, -1921, -1535, -622, 210, -1128, -2792, -1201, 1700, 1289, -834, -708, 509, 588, 142, 137, 1193, 2125, 2423, 2406, 1543, 452, 251, 1118, 1501, 699, 1335, 2946, 2282, 758, 1262, 2153, 1689, 1454, 1662, 1643, 1446, 623, 512, 892, -242, -1655, -2391, -2459, -2035, -1624, -1679, -1567, -874, -535, -243, -98, -472, -996, -708, 302, 794, 314, -262, -382, -289, -284, -1194, -2585, -2129, 189, 1199, 40, -930, -286, 1197, 1658, 619, -439, -501, 320, 981, 1019, 974, 1202, 1342, 962, 160, -31, -287, -1497, -2482, -2742, -2280, -1363, -1208, -1503, -840, -1087, -2050, -824, 342, -1629, -3794, -3002, -1263, -917, -2126, -3280, -2846, -1766, -1710, -2131, -2429, -3312, -3757, -3410, -3958, -4509, -3624, -2720, -2309, -2394, -3326, -3328, -1888, -1185, -1459, -1729, -1235, 637, 2405, 2180, 608, -169, 406, 377, -34, 603, 1287, 1260, 956, 371, -1185, -2240, -1563, -1080, -1436, -1227, -894, -1734, -2390, -1522, -714, -1271, -1555, -604, -10, -180, -361, -745, -521, 710, 1125, 282, -190, 352, 314, -366, 111, 740, 178, -484, -137, 232, -593, -2044, -2618, -1408, 42, -394, -1858, -1524, -527, -1397, -2066, -825, -13, -592, -1908, -3232, -3187, -2489, -2030, -1655, -1937, -2736, -2393, -748, 489, -526, -2310, -1905, -608, -121, -446, -1279, -992, 352, 1315, 1027, 288, 1405, 2658, 1058, -924, -1786, -2200, -1199, -2, -305, -899, -1077, -774, 654, 825, -1349, -3189, -3427, -3170, -3396, -3908, -3423, -1728, -859, -2075, -2937, -1168, 701, 330, -645, -848, 42, 1669, 2568, 1799, -256, -994, 1040, 3065, 3323, 2977, 2784, 2401, 1914, 1785, 1122, -271, -153, 1072, 1196, 987, -698, -3095, -2183, -573, -2115, -3494, -2557, -1398, -2146, -3036, -2289, -2141, -1441, 709, -376, -3621, -3496, -1544, -1029, -1270, -1563, -1501, -1404, -1252, -236, 989, 1875, 1957, 265, -404, 667, 629, -153, -45, 539, 221, 431, 1754, 721, -1968, -2291, -1083, -286, -295, -1961, -3236, -1659, 603, -142, -2550, -3200, -3273, -3661, -2751, -1091, -580, -1455, -1033, 1623, 2346, 498, -296, 43, 635, 1590, 2015, 1234, 685, 2248, 4408, 3333, 116, -139, 1770, 1844, 176, -1102, -457, 938, 1031, 669, 678, -51, -1085, -1076, -453, -261, -634, -1263, -582, 1211, 872, -1676, -2148, 981, 2712, 853, -793, -345, 1272, 1833, 628, 305, 1124, 2137, 2991, 2746, 2291, 2266, 2188, 2318, 1668, -8, -544, 161, 810, 1524, 1283, -16, 7, 1019, 594, -625, -1293, -1598, -722, 282, -326, -1558, -838, 1234, 730, -1438, -1644, -1137, -1649, -2429, -2362, -2084, -2746, -3038, -2282, -1844, -2048, -1911, -855, 1150, 1837, 578, 361, 975, 1242, 1664, 885, -1026, -1357, -112, -550, -1741, -1091, -479, -243, -547, -2491, -4159, -3493, -2704, -4150, -4837, -2478, -470, -1054, -1738, -1463, -1438, -1707, -597, 1071, 334, -1584, -1523, 697, 2726, 2411, 381, -786, 787, 2650, 1691, -76, -233, 989, 2449, 3184, 1994, -146, -630, -573, -1914, -3009, -2042, -745, -476, -318, -739, -1785, -1336, -77, -791, -3121, -3553, -1527, -226, -246, -326, 1, 516, 506, 1199, 1999, -7, -1935, -379, 1313, 525, -988, -1159, -526, 245, 682, -299, 423, 2929, 2098, -464, -228, 1065, 1167, 662, 373, 111, -557, -782, 238, 1221, 184, -921, -125, 744, 548, -808, -2684, -2632, -483, 0, -2124, -3621, -2972, -2182, -2147, -1933, -1730, -1414, -275, 949, 1259, 591, 244, 750, 879, 543, 769, 426, -1485, -2146, -657, 169, 126, 1051, 2296, 1337, -1369, -2308, -1251, -1304, -2176, -2197, -1695, -794, -985, -2258, -2431, -1675, -720, -281, -1628, -3644, -3544, -2028, -1983, -3005, -3351, -3043, -2845, -2742, -2052, -1920, -2711, -2066, -587, -711, -1381, -1411, -1261, -23, 1178, 141, -442, 1088, 1588, 315, -311, -32, -263, 59, 1470, 2195, 1512, 859, 978, 1339, 1469, 278, -1147, -792, 168, 207, -694, -1009, -501, -521, -1130, -1709, -1868, -1749, -1394, -521, -788, -2639, -3135, -1904, -1591, -2139, -1609, -1217, -1701, -1789, -1015, -35, -378, -1141, -228, 596, -46, -27, 1065, 1635, 1333, 398, -394, 1126, 3429, 2538, -1077, -2517, -1138, -1139, -2792, -3657, -3669, -3425, -2092, -691, -1609, -3840, -4020, -2249, -1915, -2597, -1840, -851, -570, 352, 1048, 472, 357, 491, -820, -2788, -3902, -3125, -769, 164, -1201, -2019, -1314, 356, 1189, 137, 38, 1247, 1087, 466, 1683, 2307, 938, 60, 425, 762, 576, -257, -1812, -2253, -1212, -869, -1715, -2076, -1498, -730, -1020, -1754, -1709, -1464, -1016, -395, 143, -12, -1691, -2850, -2771, -3174, -3489, -2710, -1482, -1352, -2597, -3424, -1996, -896, -2582, -4448, -3909, -1534, -62, -1044, -2367, -2115, -1139, -120, 46, -435, -99, 173, -905, -1838, -1188, -324, -91, -92, -143, 178, 152, 191, 1556, 1503, -1089, -2226, -1248, -532, -546, -1448, -2045, -1009, -757, -1040, 513, 1087, -681, -1263, -101, -598, -2258, -2329, -1499, -970, -1098, -1825, -2009, -786, 655, 617, -606, -1468, -1492, -1010, -209, 468, 11, -1040, -598, 210, 24, 745, 2791, 2726, -159, -2081, -1872, -1312, -736, -140, -163, -453, 323, 1088, 430, 528, 1989, 1961, 960, 658, 595, 902, 1431, 1707, 2381, 2843, 2344, 1398, 520, 258, 746, 255, -1868, -2759, -1531, -72, 242, -170, 30, 568, 364, -533, -1372, -840, 394, 1538, 1486, -388, -870, 268, 464, 125, -940, -2081, -947, 452, 230, 837, 2912, 2838, 916, 979, 1470, 593, 308, 720, 836, 140, 8, 1177, 1110, -679, -2260, -2553, -2456, -2151, -853, -468, -1948, -1716, 473, 673, -513, 104, 1391, 1121, 479, 887, 1187, 1063, 2443, 3010, 613, -481, 663, 549, -18, 1883, 3649, 2322, 2057, 3735, 3075, 1847, 2582, 3458, 3292, 2294, 1552, 2805, 3950, 2254, 298, -168, 177, 1285, 2605, 2840, 1725, 614, 498, 1262, 1849, 1562, 726, -243, -471, 1062, 1726, -415, -1425, 502, 1598, 30, -1666, -2271, -2281, -931, 939, 615, -1256, -2028, -805, 392, 394, 287, 646, 969, 106, -1017, 18, 1312, 470, -1269, -2074, -1143, 297, 45, -1402, -1824, -571, 509, 203, 458, 1119, -224, -1225, 977, 2674, 729, -973, -172, 140, -650, 34, 2125, 2533, 1175, 1366, 2373, 1263, -85, 1063, 2397, 1207, -793, -1741, -1386, 120, 1122, 47, -1103, -659, 418, 1188, 943, 138, 356, 1476, 1080, -267, -1017, -1321, -737, 784, 989, -1175, -2637, -1892, -879, -1218, -2291, -2142, -1421, -2139, -2085, 196, 474, -1621, -2270, -2023, -2874, -3112, -1524, -322, -925, -1996, -1923, -1521, -1335, -1170, -1702, -2442, -2336, -1787, -1179, -1319, -2089, -1973, -769, 188, 24, 72, 1046, 1351, 416, -781, -754, 602, 1342, 909, 634, 1014, 1929, 1777, 665, 745, 293, -521, 297, 951, 225, -464, -633, -400, 129, -152, -1239, -811, 501, 387, -316, -512, -795, -733, -3, -120, -1262, -1980, -1470, -279, -250, -1788, -2853, -1338, 1556, 1921, 676, 1566, 2731, 2051, 866, -345, -609, 840, 2907, 4064, 2575, 224, 1052, 3343, 2949, 1429, 1483, 2098, 2239, 2623, 3432, 3513, 2374, 1383, 1576, 1654, 833, -101, -1065, -1587, -783, -266, -193, 527, 1687, 3286, 3662, 2283, 1464, 1563, 2082, 2521, 2594, 2992, 3019, 2144, 1662, 1757, 2018, 2801, 3561, 3233, 1943, 150, -684, 695, 2003, 1503, 1089, 1453, 2027, 2728, 1309, -1145, -148, 1744, 324, -2390, -3534, -2510, -1644, -2307, -2959, -2308, -1095, -430, -414, -434, 133, 1369, 2311, 2201, 1839, 2070, 2462, 2687, 2802, 2011, 788, 492, 1275, 2649, 2785, 788, 157, 1088, 895, 649, 1846, 2701, 3163, 4279, 4276, 2553, 1079, 439, -144, 206, 1634, 2732, 3120, 2219, 1286, 1160, 567, 739, 2010, 1924, 1073, 1013, 1232, 1580, 1844, 1383, 999, 645, -61, 847, 2265, 983, -890, -101, 1554, 1368, -285, -729, 211, 1125, 2093, 1954, 797, 849, 1710, 1703, 1374, 2181, 3578, 3561, 2153, 1479, 2281, 3879, 5970, 6442, 4202, 2539, 2200, 1809, 1579, 1910, 1884, 1048, 1237, 1741, 1147, 1263, 1553, 802, 289, 451, 1648, 3128, 2479, 339, 47, 1627, 1787, 1622, 3751, 5055, 3564, 2857, 3311, 2758, 1552, 617, 943, 1530, 393, -1659, -2254, -1382, -947, -1439, -2524, -2594, -1607, -1759, -1799, -1031, -1139, -2454, -3396, -3215, -3497, -3895, -2737, -2094, -3013, -3133, -2442, -2639, -2961, -1752, -96, 59, -1139, -2037, -1394, -221, -298, -1400, -1548, -594, 343, 451, -646, -1693, -1545, -777, -170, -976, -3004, -3834, -3344, -2912, -2075, -1102, -1413, -2288, -1640, -984, -1761, -1101, 515, -105, -1411, -1649, -2030, -2912, -2923, -1558, -533, -907, -605, 185, 109, 1134, 2512, 2055, 1263, 1991, 2719, 1247, 470, 2853, 4224, 1962, 304, 2276, 4630, 3697, 1525, 1233, 2199, 3056, 3054, 2274, 1463, 491, -170, -281, -1257, -1795, -234, 2119, 2534, 950, 1425, 3633, 3435, 1337, 600, 1584, 1866, 556, -797, -1153, 295, 2576, 3484, 3020, 2233, 1678, 2061, 3100, 2655, 1255, 1421, 2645, 3896, 3419, 1392, 516, 643, 549, -233, -1809, -2759, -2546, -1919, -1104, -1642, -3528, -2334, 1649, 2717, 702, -463, 89, 1329, 2389, 2248, 1016, 506, 1566, 2299, 1468, 453, 582, 989, 666, -117, -670, -183, 1196, 1945, 1233, 53, -259, 39, 1071, 2370, 1700, 696, 1207, 631, -376, -224, -929, -1492, -353, 79, -551, -1185, -1272, -474, -237, -978, -830, 301, 139, -1338, -1809, -1413, -1359, -1281, -1424, -1846, -1768, -1161, -982, -1538, -2023, -1764, -1333, -1994, -2585, -2105, -1976, -2453, -2258, -1553, -724, -361, -1970, -3492, -2244, -757, -1432, -2460, -2306, -2088, -2657, -3237, -2976, -1661, -1418, -2955, -4078, -4881, -5348, -3960, -2065, -2161, -3828, -3991, -2303, -1600, -2000, -2554, -2834, -1719, 167, 1417, 1660, 746, 166, 1091, 1860, 903, -459, 488, 2736, 2533, 329, -906, -70, 2599, 4078, 1803, -620, -260, -229, -1239, -1748, -2949, -3296, -1353, -487, -1815, -2073, 477, 3759, 3993, 1617, 147, 440, 839, 826, 653, 122, 149, 1623, 4167, 4878, 2017, -322, 992, 2379, 1520, 1258, 1430, 187, 194, 2398, 2225, -59, -513, 1727, 3869, 2508, -870, -1844, -899, -1879, -3511, -2781, -1386, -656, -71, 17, -229, -333, 695, 1919, 1060, -268, -280, 381, 2095, 3234, 1166, -1302, -252, 2352, 2646, 1687, 928, 306, 917, 1242, -140, -775, -20, -18, -185, 217, 135, -411, -260, 583, 264, -1642, -3194, -2637, -1608, -2265, -2514, -1789, -1864, -2700, -3358, -3851, -3567, -2087, -2012, -3749, -4357, -3927, -3834, -3693, -3189, -2563, -2945, -4064, -3482, -2475, -3181, -4024, -4562, -4585, -3297, -2344, -2723, -2660, -2100, -2127, -1145, 82, -727, -1356, 437, 1028, -1177, -2567, -2216, -1669, -998, -887, -1407, -1556, -1100, -1377, -2584, -3193, -2636, -1834, -2037, -3046, -3708, -3714, -3240, -2847, -3111, -2841, -1141, -222, -883, -824, -64, 1605, 3690, 2371, -660, -907, 808, 1516, 1169, 1184, 1350, 1630, 2103, 2312, 2193, 1703, 1515, 1076, 321, -760, -1925, -1253, 645, 1232, 618, 906, 2183, 3166, 3922, 4234, 2914, 532, 245, 2121, 2547, 1407, 1429, 2580, 3575, 3899, 2993, 1540, 2111, 3555, 2763, 2663, 4301, 4679, 3376, 2015, 2304, 3377, 3708, 3836, 2591, 315, -245, -72, -785, -312, 1462, 1084, -248, 1639, 4071, 2760, 879, 1134, 2010, 2564, 2785, 1943, 715, 1772, 3537, 2827, 1347, 889, 1187, 2170, 2604, 1723, 576, 502, 1743, 2340, 1911, 1994, 2147, 917, -809, -974, -1018, -1823, -1078, -21, -1045, -2235, -2688, -3050, -2501, -1007, -896, -2347, -2165, -1194, -1981, -2492, -1484, -1336, -1779, -1600, -1677, -1594, -1081, -854, -579, -306, -1525, -1926, -593, -1514, -3455, -3277, -2354, -891, -201, -1455, -1019, 456, -1007, -3342, -3951, -3541, -2882, -2796, -3222, -3373, -3466, -4091, -2901, -248, -1432, -4774, -5149, -3977, -3732, -3173, -2541, -2710, -2372, -1920, -2940, -4495, -4336, -2671, -1667, -2818, -4805, -5417, -4450, -3261, -3537, -4566, -4705, -3872, -2120, -926, -979, -1101, -1222, -296, 676, -394, -1666, -966, -197, -1020, -1595, -1011, 529, 1487, 440, -799, -254, 583, -339, -1464, -1225, -2379, -4442, -4283, -3399, -3141, -2025, -675, 383, 1897, 3079, 2377, 881, 731, 1155, 192, -597, 961, 2107, 1303, 1182, 1365, 728, 769, 1823, 1783, 471, 716, 1926, 1618, 474, -190, 856, 2388, 1099, -898, -817, -639, -1164, -963, -712, -1894, -2576, -1845, -1606, -928, 177, -357, 35, 2166, 1615, -777, -1276, 31, 649, 422, 993, 1008, 16, -24, 888, 877, -409, -382, 1128, 981, -367, -1403, -1919, -1112, 89, 345, -326, -2347, -3430, -1450, -144, -739, -684, -581, -1621, -2404, -1897, -2222, -3581, -2770, -1161, -1491, -2838, -3280, -2299, -1355, -1635, -2252, -3197, -4016, -3458, -2800, -2938, -2321, -1289, -1741, -3110, -3502, -3104, -3031, -2574, -2280, -2813, -2877, -3097, -4001, -4697, -4454, -3973, -3808, -3052, -2461, -3206, -4225, -4258, -3874, -4348, -4996, -5769, -5663, -3743, -3669, -5274, -4827, -3072, -1732, -1990, -2695, -2781, -3429, -3030, -1701, -3358, -6701, -6351, -3689, -3581, -4876, -4914, -4598, -3843, -2550, -1734, -1099, -345, -1012, -2035, -973, -164, -179, 290, 659, 853, 644, 115, -348, 590, 2321, 2335, 1058, -187, -809, -871, -1588, -1869, -1351, -1281, -1368, -1483, -1571, -1877, -1306, -9, 709, 1308, 1595, 1850, 3265, 3656, 545, -1942, 370, 2795, 2226, 1779, 1858, 1712, 2533, 3633, 3794, 3228, 1569, 941, 3130, 4358, 2563, 1335, 2344, 2259, 403, -350, -537, -1535, -1921, -1307, -937, 185, 1452, 1050, -24, -201, 2107, 5537, 5802, 3889, 3268, 2622, 767, 1157, 4292, 4089, 677, 1298, 3842, 2167, 150, 958, 1236, 480, -368, -383, 404, 419, 927, 1472, -252, -2790, -1938, 1324, 1319, -1093, -2453, -3059, -3472, -3184, -2874, -2904, -1663, 763, 1136, 111, 894, 2151, 1729, 1323, 773, -1060, -1340, 222, 1091, 1824, 1678, 624, 2483, 5301, 4408, 1954, 1406, 2238, 2975, 2570, 1510, 1808, 2790, 1755, 316, -139, -570, -672, 325, 1273, 164, -1204, -279, 944, 495, -242, -977, -1865, -1789, -599, -1055, -3010, -2964, -1212, -342, -959, -902, 1119, 1937, -45, -1083, -475, -565, -479, 755, -446, -2676, -1585, -713, -870, 1182, 2245, 76, -2112, -1403, 278, -20, -239, 1129, 1720, 1725, 2251, 1637, 780, 1739, 2562, 1688, 984, 399, -160, 114, -159, -310, -155, -710, -720, -484, -1403, -1719, -654, 599, 715, -1441, -2452, -637, 181, -198, 46, -134, -25, 1769, 2867, 1514, 606, 3204, 5823, 6155, 5608, 4050, 2848, 3072, 3563, 3727, 3163, 2592, 4114, 5685, 4611, 4138, 4990, 4381, 3433, 2847, 898, -572, 436, 1394, 347, -218, 1070, 1630, 2274, 4010, 3452, 2177, 3882, 6551, 6900, 5806, 5834, 6034, 6349, 8205, 8706, 7374, 6038, 5332, 5434, 4916, 4143, 4559, 5399, 5574, 4473, 2967, 3883, 5474, 3819, 1220, 723, 1516, 1772, 1010, 191, 1103, 3897, 6051, 5391, 3069, 2711, 5065, 6277, 6025, 5732, 3978, 3221, 6479, 8134, 4236, 1955, 4363, 5720, 4131, 2447, 2523, 2894, 2045, 1839, 3005, 3089, 3082, 3500, 2897, 3005, 3420, 2454, 1057, -62, 384, 1553, 1460, 285, -1744, -1505, 1368, 1215, -994, -253, 2629, 3940, 3598, 3885, 4533, 4132, 2000, -675, -680, 2331, 3928, 3911, 3878, 2639, 2322, 4132, 4657, 3404, 3809, 6137, 5258, 1311, 662, 3101, 3561, 3055, 4481, 5446, 3637, 2359, 3511, 3654, 1273, -1908, -3054, -902, 247, -1803, -1699, 714, -138, -2503, -2886, -2361, -1239, 151, 306, 380, 1126, 969, 1358, 2946, 2777, 746, -70, 1859, 4436, 4282, 836, -2022, -1103, 1026, 2233, 1503, -774, -1302, -290, 112, -192, -214, -467, -1900, -970, 3602, 3882, -169, -1254, -409, -465, -208, 837, 1600, 1566, -75, -1179, 985, 2550, 798, -363, 201, -425, -946, -635, -943, -1033, -1083, -1019, -529, -1099, -1774, -742, 257, -706, -2018, -1253, -781, -1672, -898, 958, 26, -1598, -49, 2169, 2150, 2028, 3328, 4660, 5990, 6696, 5086, 3407, 4909, 6570, 4361, 2229, 4430, 6750, 5780, 4418, 3425, 2748, 3561, 3659, 2110, 439, -741, -266, 1210, 1726, 1374, 1014, 867, 2405, 5027, 4809, 2524, 2367, 4072, 4671, 4518, 4735, 5282, 5737, 5163, 5385, 6012, 5002, 4108, -3548, -1479, -2286, -3170, -2321, -2701, -3688, -2838, -1346, -1707, -3535, -2208, 1670, 1324, -2107, -2801, -1298, -988, -2331, -4072, -4413, -4365, -7318, -8733, -4053, -662, -2307, -3003, -930, 840, 1619, 1791, 1349, 821, 1029, 832, -1213, -2532, -2126, -2747, -3567, -2377, -1162, -1947, -2950, -1992, -620, -1408, -2512, -2789, -4187, -5590, -5518, -4124, -3178, -4494, -5946, -5510, -4699, -5276, -6923, -7312, -5478, -3819, -4216, -4650, -3999, -5221, -6172, -2339, 853, -754, -1420, 1558, 3561, 2394, 381, -1488, -2017, 210, 1439, -1069, -3003, -2166, -1360, -1141, -1624, -3155, -3021, -45, 1744, 987, 55, -1984, -4454, -3320, -1182, -1790, -2971, -3489, -4111, -4482, -4459, -4686, -5989, -6558, -5635, -5661, -8073, -10108, -7952, -5141, -5828, -7627, -7300, -4382, -3062, -4991, -5114, -2899, -1776, -2126, -2016, -2424, -4374, -4436, -3616, -4419, -5454, -5546, -4182, -2679, -2974, -3485, -2431, -1451, -1318, -2479, -3771, -2046, -306, -2352, -5096, -6201, -6324, -4320, -1161, -889, -2378, -2294, -817, 26, -1022, -3445, -5467, -5703, -4312, -3151, -4020, -5429, -4456, -3103, -3266, -1540, 968, -193, -3595, -4938, -4847, -5108, -4373, -2634, -2350, -4241, -5960, -5514, -4009, -3854, -4082, -3150, -1987, -1270, -1653, -3460, -5349, -5310, -3966, -3464, -3562, -3337, -4249, -4492, -2975, -3561, -5229, -3980, -1025, -1106, -5001, -6620, -3136, -94, -170, -584, -969, -1361, -724, 7, 223, 77, -1296, -1941, -1686, -3562, -4246, -1591, -231, -1252, -2710, -3721, -4475, -5877, -6970, -6455, -5425, -5412, -6667, -8260, -7291, -4249, -3790, -5703, -5755, -4918, -6059, -6909, -6289, -5827, -4215, -2687, -3567, -3311, -1197, -1083, -2150, -2767, -4148, -4555, -2110, -129, -733, -1955, -2537, -2203, -2019, -2470, -2314, -2176, -2382, -1926, -2216, -4633, -6371, -4027, -718, -888, -2692, -2346, -231, 1064, 1250, 1142, 1031, 1667, 2999, 3398, 3121, 2757, 2303, 1832, 649, 636, 1759, 1946, 1838, 1498, -145, -1344, -325, 923, -129, -2564, -4090, -4010, -3075, -2841, -3921, -4671, -4596, -5708, -6465, -4120, -2451, -4135, -4774, -3240, -2792, -3174, -2782, -1841, -1010, -1760, -2931, -2524, -2776, -3486, -2783, -4413, -7261, -5242, -1252, -439, -2272, -4318, -4814, -3926, -3781, -5116, -5613, -4775, -4286, -3855, -3385, -3985, -4348, -3024, -2297, -5418, -8886, -5787, -1364, -2965, -6039, -5427, -2817, -2162, -2872, -2087, -827, -141, 1106, 2477, 2785, 972, -2449, -2387, 2062, 4288, 1826, 836, 3214, 2985, 548, 863, 2032, 1979, 2734, 4031, 3835, 3095, 2295, -770, -1653, 2657, 5057, 3498, 2537, 2525, 1785, 1292, 1568, 1884, 2290, 2988, 3540, 4077, 4806, 5361, 4958, 4230, 5459, 6430, 3732, 584, 2387, 6979, 8064, 6144, 4286, 2903, 1878, 1112, 1345, 1862, 1129, 591, 2334, 3911, 3339, 3356, 5024, 6873, 5809, 2248, 1710, 3155, 3157, 3455, 3810, 2720, 1818, 2552, 4158, 5487, 6839, 7398, 5886, 5038, 6302, 7324, 7267, 7015, 7273, 7496, 8088, 8105, 6709, 7112, 8596, 7516, 6397, 7184, 6494, 4915, 5783, 6970, 6531, 5844, 5343, 4764, 3370, 2061, 2068, 2260, 2178, 1538, 626, 660, 1487, 2421, 1584, -800, -83, 3539, 4575, 2241, 879, 2250, 3818, 3816, 2819, 1864, 2009, 3514, 4545, 3036, 1614, 1755, 1410, 2235, 4116, 3463, 2153, 3165, 3947, 3196, 1442, 34, 900, 2517, 2595, 1515, 77, -113, 611, 484, -74, -415, 2145, 6201, 6777, 4514, 3199, 3976, 4798, 4854, 5110, 4469, 2663, 2881, 3844, 1920, 783, 3877, 7004, 6769, 4824, 3026, 3404, 5445, 5546, 4510, 4460, 4664, 4697, 4889, 4716, 2979, 245, 1056, 5443, 6132, 3059, 2519, 3208, 2373, 2600, 3758, 4182, 4690, 4473, 4032, 4360, 3822, 2754, 3671, 6371, 7040, 4651, 3497, 5082, 6026, 5191, 4875, 5860, 6093, 5426, 5250, 5664, 5631, 3480, 1475, 3199, 5551, 3693, 104, -685, -402, -706, -518, 171, 1122, 467, -971, 1215, 4500, 3764, 1577, 1816, 2811, 3455, 4580, 3153, -261, -1646, -1440, 1019, 5007, 6243, 4705, 3963, 5072, 6290, 5814, 4111, 2733, 2861, 4605, 6293, 5811, 3901, 3049, 3381, 2646, 1742, 2904, 4134, 3364, 1137, -69, 1579, 4487, 5589, 4112, 2777, 3747, 4553, 4247, 3672, 1385, 1534, 5667, 7378, 6176, 4601, 3778, 5110, 5824, 2904, 1131, 4029, 6775, 6370, 5413, 5424, 5427, 5710, 6533, 6076, 4231, 3667, 4656, 3428, 730, 1836, 5168, 5557, 3015, 1809, 3292, 3793, 2664, 2303, 1901, -477, -2508, -663, 2362, 2048, 639, 1402, 3705, 4819, 4166, 3758, 2407, -402, -440, 2587, 3765, 2450, 2096, 2944, 4329, 5919, 5736, 2979, 1405, 4020, 6857, 6402, 4686, 3758, 3572, 3621, 3154, 1113, -361, 1805, 4791, 4394, 3177, 4299, 4451, 2999, 2650, 2251, 1230, 303, -911, -618, 2086, 3644, 2754, 1008, -675, -250, 1932, 2136, 1642, 2236, -28, -2033, 2212, 6086, 3940, 1397, 1865, 3106, 3740, 3131, 2240, 2470, 1450, -452, 826, 2526, 1329, 1466, 3020, 2244, 339, -838, -1269, -695, -261, -1640, -2543, -777, 1390, 2663, 3356, 3261, 2544, 2667, 3672, 3860, 3955, 3764, 1463, 95, 2203, 4542, 4871, 4505, 4375, 4112, 3854, 4162, 4266, 2947, 2522, 4065, 4114, 3443, 4326, 3955, 1266, -764, -275, 1079, 1602, 1407, -211, -858, 1122, 2076, 1316, 1201, 1896, 2162, 1419, 766, 1438, 434, -3420, -3826, 903, 3206, 260, -1638, -714, -336, -797, -1094, -660, 262, -952, -4046, -4124, -909, 1660, 1576, -1016, -2780, -1663, -490, -928, -1417, -1383, -2605, -2780, 1269, 3600, 938, -980, 19, 755, 878, 1208, 1503, 2565, 3532, 1547, -1227, 186, 3256, 3593, 2528, 1496, 733, 399, -412, -665, -9, -1386, -3307, -1394, 2581, 3044, 934, 1489, 3748, 3403, 1331, 302, 1635, 3761, 2800, 659, 947, 4135, 7414, 6535, 4467, 3827, 3444, 4080, 4968, 3218, 465, -477, -731, -322, 909, 745, -400, -598, -657, -1804, -2371, -2746, -5103, -5253, -872, 392, -2970, -3369, -866, 133, 157, 958, 1700, 1721, 1944, 981, -2132, -1459, 3361, 4661, 2231, 839, 1952, 3497, 3493, 3864, 5430, 5130, 2637, 2883, 6105, 6860, 4944, 4121, 4456, 3673, 1619, 297, 1173, 351, -2160, -428, 2165, 742, -468, -454, -1962, -3074, -1457, -538, -3629, -4861, -1125, 1127, 27, -691, 8, 221, -5, 1859, 4138, 2545, -261, 2132, 7485, 8593, 5405, 2315, 1779, 2974, 3516, 2438, 203, 475, 4266, 5580, 3141, 1401, 1974, 3183, 3029, 1793, 500, 501, 1249, 148, -133, 1656, 1751, 1119, 1377, 1764, 1524, -30, -1663, -836, 707, -797, -1325, 2322, 4913, 3338, 1139, 2535, 5318, 6287, 6435, 5309, 3281, 3653, 5106, 3332, -334, -731, 2551, 4004, 2407, 1903, 1153, -1414, -2441, -984, 5, -1655, -3887, -1970, 1827, 2250, 1687, 1861, 1898, 2015, 1403, 727, 668, 1107, 944, -2020, -3121, -218, 391, -1201, -918, -227, -985, -1331, -220, 561, -39, -1552, -1257, 2274, 4256, 3040, 2595, 2365, 1181, 914, 896, -805, -2395, -2720, -3852, -4029, -2661, -2755, -3683, -3925, -3925, -3531, -2988, -2375, -2757, -4348, -3212, 147, 1748, 2463, 3492, 3151, 2060, 2841, 4563, 3712, 523, -1612, 255, 4784, 6749, 4920, 3239, 3849, 4052, 1934, -34, -349, -1406, -2743, -755, 1286, 1281, 2384, 2515, 800, 972, 2132, 832, -160, 1380, 1004, -1375, 163, 4123, 3706, 460, -307, 629, 1503, 1852, 1679, 2060, 346, -2649, -679, 2737, 890, -2415, -2417, -63, 1847, 1619, 752, 733, 1359, 605, -3586, -5670, -2231, -720, -3485, -4188, -2550, -2753, -3730, -3204, -1724, -1028, -1819, -685, 3250, 3657, 137, -647, 1689, 2648, 1014, -1567, -3154, -1942, 716, 1535, 759, 237, 62, 280, 449, 806, 1736, 1829, 1923, 1810, -132, -148, 2219, 1592, -653, 26, 1296, 400, -597, -684, -1945, -5015, -6565, -4233, -1095, -436, -1763, -2556, -1432, -415, -646, -585, 646, 1410, 85, -1843, -1236, 2023, 5332, 5892, 2955, 261, 476, 1127, -244, -2627, -2448, 130, 1665, 2680, 3231, 1121, -886, -22, 1421, 1286, -220, -1606, -1768, -1904, -2822, -1581, 1318, 1496, -378, -732, -525, -1741, -2675, -1491, -502, -1711, -3302, -4820, -5585, -2911, 105, -711, -1566, -340, 625, 501, -877, -2309, -3069, -3411, -2545, -1638, -3304, -3440, 1526, 4654, 3016, 1959, 2300, 683, -1037, 346, 2199, 1226, -724, 1438, 4879, 3116, 229, 1211, 2878, 2688, 1600, 981, 2251, 2935, -319, -3206, -911, 2320, 1449, -1590, -2974, -2003, -1321, -1504, -922, -1726, -4792, -5126, -1994, -635, -2849, -4931, -4168, -2776, -1822, -728, -750, 163, 1609, -1444, -5251, -3826, -467, 194, -379, -564, -857, 258, 2260, 1990, 629, 976, 1958, 534, -809, 1682, 3916, 2294, 463, 584, 379, -83, 593, 748, 95, 2138, 4489, 2928, 932, 1516, 1855, 589, -131, 607, 675, -893, -2427, -2957, -2407, -2482, -2758, -93, 2513, 1764, 604, 818, 1704, 1486, -245, 110, 709, -2622, -4389, -837, 2276, 1809, -35, -1357, -1045, 647, 1305, 563, 481, 474, -620, -2580, -2471, 518, 1175, -1493, -2944, -2641, -3381, -3763, -1656, -1457, -4696, -5326, -1444, 2536, 3774, 2815, 963, -131, 1211, 3401, 2063, -93, 1323, 1710, -152, 901, 4012, 3997, 1897, 1479, 1654, 1849, 1877, 763, -17, 14, 9, 1, -740, -1712, 376, 2710, 1644, 1139, 1008, -512, -302, 798, 1056, 2088, 2770, 305, -2068, -299, 2273, 2130, 304, -1221, -2040, -2321, -1174, 251, -504, -1845, -2050, -3059, -3407, -1448, -848, -1638, -1707, -2281, -3540, -4608, -4790, -3558, -2948, -3593, -4177, -5955, -7396, -5229, -2883, -3203, -4321, -5055, -4772, -4063, -3502, -2545, -1282, -360, -953, -4187, -6571, -3351, 1708, 2127, 27, -84, 385, -50, -535, -1096, -1485, -602, 326, -1926, -3701, -753, 958, -1028, -1628, -445, -378, -1626, -1505, -1494, -4499, -6170, -4009, -1801, -977, -284, 201, -110, -745, -117, 1119, -172, -2781, -3076, -3338, -5239, -3837, 543, 2643, 2433, 1689, 596, 162, 583, 48, -1315, -751, 1571, 963, -2201, -1190, 1704, 279, -1520, -245, 554, -927, -2145, -1125, 92, -1798, -5279, -4421, 92, 1420, -434, -5, 1571, 720, 618, 3512, 5130, 3544, 656, -1297, -380, 1481, 1109, -284, -1168, -1269, -453, -1239, -3294, -2693, -985, -1417, -2443, -2926, -3542, -3239, -1336, -355, -1478, -2197, -1473, -941, -1375, -1543, 138, 2064, -389, -4280, -4021, -2627, -3002, -5031, -8097, -7833, -4260, -3020, -3497, -2295, -1667, -3358, -2791, 1693, 4176, 1830, -1335, -1170, 243, -410, -434, 1784, 1417, -3037, -4113, -597, 132, -1148, 528, 1939, -249, -1901, -197, 1488, 1745, 1724, 597, -1691, -2375, 590, 2922, 641, -1550, -168, 916, -117, -964, -180, 1440, 2005, 478, -1532, -3252, -4633, -3184, -394, -355, -1435, -1760, -2672, -3319, -3038, -1558, -1051, -4518, -6462, -3067, -739, -1986, -2714, -2010, -1943, -3130, -3847, -3247, -3066, -3634, -5618, -8556, -7718, -4049, -3754, -6138, -6644, -5510, -5231, -5884, -6456, -6089, -4577, -3578, -4988, -6223, -3979, -2187, -2851, -2973, -3434, -4529, -4677, -4682, -4255, -2226, -1052, -2976, -2728, 1010, 1239, -1551, -2739, -2731, -2460, -2136, -2334, -1469, 1093, 338, -2774, -1357, 1865, 1817, 1497, 1888, -72, -1821, 32, 2374, 2502, 371, -2671, -2096, 2554, 3674, 182, -119, 2777, 2436, -253, -385, 1136, 1958, 1846, 696, -1175, -2998, -1204, 3035, 2519, -550, -422, 647, -226, -1137, -520, -967, -2799, -1453, 2102, 1797, -658, -1749, -2493, -3142, -4126, -4958, -4408, -3431, -3622, -3973, -3497, -3966, -3989, -440, 2702, 1673, -494, -1082, -537, -213, -803, -1199, 145, 1644, 443, -2750, -5758, -5911, -2659, -928, -2564, -3743, -2869, -1158, -468, -965, -643, 325, 656, 360, -2646, -6648, -6640, -4580, -4512, -5845, -6920, -6649, -5260, -5154, -5923, -5481, -5484, -6106, -5548, -5965, -7017, -3827, 1017, 1525, -417, -705, -183, 49, 884, 1640, 1277, -57, -2151, -4075, -2974, 568, 2112, 1635, 1121, 546, 187, 906, 1343, -339, -1175, 660, 1012, -1426, -3178, -3435, -3637, -4122, -4529, -4740, -3210, -1698, -4282, -7333, -5490, -1684, -337, -752, -546, 984, 1388, 552, 285, -926, -2467, -1643, 847, 655, -2813, -2840, 1180, 1648, -1004, -2059, -1393, 177, 396, -777, -318, 837, 964, -498, -4231, -5415, -1914, -550, -2790, -3782, -3575, -2804, -375, 945, 146, -588, -1408, -2956, -3969, -2019, 901, 1436, 217, -1234, -719, 929, 1559, 1748, 500, -1311, -111, 2362, 3020, 2551, 2441, 2803, 2757, 2130, 2870, 3392, 1435, -220, -157, -992, -4618, -6926, -4954, -3083, -3750, -4911, -5101, -4372, -3018, -2314, -2891, -2332, -1449, -3358, -5934, -4323, -491, -585, -2557, -1911, -1217, -2377, -3579, -3629, -2970, -2339, -1815, -2421, -3618, -2414, 950, 2421, 959, -641, 137, 1930, 1475, -61, -425, -927, -1303, -454, -1091, -4745, -6777, -2898, 1788, 1660, 435, 213, -661, -837, -307, -708, -1122, -202, 276, -1588, -2957, -1674, -1091, -1315, -1357, -2355, -1570, -24, -1673, -2247, -213, 496, 689, 1545, 1503, 2259, 3118, 740, -1841, 76, 3602, 3491, 1840, 2538, 3514, 1960, 141, 1215, 3386, 3251, 2310, 3616, 5048, 3368, 1627, 3125, 4551, 3701, 2328, 1136, 1181, 1288, 1215, 3017, 4145, 2763, 1647, 2339, 2669, 361, -1997, -551, 1860, 1439, -495, -1196, -1133, -1388, -1456, -1131, -1407, -2629, -3221, -2739, -3587, -6581, -8482, -6026, -2244, -1966, -4214, -5624, -5437, -3664, -2202, -3717, -6536, -7325, -5926, -4467, -4580, -6633, -6657, -1560, 2684, 1644, -434, -1291, -1962, -1279, -71, -1552, -2799, -921, 105, -503, 506, 1881, 1564, 1206, 1877, 1965, 1063, 325, 231, 924, 1568, 327, -1898, -1525, -917, -3768, -4409, -985, 190, -423, -519, -1180, -716, 165, -228, -699, -1504, -2254, -1821, -1670, -3434, -3621, 52, 1980, 646, -106, 39, 824, 1503, 466, -694, -596, 404, 1295, 215, -2670, -2608, 1285, 3225, 1399, -557, -861, -1262, -2489, -2856, -1431, -1832, -5263, -6640, -4050, -2840, -5011, -5838, -4604, -4268, -5053, -5899, -5708, -3573, -1807, -2575, -3999, -5774, -7362, -5357, -2837, -3776, -4594, -4375, -4322, -2625, -525, 112, -354, -2354, -3438, -604, 1840, 804, 88, 1351, 2524, 1866, 51, -342, 999, 2393, 2401, 136, -2411, -742, 3295, 3944, 3130, 3719, 2981, 1787, 1642, -463, -2028, -769, 36, -197, -1241, -1275, 1798, 4446, 3805, 1636, -346, -890, 96, 2372, 2531, -2406, -5451, -678, 4460, 2731, -1480, -2587, -1581, -1495, -2778, -4494, -5866, -6190, -4891, -2246, -1651, -4325, -4763, -979, -611, -5651, -8572, -7390, -6553, -7166, -5972, -2879, -938, 690, 3100, 1591, -3172, -3232, 182, 1817, 1854, 264, -890, 721, 2133, 912, 217, 1415, 1526, 917, 2486, 4155, 2897, 1574, 2637, 3760, 3778, 3347, 1892, 762, 1048, 824, -1691, -4188, -2370, 1804, 2463, -277, -1379, -870, -1332, -2708, -3831, -3175, -1393, -1916, -4880, -4286, 336, 1883, 986, 447, -1786, -3164, -2133, -954, 149, 648, 576, 562, -1198, -3766, -1850, 2894, 3309, 507, -19, 2051, 3466, 1797, -381, 413, 1023, -2027, -3939, -519, 3613, 3338, 343, -1463, -550, 970, 1477, 1467, 1383, 1619, 1489, 506, -1603, -3539, -1976, 1794, 2267, 72, -528, 1947, 5098, 5169, 3550, 3805, 5047, 5486, 4063, 1268, 2501, 7545, 8459, 5378, 3971, 4048, 4710, 5657, 5445, 5001, 4580, 4242, 5119, 4093, 1860, 3239, 5685, 5882, 4110, 1715, 641, 1583, 2469, 2068, 1619, 1139, 1381, 4601, 7820, 6540, 3388, 2400, 3448, 4133, 3093, 2492, 4721, 6981, 6365, 4556, 3499, 3484, 2863, 846, 796, 3960, 5774, 4498, 2842, 2581, 3239, 2857, 1961, 974, -1770, -3560, -2839, -2497, -698, 4152, 6088, 3763, 3787, 6678, 7559, 5237, 2619, 2872, 4637, 4410, 3417, 3368, 2932, 4355, 7964, 8830, 6586, 5319, 6553, 7573, 6632, 5286, 5087, 4600, 2234, 188, 1642, 4203, 3463, 1435, 938, 760, 508, 885, 1691, 1953, 1449, 1631, 1601, 133, 1194, 4629, 4678, 3443, 4561, 4452, 3108, 3238, 4089, 4870, 5267, 5604, 5036, 2462, 1433, 4192, 5315, 3789, 3963, 4787, 3703, 2092, 1241, 1319, 2251, 1285, -1567, -843, 3291, 4546, 2355, 1138, 1205, 751, 797, 1565, 1782, -354, -3807, -1881, 4012, 5271, 3557, 3486, 3375, 2776, 2950, 3251, 3194, 3249, 3810, 3855, 1975, -1126, -940, 3225, 4848, 2651, 734, 634, 1792, 3381, 4345, 3595, 3250, 4002, 3782, 3469, 2378, 2254, 6072, 8786, 7021, 4213, 3519, 4650, 5463, 4711, 4112, 4744, 5525, 5911, 6139, 6388, 5406, 3173, 3534, 6366, 7109, 4691, 2641, 2499, 3267, 4328, 5606, 7003, 7502, 7372, 6297, 4334, 3689, 3266, 29, -2847, -1677, 33, 85, 268, 86, -785, -418, 1042, 789, -1156, -2370, -1910, -1434, -4091, -7832, -5927, -256, 1965, 1183, 674, 186, -82, 618, 72, -1899, -1925, -657, -173, 1456, 3382, 1620, 684, 4654, 7170, 5002, 1889, 688, 954, 1366, 1167, 738, 233, 536, 2436, 2741, 119, -1397, 1230, 3921, 2712, 689, -136, 142, 1762, 2721, 2556, 2197, 2450, 3023, 1632, 38, 2172, 4923, 4116, 2861, 3795, 4556, 4496, 4519, 4808, 5034, 3821, 1935, 2730, 5095, 5672, 5577, 4931, 3645, 3784, 3731, 2992, 3484, 3875, 3102, 2895, 3019, 1007, -1790, -608, 2318, 1918, -43, -451, 450, 1298, 297, -1604, -1623, -1637, -3019, -2496, -637, -71, 787, 2455, 1826, -95, 287, 917, 94, 259, 170, -1864, -1225, 2616, 4318, 2786, 26, -1388, -522, -1853, -5343, -4649, -674, 1231, 1044, 765, 1314, 3005, 3100, 1978, 4340, 6260, 3174, 2352, 5428, 6220, 5443, 5684, 5658, 5450, 6100, 5843, 3771, 1993, 4345, 8851, 8961, 6941, 7843, 8243, 5421, 2837, 2592, 3036, 2611, 2196, 2303, 2205, 2356, 2759, 2644, 2392, 959, -1259, 162, 3309, 2071, -45, 54, -13, 242, 368, -412, 125, -327, -3571, -2096, 2895, 1730, -1723, -1274, -1544, -3663, -2949, -961, -1055, -1601, -1427, -2154, -2398, -1619, -3955, -5667, -2122, 1925, 3938, 4197, 2963, 4168, 5994, 4112, 2923, 5139, 5828, 3220, 1748, 2308, 1009, -690, 2060, 5443, 3708, 309, -61, 2398, 4081, 3140, 2905, 3522, 1770, 29, 1037, 205, -4630, -6257, -1999, 1394, 693, -683, -1816, -4028, -5526, -4973, -4411, -3452, -1138, -344, -787, -826, -2294, -3537, -689, 1764, 95, -636, 906, 2549, 4161, 3687, 1740, 2392, 5532, 7884, 6501, 2537, 3033, 8006, 9194, 5810, 3354, 3497, 4375, 4195, 3541, 3404, 2615, 1857, 2706, 2058, -590, -374, 2086, 2775, 3078, 3473, 1440, -69, 656, 367, -1061, -1115, -654, -1344, -1831, 312, 3426, 3904, 3420, 4241, 3118, -674, -1434, 530, -107, -607, 818, -1512, -4909, -2449, 2061, 2156, 263, 655, 2172, 2831, 2652, 901, -1555, -1527, 277, 371, -2020, -3974, -2608, 387, 1066, -284, -1228, -887, 180, 836, 1446, 1313, 477, 1025, 2048, -5, -3471, -3176, -35, 1043, -603, -1854, -2022, -1773, -585, 46, -473, 340, 1526, 396, -679, -1284, -2367, -511, 3564, 4233, 2003, 2457, 5234, 4990, 2543, 2633, 4467, 4720, 2892, 1638, 2200, 1889, -266, -2646, -4303, -3163, -410, 232, 255, 1522, 2242, 1801, 3301, 5347, 3814, 1024, 1207, 2977, 2553, 1897, 3040, 2509, 65, -860, 1202, 2444, 885, 44, -457, -2713, -3634, -1617, -443, -118, 258, -453, -915, -165, -801, -3926, -4474, -823, 947, -1123, -2738, -2869, -2036, 199, 1701, 621, -885, -1495, -1573, -1023, -1726, -4852, -6058, -656, 3691, 476, -2841, -2133, -804, -1218, -1475, -711, -1103, -1984, -813, 770, -110, -1295, -1924, -4235, -6095, -3148, 780, -687, -3489, -2873, -1253, 325, -318, -3836, -5266, -4856, -5421, -5892, -5866, -5580, -5528, -5390, -3479, -913, 71, -869, -2918, -3666, -3309, -3358, -2544, -1983, -3182, -3275, -886, -804, -5587, -7132, -922, 3295, 675, -2516, -2782, -1089, 218, -99, -1124, -2288, -3048, -2950, -1621, -127, -939, -2455, -2120, -3553, -7025, -5642, -414, 1271, -397, -1501, -2105, -2151, -2488, -3120, -2590, -3302, -5471, -5423, -3496, -2273, -3400, -8034, -9760, -4385, -1995, -4993, -4824, -3972, -5504, -5210, -3733, -3783, -4783, -4727, -4145, -4735, -4266, -3439, -6563, -9038, -5655, -2229, -2669, -3362, -3424, -3842, -3732, -3364, -2529, -1077, -1169, -3233, -3804, -2134, -2085, -3160, -1540, 476, -500, -2255, -1881, -1037, -2577, -3514, -762, 644, -2395, -3980, -2099, -1840, -2837, -2930, -3373, -5388, -6291, -3696, -1682, -1024, 1172, 2777, 1395, -104, 639, 965, 76, 769, 2066, 1279, 1046, 3538, 4382, 318, -2268, 1936, 6038, 4031, 1392, 1671, 1847, 1992, 3496, 3434, 854, -521, -37, -138, 433, 1712, -52, -2145, 1039, 5351, 4062, 483, -287, 134, 579, 1587, 1883, 998, 925, 2052, 2329, -1589, -915, -2382, -3208, -1668, -796, -1359, -1561, -1501, -2094, -2943, -1827, -7, -204, -1130, -1356, -1753, -2263, -1632, -1528, -2294, -2618, -3077, -2848, -1594, -1064, -1409, -1996, -1874, -1202, -590, 193, -333, -1341, -512, -570, -2277, -2394, -2343, -2673, -2238, -2316, -2713, -3077, -3107, -2149, -1472, -2091, -3024, -2330, -1142, -875, -484, 29, -417, -1143, -1053, -647, -491, -587, -492, -654, -1008, -1557, -1574, -698, -869, -1480, -959, -720, -2180, -3366, -2595, -1749, -2490, -3942, -4205, -3875, -4628, -4669, -3539, -3179, -3005, -2462, -2328, -2514, -2280, -2194, -2322, -1667, -1502, -2162, -1872, -908, -138, 104, -1030, -2216, -1581, -835, -1293, -1842, -1470, -1286, -2049, -2346, -2329, -2725, -2872, -2098, -925, -1529, -3454, -4152, -3914, -3779, -4005, -4098, -3544, -2952, -2979, -3274, -2590, -1531, -1675, -2044, -2356, -2710, -2255, -2244, -2617, -1962, -1477, -1608, -1354, -1228, -1836, -2846, -3000, -2032, -1786, -2515, -2534, -1591, -553, -542, -1039, -637, -111, -334, -683, -1361, -1782, -1302, -1060, -1540, -2140, -2193, -2835, -3621, -2685, -2826, -4907, -4730, -2579, -2513, -4292, -5029, -4206, -3854, -4680, -5140, -4932, -4918, -5216, -5330, -5363, -5112, -4065, -3735, -5100, -5872, -5021, -4590, -5133, -4805, -4017, -4298, -4186, -2906, -2603, -2631, -2039, -2189, -2028, -1603, -2168, -2759, -2469, -1652, -1189, -1411, -2033, -2147, -1654, -1548, -1633, -1949, -2138, -1951, -2377, -2484, -2411, -4050, -4994, -3390, -2409, -3264, -4310, -4483, -4033, -4065, -4976, -5159, -3686, -2515, -2635, -2156, -2302, -3696, -3215, -2108, -2650, -3147, -2849, -3217, -4198, -4074, -2902, -2032, -1580, -862, -832, -1909, -2528, -2238, -2096, -3067, -4204, -4258, -3817, -2966, -2552, -3600, -4527, -4477, -3375, -2714, -3656, -3433, -2047, -2061, -1964, -1275, -1232, -619, -69, -586, -685, -580, -645, -25, -166, -982, 8, 1458, 1498, 936, 1043, 1708, 1705, 1245, 574, -109, -84, -458, -1393, -1196, -527, -968, -2230, -3082, -3133, -2737, -2303, -2646, -3394, -2787, -2249, -3611, -4304, -3165, -2245, -2104, -2354, -2639, -1880, -563, -579, -1277, -1001, -814, -1474, -1436, -1144, -1411, -853, 211, 184, -873, -1354, -1156, -1003, -364, -116, -715, -1030, -568, -1063, -2307, -1829, -1450, -1832, -1460, -1428, -1914, -1308, -980, -1920, -1462, 111, 50, -446, 188, 379, -762, -1138, -90, 564, 531, 659, 448, -425, -621, 302, 219, -446, 176, 634, 622, 957, 769, 998, 2635, 2595, 1015, 802, 955, 508, 337, 730, 1425, 2222, 2137, 1572, 1691, 1787, 2046, 2433, 2018, 1451, 1027, 544, 549, 1205, 2091, 1997, 1998, 2840, 3099, 2583, 2190, 2446, 3442, 4186, 3563, 3110, 3981, 4149, 3643, 3629, 3418, 2760, 2152, 1716, 2096, 1992, 364, -166, 438, 932, 1515, 737, -143, 516, 1015, 966, 1007, 1235, 1366, 1276, 1849, 2468, 1788, 1308, 2384, 3284, 2342, 1219, 2435, 3596, 3107, 3056, 3560, 3767, 3419, 2739, 3125, 4271, 4516, 4310, 4669, 4660, 4136, 4137, 4009, 3774, 4132, 4601, 4302, 3388, 2391, 2065, 2823, 3399, 3178, 2916, 3027, 3294, 2893, 2994, 4291, 4994, 4638, 3437, 2382, 3179, 4709, 4642, 3880, 4039, 4597, 4484, 4713, 5232, 4504, 3732, 3813, 3998, 3692, 2916, 2662, 3330, 3428, 2802, 2832, 3390, 3099, 2664, 3679, 4190, 3941, 4401, 4107, 3163, 2862, 2841, 2932, 3190, 3411, 3640, 3863, 3989, 3736, 2746, 1783, 2850, 4213, 2850, 1489, 2640, 3280, 2182, 2238, 3113, 2358, 1348, 2219, 3856, 4454, 3975, 3467, 3338, 4006, 4225, 3967, 4382, 3926, 3173, 4103, 5001, 4232, 3391, 3526, 3340, 2018, 1358, 2598, 3788, 3076, 2349, 3345, 3941, 3510, 3826, 3594, 2941, 3886, 4600, 4140, 4108, 4303, 3787, 3572, 3765, 3007, 2355, 2491, 2968, 3927, 3353, 1352, 1262, 2614, 1956, 599, 1126, 1276, 449, 1164, 2471, 2547, 2519, 3268, 3824, 3803, 3429, 3314, 4714, 5666, 4301, 3749, 5093, 5015, 3544, 3439, 3921, 3892, 4616, 4437, 2947, 3006, 4170, 4747, 4934, 4574, 2880, 1244, 1390, 1691, 1036, 1254, 1746, 758, 905, 2297, 2799, 2271, 1785, 2287, 2701, 2456, 2481, 3592, 4726, 3839, 2855, 3557, 3499, 2898, 3819, 4887, 4347, 3905, 4143, 3884, 4317, 4834, 3259, 2076, 2787, 3915, 4526, 4200, 3841, 3336, 2491, 2966, 3693, 3385, 3788, 3636, 1379, 447, 1927, 2178, 1489, 1398, 1016, 1117, 1755, 2266, 2969, 2471, 742, 642, 1714, 1992, 1624, 1668, 2877, 4391, 3806, 2368, 2900, 3414, 2607, 2116, 2186, 2304, 2494, 2177, 2103, 3654, 4708, 3500, 2880, 3765, 4276, 4910, 5206, 4246, 3633, 3267, 2246, 1365, 822, 784, 1337, 923, 211, 1239, 1971, 1668, 2638, 3708, 2891, 1984, 2758, 4326, 4406, 2608, 2145, 3042, 1978, 491, 1316, 2457, 2717, 3352, 3178, 2424, 2627, 3034, 3058, 3061, 3519, 4278, 4796, 3849, 2918, 4039, 4564, 3273, 2580, 2867, 2745, 2437, 2495, 2248, 1145, 321, 259, 94, -210, 262, 572, 107, -139, -365, -525, -156, 398, 634, 381, 350, 869, 1665, 1960, 1909, 2443, 2611, 2496, 3265, 2959, 1810, 2205, 2657, 2755, 3356, 3467, 3051, 2328, 2033, 2584, 2198, 861, 397, 890, 1453, 1582, 1115, 618, -50, 242, 1827, 1913, 798, 527, 1073, 1721, 701, -546, 510, 1314, 878, 1481, 2185, 1045, 303, 1405, 1545, 774, 1239, 2130, 1444, 240, 254, 702, 259, 556, 1469, -340, -2541, -1819, -790, -1010, -1557, -2313, -1491, -407, -1076, -990, -548, -1489, -1289, 773, 1493, 604, -591, -953, -209, -189, 152, 1599, 582, -2385, -2214, -88, 392, 8, -403, -960, -843, -192, 48, -58, 246, 503, 717, 977, 625, 502, 741, 796, 1258, 1919, 1676, 400, 114, 1633, 1375, -889, -860, 807, 1445, 1165, 793, -38, -1305, -1498, -598, -501, -1194, -2202, -2881, -2139, -1311, -1490, -1617, -628, 694, 1102, 1116, 1063, 244, -603, 521, 2094, 2159, 2065, 1893, 865, -118, 448, 2122, 3193, 2675, 929, 616, 1277, 250, -309, 946, 1049, -220, -227, 641, 848, 669, 260, -322, -1175, -1615, -1243, -1215, -1875, -2655, -2116, -62, 779, -800, -2070, -1860, -1039, -518, -877, -1272, -891, -534, -496, 227, 838, 180, -348, 308, 1791, 1723, -343, -475, 1404, 1602, 1013, 1220, 765, 80, -133, -135, -1017, -2135, -1381, -1080, -1959, -1710, -684, 164, 770, 532, 230, 795, 1375, 1170, 725, 783, 1175, 1434, 1249, 328, -398, -87, 261, -120, 36, 442, -432, -1901, -1771, -463, -528, -691, 168, 147, -207, 560, 987, 498, 691, 481, -664, -828, -527, -478, -1151, -2092, -1120, -1193, -2538, -1241, 581, 58, -734, -301, -252, -820, -1483, -1561, -1086, -681, -314, -1055, -1194, 257, 578, 747, 1100, 775, 1463, 2198, 1589, 821, 190, -757, -1088, -132, 222, -369, 86, 518, -524, -933, -376, -781, -1670, -1831, -2306, -3539, -4009, -3450, -2884, -2062, -2233, -2585, -384, 880, -461, -654, -786, -2563, -2399, 126, 733, -961, -1422, -306, -137, 16, 610, 17, 134, 1646, 1734, 1792, 2652, 1142, -895, 97, 1618, 482, -708, -83, -160, -1752, -2853, -2131, -1109, -1372, -1722, -1121, -186, 452, 1216, 1670, 1405, 1294, 2250, 2982, 2022, 1235, 1416, 2208, 2502, 1780, 1602, 1518, 334, 219, 1384, 1031, 66, -265, -54, 428, 162, 216, 783, 176, -993, -724, -188, -1855, -2975, -1646, -2042, -3671, -2962, -2331, -2414, -1703, -2509, -4022, -3120, -1510, -1753, -2516, -2267, -2051, -2555, -2272, 236, 916, -1574, -1329, 982, 1384, 683, 684, 1348, 2057, 1827, 1292, 1485, 1216, 566, 647, 637, 406, 158, 42, 498, 465, 484, 1520, 1104, -398, 33, 780, -46, -810, -851, -1292, -2235, -2618, -2026, -1610, -1684, -1002, -129, -984, -2636, -1993, 64, 695, 875, 1180, 702, 263, 392, 466, 696, 1513, 1664, 1205, 1469, 2067, 2725, 2886, 2236, 1752, 1526, 1412, 804, -354, -109, 648, 642, 442, -296, -1092, -1221, -1518, -1194, -531, -1418, -2212, -2492, -2633, -1948, -1689, -2137, -1336, -12, -233, -861, -964, -583, -819, -2054, -1871, -1268, -1576, -1230, -616, -804, -375, -67, -900, -948, 12, 266, -53, 562, 1237, 691, 189, 656, 197, -960, -495, 258, -580, -612, 585, 898, 195, -1260, -2209, -1984, -1568, -923, -650, -1836, -3315, -3056, -1825, -1220, -710, -361, -344, -646, -200, 754, -132, -1186, -828, -998, -1823, -2042, -1682, -1832, -2130, -1326, -806, -894, -502, -1004, -1724, -338, 480, -426, -228, 733, 1563, 2168, 1125, 968, 2293, 1410, 705, 1591, 524, -654, 250, -93, -1073, -787, -1015, -1990, -2926, -3291, -2450, -1405, -839, 40, 664, 1030, 1294, 628, 329, 629, 578, 349, 693, 1537, 898, -349, -28, 1061, 1856, 2008, 2155, 2091, 1271, 1069, 1958, 2658, 2090, 831, 112, -115, -381, -538, -662, -1173, -1526, -1932, -1830, -938, -776, -1700, -1977, -1401, -1775, -2846, -2697, -1546, -1161, -1162, -957, -1517, -1749, -669, -1103, -2299, -1374, -784, -1585, -1201, -352, 47, 1376, 2798, 2348, 752, -663, -1963, -2039, -1412, -1542, -1849, -1755, -696, 605, -315, -1885, -1055, 383, 470, 296, 708, 1130, 1199, 627, -301, -29, 5, -1502, -643, 1668, 1276, 63, -317, -318, 369, 657, 342, 440, -56, -833, -440, 407, 570, 197, -129, -579, -1569, -1627, -322, -157, -1733, -2772, -1648, -1221, -3068, -4000, -2744, -2349, -3971, -4807, -3655, -2939, -3466, -3282, -2297, -1965, -2383, -2369, -1498, -156, 829, 665, 24, -358, -185, 251, 448, 513, 1172, 1668, 1252, 559, 870, 1328, 90, -615, 312, 795, 246, -137, -288, -1217, -2229, -2147, -2167, -2924, -2816, -3042, -4033, -4084, -3257, -3434, -4435, -3889, -2631, -1870, -884, -1330, -1873, -496, 459, -3, -301, 124, 621, 1556, 1911, 1017, 150, -224, -801, -1394, -1620, -1108, 93, 383, 294, 674, 517, 281, -75, -548, -124, -5, -1066, -1645, -1358, -1390, -1708, -1753, -1800, -2208, -2542, -2196, -2044, -2097, -1532, -1213, -2508, -3969, -4454, -4150, -2757, -2498, -3567, -3377, -2691, -2648, -2398, -2135, -1760, -1725, -1965, -1367, -968, -1261, -1234, -858, -328, 173, -624, -2760, -3421, -1993, -1081, -1616, -2331, -1918, -1192, -1762, -3007, -3284, -3058, -2784, -1560, -1818, -3489, -2775, -1669, -2259, -2388, -2110, -2684, -3042, -2471, -1668, -1243, -1248, -446, 944, 330, -1255, -1258, 177, 1230, 1009, 339, -30, 944, 1976, 245, -1439, -1222, -1473, -1710, -2266, -2679, -2091, -2637, -3784, -3376, -2749, -2773, -2793, -2249, -994, -574, -1311, -1980, -2573, -2155, -891, -659, -90, 1378, 1021, -164, -336, -262, -389, -1115, -881, 280, 796, 400, 12, -526, -1414, -1182, 104, 862, 688, 337, -472, -948, -445, -30, -247, -935, -1596, -1819, -2367, -3569, -3019, -1151, -1324, -2475, -2312, -2588, -3369, -2634, -2246, -2560, -2230, -2621, -3110, -2484, -1695, -1289, -1254, -1463, -2424, -3882, -4843, -4040, -2654, -2988, -3828, -3213, -1882, -875, -94, -133, -832, -1382, -1946, -2704, -3059, -3278, -2874, -1116, 314, -23, -500, 318, 976, 463, -473, -420, 978, 1491, 896, 997, 1332, 1650, 2491, 2279, 1659, 1941, 1701, 706, 87, 468, 936, 342, 180, 1137, 1658, 1065, 211, 70, 808, 1342, 1433, 1170, 704, 829, 1108, 395, -304, -415, -1202, -2054, -1292, -115, -272, -560, -283, 268, 918, 678, -703, -1566, -164, 1068, 352, 296, 750, -271, -1544, -1086, 255, -175, -1898, -1630, 300, 1277, 846, 737, 1663, 1776, 694, -775, -871, 640, 515, -1042, -741, 285, -470, -917, 156, 145, -980, -1096, 187, 1131, 832, 1186, 2219, 1495, 46, -45, -150, -1292, -852, 1138, 1391, 386, 97, 271, 761, 640, 150, 644, 1469, 1799, 1513, 1849, 2534, 1486, 402, 1614, 2547, 1643, 641, -362, -1289, -584, 1054, 818, -1389, -2603, -1357, -14, -753, -1169, -428, -682, -1204, -1272, -1225, -612, -254, -306, -223, -564, -234, 923, 617, -1005, -1812, -1159, -386, 543, 2359, 2217, 336, 584, 1792, 1284, 458, 787, 1497, 1510, 1449, 1818, 1340, 185, 526, 1629, 1567, 841, -399, -991, 190, 859, 213, -187, -55, 181, -418, -1687, -1973, -1608, -2074, -2369, -1908, -1294, -1060, -1600, -623, 1465, 1610, 360, -4, 673, 318, -616, -589, -259, 376, 545, -851, -477, 1118, 637, -433, -972, -1224, -1548, -2502, -2241, -775, -1688, -2962, -1906, -1280, -1938, -1356, -425, -1337, -1724, -409, -438, -1877, -1540, -24, 743, 1505, 1697, 856, 648, 1383, 2054, 2025, 918, 435, 1512, 1756, 1403, 1147, 456, 117, 463, 264, -14, 1477, 2534, 1658, 707, -230, -516, 265, 932, 66, -1221, -1537, -1428, -897, -332, -259, -483, -138, 468, 920, 1026, 954, 2360, 2921, 719, -517, 644, 1487, 1478, 933, -14, 713, 1929, 1602, 665, -871, -2352, -936, 861, 222, -252, 351, 589, 268, 60, -23, -420, -876, -899, -1123, -1477, -682, 167, -79, -206, -467, -1209, -1347, -1475, -1985, -1262, 61, 165, 17, 437, 662, 447, 369, 1211, 1059, -567, -1698, -1984, -1612, -986, -1927, -2762, -1514, -1004, -1412, -450, 0, -1483, -2193, -1446, -1607, -2626, -1834, -395, -449, -912, -1178, -1289, -1289, -2783, -4678, -4157, -3025, -2651, -3421, -4676, -4473, -3554, -2095, -558, -607, -1838, -1998, -1016, -1257, -2859, -2749, -1259, -1580, -1883, -1028, -900, -849, -99, -667, -1793, -695, 519, -75, -477, 419, 575, -460, -704, -388, 30, 1002, 546, -1058, -1133, -627, -646, -584, -1005, -1951, -2041, -1678, -1542, -1099, -680, 90, 946, 318, -457, -95, 505, 641, 446, 805, 314, -769, 417, 1876, 1209, 865, 1417, 1160, 1053, 2007, 2425, 1146, 236, 1231, 1952, 1943, 2026, 934, -914, -1214, 199, 786, -961, -1540, 47, 186, -748, -955, -413, -210, -601, -806, -1047, -1173, -395, 148, -193, -197, 489, 424, -214, 60, 199, -138, 99, 396, 455, -174, -1934, -2162, -254, 453, 87, 565, 410, -588, -853, -1121, -949, -39, -84, -846, -914, 67, 65, -1667, -2266, -1179, -635, -1254, -1699, -2128, -1994, -984, -1268, -1229, 1006, 1947, 747, 195, 860, 1463, 839, -186, -295, 341, 38, -1097, -644, 491, -226, -1003, -871, -1304, -1131, -444, -1074, -1299, -517, -211, 394, 345, -413, 494, 1439, 967, 734, 998, 99, -1528, -1656, -242, -14, -919, -619, -562, -1332, -1204, -827, -1139, -1432, -1885, -2073, -1030, -351, -1017, -1901, -1680, -340, -344, -1648, -1246, 467, 184, -782, 694, 1063, -1103, -645, 1902, 2053, 335, 100, 966, 682, 235, 243, 249, 1121, 932, -798, -748, 65, 665, 1057, 420, 74, 767, 1226, 1231, 1129, 695, 680, -158, -1034, 90, 1072, 959, 969, 276, 34, 1449, 2091, 1316, 1036, 1946, 2425, 1874, 2307, 3247, 2735, 1895, 1881, 1212, -199, 225, 1185, -96, -1277, -237, 445, -829, -1336, -52, -146, -1155, -684, -138, 21, -106, -329, -392, -207, -120, 32, 991, 1192, -51, -793, -831, -836, -1229, -1364, 297, 2116, 1106, -824, 190, 1145, -956, -1421, 579, 349, -857, -491, 799, 1526, 551, -1056, -916, 414, 645, 356, 470, 1030, 979, -236, 5, 1872, 2117, 1165, 1184, 1866, 2514, 2200, 1180, 688, 951, 1002, -133, -624, 332, 19, -1072, -412, 845, 1030, 311, 268, 856, 989, 432, 73, 1012, 1318, -152, -576, 797, 1365, 721, -268, -694, -857, -1456, -1951, -1666, -3, 1561, 1306, 1103, 751, -1608, -2065, 416, 599, -1320, -1228, -4, -467, -1106, 23, 439, -599, -353, -364, -1450, -568, 1294, 1009, -140, 809, 2526, 1530, 1048, 3223, 3027, 718, 792, 1594, 589, -221, 320, 579, 457, 633, 984, 1079, 817, 905, 781, 340, 147, 769, 2221, 3220, 2764, 1348, 833, 1344, 1861, 2550, 2637, 1727, 1115, 1871, 2893, 2553, 2097, 1805, 790, 357, 869, 1102, 1774, 2198, 1641, 1525, 1268, 342, 190, 639, 236, 96, 1351, 2451, 2312, 1132, 714, 1578, 1418, 1139, 1847, 2183, 1950, 2156, 2418, 1784, 973, 1638, 2974, 1859, 17, 749, 2691, 3089, 1714, 888, 1616, 2148, 1934, 983, 139, 1169, 1677, 136, -53, 1447, 1655, 1376, 841, 553, 1386, 979, 245, 525, 359, 642, 1653, 1650, 785, -434, -435, 1295, 1568, 13, -727, 78, 1325, 1263, 860, 1640, 2885, 3075, 2751, 3611, 3786, 1827, 316, 216, 0, -26, 529, 1236, 745, 23, 1039, 1686, 447, -763, -1586, -2360, -1488, 283, -51, -1482, -1172, 78, -307, -1591, -1529, -698, -404, -447, 160, 484, -1184, -2054, -340, 1284, 918, -1014, -1259, 618, 500, -673, -907, -1354, -1016, -363, -1130, -1639, -238, 1142, 777, -473, -870, 215, 1810, 2070, 927, 541, 763, 934, 1381, 1252, 1002, 1685, 1505, 319, 289, 979, 1012, 1071, 1849, 1854, 817, -357, -85, 1412, 1766, 2034, 2520, 1996, 1419, 1422, 2007, 2648, 2072, 1120, 1780, 2690, 2676, 2978, 3543, 2809, 1588, 2519, 2777, 1059, 1515, 3177, 3354, 3107, 2410, 1047, 980, 1641, 252, -1042, -322, -387, -1310, -764, 354, 195, -622, -785, -34, 713, 427, 390, 1310, 1171, -39, 245, 1337, 1002, 657, 1724, 2096, 1010, 134, 422, 1343, 925, -278, 28, 765, 918, 1128, -60, -2916, -3046, -692, 407, 87, 98, 204, -801, -1150, 94, 98, -1326, -1794, -1873, -1876, -830, 340, 431, -110, -815, -827, -412, -1671, -3284, -2006, 492, 348, -422, 681, 1795, 1536, 48, -1178, 196, 1279, -27, -414, -23, -1042, -1754, -916, -635, -2004, -2337, -772, -445, -2068, -2456, -1049, -898, -1297, -681, -299, -637, -602, -1030, -2230, -2215, -1404, -1236, -1455, -1577, -1669, -2290, -2079, -501, 514, 1303, 2431, 2422, 989, -521, -1388, -2338, -2736, -2700, -3899, -4295, -2217, -462, -1296, -2543, -1632, 235, -70, -2107, -2273, -2036, -1804, 696, 1946, 720, -208, 107, 1274, 1781, 1582, 1837, 1590, 464, -766, -1557, -1465, -973, 93, 913, 421, 543, 1179, 508, 323, 384, -1492, -2363, -1711, -1470, -755, -55, -140, 732, 2305, 2256, 1963, 2113, 1416, 323, -107, 1195, 2509, 992, -346, 360, 495, 87, -241, -891, -1497, -1817, -1422, -778, -1022, -447, 1388, 1235, -492, -982, -549, -10, 459, 773, 1950, 2634, 867, -607, 1167, 3042, 1401, -153, 1633, 3282, 3117, 2990, 2064, 1145, 2342, 3685, 2968, 1643, 1685, 2461, 1931, 544, 822, 1874, 1832, 1755, 1818, 979, 477, 1139, 890, -1699, -3255, -2182, -2057, -2370, -1441, -1314, -1532, -1159, -1280, -1283, -568, -748, -1345, -520, 564, 477, 136, 52, -204, 396, 2381, 2671, 551, 1002, 2933, 1802, 781, 1551, 1292, 783, 863, 249, -498, -509, -732, -1266, -1483, -1469, -2050, -3514, -3438, -1411, -1290, -1691, -787, -926, -457, 1299, 906, -1143, -937, 1078, 1199, -464, -979, -412, 1058, 2272, 1362, 397, 1043, 1077, -508, -2267, -2457, -489, 738, 362, 461, 479, 189, -9, -1123, -1722, -606, 345, 350, 387, 1174, 1305, 272, -549, -833, -905, -1657, -2366, -1712, -1226, -2640, -3976, -2697, -1136, -1226, -1043, 446, 1207, 778, -66, -985, -832, -385, -1146, -2109, -1871, -1171, -635, -246, -636, -599, 11, -975, -2102, -428, 1383, -129, -1590, -553, 87, 483, 1244, 584, -1026, -1361, -989, -1241, -1619, -1753, -1710, -1608, -1565, -2210, -2129, -156, 178, -1419, -1510, 41, 1316, 1020, -81, -413, 117, -50, -1945, -3092, -2116, -378, -55, -1083, -1112, -435, -92, -89, -416, -1065, -1208, -820, -794, -1276, -1423, -1236, -1701, -2499, -1960, -1201, -2053, -2984, -2964, -3066, -3205, -2490, -1225, -151, 5, 23, 834, 1404, 750, 329, 683, 532, 702, 1886, 1662, 9, 14, 1315, 932, -603, -319, 1257, 1684, 777, -61, -147, 103, 109, 46, -994, -1856, -1153, -1417, -2183, -1063, -533, -1609, -1423, -331, -169, -776, -925, -212, 444, 246, -645, -1304, 131, 2015, 933, -603, -37, 166, -2, 1110, 1713, 572, -8, 1970, 2890, 1480, 2044, 3917, 2928, 1241, 1668, 2560, 2441, 2078, 2221, 1902, 1714, 1888, 1317, 415, 177, 71, -376, -468, -74, 185, 72, -313, -946, -1604, -1239, -603, -683, -670, -527, -447, -633, -1271, -1583, -470, 1215, 815, 200, 1652, 1538, -351, -766, -411, -330, 143, 1088, 972, 633, 1968, 2513, 596, -348, 777, 549, -1250, -1513, -234, 897, 1053, 523, -452, -1775, -1549, -659, -937, -868, -190, -787, -1461, 283, 1785, 978, -280, -273, 390, 1142, 1007, 533, 516, 588, 513, 635, 664, -83, -1260, -1792, -1631, -1673, -2282, -2545, -1917, -598, -67, -1365, -2884, -3418, -2982, -2085, -1816, -2132, -2486, -2586, -2370, -1925, -1352, -782, -664, -1241, -1675, -1402, -812, -588, -473, -177, 163, 445, 631, 875, 1072, 1001, 711, 405, 86, -124, -333, -777, -1240, -1921, -2831, -3018, -2510, -1965, -1485, -997, -891, -1402, -1858, -1195, 335, 1445, 1455, 503, -411, -755, -475, -299, -567, -2, 1338, 2046, 2323, 2554, 2445, 2946, 3668, 3473, 3327, 3475, 2943, 2033, 1851, 1942, 1761, 1765, 1354, 1091, 1813, 2218, 1941, 1587, 750, -192, -610, -1070, -1303, -1399, -1671, -1468, -1055, -1181, -1362, -560, 702, 892, -28, -607, -310, -52, -149, -337, -738, -1329, -1676, -1629, -1557, -1539, -1240, -15, 1694, 2374, 2197, 2026, 1912, 1707, 1303, 1044, 1160, 1601, 1987, 1996, 2174, 2430, 2409, 2671, 2934, 2540, 2031, 1716, 1434, 1439, 1167, 367, 59, 175, -160, -332, 43, 416, 883, 1273, 1140, 1036, 1473, 2099, 2626, 2687, 2221, 2491, 3409, 3019, 2591, 4350, 5803, 5193, 4858, 5894, 6979, 7587, 8355, 9115, 9048, 8476, 8375, 8766, 9521, 10470, 11072, 11732, 12989, 13989, 14458, 14785, 15149, 15861, 16018, 15346, 15215, 15112, 13670, 12568, 13251, 13399, 12616, 12677, 12580, 11490, 11059, 11996, 12653, 12503, 12456, 12725, 12610, 11813, 10968, 10045, 8910, 8093, 7542, 6851, 6153, 5478, 4797, 4227, 4121, 3815, 2659, 1655, 947, -60, -1067, -1942, -2694, -3523, -4835, -6114, -6607, -7256, -8535, -8910, -8774, -9524, -10414, -10452, -9906, -9405, -9012, -8733, -8961, -9193, -8811, -9123, -9913, -9923, -9763, -9629, -9185, -8793, -8609, -7993, -7388, -7274, -6701, -5792, -5783, -6228, -6037, -5881, -5999, -6097, -6672, -7714, -8395, -8723, -9588, -10531, -10823, -11041, -11682, -12018, -12133, -12302, -11630, -10855, -10816, -10270, -8811, -7350, -6121, -5164, -4723, -4327, -3833, -3792, -3886, -3786, -3888, -4246, -5122, -6887, -8072, -7019, -5576, -6372, -7771, -7601, -6831, -6324, -6934, -8774, -10047, -10093, -10169, -10834, -11642, -12230, -12248, -11871, -11840, -12054, -12216, -12105, -11538, -11127, -11118, -11043, -10666, -9983, -9491, -9124, -8290, -7646, -7846, -8319, -8474, -8386, -7868, -6937, -6517, -6485, -6115, -5753, -5335, -4578, -4224, -4306, -4385, -4604, -4700, -5107, -5817, -5727, -5465, -5592, -5554, -5425, -5221, -4635, -4254, -4241, -4197, -4565, -4795, -3985, -3408, -3597, -3263, -2673, -2313, -1886, -1773, -1760, -1873, -2271, -2579, -3115, -3856, -4594, -5491, -6383, -6854, -6649, -5920, -4811, -3702, -3382, -3277, -2926, -2843, -2943, -3194, -3538, -3840, -4133, -3817, -3046, -2986, -3626, -3476, -2585, -2140, -1844, -1344, -966, -486, -38, 140, 191, -284, -862, -1161, -1832, -2402, -2239, -1920, -1951, -2289, -2511, -2553, -2873, -3141, -2845, -2948, -3176, -2401, -1968, -2917, -3679, -3689, -4312, -4293, -2723, -2497, -4065, -5051, -5174, -5436, -5617, -5651, -5977, -6079, -5190, -4652, -5450, -6060, -5767, -5374, -5289, -5559, -5900, -5787, -5427, -5552, -5865, -5744, -5236, -4899, -5098, -5115, -4574, -4053, -4057, -4675, -5256, -5120, -4459, -3802, -3596, -3947, -3965, -3040, -2553, -2987, -2897, -2529, -2721, -2548, -2297, -2892, -3277, -2925, -2644, -2839, -3235, -2980, -2489, -2937, -3606, -3518, -3669, -4233, -4384, -4210, -3829, -3407, -2879, -1789, -749, -479, -385, -345, -827, -1589, -2341, -2830, -2507, -1970, -1817, -1637, -1238, -809, -644, -536, -389, -597, -609, -26, 213, -169, -434, -644, -915, -944, -1278, -1629, -974, -139, -435, -1305, -2106, -2856, -3224, -3223, -3543, -3798, -3086, -2136, -1506, -545, 264, 38, -283, 3, -225, -989, -1669, -2157, -2092, -1664, -1751, -2018, -1515, -1146, -1033, -420, -101, -165, 562, 1643, 2072, 2118, 1851, 1580, 2042, 2549, 2124, 1578, 1738, 1755, 1223, 823, 769, 636, 92, -418, -533, -956, -1670, -1864, -1901, -2108, -1936, -1496, -1426, -1337, -963, -502, -76, 76, -130, -247, -20, -129, -854, -1145, -714, -738, -777, -278, -245, -466, 89, 354, -80, -116, 277, 536, 281, -155, -498, -349, 72, -268, -946, -1042, -1031, -1426, -1627, -1465, -1375, -1096, -1070, -1278, -1065, -1063, -1372, -1297, -986, -894, -1039, -914, -654, -88, 777, 1025, 850, 1107, 1451, 809, 168, 95, -386, -455, 297, 627, 439, 371, 283, 175, 285, 390, 405, 60, -382, -253, 465, 1036, 804, 429, 502, 433, 11, 31, 557, 608, -126, -244, 713, 1110, 646, 654, 924, 764, 471, 466, 670, 636, 630, 167, -724, -130, 1348, 1640, 1269, 1431, 1671, 1522, 1330, 1124, 926, 677, 423, 155, -408, -638, -201, 249, 588, 585, 320, 361, -91, -669, -335, -703, -1883, -1639, -657, -371, -150, 291, 610, 682, 626, 387, 275, 738, 1377, 1320, 1063, 1553, 2168, 2267, 1933, 1702, 2016, 2015, 1730, 1901, 2069, 1828, 1479, 1300, 1241, 1286, 1362, 1278, 918, 758, 1072, 1580, 1596, 1034, 1002, 1305, 1074, 709, 744, 1026, 1010, 650, 412, 306, 520, 671, 494, 841, 1309, 1048, 921, 1426, 1803, 1601, 1333, 1142, 639, 161, 319, 810, 829, 661, 1088, 1596, 1883, 2197, 2483, 2842, 3252, 3114, 2534, 2093, 1700, 1453, 1445, 1462, 1244, 1182, 1403, 1439, 1367, 959, 442, 806, 1687, 1902, 1749, 1991, 2221, 2387, 2606, 2772, 3009, 3118, 3060, 3123, 3397, 3269, 2899, 3162, 3216, 2702, 2543, 2709, 2482, 2033, 1627, 1405, 1674, 1993, 2166, 1775, 1177, 1123, 1292, 1263, 881, 795, 1253, 1181, 979, 1089, 777, 531, 1440, 2513, 2598, 2564, 2667, 2505, 2413, 2353, 1622, 939, 992, 1034, 1039, 714, 303, 606, 987, 946, 678, 373, 353, 540, 626, 410, 201, 568, 1192, 1452, 1544, 2197, 2893, 3101, 3608, 3783, 3106, 2644, 2805, 2733, 2351, 2440, 2688, 3055, 3543, 3320, 2381, 1579, 1182, 500, -307, -499, -934, -1726, -1789, -1342, -1203, -1296, -1606, -2167, -2009, -1190, -1124, -1677, -1077, 220, 357, -337, -426, 458, 1317, 1386, 1562, 2483, 3469, 3715, 3468, 3335, 3510, 3166, 2487, 2467, 2488, 1982, 1834, 2146, 1941, 1293, 1176, 1557, 1518, 874, 475, 744, 653, 261, 217, 42, 51, 479, 611, 264, -25, 45, 524, 1655, 2652, 2461, 1874, 1787, 2325, 3012, 2817, 2141, 2146, 2533, 2506, 2048, 1893, 2077, 2237, 2552, 2836, 2770, 2344, 1728, 1540, 1690, 1320, 475, 350, 1040, 1329, 1166, 1295, 1569, 1724, 1923, 2273, 2589, 2357, 1595, 1001, 497, 91, 359, 998, 1141, 704, 415, 569, 972, 1549, 1874, 2159, 2570, 2348, 2020, 2202, 2287, 2029, 2045, 2536, 2641, 2406, 2333, 1985, 1900, 2317, 1957, 899, -160, -980, -1008, -886, -1271, -1595, -1478, -1121, -1194, -1380, -732, 450, 1426, 2072, 2509, 2815, 3021, 3034, 2621, 2169, 2462, 3239, 3413, 3295, 3813, 4630, 5111, 5064, 4856, 4969, 5181, 4564, 3345, 2662, 2188, 1903, 2022, 1578, 964, 867, 826, 922, 1032, 624, 53, -55, 18, -456, -1329, -1945, -2218, -2458, -2434, -2423, -2461, -1694, -287, 622, 618, 514, 867, 1098, 841, 633, 1166, 2049, 2369, 2231, 1925, 1620, 1264, 795, 658, 495, -7, -229, -369, -976, -1388, -1352, -1527, -1510, -979, -504, -461, -803, -714, 47, 812, 962, 169, -731, -799, -588, -268, 303, 968, 1684, 2154, 2863, 3888, 4146, 4283, 4746, 4492, 4348, 4522, 4165, 4320, 5089, 5236, 5117, 5354, 5335, 4376, 2991, 1731, 715, 375, 177, -520, -1250, -1394, -1443, -1906, -2279, -2250, -1925, -1613, -1387, -1066, -788, -761, -550, 97, 696, 1167, 1354, 1167, 1104, 1287, 1789, 2627, 3286, 3798, 4038, 3664, 3202, 2741, 2408, 2483, 2473, 2011, 1197, 534, 394, 547, 447, 8, 145, 602, 373, 124, 63, -456, -1201, -1757, -1858, -1637, -1843, -2166, -1632, -1186, -1710, -1928, -1337, -927, -356, 752, 1548, 1847, 1959, 1985, 1862, 1450, 1387, 1820, 1728, 1749, 2502, 2326, 1250, 1093, 1693, 1717, 1251, 1160, 1166, 468, -298, -247, 239, 786, 1158, 1068, 855, 1278, 1620, 1042, 162, -577, -838, -672, -958, -1314, -391, 1281, 1869, 1603, 1376, 683, 20, 369, 840, 835, 1301, 1933, 1512, 708, 800, 1253, 1684, 2270, 2416, 2013, 1865, 2127, 2391, 2187, 2009, 2381, 2762, 2807, 3115, 3546, 3158, 2450, 2004, 1591, 801, -582, -1493, -1294, -1396, -2478, -3508, -3525, -2666, -1822, -1399, -959, 79, 1172, 1370, 630, -105, -451, -711, -1174, -1800, -1857, -1635, -1372, -835, -358, 19, 220, 352, 934, 1492, 1234, 977, 1130, 1245, 1337, 1189, 1072, 1381, 1485, 1010, 555, 435, 243, -102, -653, -1160, -882, -245, -262, -931, -1366, -1428, -1624, -1803, -2015, -2228, -2050, -2081, -2258, -2071, -1936, -1952, -2163, -2259, -1880, -1658, -1994, -2750, -3365, -2380, -688, -363, -840, -783, -44, 503, 505, 193, -73, 254, 676, 762, 1001, 1168, 1344, 1352, 961, 1126, 1943, 2377, 1876, 1607, 2347, 2679, 2896, 3691, 3774, 2578, 1295, 1014, 1070, 832, 806, 1241, 1467, 1414, 1435, 1174, 857, 962, 1208, 970, 711, 1326, 1987, 2280, 2682, 2519, 1779, 1391, 1283, 1083, 1167, 1292, 1086, 790, 1055, 1908, 1919, 1450, 1673, 1394, 479, 99, 278, 605, 672, 558, 400, 355, 654, 1217, 1395, 770, 420, 861, 1295, 1123, 429, -6, 454, 1102, 1275, 1263, 1094, 1459, 2226, 1964, 1218, 1015, 1012, 653, 217, 562, 953, 387, -29, 226, -224, -1058, -756, -103, -48, 79, 233, 302, 618, 820, 680, 348, 516, 1399, 2017, 1793, 1559, 1957, 2367, 2317, 2201, 2384, 1997, 1188, 1132, 1481, 1564, 1634, 1982, 2278, 2111, 1505, 1206, 1423, 1658, 1185, 53, -382, -406, -1069, -2003, -2339, -2350, -2405, -2511, -3018, -3019, -2170, -1630, -1235, -292, 460, 374, -41, -33, 423, 700, 691, 680, 597, 953, 1845, 2047, 1926, 2216, 2522, 2483, 1868, 1124, 1190, 2014, 2089, 1216, 955, 1388, 1400, 1313, 1200, 479, -44, 246, 108, -1099, -1683, -925, -595, -1167, -1310, -1381, -1847, -1538, -932, -1094, -1182, -508, 471, 843, 566, 393, 459, 996, 1586, 1360, 667, 398, 1042, 1784, 1674, 1497, 1554, 1490, 1819, 2167, 1697, 1158, 1012, 683, 327, 309, 470, 592, 819, 994, 792, 288, -75, 11, -428, -1293, -1442, -1250, -1232, -1271, -1457, -1326, -1018, -761, -447, -344, 80, 685, 759, 384, 344, 928, 1141, 1139, 1720, 2097, 1682, 1184, 1268, 1581, 1568, 1181, 1078, 1214, 672, -70, -129, -228, -728, -1012, -901, -751, -781, -387, 334, 317, -238, -169, 309, 183, 72, 689, 832, 609, 1085, 1233, 721, 707, 1412, 2101, 2395, 2291, 2325, 2520, 2407, 2358, 2526, 2426, 1875, 1515, 1487, 1396, 987, 240, -146, 248, 716, 683, 589, 665, 197, -814, -1285, -1177, -1019, -637, -170, -298, -347, 353, 1080, 1662, 2702, 3946, 4506, 4385, 3710, 2460, 1074, 668, 1098, 1256, 1325, 1558, 1666, 1471, 701, -360, -1020, -1156, -1054, -750, -204, 122, -202, -604, -332, -154, -598, -1078, -1125, -774, -754, -1111, -1093, -931, -1129, -1061, -747, -879, -1342, -1784, -2277, -3111, -3792, -3762, -3214, -2456, -1528, -648, -146, -112, -246, -9, 493, 875, 908, 767, 728, 845, 1267, 1993, 2380, 2085, 1386, 560, -143, -239, -219, -928, -1876, -2458, -2225, -1360, -777, -668, -438, 335, 797, 113, -422, 119, 565, 363, 96, -449, -1257, -1513, -1168, -707, -680, -1303, -1108, 129, 383, 122, 445, 234, -297, -1, 136, -409, -1087, -1564, -1617, -1936, -2480, -2426, -2509, -2805, -1786, -1006, -1891, -1784, -410, -196, -774, -576, 160, 282, -249, -440, -24, 95, -198, -177, -303, -1046, -1608, -1545, -1438, -1285, -709, -304, 19, 1110, 1420, 621, 414, 668, 1075, 1178, 868, 796, 339, -210, -498, -1076, -1605, -1534, -865, -625, -1081, -1308, -1605, -1928, -1664, -1223, -655, -191, -698, -1613, -1418, -653, -629, -1064, -1323, -1074, -809, -785, -715, -1025, -1485, -1255, -480, 178, 195, 60, 241, 290, 559, 1075, 1057, 781, 938, 1128, 942, 642, 582, 705, 961, 589, -558, -313, 870, 312, -1366, -2238, -2395, -2627, -2722, -2382, -2215, -2350, -1980, -1192, -825, -881, -935, -716, -154, -330, -1106, -982, -23, 1248, 1985, 2153, 2502, 2470, 2237, 2237, 1742, 1141, 969, 886, 768, 381, -410, -998, -1145, -1087, -1171, -2021, -2885, -2848, -3041, -3883, -4076, -3710, -3743, -3981, -4102, -4154, -4723, -5367, -4569, -3439, -3694, -3897, -2892, -2228, -2387, -2366, -2245, -1878, -814, -62, -317, -1067, -1206, -634, -162, 327, 762, 589, 16, 65, 424, -263, -1503, -1426, -478, -757, -1812, -2152, -1778, -1290, -1374, -1949, -1915, -1059, -438, -443, -585, -545, -746, -1132, -1232, -871, -281, -241, -920, -1809, -2468, -2380, -1730, -1095, -518, -528, -571, 483, 1552, 1447, 1177, 1582, 1755, 1413, 1147, 1335, 1767, 1784, 1857, 2540, 2783, 2331, 2129, 1952, 1476, 905, 598, 631, 704, 930, 1434, 1577, 1310, 1349, 1603, 1331, 510, 222, 875, 1324, 1348, 1572, 1405, 1455, 2784, 3698, 3292, 2986, 3031, 2666, 2464, 2658, 2343, 1604, 1906, 3047, 3583, 3892, 4266, 4084, 3591, 3057, 2376, 1633, 1078, 843, 1089, 1177, 747, 485, 360, 606, 1212, 1075, 164, -424, -413, -651, -1180, -1044, -515, -199, -139, -333, -329, 200, 332, -120, 170, 841, 744, 330, 92, -195, -91, 553, 868, 944, 1182, 1084, 1008, 1225, 963, 479, 370, -72, -502, -532, -1596, -3246, -3058, -1933, -2273, -3083, -3148, -3002, -2768, -2594, -2720, -2544, -1736, -918, -679, -959, -887, -42, 214, 266, 934, 911, 377, 906, 1542, 905, 313, 614, 1029, 1182, 916, 365, -21, 73, 394, 457, 590, 690, 972, 1259, 621, -182, 143, 782, 710, 500, 1, -912, -1596, -1643, -1307, -1074, -1186, -1448, -1413, -1261, -1421, -1395, -976, -471, -98, -62, -272, -131, 728, 1032, 384, 33, 188, 349, 268, 63, -24, 574, 1709, 2328, 2627, 2981, 3069, 3075, 3113, 2622, 1800, 1205, 864, 1337, 2102, 1762, 1311, 1826, 2254, 2049, 1666, 1045, 395, 212, 80, -364, -377, 97, 217, 182, 555, 1166, 983, 461, 925, 1663, 1760, 2034, 2873, 3245, 2940, 2669, 2509, 2291, 2203, 2224, 2101, 1618, 1021, 759, 547, 226, 127, 596, 1347, 1002, -554, -1276, -1014, -1365, -2340, -2670, -1814, -931, -840, -853, -649, -525, -186, -229, -620, -591, -605, -933, -859, -458, -191, 268, 848, 1208, 1527, 1508, 982, 809, 902, 732, 335, -419, -786, -592, -1266, -2438, -2420, -1828, -1973, -1977, -1928, -3068, -3771, -2608, -1920, -2331, -1984, -1395, -1766, -1921, -1239, -774, -398, 223, 849, 1314, 934, 209, 344, 530, -463, -1226, -390, 220, 257, 762, 319, -651, 170, 1456, 1177, 641, 624, 267, -134, -194, -203, -258, -103, -241, -726, -659, -641, -961, -892, -788, -595, -185, -21, -217, -237, -126, -663, -1412, -1367, -1013, -712, -120, 178, 67, 274, 659, 730, 411, -64, -284, -91, -40, -380, -188, 472, 696, 447, 518, 733, 395, -282, -892, -1132, -807, -662, -1007, -1009, -644, -565, -256, 249, 118, 97, 613, 548, -240, -651, -596, -289, 276, 637, 780, 729, 724, 927, 715, 347, 790, 1253, 1267, 1689, 1844, 952, 221, 156, 19, -156, -521, -1139, -971, -521, -580, -633, -842, -853, -307, -198, -863, -1414, -1544, -1671, -2075, -2644, -2375, -1456, -938, -411, 40, -184, -417, 265, 1135, 908, 327, -238, -1173, -1497, -1335, -1017, -495, -606, -597, 397, 590, -503, -818, -277, -611, -1284, -1355, -1728, -2277, -2335, -2581, -3129, -3055, -2667, -2822, -2722, -2573, -3246, -3207, -2432, -2282, -2165, -1905, -1655, -1182, -868, -589, -489, -743, -607, -599, -647, 39, 298, -279, -792, -847, -972, -1265, -871, -571, -841, -751, -790, -1732, -2522, -2113, -1589, -2107, -2691, -2832, -3236, -3338, -3193, -3711, -3612, -2737, -2831, -3202, -2378, -1578, -1653, -1441, -1005, -1020, -921, -810, -703, -250, 169, 310, 302, 386, 337, -434, -1130, -852, -371, -281, 13, 562, 516, 7, -626, -1308, -1295, -541, -465, -1064, -340, 1158, 1384, 992, 985, 1277, 1748, 1258, -320, -1306, -1516, -1589, -1550, -1415, -882, 58, 1204, 2138, 2278, 1592, 1076, 1253, 1132, 495, -137, 70, 1160, 1737, 1380, 999, 1398, 1914, 1694, 1500, 1879, 2156, 1857, 1555, 1877, 2401, 2683, 3027, 3537, 3784, 3638, 3590, 3221, 2190, 1242, 424, -144, -468, -517, 39, 0, -1129, -1472, -699, -688, -1465, -1714, -1858, -2388, -2169, -1203, -935, -1350, -1257, -425, 139, -151, -344, 117, 398, 48, -309, -179, 338, 1017, 1234, 765, 174, -668, -1640, -2127, -2120, -1937, -2174, -2890, -3014, -2373, -2415, -3468, -4010, -3252, -2556, -3095, -3845, -3690, -3670, -3830, -3179, -2852, -2921, -2162, -1283, -668, 16, 424, 680, 463, -626, -1011, -474, -785, -1492, -1278, -606, -748, -1454, -1758, -1225, -618, -834, -1166, -1228, -1527, -1789, -1703, -1739, -2092, -2149, -1789, -1658, -1609, -1334, -1841, -2295, -1260, -348, -499, -753, -352, -184, -641, -431, -272, -862, -1251, -1301, -1112, -600, 32, 309, 204, 11, -380, -666, -431, 45, 430, 889, 1357, 1416, 1359, 1783, 1616, 361, 143, 1348, 2182, 1795, 421, -2, 1011, 1368, 1097, 1297, 1297, 975, 1034, 1149, 505, -565, -152, 1560, 2017, 1470, 1820, 2707, 3180, 3337, 3237, 2639, 1600, 1397, 2152, 2213, 1912, 1761, 1179, 1034, 1746, 2194, 2162, 2354, 2547, 2993, 3998, 3831, 3425, 4403, 4894, 3900, 2873, 2488, 1948, 1384, 778, -320, -891, -493, -561, -772, 46, 681, 102, -220, 299, 23, -441, -395, -798, -783, 173, 1047, 1032, 968, 1475, 1483, 1049, 192, -976, -471, 971, 554, -746, -655, 132, 202, 141, 661, 914, 604, 1061, 1877, 1410, 190, -637, -1041, -1830, -2370, -1428, -497, -775, -1344, -1859, -2175, -2821, -3996, -4739, -4890, -4867, -4281, -2979, -2526, -2373, -1109, -413, -341, 85, -111, -711, -255, 222, -403, -828, -84, 976, 1052, 534, 618, 1325, 1371, 642, 291, 419, -193, -1295, -1758, -2592, -3837, -3715, -3102, -3802, -5168, -5814, -5483, -5028, -5227, -4720, -3492, -3461, -3981, -3680, -3189, -2959, -2773, -3011, -2701, -1421, -926, -1446, -1628, -868, -340, -1008, -1724, -1317, -267, -54, -399, -521, -425, 435, 1242, 315, -985, -349, 77, -779, -512, -9, -761, -1546, -1654, -1646, -2249, -2994, -3197, -3273, -3519, -3987, -4680, -4741, -3628, -3259, -3849, -3612, -3043, -2534, -1751, -2127, -3041, -2019, -348, -350, -977, -617, -16, 101, 493, 625, -171, -241, 623, 501, 334, 669, 495, 915, 1721, 1541, 1308, 1447, 1903, 2565, 2502, 1635, 1076, 835, 97, -899, -1460, -1335, -1220, -1212, -1022, -1005, -493, 229, 131, 101, 706, 1239, 1262, 1156, 1096, 686, 418, 779, 808, 60, -27, 784, 955, 1143, 1896, 1353, 51, -3, 273, -182, -296, 201, -364, -1158, -714, -539, -946, -729, 83, 864, 1413, 1403, 1611, 1890, 1176, 316, 62, 137, 192, -311, -698, -89, 327, 735, 1438, 1020, 256, 167, -36, -742, -1383, -1025, -346, -134, -18, -161, -516, -28, 644, 14, -394, 181, -33, -806, -1567, -3309, -4759, -4722, -4544, -4427, -3554, -2727, -2488, -2159, -1859, -1898, -2007, -1824, -1756, -2549, -2774, -1674, -1267, -1305, -853, -447, -417, -967, -1218, -842, -1466, -2066, -581, 532, 57, 33, 900, 1649, 1302, 293, 482, 977, 252, -189, -56, -526, -1584, -2244, -2315, -2689, -3422, -3823, -3459, -3277, -3686, -3776, -3597, -3357, -3490, -4143, -4603, -3926, -2437, -1673, -1684, -1173, -440, -659, -693, -103, -523, -1795, -2275, -1727, -1543, -1633, -1529, -1689, -1394, -742, -1117, -1794, -1515, -1271, -1447, -1474, -1259, -541, 213, -61, -1545, -2295, -1234, -583, -1381, -1308, -518, -1315, -2207, -1735, -1742, -2513, -2027, -991, -990, -1510, -1568, -883, -465, -723, -830, -732, -1029, -1150, -1335, -2019, -2090, -1653, -1217, -818, -914, -1763, -2390, -1049, 392, -39, -776, -718, -400, -48, 351, -221, -664, 622, 1504, 1014, 773, 1104, 1433, 1771, 1901, 975, -587, -815, -376, -994, -1788, -2018, -1622, -765, -890, -2327, -2730, -1996, -2192, -2992, -3168, -2414, -1289, -788, -1100, -1225, -646, -157, -533, -1348, -1066, -332, -751, -935, 5285, 5350, 4537, 3644, 3654, 3779, 3009, 1750, 1061, 774, -344, -1786, -2146, -1516, -657, -239, -600, -1040, -761, -878, -1144, -441, -701, -1439, 423, 2962, 3377, 3213, 4111, 5403, 5692, 4839, 3943, 3222, 2708, 3350, 4314, 4177, 3889, 3440, 2763, 4003, 5275, 3867, 2523, 2299, 1387, 426, 542, 263, -855, -1445, -1693, -1973, -2047, -1719, -1220, -1486, -1803, -1242, -1071, -1237, -912, -705, -232, 233, 413, 356, -190, 751, 2913, 3656, 3968, 4830, 4655, 4326, 5111, 5314, 4285, 3563, 3699, 3395, 2657, 2578, 2764, 3125, 3974, 4328, 3731, 3340, 3188, 2728, 2662, 2032, -336, -1803, -301, 786, -273, -1555, -2540, -2821, -2069, -1285, -788, -256, 9, 354, 426, -1243, -2602, -1458, 219, 824, 403, -195, -79, 331, 841, 1358, 1414, 1586, 2029, 1890, 1347, 824, 372, 412, 703, 781, 921, 1891, 3466, 4234, 3952, 3510, 2982, 2550, 2123, 1334, 739, 219, -427, -873, -1281, -468, 1473, 2060, 1389, 869, 180, -489, -413, -623, -1582, -2185, -2249, -1777, -776, -191, -250, 36, 1545, 3927, 5088, 4587, 3840, 3265, 3353, 4613, 5962, 5736, 4506, 4368, 4460, 3326, 2720, 2969, 2651, 3103, 5140, 6347, 6134, 5930, 6055, 6835, 8270, 9338, 9578, 9249, 8383, 7491, 6643, 5758, 6225, 7379, 6964, 5930, 5683, 6415, 8446, 10004, 10194, 9967, 9778, 10577, 11452, 9975, 7955, 7318, 6609, 5919, 4994, 2975, 2901, 4614, 3805, 1713, 945, 950, 875, 726, 283, -650, -1201, -1013, -1489, -3298, -3762, -1781, -942, -1958, -1990, -1359, -2105, -3398, -3650, -3351, -3150, -2861, -2709, -2493, -1750, -1224, -1101, -969, -1630, -2302, -995, 642, 746, 403, 24, -529, -953, -1103, -1033, -1302, -1735, -1667, -1177, -1004, -2023, -2648, -1620, -1657, -3222, -4205, -4354, -3783, -2726, -2319, -2416, -2076, -1719, -1817, -1627, -1299, -1477, -1975, -2844, -2323, -43, 177, -1417, -1620, -884, -619, -563, -348, -298, -600, -796, -651, -757, -1042, -1147, -1581, -2378, -2969, -3376, -2822, -1779, -2531, -4288, -4688, -4383, -4657, -5006, -5056, -5089, -4862, -4305, -3950, -4016, -4031, -3383, -3485, -5083, -5178, -3866, -4117, -4866, -4373, -3761, -4387, -4973, -4434, -4213, -4552, -4531, -4026, -3170, -2619, -2638, -2351, -2493, -4044, -5272, -4712, -4214, -5048, -5572, -5652, -5982, -5712, -5121, -4778, -4368, -4243, -4359, -4024, -2729, -1562, -2511, -3752, -1626, 933, 218, -1397, -1810, -2202, -2642, -2250, -1977, -2190, -2026, -1580, -1272, -1065, -1218, -2725, -4650, -3890, -2119, -2740, -3865, -3738, -3539, -3326, -2430, -1473, -718, 81, 429, -145, -1158, -1970, -2187, -2129, -2311, -2001, -1015, -772, 26, 2652, 3467, 1595, 497, 463, -183, -1283, -2348, -2521, -1773, -1783, -2125, -1610, -1207, -1105, -965, -1445, -2245, -2458, -1763, -1457, -2241, -2930, -2871, -1810, -196, -128, -816, 101, 907, 513, -399, -1832, -1629, 629, 1597, 493, -613, -1025, -568, 800, 1087, -61, -316, -182, -599, -153, -139, -1439, -987, 724, 710, -336, -1359, -2155, -2554, -2817, -2866, -3066, -3366, -3103, -2876, -3040, -3005, -2336, -1601, -2413, -3708, -2807, -1393, -1594, -2179, -2524, -3262, -4084, -4034, -3311, -3079, -3556, -3646, -2655, -1497, -1713, -3208, -3345, -1651, -1643, -3649, -4585, -4178, -3223, -2055, -1808, -2579, -3095, -2671, -2002, -2040, -2458, -2635, -2801, -2982, -2741, -1605, -700, -907, -797, -469, -884, -957, -129, 436, 201, -568, -1144, -1595, -2728, -3120, -1065, 822, 1058, 1295, 1080, 10, -817, -1128, -1386, -1665, -2379, -3139, -2950, -2163, -1683, -2190, -2119, -527, 741, 769, -392, -1468, -1420, -797, -53, 373, 168, -664, -1075, -260, 343, -943, -1779, 325, 1842, 941, 416, 997, 1470, 1445, 1153, 989, 467, -422, -524, 177, 168, -1871, -3951, -3235, -2278, -3218, -4323, -4870, -4907, -4616, -4180, -3647, -3087, -3263, -4265, -3501, -1411, -1321, -2060, -1512, -629, -689, -1339, -1286, -251, -172, -1858, -2501, -624, 763, 477, 241, 114, -381, -748, -974, -2147, -3551, -2493, -395, -413, -1048, -1504, -2644, -3441, -3179, -2611, -2431, -2295, -2653, -3578, -2976, -1756, -2421, -3633, -3956, -3975, -4071, -3993, -3701, -3638, -3300, -2030, -1566, -1955, -1813, -1516, -1309, -1620, -2314, -1543, -25, -224, -647, 108, 665, 76, -846, -1375, -1780, -2004, -2177, -2455, -2470, -2556, -1874, -278, -139, -1140, -1238, -656, -558, -854, -1353, -2410, -3334, -4030, -4005, -2760, -2622, -3637, -3796, -3096, -2686, -2705, -2034, -1361, -2265, -3044, -1686, -563, -1037, -1115, -633, -1045, -1737, -2087, -3636, -4821, -2907, -1024, -1059, -854, -713, -1396, -2225, -2524, -2708, -3444, -3185, -1660, -1556, -2582, -2828, -2669, -2598, -2714, -3047, -3139, -3557, -5018, -5890, -4431, -2734, -2991, -4114, -4377, -3713, -3489, -3792, -3523, -3084, -4000, -4307, -2158, -1257, -2711, -3223, -2721, -2956, -3124, -2345, -1479, -1192, -1979, -3368, -3533, -3161, -3976, -5075, -5868, -6019, -5402, -5004, -5011, -4998, -5249, -6259, -6003, -3988, -3072, -2929, -2018, -996, -899, -1359, -1410, -1287, -1230, -693, -515, -742, 419, 1951, 1861, 512, -586, -832, -1158, -1728, -2123, -2910, -3196, -1441, 146, 42, -480, -923, -1306, -1875, -2865, -3627, -3559, -3442, -4318, -4518, -2777, -1690, -1688, -1124, -649, -600, -595, -969, -1212, -1113, -2445, -4640, -4072, -1885, -1425, -1717, -1862, -2105, -1913, -1759, -1889, -1504, -1599, -3203, -3613, -2331, -2746, -4073, -4135, -3624, -3675, -4335, -4802, -4447, -3882, -4438, -5633, -4870, -2422, -1526, -1925, -1932, -1738, -1319, -748, -175, 127, -8, -905, -2675, -3159, -2067, -2216, -2976, -2574, -1874, -1769, -1583, -875, -304, -468, -1910, -3030, -2102, -1527, -2699, -3822, -4249, -4108, -3148, -2353, -2311, -1910, -1001, -820, -1407, -761, 735, 640, 303, 763, 566, -380, -576, 531, 1302, 715, -238, 348, 2116, 2336, 1169, 114, -749, -1245, -1432, -2375, -4422, -5357, -3671, -2040, -2315, -3110, -3024, -2625, -2642, -2606, -2345, -2083, -1885, -1919, -2813, -3269, -1702, -1020, -2403, -2547, -1487, -1710, -2173, -1318, 87, 828, -105, -630, 1368, 2521, 1376, 257, -496, -1022, -1143, -1370, -1606, -2411, -3776, -2909, -602, -1051, -3158, -3788, -3475, -3861, -4470, -4727, -5636, -6185, -4656, -3449, -4080, -4358, -3482, -2650, -2357, -2136, -1164, -458, -1834, -2545, -349, 1381, 1430, 1723, 2081, 2150, 2497, 2628, 1557, 548, 632, 382, 24, 714, 1289, 848, 643, 1148, 1026, 419, -592, -2889, -3960, -1957, -590, -1298, -1766, -1343, -624, -479, -1139, -1652, -1788, -1883, -428, 2223, 2730, 1610, 1501, 1872, 1967, 2335, 2929, 3594, 3598, 2751, 2468, 1913, 267, 38, 1127, 867, 52, 337, 1052, 1224, 420, -889, -1396, -1668, -2843, -2976, -1541, -1200, -1751, -1446, -909, -1331, -1776, -1229, -825, -1008, -1563, -2750, -2406, 102, 1160, 261, -108, 625, 1217, 1103, 811, 886, 1671, 2171, 1823, 2503, 3685, 3586, 3190, 2704, 1329, -465, -1357, -1150, -1098, -1319, -1867, -1836, 114, 555, -1415, -2442, -2249, -2222, -2369, -2123, -2412, -3268, -2195, -181, -350, -816, 731, 2663, 2877, 2075, 1866, 2633, 3497, 2850, 1927, 3253, 4604, 3786, 2455, 1701, 1426, 1289, 1331, 1627, 634, -1697, -1579, 156, -732, -2184, -1875, -1115, -213, 1044, 1885, 1666, 997, -163, -1831, -1810, -324, -477, -1193, -375, 580, 1003, 1528, 2422, 3386, 2753, 1041, 1714, 3731, 3620, 2186, 1086, 568, 709, 1227, 2039, 2428, 1933, 1963, 1629, -91, -451, 433, -6, -716, -932, -1587, -2607, -2997, -1835, 236, 640, -528, 686, 2991, 2524, 811, -155, -226, 548, 736, -702, -827, 1070, 1597, 1235, 1829, 2403, 2697, 3368, 4087, 4477, 4676, 4708, 3777, 2202, 2632, 4198, 3018, 466, -340, 22, 166, -357, -744, -622, -1541, -2625, -1642, -485, -942, -1299, -695, -352, -194, 470, 320, -382, -239, -485, -1091, -161, 959, 530, 189, 455, 166, -480, -1049, -1656, -2398, -1876, 413, 1482, 1271, 2171, 3009, 2850, 2748, 2534, 2363, 2947, 3127, 2077, 551, -339, 780, 2518, 2284, 1102, 567, 657, 1310, 1900, 1444, 750, 1114, 1392, -48, -1478, -122, 2237, 2524, 2180, 3024, 3889, 3657, 3165, 2777, 2015, 1085, 773, 1366, 1474, 1070, 2091, 2732, 1629, 955, 704, 214, 489, 2172, 3590, 3254, 2390, 2939, 4493, 4763, 3476, 2466, 2801, 3796, 3980, 3008, 2481, 2820, 1819, -23, 639, 2598, 2600, 1130, -279, -1004, -1511, -2111, -1847, -1214, -1529, -1398, -340, -176, -371, -373, -490, -62, 597, 1471, 2656, 3260, 3163, 2462, 1029, 691, 1723, 1848, 1864, 2652, 3044, 3485, 3752, 2756, 1905, 2306, 1963, -71, -1209, 584, 2591, 2251, 1269, 1275, 1448, 804, -38, -1109, -2564, -2088, 332, 919, -317, -239, 749, 933, 1150, 1447, 1311, 1148, 1040, 1253, 1194, 84, -69, 1486, 2200, 1710, 1245, 848, 586, 788, 928, 596, -509, -2353, -2619, -405, 434, -748, -662, 296, 417, 273, 400, 537, 943, 1486, 908, -870, -1159, 458, 985, 282, 5, 376, 880, 1157, 1604, 1570, 378, 324, 2687, 3890, 2579, 1760, 1850, 1898, 1779, 1460, 1339, 1635, 2337, 2765, 1570, 488, 2021, 3117, 1493, 10, -10, 185, 97, 8, 484, 1285, 1975, 2344, 1688, 1057, 2870, 4544, 3612, 2908, 2731, 1461, 811, 1532, 2132, 2553, 3027, 2804, 2085, 2709, 3450, 2470, 1669, 2147, 2877, 2998, 2754, 2465, 1638, 873, 1151, 673, -369, 804, 2004, 1227, 498, 413, 768, 1627, 2173, 2277, 2252, 1604, 232, -1418, -3294, -3677, -1873, -549, -244, -127, 183, 1096, 2101, 2759, 3295, 3683, 3564, 2468, 1977, 3267, 3755, 3065, 2878, 2395, 1788, 1853, 2154, 2578, 2731, 3117, 3992, 3552, 2156, 2404, 2666, 1114, 473, 1198, 1411, 1269, 1183, 434, -739, -558, 641, 707, 344, 852, 1523, 2033, 1775, 1031, 1640, 2312, 1359, 1036, 1599, 729, 595, 3079, 4468, 3663, 3170, 3385, 3238, 2783, 2610, 2697, 3412, 4632, 4742, 3361, 2754, 3840, 4375, 3864, 3417, 2967, 2770, 2752, 2135, 1661, 1949, 1042, 78, 2208, 3920, 2582, 1722, 2316, 2508, 2137, 2246, 2749, 3116, 2934, 1622, 993, 2929, 4260, 3427, 2444, 1194, 227, 354, 25, -897, -1268, -1463, -1775, -2136, -2680, -2046, 130, 1238, 942, 814, 842, 453, 209, 692, 789, -20, -1319, -2487, -1852, -743, -1490, -2591, -3001, -2742, -1770, -1365, -1279, -203, 51, -1301, -1181, 818, 1897, 1868, 1325, 732, 850, 1371, 1672, 1876, 2406, 2210, 2041, 3582, 4197, 3080, 2494, 2075, 1771, 2003, 1481, -25, -1192, -1287, -652, -1092, -2385, -657, 2511, 2622, 1988, 2824, 3277, 2837, 2691, 2683, 1874, 827, 925, 1925, 1971, 232, -165, 2355, 3398, 2267, 1665, 1182, 1113, 1797, 2107, 1783, 499, -558, 1013, 2641, 1571, 6, -485, -363, -345, -944, -1776, -1755, -1052, -1120, -2655, -3820, -2592, -979, -1202, -2045, -2325, -1890, -1150, -830, -704, -320, 411, 467, -154, 1147, 2902, 2547, 2421, 2925, 2254, 1505, 1234, 961, 1299, 1643, 812, 910, 3152, 3634, 1680, 409, -245, -841, -454, -31, -623, -289, 809, 100, -251, 1377, 1744, 702, 761, 1474, 1554, 1160, 928, 1520, 1818, 287, -394, 1692, 2839, 2084, 1858, 2306, 2421, 1721, 1475, 2212, 2148, 1290, 1629, 2251, 1621, 1980, 3925, 4094, 2774, 2588, 3059, 2996, 2863, 3143, 2719, 1253, 1346, 3441, 3932, 2254, 554, -311, -877, -1419, -1291, -740, -355, -126, -61, 460, 1178, 1417, 2276, 3095, 2870, 2844, 2771, 2501, 2897, 3204, 3186, 3247, 2684, 2149, 2410, 1490, -317, 240, 1612, 943, -14, -269, -404, -43, 529, 573, 360, 287, 71, -984, -3320, -4643, -3294, -2338, -3108, -3815, -3439, -2561, -2175, -1981, -1575, -1568, -1870, -1818, -1669, -1130, 931, 3002, 3242, 2940, 2881, 2644, 2569, 2772, 2678, 2553, 2736, 1921, 137, 392, 2345, 2628, 1754, 1813, 2136, 1819, 1656, 1708, 405, -918, 226, 1443, 616, -159, -120, -113, -470, -1078, -1519, -1016, 97, -475, -2223, -1156, 1494, 2049, 1784, 1888, 1519, 1213, 1577, 1913, 1663, 851, -77, 96, 1139, 753, -245, 563, 1585, 1555, 1505, 1635, 1558, 1208, 977, 812, 29, -531, -480, -1452, -2053, -178, 1288, 704, 947, 2469, 2574, 1945, 2278, 2380, 1925, 1442, 310, -1094, -345, 1840, 2366, 1636, 1174, 1539, 2516, 2862, 2297, 1216, 108, 734, 2460, 2637, 2199, 2431, 2896, 3311, 3121, 2302, 2146, 2396, 1676, 371, -549, -1895, -3236, -2230, -882, -1647, -2718, -2649, -2277, -2843, -3556, -3575, -3576, -3727, -4734, -6753, -6577, -3959, -3074, -3672, -3674, -3426, -3257, -2787, -2242, -2320, -2557, -2511, -2467, -2354, -1748, -1115, -984, -571, -258, -775, -1355, -1526, -1814, -1956, -1814, -1889, -1792, -1461, -2286, -4489, -4995, -3299, -2671, -3194, -3210, -3202, -3641, -3385, -2201, -1562, -1947, -2282, -2066, -1603, -1650, -3085, -4106, -2513, -1204, -2450, -3261, -2619, -2286, -1986, -1190, -707, -594, -655, -163, 933, 491, -840, 323, 2363, 2256, 1510, 1116, 1005, 1303, 1366, 1272, 1838, 2420, 2179, 2028, 1813, 203, -1379, -607, 745, 274, -877, -1593, -1694, -412, 839, 448, 215, 967, 1396, 1196, 434, -1173, -2404, -807, 1395, 467, -1274, -500, 1297, 1505, 875, 864, 914, 731, 284, -258, -435, -1120, -2163, -1699, -219, -591, -2800, -4036, -3870, -4207, -4825, -4656, -4852, -5382, -4799, -3486, -2907, -3821, -4038, -2069, -615, -762, -817, -233, -8, -509, -995, -1221, -729, 320, 69, -1196, -320, 1620, 1152, -240, -600, -718, -355, 523, 412, -450, -1064, -1233, -978, -1128, -2488, -4195, -4099, -1969, -1439, -3001, -3368, -2633, -2238, -2009, -2304, -3034, -3188, -2776, -2430, -3068, -4576, -4597, -2549, -1706, -2491, -2352, -1778, -1688, -1129, -877, -1470, -1647, -1405, -1163, -1450, -3297, -4287, -2117, -439, -1209, -2113, -2215, -2120, -2319, -2727, -3016, -3364, -4547, -5241, -3845, -3059, -3888, -4066, -3342, -2866, -3403, -4186, -4454, -4378, -4371, -4376, -4318, -5129, -6695, -6066, -3186, -2113, -3216, -3572, -2831, -2584, -2867, -2157, -560, -285, -1348, -928, 1162, 2349, 2532, 2071, 1187, 1106, 1359, 1169, 636, 252, 556, 601, -339, -412, 991, 1305, 651, 563, -127, -1364, -1446, -1357, -1673, -1135, -265, -26, -317, 180, 1811, 1807, 281, -34, 302, -454, -1026, 429, 2121, 1324, -293, 1169, 3213, 2785, 1965, 1252, 452, 334, 237, -241, -257, -50, 178, 636, 579, -924, -2522, -2444, -2745, -4441, -5518, -5569, -5682, -5603, -4094, -2278, -2051, -2418, -2034, -1807, -2648, -2551, -899, -256, -436, 92, 583, 106, -148, 696, 1567, 1767, 1006, -604, -233, 2260, 2398, 207, -535, 116, -43, -490, -550, -1333, -2209, -1863, -2047, -3848, -4424, -2962, -2168, -2630, -3560, -4073, -3962, -3596, -3245, -3385, -3921, -4650, -5637, -4801, -1983, -1079, -1997, -2014, -1761, -2205, -2713, -3254, -3225, -1917, -983, -1574, -3376, -5354, -4369, -1175, -700, -2347, -2695, -2081, -2128, -2423, -2213, -1766, -1778, -2465, -3300, -2842, -1639, -1744, -2607, -2986, -2524, -1489, -1067, -1388, -1808, -2200, -2512, -2354, -2782, -4763, -4978, -2487, -1431, -1892, -1474, -1178, -1349, -1107, -517, -108, 276, 1194, 1745, 816, 407, 1569, 1889, 1384, 1622, 2160, 2070, 1631, 1560, 1868, 1723, 1203, 775, -34, -247, 1180, 1199, -602, -1127, -396, 100, 22, 188, 1508, 2699, 1924, 1281, 2603, 3300, 2390, 1764, 1788, 1726, 1657, 1769, 2003, 2702, 3570, 3714, 3114, 2373, 2043, 1530, -391, -1196, 972, 2480, 1909, 1130, 1080, 1601, 1244, -395, -1827, -2633, -3147, -3626, -4318, -3512, -1122, 270, 525, 829, 1400, 1447, 1013, 990, 1348, 1616, 1535, 1764, 2217, 1705, 1295, 2795, 4243, 4058, 3820, 3751, 2990, 2351, 2150, 1760, 1465, 513, -891, -187, 1056, 89, -1399, -1909, -1808, -2041, -2848, -2874, -2342, -2140, -1798, -2018, -3241, -3282, -1210, -75, -679, -1058, -1337, -1707, -1136, -468, -737, -915, -305, 687, 759, -519, -592, 1291, 1627, 33, -808, -868, -1072, -1103, -892, -915, -1829, -3587, -3958, -2129, -1458, -2396, -2917, -3151, -3215, -3345, -3851, -3869, -3616, -4654, -4935, -2823, -1959, -2643, -2121, -1004, -688, -679, -292, -225, -968, -1627, -1341, -1192, -2433, -2691, -628, 165, -1091, -1633, -1274, -1423, -2106, -2181, -1160, -294, -810, -1329, -375, 203, -348, 828, 2532, 1966, 924, 952, 1407, 1337, 1177, 1813, 2545, 2319, 1636, 1501, 1681, 1190, -712, -2380, -1236, 476, 211, -167, 275, 801, 2336, 4610, 5400, 4543, 3888, 3747, 3428, 2811, 2049, 1008, 330, 1584, 2876, 2312, 2096, 2771, 2980, 2773, 2747, 3030, 2707, 1770, 1454, 1515, 238, -1710, -757, 1665, 1306, -437, -1028, -810, -797, -1391, -2121, -2403, -1984, -977, -314, 223, 1296, 1366, 1182, 2795, 3564, 2452, 1931, 2360, 2748, 2352, 1607, 1774, 2610, 3216, 3453, 2914, 1282, -58, 685, 1491, 288, -984, -1452, -1318, -580, -529, -805, -401, -265, -286, -755, -2074, -1590, 191, 229, -599, -483, 327, 687, 180, -329, 493, 1196, -13, -372, 1773, 2738, 1558, 647, 280, 117, 218, 347, 710, 772, 68, -315, -549, -1741, -3710, -3743, -1614, -995, -1892, -2411, -2729, -2681, -2192, -1981, -2336, -2891, -3519, -3857, -2856, -1506, -1400, -2259, -2456, -731, 221, -1274, -1970, -538, 499, -1354, -2569, 113, 1604, 623, 526, -1, -1749, -2291, -2061, -2662, -2722, -1836, -1487, -799, 836, 1406, 397, -345, 807, 2675, 2804, 1742, 1374, 1960, 2901, 3019, 2304, 1918, 2131, 2971, 2849, 904, 427, 2726, 4343, 3964, 3145, 2689, 2183, 1977, 2544, 2336, 1295, 1092, 1560, 2177, 2628, 2780, 3075, 3440, 3430, 2716, 2213, 2322, 2138, 1671, 1919, 2557, 2285, 1695, 2189, 3120, 2734, 1201, 819, 2762, 4835, 4038, 1573, 817, 1525, 1569, 650, 75, -461, -1399, -1514, -1160, -1930, -2719, -1433, 1381, 2713, 2449, 2865, 3939, 4966, 4882, 3298, 1969, 1986, 2919, 3780, 3867, 3499, 2808, 1708, 1931, 4250, 5717, 4080, 1633, 1324, 2125, 1834, 1257, 1545, 1310, -336, -1721, -1403, -1836, -3779, -3348, -1543, -1722, -2376, -1882, -1580, -2828, -3622, -2049, -531, -866, -1912, -1187, 889, 228, -1805, -51, 2361, 1451, 1790, 4117, 4205, 3308, 4030, 4643, 4126, 4393, 4354, 2890, 2038, 2851, 3576, 2875, 2354, 1988, 583, -1113, -1616, -1427, -1378, -1239, -1195, -1117, -1214, -2177, -2091, -1069, -2160, -3207, -2281, -1876, -2428, -2840, -2392, -1764, -1055, 365, 477, -146, 1797, 4090, 3742, 2722, 1340, 1, 77, -560, -2130, -3026, -3336, -2745, -2284, -4099, -5295, -2659, -17, 55, -273, -464, -949, -748, 455, -226, -2177, -1416, 51, -1128, -2782, -943, 2245, 1696, -531, -674, -261, -554, -396, 49, 232, 113, -731, -434, 681, -1022, -3009, -852, 1431, 783, 190, -717, -2258, -1877, -548, -105, -74, -349, 109, 2205, 3796, 1975, 816, 4183, 6144, 4848, 4216, 4180, 4231, 4942, 5005, 4155, 3953, 4359, 4053, 2951, 1671, 156, -971, -731, 752, 1179, 436, 1140, 2051, 1982, 2752, 3829, 4349, 5467, 5696, 4724, 5402, 6217, 5309, 5172, 5899, 4166, 2464, 4631, 5900, 4043, 3493, 3727, 2120, 1374, 3216, 4093, 2995, 2892, 3095, 1304, 125, 145, -1254, -1495, 1729, 3549, 1963, 1546, 3635, 4925, 3700, 2801, 3765, 3787, 3107, 3355, 3895, 5227, 5399, 3323, 4037, 6870, 6376, 4374, 3276, 1792, 133, 32, 1565, 2359, 1618, 234, -14, 1257, 1826, 943, -1201, -2599, -1707, -1711, -3129, -3415, -3320, -3634, -3341, -2117, -875, -323, -704, -702, 704, 1861, 1910, 1117, 323, 1410, 3752, 4270, 2246, 793, 1850, 3015, 2957, 3114, 3776, 3606, 2669, 2837, 3765, 2630, -814, -1773, -242, 142, -30, 181, 1118, 2146, 1206, -92, 733, 1637, 458, -1877, -2791, -1920, -1345, -1290, -1730, -3646, -4220, -1597, -551, -2426, -2692, -942, -184, -228, 926, 1537, 457, 324, 2017, 2797, 1865, 1220, -107, -1848, -1143, -1, -1584, -3224, -2481, -2442, -3339, -2196, -1067, -1719, -2013, -1711, -2161, -2176, -1474, -2541, -4525, -2788, 641, 566, -130, 332, -215, -335, 409, -220, -1064, -297, -61, -1088, -982, -1004, -2304, -1429, 352, 259, -566, -1667, -2463, -2758, -3039, -3058, -2749, -2883, -3438, -3197, -2250, -2465, -3449, -3881, -4870, -4985, -2544, -1394, -868, 1398, 2542, 2785, 3630, 4085, 4179, 4912, 5474, 4602, 3191, 2059, 2140, 2902, 1946, 1340, 2986, 3977, 3302, 1430, -225, 191, 428, -892, -935, 324, 731, 791, 134, -780, 85, 284, -1999, -1900, 1812, 3684, 3013, 2779, 2830, 2920, 3798, 4615, 4060, 2825, 2893, 3766, 677, 146, -1534, -2163, -1144, -1090, -2032, -2136, -1300, -701, -1016, -927, 89, 891, 1308, 1226, 249, -1041, -1942, -2363, -2091, -1683, -1694, -958, 680, 1301, 838, 549, 1220, 2952, 4260, 4000, 3196, 2242, 1061, 1146, 1842, 1136, 0, -66, 175, -312, -1059, -1459, -1337, -509, -63, -1055, -1891, -1648, -1651, -1671, -1609, -2050, -2126, -1520, -1338, -2131, -2631, -2226, -2162, -2072, -1680, -1884, -1827, -1439, -1086, -357, -317, -932, -646, 347, 1304, 1982, 1488, 594, 716, 222, -1763, -2944, -2259, -1605, -1833, -2107, -2311, -2055, -1283, -622, -37, 866, 1816, 2487, 2825, 2333, 1478, 1092, 645, 693, 1321, 915, -286, -645, -319, -863, -2347, -3107, -2821, -3090, -3946, -4086, -3869, -4491, -4540, -3446, -3011, -2845, -1957, -1028, -530, -672, -1197, -1467, -1336, -1257, -2015, -3276, -3802, -3269, -2991, -3757, -4114, -2962, -1315, -101, 407, 148, 117, 759, 1244, 1323, 893, -145, -795, -445, -300, -1249, -1911, -1326, -565, -316, -368, -282, -8, -639, -2136, -3331, -4065, -3961, -2989, -2105, -1300, -264, 73, 269, 1034, 728, -756, -1539, -1218, -839, -1203, -2481, -3183, -2329, -1900, -2571, -2397, -1101, 353, 1156, 952, 999, 1632, 1876, 1792, 1800, 1495, 1216, 1847, 2632, 1876, 648, 616, 813, 1027, 1196, 481, -623, -572, 432, 731, 534, 937, 1950, 2953, 3593, 3661, 2750, 1829, 1773, 1740, 1094, 152, -436, -535, -928, -1906, -3001, -3691, -3491, -3328, -4270, -5816, -6350, -5166, -4116, -4470, -4917, -4403, -3447, -3003, -3415, -3860, -3796, -3640, -3404, -3102, -3198, -3059, -2121, -1468, -1444, -1276, -1053, -902, -523, -216, -540, -1354, -1323, -444, -267, -993, -1600, -2017, -2067, -1505, -1861, -2796, -2116, -793, -532, -740, -819, -918, -965, -1223, -1892, -2241, -1922, -1191, -688, -745, -832, -431, 388, 1350, 1503, 644, 448, 1496, 2217, 1389, 114, -429, -614, -894, -1190, -1475, -1979, -2508, -2667, -2772, -3218, -3648, -3596, -3438, -3708, -4022, -3355, -2220, -1662, -1280, -1454, -2409, -2564, -1333, -89, 150, 3, 211, 655, 1365, 1774, 732, -334, 377, 1118, 743, -105, -1200, -1180, -193, -256, -1219, -2000, -2047, -1785, -2094, -2557, -2590, -2088, -1341, -1084, -1307, -1698, -2164, -2349, -2881, -4066, -4571, -4098, -3604, -3524, -3519, -3374, -3088, -2135, -1236, -1392, -1449, -364, 876, 1018, 510, 234, 289, 523, 377, -154, -109, -251, -637, -140, -167, -1206, -1356, 44, 1679, 2051, 1503, 1157, 1257, 1033, 1, -952, -1138, -797, -435, -155, -154, -661, -634, 558, 1853, 2047, 1307, 1076, 1853, 2254, 1689, 1131, 1357, 2155, 2547, 2227, 1884, 1491, 1075, 1102, 662, -798, -1716, -964, 90, -189, -749, -227, 514, 1119, 1450, 599, -324, -40, 605, 417, -717, -1451, -1128, -474, 446, 1502, 1641, 830, 1157, 2596, 2248, 558, 458, 1461, 1775, 1413, 806, 739, 1743, 2379, 1293, 274, 839, 1113, 453, 425, 1079, 1820, 2041, 1550, 1127, 627, 74, 160, -19, -1251, -2145, -2087, -1773, -1358, -1313, -2037, -2292, -985, 535, 1132, 973, -140, -1087, -732, -390, -649, -788, -717, -522, -325, -475, -745, -96, 1135, 1102, 323, 281, 76, -662, -717, -548, -654, -451, 203, 672, 293, -710, -1138, -285, 516, -53, -1130, -1832, -1835, -471, 731, 123, -381, 518, 1153, 923, 994, 1522, 2141, 3024, 3221, 1766, 75, -556, 116, 1523, 1484, 217, 263, 1523, 2268, 2302, 2364, 2791, 3621, 4203, 3711, 3079, 3396, 3993, 4221, 3878, 3022, 2282, 2269, 2457, 2151, 1307, 332, 601, 2280, 3143, 2443, 1717, 1965, 2423, 2331, 2011, 1725, 1810, 2681, 3332, 3096, 2835, 2631, 2687, 3222, 3129, 2066, 1530, 2315, 3067, 2721, 2325, 2269, 1553, 508, -179, -849, -1269, -1292, -1161, -671, -338, -373, -152, 275, 425, -93, -559, 121, 1550, 2413, 2431, 2403, 2419, 1695, 445, 290, 1032, 1393, 1607, 1828, 2156, 2791, 3342, 3647, 3510, 2766, 2130, 1688, 1171, 1172, 1080, -6, -695, -28, 691, 1084, 1616, 2280, 2747, 2990, 2624, 1821, 1984, 2425, 2062, 1812, 1789, 1473, 1587, 2108, 2251, 2029, 2093, 2842, 3516, 3506, 3055, 2757, 2760, 2739, 2971, 3455, 3821, 4258, 4468, 4037, 3345, 2665, 2140, 2160, 2309, 2106, 2251, 3194, 3780, 3550, 3437, 2961, 2474, 3208, 3898, 3477, 2321, 1260, 1401, 2118, 1725, 248, -724, -190, 1039, 1720, 1660, 1487, 1511, 1566, 1675, 1499, 766, 524, 1132, 1477, 1217, 1134, 1540, 1962, 2120, 2248, 2196, 1986, 2203, 2556, 2263, 1296, 349, 249, 961, 1533, 1495, 1597, 1906, 2069, 2837, 3338, 3032, 2978, 2568, 1655, 982, 971, 1540, 1772, 1814, 1447, 206, -286, 649, 1306, 550, -549, 116, 1952, 2388, 1245, 420, 727, 1683, 2473, 1943, 732, 781, 1655, 1550, 669, 177, -60, -338, -526, -589, -405, -258, -168, 332, 596, 131, 235, 1215, 1694, 1336, 1477, 2692, 4142, 5195, 5073, 4120, 3747, 4075, 4177, 3849, 3952, 4582, 4810, 4764, 4513, 3497, 2776, 3090, 3374, 3015, 2630, 2519, 2612, 2841, 2902, 2609, 2240, 2089, 1849, 1232, 712, 646, 711, 968, 1606, 1816, 628, -533, -117, 870, 1117, 658, 552, 988, 1281, 845, 15, -138, 219, 706, 846, 122, -545, -434, 312, 1024, 1273, 1253, 1390, 1727, 1520, 378, -352, 36, -181, -1135, -1631, -1790, -1767, -1241, -695, -826, -956, -595, 155, 795, 776, 649, 761, 1216, 1892, 2297, 1993, 1331, 1604, 2250, 1304, -266, -657, -135, 500, 474, -659, -1900, -1551, -163, 188, -85, 295, 757, 969, 1165, 1299, 1093, 935, 1705, 2300, 1831, 1468, 1798, 2772, 3609, 3606, 3733, 4413, 5461, 6052, 5032, 3154, 2469, 2861, 2521, 1482, 550, -733, -1638, -1524, -1801, -2542, -2560, -1975, -1604, -1577, -1663, -1951, -2083, -1677, -1794, -2321, -1800, -467, 341, 333, 232, 533, 685, 337, -2, -16, 160, 471, 545, 560, 951, 1235, 1322, 1645, 2331, 3125, 3185, 2780, 2851, 2698, 1733, 674, 260, 119, -484, -1538, -2188, -2171, -1755, -1283, -1862, -3027, -3050, -1849, -908, -1168, -1592, -1397, -950, -583, -863, -1485, -1775, -1140, 341, 911, 503, 879, 2055, 2609, 2131, 1404, 884, 948, 1596, 1398, 189, -337, -216, 18, 894, 1565, 856, 451, 1251, 1317, 292, -391, -186, 235, 366, 495, 422, 167, 446, 854, 949, 463, -463, -523, 509, 737, -822, -2211, -1437, 431, 1146, 497, 219, 740, 1598, 2491, 2687, 2793, 3311, 3688, 3227, 2056, 1278, 973, 777, 250, -1334, -2760, -2605, -1425, -1007, -1688, -2197, -2091, -1779, -2001, -2623, -2914, -2635, -1521, -338, -186, -254, -135, 105, 1049, 1658, 1212, 828, 679, 593, 149, -748, -1178, -1085, -1092, -1126, -1036, -803, -252, 716, 2052, 2742, 2303, 2085, 2423, 2134, 652, -1276, -2405, -2481, -2786, -3988, -4366, -3194, -1846, -1156, -1418, -2455, -3267, -3218, -2958, -3513, -4101, -3756, -2702, -1505, -994, -850, 63, 1898, 3358, 3849, 3958, 3691, 2993, 2408, 2077, 1484, 577, 317, 882, 777, -19, -274, -94, 65, 306, 231, -55, 141, 449, 722, 869, 464, 502, 1654, 2506, 2011, 887, 547, 1363, 2339, 2294, 1287, 790, 1352, 2104, 2037, 1910, 2377, 2836, 3457, 3707, 3214, 2306, 894, -342, -1078, -1734, -2267, -2438, -2576, -2774, -2878, -2953, -2727, -2317, -1826, -1866, -2633, -2770, -2316, -2311, -2844, -3336, -2977, -1669, -172, 683, 501, 461, 1692, 2723, 2223, 1028, 604, 947, 1125, 971, 423, -187, 82, 664, 349, -418, -471, -118, 533, 1473, 1213, 458, 859, 1293, 778, -137, -779, -749, -156, 82, -373, -789, -1199, -1557, -1557, -1987, -3334, -3570, -2249, -1708, -1817, -1656, -1678, -1662, -1450, -1328, -1400, -1102, -21, 608, 438, 385, 449, 610, 748, 638, 66, -812, -1079, -855, -1367, -2848, -3463, -1991, -926, -1357, -1522, -1415, -1070, -198, -246, -1646, -2337, -1542, -964, -1416, -2064, -2524, -2459, -1751, -793, -130, -383, -694, -259, -304, -1093, -1650, -2086, -2232, -1697, -1299, -1582, -1645, -1179, -1069, -1439, -2354, -3461, -3393, -2091, -944, -643, -1232, -1915, -1841, -1967, -2930, -3920, -3909, -3031, -2500, -2315, -1572, -752, -443, -219, -353, -738, -474, -99, -942, -2096, -2038, -2008, -2340, -1252, -8, -288, -553, -26, 442, 432, -291, -1325, -1612, -1525, -2025, -3165, -4436, -4543, -3517, -3332, -4243, -4585, -3598, -1984, -497, 385, 333, -296, -578, -753, -1974, -3575, -3253, -1437, -859, -1081, -587, -220, 325, 1153, 729, 105, 538, 556, 12, -321, -800, -1169, -858, -477, -630, -572, 195, 933, 1023, 742, 100, -340, -239, -432, -1347, -2616, -3331, -2949, -2542, -3096, -3276, -2164, -1431, -1503, -745, 443, 623, 135, 31, 153, -405, -1365, -2313, -2575, -2047, -2161, -2959, -3115, -2236, -1496, -1702, -1962, -1997, -1910, -1221, -1031, -1773, -1978, -1499, -1458, -1854, -2369, -2530, -1997, -1468, -1171, -1043, -1551, -1313, 823, 2449, 2171, 1423, 1173, 1111, 682, 45, -112, -83, -34, 503, 787, 791, 1173, 1208, 846, 289, -383, -145, 1197, 2394, 2239, 1387, 1254, 2267, 3378, 3320, 2074, 1344, 1777, 2135, 2254, 1797, 760, 654, 1270, 1564, 1596, 2026, 3110, 3462, 2009, 276, -428, -819, -913, -877, -1438, -1608, -660, 59, -128, -269, -223, -162, -57, -415, -959, -1267, -1795, -2274, -1797, -1216, -1298, -1292, -854, -744, -1294, -1503, -1322, -1155, -172, 697, -50, -485, 684, 1452, 851, 196, -39, -369, -378, 111, -298, -813, 496, 1897, 1432, 89, -897, -1077, -653, -745, -1432, -1887, -1789, -1422, -1829, -2700, -2867, -2463, -1969, -1633, -1638, -1880, -2117, -1744, -1199, -1799, -2306, -1632, -700, 69, 665, 500, 254, 1013, 1208, -189, -1381, -1726, -1760, -1093, -204, 245, 285, 309, 822, 901, -218, -1337, -1266, -349, 378, 326, -295, -1027, -1220, -1027, -1465, -2007, -1921, -1551, -981, -484, -610, -876, -750, -555, -441, -670, -1314, -761, 738, 871, 183, 555, 1271, 1091, 415, 54, -134, -689, -1105, -1197, -1710, -2763, -3030, -2272, -1978, -2858, -4038, -4240, -3984, -4167, -3968, -3873, -4491, -4246, -3512, -3911, -4517, -4047, -3007, -2462, -2549, -2671, -2709, -2606, -3011, -4528, -5741, -6323, -6796, -6290, -5220, -5250, -5277, -3849, -2585, -2283, -1854, -1355, -93, 1748, 1492, -258, -1126, -720, 269, 122, -926, -951, -430, -1021, -2400, -3112, -2940, -2891, -2978, -2522, -2412, -2905, -2593, -1760, -1533, -1568, -1672, -1530, -839, -437, -411, -274, -411, -684, -503, -259, -1011, -2083, -2122, -1820, -2046, -2520, -2596, -2581, -2616, -2405, -3058, -4522, -4610, -3549, -3158, -3324, -3382, -2960, -2430, -2383, -2720, -3312, -3506, -3107, -3400, -4610, -5252, -4767, -4008, -4064, -4772, -5242, -5659, -5404, -4660, -4911, -5296, -4566, -3574, -3258, -2967, -2623, -2762, -2740, -2294, -2498, -3704, -4084, -2688, -1575, -1956, -2491, -2366, -1491, -195, 441, -304, -1627, -1858, -1336, -1718, -2806, -3366, -2970, -1629, -370, 37, 530, 1162, 1474, 1101, 147, -125, 101, 169, -141, -952, -1472, -1063, -142, 577, 302, -832, -736, 802, 1490, 1228, 933, 1067, 1558, 1636, 1111, 680, 587, 973, 1690, 1556, 280, -1011, -1379, -917, -696, -1056, -1275, -1032, -579, -19, 269, -310, -787, -466, -212, -781, -1703, -2560, -3617, -4327, -4143, -3359, -2486, -1843, -1327, -480, 763, 1457, 1176, 905, 858, 491, 210, 376, 384, -172, -947, -1186, -1020, -1425, -2232, -2539, -2888, -3613, -3667, -3337, -3329, -2867, -1611, -357, 613, 1540, 1740, 885, 52, -296, -1215, -2659, -3138, -2986, -3669, -4190, -3784, -3505, -2965, -1860, -1658, -2393, -2345, -1022, 261, 505, 792, 1839, 2973, 3913, 3766, 2450, 1719, 1990, 2273, 1822, 438, -744, -410, 593, 1179, 1418, 1737, 1958, 2288, 2906, 2342, 927, 637, 772, 287, -307, -537, -448, -233, -262, -826, -1641, -1549, -827, -1256, -2019, -1654, -587, 888, 1941, 1772, 1560, 1964, 2030, 1633, 1337, 1006, 322, -212, 261, 1071, 622, -639, -787, 110, 812, 1120, 984, 592, 991, 2029, 1810, 682, 661, 1266, 1117, 250, -123, 343, 1168, 2335, 2592, 1797, 1513, 1713, 1544, 480, -265, 107, 701, 1480, 1912, 1160, 689, 1668, 2598, 1912, 519, 774, 2186, 2187, 972, 441, 712, 1441, 2409, 2900, 2429, 1835, 2259, 2709, 2365, 1504, 156, -455, 291, 615, -187, -507, 33, 742, 1222, 1225, 1048, 1095, 1590, 1989, 1795, 1500, 1267, 1013, 948, 1136, 985, 446, 245, 40, -406, -576, -778, -1064, -57, 1860, 2147, 986, 909, 1992, 2214, 1682, 1715, 2077, 2248, 2091, 1287, 611, 1007, 1537, 1419, 958, 648, 981, 1641, 1904, 1711, 1651, 2125, 2652, 2732, 2404, 1761, 1417, 1784, 2076, 1475, 894, 1370, 1423, 541, 392, 904, 874, 1065, 2266, 2875, 2379, 2632, 3957, 4818, 4137, 2910, 2758, 3145, 3274, 3412, 3203, 2443, 2426, 3427, 4048, 3571, 3219, 3865, 4732, 5566, 5983, 5553, 5120, 4783, 4117, 3151, 1936, 1164, 1527, 2240, 2137, 1775, 2618, 4005, 4377, 3680, 2282, 1315, 1598, 1862, 1087, -108, -539, 829, 2302, 2149, 1452, 1195, 1246, 1236, 801, 240, -61, -116, 579, 977, 242, -176, -174, -151, -415, -1191, -1607, -1546, -1807, -2165, -2241, -1964, -1039, 110, 955, 1298, 1536, 2070, 2676, 2931, 2610, 2004, 1562, 1634, 2459, 3479, 3851, 3750, 3274, 2592, 2100, 1292, 628, 829, 1301, 1186, 532, 578, 1274, 1432, 1108, 781, 445, 577, 1116, 1335, 1362, 1223, 1076, 1604, 2521, 2514, 1444, 849, 1014, 1052, 589, 3, 76, 634, 913, 864, 924, 1390, 1958, 2505, 2824, 1957, 850, 721, 1090, 959, 140, -223, 401, 918, 916, 535, 23, 44, -78, -605, -647, -897, -1538, -1352, -1072, -1646, -2224, -1995, -1107, -554, -910, -1151, -817, -782, -998, -1374, -1867, -1991, -1883, -1707, -1692, -2109, -2274, -1495, -545, -520, -1056, -863, 308, 1490, 2327, 2581, 2202, 2455, 3589, 4032, 3360, 2973, 3612, 3886, 2834, 1381, 934, 1283, 1682, 2347, 2770, 2804, 3393, 4313, 4816, 3973, 2090, 1332, 1427, 1523, 1883, 2056, 2479, 4034, 5260, 4729, 3674, 3276, 2951, 2411, 1558, 723, 1282, 2543, 2770, 2379, 2028, 1334, 903, 1106, 844, 39, -533, -916, -1100, -1037, -1334, -1044, 536, 1738, 2091, 1538, -1, -1059, -1567, -2726, -3952, -4129, -3308, -1528, 457, 1056, 1065, 1976, 3143, 3052, 1578, 306, 703, 1906, 2698, 2680, 1421, 409, 1064, 2227, 2424, 2033, 2179, 2644, 2773, 2500, 1887, 1756, 2460, 3252, 3877, 3759, 2705, 2123, 2519, 2604, 1656, 704, 1070, 2251, 2174, 699, -184, -330, -414, -405, -764, -1445, -1553, -1118, -749, -675, -953, -1008, -488, -319, -673, -785, -443, 197, 874, 932, 49, -857, -542, 673, 1288, 740, -184, 260, 1826, 1861, 396, -284, -240, -166, 166, -147, -1247, -843, 811, 943, 42, 233, 1076, 1573, 1753, 904, -351, -708, -481, -565, -995, -1184, -995, -293, 284, -106, -424, 421, 1649, 2422, 2682, 2438, 2240, 3248, 4545, 4015, 2461, 2176, 3350, 4219, 3671, 3050, 3436, 4008, 4491, 4614, 3930, 3762, 4700, 4957, 4108, 2948, 1830, 1180, 1326, 2000, 2092, 1504, 1931, 3047, 3170, 2801, 2247, 1627, 1868, 2391, 2211, 1639, 1666, 2216, 2456, 2608, 2590, 2077, 1865, 1650, 719, 162, 775, 1824, 2192, 1965, 1790, 1703, 2108, 2544, 1742, 470, -428, -1660, -2121, -771, 472, 252, 185, 1436, 2234, 1981, 2085, 2278, 2045, 1945, 1961, 1851, 1739, 2049, 2615, 2516, 1927, 1758, 2511, 3569, 3771, 3328, 3104, 3493, 4094, 4119, 3558, 2742, 2021, 1232, 184, -351, -284, -245, -61, 352, 35, -776, -664, 129, 214, -373, -327, 270, 450, 176, -541, -939, -341, 425, 1187, 1746, 1412, 1389, 2485, 3073, 2394, 1878, 1722, 1198, 790, 198, -824, -1199, -604, -92, -101, -273, -344, 479, 1254, 314, -1132, -1520, -1274, -1186, -1127, -1386, -1979, -1922, -1135, -335, 37, -148, -349, 204, 829, 614, 150, 412, 1276, 1672, 1114, 259, 24, 779, 989, -181, -894, -502, -272, -621, -895, -887, -807, -627, 113, 1244, 1260, 602, 1246, 2555, 3079, 2883, 2370, 2269, 2281, 1878, 1283, 650, 584, 960, 703, 108, 305, 1520, 2678, 2432, 1405, 727, 277, 132, -250, -689, -152, 857, 2053, 3404, 4054, 3583, 3089, 3059, 2662, 1311, -474, -1102, -366, -269, -1103, -1288, -957, -1005, -1244, -1513, -1957, -1948, -1242, -866, -1417, -1968, -1636, -1193, -1374, -1555, -1367, -1095, -514, 267, 650, 191, -1160, -2183, -1911, -1393, -1431, -1279, -15, 1906, 2733, 2057, 1479, 1515, 894, -366, -1285, -1541, -1489, -1392, -1011, -664, -840, -963, -326, 178, -72, -529, -705, -245, 287, 424, 572, 572, 689, 1379, 1802, 1701, 1691, 1759, 1431, 553, -60, 126, 797, 1607, 2134, 1879, 1342, 1427, 1772, 2180, 2263, 957, 206, 1510, 2086, 1104, 770, 1497, 2343, 2643, 1885, 700, 371, 561, 628, 215, -672, -1317, -1063, -835, -1565, -2279, -2223, -1927, -1789, -1928, -2460, -2272, -917, -457, -1047, -1231, -1711, -1990, -740, 120, -955, -2031, -1214, 302, 390, -118, -85, 213, 735, 704, -993, -3182, -3596, -2731, -2446, -2514, -2128, -1805, -1525, -868, -157, 377, 1232, 1934, 1406, -437, -1846, -1112, 280, 933, 1347, 1240, 708, 1057, 1972, 1662, 931, 1699, 2755, 2974, 3159, 3261, 2132, 102, -286, 417, -390, -1519, -1485, -887, -329, -382, -994, -1359, -984, -155, -99, -1463, -2622, -2347, -1772, -1509, -1662, -2248, -2392, -1663, -1242, -1521, -1440, -1300, -1342, -679, -482, -1593, -2751, -2935, -2491, -2631, -2909, -2437, -1909, -1939, -2498, -3255, -3636, -3483, -3494, -3357, -1801, 224, 1214, 1767, 1648, 804, 469, 249, 17, 96, -660, -1938, -1848, -808, -681, -1541, -1908, -1434, -1172, -943, 104, 1047, 1597, 1645, 163, -1437, -1839, -2054, -2299, -2207, -2722, -3658, -3853, -3497, -3713, -5089, -5646, -4610, -3762, -3253, -2132, -1045, -1176, -2053, -2042, -1483, -1995, -2594, -2074, -1144, -646, -702, -573, 383, 1680, 2121, 1326, 520, 898, 1739, 1611, 909, 932, 1353, 1301, 655, -648, -1672, -1339, -631, -666, -1040, -1313, -1093, -48, -93, -1988, -2587, -1646, -1862, -2461, -2445, -2730, -2765, -2312, -2285, -2349, -1335, 119, 604, 770, 1322, 1479, 888, 101, -96, -120, -253, -645, -1195, -1029, -663, -611, -536, -976, -1339, -590, -345, -937, -797, -187, -349, -1530, -1875, -1072, -654, -510, -733, -2001, -2846, -2089, -1200, -1744, -2530, -1633, -127, 346, -445, -1094, -247, 644, 192, -117, 185, -564, -1580, -1439, -1479, -2944, -4538, -4362, -2887, -1833, -1682, -1746, -1437, -938, -314, 589, 389, -595, 279, 1316, 383, -478, 49, 1252, 1780, 1218, 1100, 1585, 1668, 1141, -51, -1101, -1626, -1896, -2225, -3101, -3329, -1776, 265, 1238, 826, 90, -11, 387, 956, 1361, 1126, 789, 1400, 2426, 2608, 1985, 1165, 265, -490, -1298, -2479, -3173, -2676, -1746, -1712, -2111, -1519, -378, 112, -410, -1287, -2243, -2661, -2071, -1960, -2342, -1603, -496, -632, -794, -393, -39, 109, -327, -708, -1042, -1914, -2235, -1003, 421, -443, -2958, -3726, -2604, -1945, -2582, -3646, -3298, -1723, -1438, -1968, -1419, -945, -1874, -2664, -3272, -4477, -5181, -5238, -4963, -4247, -3816, -3046, -916, 63, -1638, -3055, -3054, -3323, -3449, -2753, -2625, -3177, -2961, -1571, -917, -2650, -3877, -2761, -1480, -854, -404, -363, -363, 461, 1419, 789, -837, -1213, -696, -775, -1737, -3052, -2890, -1729, -1455, -1222, -974, -1444, -998, -402, -1841, -3323, -3153, -2287, -1813, -2170, -2773, -2521, -1163, -703, -1901, -2596, -2360, -1979, -1521, -997, -719, -1199, -1539, -1025, -640, -1534, -2638, -2414, -1491, -1217, -2117, -3214, -3512, -3470, -3612, -3516, -3360, -3378, -3460, -3136, -2768, -2908, -2798, -2344, -1943, -1849, -1769, -1274, -1619, -2909, -3133, -2450, -1561, -575, 210, 644, 414, -97, 88, 856, 474, -1203, -1465, -736, -1003, -1373, -1422, -1922, -2498, -1672, -692, -1628, -2513, -1465, -607, -873, -1170, -1571, -2144, -2757, -3410, -4159, -4997, -5092, -3819, -1697, -66, 490, 601, 1375, 2927, 3267, 2022, 968, 969, 1790, 2021, 388, -348, 876, 1096, 1015, 2202, 2937, 2724, 2692, 2491, 1689, 1033, 393, -531, -920, -1082, -1336, -859, 282, 1248, 1641, 1287, 619, 517, 628, 299, -174, -321, 113, 460, 356, 339, 35, -612, -4499, -2450, -3462, -4808, -3545, -2996, -3860, -3901, -3620, -4605, -6346, -4243, 183, 150, -3211, -4884, -4445, -3511, -1903, -2151, -3854, -3895, -3540, -2618, -1369, -2185, -3515, -3427, -2424, -1990, -1859, -1224, -2407, -4230, -3290, -3794, -7197, -7572, -6314, -5792, -5180, -5937, -6791, -6469, -5648, -4427, -3584, -3759, -4617, -4612, -4229, -4175, -3417, -2317, -2837, -4650, -5158, -4000, -3017, -3255, -3806, -4405, -4161, -3334, -2825, -2468, -3512, -4904, -4112, -2683, -4047, -6208, -5152, -2377, -1075, -1584, -2091, -2255, -2446, -484, 1484, -393, -2413, -2100, -1935, -2592, -3294, -4161, -4276, -3048, -2833, -3432, -2914, -2482, -1927, -1165, -3334, -6701, -6588, -4564, -4000, -4619, -4274, -3852, -4671, -4562, -4294, -5202, -5367, -3547, -1104, -1271, -3216, -3648, -2199, 74, 489, -942, -589, 1343, 2365, 2374, 2900, 3081, 1951, 1323, 289, -1617, -2298, -2586, -2805, -2125, -2685, -4506, -4658, -3442, -3165, -4828, -5947, -3731, -1583, -2761, -4406, -4212, -2954, -2515, -3192, -3561, -3322, -2901, -2011, -1597, -2278, -3039, -3301, -2850, -1408, 174, -739, -2155, 347, 1779, -1634, -2552, 889, 1910, -668, -2473, -2547, -3339, -4453, -3875, -2931, -3789, -5345, -5534, -4813, -3886, -3011, -3990, -6642, -7269, -5987, -6615, -8808, -8706, -7029, -7193, -7865, -6744, -5771, -4610, -2820, -2754, -2689, -1746, -1297, -908, -247, 389, 189, -515, -725, -338, -253, -1448, -2077, -1045, 262, 901, 276, 239, 980, -471, -2272, -1261, 264, 218, -969, -2045, -1985, -2006, -3184, -3218, -1397, -565, -889, 231, 487, -2229, -3577, -2731, -2393, -2412, -2455, -2701, -2799, -1745, 465, 1640, 1199, 1884, 3008, 2010, 70, -891, -414, -699, -2660, -3889, -3807, -2766, -1539, -2064, -3282, -3287, -1931, -1128, -1887, -2027, -2656, -5128, -5565, -4447, -5378, -6168, -5918, -5631, -4059, -2608, -2492, -2002, -1795, -2110, -1073, -347, -1027, -1613, -1323, -672, -974, -1948, -2987, -3050, -1522, -1163, -3052, -3748, -2233, -1033, -1771, -3523, -4357, -3621, -2686, -3021, -3687, -2664, -1817, -3647, -5309, -5760, -6747, -6978, -6188, -5875, -5190, -3600, -3286, -3859, -3077, -2760, -4050, -4085, -3114, -2938, -2409, -1383, -743, -1231, -1769, -1341, -1542, -1574, -956, -886, -1423, -1809, -2256, -3138, -2972, -2911, -3631, -3709, -3712, -4532, -4491, -4393, -5980, -5548, -3199, -3429, -4520, -3048, -916, -871, -831, 498, 981, 1275, 2804, 3138, 1218, -169, 849, 1734, 342, -1137, -1888, -1304, 229, -470, -1864, -605, -23, -1140, -1074, -594, -792, -1304, -1231, -92, 977, 180, -1027, -335, 592, 1019, 1240, 720, 68, -62, 482, 1168, 1499, 2666, 3788, 4340, 4731, 4413, 4048, 3980, 3833, 3683, 2882, 1099, 308, 1168, 941, -839, -2072, -1950, -1053, -896, -1995, -1397, 749, 780, 567, 1759, 3258, 5234, 4907, 2901, 2561, 2541, 2755, 4013, 4516, 3241, 2364, 4374, 6125, 4537, 3475, 5030, 6277, 5962, 5021, 4650, 4302, 4094, 4599, 4269, 3373, 2402, 1409, 2352, 3734, 3017, 2441, 3328, 3675, 2807, 1411, -192, 159, 2670, 4148, 3056, 1328, 885, 1561, 2517, 2836, 1866, 923, 1705, 2651, 1130, -292, 1288, 3510, 3848, 1920, -386, 288, 3308, 3986, 2603, 2299, 2382, 2153, 3550, 5101, 3445, 1480, 2263, 4140, 4633, 3261, 2002, 2766, 3989, 3931, 3171, 1640, -132, 225, 3035, 3735, 2133, 2192, 2783, 2529, 2906, 3901, 3668, 2940, 3788, 4958, 4803, 4820, 5011, 3745, 2249, 3121, 4422, 3080, 2428, 4397, 4988, 3077, 2475, 3907, 3669, 1419, 822, 2205, 2610, 1083, -504, -1118, -417, 440, 712, 787, -134, -393, 1836, 3566, 2616, 1488, 2078, 2829, 2458, 2416, 3442, 4634, 4816, 4524, 5788, 6366, 5261, 6263, 7032, 5023, 3830, 3821, 3597, 3915, 4303, 3169, 1973, 2561, 2622, 1851, 1551, 1645, 3181, 4001, 2134, 1200, 3049, 3070, 851, 917, 1246, 185, 1191, 3288, 3290, 2693, 3595, 4504, 4702, 4767, 4668, 5642, 6384, 4969, 4690, 6103, 4737, 1751, 2142, 4061, 4139, 4237, 3569, 1731, 2137, 4174, 4999, 5266, 6450, 6684, 4846, 3895, 4062, 3567, 4525, 5856, 3675, 2374, 4127, 5101, 4326, 2964, 2019, 1371, 1444, 2247, 3131, 3796, 3129, 2608, 3648, 2997, 1245, 2343, 4379, 4079, 3464, 3259, 2359, 2943, 4468, 2624, -305, -20, 2452, 3830, 3081, 2350, 1808, 1534, 3462, 4969, 3949, 3847, 4051, 1276, -889, 355, 1130, 1326, 1900, 1424, 1602, 2543, 2908, 3776, 3710, 1062, -170, 1125, 1496, 686, 394, 1227, 3065, 3170, 2010, 2345, 1582, 399, 1261, 1791, 1394, 1318, 1045, 1880, 5039, 6498, 4579, 4519, 6333, 5492, 4167, 4091, 3135, 2369, 2467, 2201, 1419, 79, -225, 1128, 845, -336, 1737, 4003, 3807, 4509, 5578, 4433, 2528, 2731, 5415, 6138, 3000, 1738, 3876, 3966, 2069, 2303, 3999, 5207, 6412, 6011, 3769, 2889, 3929, 4756, 4079, 3368, 3696, 4529, 4593, 3913, 3946, 3654, 2531, 2577, 3414, 2986, 2480, 3635, 4901, 3703, 891, -868, -994, -253, 1338, 2306, 1790, 1351, 1931, 3170, 3827, 3615, 3607, 3901, 4431, 5138, 5909, 6068, 5692, 5701, 4692, 3543, 4756, 5391, 4475, 4588, 4587, 4203, 4548, 4927, 4445, 2314, 671, 1856, 2931, 1875, 304, -442, 458, 2054, 2103, 1027, -62, 491, 2484, 2718, 1492, 759, 1438, 3328, 2884, 937, 1678, 2575, 2770, 5129, 6546, 4386, 2780, 4095, 4826, 4005, 3799, 3868, 2602, 1153, 853, 985, 642, 1598, 3838, 2860, 407, 1416, 4060, 5793, 6034, 4047, 3766, 6010, 6644, 6443, 5359, 2205, 875, 3146, 4206, 2854, 1848, 2432, 3936, 4251, 4610, 6458, 5646, 2164, 2713, 5630, 5485, 4094, 3489, 2422, 963, -40, -732, -1434, -1689, -1972, -1999, -1382, -534, 1106, 1870, 785, 590, 2566, 3985, 2582, 1905, 4523, 5403, 3490, 3481, 4402, 4008, 3872, 4949, 4810, 1869, -111, 1342, 2607, 1839, 213, -728, 568, 2070, 1690, 643, 925, 2159, 2353, 1766, 1269, -342, -2360, -1040, 1783, 1810, 640, 481, 430, -393, 107, 2591, 4748, 5406, 4055, 3348, 4378, 3663, 2920, 4546, 4975, 3714, 3821, 4621, 5200, 5428, 3997, 2708, 2901, 3490, 3929, 3612, 2689, 1968, 2828, 5188, 6239, 3776, 899, 773, 2334, 2642, 865, -140, 1136, 2443, 2559, 2421, 1959, 1371, 1499, 1912, 3096, 3650, 2423, 3278, 6116, 6400, 6122, 7698, 7863, 6308, 4584, 3309, 2652, 2235, 2563, 2212, 1187, 1337, 2246, 3065, 2843, 1075, 376, 1538, 1960, 723, -798, -1000, 474, 1957, 1952, 208, -1221, -418, 525, -128, -663, -858, -1675, -2098, -560, 1944, 2000, 1194, 2237, 2332, 1651, 3181, 4157, 2885, 2550, 1641, -247, 986, 2648, 1558, -394, -1496, 454, 1289, -1096, -823, 509, -989, -1661, 282, 705, -621, -1048, -210, -152, -1042, -307, 331, 1345, 3758, 3591, 2496, 2103, 1665, 2793, 3312, 1704, 645, 736, 135, -725, -326, 3, 233, 1706, 1834, -198, -400, 1181, 1370, 747, 681, 275, -394, 126, 1473, 2135, 2194, 767, -452, 1475, 1699, -1909, -2826, -1809, -3103, -2767, 876, 2386, 781, 854, 2813, 2072, 854, 2433, 2878, 1738, 1355, 405, 658, 2648, 1010, -2614, -1675, 1852, 1916, 683, 1945, 3109, 2475, 1221, 700, 522, -757, -1444, -221, 748, 62, 116, 645, -535, -1947, -1574, -985, -2383, -2707, -702, 1428, 2044, 1330, 1893, 3042, 1768, 454, 1457, 2279, 2254, 1651, 1183, 1793, 2225, 2265, 2389, 1325, -485, 246, 2091, 596, -1402, -658, -1241, -2987, -2709, -3297, -4069, -2923, -3885, -6354, -5584, -3329, -3145, -3229, -2041, -1408, -1939, -1059, 3540, 5132, 12, -1819, 1389, 3691, 3618, 1765, 700, 2188, 2590, 1193, 1621, 2396, 2390, 3141, 2901, 1267, -248, -784, -158, 120, 796, 2387, 1308, -1115, -641, 355, -736, -1767, -1413, -804, -968, -1823, -1729, -1025, -854, 249, 1302, -768, -3956, -3501, -1172, -1055, -1153, -248, -194, -271, 116, -460, -508, 2393, 4738, 3199, 1426, 2164, 3629, 3698, 2823, 2238, 1463, 1730, 2574, 914, -923, -759, 68, 635, -239, -2123, -3515, -3757, -1359, 1083, -382, -1852, -1299, -747, 92, -143, -2138, -1978, 683, 1160, -1116, -2686, -1356, -194, -1753, -2530, -2524, -2635, -1331, -471, -1737, -2682, -3045, -3714, -2943, -1071, -841, -1795, -227, 2452, 2424, 1671, 2585, 2612, 1275, 1274, 1409, -91, -225, 1059, 1299, 101, -2548, -3726, -2054, -994, -1251, -1266, -1684, -3012, -3540, -2968, -3190, -3964, -4699, -5414, -6722, -7006, -5123, -4224, -3919, -2471, -1604, -1844, -2302, -2209, -2164, -2808, -2187, -925, -491, 42, -588, -2183, -1048, 132, -1526, -1815, -777, 50, 1680, 1138, -125, 634, -38, -902, -196, -1115, -2389, -1269, -1013, -1647, -1186, -1102, -1354, -1887, -2872, -2930, -2186, -1143, 725, 1729, 1408, 820, 65, 471, 1020, 354, -649, -193, 2166, 2475, 195, -1064, -670, 963, 1997, 1175, -240, -1714, -2562, -1509, 518, 1372, 733, -199, -216, 486, 872, 50, -1431, -1196, -505, -990, -1343, -1100, -1185, -1179, -488, -985, -2780, -2164, 373, 721, -5, 264, -1, -387, 361, -1039, -3197, -1887, -1372, -3604, -4557, -4739, -4331, -1487, 1255, 1118, -131, -200, -45, -479, -1360, -2100, -2187, -1162, 815, 1780, 83, -1839, -1243, -835, -1907, -2961, -3580, -3739, -3924, -5353, -7196, -6555, -5496, -6879, -6334, -3783, -3364, -3517, -2829, -1841, -497, 493, 1354, 2259, 1143, -1135, -1596, -145, 1344, 1194, -266, -1638, -2601, -1806, 17, -139, -1551, -2366, -1182, -368, -2934, -5097, -3060, -1269, -3031, -4700, -4205, -3828, -4669, -5168, -4777, -4946, -5420, -4150, -2436, -2065, -1717, -1558, -1841, -1511, -931, -1067, -1087, -364, 531, 785, 356, -485, 174, 1786, -57, -2505, -1137, 890, 588, -493, -1301, -2514, -2735, -826, -424, -2632, -3131, -2900, -3590, -3766, -3372, -3619, -4723, -4410, -3204, -2995, -2989, -4119, -4853, -3381, -2247, -2599, -3196, -3044, -1988, -60, 533, -536, -884, -499, -562, -711, -743, 236, 2335, 2559, 1265, 1003, 1534, 2294, 1504, -607, -711, -37, -710, -1098, -1193, -1773, -1056, 812, 931, -896, -2234, -1898, -1555, -1572, -969, -358, -1546, -3189, -3464, -2893, -1404, -802, -1213, -392, 550, 154, -268, 215, 938, -269, -1758, -591, 236, -215, 399, 603, 249, 1551, 1814, -1366, -3298, -949, 1782, 1185, -1030, -1516, -886, -994, -1284, -973, -1444, -2135, -62, 1487, 60, -544, -1312, -2761, -1544, -106, -1334, -1822, -304, 850, 1267, 1093, 1562, 3306, 2924, 995, 833, 1482, 1395, 1142, 587, -748, -626, 966, -196, -2610, -2872, -2946, -2234, -910, 71, 1049, -239, -2594, -1932, -358, -528, -1497, -2240, -1814, -1375, -2370, -3946, -5300, -5021, -3374, -2971, -2769, -1421, -1119, -418, 1391, 1033, -1164, -2526, -791, 1536, 1211, -565, -1103, -751, -1365, -1903, -1078, 123, 462, 490, -669, -2736, -3262, -2216, -926, -413, -1281, -2170, -1829, -1580, -1393, -1268, -2477, -2883, -1403, -1826, -3951, -3689, -2296, -1559, -1219, -2319, -3392, -2388, -121, 1369, 1335, 1113, 234, -1378, -2118, -1397, -1333, -3189, -4831, -4572, -3128, -2128, -1390, -349, 992, 1666, 640, -774, -1008, -970, -546, 644, 1019, 479, 502, 575, -417, -1617, -2269, -2072, -580, -419, -2194, -2274, -907, -520, -705, -1785, -1957, 124, 759, -1301, -3034, -1957, 640, 716, -608, 99, 1616, 1845, 916, -769, -1876, -1847, -1142, -621, -884, -1325, -1826, -2694, -2817, -2312, -2803, -3316, -1794, 47, -783, -2749, -3614, -3061, -2329, -3151, -4979, -5071, -2293, -465, -1077, -1151, -749, -1413, -2113, -1803, -986, -1598, -3970, -4576, -2633, -1309, -1926, -1745, 1139, 3104, 1237, -2503, -2728, 1130, 1928, -1324, -2352, -885, -862, -979, 4, -638, -2194, -2261, -1223, -1203, -3157, -3572, -1486, -1656, -3600, -3616, -2984, -2977, -1245, 1127, 378, -2181, -3506, -2929, -1036, -608, -1759, -1715, -582, 8, -906, -1188, 313, 872, 728, 2285, 3062, 1228, -62, -370, -1398, -1585, 457, 1773, -171, -2214, -1221, 227, -789, -813, 553, -1122, -3409, -3086, -2195, -1676, -1519, -1518, -866, -450, -192, 222, -25, -1137, -2631, -2620, -1565, -790, 1362, 2500, 518, 2, 1356, 675, -299, 346, 1040, 462, -348, 426, 534, -1694, -2732, -1837, -761, -85, -1828, -3495, -1617, 165, -505, -1761, -2408, -2131, -2120, -3119, -3992, -4175, -4226, -3124, -1077, -319, -1135, -2698, -1864, 1708, 3288, 1887, 1096, 2101, 1873, 301, -542, -1204, -539, 898, -314, -262, 1379, 461, -190, 94, -638, -1767, -2662, -1239, 1713, -77, -3597, -2936, -1655, -2339, -2688, -2986, -5425, -6665, -4128, -3243, -5961, -6190, -2809, -329, 493, 536, -15, 268, 1790, 2494, 1608, -158, -617, 1322, 2074, 1074, -118, -1045, -794, 54, -283, -913, 1016, 2903, 2353, 1305, -383, -1026, 923, 2624, 1490, -665, -1848, -2162, -1067, 63, -763, -2346, -1176, 1561, 2118, 1018, 790, 2890, 3837, 1274, -602, 137, 1160, 1999, 1698, -376, -502, 1515, 2755, 2413, -950, -4649, -2101, 1515, 50, -986, 140, 293, 66, 292, 97, -156, -177, -313, -1048, -2062, -1514, -535, -890, -772, -1307, -3677, -4521, -3508, -3436, -3899, -3533, -2932, -2846, -2776, -2254, -2936, -4359, -3236, -1989, -2806, -3623, -4226, -3542, -530, -186, -2646, -2609, -1580, -1127, 482, 781, -1873, -3105, -1271, -623, -2885, -4207, -3098, -1853, -1394, -1948, -2956, -2920, -3349, -5239, -5681, -4927, -4140, -3871, -4344, -4500, -4611, -3624, -1094, -57, -2306, -4529, -4059, -3252, -4154, -4041, -1925, -1689, -1964, -326, 584, -172, -917, -1751, -1866, 672, 2269, -84, -2198, -378, 1514, -4, -1808, -1794, -358, 2472, 2959, 124, -1247, -477, 578, 1403, 1085, -345, -881, -529, -1031, -2266, -3576, -2925, -357, -207, -1980, -1920, -690, -121, -147, 137, -512, -1483, 941, 3959, 3299, 2195, 2684, 2823, 2439, 2594, 2589, 918, -304, 1234, 2067, 1491, 2041, 1971, 184, -308, 1517, 2422, 409, -283, 1644, 1800, 807, 654, 1219, 1035, 318, 304, -391, -1525, -1302, -873, -1177, -1048, -276, -703, -2162, -1394, 944, 1618, 938, 869, 1944, 2072, -407, -1145, 1464, 2249, 1085, 2128, 3502, 2923, 2082, 1127, 1646, 2993, 1547, -1185, -1923, -98, 1019, -1090, -2813, -1401, 653, 659, -833, -2788, -3339, -2039, -2327, -3266, -1974, -1457, -3011, -3206, -2180, -2728, -4119, -4419, -3990, -2773, -2174, -3311, -2885, -567, -25, -726, -1226, -1205, 877, 2954, 1452, -437, 206, 1000, 1950, 1655, -830, -1422, -188, -438, -1466, -1666, -2404, -4090, -4309, -2341, -1203, -1714, -1433, -1148, -2464, -3996, -4066, -2735, -1531, -2270, -3172, -1774, 15, 701, 715, 41, 93, 293, -353, 744, 3165, 2481, 553, 2031, 2635, -625, -1580, 738, 1744, 753, -196, -1014, -2147, -1712, -460, -659, -321, -437, -2426, -2228, -675, -33, 110, -97, 352, 1563, 1749, 1137, 1803, 2595, 2475, 418, -1142, 958, 3088, 3446, 3904, 2591, 1159, 3007, 4712, 3238, 914, 1030, 2119, 2025, 2300, 2530, 1272, 620, 1587, 1359, -587, -688, 740, 92, -1275, -21, 1541, -29, -1223, 508, 476, -975, 324, 1885, 1823, 1019, 531, 642, 1106, 1178, 1115, 2122, 3028, 2839, 2366, 1210, 6, -59, 226, 1054, 1812, 103, -2276, -175, 3032, 1243, -476, 1695, 2116, 454, 183, 1271, 1905, 1051, -527, -1662, -1753, -1485, -1017, -855, -692, -857, -2390, -1976, 822, 1091, -1049, -2580, -1834, 1302, 2307, 126, -1447, -372, 1371, 238, -1274, 327, 1352, 464, 1454, 2686, 1402, -493, -197, 780, 48, -791, -138, 1072, 573, -1832, -3091, -1946, -667, -241, -1064, -2014, -1733, -1111, -867, -697, 464, 1541, 974, 765, -96, -3004, -2025, 2299, 2306, 131, 751, 1978, 1674, 1870, 3607, 3664, 1505, 1561, 2036, -144, -828, 1379, 2340, 1546, 1333, 1347, -1023, -2155, 993, 1975, -645, -1362, 13, 506, 246, 201, -193, -254, 341, 725, 630, 184, 520, 1369, 1567, 647, -125, 1332, 3720, 4023, 2309, 1010, 1234, 2932, 4785, 4412, 2838, 1678, 1695, 3390, 4247, 3288, 1289, -203, 580, 1721, 1364, 2143, 3553, 3904, 4015, 3041, 1507, 1467, 2010, 1609, 1865, 2976, 3427, 3523, 2839, 2297, 2700, 1848, 1991, 4256, 4855, 3195, 2714, 3759, 3163, 1706, 2896, 5051, 3527, 778, 1183, 3036, 3480, 2483, 2111, 2972, 2911, 1966, 1055, 275, 1236, 2064, 248, -529, 1656, 3202, 3687, 2768, 1462, 2352, 2529, 1265, 490, 650, 1768, 2348, 1303, -796, -2854, -2375, 616, 1617, -269, -1557, -405, 1424, 711, -1111, -907, 919, 1742, 795, 843, 1171, -479, -1913, -1963, -2360, -1908, 243, 2336, 2186, 853, 1349, 2348, 1489, -327, -2303, -3743, -2253, 967, 1227, -851, -990, 902, 1426, -293, -2152, -2841, -2635, -2431, -2058, -2174, -4406, -5076, -1595, 1894, 1675, -1531, -2574, -21, 591, -786, -898, -646, 215, 1627, 1414, 190, 1334, 3914, 4323, 2175, -37, 169, 2010, 2584, 1422, 268, -1125, -1461, 422, 1279, 841, 1209, 548, -1116, -1298, -857, -854, -269, 1121, 1645, 1146, -274, -824, 711, 1938, 2978, 3083, 1792, 1833, 2640, 2795, 2716, 2154, 1782, 2956, 3759, 2980, 2938, 3885, 3236, 1017, 869, 983, -375, 368, 1585, 1277, 1725, 1901, 1008, 1640, 2583, 1055, 643, 2848, 3217, 1365, 539, 1674, 2924, 2607, 1071, 646, 1887, 2366, 2665, 3630, 2156, -726, 412, 3882, 3801, 1261, 1128, 2225, 1980, 1083, 905, 2472, 3336, 1696, 943, 1337, 675, 688, 776, -2249, -3608, -811, 1183, 729, 534, 978, 329, 683, 3348, 4191, 1718, -779, -1265, 610, 2524, 2178, 731, -454, -1256, -418, 751, -1235, -3431, -1208, 2337, 1172, -1780, -1145, 608, 187, -1698, -3410, -2350, -460, -884, -888, 257, -127, -302, 1556, 1959, -568, -2084, -243, 1318, -427, -1690, 110, 347, -732, 193, 539, -1214, -1568, -1235, -2692, -3026, -2075, -2887, -3814, -2918, -2377, -3545, -3615, -1427, -54, -357, -294, -72, -803, -1554, -1769, -2312, -2123, -753, -909, -1752, -393, 1970, 1973, 374, 1138, 4050, 3988, 250, -1000, -640, -856, 1941, 4342, 2863, 495, -715, -202, 1254, 1726, 810, -753, -1796, -2489, -3082, -2650, -2163, -1375, 113, 209, -404, -219, -540, -672, -115, -858, -1219, -1202, -1568, -46, 1778, 1532, 1456, 3187, 3999, 4064, 4085, 2797, 1128, 529, 2369, 4671, 2874, 708, 2135, 3233, 3342, 3789, 3017, 1914, 1868, 2135, 1421, -442, -45, 3139, 3697, 1197, 35, -1, 139, 1212, 2243, 3396, 4090, 2676, 1725, 4413, 7258, 5176, 2549, 4502, 6216, 5040, 3930, 2366, 1823, 3868, 4407, 2197, 786, 2065, 4405, 3640, 174, -254, 1687, 2254, 2668, 3190, 2453, 2494, 3377, 1978, -1515, -2440, 257, 2037, 2840, 4203, 3670, 2789, 3681, 3803, 2849, 3064, 2986, 1633, 1239, 1600, 1228, 1307, 2286, 2027, 1731, 3921, 4696, 2168, 2155, 3148, 413, -672, 1126, 587, -701, -552, -514, -183, 1330, 2613, 2736, 2194, 1781, 1372, 9, -340, 1617, 1996, 1104, 1097, -314, -1215, 1227, 2845, 575, -1101, 912, 2604, 790, -1817, -3074, -1846, -151, -1912, -4320, -4139, -4250, -5550, -6081, -5629, -3848, -2294, -1702, 139, 1368, 456, -95, -470, -1569, -1555, -300, 294, 275, 1685, 2630, 1084, -808, -1237, -440, -1138, -3119, -2461, -788, -1731, -2414, -394, 559, -656, -724, 1083, 1256, -1439, -4185, -4450, -2310, -1287, -2950, -3924, -2230, -420, 548, 1681, 1919, 2392, 3723, 2375, -26, 1895, 5235, 3882, 807, -22, -328, 1090, 3720, 3334, -44, -2186, -2061, -1294, -968, -1910, -2641, -1532, 557, 910, 524, 2300, 2556, 387, 431, 1754, 1543, -29, -1491, -1823, -1375, -1470, -3088, -3894, -1949, 1519, 3194, 1375, -348, 639, 1904, 1377, 421, -378, -787, -424, -709, -2015, -1956, -525, -146, -1112, -708, 1240, 2014, 1032, -922, -2334, -1740, -225, 734, 1171, 79, -1353, -550, 1121, 752, -696, -1286, -1514, -931, 958, 931, -897, 272, 3427, 3634, 1230, 1293, 3651, 4103, 2449, 824, 89, 196, 508, 733, -719, -2286, -614, 684, 8, 1369, 2882, 1648, 1675, 3266, 2550, 363, -181, 1229, 2710, 2256, 45, -1082, 1783, 5042, 2727, -1107, -665, 568, -147, -217, 88, -1191, -1568, 1643, 3397, 1396, 1786, 5047, 5206, 2798, 1696, 1885, 1614, 993, 1358, 1068, 562, 1716, 2419, 1215, 177, 108, -38, -50, 435, 332, -207, -91, -223, -1121, -670, -51, -647, -418, -597, -1819, -2776, -4286, -5426, -3869, -1655, -2593, -3215, -266, 456, -2527, -4029, -3521, -2602, -1633, -433, -715, -2031, -513, 1754, -319, -3109, -2237, -1340, -2341, -1862, 187, 2296, 4617, 5288, 2802, -431, -658, 668, 846, 1018, 673, -1727, -2970, 2, 2422, 613, 1824, 1868, 2196, 2514, 1619, 222, -443, -581, -307, -550, -1458, -2249, -2542, -2155, -2160, -2892, -3419, -3489, -3910, -4839, -5136, -4624, -4074, -3284, -2745, -3015, -2986, -2585, -2010, -1008, -399, -267, 297, 804, 578, -142, -834, -1283, -1664, -1830, -1674, -1789, -2191, -2136, -1931, -2126, -2507, -2938, -3172, -2798, -2859, -3474, -3377, -3301, -3931, -4310, -4348, -4644, -4665, -4175, -3475, -2818, -2738, -3072, -2492, -1206, -1015, -1973, -2497, -2236, -1860, -1465, -781, 169, 775, 801, 687, 47, -859, -849, -488, -923, -1533, -1446, -781, -290, -624, -1078, -1136, -710, -241, -600, -1396, -2089, -2311, -2056, -2183, -3107, -4126, -4159, -3329, -2803, -2912, -3118, -3203, -2906, -2712, -3322, -4063, -4278, -3865, -3545, -3879, -4025, -3465, -2496, -1495, -968, -766, -51, 732, 744, 327, -264, -412, 224, 894, 1077, 426, -252, -52, 347, 316, -329, -1402, -1383, -339, -362, -1320, -1689, -1550, -1609, -1688, -1736, -1826, -1458, -1169, -1097, -507, -80, -473, -588, 583, 1136, -83, -458, 426, 1047, 1674, 1952, 1450, 1400, 2592, 3362, 2811, 2362, 2894, 3419, 2673, 1447, 1300, 2440, 3250, 3017, 2831, 2607, 2533, 3389, 4249, 3982, 3229, 2956, 3745, 4786, 4490, 4197, 5862, 8546, 10552, 11105, 10693, 11124, 12366, 12995, 13462, 14449, 14782, 14066, 13931, 14425, 13997, 13853, 15182, 15884, 14801, 13657, 13646, 13639, 12989, 12238, 11379, 10594, 10320, 9467, 7476, 5739, 4835, 4648, 4678, 4118, 2587, 387, -804, -625, -1010, -2338, -3256, -3551, -4039, -4920, -6402, -8232, -8789, -8416, -8916, -10232, -11419, -11606, -10734, -9822, -10087, -11069, -10943, -9935, -9642, -9933, -10157, -10216, -10131, -9912, -9618, -9104, -8701, -8959, -8912, -8289, -8435, -9071, -9118, -9209, -9592, -10018, -10867, -11421, -11000, -11016, -11765, -11875, -11491, -11145, -10796, -10670, -10563, -9997, -8842, -7837, -7675, -7513, -6605, -5471, -4783, -4916, -5289, -5191, -4763, -4598, -5124, -5704, -5499, -5162, -5352, -5465, -5385, -5736, -6354, -6413, -6329, -6919, -8115, -9218, -9334, -9394, -10823, -12788, -13337, -12307, -11809, -12665, -13587, -13503, -12370, -11486, -11734, -11856, -11254, -10626, -10038, -10067, -10838, -11155, -10784, -10408, -9808, -9539, -10164, -10047, -8964, -8860, -9603, -9418, -8501, -8329, -8611, -8526, -8363, -8305, -8522, -9171, -10059, -10735, -10513, -9751, -9381, -9153, -8736, -8052, -7142, -6466, -6130, -5587, -4969, -4488, -4052, -4057, -4342, -4399, -4342, -4395, -4195, -3882, -3687, -3042, -2074, -1954, -2560, -2765, -2026, -1189, -1348, -1747, -2077, -2920, -3634, -4149, -4887, -5424, -5603, -5669, -5731, -5855, -5921, -5502, -4641, -4262, -4462, -4220, -3413, -2584, -1991, -1556, -1413, -1495, -1292, -724, -135, 36, 95, 592, 810, 344, -369, -980, -1255, -1297, -1608, -2288, -2601, -2392, -2318, -2370, -2767, -3669, -3968, -3327, -2538, -2087, -2145, -2137, -1721, -1578, -1695, -1727, -1375, -224, 1090, 1397, 695, -159, -185, 432, 332, -822, -1773, -1484, -651, -395, -492, -457, -279, -294, -736, -977, -820, -681, -958, -1822, -2684, -2652, -2426, -2902, -3021, -2271, -1690, -1674, -1561, -1078, -1126, -1680, -1264, 11, 492, 202, 170, 476, 551, 441, 542, 474, 169, 307, 396, -429, -1015, -461, -141, -389, -441, -649, -694, -50, 159, -632, -1233, -812, -47, 233, 17, -332, -628, -485, 34, -116, -1034, -1053, 30, 748, 527, -30, 563, 2126, 2942, 2672, 2007, 1449, 1754, 2729, 2580, 1326, 921, 1731, 2341, 2232, 1891, 1682, 1892, 2675, 3346, 3086, 2524, 2618, 3010, 2892, 1930, 517, -149, -44, 42, 200, 270, 255, 805, 1505, 1212, 274, 215, 1343, 2509, 2567, 1702, 1564, 2690, 3584, 3460, 2834, 2511, 2877, 3525, 3481, 2712, 2822, 3683, 3745, 3281, 2794, 2466, 2679, 2996, 2987, 2600, 1886, 1221, 650, -166, -907, -1518, -1860, -1403, -994, -1180, -1251, -1082, -645, 312, 742, 123, 469, 2112, 2946, 2899, 3151, 3616, 4176, 4801, 4915, 4142, 3188, 2788, 2682, 2484, 2260, 2215, 2277, 2568, 2919, 2733, 2595, 2822, 2941, 2975, 2901, 2756, 2667, 2949, 3290, 2563, 1442, 1820, 3351, 4046, 3515, 2959, 3035, 3257, 3158, 3116, 2989, 2964, 3285, 3085, 2517, 2416, 2693, 3050, 3367, 3528, 3406, 3075, 2905, 2974, 2935, 2533, 2132, 2210, 3062, 3455, 2466, 1980, 2855, 3582, 3317, 2735, 2435, 2439, 2992, 3430, 2892, 2212, 2079, 2509, 3118, 2777, 1884, 1755, 2675, 3461, 2537, 1368, 1632, 2061, 1999, 1877, 1728, 1836, 2407, 2687, 2206, 1617, 1168, 1237, 1950, 2324, 2406, 3015, 3424, 3504, 3761, 3478, 2813, 2679, 2826, 3114, 3428, 3192, 2609, 2172, 2094, 2156, 2158, 2272, 2538, 2723, 2386, 1675, 1800, 2775, 3152, 2658, 1817, 1047, 1254, 2066, 2288, 1979, 1722, 2116, 2487, 1957, 1563, 1821, 2142, 2659, 3336, 3319, 2754, 2673, 3058, 3411, 3308, 2769, 2841, 3653, 3532, 2573, 2613, 3188, 3217, 2958, 2050, 706, 232, 566, 648, 206, -275, -375, -241, -295, -471, -600, -406, 700, 2168, 2726, 2624, 3243, 4542, 4702, 3514, 2782, 3183, 3710, 4199, 4645, 4170, 3348, 3633, 4705, 4765, 4025, 3920, 4328, 4703, 4558, 3992, 3750, 3877, 3904, 3454, 2406, 1402, 1217, 1399, 1448, 1214, 456, 448, 1989, 2917, 2347, 2355, 3005, 2986, 2753, 2605, 2060, 1644, 2266, 3066, 3226, 3346, 3720, 3875, 3975, 4008, 3241, 2433, 2797, 3255, 2464, 1601, 1800, 1962, 1785, 1426, 833, 766, 1039, 1518, 2181, 2133, 1218, 662, 1040, 1706, 1998, 1796, 1528, 1423, 1521, 1534, 1558, 2000, 2451, 2674, 2644, 2165, 1942, 2446, 2780, 2526, 2081, 1830, 2028, 2273, 1841, 1359, 1660, 1832, 1487, 1260, 1004, 800, 1072, 1795, 2742, 2873, 2031, 1486, 2098, 3417, 3351, 2536, 3055, 3618, 3264, 3156, 3552, 3943, 4156, 4026, 3430, 2587, 1940, 1869, 1916, 1214, 480, 578, 1308, 2048, 1896, 994, 529, 971, 1198, -25, -1492, -1591, -736, -121, -211, 24, 968, 1658, 1844, 2202, 2969, 3351, 3432, 3889, 3951, 3197, 2742, 3120, 3501, 3203, 2927, 3535, 4284, 4772, 4751, 3504, 2498, 3172, 4037, 3887, 3080, 2174, 1988, 2335, 2249, 1757, 1546, 2002, 2456, 2179, 1526, 705, 534, 1247, 1615, 1511, 1132, 515, 718, 1701, 2087, 1793, 1748, 2516, 3724, 3954, 3148, 3236, 4322, 4792, 4497, 4228, 3929, 3970, 4337, 4180, 3692, 3232, 2878, 3171, 3910, 3754, 2494, 2215, 3662, 4362, 3186, 2396, 2744, 2784, 2400, 1914, 1369, 1000, 1178, 1746, 1443, 494, 555, 1403, 1958, 1717, 1255, 1826, 2964, 3703, 4038, 3875, 3740, 4398, 5238, 5364, 4799, 3968, 3612, 3702, 3309, 2740, 2528, 2293, 2093, 1898, 1526, 968, 205, -43, 455, 610, -281, -857, 33, 775, 411, 205, 697, 1484, 2553, 3525, 3445, 3090, 3427, 3665, 3869, 4429, 4690, 4754, 4743, 4368, 3741, 3540, 3966, 4020, 3486, 3256, 3150, 2995, 3267, 3290, 2481, 1639, 1355, 1261, 1494, 1590, 927, 655, 1313, 1330, 82, -1090, -1279, -980, -1153, -1859, -2058, -1532, -1329, -1840, -1979, -950, 674, 1957, 2301, 2102, 1907, 1757, 1813, 2356, 2813, 2505, 1929, 1763, 2518, 3411, 2852, 1633, 1746, 2225, 1396, 327, 298, 745, 912, 833, 605, 73, -331, 47, 623, 454, -160, 60, 1054, 1281, 287, -546, -129, 647, 995, 1446, 1879, 1929, 1875, 2319, 3078, 3196, 3240, 4047, 4618, 4223, 3543, 3106, 3308, 4129, 4051, 2854, 1872, 1483, 1392, 895, 85, -249, -399, -1307, -2360, -2578, -2478, -2380, -2086, -1815, -1643, -1260, -715, -58, 251, -163, -495, -20, 852, 1355, 1137, 836, 1372, 2342, 2738, 3098, 3452, 2949, 2609, 3023, 3403, 3281, 2809, 2655, 3090, 3538, 3475, 3044, 2217, 1301, 1015, 949, 690, 449, 537, 972, 610, -690, -1164, -501, -327, -849, -1126, -780, 107, 442, -681, -1589, -698, 796, 1569, 1453, 1180, 1584, 2533, 3153, 2915, 2764, 3462, 3830, 3465, 2940, 2189, 1963, 2920, 3652, 3241, 3077, 3521, 3212, 2491, 2174, 1774, 1211, 947, 1022, 948, 482, -157, -411, -139, -172, 26, 473, 40, -365, -338, -919, -1939, -2182, -1494, -891, -476, 54, 380, 830, 1452, 1180, 29, -419, 27, 191, -51, -246, -109, 749, 1677, 1409, 107, -613, -66, 765, 1073, 822, 310, -73, -103, 317, 502, -72, -141, 470, 230, -1178, -2389, -2200, -1716, -2009, -2499, -3130, -3332, -2456, -2017, -2869, -3663, -3653, -3409, -2988, -2501, -2754, -3302, -3210, -2985, -3091, -2994, -2278, -1148, -305, 122, 543, 945, 1400, 1735, 1798, 1962, 1675, 1031, 852, 712, 127, -479, -511, -206, -477, -1185, -1429, -1246, -948, -621, -661, -886, -624, 88, 458, -191, -1208, -1222, -223, 342, 18, -286, -243, -343, -380, 363, 1300, 1333, 1091, 1625, 1921, 1492, 1509, 1726, 1586, 1433, 1035, 691, 1206, 1817, 1729, 1592, 1609, 1294, 610, -36, -550, -746, -599, -308, 115, 76, -587, -880, -514, -544, -1253, -1058, 516, 1465, 1411, 1019, 429, 414, 540, -43, -522, -696, -1159, -1532, -1209, -1240, -1669, -847, 894, 2062, 2245, 1703, 1224, 1401, 1171, 96, -271, -38, 206, 1049, 1777, 1458, 625, 218, 196, -25, -557, -868, -469, 345, 601, 52, -466, -585, -459, -488, -776, -930, -359, 646, 751, 70, -485, -570, -189, 235, 421, 668, 953, 1254, 1577, 1336, 922, 1103, 1487, 1748, 1654, 1061, 930, 1255, 1130, 723, 189, -430, -910, -1026, -1073, -2043, -3532, -3910, -3492, -3478, -3910, -4348, -4459, -4435, -4152, -3598, -3807, -4286, -3360, -1670, -646, -439, -489, -243, 403, 472, -306, -594, -82, 355, 680, 842, 294, -69, 191, 301, -105, -523, -638, -844, -1098, -1697, -2343, -2157, -1891, -2092, -2046, -2060, -2721, -3096, -2700, -2565, -3441, -4191, -3597, -2673, -2391, -2293, -1977, -1363, -837, -1055, -1473, -1008, -146, 318, -4, -510, -25, 885, 1382, 1442, 1079, 906, 1578, 2221, 2156, 1390, 565, 561, 754, 428, 98, 17, -140, -271, -339, -681, -1482, -1832, -1206, -1124, -1820, -1990, -1840, -1809, -1793, -1839, -2017, -2018, -1190, -56, 186, -455, -265, 1041, 1695, 1302, 824, 979, 1676, 1945, 1120, 254, 452, 718, 125, -300, -252, -607, -974, -1081, -1366, -1800, -2258, -2600, -2565, -2393, -2587, -2852, -2687, -2219, -2202, -3287, -4689, -5173, -4785, -4220, -3898, -3370, -2466, -1981, -1782, -895, -167, -293, -109, 680, 1056, 514, 448, 1465, 1864, 1086, 192, -138, 184, 555, -76, -1633, -2535, -2071, -1220, -900, -1273, -2139, -2434, -2102, -2206, -2722, -3021, -2849, -2559, -2457, -2482, -2497, -2647, -2641, -1876, -1413, -1912, -2055, -1622, -1280, -939, -1045, -1542, -1067, 10, -149, -988, -773, 1, 139, -486, -1153, -1204, -769, -608, -1034, -1482, -1824, -2208, -2405, -2612, -3307, -3742, -3002, -2236, -2610, -3290, -3436, -3109, -2476, -1789, -2013, -3403, -4064, -3356, -2796, -2700, -2176, -1447, -1064, -1056, -1103, -999, -1068, -1204, -1225, -2396, -4714, -6020, -5068, -3230, -2781, -2997, -2240, -1343, -1510, -2684, -4420, -5406, -4367, -3055, -3118, -3491, -3156, -2492, -2243, -2533, -3081, -3301, -3083, -2950, -3207, -4054, -4563, -3616, -2499, -2819, -3606, -3691, -3468, -3117, -2947, -3674, -4231, -3750, -2963, -2227, -2024, -2114, -1526, -227, 440, -44, -474, -111, 247, -124, -861, -1522, -1811, -1613, -1239, -1190, -1661, -2072, -1755, -898, -695, -1868, -3280, -3817, -4099, -4684, -5242, -5651, -5594, -4616, -3395, -3284, -4032, -4112, -3382, -2875, -3598, -4676, -4188, -2944, -2607, -2894, -2707, -2037, -1461, -1126, -1065, -831, -414, -565, -1387, -1909, -1891, -1914, -1706, -1272, -1610, -2261, -2305, -1527, -218, 43, -1632, -3191, -3148, -2668, -3138, -4208, -4322, -3294, -2506, -2235, -2023, -2102, -2258, -1920, -1754, -2301, -2368, -1773, -1187, -426, 120, -107, -215, 535, 1056, 183, -1445, -2352, -2273, -1914, -1794, -2012, -2078, -1323, -492, -989, -1804, -1658, -1863, -2445, -2714, -3447, -4413, -4255, -3261, -2727, -2668, -2314, -1305, -156, -238, -1520, -2041, -1431, -1251, -1592, -1462, -1099, -977, -607, -19, -31, -370, -134, 621, 835, -458, -1851, -1963, -1631, -1424, -1518, -2025, -2330, -2015, -1397, -1204, -1853, -2097, -1214, -995, -2168, -2933, -2787, -2484, -2063, -1767, -1676, -1218, -554, 69, 517, 60, -512, -71, 201, -210, -492, -787, -987, -662, -241, 139, 167, -91, 597, 2180, 2227, 610, 314, 1208, 1228, 293, -665, -1156, -1092, -842, -1345, -2385, -2381, -1291, -802, -1752, -3227, -3778, -3535, -3443, -3364, -3391, -3827, -3658, -2697, -2422, -3137, -3256, -2745, -2733, -2555, -2139, -2034, -1966, -2013, -2119, -1869, -1920, -2196, -1959, -1494, -1402, -1696, -1712, -1317, -759, -84, 61, -556, -806, -576, -837, -1056, -695, -568, -1030, -1325, -1242, -1309, -1222, -723, -518, -1221, -2283, -2366, -1323, -393, -569, -980, -840, -669, -648, -786, -747, -255, -5, -331, -664, -721, -1144, -1434, -704, -42, -224, -454, 18, 612, 230, -800, -1171, -392, 604, 495, -281, -156, 462, 310, -256, -661, -906, -390, 826, 1358, 1064, 530, 261, 315, 316, 153, -413, -1112, -1057, -751, -1004, -1100, -114, 843, 492, 49, -312, -965, -877, -391, 164, 569, 353, 776, 1898, 1981, 1194, 981, 1115, 1053, 926, 736, 298, 277, 1246, 1300, -432, -1961, -2041, -1502, -1728, -2521, -2722, -2558, -2892, -3508, -3356, -3291, -4437, -5015, -4234, -3580, -3277, -2637, -1769, -871, -286, -410, -304, 372, 506, 376, 673, 1071, 1379, 1668, 1929, 1939, 1792, 1820, 1896, 1571, 1140, 988, 812, 935, 1090, 292, -935, -926, -85, -560, -2069, -2643, -2341, -1791, -1498, -1925, -2474, -2724, -2609, -2124, -1600, -1595, -2147, -2001, -1062, -875, -1037, -220, 889, 1315, 1392, 1691, 2194, 2223, 1816, 1360, 729, 630, 1515, 2550, 2706, 2143, 1955, 2084, 1814, 1460, 1094, 468, 352, 445, -160, -1215, -1799, -1502, -874, -763, -1345, -1860, -1989, -1891, -1569, -1545, -1884, -1609, -783, -579, -1371, -2013, -1601, -1203, -957, -451, -360, 126, 1377, 1853, 1388, 1000, 916, 1657, 2735, 2755, 2156, 2004, 2372, 2401, 1621, 753, 428, 767, 1340, 928, -437, -1058, -525, 312, 214, -988, -1640, -1194, -566, -590, -1463, -1923, -1220, -644, -920, -1428, -1531, -1515, -1573, -1014, -240, -95, -275, -434, -171, 497, 644, 399, 746, 1243, 735, -100, 210, 921, 771, -129, -1125, -1347, -880, -344, 98, -598, -2111, -2390, -2088, -3171, -4934, -5716, -5436, -4898, -4556, -4340, -4102, -3471, -2187, -939, -917, -1503, -1079, -48, 380, 567, 1137, 1667, 1896, 2021, 2380, 2565, 1866, 1405, 2011, 2080, 1179, 965, 1249, 1217, 1277, 1027, 255, 84, 608, 522, -395, -1079, -796, -234, -85, -353, -720, -376, 593, 1170, 1061, 902, 1238, 2098, 2730, 2667, 2512, 2558, 2812, 3450, 3527, 2511, 1979, 2344, 2560, 2232, 1648, 1745, 2168, 1443, 537, 955, 1231, 1018, 1521, 1415, 373, 536, 1402, 1197, 278, -299, -321, 60, 622, 579, -382, -1043, -463, 180, 184, -49, -160, 427, 985, 591, 63, -251, -539, -79, 1133, 1519, 1109, 1410, 2328, 2894, 2820, 2683, 2960, 3450, 3693, 3414, 3190, 3588, 4175, 3949, 2995, 2266, 2065, 2527, 2850, 2528, 2059, 1450, 1330, 2054, 2346, 1454, 244, 254, 952, 1026, 779, 580, 765, 1516, 1967, 1961, 2340, 2931, 3325, 3429, 2865, 1918, 2041, 3270, 3622, 3267, 3525, 3700, 3275, 3018, 2905, 2484, 1908, 1654, 1723, 1574, 951, 552, 1472, 2770, 2569, 1265, 281, -206, -769, -1220, -1531, -2078, -2172, -1219, -33, 303, 83, 351, 1069, 1469, 1432, 1588, 1793, 1785, 1819, 1665, 1311, 1560, 2515, 3249, 3373, 3132, 2926, 3217, 3718, 3463, 2677, 2354, 2496, 2263, 1999, 1956, 1623, 1235, 802, 131, -499, -742, -306, 458, 928, 679, 188, 725, 1854, 2127, 1206, 179, 633, 1639, 1376, 1124, 1725, 2339, 3008, 3287, 2717, 2416, 2763, 2514, 1411, 782, 1307, 1944, 2035, 1813, 1505, 1159, 1016, 1616, 2223, 1466, 101, -260, 244, 377, 103, -152, -435, -72, 846, 1025, 387, 74, 595, 1113, 1021, 787, 878, 1545, 2674, 3217, 2482, 1291, 998, 1541, 1740, 1586, 1647, 1940, 1990, 1670, 1762, 2096, 1691, 1403, 2271, 3037, 2972, 2590, 2419, 2785, 3000, 2507, 2007, 2288, 2686, 2327, 1695, 1616, 1968, 1989, 1210, 408, 960, 1973, 2115, 1981, 1852, 1799, 1927, 1604, 877, 702, 840, 563, 752, 1474, 1396, 1083, 1787, 2994, 3606, 3431, 2593, 1702, 2648, 4455, 3995, 2247, 1784, 2425, 2956, 2962, 2494, 2076, 2272, 2386, 1814, 1205, 491, -215, -383, -690, -1496, -1667, -609, 546, 662, -213, -858, -758, -687, -1061, -1420, -1616, -1487, -390, 948, 1467, 1567, 1875, 2323, 2507, 2155, 1845, 2099, 2171, 1705, 1342, 1205, 1372, 1983, 2259, 1893, 1533, 1538, 1689, 1620, 914, -111, -279, 78, 251, 90, -362, 51, 1086, 1118, 522, 755, 1224, 1053, 1086, 1142, 1139, 2012, 2998, 3238, 3246, 3745, 4361, 4249, 4056, 4121, 3767, 3665, 4399, 4807, 4461, 4268, 4252, 4060, 3868, 3607, 3216, 2643, 2075, 2264, 2606, 2259, 1512, 926, 1170, 1473, 816, -273, -376, 747, 1342, 623, 161, 777, 1399, 1532, 1577, 1788, 2017, 2042, 2002, 2070, 2014, 1779, 2079, 3057, 3782, 3505, 2735, 2623, 2586, 1374, 253, 646, 1079, 948, 1074, 1152, 1089, 1509, 2056, 1528, 412, -282, -427, 248, 696, 139, -73, 558, 993, 1422, 1997, 1227, -35, 363, 1638, 2071, 1541, 1243, 1689, 2127, 1942, 1086, 279, 18, 456, 1319, 1693, 2006, 2857, 3429, 3291, 2941, 2550, 2000, 1544, 1659, 1612, 1236, 1786, 2411, 2277, 2163, 1470, 311, 269, 1024, 965, 68, -186, 271, 680, 1009, 1305, 1279, 801, 424, -156, -1213, -1560, -1377, -1232, -1068, -1260, -1353, -987, -640, -357, 64, 409, 928, 2256, 2756, 1271, 367, 1062, 1614, 1624, 1571, 1549, 1982, 3009, 3638, 3150, 2939, 3814, 4240, 3760, 3246, 2508, 1901, 1932, 1895, 1506, 1006, 709, 422, 40, -300, -1071, -2150, -2474, -2294, -2645, -3036, -2646, -1478, -255, 65, -330, -165, 543, 839, 708, -12, -763, 133, 1888, 2154, 1490, 1575, 1803, 1264, 959, 1039, 639, 479, 862, 865, 370, -210, -454, -420, -479, -622, -801, -513, 451, 1409, 1784, 1873, 2427, 3053, 2856, 2466, 2168, 1547, 1467, 2115, 2468, 2519, 2945, 3872, 4148, 3439, 3037, 2959, 2579, 2836, 3655, 3170, 1812, 1581, 1972, 1769, 1072, 180, -45, 454, 225, -581, -659, -253, 281, 1122, 953, -324, -342, 1029, 1759, 1285, 441, 67, 404, 818, 593, 273, 678, 1482, 2066, 2113, 1904, 2171, 2977, 3877, 4004, 2824, 1424, 719, 592, 766, 566, 457, 922, 801, 231, 7, -400, -579, -146, 146, -146, -665, -88, 1495, 2108, 1236, 726, 1404, 1716, 1544, 1868, 1936, 1718, 1886, 2072, 2079, 1853, 1303, 609, 4, -453, -974, -1392, -1559, -1349, -670, -432, -598, -226, 824, 1933, 2101, 1520, 1432, 2024, 2847, 3345, 3702, 4855, 6182, 6438, 5289, 3423, 2026, 1197, 340, -271, -1140, -2596, -3169, -2343, -2210, -3575, -4000, -3246, -3191, -3587, -4205, -4980, -5036, -4467, -4213, -3897, -2721, -1297, -126, 666, 1131, 1494, 2222, 3187, 3116, 2468, 2928, 3362, 2585, 2103, 1533, 125, -274, 281, -383, -2174, -3074, -3086, -2882, -2180, -1887, -2610, -2922, -2028, -918, -433, -470, -839, -1051, -860, -909, -1284, -1431, -935, -529, -854, -921, -362, 447, 1672, 2540, 2198, 1653, 2188, 3049, 2638, 1365, 492, 595, 1292, 1426, 320, -552, 368, 1297, 752, -52, -143, 142, 21, -287, -190, -322, -1086, -1356, -845, -1053, -2075, -2095, -901, 7, 458, 499, 375, 1107, 1610, 389, -1119, -1163, -302, 417, 909, 1240, 1490, 2269, 2921, 2171, 671, -11, 565, 1344, 1351, 472, -92, 674, 1022, 114, -581, -617, -249, 543, 1303, 1159, 415, -50, 35, 24, -834, -1720, -1352, -436, -257, -608, -1479, -2423, -2120, -1023, -510, -581, -676, -711, -387, 309, 273, -342, -185, 765, 743, -584, -996, -127, 524, 381, -650, -1773, -1487, -587, -672, -1765, -2930, -3090, -2619, -2403, -2286, -2111, -1913, -1704, -1824, -2061, -2193, -2256, -2194, -2161, -1974, -1608, -1212, -781, -552, -604, -460, 50, 382, 539, 449, -79, -478, -374, -321, -1098, -2604, -3315, -2687, -2270, -2831, -3578, -3736, -3052, -1780, -1140, -1687, -1961, -1315, -681, -712, -947, -1190, -1312, -421, 897, 1001, 495, 453, 481, 792, 3612, 4426, 5464, 4859, 4171, 4415, 3892, 2620, 2696, 3331, 2491, 1662, 1435, 765, 1129, 1819, 1258, 776, 708, 106, -131, 658, 1321, 1717, 2274, 2572, 2744, 2824, 3231, 4519, 4765, 3222, 2259, 2302, 2215, 1963, 2064, 2350, 2496, 2579, 1666, 861, 1790, 2674, 2278, 1937, 2556, 2599, 1979, 1492, 1027, 826, -142, -1760, -1707, -121, 435, -419, -353, 1156, 1732, 1407, 1628, 2408, 2959, 2260, 1878, 2782, 2745, 1842, 2006, 2602, 2298, 2061, 2826, 3209, 2892, 3064, 2849, 1901, 1766, 1942, 1366, 1238, 1564, 1595, 1781, 1795, 1263, 666, 227, 465, 2166, 3870, 3804, 3541, 3680, 3569, 3460, 3148, 2108, 1487, 1884, 1993, 1380, 852, 1081, 1709, 1615, 1092, 773, 435, 350, 1242, 2534, 2343, 1306, 1819, 3077, 3454, 2993, 2395, 2445, 2577, 2287, 2165, 1880, 1123, 1033, 1755, 2257, 2342, 2583, 2605, 1792, 1115, 1236, 1373, 767, 221, 404, 1048, 1624, 1793, 1098, 13, 270, 1042, 1172, 1200, 492, -345, -39, 212, 202, 793, 952, 935, 1697, 2092, 2239, 2829, 3345, 3126, 2173, 1474, 752, 464, 1869, 3276, 3010, 1781, 666, 777, 2066, 3506, 4116, 2836, 1101, 1309, 2610, 2791, 1804, 991, 1367, 2691, 4024, 4620, 3992, 3263, 3622, 4577, 5331, 5754, 5890, 5419, 4371, 4524, 5840, 6343, 6332, 6465, 5961, 4881, 4870, 5617, 5317, 4692, 4737, 4561, 3977, 3547, 3407, 3257, 2413, 977, 348, 459, 65, -492, -784, -918, -1321, -1741, -1323, -441, -468, -1717, -2455, -1630, -634, -1170, -2551, -2648, -2221, -2808, -3064, -2248, -1787, -1768, -1354, -1390, -1038, 184, -65, -1180, -1706, -1953, -2106, -2397, -2213, -2050, -2978, -3341, -3107, -3199, -2962, -2995, -4033, -5410, -5668, -4336, -3316, -3735, -4501, -4774, -4055, -3465, -3631, -3396, -3183, -3558, -3932, -3854, -3534, -2801, -2204, -3087, -3699, -2853, -2542, -2251, -1736, -2066, -1917, -1729, -2243, -1990, -948, -1110, -2293, -2608, -2284, -2772, -3922, -4362, -4677, -6124, -7373, -7229, -6349, -5305, -4528, -4572, -5247, -5194, -4878, -4989, -4919, -3872, -2196, -2157, -4166, -5525, -4945, -4134, -4383, -5342, -6109, -5705, -5243, -5665, -5890, -5313, -4313, -4033, -5158, -6717, -6649, -5302, -4486, -4248, -4683, -5306, -4991, -4310, -4338, -4658, -4858, -5231, -5990, -6102, -5160, -4490, -4544, -4838, -4770, -4389, -3612, -2391, -2605, -3544, -2725, -1992, -3017, -3922, -3517, -2476, -2103, -2929, -3224, -1929, -1169, -1639, -2475, -3918, -4380, -2890, -2176, -2781, -3189, -3629, -3926, -3826, -3843, -4487, -5905, -6985, -6491, -5448, -5145, -5279, -4481, -2707, -1801, -2612, -3681, -3780, -3136, -2431, -2020, -1501, -685, 23, -235, -1034, -1118, -695, -603, -587, -821, -2281, -3770, -4026, -3704, -3561, -4015, -4074, -3204, -2880, -3308, -3478, -2421, -1290, -1564, -2044, -1874, -2343, -2843, -2358, -1951, -1742, -1345, -1583, -1959, -1463, -1860, -3176, -3266, -2887, -2905, -3090, -4227, -5772, -5773, -4106, -3686, -5829, -8189, -7945, -5659, -5198, -6115, -5841, -5896, -6527, -5481, -4739, -6121, -6706, -6074, -5897, -5771, -5684, -5487, -5409, -6205, -5994, -4649, -4020, -4075, -5142, -6323, -5914, -5350, -5416, -5394, -5581, -5289, -4525, -4793, -4962, -3974, -4036, -5539, -5237, -3528, -3608, -4678, -4684, -4578, -5273, -5092, -4288, -4554, -4862, -4840, -5029, -4634, -4281, -4769, -5060, -4416, -4203, -4873, -4401, -3291, -3648, -4107, -3881, -4006, -3763, -3192, -3891, -4297, -3238, -3604, -5155, -4111, -2590, -3989, -5484, -4695, -3625, -3681, -3255, -2157, -2561, -3774, -3119, -2359, -3209, -3719, -3745, -4317, -4202, -3070, -2933, -4242, -5128, -5011, -4688, -4673, -4688, -4313, -3590, -3077, -2774, -2694, -3479, -3986, -3354, -3097, -3275, -3348, -4053, -4189, -3205, -3082, -4216, -4641, -4017, -3422, -2731, -2464, -2900, -3533, -3856, -3004, -2188, -2693, -3379, -4003, -4728, -4652, -4472, -5026, -4684, -3689, -3717, -3955, -3921, -4253, -4019, -3113, -3201, -3707, -2688, -1646, -2173, -2543, -2220, -2040, -1425, -1404, -3012, -4153, -4185, -4454, -4453, -3535, -3026, -3029, -2476, -1806, -1342, -1920, -3501, -3799, -2676, -2347, -3129, -3871, -4089, -3945, -3778, -2761, -1280, -1168, -1647, -2272, -3417, -3704, -2558, -1982, -3009, -3660, -2879, -1846, -2178, -3551, -3866, -3638, -3671, -2820, -1632, -1448, -1651, -1122, -784, -1858, -2883, -2038, -625, -333, -603, -1224, -2248, -3200, -3487, -2601, -2143, -2482, -2366, -2352, -2418, -2229, -1979, -1654, -1464, -1631, -2293, -2463, -1368, -698, -1979, -3409, -3752, -3890, -3878, -3493, -3156, -3017, -3831, -4505, -2794, -1296, -2526, -3658, -2851, -1697, -1580, -1814, -1729, -1676, -1443, -249, 517, -953, -2967, -2878, -1272, -1007, -2223, -3124, -3599, -4001, -3978, -3474, -3728, -4456, -3944, -2542, -2237, -2330, -1785, -2393, -3392, -2859, -2447, -2674, -1623, -587, -1189, -1637, -1415, -776, 189, -76, -1064, -1173, -734, -131, -330, -1565, -1650, -1046, -570, 769, 1174, -283, -953, -346, 86, -351, -1290, -1558, -1345, -2515, -4186, -3458, -2052, -2057, -2091, -1788, -1883, -1882, -882, -381, -1611, -2220, -1111, -403, -551, -350, 75, 268, 740, 1539, 1720, 1869, 2147, 1625, 708, 591, 635, 23, -19, 616, 593, 201, 147, 450, 958, 0, -2253, -2981, -2239, -2649, -3198, -2569, -2352, -2874, -2727, -1994, -2361, -2365, -521, -862, -3620, -4028, -2582, -1315, -821, -1060, -581, -272, -897, -879, 98, 317, -577, -947, -743, -238, 353, 39, -862, -833, -34, 306, 232, -613, -1669, -1064, -571, -2518, -4121, -2931, -1475, -1305, -2151, -3288, -2303, -381, -539, -1684, -1598, -341, 597, 350, 222, 788, 709, -9, -599, -1090, -1527, -1436, -1672, -2362, -1926, -1316, -1608, -1646, -1416, -2155, -3142, -3006, -2736, -2585, -1877, -1190, -641, 513, 1487, 1169, 502, 1465, 3189, 3271, 2158, 2101, 2494, 1932, 1347, 408, -1463, -2976, -2297, -646, -731, -1287, -1164, -1404, -1916, -2880, -3895, -3880, -2877, -2797, -3427, -1842, -597, -2249, -3197, -2257, -1546, -1604, -1661, -1129, -543, -307, 349, 1175, 1665, 1289, -5, -900, -550, 85, 286, -5, -817, -758, 73, 15, -611, -1057, -1559, -1438, -504, -605, -1530, -1261, 286, 889, -812, -2649, -1800, -242, -1045, -2021, -2057, -1966, -867, 485, 283, -808, -774, -320, -1296, -2145, -2234, -2792, -3002, -2512, -2177, -2041, -1411, -53, 540, -346, -514, 304, 767, 821, 1084, 1316, 432, -626, -789, -967, -1118, -733, -634, -672, 41, 1328, 1521, 212, -335, 290, -21, -1552, -1781, -610, -605, -1182, -118, 166, -1567, -2250, -1494, -1107, -1358, -1433, -732, -620, -1702, -452, 2113, 1357, -859, -1274, -118, 1168, 1358, 778, 117, 136, 1302, 1309, -466, -1832, -1722, -1446, -1775, -1390, -1092, -1704, -2059, -1718, -890, -182, -38, -740, -844, 322, 580, 126, 594, 344, -931, -902, 50, 375, -127, -676, -886, -790, -631, -1052, -1385, -785, -440, -1114, -1789, -1816, -1466, -984, -334, 81, -38, -252, -297, 251, -84, -1006, -41, 217, -1090, -831, 56, -548, -656, 243, -435, -2146, -1662, -524, -1438, -2349, -2240, -2331, -1457, -189, -607, -998, 250, 1764, 1412, 239, 82, -44, -39, 674, 826, 589, 10, -288, 921, 1796, 513, -1179, -828, 192, -523, -824, 219, 281, -928, -1440, -524, -60, -428, -965, -1940, -1236, 541, 560, 203, 1026, 1257, 689, 1038, 1423, 1163, 1528, 2075, 1702, 1502, 1734, 1019, 169, 548, 451, -587, -1176, -1486, -1710, -1332, -557, -781, -1504, -1462, -1156, -1311, -1516, -870, -162, 294, 247, -437, -854, -602, -138, -14, 262, 518, 650, 865, 768, 500, 186, -234, -408, -57, 314, 1094, 2188, 1584, 323, 776, 1887, 2062, 1651, 1626, 1228, -327, -1043, 692, 1949, 1244, 978, 1035, 964, 1329, 1400, 458, -830, -1235, -1462, -1587, -918, -847, -1429, -575, 1042, 1264, 623, 220, 268, -324, -1875, -2674, -2351, -1651, -935, 5, 809, 807, 494, 1293, 1888, 309, -1022, -201, 883, 546, -558, -684, 487, 569, -419, -230, 579, 1501, 2086, 935, -671, -1080, -566, -124, -725, -1008, 332, 1418, 416, -431, 507, 1481, 1637, 779, -55, 570, 1294, 1332, 1105, 647, 787, 1135, 427, -306, 283, 302, -176, 590, 1323, 1289, 1343, 1373, 778, -255, -323, 875, 1489, 612, 142, 1033, 2443, 3529, 3843, 3656, 3359, 2266, 1314, 2695, 3675, 2123, 932, 1534, 1995, 1238, 1080, 1707, 1020, 122, 1081, 1955, 649, -964, -1176, -670, -65, 200, -288, -1081, -741, 547, 633, 62, 659, 2098, 2706, 2073, 2183, 2705, 2311, 1513, 854, 866, 1213, 1452, 1741, 1826, 2154, 2603, 2002, 1166, 1052, 1365, 1290, 674, 890, 1286, 288, -698, 262, 1771, 1727, 764, 365, 1218, 2605, 2752, 1555, 642, 582, 514, 49, -18, 210, -11, -260, -503, -1076, -1498, -1087, -463, -299, 208, 752, 685, 413, -247, -544, -31, -255, -1707, -2433, -1149, -354, -1383, -1699, -1156, -1230, -870, 541, 629, -634, 190, 2269, 2173, 1787, 2805, 3805, 4218, 4045, 3760, 3660, 3183, 2607, 2213, 1318, 180, 189, 1274, 1844, 1740, 1366, 1226, 2337, 3887, 4296, 3402, 2644, 2512, 2325, 2304, 2550, 2655, 2279, 1990, 2882, 3922, 4002, 3948, 3769, 3445, 3118, 2800, 2375, 1768, 2161, 3109, 3129, 3312, 4391, 4849, 4872, 5389, 4713, 3300, 3472, 4059, 3862, 3778, 3626, 3120, 2319, 1631, 2087, 2179, 986, 957, 994, 112, 397, 663, 0, -168, -77, -387, -655, -687, -1027, -2068, -2264, -900, -77, -343, -497, -10, 706, 465, -76, 302, 1149, 1884, 2274, 2351, 2684, 3371, 3637, 3081, 2277, 1678, 1563, 2144, 2448, 2231, 3019, 3376, 2147, 2366, 3725, 3359, 2671, 2945, 2518, 1726, 2182, 2673, 1423, -228, -61, 864, 606, 312, 761, 747, 637, 1215, 1103, 667, 1840, 2509, 1182, 465, 1256, 1416, 1067, 1550, 1901, 1600, 1021, 1207, 2378, 2768, 1565, 1131, 2725, 3629, 3215, 3538, 3523, 2775, 3054, 3617, 3069, 2799, 3479, 3495, 2798, 2701, 3147, 3092, 3260, 4009, 4229, 3654, 3326, 3379, 3051, 2697, 2492, 1531, 230, 141, 640, 851, 1281, 1780, 1845, 2139, 3411, 3199, 894, 692, 2638, 3994, 3839, 2896, 2759, 3283, 3426, 2843, 2385, 2780, 2187, 526, 400, 1438, 2149, 2725, 2891, 2709, 3150, 3029, 1622, 1295, 2866, 3664, 2564, 1537, 1766, 2490, 2393, 1511, 1456, 2625, 2607, 1321, 1497, 2469, 2072, 1543, 2606, 3726, 3274, 2177, 2247, 3360, 3326, 1926, 1447, 2602, 3572, 3326, 2829, 2790, 2730, 2114, 1533, 2104, 3350, 3253, 1833, 892, 1097, 1106, 683, 870, 1438, 1579, 1209, 1730, 3386, 4176, 3483, 2654, 2553, 2561, 2137, 1456, 1404, 2171, 2296, 2629, 3768, 4649, 4910, 4167, 3088, 3037, 3358, 2880, 1642, 931, 1586, 2242, 2515, 3367, 3474, 2117, 1312, 1576, 1540, 1391, 1332, 755, 1010, 2143, 2482, 1732, 1123, 1281, 1084, 248, -18, 371, 858, 1270, 1033, 841, 1576, 2487, 3326, 3416, 2294, 1848, 1916, 594, 108, 1765, 2506, 2185, 2496, 2882, 3589, 4784, 5024, 4147, 3397, 2276, 987, 1023, 2148, 2962, 2631, 2388, 2926, 2867, 3518, 4755, 3493, 1465, 1473, 2211, 2137, 2051, 1896, 2066, 3624, 4456, 3430, 2518, 2809, 3215, 1918, 295, 466, 1276, 1919, 1874, 854, 793, 2445, 3644, 3718, 3728, 3979, 4468, 5050, 4816, 3595, 2507, 2273, 2529, 2216, 1731, 1915, 2000, 2343, 3325, 2631, 750, 169, 503, 1060, 1292, 651, 626, 2125, 3309, 2833, 2134, 2731, 3207, 2363, 1274, 1151, 1988, 2424, 2592, 3647, 3965, 3164, 3286, 3718, 3298, 2615, 2141, 1787, 1851, 2046, 1578, 508, -294, 86, 1368, 2151, 1330, -263, -527, 252, 800, 1127, 432, -58, 1229, 2845, 3178, 2564, 2785, 3815, 3374, 1659, 1188, 2081, 2716, 2276, 1939, 2872, 3541, 3687, 4154, 4030, 3459, 2793, 2295, 3525, 4371, 2705, 1692, 2444, 2815, 2144, 1798, 2212, 2867, 3100, 2550, 1879, 1284, 122, -337, 824, 1190, 34, 71, 1649, 1733, 1001, 1252, 1669, 1663, 1021, 462, 693, 1618, 1923, 1224, 1713, 2804, 2550, 2001, 1870, 2031, 2462, 2107, 1200, 700, 123, -259, 510, 1287, 1553, 2184, 2606, 2456, 1971, 1738, 2006, 1835, 1870, 2022, 1167, 1076, 1330, -62, -348, 1582, 1551, -272, 538, 2921, 3233, 1487, -277, -123, 1222, 1650, 1773, 1602, 636, 430, 699, 332, 134, 761, 1391, 1336, 1345, 1761, 1559, 1275, 2169, 2447, 1447, 1607, 2276, 1706, 1298, 1998, 1976, 59, -1209, -519, 23, 351, 747, 665, 340, -277, -267, 723, 807, -57, 35, 337, 114, 344, 817, 753, 648, 1831, 2910, 1723, 684, 1607, 1239, -317, 226, 1780, 1507, 595, 1378, 1892, 734, 279, 1163, 1494, 1108, 1344, 873, -618, 7, 1471, 756, -131, 719, 1417, 942, 434, 378, 915, 2067, 2123, 582, 8, 1130, 2260, 2405, 2070, 1516, 807, 1022, 1327, -466, -1956, 167, 2128, 709, -543, 153, 948, 987, 687, 654, 1271, 1800, 1477, 1069, 1461, 2384, 2686, 2131, 1315, 612, 1120, 1903, 1450, 1500, 2162, 2248, 2355, 2898, 2843, 1400, 610, 1329, 1211, 237, 115, -26, -1335, -2096, -1053, 149, 342, 477, 419, -525, -1274, -881, -119, 83, -124, -144, 638, 1940, 2654, 2830, 2692, 2000, 1037, 697, 65, -1800, -2428, -1461, -982, -502, 394, 208, -1075, -858, 277, -829, -1982, -1783, -2487, -2967, -1493, 25, -45, -475, -119, 445, -11, -100, 1146, 1316, 19, -509, 224, 747, 312, -720, -1138, -348, 509, -105, -1227, -883, 520, 1075, -49, -1229, -918, -72, -582, -1588, -1243, -1204, -1918, -1239, 29, 291, -470, -1215, -1025, -609, -867, -982, -783, -1288, -2080, -1688, -414, 393, 743, 854, 383, -49, 696, 1397, 801, 1385, 2612, 1723, 1188, 1535, 157, -689, 318, 626, -736, -2025, -1369, -691, -1390, -1002, -3, -865, -2729, -3309, -1797, -169, -550, -1712, -1688, -1085, -1209, -1059, -102, -180, -999, -1885, -2600, -1627, -655, -1373, -1394, -586, -1335, -2479, -2349, -1828, -1724, -1805, -684, 811, 1365, 2089, 2157, 1265, 1103, 946, 277, 395, 660, 976, 1859, 1822, 557, 44, 863, 1182, 346, 412, 1254, 742, -462, -1122, -1126, -157, 302, -247, -340, -685, -1055, 423, 2190, 1888, 411, -830, -1336, -1176, -1410, -1536, -800, -218, 47, -49, -218, 309, 1021, 1365, 809, -1322, -3040, -2260, -632, 14, -512, -669, -171, -287, -58, 65, -1434, -2194, -1276, -1779, -3281, -3106, -2481, -3349, -3564, -1976, -1410, -2311, -2578, -1837, -1388, -1886, -1617, 668, 1531, -798, -2002, -437, 1011, 1261, 672, -124, -411, -713, -1007, -819, -802, -1425, -1763, -845, 36, -770, -1946, -1935, -1178, -965, -1698, -2034, -1819, -2613, -2984, -2111, -2346, -2996, -2335, -2070, -2969, -3634, -3546, -3140, -2256, -1629, -2075, -1716, -1216, -2087, -1824, -686, -532, -18, 191, -1006, -1124, -151, -861, -2016, -1379, -1323, -3483, -4625, -3956, -3701, -3972, -3978, -3955, -4419, -4943, -5055, -4664, -4071, -3975, -4046, -3855, -3482, -3024, -2765, -2477, -2099, -2591, -3172, -3064, -3723, -4090, -3393, -3747, -5110, -5104, -3996, -3694, -3432, -2220, -1785, -2705, -2251, -671, -970, -2126, -2804, -3425, -3616, -3039, -2458, -2932, -3394, -2796, -2126, -2230, -2346, -1965, -2224, -2159, -850, -986, -2549, -3415, -3597, -3718, -3662, -2972, -2338, -2721, -2757, -2023, -1947, -1762, -752, -1355, -2960, -2385, -1332, -1705, -1293, -722, -1750, -2024, -1245, -1570, -2361, -1895, -1117, -2317, -3757, -2875, -2014, -2513, -2709, -2702, -2212, -657, -772, -2685, -3261, -3674, -4647, -4182, -3038, -2638, -2721, -2666, -2201, -2100, -1833, -814, -372, -928, -975, -545, -855, -873, -834, -1985, -2458, -1100, -710, -1329, -1725, -1983, -849, -504, -2167, -2628, -2152, -1759, -1070, -1042, -1406, -1200, -1604, -2831, -3759, -4100, -3492, -2919, -3567, -3814, -2889, -3058, -4105, -3993, -2585, -1564, -2426, -3250, -2954, -3297, -3245, -2095, -1811, -1674, -1011, -1468, -2160, -1880, -1594, -890, -1483, -4427, -5097, -2762, -1907, -2779, -3304, -3383, -3362, -3262, -2381, -1507, -2070, -2961, -3570, -3933, -3559, -3971, -5335, -5014, -3682, -3598, -3552, -2488, -2063, -2638, -3355, -3367, -2376, -1771, -2291, -3224, -3665, -3004, -1601, -1097, -2120, -2785, -2682, -2813, -2942, -3495, -4169, -3853, -3143, -2284, -2115, -3030, -3054, -2394, -2601, -3186, -3510, -3104, -2012, -1996, -2864, -3025, -3144, -3241, -2205, -1584, -2748, -3212, -1649, -865, -1708, -2618, -2744, -2027, -1545, -2434, -3768, -3613, -2530, -2264, -2639, -2535, -1820, -1185, -435, -53, -506, -718, -1011, -1641, -1886, -2194, -2496, -2238, -1599, -1362, -2101, -2751, -2719, -2570, -2074, -2424, -3843, -4088, -3446, -3117, -2941, -2891, -2763, -1563, 3, -489, -2559, -3981, -4133, -4334, -4933, -4377, -3119, -2302, -1321, -174, 151, 306, 589, -353, -1515, -1847, -2361, -2309, -1784, -1995, -1767, -856, -1097, -1890, -1795, -1732, -1732, -1590, -1989, -2465, -2608, -2693, -2569, -1857, -1533, -1458, -863, -713, -1138, -1066, -1157, -2116, -2140, -1372, -1387, -1612, -1709, -1446, -691, -292, -1245, -2487, -1713, -185, -474, -1024, -341, -38, -807, -1440, -1529, -1331, -1387, -2013, -2761, -3459, -3475, -2077, -1198, -2234, -2869, -1727, -1433, -2743, -3522, -3152, -3008, -3808, -3573, -2555, -2345, -2177, -1773, -1887, -2695, -2839, -1656, -1021, -2883, -4697, -3434, -1633, -1412, -966, 361, 670, -341, -1623, -2437, -2066, -1281, -1174, -1599, -1880, -1614, -858, -255, -386, -1249, -2190, -2091, -749, 183, -919, -2476, -1945, 18, 532, -749, -1537, -1558, -1482, -1047, -545, -70, 708, 697, -452, -1460, -1872, -2266, -2629, -2433, -2550, -2863, -2233, -1508, -1155, -518, 425, 564, 94, 235, 118, -882, -1361, -925, -535, -644, -724, -986, -1632, -1964, -1865, -730, 483, -544, -1793, -982, -619, -1634, -1502, -1394, -2582, -2370, -1169, -1663, -1713, -216, -1376, -4404, -4808, -3488, -2005, -591, -158, 236, 1528, 2379, 1697, 572, -11, -297, -67, 853, 850, -49, -160, -101, -71, 1023, 2014, 2371, 2599, 2036, 1228, 977, 214, -561, 444, 1384, 238, -1416, -946, 773, 651, -471, -782, -973, -1431, -1253, -1038, -1401, -2078, -3309, -3809, -2794, -2412, -3252, -4066, -4252, -3325, -2559, -2716, -2418, -1171, -1089, -2069, -1724, -742, -518, -332, 135, 333, 594, 799, 117, -671, -676, -808, -1046, -1503, -2150, -2494, -2325, -1443, -806, -1395, -1973, -1482, -995, -1410, -2020, -1344, -783, -1796, -2345, -2025, -2417, -2770, -2356, -2364, -2777, -1705, 32, -13, -991, -1341, -1593, -1805, -1548, -1724, -2339, -2893, -3162, -2764, -2513, -2684, -2347, -1157, -744, -2096, -2807, -2317, -2049, -1241, 119, 155, -247, 626, 1556, 1339, 1102, 1016, 585, 193, -535, -1423, -1264, -389, -329, -507, -315, -1185, -2553, -2389, -2095, -2210, -1813, -2342, -3351, -3169, -2794, -3432, -3806, -2945, -2047, -1082, -133, -294, -675, -595, -428, -50, -126, -549, 50, 682, 571, 760, 1280, 1527, 857, -102, 372, 1013, 312, -70, 804, 969, -618, -1609, -1477, -2327, -3009, -2129, -1485, -756, 1243, 2005, 607, -120, 657, 1674, 1894, 1844, 2424, 3305, 3743, 3635, 3288, 2840, 2053, 881, 587, 1517, 1395, -565, -2316, -2725, -2479, -2913, -3667, -3413, -3432, -3659, -2690, -2458, -2977, -2521, -1623, -294, 1414, 1955, 1291, 722, 754, 1340, 1800, 1766, 1627, 2175, 3075, 2934, 1954, 1117, 1093, 896, -322, -1264, -2219, -3120, -2680, -2144, -2763, -3377, -2875, -1837, -787, -409, -1091, -1358, -105, 1249, 1412, 1002, 1085, 1187, 572, 327, 515, 570, 366, 480, 1695, 2798, 2638, 2219, 3129, 4041, 2990, 1139, -176, -525, 76, 288, -358, -615, -915, -1798, -2148, -2209, -1783, -692, -660, -1605, -2538, -2939, -2419, -3051, -4091, -2832, -1493, -1181, -415, -327, -1283, -1606, -1464, -1445, -385, 911, 449, -1170, -2341, -2748, -3023, -3022, -2618, -2037, -1823, -2286, -2728, -2482, -2000, -1945, -1833, -1922, -2894, -3639, -3482, -3208, -3471, -4334, -4252, -2593, -2181, -3050, -2533, -1206, -369, 403, 835, -168, -1566, -1502, -1071, -1711, -1797, -556, -636, -2054, -1802, -1305, -2395, -2076, -1306, -2679, -2905, -690, 485, 198, 344, 508, 23, 631, 2478, 2586, 574, -820, -502, 877, 1759, 527, -1247, -1793, -1126, -269, -1338, -2639, -2758, -3238, -4273, -4945, -4376, -3439, -3429, -3336, -2340, -1568, -1700, -1807, -885, -162, 56, 1455, 2656, 2031, 2308, 3348, 1826, -271, 894, 2804, 1980, 195, -149, 353, -53, -1233, -2040, -2353, -2176, -2093, -2697, -2939, -1784, -268, -469, -1522, -768, 873, 362, -547, 144, 17, -1342, -702, 967, 1042, 1112, 1948, 445, -990, -2855, -2167, -384, -1682, -3608, -3462, -3255, -2836, -1943, -1916, -312, 2929, 2584, -436, -1730, -1414, -664, 533, 957, 238, -506, -616, 567, 1370, -1, -179, 1087, 508, -500, 1366, 4036, 2716, -275, 227, 1088, -613, -1669, -894, 631, 960, 200, 211, 1436, 2642, 2220, 1958, 2114, -68, -2284, -2298, -1285, 675, 1112, -1676, -2551, 240, 808, -1540, -1832, -1004, -2123, -3832, -2899, 27, 952, -409, -688, 1060, 926, -682, 456, 1516, 499, 172, -21, -152, 1826, 4287, 3782, 1669, 795, 83, -397, 629, 1345, 666, 852, 1377, 1630, 3813, 4139, 672, -1516, -1090, 524, 1195, 382, -374, -643, -951, -752, -506, -257, 705, 445, -1568, -2097, -410, 1168, 1685, 2025, 1693, 179, -120, 759, 312, -1006, -1547, -1066, -125, -55, -405, -628, -1204, -1361, -589, 102, -437, -1208, -832, -293, 954, 3355, 2796, -813, -2241, -656, 1128, 1626, 718, -672, -2189, -2530, -1018, 129, -145, -1505, -2488, -632, 2016, 1528, -407, -1303, -1689, -505, 2315, 1865, -1248, -1586, -952, -1889, -1709, -197, 1272, 2396, 356, -3242, -2282, 1044, 1559, 1929, 3906, 3367, 924, 2221, 6368, 6993, 4164, 2878, 3404, 2800, 1071, 27, 115, -39, -897, -904, -135, 512, 1028, 961, 705, 981, 676, -165, 235, 1705, 1508, 1095, 2193, 2292, 1850, 2525, 3189, 2892, 1432, 955, 3090, 4640, 3044, -166, -1505, 560, 2864, 2358, 335, -293, 536, 449, 121, 460, 178, 596, 1659, 619, -482, 55, 505, 1068, 1495, 557, -515, -459, 118, -124, -182, 1926, 4388, 4852, 5430, 6095, 4599, 3249, 3041, 2328, 555, -678, -629, -1162, -1129, 922, 1873, 978, -475, -1641, -1410, -498, 871, 1066, -1319, -2482, -941, 1376, 3127, 2034, -52, 222, 1427, 2130, 1913, 1079, 836, 1045, 216, -878, -327, 183, -129, -101, -1465, -3140, -2871, -2726, -2458, -1414, -1753, -2587, -1043, 946, 108, -1871, -1659, -234, -76, -718, -1287, -1238, 1330, 3284, 768, -1605, -333, 1576, 948, -819, -1670, -1682, -1232, -1847, -2778, -1305, 956, 1015, -576, -1484, -465, 1509, 1865, 938, 1273, 1518, 390, -454, -581, 240, 2534, 2635, -433, -2090, -857, 861, 904, 703, 503, -197, -562, -392, 1088, 2349, 1359, 56, 32, 567, 902, 1050, 1733, 1769, 54, -555, 953, 1153, 833, 1887, 2085, 1291, 797, -175, 87, 1452, -290, -2700, -1780, 252, 2072, 2305, -423, -2386, -2542, -2544, -1234, 578, 305, -1538, -2149, -677, 904, 834, -586, -1167, 939, 2832, 1340, -245, 1294, 2990, 2868, 1682, -350, -2213, -2295, -1197, -518, 118, 45, -390, 345, 1545, 490, -2123, -1650, 1011, 1765, 509, -224, 1612, 3823, 3255, 1451, 1542, 2992, 2192, 381, 369, 225, 353, 2040, 2057, 377, 469, 2078, 1470, -63, 140, 338, 143, -531, -777, 1230, 1826, 684, 1717, 2274, 305, -1632, -2361, -1985, 131, 1475, -281, -1495, -645, 123, 406, -141, -1885, -1919, 1038, 1587, -1527, -3843, -4300, -3329, -2641, -3826, -4212, -3738, -4660, -5938, -5698, -4084, -3280, -3793, -3334, -2681, -3223, -2283, -371, -508, -988, -1017, -2682, -2432, 1139, 1044, -2408, -2657, -1256, -1785, -1554, 28, -833, -2479, -1404, 420, 260, -927, -1768, -1541, -653, -170, -778, -1778, -1671, -1876, -981, 2334, 2391, -163, -525, -1116, -2781, -628, 2022, 347, 88, 1883, -324, -3396, -1932, -405, -1227, -465, 1324, 844, -991, -1067, 16, -509, -1609, -1402, -473, -4, 232, 675, 352, -531, 126, 2108, 1949, -327, -1016, -593, -1230, -2278, -2122, -680, 1546, 3377, 2823, 1123, 1155, 1638, 549, -682, -831, 9, 2268, 3582, 2819, 3223, 3774, 1809, 306, 620, 1578, 2771, 1818, -197, 218, 1261, 2074, 3928, 4200, 2482, 1808, 1307, 312, 579, 1359, 1490, 755, -417, -341, 116, 7, 47, 4, 767, 2298, 2368, 915, -1655, -2920, -400, 2651, 3005, 1897, 770, -473, -878, -223, 135, -99, -757, 173, 2658, 3113, 1629, 952, 1441, 1378, 410, 510, 1892, 1679, -625, -1420, -440, 464, 1169, 881, -441, -698, 722, 653, -1351, -2276, -1953, -1332, -997, -449, 1039, 756, -1358, -1422, 507, 1458, 1475, 2959, 5294, 4849, 1886, 1015, 2357, 2797, 2352, 2104, 1665, 203, -783, -74, 1086, 1260, 162, 411, 1810, 1241, 606, 1487, 2077, 1611, -473, -2995, -1947, 241, -981, -2579, -2102, -1395, -1150, -963, 809, 3438, 1389, -2427, -825, 1961, 1104, -512, -284, 589, 1649, 2297, 1285, -214, -1127, -454, 2153, 3048, 995, 245, 1321, 1344, 853, 122, -1158, -1540, -186, 1541, 1894, 1209, 965, 1089, 947, 839, 1037, 1413, 1647, 984, -842, -1889, -922, -262, -325, -564, -1132, -27, 2252, 2657, 958, -66, 1256, 3229, 3297, 2365, 2188, 2133, 2909, 4148, 3531, 2490, 1434, 480, 514, -325, -1023, 1833, 4170, 1840, -383, -298, -155, 634, 2152, 1393, -1467, -1240, 3450, 6097, 3576, 1054, 1763, 2313, 1073, 1556, 3291, 3237, 2758, 2841, 2420, 1892, 2572, 3009, 2538, 1829, 640, -161, 501, 1266, 1361, 810, -1127, -1338, 2233, 3742, 261, -1457, -673, -1272, -858, 473, 328, 424, 1668, 1067, -1463, -723, 2865, 3722, 2032, -1, -569, 318, -106, -880, -267, 55, -1325, -1609, 679, 1466, 196, -210, 230, 633, 1484, 3547, 3992, 1417, -757, -552, 724, 310, -770, 1296, 2871, 331, -2110, -2271, -1058, 1163, 451, -3497, -3849, -204, 1517, -190, -723, 1353, 2437, 1982, 1939, 2202, 2113, 1521, 887, -346, -2078, -2439, -2247, -2728, -2844, -2735, -4163, -5296, -3521, -1553, -1366, -1403, -480, 725, 662, -581, -642, 1650, 4873, 4504, 485, -740, 1956, 3448, 2819, 2492, 2106, 1706, 2055, 2873, 1456, -1410, -1394, 164, 589, 696, 1442, 2272, 2395, 1740, -364, -622, 1287, -478, -3306, -2236, -357, -741, -2751, -3396, -1864, -900, -1346, -1470, -836, -363, -1278, -2215, 84, 3261, 2709, -58, -1939, -1809, -403, 494, 1805, 1937, -63, -373, 835, 816, 672, 1870, 2738, 1863, 79, 67, 2352, 3483, 1853, 650, 1895, 2192, 400, -407, -1266, -3028, -2030, -163, -1491, -2838, -1685, -1514, -2486, -2123, -1825, -2303, -1508, 19, -161, -633, 834, 2119, 914, 214, 2003, 3163, 1537, -1072, -1948, -1343, -585, 340, 508, -421, -1098, -793, 489, 645, -889, -741, 1332, 2215, 1216, 531, 311, -816, -1286, -1440, -2788, -3233, -1903, -75, 875, -205, -1368, -619, 734, 2767, 4177, 1653, -527, 1639, 3614, 3101, 2083, 933, -484, -828, 709, 936, -1505, -1527, 239, -857, -3098, -3030, -1046, -619, -1777, -860, 2468, 2444, -2111, -3653, -1416, 142, 883, 1529, 1135, -302, -1476, -1850, -1478, -818, -1643, -3270, -2559, -540, -463, -2261, -3156, -2362, -1726, -1847, -1754, -1104, 85, 1610, 2362, 2385, 2378, 2129, 2168, 3376, 3927, 2267, 2226, 1849, -2127, -2916, -341, -885, -2121, -946, -692, -1861, -1215, 1476, 1368, -1528, -1337, 1351, 3295, 3752, 1353, -1133, -692, 705, 354, -1343, -864, 1345, 1446, -170, -929, -311, 369, -568, -1350, -613, -788, -2339, -1562, 1488, 1713, -378, -697, -649, -1243, -1242, -1221, -1398, -2075, -2436, -1631, -532, 179, -368, -1468, -2069, -1918, -253, 1934, 1873, -232, -1120, 525, 2147, 1317, 153, 477, 493, -194, -774, -1972, -3171, -3357, -3304, -2837, -1326, -765, -2488, -3435, -2153, -1187, -1148, -265, -18, -1075, -922, -602, -947, -397, 636, 773, 720, 2064, 3089, 1618, -216, -58, 887, 707, -312, -125, 894, -577, -2685, -2965, -2867, -2484, -1556, -1282, -1506, -1194, -717, -706, 229, 3123, 5175, 2858, -405, -582, 343, 1175, 1627, 333, -1846, -1705, 506, 237, -2098, -3708, -4070, -1679, 754, -995, -2994, -2409, -2905, -3718, -2622, -1350, -1154, -1042, -312, 348, 594, 207, -267, 90, 679, -574, -2357, -732, 1071, -638, -2529, -2323, -1546, -1209, -1447, -1506, -1092, -239, 224, -1318, -3031, -2868, -1904, -1577, -1834, -1963, -1145, -561, -644, -130, 80, -716, -2448, -4380, -4829, -3695, -2669, -3167, -3387, -2408, -2611, -3275, -2606, -1976, -2077, -2888, -4423, -3790, -1847, -1765, -1019, 145, -399, -617, -388, 40, 525, -423, -724, 1934, 2893, -171, -2173, -983, 1259, 1519, -377, -233, 868, -698, -1432, 1215, 2449, 151, -489, 1012, -531, -2792, -1649, -494, -2550, -5094, -4220, -1813, -1634, -2824, -3826, -4730, -4664, -2056, -103, -2596, -4649, -3362, -2833, -4098, -4027, -1348, 89, -1118, -1950, -1722, -1880, -936, 607, 284, 466, 1620, 891, -665, 45, 2294, 2529, 210, -1516, -1314, -1753, -2704, -1350, -52, -1944, -4042, -3153, -745, 656, -18, -1497, -1207, 515, 552, -230, -81, -1245, -2942, -2814, -2346, -3649, -4543, -3190, -1884, -2048, -1959, -858, -5, -72, -865, -1814, -1507, -1364, -2813, -3407, -1872, -1055, -3441, -5915, -5151, -4006, -4511, -4739, -4410, -3810, -1141, 1716, 247, -3115, -2953, -1403, -2257, -3338, -2877, -2099, -1667, -1268, -1193, -1057, 149, 1662, 1067, 497, 1901, 2382, 1387, 993, 1542, 1984, 568, -1866, -1064, 837, -192, -2444, -3342, -1939, -1079, -1168, -312, -1505, -3709, -3696, -2720, -2007, -2367, -3168, -3312, -2833, -1545, -834, -85, 2000, 1310, -1356, -1537, -1790, -3443, -2466, 222, 789, 1196, 2387, 1700, -484, -1072, 425, 1191, -598, -2393, -2362, -2388, -1658, -420, -1364, -2847, -2798, -3053, -4111, -4680, -4466, -3659, -2831, -1933, -1487, -2209, -2513, -2094, -2240, -3088, -3238, -2047, -1291, -1230, -394, 1380, 2284, 1624, 772, 265, 168, 875, 2257, 2417, 1240, 488, 586, 1055, 1344, 2362, 3531, 2494, 860, 877, -103, -1787, -1416, -1139, -2665, -3725, -2409, -1643, -3209, -3541, -2052, -2192, -3319, -2643, -2588, -4403, -4471, -3388, -4229, -4306, -2040, -505, -583, -706, -483, 295, 1032, -716, -3086, -2776, -2208, -1971, 707, 2539, 756, -885, -1085, -1643, -1196, -195, -886, -2032, -1492, -474, -610, 475, 2691, 1831, -133, 947, 2132, 1151, -183, -369, -279, -861, -925, -134, -130, -651, -1323, -2481, -2761, -2613, -2487, -1358, -445, -1649, -3272, -2743, -435, 674, -304, -2303, -3656, -2981, -1804, -1683, -1940, -1592, -2003, -3464, -3472, -2390, -2373, -2191, -1562, -1799, -1787, -948, -526, 7, 1356, 1399, -480, -816, 170, -703, -2031, -2735, -3530, -3683, -3882, -4382, -3697, -2862, -3352, -3792, -3497, -3134, -2977, -2309, -504, 694, 345, -1459, -2684, -1183, 255, 10, -1220, -2783, -3150, -2789, -1212, 791, -194, -2725, -4436, -4839, -3304, -1752, -1968, -2789, -2387, -1367, -2292, -2776, -490, 275, -2383, -3836, -1922, -1131, -2574, -2526, -580, 1237, 465, -2053, -1568, -829, -2267, -2224, -739, 270, 698, 647, 682, 1425, 2723, 3033, 1666, -58, -1257, -2990, -4113, -2197, -52, -1205, -2728, -2975, -2878, -1317, -813, -2564, -2925, -2231, -3492, -5539, -5290, -2159, -369, -2163, -4004, -3656, -2121, -1295, -1635, -1265, -876, -2109, -2311, -907, 298, 1867, 1402, -975, -1948, -2039, -469, 1997, 888, -957, 467, 425, -1712, -988, -66, -807, -1217, -1652, -2018, -1675, -1005, -887, -2102, -3131, -1781, -27, -527, -1532, -611, -347, -300, 1225, 336, -1242, -397, -380, -1790, -1725, 452, 2015, 1338, -855, -2839, -3338, -2553, -2286, -2816, -2503, -2799, -3920, -3656, -2986, -2796, -2193, -1487, -849, -1011, -2162, -2030, -558, -18, -280, -1853, -4875, -5359, -3242, -2228, -2878, -3472, -2935, -2309, -2818, -3999, -3814, -1368, 805, 515, -444, 1451, 4016, 2735, 763, 1098, 550, -629, 594, 1382, -347, -1617, -2684, -4102, -4178, -3642, -4318, -5345, -4944, -3869, -3633, -3168, -2410, -2630, -2376, -1572, -2488, -3853, -3786, -3350, -2239, -1103, -1877, -3678, -4419, -2941, -2526, -4892, -5267, -2792, -1165, -1461, -2271, -1408, 360, 1547, 2168, 1541, 1162, 2364, 2905, 2745, 3517, 2451, -302, -538, 249, -697, -1562, -544, 633, 431, -66, -361, -1034, -1039, -463, 347, 1301, 553, -573, -22, -213, -1429, -1067, -983, -1541, -687, 28, -760, -1358, -227, 514, -647, -1445, -1227, -918, -301, -59, -487, -1108, -2048, -1774, 528, 2429, 2609, 2124, 1944, 2892, 2901, 1603, 1263, 973, 971, 1939, 1565, -472, -2212, -2415, -1075, -697, -989, 726, 1082, -1687, -1421, 2557, 2524, -1355, -2375, -190, 1587, 1910, 1625, 1525, 1478, 1701, 2148, 1551, 801, 1423, 2119, 589, -2183, -2373, -171, 417, -39, 1022, 1833, 2442, 4682, 5790, 3999, 2828, 3376, 2787, 1210, 569, -62, -683, 154, 386, -362, -615, -766, -236, 859, -203, -2138, -728, 563, -752, -605, 724, 378, -539, 233, 743, -232, -524, 404, 393, 272, 1641, 2396, 1527, 1601, 2948, 2308, 750, 1721, 3831, 4065, 3450, 2983, 751, -867, 342, 717, -1109, -2138, -1022, 281, 230, -369, 866, 3324, 2975, 1194, 2179, 4028, 3507, 2489, 1931, 287, -384, 865, 1108, 43, 116, 1973, 1771, -1578, -2325, 118, 954, -406, -1007, 27, 1268, 2314, 2928, 3246, 4210, 4540, 3213, 1409, 315, 623, 1820, 2364, 1651, 2191, 3345, 2073, 503, 187, 906, 1713, 1950, 2271, 1806, 511, 168, 546, 660, 1046, 2620, 2578, 314, -230, 800, 1307, 1118, 806, 1290, 1130, -171, -397, 218, 577, 1164, 1777, 1466, 1022, 1088, 564, -413, 135, 757, -315, -1204, -1159, -625, -1010, -3077, -3247, -1149, -1718, -2823, 379, 2118, -259, -179, 2595, 1782, -939, -200, 2218, 3045, 2605, 1478, -560, -1967, -1477, 422, 2052, 1978, 1113, 1436, 3085, 3707, 1698, -213, 412, 1415, 904, -284, -1336, -982, 442, -33, -1469, -1240, -635, -1046, -1578, -1049, -544, -652, -400, 188, 772, 1006, 892, 1357, 1487, 784, 528, 1558, 2161, 384, -1095, -576, 97, 1575, 3651, 3566, 2713, 2928, 976, -532, 979, 1169, 1322, 2906, 1497, -1554, -1283, 1148, 1833, 917, 1433, 2438, 739, -1380, -717, 1267, 2222, 1590, 43, -693, 352, 922, 305, 1141, 3239, 2646, 133, -441, 1257, 1581, -1813, -3501, -1171, -628, -3124, -2363, 503, 756, -34, -493, -280, 569, 1528, 1850, 1302, 1191, 1660, 840, 194, 1639, 2031, 1128, 710, 239, 1460, 3931, 3873, 2531, 2551, 2804, 1704, 74, 691, 2780, 3280, 2047, 189, -345, 1279, 2403, 2308, 2758, 2940, 1881, 615, 1736, 4651, 4083, 1169, 1175, 2961, 4925, 6182, 4594, 2883, 3701, 4089, 2440, 777, 2, 1381, 4022, 3452, 1595, 1876, 2239, 2316, 3180, 3441, 2953, 4092, 6451, 4508, -640, -1545, 615, 521, -481, 688, 1310, -127, 13, 1906, 1577, -455, -135, 2434, 3666, 2370, 2004, 4092, 4961, 3582, 2405, 1520, 1137, 2298, 2975, 1687, 323, -349, -654, 513, 962, -1235, -2036, 356, 2428, 2793, 2868, 2803, 2880, 3394, 4136, 4684, 3963, 2288, 505, -662, -1648, -2844, -2263, -688, -1114, -2265, -2662, -2276, -340, 1159, 866, 450, -121, -273, 1700, 2778, 1949, 2992, 4212, 3290, 2514, 2040, 1035, 1224, 2467, 1134, -1703, -2496, -2443, -1968, -197, 702, 1291, 3285, 3171, 871, 1006, 3439, 4621, 3394, 2844, 3251, 2810, 2373, 2676, 2672, 1991, 1861, 1482, 322, 19, -145, -646, -738, -334, 105, 477, 1696, 3375, 3284, 1214, 205, 1692, 3074, 2164, 259, -683, 145, 2850, 3886, 1322, -175, 804, 814, 377, 2041, 2532, -615, -1761, 1279, 2695, 716, -41, 1162, 1167, 54, 61, 888, 1351, 1411, 587, -890, 49, 1933, 598, -741, 740, 1375, 218, 160, 1092, 1974, 2155, 2063, 1268, -873, -1437, 120, 300, -296, 1491, 4258, 4822, 3010, 223, -690, 326, 109, -237, 362, 677, 1326, 1516, 686, 899, 2430, 4167, 4342, 2813, 2317, 2997, 2768, 2239, 2432, 2263, 1811, 2304, 2126, 201, 476, 2210, 1741, 739, -181, -49, 806, 1212, 2272, 1571, -1169, -1337, 547, 243, -994, 208, 1817, 1832, 1138, 85, -698, -465, -91, -333, -753, -844, -1156, -1038, 728, 2162, 2178, 2090, 1919, 1156, 562, 465, 889, 1854, 2419, 2959, 3816, 2724, 1757, 3799, 4162, 1550, 52, 233, 559, 634, 933, 1821, 2246, 1702, 1122, 1174, 1530, 1712, 1645, 1942, 1864, -190, -1912, -472, 962, -235, -962, 107, 1304, 1390, 664, 315, 292, 1639, 4163, 4678, 2884, 1054, 457, 398, 731, 1585, 1834, 1882, 1843, 1021, -563, -2509, -2096, 921, 1400, -234, 5, 936, 1827, 2153, 1066, 344, 779, 1446, 1860, 1536, 886, 1481, 2440, 2631, 2245, 1578, 880, 586, 474, -264, -520, 311, 682, 24, 32, 1453, 3473, 5527, 6137, 4416, 2964, 2922, 2918, 2665, 1728, 80, -478, 118, 350, 124, -265, 88, 1788, 2276, 266, -1354, -1412, -605, 717, 1662, 1782, 1109, 2210, 4885, 4812, 2268, 851, 1404, 1550, 1153, 1370, 1307, 736, 426, 1229, 2063, 903, 62, 1837, 2969, 1948, 1707, 2275, 1583, 994, 1484, 2581, 2441, 639, -214, 572, 1300, 1250, 2198, 2223, -6, -926, 22, 824, 1114, 2088, 2423, 1044, -39, -349, -8, 1648, 2036, -196, -69, 2164, 1809, 862, 1244, 454, -694, -160, 71, 724, 2677, 2099, -178, 226, 1058, -532, -1792, -156, 1932, 1648, 526, 346, 390, -146, -479, -328, -729, -1278, -66, 816, -1529, -2385, 6, 351, -1161, -894, 173, -510, -1406, -1058, -806, -933, -384, 978, 847, -1184, -2345, 259, 3510, 2517, -91, -317, 543, 672, 426, -284, -587, -773, -1803, -1670, -836, -726, -418, -438, -1148, -1129, 458, 2379, 3359, 4270, 4155, 1826, 459, 1842, 3682, 2322, -352, 351, 2947, 4045, 2951, 1425, 1617, 2817, 2902, 3073, 4168, 3603, 1611, 827, 317, -1014, 112, 3364, 3663, 2520, 3402, 3793, 2352, 1212, 1093, 639, -433, -569, -78, -671, -697, 741, 190, -1004, 62, 972, 2115, 2529, -411, -1551, 926, 1815, 822, 325, -29, 1068, 2263, 952, 325, 1370, -155, -3457, -2401, 1482, 1232, -1228, -1730, -1429, -142, 2093, 3088, 2962, 2866, 1892, 659, 1976, 3352, 491, -2079, -1417, -504, 1298, 3601, 1601, -2053, -2559, -1231, -433, -1557, -2774, -2225, -2949, -6044, -8143, -7704, -5445, -4674, -5934, -6344, -5981, -5761, -5483, -5222, -5435, -5569, -4679, -2349, -392, -1374, -4020, -4309, -1748, 1051, 859, -1410, -1543, -298, 796, 1845, 2497, 2776, 2584, 2273, 2921, 4367, 4053, 1783, 566, 1128, 1713, 2087, 2529, 1754, 930, 2390, 3491, 2552, 1338, 657, -228, -1215, -2413, -3769, -3672, -3369, -3824, -3741, -3385, -3815, -4456, -4692, -4458, -4231, -4494, -3917, -3020, -3065, -1955, -193, 557, 1796, 2514, 1165, -312, -789, -750, 236, 514, -815, -1313, -1365, -1690, -2021, -1830, 312, 2008, 2337, 2935, 2812, 2009, 1230, 1124, 1569, 1108, 969, 444, -1311, -1510, -1207, -2604, -3435, -3021, -3215, -3048, -2549, -3077, -2630, -1160, -2040, -3459, -3332, -2798, -925, 920, -62, -1396, -557, 341, 112, 279, 411, -203, -517, -348, 270, 1475, 996, -824, -622, 781, 927, 1342, 3807, 4672, 2595, 2197, 3835, 3227, 910, -621, -1826, -3627, -3893, -2018, -2282, -4227, -4736, -4416, -3681, -2193, -876, -698, 487, 2946, 3372, 2159, 1941, 3351, 4712, 3854, 1703, 775, 299, -1202, -2120, -1754, -1036, -1811, -4453, -5392, -4252, -3072, -1241, 554, 1172, 1325, 1341, 1855, 2350, 1162, 433, 1848, 3333, 3875, 3324, 3122, 3193, 2076, 2019, 2787, 1437, -367, -311, -896, -2749, -2256, -81, 169, 19, 913, 217, -1351, -216, 2670, 2881, 121, -1210, -256, 545, -436, -2542, -3431, -1884, -693, -2212, -4273, -5285, -5279, -3697, -1693, -719, -1041, -3111, -4874, -5243, -4410, -4376, -7028, -8327, -6546, -5104, -5300, -5457, -4260, -1947, 194, 874, -702, -2217, -2057, -2242, -2469, -1430, -651, -1335, -1948, -2057, -1434, 470, 1350, 431, -667, -358, 817, 1000, 1127, 1620, 1176, 1044, 2012, 1695, 644, 626, 224, -2163, -4302, -2912, -523, -176, -922, -1567, -1643, -1518, -983, -1054, -2675, -3667, -3210, -2000, -1613, -3523, -4368, -3218, -2594, -3303, -5005, -4626, -2921, -3148, -3693, -3107, -2267, -1703, -1404, -1412, -1636, -1877, -1218, -379, -1399, -2272, -1182, -782, -1642, -1084, -532, -924, -392, -1222, -2262, 531, 4042, 3649, 1158, 410, 1421, 2255, 3144, 3385, 1124, -139, 1155, 1315, -130, -943, -1251, -1611, -1327, -663, -1549, -2678, -285, 1237, -1905, -5150, -5372, -3575, -2983, -3349, -1673, 804, 875, 241, 2099, 3991, 2722, 1056, 1578, 2398, 2554, 2397, 66, -2167, -406, 1970, 1426, 229, -655, -1387, -636, 376, -253, -1047, -639, -484, -907, -1299, -1970, -2379, -1846, -1203, -708, -124, -265, -770, -587, -978, -1162, 851, 2182, -606, -3224, -2107, -339, -92, -3769, -3994, -5438, -4990, -3269, -2710, -2730, -2543, -2245, -2330, -3214, -2908, -1893, -2332, -2691, -1876, -1383, -1826, -1626, -1104, -1271, -1934, -2828, -2638, -1736, -1796, -1622, -848, -428, -381, 175, 48, -2779, -4849, -3734, -3128, -3949, -3786, -3183, -2858, -2764, -2947, -3127, -3594, -3875, -3346, -2721, -3003, -3557, -2137, -353, -385, -886, -783, -620, -850, -1212, -1864, -1829, -1005, -1845, -3363, -2929, -2214, -2514, -2560, -2375, -2194, -2352, -3018, -3101, -2802, -2543, -2127, -2601, -2745, -1413, -1079, -2627, -3644, -2256, -815, -806, -690, -576, -892, -782, -564, -470, 277, -6, -1917, -1885, 58, 631, -273, -1335, -1309, -839, -1254, -1799, -1990, -1925, -2132, -3041, -3119, -2350, -2482, -2809, -2399, -1918, -2138, -2883, -3417, -3254, -2594, -2426, -2809, -2524, -2381, -2594, -2221, -2011, -2797, -3781, -3943, -3709, -3611, -4011, -4890, -4683, -2886, -1592, -1991, -2966, -2196, 341, 1698, 1237, 856, 1024, 380, -907, -782, 70, -99, -463, -363, -641, -1028, -1107, -1764, -2765, -3573, -3974, -4335, -5130, -6018, -6180, -4841, -2926, -1891, -1827, -1273, -301, -389, -1433, -1632, -417, 22, -1179, -2773, -3572, -3527, -3134, -2784, -2928, -3415, -2466, -357, 432, 1053, 2527, 3227, 2559, 1959, 1923, 1599, 1283, 1228, 169, -1061, -1245, -2032, -3014, -3692, -4374, -4564, -4806, -4263, -3195, -3411, -3869, -3225, -2245, -1826, -1893, -1738, -1025, -495, -932, -1186, -904, -1381, -1389, -291, -9, -463, -706, -1116, -715, -1, -811, -1494, -1166, -1238, -1567, -1759, -1536, -866, -782, -977, -493, -141, -396, -889, -746, -385, -800, -1821, -2388, -1571, -512, -215, 324, 800, 244, 84, 495, -163, -967, -1048, -1825, -2933, -2975, -1847, -360, 80, -426, 154, 1548, 2166, 2033, 1879, 1315, 624, 942, 1372, 1054, 335, 269, 1009, 835, 331, 622, 270, -430, -718, -1485, -2993, -3551, -1702, -637, -1697, -1811, -1203, -1465, -1002, 94, -181, -1063, -981, -193, 694, 1290, 956, 366, 589, 892, 227, -200, 978, 2643, 3284, 2762, 2740, 3544, 3665, 3178, 2653, 2453, 2282, 1712, 1131, 450, 727, 2283, 2892, 1836, 930, 1433, 1700, 690, 766, 1886, 1994, 1430, 788, 380, 619, 854, 256, -515, -600, -644, 83, 1388, 1394, 706, 698, 1575, 2514, 2627, 2359, 2412, 2129, 1731, 1686, 1089, 639, 1693, 2471, 2336, 1847, 1071, 1386, 2866, 3325, 1924, 42, -686, -348, 97, 283, -898, -2615, -2485, -277, 2338, 3692, 3643, 2624, 1517, 2029, 3216, 2975, 2003, 1648, 1323, 1577, 2627, 2290, 1490, 2925, 4909, 4436, 2949, 2666, 2951, 2400, 1390, 648, 528, 605, 193, 848, 2023, 1070, -1183, -1173, 491, 373, -186, 904, 1964, 2215, 1918, 1379, 1768, 3181, 3995, 3536, 2763, 2584, 2487, 1753, 712, 77, 286, 1099, 1682, 2062, 3021, 2781, 1312, 1531, 2497, 2291, 1727, 1536, 1673, 1655, 1207, 1145, 1741, 1761, 909, 1067, 1667, 1061, 712, 1215, 1094, 705, 1544, 2557, 2538, 1956, 1168, 943, 455, -583, 0, 459, -1064, -1783, -1112, -956, -755, -247, -226, -246, 177, 448, -343, -1354, -1116, -600, -1186, -1766, -1176, 289, 1901, 2098, 1640, 2309, 3152, 3177, 3120, 3125, 1937, 616, 1524, 2560, 1627, 766, 1141, 871, 181, 465, 892, 962, 1164, 1503, 1685, 2195, 2478, 1534, 974, 1484, 1706, 1806, 2427, 1956, 705, 1478, 3965, 5207, 3759, 2165, 1679, 1612, 1823, 1826, 1763, 1702, 1496, 1705, 2190, 2154, 2057, 1842, 1276, 2084, 3460, 3733, 3614, 3093, 2144, 1509, 2020, 3136, 3584, 3917, 3946, 2956, 2835, 4033, 4173, 3211, 2680, 2705, 2335, 1801, 1938, 2298, 2590, 2134, 275, -12, 1611, 1688, 878, 1616, 2780, 2456, 1763, 1855, 3132, 4850, 4393, 3046, 3438, 3759, 3436, 3648, 3719, 3037, 2430, 2893, 3600, 3533, 2979, 2420, 1892, 1441, 432, -579, 489, 1406, -251, -883, 541, 684, -489, -703, -264, 306, 1611, 2255, 2184, 2856, 3369, 3059, 2602, 2521, 1848, 661, 1117, 2317, 1922, 1204, 1516, 1541, 1767, 2363, 2022, 1734, 1573, 771, 96, 495, 1737, 2053, 505, -1080, -655, 552, 631, 367, 1240, 2623, 2190, 661, 623, 1181, 1198, 786, -1106, -2523, -667, 1559, 2099, 2832, 3583, 2898, 1802, 2080, 2559, 1906, 1724, 2049, 843, -541, 785, 3005, 2646, 831, 642, 1939, 2471, 2057, 1426, 1026, 1471, 1553, 1127, 1606, 2031, 1703, 1683, 2797, 3512, 2460, 1340, 1967, 3271, 3267, 2709, 2377, 1810, 1209, 1303, 1687, 1299, 508, -58, 668, 2638, 3575, 3259, 2691, 2220, 1959, 1773, 1051, 118, 139, 900, 695, -1167, -1708, -19, 1201, 1764, 2488, 2584, 1964, 1546, 1790, 2137, 1585, 794, 636, 19, -896, -161, 861, 163, -336, 419, 575, 37, 644, 1240, 388, -37, 408, 336, -466, -501, 899, 1185, -168, -652, 487, 1503, 1146, 43, 286, 1093, 383, -106, 483, 292, -181, 392, 1541, 2073, 1081, 823, 2745, 4272, 3217, 1612, 1906, 2522, 2538, 2413, 2112, 2088, 2043, 1979, 1975, 1231, 662, 894, 773, 638, 849, 145, -1467, -2090, -1079, -169, -1112, -1662, 160, 1206, 1147, 1910, 1960, 1619, 2138, 2898, 2696, 1420, 1311, 2040, 1483, 1070, 1139, 1052, 1285, 1414, 1547, 1694, 1754, 1453, 1033, 1090, 741, 617, 1459, 1431, 526, 417, 240, -1612, -2600, -858, 967, 677, -518, -389, 565, 1118, 1123, 934, 1996, 3030, 2119, 1201, 1721, 2062, 1675, 1530, 1390, 1222, 158, -797, -464, -692, -1286, -1216, -2079, -3560, -2829, -450, 1051, 1279, 1304, 1882, 2670, 3173, 3683, 3334, 2134, 1686, 1792, 1497, 765, -215, -1414, -2431, -2529, -1944, -2182, -2877, -2044, -404, -236, -805, -208, 1099, 1747, 1576, 1168, 751, 712, 1502, 2172, 1666, 977, 705, 158, 174, 867, 573, 287, 930, 1509, 1977, 2637, 3020, 1957, -2, 524, 2026, 1202, -351, -1993, -3780, -4751, -4444, -3198, -2871, -4139, -5236, -4472, -2996, -2176, -1593, -455, 178, -1028, -720, 1512, 2180, 2066, 2216, 1989, 1283, 477, 418, 568, -292, -1056, -303, 394, 152, -68, -367, -1015, -1538, -1155, -961, -2108, -2355, -1259, -1262, -1671, -454, 761, 234, -197, 1009, 974, -790, -188, 1404, 419, -961, -401, 628, 617, 257, 313, 735, 1546, 2154, 1466, 158, 516, 1755, 2135, 1444, -657, -1758, -395, 285, -1089, -2156, -1344, -318, -529, -234, 484, 436, 229, 640, 1099, 859, 30, -763, -928, -173, 1018, 1137, 826, 776, -1108, -3106, -1803, -271, -933, -1123, -291, -589, -1343, -1248, -1297, -2513, -3121, -779, 1196, 788, 1067, 1570, 1091, 596, -571, -769, 886, 768, -232, 56, 143, -756, -1367, -30, 1105, 437, 96, -443, -1311, -893, -1352, -3283, -3454, -1919, -1465, -1407, -487, -139, -85, 818, 1078, 267, 333, 1051, 1298, 1512, 2044, 1584, 476, 253, -66, 531, 2029, 933, -576, 851, 2105, 1661, 1538, 1107, -530, -969, 776, 2027, 1807, 1664, 1368, 582, 1053, 1752, 1173, 891, 1393, 1150, 745, 561, -949, -1885, -986, -398, -433, -136, 385, 167, -164, 110, -312, -658, 178, 250, -312, 328, 667, 657, 1535, 1505, 919, 1600, 2222, 1409, 517, 392, 1028, 1744, 1778, 1079, 190, 172, 339, -144, -307, 226, 1030, 1538, 284, -1404, -1244, -851, -1593, -2454, -2092, -967, -1207, -1894, -989, 309, 1149, 1862, 1905, 1664, 1188, 1146, 1958, 2119, 1739, 1757, 1524, 973, 1659, 2738, 1716, 1195, 3191, 3693, 2272, 1504, 1271, 1056, 254, -699, -36, 185, -1073, -1013, -77, -235, -322, -180, -626, -526, 213, 119, -704, -1040, -209, 943, 1461, 1386, 802, -73, -151, 793, 1147, 280, -97, 597, 1272, 1369, 1041, 920, 965, 602, 788, 1762, 1514, 443, 309, 308, -389, -1207, -1855, -2188, -1949, -1951, -2332, -2405, -2218, -1883, -2012, -2245, -1290, 215, 602, 296, 448, 128, -1053, -1448, -1125, -1044, -1158, -1742, -1932, -1031, -514, -910, -549, 92, -41, -520, -1078, -1037, -57, 1554, 3084, 3445, 2567, 1945, 1861, 1211, 351, -289, -829, -1350, -1642, -1914, -1543, -726, -1387, -2001, -797, -410, -996, -136, 813, 492, -38, -266, -836, -2092, -3697, -3621, -1293, 459, 560, 118, -253, -874, -1550, -936, 413, 385, -1043, -1468, -168, 356, 222, 1827, 3972, 4157, 2726, 1730, 2041, 1420, -1010, -1603, -296, -540, -1628, -1659, -2260, -3402, -2085, -148, -406, -811, -118, -279, -1694, -2022, -1567, -2575, -3660, -3448, -4195, -4716, -3231, -1935, -1378, -596, 750, 1225, 473, 711, 1777, 1654, 1439, 2264, 2544, 1389, 118, -124, 401, 401, -591, -1595, -1780, -771, 140, -254, -29, 971, 504, -510, -715, -783, -1296, -1780, -2435, -3071, -2639, -2016, -2101, -2796, -3593, -3492, -2891, -2409, -2207, -2494, -2866, -2220, -1179, -763, -20, 886, 937, 1122, 2368, 3226, 3031, 2081, 86, -1322, -247, 785, -452, -1747, -1427, -938, -1494, -2450, -2009, -715, -795, -573, 906, 1026, 1482, 3107, 2598, 885, 561, 889, -64, -1830, -1823, -378, -214, -580, 51, 794, 638, 62, 865, 1089, -470, 85, 2230, 3114, 2465, 829, 115, 966, 1506, 1084, 458, -257, -700, -331, 853, 1264, -124, -1038, -100, 938, 1312, 1583, 1692, 1053, -388, -992, -621, -1144, -2147, -1443, -303, -794, -741, 479, 120, -1079, -285, 1299, 1804, 2189, 2544, 2611, 2532, 1666, 705, 1775, 3422, 3383, 3110, 3163, 2342, 694, 131, 1611, 3181, 2732, 667, -90, 1528, 2754, 1870, 1161, 2129, 2310, 1413, 1498, 2008, 2463, 2746, 1874, 451, 160, 1176, 1114, 526, 1480, 1572, 606, 1524, 2609, 2064, 1372, 1130, 1191, 1149, 855, 388, -48, 14, 347, 625, 858, 270, -516, -348, -177, -798, -1035, -683, -631, -668, -791, -143, 1047, 743, 46, 1064, 1717, 1228, 1547, 2001, 2236, 2154, 694, -660, -365, 929, 2425, 2290, 518, -570, -657, -344, 59, 72, -594, -1506, -1660, -650, 236, 243, 70, 165, 934, 1771, 1676, 1453, 1595, 1590, 1203, 155, -969, -306, 651, -170, -1337, -2142, -2623, -2096, -1617, -2372, -2469, -2065, -2715, -3135, -2786, -3164, -3926, -3762, -2462, -1505, -1339, -973, -465, -377, -532, -135, 33, -448, -269, -776, -2196, -1560, -548, -934, -369, 69, -1131, -1399, -760, -1279, -1230, -377, -666, -1186, -1470, -2152, -2352, -1441, -1314, -1772, -1731, -1704, -796, -212, -612, -323, 128, 211, -664, -1545, 508, 2465, 1640, 1096, 1413, 881, 523, 1402, 1414, 352, 648, 1664, 949, -696, -213, 1532, 1487, 1241, 2041, 2014, 1154, 346, 380, 699, -595, -1006, 89, -221, -1497, -1846, -2225, -3760, -4035, -2248, -825, -700, -1117, -664, 753, 1965, 2188, 1070, 232, 1248, 1880, 687, -932, -1429, -416, -654, -3027, -3502, -1644, -561, -489, -1159, -1420, -384, -323, -1500, -1787, -869, 206, -325, -1815, -1128, 220, 230, 1264, 3101, 4256, 4477, 4380, 4158, 2365, 116, -326, -543, -918, 605, 1963, 1133, -192, -705, -270, 108, 263, 877, 933, 693, 848, 656, 639, 1489, 1603, 483, -680, -951, -553, -350, -432, -665, -93, 1893, 2844, 1904, 1409, 1734, 1465, 1533, 1964, 1357, 213, -720, -1725, -2596, -2281, -1211, -1189, -2029, -2396, -2078, -1404, -744, 280, 789, 115, 98, 1573, 2310, 1958, 2047, 2231, 1883, 714, -1060, -1827, -755, 575, 1284, 1493, 1325, 1051, 1178, 2181, 2893, 1274, -710, -25, 889, 106, -730, -1577, -2465, -2211, -2034, -3164, -3139, -1479, -758, -1097, -801, 285, 384, 548, 2549, 3507, 2428, 2170, 2484, 1463, -162, -686, -749, -1714, -3095, -3617, -2880, -1751, -1033, -706, -243, 172, -355, -1082, -891, -723, -166, 1019, 1545, 665, -95, 772, 778, -1273, -2230, -855, -383, -947, -292, -99, -395, 1597, 3759, 3248, 1606, 1124, 2530, 3694, 3041, 2711, 2969, 2498, 1400, 429, 363, 870, 1181, 406, -1038, -1627, -1269, -1204, -2320, -3062, -1846, -289, 171, 931, 2829, 3465, 1901, 680, 585, 379, -99, -836, -1351, -980, -703, -554, -336, -654, -876, 489, 2282, 2062, 511, 293, 1607, 1817, 1266, 1725, 2106, 1759, 1839, 1966, 1305, 1483, 2272, 2102, 1542, 1157, 651, -458, -1336, -826, -273, -387, -190, 714, 1067, 885, 1976, 2847, 1776, 270, 82, 1221, 1490, 321, 22, 635, 314, 441, 1551, 1608, 1458, 1833, 1962, 1657, 136, -1397, -728, 474, 62, -668, -53, 542, 217, -111, 111, 975, 2280, 3190, 2298, 920, 1337, 1854, 793, -559, -632, -641, -1528, -1946, -2022, -2333, -1933, -1301, -1979, -2457, -718, 537, -271, -536, -123, -589, -606, 158, -386, -1119, -491, -299, -412, 491, 1436, 842, -834, -1427, -54, 1177, 612, 103, 345, -1274, -3403, -1817, 701, 293, -832, -536, 33, -252, -593, -286, -696, -1855, -592, 1295, -85, -1652, -1539, -1028, -541, 206, 570, 102, 308, 831, -91, -355, 1706, 3131, 2600, 1714, 971, 629, 1038, 485, 271, 1606, 2111, 2538, 2937, 1551, 5, 156, 634, 388, -39, -217, 286, 1061, 1039, 1811, 3342, 3484, 3024, 2471, 1865, 2041, 1616, 494, 28, -192, -776, -1048, -866, -867, -697, -537, -990, -1177, -942, -2110, -2548, -572, 783, 1847, 2921, 2414, 1657, 1290, 931, 858, 365, -1221, -1629, -320, -5, -686, 533, 2221, 1447, 626, 1138, 961, 1131, 2232, 1714, 356, 87, 4, -378, -284, 316, 401, -370, -608, -753, -1388, -446, 407, -831, -1590, -1083, -162, 682, 643, 648, 1425, 1219, 944, 1623, 2001, 1697, 907, 367, 293, 334, 342, 108, 100, -22, -1017, -1959, -1146, 83, -196, -161, 360, -455, -1205, -817, -661, -1245, -1676, -1712, -1406, -546, -602, -1979, -2661, -1707, -432, -374, -1441, -1797, -1304, -1737, -1717, -362, 125, -753, -1745, -2046, -1334, -559, -1014, -1208, -182, 87, -1224, -1804, -1313, -1463, -2184, -2342, -1685, -1966, -3205, -3099, -1393, -317, -302, -742, -1341, -1374, -1052, -1036, -1142, -1023, -590, -91, -125, -169, -133, -1051, -1705, -1318, -1070, -994, -1403, -2078, -1622, -703, 247, 1511, 2242, 2404, 2770, 2980, 1716, 317, 1149, 1924, 981, 381, 991, 1742, 1290, 1094, 3038, 3611, 1212, 459, 1469, 862, 69, 202, -773, -1931, -767, 959, 1066, 788, 898, 1152, 858, -24, -142, 0, -338, -911, -1467, -909, 9, -567, -2142, -3364, -2654, -826, -57, 190, 945, 1728, 2680, 3502, 3301, 2740, 2149, 1450, 1187, 513, -850, -859, 325, 241, -963, -1619, -2215, -3081, -2643, -1180, -1229, -2237, -1328, 327, 401, -60, 234, 1265, 2333, 2301, 1316, 578, 155, 67, -274, -1418, -2280, -2276, -1878, -1789, -1639, -452, 86, -1281, -2054, -1649, -1424, -1417, -1699, -1896, -1253, -1209, -1792, -1515, -1362, -905, -522, -1607, -1771, -659, -1447, -3471, -4148, -3797, -3167, -2178, -1664, -2134, -1542, 808, 1720, 729, 161, -26, -160, -279, -1308, -1506, 429, 1008, -1030, -2340, -1074, -39, -118, -341, -1106, -2155, -2846, -2622, -2482, -2976, -2567, -881, 487, -1242, -4201, -3307, -1070, -1847, -2449, -1465, -1969, -1882, 427, 917, -907, -1563, -623, 412, 531, -882, -821, 1615, 2866, 2355, 1786, 1712, 1675, 916, 469, 1088, 569, -602, -477, -204, -704, -516, 1329, 2943, 2213, 556, 323, 937, 1052, 149, -625, -313, -351, -1244, -1433, -694, 346, 976, 57, -1145, -1639, -1737, -411, 1433, 1209, 565, 1277, 435, -2624, -2922, -214, 735, 140, 211, -274, -1063, 403, 2293, 1832, 1500, 2664, 2575, 861, -125, -542, -1570, -2192, -1343, -540, -714, -128, 611, 382, 998, 2478, 2598, 431, -1038, 372, 1017, -223, -347, 742, 433, -1063, -673, 196, -972, -1854, -698, 159, -546, -692, -1067, -1982, -1268, -258, -778, -1347, -1050, -1113, -864, -351, -738, -1191, -1880, -2531, -2059, -1378, -640, 453, 997, 354, -1079, -1686, -1072, -643, -237, -165, -334, -133, -763, -1059, -247, -203, -879, -921, -253, 149, -556, -1276, -1102, -859, -1195, -1617, -1694, -1141, -428, -240, -984, -2393, -2525, -537, 533, -940, -1530, -461, 128, 673, 338, -1468, -1949, -1060, -1254, -1634, -435, 871, 87, -2152, -2526, -855, -483, -844, -162, 959, 693, -289, 525, 1480, 1110, 923, 1053, 937, 98, -1135, -455, 1374, 1741, 1168, 388, 623, 1675, 1374, 592, 601, 477, -132, -58, 1024, 1361, 969, 1460, 2024, 2622, 3386, 2402, 1077, 1449, 961, -439, -720, -1064, -2121, -2966, -2854, -1133, 724, 571, -769, -1196, -490, 94, 666, 1346, 1568, 1313, 1294, 1848, 1841, 1517, 1286, 440, -40, 104, -1166, -1957, -358, 216, -335, 565, 1779, 2425, 2443, 1651, 1174, 1089, 430, -540, -2028, -3875, -3996, -2311, -1157, -1779, -3278, -2895, -299, 959, -170, -1233, -1636, -2631, -2824, -1052, 185, -396, -767, -214, -672, -1445, -977, -289, 126, -366, -1203, -854, -278, -994, -1420, 69, 1048, -367, -1507, -1184, -1428, -1625, -1543, -2403, -2881, -2458, -1975, -2061, -2329, -1684, -1267, -1323, -899, -1291, -2055, -1263, -540, -1577, -2320, -1471, -633, -1488, -2430, -1160, -279, -1018, -1051, -854, -1281, -1682, -1412, -611, -712, -1718, -1580, -1021, -1490, -1250, -349, -859, -2236, -2419, -1454, -470, 82, -602, -2268, -3113, -2747, -2996, -4503, -5332, -4126, -2461, -1819, -1670, -1571, -1399, -1020, -460, 171, 494, 324, 248, 251, 1118, 2216, 1270, 773, 2066, 1728, 709, 978, 511, -158, 664, 1675, 1378, 964, 1900, 3323, 2911, 567, 3, 1682, 862, -1517, -1050, 172, -361, -695, 3, 425, -118, -345, 120, 301, 145, -103, -561, -1248, -805, 562, 254, -710, -535, -201, 91, 559, 1113, 1527, 1359, 1115, 699, -651, -846, 580, 1161, 830, 982, 1337, 720, -584, -960, 81, 1560, 2028, 1046, 199, 254, 408, 154, -239, -709, -1210, -646, 894, 993, -474, -987, -839, -1751, -2315, -2255, -2841, -3772, -3950, -2691, -1790, -1788, -1250, -1258, -1542, -793, -526, -484, 0, 418, 935, 702, -144, -185, 87, 152, 837, 787, 152, 1296, 2183, 949, -472, -1596, -2384, -1743, -424, 51, -504, -1063, -362, 385, 67, 147, 443, -496, -876, -139, -473, -1011, -113, 1249, 1755, 1923, 2372, 2273, 1485, 1085, 1199, 816, 551, 981, 1085, 524, -959, -2555, -2935, -2324, -2159, -2998, -3581, -2990, -2304, -1897, -1247, -2149, -3290, -2016, -1162, -1804, -1896, -1972, -2369, -2906, -3018, -2120, -1656, -2056, -1537, -408, 10, 578, 1063, 1092, 1417, 1145, 376, 387, 952, 1491, 1434, 977, -127, -1218, -380, 208, -634, -294, 672, 719, 375, -243, -1098, -1421, -817, -48, -701, -2211, -2270, -1419, -1727, -2022, -1353, -1362, -1792, -1373, -1239, -1983, -1883, -676, 417, 1430, 2015, 1878, 1869, 2860, 4232, 3728, 2747, 2979, 2645, 1824, 1130, 292, 370, 1527, 2224, 1246, 384, 1140, 1611, 1344, 1287, -26, -1446, -453, 132, -626, -364, 744, 1149, 285, 75, 783, 728, 885, 1081, 481, -109, -1285, -2027, -972, -372, -1103, -1162, -637, -536, -411, 541, 1667, 2066, 3149, 4743, 4704, 4226, 5361, 6536, 6039, 4820, 4082, 3957, 4048, 3610, 2620, 2854, 4090, 3401, 2047, 2228, 2229, 1742, 1201, 16, -905, -455, -119, -1172, -1302, 21, -190, -1797, -2095, -1050, -807, -2249, -2666, -481, 1504, 1415, 1279, 2599, 2973, 1744, 776, 682, 526, 269, 617, 76, -1816, -2815, -2413, -2402, -3060, -2829, -1882, -2312, -3007, -2546, -2819, -3339, -2927, -3112, -3627, -3857, -4716, -5272, -4317, -2207, -426, 186, 1122, 2678, 2649, 1401, 1240, 1152, 293, -91, -993, -2122, -888, 1159, 1826, 1837, 1871, 2114, 2241, 1755, 1538, 1128, 11, -906, -2018, -4102, -4925, -3439, -2343, -2430, -2469, -2101, -2054, -2573, -3333, -3520, -2190, -865, -793, -1008, -1090, -308, 1608, 2219, 829, -276, -48, 430, -95, -1061, -1292, -482, -24, -922, -2160, -2770, -2952, -2590, -979, 288, 149, 361, 1793, 2415, 1437, 1168, 1644, 1479, 1329, 1541, 2021, 1762, 441, -515, -1435, -2028, -1842, -2189, -3154, -4518, -4889, -2834, -1591, -2618, -3177, -2241, -1275, -682, -179, -337, -506, 315, 745, -280, -650, 1036, 2410, 1399, -848, -1075, 1430, 3629, 3674, 3473, 3706, 3482, 3147, 2235, 953, 117, -734, -2251, -3261, -2281, -1095, -2058, -3163, -2611, -1276, 554, 2013, 1344, 491, 1599, 2371, 1754, 1906, 2375, 1418, 556, 1019, 1519, 1501, 1240, 1420, 1752, 906, 742, 1975, 1631, -113, -598, -203, -603, -802, -846, -2307, -1110, -1226, -32, 1256, 921, -365, -1064, -966, -260, 46, -637, -1874, -3012, -3277, -3114, -3399, -3903, -3893, -3484, -3177, -2841, -2317, -1804, -1419, -1508, -2135, -2484, -2401, -2366, -2060, -1491, -1295, -1168, -460, 785, 1516, 1262, 750, 473, 531, 536, -34, -760, -1378, -2039, -2665, -3250, -3824, -3976, -3249, -2595, -2543, -2353, -2032, -2124, -2815, -3658, -4235, -4350, -3909, -3225, -2731, -2921, -3655, -3260, -1592, -714, -1145, -1652, -1407, -807, -539, -430, -129, 22, -207, -796, -1485, -1693, -1563, -1407, -1060, -635, -379, -137, 180, 13, -593, -835, -567, -460, -777, -1236, -1774, -2197, -1997, -1501, -1969, -3257, -3683, -3322, -3330, -3286, -2753, -2180, -1617, -1518, -2302, -3200, -3517, -3236, -3123, -3715, -4108, -3746, -3289, -3050, -2778, -2594, -2537, -2454, -2269, -2309, -2976, -3227, -2197, -972, -639, -1044, -1380, -1355, -1181, -1039, -1527, -2591, -2579, -1480, -1152, -1896, -2460, -2205, -1704, -1581, -1996, -2318, -1713, -730, -3, 415, 338, 52, 338, 1129, 677, -761, -894, -190, 240, 399, -294, -1450, -1697, -773, 166, 717, 1506, 2033, 1536, 1341, 2743, 4014, 4163, 3956, 3810, 3739, 3299, 3365, 4262, 4395, 3602, 3405, 4290, 5413, 5894, 5393, 4993, 6095, 8034, 9161, 9301, 9680, 11037, 12044, 11978, 12321, 12754, 11942, 11467, 12077, 11680, 10349, 10120, 10560, 10373, 10250, 10707, 10822, 10208, 10045, 10644, 10463, 9222, 8283, 7745, 6972, 6033, 5355, 5053, 4723, 4104, 2840, 1149, 11, -711, -1479, -2099, -2855, -3962, -4887, -5221, -5984, -7796, -8909, -8524, -8276, -9397, -10964, -11283, -10583, -10242, -10877, -11928, -12088, -11514, -11180, -11122, -11190, -10842, -9919, -9357, -9440, -9526, -9545, -9527, -9102, -8828, -9144, -8990, -8030, -7357, -7282, -7573, -8109, -8105, -7436, -7322, -7908, -8349, -8606, -8715, -8650, -8839, -9097, -8614, -7608, -7223, -7554, -7444, -6574, -5743, -5253, -5094, -5190, -5033, -4492, -4104, -4288, -4641, -4494, -4260, -4497, -4830, -5051, -5398, -5558, -5174, -5430, -7256, -8665, -7435, -5744, -6657, -8683, -9847, -10279, -10104, -10421, -11769, -12651, -12159, -11213, -11290, -12383, -12976, -12714, -12288, -11913, -12044, -12625, -12603, -12075, -11939, -11777, -11353, -11164, -10841, -10251, -10247, -10702, -10430, -9284, -8248, -7865, -7775, -7291, -6288, -5895, -6517, -7217, -7449, -7003, -6370, -6474, -6902, -6900, -6593, -6065, -5554, -5389, -5198, -4954, -4605, -4269, -4724, -5554, -5665, -5104, -4673, -4533, -4450, -3959, -2762, -1634, -1272, -1433, -1524, -961, -317, -586, -1327, -2145, -3025, -3397, -3408, -3810, -4449, -4544, -4198, -4128, -4458, -4586, -3981, -3300, -3537, -3982, -3748, -3302, -2895, -2419, -1997, -1752, -1473, -911, -278, 243, 453, 392, 546, 760, 472, -188, -392, -35, 66, -435, -1250, -1741, -1626, -1450, -1523, -1989, -2588, -2614, -2139, -1761, -1848, -2002, -1573, -776, -371, -544, -703, -229, 550, 825, 583, -192, -1254, -792, 756, 558, -1105, -2055, -2029, -1675, -1464, -1908, -2447, -2024, -1256, -1316, -1899, -2104, -1749, -1556, -2090, -2759, -2705, -2296, -2397, -2970, -3428, -3192, -2391, -1840, -1849, -2259, -2379, -1542, -595, -558, -996, -1051, -475, 127, 152, -306, -649, -435, -53, -309, -1156, -1528, -1112, -810, -1068, -1645, -2234, -2162, -1392, -1148, -1945, -2638, -2374, -1742, -1562, -1858, -2147, -1965, -1414, -1061, -1184, -1492, -1158, -307, 2, -335, -598, -154, 735, 1355, 1349, 861, 405, 573, 1256, 1372, 952, 1130, 1923, 2386, 2072, 1541, 1521, 2048, 2719, 3022, 2605, 2054, 2239, 2437, 1705, 658, -243, -775, -574, -217, -375, -1075, -1421, -719, -116, -613, -1300, -1031, 69, 1049, 999, 155, 38, 1054, 1899, 2095, 2142, 2226, 2475, 2956, 2968, 2273, 2161, 2960, 3517, 3407, 2942, 2552, 2599, 3065, 3346, 3057, 2496, 2169, 2100, 1603, 646, -93, -316, -34, 184, -108, -350, -200, 77, 369, 422, 148, 277, 1251, 2169, 2109, 1733, 1913, 2400, 2654, 2522, 2121, 1949, 2313, 2743, 2819, 2758, 2804, 2761, 2778, 2639, 1821, 1217, 1197, 1139, 1128, 1087, 981, 1280, 1890, 2069, 1536, 945, 1207, 2069, 2255, 1734, 1396, 1607, 2010, 2112, 2032, 1843, 1868, 2576, 3220, 3028, 2783, 3117, 3618, 3924, 3757, 3167, 2989, 3500, 3867, 3514, 2899, 2675, 2964, 3886, 4673, 4358, 3761, 3964, 4167, 3393, 2636, 2513, 2454, 2641, 2802, 2188, 1479, 1314, 1285, 1213, 975, 699, 671, 1125, 1772, 1541, 982, 1406, 2117, 2202, 1816, 1518, 1687, 1970, 2045, 1960, 1718, 1459, 1771, 2674, 3065, 2772, 2639, 2826, 3333, 3750, 3348, 2762, 3008, 3664, 4055, 3920, 3519, 3532, 3702, 3498, 3074, 2792, 2954, 3550, 3710, 2735, 1568, 1436, 1983, 1900, 848, -155, -370, 24, 406, 230, -324, -557, -114, 376, 505, 599, 809, 1282, 1910, 2021, 1697, 1811, 2349, 2601, 2506, 2430, 2616, 3260, 3848, 3584, 3044, 2970, 2973, 2831, 2548, 1891, 1201, 1140, 1721, 2128, 1707, 978, 803, 1104, 986, 161, -484, -345, 417, 1207, 1281, 827, 753, 1268, 1540, 1028, 505, 827, 1554, 2430, 3281, 3149, 2513, 2906, 3800, 3456, 2311, 1915, 2414, 3033, 2908, 2245, 2287, 3014, 3318, 3049, 2547, 1929, 1808, 2322, 2671, 2371, 1701, 1555, 2143, 2380, 1721, 1194, 1370, 1637, 1717, 1565, 1252, 1162, 1467, 1771, 1657, 1460, 1620, 1785, 1774, 1639, 1344, 1437, 2383, 3249, 2924, 2196, 2093, 1980, 1406, 523, -405, -891, -1146, -1227, -906, -820, -994, -494, 731, 1630, 1535, 1121, 1203, 1601, 1540, 735, 232, 768, 1428, 1559, 1285, 681, 512, 1245, 1702, 1247, 717, 726, 1052, 1235, 945, 475, 664, 1378, 1908, 2127, 2142, 2243, 2674, 3136, 3158, 2638, 2138, 1950, 1882, 1826, 1163, 712, 1440, 1946, 1651, 1688, 2303, 2913, 3543, 4154, 4205, 3802, 3633, 3762, 3433, 2199, 815, 500, 1301, 1876, 1516, 931, 1007, 1552, 1795, 1361, 506, 175, 853, 1628, 1543, 830, 540, 1170, 1511, 1088, 937, 1067, 1480, 2260, 2254, 1455, 1352, 2212, 2874, 2566, 1988, 2281, 3089, 3485, 3155, 2262, 1591, 1797, 2457, 2804, 2479, 1850, 1759, 1977, 1757, 1339, 1073, 1026, 1387, 1726, 1459, 763, 381, 632, 820, 696, 515, 366, 884, 1815, 1716, 758, 419, 959, 1555, 1550, 870, 482, 1159, 2062, 2186, 1855, 1777, 2341, 3139, 3147, 2444, 2079, 2364, 2883, 3171, 2707, 1751, 1641, 2857, 3972, 3825, 3266, 3105, 3239, 3270, 2712, 1998, 1760, 1823, 2112, 2156, 1519, 1086, 1383, 1897, 1901, 1369, 1206, 1928, 2822, 2965, 2492, 2410, 3350, 4360, 4426, 3999, 3829, 4214, 4703, 4402, 3520, 3027, 3267, 3930, 4157, 3631, 3016, 2718, 2677, 2579, 2228, 1748, 1690, 2406, 3026, 2653, 1782, 1486, 1832, 2078, 2017, 1765, 1669, 1933, 1835, 1409, 1607, 2372, 3262, 3720, 3410, 2884, 2832, 3122, 3278, 3596, 4007, 3844, 3415, 3214, 2899, 2315, 1775, 1484, 1420, 1608, 1578, 1070, 1042, 1872, 2205, 1194, 176, 294, 701, 470, -281, -739, -255, 304, -152, -806, -624, 213, 973, 1015, 690, 604, 949, 1627, 2365, 2704, 2465, 2294, 2504, 2897, 2880, 2148, 1759, 2202, 2295, 1864, 1791, 1776, 1444, 1433, 1713, 1523, 1125, 1337, 1809, 1632, 903, 206, -89, 288, 813, 689, 313, 290, 415, 581, 543, 257, 414, 965, 1101, 749, 264, 157, 861, 1731, 2061, 2119, 2416, 3202, 4007, 3854, 3060, 2907, 3274, 3316, 2881, 2263, 1923, 1934, 1643, 1093, 880, 746, 631, 687, 415, -305, -732, -706, -611, -498, -510, -639, -544, 85, 872, 719, -141, -307, 388, 959, 1258, 1506, 1631, 2017, 2606, 3054, 3113, 2700, 2445, 2626, 2740, 2472, 2031, 1783, 1881, 2004, 1705, 1128, 720, 867, 1293, 895, -98, -22, 883, 885, 157, -262, -121, 649, 1230, 760, 348, 1094, 2024, 2003, 1286, 824, 666, 780, 1334, 1254, 550, 850, 1914, 2314, 2028, 1762, 1957, 2622, 3199, 2977, 2191, 1784, 1932, 2224, 2197, 1984, 1942, 1787, 1533, 1272, 773, 79, -59, 446, 320, -270, -448, -575, -749, -1020, -1920, -2883, -2753, -1942, -1548, -1550, -1574, -1412, -783, -177, -335, -825, -642, 19, 352, 317, 99, 93, 824, 1442, 1019, 266, 172, 649, 1151, 1405, 1314, 1410, 2110, 2714, 2630, 2022, 1322, 1139, 1696, 2015, 1296, 176, -86, 513, 837, 519, -107, -476, -210, -119, -897, -1960, -2753, -3128, -3163, -3530, -4362, -4693, -4303, -3902, -3627, -3374, -3065, -2284, -1065, -22, 395, 554, 1199, 1821, 1715, 1329, 1114, 1209, 1488, 1338, 619, 390, 886, 1216, 945, 249, -128, 155, 537, 555, 221, -232, -533, -487, -334, -564, -1044, -1097, -579, -375, -997, -1644, -1857, -1911, -1972, -2172, -2434, -2332, -1501, -546, -346, -488, -165, 384, 682, 603, 42, -446, -61, 460, 87, -711, -1069, -1002, -975, -1232, -1825, -2558, -2991, -2410, -1472, -1810, -2743, -2547, -1797, -2065, -2910, -2868, -2006, -1270, -873, -889, -1275, -1253, -695, -584, -904, -911, -517, 87, 611, 673, 310, 96, 536, 1086, 747, -168, -360, 398, 914, 636, 179, -361, -539, -3, 94, -400, -443, 77, 669, 943, 639, 136, 253, 768, 795, 262, -284, -498, -179, 214, 105, -214, -86, 457, 688, 555, 316, 344, 771, 807, 137, -276, -47, 373, 633, 264, -324, -95, 789, 1352, 1098, 302, -311, -520, -557, -783, -1444, -2039, -2214, -2208, -2433, -3080, -3642, -3622, -3399, -3283, -3327, -3650, -3868, -3769, -3619, -3739, -4305, -4575, -3629, -2228, -1599, -1379, -667, 308, 968, 951, 431, 268, 735, 1302, 1388, 1122, 1030, 1340, 1691, 1604, 1145, 782, 827, 999, 738, -25, -499, -367, -465, -916, -1134, -1364, -1648, -1510, -1347, -1904, -2797, -2858, -1925, -1584, -2181, -2385, -2166, -1892, -1624, -1878, -2232, -1963, -1581, -1306, -1210, -1633, -1820, -916, 111, 209, -96, 6, 621, 1137, 1237, 1095, 1071, 1218, 1242, 1235, 1150, 941, 890, 1029, 883, -74, -1370, -1607, -956, -1011, -1805, -2305, -2348, -2116, -2126, -2851, -3509, -3163, -2450, -2500, -3042, -3172, -2390, -1245, -668, -737, -916, -602, 95, 591, 413, -75, 148, 827, 981, 733, 454, 160, 131, 210, -134, -696, -984, -993, -1079, -1343, -1762, -2439, -2765, -2357, -2252, -2849, -3462, -3786, -3571, -3015, -2874, -2931, -2508, -1923, -1635, -1404, -1420, -1752, -1506, -887, -834, -786, 87, 1255, 1704, 1268, 529, 136, 170, 109, -344, -1142, -1870, -1952, -1368, -1064, -1544, -1911, -1518, -1027, -1191, -1778, -1806, -1229, -924, -949, -1158, -1712, -2135, -1855, -1325, -1425, -1894, -1828, -1604, -1639, -1439, -1198, -1265, -1000, -183, -11, -627, -484, 490, 1043, 787, 185, -151, 13, 21, -370, -691, -1140, -1492, -1220, -1076, -1646, -2005, -1545, -1110, -1429, -2292, -2992, -2965, -2550, -2571, -2812, -2553, -1916, -1353, -1233, -1508, -1569, -1394, -1285, -1349, -1896, -2585, -2682, -2287, -2057, -2602, -3356, -3101, -1809, -732, -1024, -2067, -2352, -1982, -1982, -2495, -3350, -4004, -3759, -3270, -3067, -2747, -2208, -1573, -1033, -1077, -1785, -2167, -1636, -1043, -1273, -2152, -2663, -2166, -1312, -1131, -1687, -2316, -2624, -2619, -2809, -3341, -3254, -2564, -1937, -1540, -1897, -2632, -2599, -1715, -904, -744, -771, -222, 535, 581, 286, 210, 87, 114, 417, 99, -797, -955, -237, 460, 755, 532, -38, -267, -239, -765, -1826, -2700, -2932, -2560, -1936, -1795, -2185, -2033, -1028, -132, -233, -787, -411, 647, 871, 54, -602, -563, -322, -290, -176, 167, 294, 409, 601, 459, -2, -563, -744, -371, -229, -774, -1325, -917, -42, -336, -1943, -2994, -2752, -2565, -3006, -3368, -3245, -2417, -1220, -453, -222, -153, 148, 674, 740, 402, 209, -176, -333, 261, 655, 163, -437, -215, -5, -974, -2086, -1919, -1210, -1062, -1189, -1356, -1542, -1190, -587, -841, -1545, -1647, -1677, -1918, -1899, -2030, -2390, -2144, -1571, -1289, -1250, -1223, -650, 164, 342, -298, -964, -722, 18, 205, -330, -781, -476, 19, 32, -320, -546, -437, -305, -422, -905, -1278, -1229, -1098, -964, -1074, -1443, -1389, -833, -523, -866, -1378, -1460, -1318, -1046, -683, -651, -882, -947, -853, -1006, -1397, -1407, -753, 259, 827, 229, -631, -533, -78, -3, -325, -989, -1271, -708, 93, 345, -10, -55, 768, 1524, 1147, 387, 548, 1246, 1360, 860, 349, -12, -134, -263, -836, -1504, -1700, -1381, -1091, -1602, -2547, -2694, -2110, -1672, -1841, -2792, -3670, -3239, -2292, -2418, -3276, -3727, -3751, -3462, -2824, -2671, -3211, -3363, -2710, -2156, -2159, -2247, -2069, -1967, -1898, -1624, -1534, -1614, -1398, -852, -663, -1164, -1472, -1019, -671, -1161, -1614, -1328, -988, -1012, -1101, -1262, -1446, -1197, -738, -830, -1533, -2248, -2316, -1869, -1591, -1454, -872, -376, -696, -1199, -1450, -1454, -1115, -806, -873, -1295, -1848, -1950, -1374, -815, -900, -1330, -1421, -1058, -1095, -1643, -1636, -879, -55, 470, 499, 152, 318, 1237, 1792, 1562, 1172, 906, 1275, 2315, 2702, 2074, 1561, 1974, 2459, 2169, 1671, 1381, 1403, 1878, 2114, 1615, 1229, 1608, 1919, 1592, 1429, 1457, 1367, 1609, 1859, 1911, 2050, 2186, 2440, 2734, 2887, 2873, 2666, 2494, 2269, 1803, 1258, 539, 45, 280, 452, 25, -472, -353, 271, 325, -439, -917, -591, -373, -890, -1517, -1826, -2040, -2071, -1981, -2073, -1919, -1338, -771, -251, -23, -169, 209, 1133, 1361, 917, 781, 1204, 1702, 1827, 1751, 1661, 1509, 1621, 2181, 2409, 1919, 1483, 1586, 1877, 1488, 454, -95, 275, 503, -73, -340, -12, -36, -138, -221, -838, -1473, -1575, -1434, -1457, -1786, -2223, -2153, -1322, -754, -1276, -1781, -1070, 111, 871, 1206, 1248, 1445, 1913, 2362, 2440, 1757, 1052, 1442, 2438, 2573, 1940, 1752, 1883, 1495, 900, 490, 152, 340, 628, 295, -167, -224, 115, 631, 808, 175, -466, -163, 407, 476, 151, -317, -503, -51, 359, -420, -1620, -1462, -532, -402, -829, -914, -586, 2, 611, 459, 143, 774, 1720, 1853, 1372, 1377, 1705, 1632, 1330, 1111, 905, 867, 1390, 2135, 2256, 1927, 1954, 2296, 2405, 2083, 1499, 1054, 1103, 1438, 1124, 94, -537, -282, 358, 602, 260, 30, 157, 150, 69, 29, -172, -88, 562, 1079, 1070, 929, 1097, 1724, 2359, 2161, 1505, 1812, 2814, 3265, 2850, 2054, 1643, 1531, 1355, 1238, 816, 305, 340, 89, -1006, -2060, -2361, -2003, -1648, -1970, -2693, -2984, -2466, -1706, -1529, -1829, -1777, -992, -227, -68, 156, 714, 1200, 1716, 2112, 2119, 1824, 1469, 1737, 2623, 2825, 2288, 2462, 3130, 3109, 2428, 1632, 1174, 1029, 856, 562, -33, -632, -506, -79, -252, -897, -1331, -1096, -469, -192, -570, -902, -661, -470, -644, -600, -194, 69, 377, 782, 704, 504, 1018, 1845, 1940, 1329, 1062, 1502, 1581, 425, -369, 534, 1141, 769, 691, 130, -800, -300, 1045, 1393, 408, -762, -1152, -892, -647, -847, -1380, -1943, -2179, -1785, -1139, -1331, -2018, -1971, -1657, -1783, -1898, -1677, -1391, -982, -421, -340, -633, -340, 593, 1239, 970, 420, 715, 1604, 1889, 1483, 1005, 841, 1018, 758, 231, 524, 1185, 1742, 2210, 2151, 1647, 1342, 1472, 1293, 456, -285, -473, -239, -75, -122, -351, -940, -1130, -299, 252, -168, -278, 295, 796, 1001, 989, 862, 1218, 2102, 2525, 2188, 2091, 2606, 2996, 3135, 3240, 3058, 2988, 3423, 3432, 2406, 1095, 551, 1115, 1546, 692, -540, -854, -401, -297, -839, -1401, -1467, -823, 235, 800, 263, -341, 132, 635, -25, -920, -1000, -452, 374, 1099, 1328, 1230, 1487, 2364, 3143, 3161, 2654, 2138, 2037, 2222, 1955, 1306, 1026, 1238, 1582, 1717, 1270, 781, 935, 832, 152, -503, -1071, -961, -202, 146, -111, -184, 311, 901, 1184, 701, -178, 116, 1245, 1405, 991, 1067, 1521, 1740, 1453, 988, 503, 247, 208, -20, -179, 301, 1010, 1252, 1121, 815, 238, -243, 14, 340, 16, -301, -203, 83, 87, -320, -788, -1103, -898, -496, -559, -826, -829, -343, 385, 383, -497, -928, -198, 709, 734, 213, -137, -99, 411, 840, 461, -104, 195, 844, 883, 518, 265, 113, 283, 954, 1282, 1005, 1034, 1474, 1813, 1854, 1403, 903, 1271, 2198, 2432, 1917, 1956, 2734, 3073, 2663, 2095, 1771, 1957, 2621, 2826, 2027, 1481, 1813, 1908, 1382, 834, 496, 598, 1364, 1990, 1555, 728, 816, 1826, 2523, 2188, 1361, 878, 1441, 2358, 2352, 1804, 1668, 1972, 2306, 2410, 1988, 1649, 2348, 3130, 2862, 2024, 1273, 1180, 1746, 1855, 1050, 428, 960, 1906, 1579, 94, -845, -752, -536, -940, -1570, -1543, -699, 246, 386, -254, -675, -177, 823, 1389, 1157, 975, 1602, 2357, 2476, 2063, 1571, 1597, 2195, 2546, 2376, 2239, 2168, 1898, 1510, 812, -71, -221, 377, 641, -121, -1011, -809, -400, -509, -518, -509, -625, -238, 584, 720, 170, 91, 711, 1209, 1140, 1055, 1377, 1913, 2520, 2882, 2609, 2268, 2569, 2979, 2770, 2226, 1699, 1440, 1585, 1402, 525, -262, -215, 295, 199, -307, -626, -719, -79, 674, 329, -666, -1086, -549, 117, 29, -414, -383, 5, 148, -160, -516, -334, 256, 463, 326, 10, -581, -724, -165, 367, 191, -619, -1126, -1067, -1409, -2002, -1614, -513, 274, 419, 149, -81, 119, 615, 816, 703, 395, 385, 1403, 2255, 1820, 1234, 1478, 2033, 2355, 2124, 1336, 1082, 1761, 2348, 2195, 1465, 1031, 1435, 1799, 1365, 912, 805, 591, 879, 1559, 1679, 1712, 2192, 2701, 2846, 2424, 1496, 1008, 1671, 2726, 2883, 2451, 2776, 3639, 3941, 3503, 2940, 2909, 3169, 3330, 3269, 2717, 2226, 2191, 2151, 1573, 800, 601, 828, 1091, 706, -258, -464, 17, 322, 373, -43, -586, -122, 991, 1400, 1188, 1361, 1811, 2032, 2327, 2595, 2545, 2370, 2313, 2340, 2046, 1509, 1305, 1465, 1554, 1405, 1262, 1467, 2072, 2717, 2812, 2093, 1331, 1269, 1245, 459, -561, -928, -802, -604, -426, -444, -569, -555, -592, -832, -1282, -1505, -729, 461, 947, 499, -192, 19, 773, 786, -38, -480, 278, 1139, 929, 155, -94, 383, 629, 3, -1111, -1911, -1954, -1666, -1618, -1861, -2047, -2012, -2017, -1918, -1489, -1091, -818, -208, 770, 1404, 1665, 2265, 2780, 2490, 1738, 939, 509, 850, 1671, 2234, 2318, 2432, 2844, 3107, 3018, 2939, 2728, 2296, 2247, 2389, 1883, 965, 716, 831, 316, -566, -1486, -1882, -1417, -1394, -2144, -2680, -2886, -2740, -2408, -2868, -3530, -3182, -2467, -1732, -1138, -1523, -1847, -896, 91, 124, 43, 351, 585, 592, 419, -39, -233, 474, 1138, 580, -495, -737, -419, -349, -418, -835, -1229, -1013, -837, -960, -1294, -1594, -1298, -907, -837, -947, -1087, -958, -730, -391, 195, 452, 456, 861, 1623, 2254, 2470, 2514, 2623, 2738, 2518, 1849, 1268, 1090, 974, 543, -195, -620, -218, 711, 1290, 1090, 928, 1203, 1758, 2246, 1890, 1347, 1734, 2332, 2312, 1748, 1294, 1569, 1997, 2062, 1622, 966, 712, 509, 71, -258, -728, -1349, -1824, -1939, -1844, -2308, -2622, -1817, -1086, -1421, -2124, -2541, -2475, -1818, -1157, -1091, -1155, -843, -295, -130, -548, -1089, -1143, -644, -453, -760, -620, -183, -150, 154, 662, 479, 77, 103, -17, -766, -1464, -1349, -598, -181, -473, -828, -874, -804, -631, -411, -476, -950, -1243, -1109, -1437, -2111, -2040, -1430, -1397, -1769, -1692, -1533, -1476, -894, -280, -373, -687, -548, -266, -525, -1202, -1605, -1331, -882, -841, -1286, -1889, -1993, -1543, -1176, -1323, -1564, -1458, -1237, -1141, -1195, -1327, -1348, -804, 280, 769, 396, 343, 876, 1078, 867, 486, 111, 151, 208, -325, -1105, -1354, -1200, -1626, -2581, -2994, -2857, -2740, -2563, -2514, -3038, -3518, -3176, -2451, -2146, -2377, -2279, -1437, -765, -762, -1009, -1703, -2766, -2909, -2281, -2294, -2698, -2687, -2319, -1983, -2052, -2448, -2270, -1271, -679, -1102, -1784, -1951, -1554, -831, -256, -167, -37, 285, 464, 488, -175, -1344, -1924, -1879, -2068, -2447, -1811, -511, 205, 236, -435, -1472, -1893, -1713, -1897, -2929, -3847, -3571, -2746, -2194, -2059, -2181, -2006, -1512, -1171, -999, -1046, -871, -122, 163, 53, 540, 1178, 1557, 1903, 1995, 1830, 1805, 2075, 2478, 2404, 1593, 735, 347, -57, -974, -2131, -2848, -2680, -1975, -1682, -2192, -2767, -3021, -3084, -2906, -2996, -3360, -2953, -1973, -1634, -2061, -2593, -2151, -417, 751, 556, 535, 1038, 1371, 1627, 3852, 3422, 2350, 1930, 2724, 3098, 2542, 2045, 1935, 1946, 1859, 1798, 1658, 1210, 959, 758, 202, -144, -195, -613, -1279, -1399, -964, -171, 869, 1462, 1867, 2649, 3468, 4168, 4373, 4072, 3754, 2911, 1562, 832, 797, 737, 852, 1659, 2196, 1802, 1450, 1459, 1556, 1782, 1824, 1403, 1281, 1467, 908, -11, -282, -131, -113, -28, 110, 60, 266, 610, 433, 236, 421, 1072, 2185, 2743, 2537, 2500, 2350, 1878, 1775, 2015, 2224, 2437, 2305, 1927, 1799, 1586, 969, 551, 1194, 2189, 2123, 1404, 1180, 1370, 1238, 780, 428, 37, -476, -438, 408, 1231, 1273, 1284, 1902, 2104, 1553, 1083, 722, 549, 641, 352, -30, 291, 539, -8, -95, 676, 826, 270, 95, 387, 765, 849, 601, 553, 650, 534, 541, 892, 1123, 964, 799, 1239, 1779, 1632, 1297, 1286, 1437, 1605, 1832, 2274, 2428, 1792, 1023, 810, 1000, 1152, 1003, 754, 888, 1435, 1621, 1171, 1014, 1242, 865, 303, 263, 233, 23, -34, 151, 274, 251, 450, 669, 525, 637, 1424, 1836, 1176, 625, 1178, 1768, 1547, 1579, 2631, 3376, 2828, 2043, 2235, 3106, 3542, 3367, 2996, 2473, 1932, 1751, 1753, 1286, 571, 539, 1386, 2414, 3272, 4035, 4464, 4631, 5202, 5952, 6176, 6058, 5451, 4211, 3692, 4072, 4129, 4314, 4908, 4721, 4064, 4334, 5078, 4924, 4229, 4288, 4579, 4322, 4118, 3629, 2610, 2051, 1573, 625, -119, -430, -442, -409, -503, -672, -811, -649, -381, -332, -351, -281, -20, 200, -276, -1340, -2113, -2540, -3065, -3277, -2642, -1668, -961, -384, 84, 487, 759, 693, 367, -413, -1341, -1794, -1940, -1981, -1795, -1609, -1582, -1519, -1377, -1293, -1540, -2347, -3008, -2744, -2157, -2142, -2322, -1989, -1469, -1263, -1597, -2151, -2340, -2394, -2765, -3098, -2807, -2244, -2050, -1763, -1000, -501, -477, -277, 300, 523, 94, -402, -567, -385, -47, 152, -18, -240, -196, -353, -1002, -1754, -2320, -3013, -3955, -4339, -3706, -3264, -3698, -3449, -2463, -2483, -3041, -3498, -4146, -4404, -3883, -3302, -3125, -3083, -3143, -3132, -2601, -2107, -2385, -3067, -3525, -3686, -3672, -3665, -3514, -3127, -2927, -2803, -2658, -2581, -2349, -2166, -2253, -2397, -2338, -1981, -1637, -1954, -2845, -3398, -3378, -3467, -3560, -3273, -3104, -3276, -3441, -3385, -2949, -2529, -2589, -2653, -2032, -1061, -683, -931, -1198, -1076, -757, -603, -432, 57, 208, -292, -369, -293, -1285, -2339, -2316, -2048, -2062, -1984, -1859, -1864, -2145, -2796, -3539, -4127, -4765, -5161, -4833, -4216, -3633, -2860, -2051, -1733, -2002, -2240, -2182, -2029, -1796, -1787, -1898, -1599, -1073, -750, -617, -494, -306, -58, 27, -288, -810, -1289, -1499, -1397, -1604, -1977, -1837, -1496, -1626, -2141, -2347, -2129, -1917, -1558, -1115, -1176, -1684, -1896, -1575, -1247, -1118, -1104, -1434, -1930, -1623, -1169, -1877, -2335, -1723, -1537, -2103, -2704, -3189, -3299, -2967, -3025, -3339, -3139, -2690, -2275, -2131, -2415, -2559, -2453, -2565, -2690, -2825, -3118, -3301, -3507, -3823, -4061, -4383, -4815, -5045, -4958, -4502, -4050, -3953, -3777, -3521, -3599, -3952, -4274, -4314, -4185, -4123, -3819, -3312, -3146, -3099, -2820, -2769, -2919, -2568, -2097, -2325, -2887, -3307, -3603, -3763, -3850, -3964, -3550, -2460, -1970, -2429, -2589, -2307, -2313, -2436, -2490, -2576, -2619, -2409, -1913, -1453, -1329, -1547, -1773, -1764, -1723, -2005, -2252, -1826, -1214, -1380, -2211, -3120, -3640, -3614, -3323, -2772, -2081, -1505, -1115, -1038, -1268, -1417, -1339, -1212, -971, -709, -611, -674, -880, -1177, -1657, -2367, -2743, -2551, -2392, -2486, -2555, -2308, -1571, -724, -288, -362, -836, -1344, -1685, -1978, -2314, -2700, -2861, -2527, -1806, -1216, -1022, -831, -630, -602, -599, -651, -748, -735, -516, -620, -1369, -1817, -1789, -2184, -2748, -2914, -2960, -3112, -3076, -2537, -2034, -2114, -2103, -1609, -1258, -1260, -1359, -1220, -826, -524, -559, -873, -1190, -1656, -2302, -2854, -3302, -3517, -3508, -3219, -2518, -1897, -1420, -833, -571, -873, -1429, -1761, -1739, -1484, -1512, -2244, -2960, -3025, -2739, -2546, -2269, -1745, -1237, -948, -1330, -2175, -2357, -1866, -1641, -1736, -1722, -1783, -2082, -2515, -2667, -2351, -2302, -2357, -1751, -967, -625, -636, -805, -693, -127, 272, 663, 1304, 1528, 1077, 263, -584, -1261, -1681, -1970, -2236, -2007, -1381, -1088, -1000, -841, -642, -522, -691, -1352, -2085, -2210, -2084, -2024, -1770, -1737, -2158, -2607, -2856, -2700, -2186, -1838, -1951, -2176, -1960, -1372, -1159, -1478, -1578, -1013, -245, 277, 413, 159, -389, -1365, -2314, -2355, -2037, -1948, -1717, -1651, -2023, -2472, -2688, -2670, -2671, -2793, -2654, -2301, -2095, -1865, -1915, -2172, -2001, -1799, -2012, -2299, -2200, -1958, -1961, -1754, -1049, -486, -343, -84, 125, -320, -735, -520, -385, -697, -760, -410, -321, -440, -203, 295, 521, 561, 681, 246, -767, -1645, -2412, -3375, -4113, -4134, -3921, -3670, -3220, -2616, -1785, -1120, -1165, -1747, -2198, -2172, -1982, -2128, -2193, -1887, -1915, -1898, -1135, -341, 115, 640, 1069, 1189, 1261, 1466, 1466, 1096, 656, 227, 16, 88, 19, -146, -276, -510, -737, -1020, -1411, -1685, -1927, -2374, -2590, -2456, -2466, -2331, -1862, -1576, -1627, -1659, -1596, -1713, -1757, -1600, -1631, -1495, -1163, -993, -679, -234, 96, 207, 183, 299, 185, -230, -217, 314, 671, 548, 275, 223, 402, 260, -149, -387, -830, -1631, -2392, -2945, -3217, -2987, -2605, -2656, -3150, -3520, -3252, -2392, -1229, -538, -307, 430, 1327, 1616, 1406, 875, -71, -1439, -2565, -2767, -2790, -3313, -3575, -3180, -2618, -2182, -1697, -1199, -1202, -1478, -1238, -917, -980, -851, -547, -445, -52, 945, 1742, 1922, 1770, 1541, 1395, 1379, 1465, 1490, 1232, 571, -15, -402, -1139, -1861, -1863, -1529, -1300, -1172, -1062, -824, -737, -1240, -2107, -2829, -3125, -3071, -3018, -3113, -3137, -2687, -1972, -1634, -1489, -1262, -1081, -832, -687, -651, -480, -517, -590, -233, -4, -250, -364, -207, -248, -616, -1083, -1248, -1222, -1219, -891, -490, -411, -358, -140, 97, 119, 0, -186, -448, -514, -561, -627, -339, -27, -166, -579, -1066, -1541, -1567, -1109, -897, -1137, -1357, -1474, -1695, -2161, -2781, -3225, -3286, -3179, -2861, -2010, -1018, -587, -744, -560, 216, 896, 1037, 462, -543, -1363, -1530, -1367, -1410, -1444, -1418, -1395, -851, 139, 716, 612, 479, 510, 192, -188, -449, -740, -685, -415, -480, -794, -903, -727, -617, -675, -799, -967, -743, -151, 98, -41, -142, -286, -247, 129, 295, 394, 795, 1247, 1407, 1188, 705, 156, -460, -883, -904, -1203, -1790, -1740, -1373, -1454, -1577, -1610, -1764, -1667, -1072, -225, 311, 729, 1170, 840, -87, -745, -1057, -1107, -1261, -1708, -1551, -782, -433, -713, -899, -1003, -1414, -1517, -1227, -1128, -1228, -1159, -708, -257, -79, 29, 170, 307, 318, 176, -91, -620, -892, -546, -357, -299, 163, 490, 280, 151, 71, -516, -1157, -1442, -1645, -1590, -1167, -1109, -1274, -777, -335, -502, -147, 639, 611, 63, 64, 167, -167, -273, 86, 266, 188, 52, -162, -388, -819, -1117, -815, -321, -261, -507, -329, -25, -240, -683, -818, -763, -764, -358, 328, 563, 639, 866, 967, 1037, 1349, 1515, 1172, 762, 735, 736, 542, 712, 1254, 1336, 710, 69, -95, -14, -232, -832, -1201, -928, -371, -203, -315, -545, -870, -885, -788, -1002, -1084, -681, -303, -235, -173, 247, 601, 621, 633, 344, -45, -23, -54, -274, -315, -489, -915, -763, -28, 475, 742, 959, 985, 858, 764, 843, 1207, 1522, 1288, 651, 305, 349, 338, 564, 1001, 1091, 898, 647, 528, 583, 265, -292, -487, -662, -1174, -1520, -1160, -392, 145, 612, 1236, 1570, 1408, 953, 699, 632, 95, -527, -303, 358, 582, 632, 812, 738, 387, 263, 188, -216, -609, -565, -212, -39, 98, 504, 901, 1019, 1227, 1505, 1278, 699, 384, 359, 112, -520, -1054, -1151, -1346, -1694, -1262, -334, 19, -73, 9, 444, 845, 872, 839, 984, 1220, 1739, 2260, 2007, 1162, 686, 864, 971, 690, 473, 645, 1131, 1446, 1429, 1306, 1071, 502, -233, -439, -300, -267, 188, 1152, 1940, 2463, 2870, 3114, 3191, 2990, 2469, 1859, 1531, 1435, 1121, 663, 681, 971, 827, 547, 628, 711, 543, 241, -209, -681, -836, -635, -259, -102, -505, -1087, -1377, -1157, -609, -296, -203, 71, 709, 1654, 2481, 2743, 2561, 2088, 1364, 835, 755, 817, 917, 1166, 1435, 1491, 1254, 1204, 1413, 1322, 1127, 1082, 942, 897, 979, 600, 59, 92, 287, 82, 31, 296, 364, 397, 476, 399, 447, 697, 695, 551, 803, 851, 55, -585, -499, -440, -605, -464, -22, 337, 651, 901, 828, 544, 72, -552, -945, -1047, -1488, -2140, -2061, -1508, -1320, -1371, -1064, -492, -56, 477, 930, 698, 628, 1285, 1735, 1856, 2170, 2593, 2694, 2453, 2113, 1602, 1381, 1804, 2030, 1766, 1583, 1683, 1797, 1634, 1398, 1372, 1409, 1377, 1329, 1219, 1130, 1064, 811, 502, 403, 594, 949, 937, 596, 864, 1732, 2439, 2611, 2529, 2782, 2985, 2957, 3151, 3380, 3763, 4534, 4946, 4812, 4650, 4276, 3423, 2702, 2518, 2206, 1699, 1870, 2538, 2700, 2337, 2178, 2142, 1960, 1850, 1472, 1018, 1087, 738, -373, -1067, -1208, -1364, -1564, -1694, -1710, -1578, -1597, -1981, -2116, -1483, -910, -928, -1121, -1420, -1681, -1608, -1504, -1236, -514, 222, 1021, 1951, 2504, 2600, 2469, 2387, 2369, 2118, 1910, 2105, 2276, 1968, 1701, 2196, 2829, 2593, 1957, 1733, 1754, 1830, 1900, 1911, 1997, 1932, 1477, 1238, 1263, 972, 747, 808, 691, 310, -230, -618, -517, -198, -56, -130, -108, 179, 508, 798, 866, 819, 905, 712, 196, -326, -674, -545, 229, 994, 1487, 1997, 2115, 2037, 2231, 2122, 1879, 2354, 3060, 3435, 3813, 3927, 3342, 2538, 1958, 1806, 2024, 2456, 2779, 2390, 1409, 621, 184, -52, 183, 745, 835, 214, -166, 176, 569, 657, 775, 1050, 1103, 767, 287, -9, 352, 1275, 1978, 2143, 2024, 1862, 1850, 1989, 1770, 1069, 532, 188, -315, -519, -209, 46, 180, 719, 1314, 1342, 1152, 1214, 1307, 1128, 962, 852, 587, 284, 161, 95, -26, -117, -136, -187, -300, -226, 38, 140, 126, 156, 402, 1062, 1439, 929, 434, 794, 1318, 1400, 1406, 1624, 1840, 1859, 1753, 1412, 934, 722, 655, 573, 680, 835, 639, 280, 105, -56, -303, -231, 228, 587, 867, 1144, 1103, 961, 952, 857, 531, 229, 385, 864, 1204, 1348, 1628, 2074, 2407, 2880, 3501, 3437, 2816, 2487, 2283, 1894, 1556, 1328, 1300, 1511, 1503, 1107, 827, 638, 322, -58, -700, -1409, -1830, -1777, -1373, -1007, -794, -642, -539, -427, -294, -413, -665, -670, -524, -396, -226, 32, 295, 410, 465, 716, 1069, 1181, 1065, 1064, 1262, 1196, 1093, 1514, 1861, 2023, 2408, 2496, 1951, 1405, 872, 212, 16, 191, 283, 173, 216, 557, 450, 112, 180, 335, 417, 377, 110, -73, 333, 989, 1353, 1704, 2033, 1950, 1489, 945, 639, 279, -484, -1052, -991, -723, -920, -1454, -1384, -529, 380, 1001, 1443, 1671, 1652, 1613, 1560, 1312, 983, 794, 599, 214, 35, 223, 258, -18, -217, -297, -505, -916, -1307, -1458, -1443, -1310, -948, -501, -137, 313, 799, 819, 506, 653, 900, 709, 647, 993, 1470, 1894, 2107, 2142, 1970, 1508, 724, -431, -1269, -1122, -766, -853, -963, -925, -902, -768, -447, -224, -373, -840, -1223, -1615, -2058, -1988, -1725, -1578, -1134, -588, -382, -352, -232, -66, -7, -216, -492, -421, 225, 1113, 1828, 2236, 2270, 2134, 1987, 1881, 1778, 1644, 1526, 1449, 1164, 961, 1354, 1685, 1306, 704, 701, 1187, 1510, 1424, 906, 169, -213, -80, -171, -480, -528, -464, -230, -100, -400, -680, -479, -127, -383, -941, -700, -91, 17, 26, 367, 887, 1234, 1320, 1197, 1021, 1027, 980, 605, 276, 196, 37, -56, 284, 701, 848, 848, 872, 1048, 1029, 666, 543, 657, 294, -382, -449, 29, 160, -111, 104, 701, 586, 56, 6, -22, -300, -260, -280, -735, -768, -307, -53, -132, -420, -384, 14, 161, 130, 55, -223, -311, 55, 460, 813, 1266, 1833, 1958, 1528, 1462, 1660, 1423, 986, 558, -16, -277, -175, -398, -859, -910, -786, -812, -775, -918, -1354, -1477, -1286, -1556, -1794, -1438, -1342, -1538, -1360, -897, -468, -39, 271, 299, 326, 405, 270, 373, 884, 1154, 1046, 901, 1079, 1329, 1129, 886, 847, 599, 300, 118, -313, -665, -489, -485, -1184, -1897, -1882, -1501, -1382, -1346, -939, -455, -591, -957, -788, -510, -497, -404, -280, -376, -573, -740, -754, -597, -668, -848, -755, -767, -837, -770, -868, -945, -689, -329, 43, 643, 1230, 1280, 1258, 1762, 1966, 1485, 1203, 1148, 741, 499, 808, 1283, 1773, 2235, 2616, 2743, 2458, 2442, 2754, 2365, 1450, 679, 225, 334, 615, 490, 313, 629, 946, 681, 310, 292, 160, -141, -128, -116, -337, -95, 661, 1153, 1433, 1699, 1404, 615, 159, 143, 41, -346, -913, -1287, -1264, -1129, -1172, -1332, -1388, -1489, -1656, -1481, -1153, -926, -768, -967, -1298, -1136, -734, -552, -468, -399, -283, 71, 659, 940, 700, 484, 538, 613, 543, 516, 526, 491, 616, 637, 217, -211, -258, -158, -249, -470, -534, -642, -1051, -1588, -1868, -1761, -1402, -1094, -1065, -1138, -1331, -1451, -1049, -601, -584, -821, -1005, -1110, -1313, -1665, -1853, -1595, -1275, -931, -263, 420, 657, 691, 875, 1082, 1300, 1204, 555, 206, 426, 548, 409, 128, -85, -150, -399, -444, -144, -303, -640, -472, -451, -1050, -1359, -755, -229, -456, -450, 236, 703, 522, 152, 64, -203, -784, -1179, -1437, -1561, -1613, -1728, -1762, -1709, -1494, -1174, -1105, -1160, -1049, -754, -237, 533, 1168, 1249, 1189, 1615, 1904, 1583, 1476, 1797, 1876, 1652, 1518, 1428, 1367, 1435, 1613, 1817, 1963, 2076, 1995, 1968, 2213, 2054, 1569, 1484, 1588, 1659, 1646, 1452, 1381, 1471, 1579, 1890, 1929, 1118, 348, 192, -85, -424, -180, 212, 506, 856, 1015, 1202, 1688, 1872, 1421, 932, 735, 704, 767, 684, 370, 338, 725, 874, 567, 159, -378, -965, -1301, -1454, -1435, -1356, -1307, -1141, -854, -767, -999, -1068, -721, -456, -563, -529, 179, 1132, 1317, 1034, 1369, 1811, 1736, 1839, 2028, 1532, 882, 981, 1507, 1562, 1153, 904, 765, 440, 154, -104, -579, -871, -584, -302, -436, -694, -805, -890, -1017, -1250, -1645, -1737, -1761, -2168, -2215, -1563, -854, -523, -199, 240, 318, 439, 746, 563, 289, 544, 994, 1261, 1128, 867, 1050, 1136, 301, -508, -271, -214, -952, -1161, -777, -847, -1470, -1945, -1658, -1195, -1266, -1522, -1515, -1405, -1306, -1011, -711, -625, -684, -613, -318, -317, -815, -937, -367, -434, -1275, -1626, -1241, -886, -977, -924, -474, -89, 199, 473, 673, 1004, 1230, 1043, 832, 593, 291, 333, 755, 1181, 1074, 637, 463, 490, 372, 24, -263, -279, -34, 330, 465, 226, -311, -794, -1011, -869, -285, 321, 614, 794, 981, 1018, 768, 291, -116, 117, 753, 904, 949, 1492, 1848, 1665, 1741, 1991, 1704, 1234, 1166, 1377, 1123, 302, -153, 303, 1006, 1023, 971, 1384, 1399, 706, -322, -1269, -1810, -1842, -1543, -1364, -1234, -459, 484, 690, 438, 109, 6, 302, 526, 552, 602, 620, 712, 837, 862, 814, 979, 1331, 1447, 1217, 713, 243, 183, 469, 641, 355, 336, 845, 983, 498, -293, -920, -982, -1083, -1612, -1731, -1410, -1643, -2207, -2128, -1723, -1660, -1455, -973, -1005, -1514, -1622, -1315, -1139, -906, -316, 332, 986, 1667, 1859, 1691, 1713, 1402, 475, -443, -935, -1027, -884, -673, -664, -962, -1006, -733, -887, -1116, -944, -1178, -1879, -2105, -1837, -1793, -2224, -2826, -3046, -2823, -2457, -2184, -2027, -1768, -1533, -1390, -1097, -710, -483, -487, -516, -478, -267, 239, 670, 771, 685, 328, -206, -464, -625, -1098, -1258, -793, -584, -956, -1096, -810, -547, -290, -175, -313, -398, -238, -38, -25, 42, 69, -470, -1064, -704, 196, 662, 685, 527, 374, 345, 360, 511, 635, 317, -108, -255, -230, 403, 1612, 2178, 1976, 1927, 1986, 1691, 1315, 1129, 839, 455, 120, -303, -498, -398, -207, 327, 866, 766, 284, -124, -43, 271, 70, -548, -1044, -1078, -812, -633, -381, 56, 366, 456, 118, -793, -1537, -1779, -1722, -1374, -757, 151, 1005, 1544, 1850, 1745, 1102, 283, 161, 544, 193, -306, -28, 488, 1046, 1504, 1386, 959, 485, -66, -224, -212, -409, -375, -322, -750, -1119, -693, -124, -192, -459, -743, -1042, -1023, -1047, -1354, -1457, -1251, -772, -155, 85, 13, 164, 706, 1168, 1085, 827, 735, 634, 354, 58, 250, 821, 969, 524, -191, -751, -877, -1239, -1902, -1976, -1460, -981, -868, -1037, -1343, -1718, -1923, -2064, -2316, -2560, -2744, -2650, -2497, -2418, -2001, -1541, -1631, -1886, -1484, -894, -1028, -1456, -1438, -1119, -705, -41, 644, 1046, 968, 547, 104, -399, -973, -1075, -676, -474, -437, -458, -455, -160, 90, -86, -409, -450, -256, -246, -710, -1210, -1147, -678, -98, 445, 664, 624, 558, 532, 529, 642, 996, 1384, 1437, 1224, 1033, 820, 323, -319, -509, -170, 180, 368, 600, 912, 1233, 1606, 1702, 1257, 355, -612, -1123, -1286, -1170, -924, -1050, -1237, -770, -31, 9, -286, -216, -266, -445, -409, -509, -704, -614, -415, -278, -51, -4, -503, -929, -991, -1359, -1989, -2247, -1965, -1182, -279, 272, 775, 1369, 1550, 1093, 375, -201, -533, -713, -833, -977, -875, -572, -653, -753, 98, 1290, 1784, 1861, 1986, 1981, 1385, 481, -234, -881, -1531, -1933, -1977, -1615, -1187, -1475, -2264, -2686, -2848, -3410, -4070, -4136, -3798, -3753, -4012, -4149, -4442, -4949, -4690, -4052, -4081, -3829, -2974, -2246, -1478, -502, 18, -107, -90, 149, 23, -498, -856, -900, -919, -527, 404, 1236, 1597, 1388, 963, 791, 622, 23, -548, -606, -741, -1318, -1633, -1773, -2387, -2962, -3052, -2932, -2984, -3365, -3830, -4018, -3942, -3741, -3529, -3455, -3051, -1836, -877, -865, -734, -381, -616, -898, -721, -932, -1571, -1931, -2179, -2331, -2027, -1468, -1296, -1370, -859, -114, 3, -141, -94, -168, -315, -284, -263, -152, 254, 387, 85, -91, 226, 571, 3, -950, -1226, -1090, -1142, -1232, -1381, -1520, -1353, -1046, -1156, -1846, -2382, -2104, -1503, -1456, -1687, -1718, -1582, -1453, -1344, -973, -714, -713, -250, 402, 638, 717, 833, 1215, 1891, 2032, 1733, 1934, 2522, 2893, 3030, 2758, 2055, 1394, 1004, 842, 675, 343, 313, 594, 406, -320, -813, -525, 106, 493, 1053, 1749, 1849, 1876, 2351, 2631, 2710, 3464, 4435, 4692, 4926, 5290, 5017, 4395, 3526, 2201, 1290, 1207, 1048, 359, -155, -144, -207, -528, -679, -482, -103, 74, 108, 404, 954, 1538, 2060, 2726, 3506, 3697, 3212, 2905, 2815, 2353, 1972, 2090, 2160, 2142, 2343, 2512, 2481, 2394, 2254, 1566, 380, -466, -1028, -1684, -2042, -1811, -1584, -1620, -1299, -669, -255, -368, -782, -1036, -1022, -1147, -1683, -1793, -1587, -1998, -2642, -2767, -2334, -1400, -277, 348, 586, 992, 1421, 1219, 656, 627, 774, 118, -1158, -1860, -1609, -1399, -1753, -1927, -1528, -1370, -1700, -1620, -1159, -1181, -1426, -1077, -705, -1066, -1412, -1334, -1402, -1238, -502, 37, 292, 298, -330, -1101, -1296, -1059, -932, -1205, -1473, -1314, -1428, -2041, -2725, -3411, -3653, -3321, -3113, -3206, -3326, -3364, -3024, -2380, -1925, -1764, -1502, -1244, -1559, -2312, -3085, -3895, -4526, -4397, -3516, -2530, -1928, -1652, -1242, -867, -1174, -1786, -2067, -1874, -1486, -1451, -1332, -622, -346, -863, -1110, -1288, -1972, -2406, -2413, -2316, -1840, -1121, -756, -788, -604, -118, 177, 284, 479, 651, 396, -231, -519, -455, -679, -1130, -1605, -2196, -2588, -2569, -2680, -3129, -3597, -4082, -4658, -4955, -4614, -4068, -3207, -1734, -581, -18, 601, 1142, 1272, 1325, 1749, 2413, 2893, 3067, 3116, 3159, 2805, 2022, 1696, 1971, 1912, 1355, 808, 489, 132, -630, -1747, -2445, -2276, -2013, -2383, -2768, -2345, -1719, -1671, -1339, -451, -48, -49, 151, 108, -212, -193, -92, -124, 151, 722, 1205, 1771, 1059, -71, -560, -70, 269, -211, -1173, -1702, -1434, -1065, -468, 546, 1270, 1935, 2408, 1750, 638, 53, -375, -743, -895, -1440, -2042, -1742, -1268, -1023, -93, 1276, 2085, 2379, 2626, 2234, 967, 239, 760, 1294, 942, 378, 296, 513, 678, 685, 703, 1101, 1715, 1962, 1613, 818, -43, -752, -1373, -1858, -1809, -1464, -1299, -1003, -651, -578, -608, -721, -928, -1268, -1778, -1675, -972, -377, -89, -496, -1187, -1205, -672, -314, -598, -1125, -935, -399, -221, -294, -525, -353, 280, 378, -95, -343, 125, 869, 1042, 951, 915, 675, 765, 1165, 1018, 268, -144, 498, 1380, 1296, 609, 170, 131, 323, 208, -95, 17, 136, -116, -289, 29, 597, 922, 1063, 1119, 810, 206, -83, 275, 687, 556, 157, -80, -125, -362, -1140, -1850, -1792, -1220, -730, -707, -469, 494, 1519, 2095, 1873, 1046, 378, -110, -471, -421, -334, -601, -865, -931, -993, -1048, -802, -451, -680, -1146, -1041, -707, -716, -946, -1259, -1828, -2206, -1734, -1284, -1532, -1523, -787, -171, 61, 16, -413, -801, -1147, -1404, -1096, -818, -1234, -1248, -110, 894, 1084, 1461, 2040, 2203, 2209, 2207, 2033, 1318, 495, 382, 935, 1504, 1704, 1839, 1925, 1320, 393, -4, 13, 236, 317, -6, -68, 427, 957, 1637, 2268, 2206, 2026, 2546, 3002, 2383, 1234, 695, 758, 841, 540, -688, -1918, -1753, -1245, -1605, -1957, -1683, -1112, -506, -170, -321, -612, -588, -540, -1089, -1919, -2123, -1644, -996, -733, -1220, -1713, -1615, -1253, -823, -215, 611, 943, 877, 1452, 2227, 2459, 2546, 2372, 1367, 0, -895, -1162, -995, -784, -859, -1080, -1609, -2210, -2225, -2196, -2485, -2137, -1483, -1359, -1438, -1276, -670, 102, 419, 50, -443, -655, -647, -668, -1024, -1315, -1206, -1115, -1067, -1111, -1549, -2070, -2071, -1578, -1601, -2228, -2477, -2316, -2198, -2071, -1881, -1546, -1138, -1122, -1387, -1485, -1711, -2246, -2683, -2921, -3158, -3166, -3016, -2889, -2208, -1277, -880, -554, -268, -577, -1031, -960, -823, -963, -657, -289, -661, -1081, -1097, -819, -526, -587, -834, -647, -365, -493, -577, -781, -1099, -941, -1112, -2086, -2675, -2455, -2094, -1897, -2051, -2407, -2429, -2344, -2380, -2138, -1772, -1372, -544, 45, -204, -658, -808, -760, -1051, -1880, -2335, -1860, -1014, -719, -1121, -1285, -591, 154, 43, -406, -709, -1229, -1621, -1278, -1108, -1967, -2928, -3086, -2382, -1769, -2108, -2436, -1923, -1135, -1072, -1855, -2404, -2316, -2065, -1675, -1339, -1283, -902, -40, 558, 232, -479, -557, -605, -1417, -2111, -1944, -1341, -771, -356, 83, 535, 590, 322, 57, -321, -807, -975, -808, -536, -508, -793, -630, 86, 491, 360, 246, 101, -231, -437, -611, -671, -936, -1761, -1901, -811, 307, 382, -319, -766, -510, -50, -449, -1151, -800, -149, -62, -325, -887, -1045, -509, -810, -1965, -2222, -1618, -1125, -861, -666, -286, 127, 108, -216, -859, -1598, -1749, -1955, -2682, -3179, -3500, -3800, -3784, -3588, -3597, -3879, -3947, -3448, -3004, -3343, -3910, -3939, -3529, -3047, -2659, -2700, -3037, -2647, -1721, -1581, -1968, -1278, 35, 389, -174, -1044, -1757, -1951, -1736, -1547, -1800, -2058, -1674, -1351, -1854, -2610, -2807, -2453, -2089, -2038, -2301, -2594, -2458, -1898, -1441, -1454, -1914, -2499, -2770, -2753, -2590, -2238, -1785, -956, -340, -1283, -2930, -3457, -3008, -2414, -1842, -1565, -1553, -1429, -1449, -1613, -1496, -1505, -1776, -1411, -564, -145, 132, 718, 1127, 812, 109, -157, 12, -96, -503, -948, -1304, -1146, -455, 35, -198, -1003, -1852, -2211, -2398, -3050, -3321, -2373, -1081, -368, -158, -54, 13, -173, -473, -767, -1181, -1329, -886, -38, 318, -139, -376, 229, 929, 990, 493, 3, -87, -247, -475, -454, -455, -722, -1233, -1658, -2152, -2931, -2858, -1233, 430, 910, 888, 1095, 995, 440, 217, 198, 91, 67, -228, -620, -746, -758, -673, -481, -269, -187, 18, 634, 1089, 899, 516, 24, -704, -696, -100, -128, -357, 106, 964, 1205, 865, 753, 531, -132, -597, -776, -916, -976, -1210, -1326, -1082, -1077, -1035, -412, 126, -144, -835, -1223, -891, 163, 741, 233, -261, -77, 5, -716, -1521, -1817, -1737, -1491, -1427, -1293, -689, 233, 1046, 1327, 1445, 1898, 2252, 1975, 1441, 1066, 623, -46, -505, -907, -1723, -2430, -2490, -2051, -1116, -79, 382, 646, 1059, 986, 491, 15, -500, -539, 69, 465, 166, -354, -959, -1630, -1764, -1342, -538, 726, 1694, 1451, 498, -449, -1440, -2199, -2228, -1850, -1411, -878, -388, -8, 86, 246, 844, 1051, 709, 476, 155, -163, -124, -43, -219, -615, -947, -947, -893, -1072, -900, -251, 184, 453, 767, 968, 1345, 1878, 2183, 2154, 1811, 1639, 2039, 2157, 1420, 682, 626, 842, 843, 589, 46, -398, -226, 285, 484, 224, 34, 127, 562, 1579, 2622, 3157, 3668, 4164, 3935, 3526, 3606, 3898, 4298, 4453, 4055, 3682, 3585, 3473, 3084, 2236, 1384, 1043, 1248, 1750, 2169, 2105, 1738, 1741, 1847, 1584, 1258, 1099, 1011, 845, 611, 451, 669, 1145, 1428, 1776, 1844, 1338, 1260, 1673, 1615, 1055, 592, 665, 728, 390, -58, -584, -700, -455, -672, -799, -145, 604, 1042, 1348, 1364, 876, 256, 65, 211, 139, -223, -174, 610, 1263, 951, 361, 113, 0, -32, -471, -1444, -1805, -1196, -915, -1153, -822, -288, -249, -302, -166, -121, -206, 3, 300, 24, -844, -1677, -1980, -2012, -1997, -1627, -1134, -892, -495, -204, -860, -1487, -1027, -343, -135, -218, -353, -168, 420, 1163, 1929, 2621, 2981, 3212, 3619, 3677, 3290, 2979, 2761, 2234, 1090, -386, -1346, -1556, -1617, -1792, -1555, -919, -477, -258, -47, -65, -512, -678, -180, 161, -93, -577, -799, -922, -1454, -1919, -1790, -1381, -1008, -994, -1234, -1256, -829, 98, 1193, 1596, 1072, 391, -88, -630, -1171, -1319, -920, -166, 553, 840, 805, 806, 984, 1184, 1118, 804, 540, 525, 796, 1103, 899, 529, 852, 1312, 987, 11, -843, -1190, -1462, -1580, -1410, -1552, -2008, -2085, -1698, -1513, -1606, -1308, -352, 538, 920, 1213, 1582, 1639, 1025, 356, 495, 1160, 1699, 1857, 1463, 643, 336, 858, 1243, 1188, 1062, 1019, 1323, 1798, 1831, 1403, 1090, 1329, 1677, 1155, -30, -765, -689, -343, -216, -132, 66, 204, 598, 1199, 1218, 778, 912, 2038, 3291, 3796, 3429, 2717, 2501, 2705, 2520, 1988, 1763, 1549, 676, -350, -802, -974, -1175, -1041, -561, -559, -869, -444, 127, 146, 276, 425, 250, 118, 245, 605, 1006, 1308, 1464, 1319, 1238, 1151, 879, 1011, 1135, 453, -276, -264, -24, -20, -127, -433, -599, -61, 730, 1021, 836, 780, 1120, 1379, 1516, 2033, 2740, 3369, 3685, 3167, 2091, 1056, 90, -823, -1420, -1235, -868, -703, -31, 617, 275, -481, -507, 43, 269, 314, 600, 816, 970, 1288, 1281, 1075, 1766, 3072, 3359, 2412, 1541, 1172, 968, 907, 852, 555, 208, 217, 331, 115, -364, -547, -38, 643, 508, -22, 194, 637, 606, 448, 204, 13, 572, 1767, 2314, 1864, 1303, 888, 566, 760, 1609, 2409, 2593, 2433, 2355, 2461, 2718, 2928, 3065, 3133, 2694, 1767, 681, -673, -2054, -2643, -2555, -2412, -1969, -1285, -930, -758, -323, 371, 815, 631, 493, 1010, 1489, 1203, 442, -206, -318, 311, 1154, 1515, 1948, 2742, 3008, 2634, 2030, 1295, 778, 647, 552, 181, -293, -522, -275, 109, 204, 212, 166, 317, 974, 1510, 1482, 1473, 1833, 2274, 2613, 2500, 2063, 1831, 1519, 1038, 627, 409, 378, 8, -532, -657, -716, -645, -204, 155, 253, 126, -274, -640, -667, -740, -1297, -1529, -765, 34, 361, 572, 498, 424, 727, 714, -63, -605, -473, -457, -663, -1104, -1686, -1731, -1307, -787, -137, 489, 706, 420, -167, -856, -1420, -1646, -1340, -817, -687, -814, -474, 93, -139, -776, -850, -332, 392, 776, 992, 1093, 774, 681, 847, 802, 709, 396, -29, -127, -377, -1082, -1453, -1095, -755, -798, -844, -934, -1145, -1191, -1075, -1156, -1512, -1503, -744, 0, 105, -40, 156, 673, 802, 397, 197, 426, 818, 1412, 1922, 1972, 1966, 2212, 2525, 2785, 2725, 2621, 2626, 2245, 1749, 1282, 589, 211, 197, -269, -998, -1028, -484, -288, -329, -264, -315, -341, 24, 612, 740, 257, -228, -238, -216, -422, -397, 143, 1083, 1680, 1679, 1454, 1251, 1482, 2054, 2149, 1409, 701, 791, 1135, 895, 309, 158, 507, 839, 962, 910, 660, 845, 1396, 1290, 633, 295, 300, 131, -316, -923, -1542, -1824, -1633, -1286, -987, -782, -423, 337, 1163, 1352, 646, 19, 49, -341, -1347, -1729, -1522, -1453, -1413, -1230, -989, -751, -566, -406, -205, -99, -23, 308, 938, 1223, 457, -479, -625, -394, -479, -1167, -1654, -1209, -474, 270, 827, 832, 1219, 2707, 4107, 4296, 3579, 2855, 2673, 2617, 2051, 1415, 1533, 1764, 1233, 543, 180, 228, 1028, 1683, 1094, 169, -71, 43, -75, -387, -162, 349, 505, 548, 573, 517, 857, 1585, 2155, 2203, 1525, 683, 516, 919, 1493, 1998, 2386, 2724, 2705, 2306, 1717, 908, 501, 796, 586, -208, -397, -259, -404, -458, -325, -69, 479, 1108, 1276, 973, 661, 247, -239, 28, 629, 557, 331, 342, 247, 153, 276, 898, 2038, 2993, 3523, 3974, 4098, 3875, 3858, 4048, 3777, 2888, 2303, 2375, 2451, 2292, 2322, 2893, 3344, 2760, 1743, 1012, 585, 300, -181, -729, -1112, -1373, -1377, -1232, -1508, -2047, -1753, -697, -413, -776, -748, -716, -735, -387, -96, -347, -560, 47, 801, 872, 616, 462, 706, 1171, 1113, 703, 581, 799, 1381, 1943, 1717, 905, 211, 76, 203, -75, -534, -724, -613, -280, -336, -718, -448, 596, 1216, 839, 430, 451, 498, 545, 733, 586, 276, 665, 1418, 1646, 1157, 212, -173, 411, 867, 575, 170, 258, 605, 501, -189, -592, -437, -591, -1441, -2504, -3259, -3413, -2890, -2188, -2173, -2896, -3713, -4302, -4793, -5057, -4606, -3600, -2626, -1665, -972, -953, -1059, -526, 405, 720, 266, -421, -749, -848, -1448, -2327, -2929, -3050, -2653, -2555, -3079, -3180, -2531, -1994, -1595, -949, -349, 264, 842, 635, -367, -1075, -747, 138, 747, 1013, 969, 691, 529, 460, 156, -211, -336, -123, 252, 289, -245, -534, -183, 123, 217, 300, 623, 1233, 1713, 1871, 1864, 1717, 1699, 1790, 1630, 1148, 413, -312, -756, -944, -950, -720, -450, -382, -366, -514, -885, -896, -478, -53, 17, -330, -418, 11, 254, -167, -716, -655, -376, -576, -1298, -2344, -2692, -1877, -1426, -1822, -2076, -1905, -1419, -1034, -1294, -1971, -2436, -2629, -2707, -2593, -2221, -1603, -708, 82, 203, -230, -406, 192, 808, 601, -43, -467, -366, 307, 1001, 1055, 787, 920, 919, 203, -727, -1537, -1775, -1250, -864, -1099, -1236, -987, -497, -90, -274, -697, -455, 258, 344, -107, -77, 253, 463, 773, 935, 947, 1108, 888, 439, 408, 232, -536, -1118, -1192, -1373, -1537, -1384, -1163, -983, -855, -939, -1276, -1515, -1458, -1326, -1268, -1339, -1246, -896, -769, -776, -655, -486, -518, -1154, -2243, -2885, -3267, -3985, -4150, -3472, -3198, -3365, -2868, -2009, -1713, -1673, -1323, -1126, -952, -444, -188, -168, 102, 359, 240, -22, -544, -1637, -2743, -3546, -4351, -5007, -5055, -4619, -4359, -4542, -4566, -3910, -2563, -1160, -748, -1261, -1652, -1692, -1788, -1928, -1997, -1949, -1836, -1864, -2395, -3270, -3512, -3162, -3145, -3614, -3904, -3919, -3839, -3067, -1631, -317, 532, 1130, 1575, 1793, 1644, 1033, 735, 1111, 1045, -174, -1698, -2270, -2036, -1976, -2078, -1796, -1104, -61, 731, 676, 462, 616, 756, 306, -485, -780, -790, -931, -1125, -1401, -1815, -2062, -2052, -2266, -2539, -2156, -1171, -330, -44, -43, -237, -520, -575, -626, -1051, -1886, -2557, -2290, -1490, -921, -729, -688, -431, 21, 332, 314, -6, -232, 261, 954, 901, 455, 92, -274, -309, 132, 194, -132, 22, 598, 868, 778, 441, 97, -171, -650, -1075, -1061, -720, -310, 85, 16, -344, -32, 242, -491, -1278, -1552, -1724, -1416, -585, -42, 260, 556, 860, 1145, 1167, 1025, 946, 1146, 1431, 1003, 104, -277, -210, -22, 184, 390, 665, 766, 715, 450, 34, -36, 197, 301, 96, 91, 497, 576, 292, 346, 390, 220, 221, 17, -210, -175, -439, -693, -251, 280, 266, 189, 355, 738, 1079, 1289, 1495, 1479, 1259, 941, 280, -115, 379, 755, 223, -478, -402, 204, 662, 1006, 1358, 1266, 936, 1247, 1908, 2062, 1640, 1421, 1696, 2022, 1779, 930, 495, 565, 282, -192, -388, -670, -841, -479, -177, -170, 280, 1236, 1793, 1649, 1573, 1743, 1933, 2213, 1936, 860, -174, -413, -31, 185, -166, -116, 622, 1070, 1444, 1871, 1469, 596, 442, 352, -335, -970, -1463, -1522, -1206, -1179, -1019, -478, -35, -66, -526, -990, -1285, -1471, -1439, -1415, -1755, -1935, -1244, -397, -123, -229, -724, -1423, -1795, -1911, -2106, -2379, -2527, -2233, -1464, -995, -1405, -2022, -2082, -1868, -1901, -2376, -2881, -2491, -1949, -2250, -2351, -1864, -1614, -1447, -1275, -1294, -1062, -531, -350, -1074, -2149, -2398, -1658, -887, -626, -582, -750, -960, -888, -980, -1554, -2164, -2408, -2447, -2696, -3141, -3177, -2827, -2678, -2650, -2271, -1930, -1825, -1248, -387, -31, -38, -66, 152, 391, 190, -319, -829, -891, -602, -932, -1697, -1667, -1024, -631, -521, -91, 676, 973, 880, 826, 440, -142, -420, -346, -596, -1411, -2054, -2023, -1481, -1148, -1357, -1304, -803, -548, -597, -911, -1451, -1568, -1430, -1698, -2349, -2873, -2854, -2175, -1062, -392, -410, -468, -681, -1225, -1869, -2685, -3541, -3898, -3878, -3873, -3844, -3663, -3269, -2989, -2849, -2638, -2345, -1701, -716, -6, 81, -106, 43, 327, 106, -129, 135, 508, 637, 520, 196, -173, -364, -217, -166, -397, -387, -390, -226, 446, 406, -338, -249, 296, 638, 994, 1014, 819, 996, 1355, 1269, 809, 168, -399, -512, -504, -530, -260, 35, 118, 149, 65, -70, -182, -355, -659, -1119, -1419, -1305, -932, -546, -453, -290, 469, 1106, 1022, 456, -499, -1477, -1677, -1635, -2010, -2259, -1913, -1032, -335, -142, -72, -56, -267, -495, -637, -905, -594, 635, 1102, 202, -261, -184, -384, -262, 12, -429, -1230, -1234, -767, -1152, -1922, -1910, -1467, -1105, -534, 94, 576, 1151, 1707, 1716, 1001, 161, 137, 563, 430, -40, -396, -626, -1075, -1782, -2168, -2101, -2022, -2185, -2296, -2118, -1912, -1566, -1061, -673, -156, 240, 329, 638, 1027, 1118, 751, -15, -594, -605, -357, -512, -1167, -1550, -1388, -1533, -2171, -2457, -2056, -1543, -1550, -1899, -1672, -781, -196, -188, -127, 274, 626, 837, 1151, 1064, 365, -203, -389, -683, -1319, -1896, -1681, -1063, -1353, -2104, -1951, -1142, -500, -30, 216, 119, 30, 562, 1126, 750, 15, -123, 508, 1024, 596, 387, 827, 973, 1119, 1276, 1074, 1074, 1339, 1503, 1403, 814, -143, -909, -1098, -771, -86, 538, 751, 866, 1104, 1112, 797, 408, -146, -784, -987, -1150, -1557, -1363, -728, -517, -386, -189, -542, -1174, -1617, -1972, -2185, -1965, -1387, -882, -532, -224, 532, 1435, 1077, -309, -1413, -2067, -2439, -2329, -2170, -2254, -2158, -1636, -1112, -814, -487, -233, 42, 764, 1536, 1669, 1061, 338, -96, -500, -624, -337, -70, 252, 808, 1229, 1492, 1974, 2286, 1869, 1227, 700, 247, 146, 523, 1069, 1085, 576, 433, 602, 152, -551, -825, -1048, -1501, -2044, -2154, -1734, -1491, -1644, -1728, -1629, -1594, -1359, -971, -849, -613, 65, 884, 1498, 1561, 1159, 1075, 1590, 1885, 1209, 367, 205, 254, 284, 270, 47, -130, 231, 989, 1073, 239, -502, -639, -477, -428, -795, -1369, -1505, -1378, -1604, -1902, -1871, -1426, -643, -264, -441, -514, -350, 43, 454, 459, 117, -155, -79, -7, -236, -419, -267, -117, -270, -599, -1327, -2284, -2575, -2003, -1324, -1076, -776, -276, -102, -221, -136, 81, 200, 119, -244, -439, -445, -698, -927, -674, 0, 771, 1094, 991, 710, -37, -785, -819, -275, 76, -55, -211, 2, 815, 1635, 1845, 1922, 2061, 1926, 1668, 1342, 840, 196, -543, -1095, -1055, -589, -444, -619, -530, -440, -1054, -1700, -1403, -760, -564, -372, 72, 179, 278, 821, 990, 661, 642, 820, 735, 120, -844, -1242, -895, -658, -572, -71, 539, 938, 1572, 2224, 2046, 1340, 816, 821, 976, 696, 335, 199, 291, 602, 655, 417, 382, 471, 455, 420, 618, 1362, 1964, 1643, 1215, 1259, 1349, 1411, 1563, 1668, 1504, 1453, 1804, 1607, 868, 460, 622, 1236, 1551, 1122, 611, 609, 975, 1264, 1117, 876, 931, 1226, 1339, 1129, 1015, 1360, 1991, 2137, 1749, 1227, 602, 72, -243, -560, -705, -557, -496, -468, -438, -739, -1131, -1126, -934, -885, -769, -541, -421, -266, -53, -27, 18, 304, 683, 848, 585, 328, 532, 767, 884, 1282, 1818, 1901, 1309, 627, 0, -808, -1140, -527, 113, 117, -228, -714, -821, -307, 364, 797, 1228, 2132, 2822, 2294, 1079, 381, 579, 1303, 1663, 1551, 1952, 2680, 2782, 2197, 1625, 1798, 2512, 3128, 3405, 3078, 2276, 1515, 1377, 1677, 1816, 2006, 2334, 2553, 2545, 2077, 1334, 1049, 1342, 1653, 1519, 1230, 949, 262, -344, -556, -818, -819, -342, 270, 699, 770, 729, 841, 1248, 1718, 1584, 830, 469, 878, 1211, 1063, 983, 1060, 1213, 1230, 672, 98, -21, 300, 1100, 1520, 1091, 986, 1842, 2598, 2029, 771, 181, 433, 993, 896, -134, -631, 9, 441, 482, 951, 1369, 1418, 1509, 1526, 1450, 1045, 326, -213, -874, -1797, -2149, -1630, -1070, -714, -337, -329, -612, -661, -724, -1076, -1375, -1195, -912, -992, -1080, -1324, -1834, -1887, -1707, -1967, -2109, -1662, -941, 19, 1120, 1425, 1075, 1640, 2753, 2816, 2065, 1630, 1645, 1787, 2032, 2459, 3057, 3551, 3609, 3464, 3469, 3373, 2957, 2507, 2209, 1855, 1167, 148, -1052, -1945, -2314, -2538, -2408, -2114, -2281, -2762, -3295, -3477, -3170, -2753, -2106, -1382, -829, -175, 390, 602, 565, 82, -663, -931, -1031, -1356, -1281, -748, -99, 416, 351, 179, 647, 1279, 1629, 1930, 2206, 2645, 3500, 3947, 3454, 3094, 3205, 2934, 2142, 1133, 329, 117, 152, -445, -1504, -1844, -1192, -179, 492, 478, 469, 1038, 1433, 1181, 766, 479, 364, 520, 731, 550, -55, -350, 20, 755, 1457, 1597, 1375, 1738, 2623, 3161, 2925, 2711, 2980, 3104, 3017, 3141, 3449, 3605, 3334, 2680, 1994, 1451, 784, -4, -726, -1318, -1508, -1093, -706, -985, -1644, -1908, -1589, -1153, -501, 553, 1334, 1813, 2879, 4188, 4687, 4343, 4270, 5156, 6025, 6076, 5592, 4997, 4522, 4120, 3698, 3129, 2284, 1369, 863, 879, 1205, 1978, 2892, 3445, 3633, 3191, 2522, 2628, 3368, 3898, 4039, 4291, 4633, 4664, 4471, 4220, 3788, 3216, 2532, 1725, 934, 353, 617, 1825, 3022, 3310, 2713, 1812, 941, 440, 146, -880, -1975, -1791, -1421, -2172, -3196, -3595, -3712, -3675, -3629, -3751, -3506, -2823, -2373, -2194, -1523, -473, 333, 762, 513, -47, -495, -1018, -1237, -1091, -1240, -1667, -1719, -1408, -1283, -1355, -1324, -978, -65, 1003, 1466, 1150, 985, 1418, 1544, 974, 387, 173, 120, 257, 427, 58, -439, -234, 111, -19, -264, -275, 115, 761, 1076, 546, -339, -536, -618, -1433, -2129, -2009, -1346, -867, -1046, -1692, -2242, -1938, -874, -81, 292, 752, 1170, 1124, 710, 486, 94, -604, -865, -906, -1664, -2988, -3620, -3428, -3218, -2916, -2442, -2038, -1497, -690, -362, -937, -1244, -832, -879, -1654, -2238, -2031, -1257, -625, -591, -820, -728, -514, -310, 9, 362, 664, 633, 444, 405, 220, -171, -172, 653, 1506, 1124, -121, -974, -1145, -987, -1115, -1517, -1440, -941, -580, -616, -897, -1310, -1922, -2708, -3650, -4206, -3589, -2129, -1049, -559, -105, 225, 455, 935, 1154, 657, 250, 434, 612, 195, -695, -1489, -2041, -2321, -1978, -1246, -707, -233, 221, 319, -45, -533, -739, -691, -668, -971, -1513, -1547, -962, -708, -1179, -1283, -642, -204, -66, -55, -613, -1413, -1547, -1203, -1510, -2152, -1916, -1343, -2400, -1945, -2878, -2410, -1437, -2757, -4156, -3872, -3083, -2944, -4280, -4866, -2504, 3, -918, -3154, -3323, -2553, -1866, -1137, -716, -1048, -1878, -1187, 742, 1073, -224, -943, -499, -555, -1220, -1033, -1005, -2445, -3801, -4188, -4983, -5762, -5725, -5490, -5387, -5361, -4702, -3629, -2710, -1725, -988, -576, -759, -1684, -2029, -1403, -1196, -1195, -1444, -2815, -3125, -1862, -1376, -1658, -1908, -2355, -2394, -2347, -2196, -1657, -2005, -3059, -2993, -1634, -1791, -3150, -2049, -89, 297, 654, 1541, 2000, 2207, 3232, 3370, 464, -2042, -1742, -891, -633, -401, -409, -35, 1225, 1872, 2212, 2685, 2038, 1263, 980, -211, -1166, -714, -647, -1235, -1607, -1385, -1571, -2814, -3158, -2692, -3236, -3769, -3183, -2028, -1631, -1829, -1904, -1835, -633, 677, 303, 36, 919, 1818, 2250, 2017, 1485, 1033, 50, -1310, -1772, -1971, -3023, -3298, -1948, -1298, -1603, -931, 74, 503, 921, 1395, 2247, 3041, 2088, -85, -1422, -1497, -973, -712, -1349, -2080, -1893, -995, -547, -1128, -2328, -3287, -3240, -2112, -676, -727, -743, 1513, 2445, 1330, 2101, 3125, 2448, 1609, 671, -633, -1815, -2395, -2749, -2477, -1762, -2609, -3671, -2251, -119, 805, 1353, 1786, 2129, 2858, 3116, 2129, 1647, 1755, 858, -112, -228, -634, -963, -579, -744, -1296, -1670, -1532, -829, 92, 1245, 1929, 1804, 2077, 2927, 2820, 1849, 1832, 2354, 2628, 3412, 3436, 2117, 1431, 1400, 1791, 2928, 3156, 2004, 1134, 496, -387, -887, -1492, -1546, -185, 662, -395, -1278, -683, -26, 31, -77, 193, 628, 439, -96, -290, -281, 245, 1236, 1407, 1790, 2974, 2928, 1807, 1110, 945, 653, 188, -642, -1544, -1225, -568, -1170, -1784, -1394, -736, -669, -1213, -1090, -1134, -2418, -2942, -2515, -2714, -3348, -4091, -4123, -2645, -1067, 113, 965, 640, 54, 351, 236, -801, -2090, -2982, -3155, -3376, -3963, -4535, -4657, -3846, -3000, -3375, -3689, -2717, -1672, -1885, -2797, -2942, -1588, -196, -154, -230, 392, 328, -581, -573, 292, 27, -822, -602, -113, 226, 833, 1077, 1048, 1378, 1238, 630, 1115, 1774, 1360, 1496, 2267, 2618, 2652, 2940, 3159, 2318, 1666, 1823, 1882, 1703, 1592, 1158, 331, -97, -220, -589, -1517, -1971, -1694, -1390, -1290, -1607, -1214, -334, -676, -1565, -1290, 79, 835, 1128, 1829, 2086, 2383, 3508, 3891, 3057, 2759, 3207, 3300, 3072, 2527, 544, -1394, -1534, -1826, -2297, -2171, -2845, -2449, -357, 939, 1445, 1780, 2070, 2161, 1721, 1047, 626, 757, 894, 1177, 1290, 653, 536, 1347, 2262, 2925, 3556, 4416, 4866, 4805, 4560, 3272, 1394, 672, 1205, 1509, 804, -23, 177, 482, -455, -1482, -2024, -2527, -1900, -413, -468, -496, 1426, 2830, 2359, 2040, 3231, 4069, 3209, 2636, 2511, 1423, 896, 1833, 2212, 1388, 1108, 2186, 2722, 2113, 2455, 3353, 2887, 2006, 1778, 2078, 2055, 1699, 2009, 2269, 1641, 569, 113, 547, 716, -136, -1246, -1564, -1302, -1099, -1021, -1386, -1845, -963, 671, 370, -1733, -2659, -1327, 45, -299, -1417, -1850, -1889, -1857, -1697, -1722, -1748, -1260, -444, -390, -1318, -1652, -557, 278, -90, -458, -142, 159, 1019, 2107, 1328, 129, 996, 2586, 3062, 2666, 2185, 2400, 3119, 2972, 2255, 1759, 1012, 315, 686, 1331, 1324, 955, 504, 691, 1532, 2879, 3681, 2759, 2292, 3034, 2785, 2076, 3076, 4100, 3671, 3829, 4031, 2608, 2036, 2809, 2504, 1988, 2511, 2898, 2307, 1215, 1045, 1785, 1817, 1506, 1406, 738, 369, 758, 1278, 1318, 253, 219, 2423, 3384, 2281, 2209, 3200, 3153, 1973, 1811, 3328, 4823, 5195, 4993, 5357, 5656, 5234, 4788, 3987, 3373, 3058, 2076, 1390, 1588, 1940, 1908, 1622, 1903, 2089, 1817, 2032, 2045, 2157, 2478, 1672, 1300, 2658, 3317, 2535, 2089, 1680, 1305, 1867, 2611, 2949, 2250, 1146, 1329, 1961, 1883, 1635, 1697, 1513, 855, 1025, 1657, 657, -931, -242, 1813, 2491, 2160, 1523, 725, 1110, 2086, 2506, 2661, 2942, 3344, 3363, 3383, 3479, 2915, 2632, 3019, 2812, 2795, 3621, 3952, 3214, 1905, 447, -23, 985, 1765, 1435, 681, 112, -67, -269, -566, -550, -15, 769, 913, 865, 494, -729, -817, 519, 365, -827, 31, 2413, 3259, 2226, 1595, 1678, 2048, 3180, 3958, 3428, 2886, 2709, 1572, 601, 1176, 1406, 1075, 624, 76, 1425, 3506, 3670, 2802, 2195, 1537, 899, 990, 981, 543, 866, 1606, 2002, 1598, 1443, 2446, 1709, -168, 292, 1941, 1986, 412, -844, -287, 1625, 2286, 1709, 2603, 4187, 4599, 4500, 3710, 1945, 1330, 1659, 1384, 1030, 191, -730, -151, -165, -1888, -1624, 628, 2120, 3240, 4058, 3589, 2885, 3340, 4266, 4229, 3263, 2418, 2071, 1452, 765, 981, 1651, 2465, 3348, 3423, 2314, 1705, 2505, 2670, 1469, 748, 924, 942, 864, 967, 703, 454, 341, 654, 1884, 2563, 2205, 2410, 3238, 2388, -85, -1632, -1716, -1143, -127, 241, 194, 929, 2219, 3954, 4695, 4091, 4208, 4438, 3857, 3951, 4642, 4372, 3821, 4082, 3533, 1921, 1726, 2335, 2521, 2380, 1438, 967, 1759, 1567, 248, -410, -612, -609, -115, 271, -496, -1513, -1272, -517, -378, -818, -984, -117, 679, 289, 197, 1120, 2031, 2945, 2977, 1600, 1369, 2083, 2078, 2159, 2487, 2447, 2182, 2396, 2892, 2963, 2456, 1217, 70, 78, 336, 352, 147, 173, 797, 452, -339, 463, 2324, 4666, 5724, 4410, 4001, 4796, 4661, 4711, 4394, 1954, 344, 1326, 1726, 490, -193, 782, 2141, 2432, 2544, 3474, 3459, 1911, 2198, 4138, 4167, 3019, 2479, 2130, 1845, 1382, 395, -782, -1351, -1350, -1854, -2642, -2269, -1484, -2514, -4283, -4355, -3084, -1663, -1214, -1387, -683, 560, 1578, 2564, 3803, 4450, 4252, 4317, 4470, 3161, 1818, 1923, 1578, 492, -218, -305, 521, 1618, 1782, 1021, 1142, 2289, 2384, 1867, 1424, -88, -1911, -2132, -1510, -1610, -2297, -3006, -3244, -3014, -1951, -1203, -2724, -3368, -1745, -711, -976, -1208, -230, 1633, 2711, 2876, 2837, 2142, 1629, 2234, 2564, 2355, 2239, 2136, 2060, 1678, 918, 217, 421, 902, 540, -85, -544, -1128, -933, -105, -406, -1223, -865, -221, -260, -278, -103, -135, -459, -605, 203, 965, 458, 593, 2322, 3147, 2809, 2957, 3598, 4061, 3816, 2987, 2211, 2379, 2575, 1632, 947, 1315, 1469, 1064, 246, -1016, -1588, -1204, -1009, -1542, -2159, -1985, -1219, -947, -1157, -1445, -2117, -2511, -2234, -2215, -2161, -2138, -3027, -3447, -2333, -1051, -220, 166, -274, -1072, -1290, -501, 69, -303, -702, -1275, -1924, -1214, -680, -1683, -2189, -2202, -2502, -2836, -2865, -1828, -1297, -2518, -3180, -1697, -653, -2184, -4269, -4616, -4233, -4105, -3781, -3389, -2146, -530, -415, -708, -358, -228, -466, -1163, -1583, -1247, -1626, -2324, -1785, -1062, -1417, -1465, -164, 495, -461, -644, 321, 859, 865, 888, 869, 626, 643, 1482, 2062, 1241, -130, -860, -721, -620, -1193, -1845, -2432, -2866, -1599, 304, 31, -968, -399, 1028, 1135, 111, -55, 284, 265, -301, -1097, -373, 727, -769, -2792, -2549, -1339, -800, -891, -692, -201, 115, 294, 234, 37, -722, -1660, -1702, -1532, -1848, -1587, -1430, -2387, -2693, -1713, -1696, -3098, -3522, -2389, -1184, -1700, -2592, -1525, -311, -616, -1148, -1310, -301, 1550, 1999, 1403, 726, 500, 928, 843, -168, -1462, -1871, -1585, -2069, -2393, -1802, -2525, -3555, -2526, -2216, -2845, -2188, -2132, -3267, -3605, -2994, -2435, -2364, -2300, -1333, 193, 1378, 2635, 3161, 1922, 1066, 1589, 2198, 1834, 493, -319, -350, -955, -1427, -622, -104, -491, -566, -583, -1181, -1505, -860, -101, 478, 1382, 1300, -124, -454, 180, -46, -518, -866, -982, -489, -264, -762, -1540, -2436, -2885, -1832, -909, -2381, -3703, -2712, -2195, -3084, -3384, -3195, -3312, -3277, -3236, -3385, -3117, -2024, -966, -778, -684, -264, 134, 302, 37, -195, -126, -24, 78, 236, -160, -1336, -2313, -2310, -1958, -2117, -3114, -4099, -3138, -1517, -1239, -960, 18, 545, 319, -44, -123, 566, 1070, 456, -303, -996, -1666, -2242, -2429, -2488, -3829, -4638, -3248, -1951, -2769, -4067, -4323, -4044, -3209, -2168, -1165, -540, 141, 1358, 1760, 1560, 1291, 286, -263, -220, -1326, -2864, -2939, -1907, -867, -1254, -3204, -3779, -2091, -772, -1409, -2713, -3238, -3251, -3304, -3413, -3715, -3549, -2764, -3055, -4505, -5106, -4920, -5135, -4649, -3569, -3498, -3774, -3136, -1898, -1689, -2700, -3158, -2450, -1605, -1726, -3134, -3915, -2843, -2599, -4160, -4913, -4460, -4037, -3494, -3191, -2603, -1540, -1591, -1417, -604, -382, -517, -1225, -2466, -2331, -1464, -1872, -1823, -1093, -1482, -1871, -1573, -1729, -1906, -1250, -188, 829, 1485, 1698, 1898, 1533, 145, -427, 351, 423, -1107, -3081, -3631, -2754, -2563, -3175, -3800, -4212, -3928, -3278, -3017, -2442, -1204, -739, -809, -163, 537, 137, -832, -897, -358, -80, 43, 169, 101, -49, 273, 280, -760, -902, -4, -140, -761, -662, -121, 860, 1823, 670, -884, -230, -211, -1893, -2511, -2109, -1763, -929, -3, 120, 368, 835, 419, -282, -465, -124, -46, -236, 904, 2145, 1437, 585, 569, 310, -32, -40, -556, -2150, -2843, -2661, -3284, -3453, -3298, -3348, -2436, -2373, -3270, -2886, -1875, -1311, -737, 333, 1233, 1731, 1469, -31, -1548, -1468, -569, -842, -1529, -1329, -1781, -2164, -266, 1146, 239, 305, 1710, 1355, 93, -455, -297, 426, 723, 419, 515, 703, 875, 1370, 1308, 94, -1079, -814, -85, 196, 412, -115, -1168, -830, 293, 133, -528, 116, 1286, 729, -656, -825, 373, 1191, 201, -692, 206, 1601, 1544, 923, 613, -239, -778, -240, -277, -925, -1292, -2339, -2795, -1948, -1877, -2681, -2836, -1977, -1853, -2661, -2583, -2941, -3759, -3149, -2350, -2358, -1941, -1269, -800, 353, 1081, 190, -438, 703, 1587, 1458, 2175, 3489, 3928, 3689, 3485, 2791, 1875, 1530, 1256, 986, 1142, 632, -478, 17, 891, -38, -497, 626, 589, -847, -1157, 379, 1850, 2050, 1469, 1111, 1219, 1165, 462, -213, -101, -116, -89, 891, 1566, 1703, 2238, 2313, 2011, 1674, 1068, 798, 509, 357, 1390, 1281, -701, -1177, -686, -1523, -2131, -1223, 373, 1451, 1508, 1167, 480, -231, 95, 1322, 1273, -290, -146, 921, 246, -514, -686, -1119, -662, -360, -1595, -1390, 453, 601, 263, 645, 271, -57, 410, 609, 659, 1038, 1013, 423, -597, -1372, -812, -89, -1173, -2578, -2297, -1802, -1510, -395, 1217, 1673, 267, -1150, -1410, -1287, -1168, -1217, -1298, -1272, -1893, -2021, -1659, -2596, -3010, -1608, -416, -438, -615, -131, 1108, 2224, 2058, 869, -117, -160, 169, 440, 36, -904, -1649, -2494, -2490, -1020, 360, 637, 354, 8, -176, -206, -75, 163, 324, 137, -333, -634, -182, 1405, 2255, 725, -1084, -1274, -1392, -2078, -2433, -2332, -1571, -1077, -1732, -1845, -492, 1072, 1940, 1603, 934, 1094, 1330, 1592, 2936, 3895, 2744, 1129, 950, 1081, 814, 1203, 1185, 727, 1628, 2118, 969, 874, 1446, 1486, 1667, 1254, 854, 1691, 2073, 1263, 947, 1241, 1266, 1058, -19, -1194, -875, -952, -1387, -563, -868, -1796, -801, 935, 1891, 1981, 2117, 3112, 3833, 3378, 2834, 2706, 2578, 2043, 942, -151, -1212, -1796, -1548, -1390, -1445, -1421, -1240, -458, 336, 164, -6, 896, 2385, 2899, 1534, -529, -1197, -767, -1020, -2062, -2045, -432, 764, 1348, 1530, 1480, 2068, 2914, 3580, 3534, 2024, 234, -435, -430, -945, -2367, -2800, -1463, -400, -263, -716, -701, 1105, 2506, 1236, -250, 311, 1174, 1716, 2534, 2377, 1508, 1684, 2463, 1944, 119, -572, 53, -347, -1331, -1496, -1370, -675, 501, 1493, 1629, 505, -574, -500, 949, 1663, 416, -172, 737, 1462, 1526, 1755, 2043, 1817, 2072, 3366, 3948, 3176, 2352, 1741, 1610, 3090, 5027, 5685, 4998, 3779, 3734, 4017, 2965, 2733, 2860, 1477, 812, 749, 178, 449, 764, 433, 338, 232, 663, 1376, 799, -396, -595, 170, 820, 1093, 1966, 2801, 2448, 2133, 2246, 1969, 1985, 2081, 1925, 2408, 2579, 2135, 1740, 1488, 2135, 3182, 3966, 3885, 2252, 1608, 3189, 3306, 1620, 1047, 885, 328, 152, 415, 1002, 1328, 588, 966, 3191, 3582, 1833, 702, 989, 2300, 3590, 3741, 3435, 4135, 4771, 4481, 4040, 3886, 4040, 3636, 2758, 3033, 3263, 2249, 1550, 1044, 656, 1184, 2322, 3897, 5410, 4922, 3419, 3034, 2681, 1792, 745, -560, -1399, -899, -219, -721, -1209, -1075, -90, 2468, 3908, 2944, 2907, 3689, 3275, 2939, 3094, 2237, 1310, 1714, 1563, 275, -849, -1032, -289, 387, 69, -246, 994, 2235, 2262, 1808, 1030, 884, 2245, 3258, 2575, 1735, 1103, 373, 512, 1308, 1305, 441, 525, 1833, 2904, 2783, 2565, 3351, 3375, 2188, 1809, 2559, 2556, 2307, 2369, 1291, 737, 1630, 1992, 1838, 1319, 667, 1390, 1834, 1097, 965, 979, 870, 1481, 2707, 3328, 3109, 3052, 2781, 2236, 2197, 2401, 2589, 2781, 2664, 1890, 1077, 1291, 2126, 2235, 1295, 129, -96, 554, 522, -382, -1221, -1185, -679, -885, -1129, -613, 53, 683, 1275, 1378, 1393, 2172, 2702, 1770, 961, 995, 565, -211, -245, -314, -866, -725, -138, 267, 1256, 2382, 2146, 927, 547, 1233, 1718, 1519, 1497, 1950, 1792, 556, -332, -17, 34, -287, -156, -693, -1483, -918, 194, 878, 1405, 1694, 2757, 4460, 4359, 2439, 999, 787, 1129, 1682, 1812, 1557, 1553, 1999, 2666, 2510, 1192, 163, 538, 2317, 2811, 1173, 315, 1002, 1987, 2259, 2435, 2902, 2502, 1420, 801, 511, -56, -386, -135, -49, -529, -560, 19, 591, 1264, 1313, 325, 745, 2883, 2637, 1093, 1970, 2842, 2024, 1840, 2223, 1880, 1018, -307, -383, 615, 872, 1398, 1526, -135, -934, 609, 1539, 326, -297, 704, 724, -138, -45, 459, 219, -497, -845, -454, -90, -575, -1607, -2124, -1503, -611, -1154, -2520, -2591, -1330, -344, -755, -1549, -1094, 120, 311, 471, 1611, 2138, 1358, 809, 1337, 2029, 2310, 1887, 1612, 2111, 2024, 926, 96, -181, -470, -843, -1163, -1086, -184, 594, 430, -32, -34, 84, -151, 34, 594, 151, -1281, -2290, -2057, -1718, -1842, -1583, -789, 242, 662, 543, 820, 1348, 2022, 2173, 1512, 1296, 2262, 3771, 3691, 1513, 776, 2663, 3356, 1628, 99, -403, -497, -251, -842, -1851, -1764, -2091, -2281, -794, 41, -678, -1018, -200, -74, -1928, -3166, -2384, -1455, -1261, -391, 791, 989, 1410, 2388, 2027, 759, 464, 1046, 1784, 2045, 1769, 1516, 698, -516, -1107, -1176, -669, 238, 343, -713, -1842, -2285, -2244, -1549, -724, -233, 76, -7, 119, 484, 594, -211, -1247, -677, 553, 686, 319, 439, 467, -144, -1064, -1385, -691, -183, -632, -1019, -1050, -572, 458, 1212, 1117, -67, -977, -1305, -1262, -291, 229, -861, -1943, -1543, -834, -1121, -1472, -944, -780, -1491, -1400, -921, -1207, -1024, -660, -1268, -651, 1175, 1142, 686, 970, 558, 165, 904, 1806, 1466, 441, 279, 779, 438, -562, -1264, -1564, -1264, -782, -1264, -2802, -4162, -3158, -1429, -1634, -1128, 578, 186, -754, -138, 456, 204, -384, -1032, -1383, -1221, -893, -476, -363, -259, -185, -634, -578, 555, 745, -941, -1788, -1023, -373, -625, -704, -432, -428, 82, 734, 398, -71, 275, 833, 1239, 1535, 890, -809, -1356, -432, -382, -1238, -956, -216, -737, -1839, -2331, -2486, -2887, -3029, -2473, -1300, -598, -1059, -1518, -1082, -358, -368, -582, -215, -560, -1105, 161, 1891, 2390, 2317, 1891, 1477, 1639, 2208, 2525, 1876, 1039, 1252, 1275, 726, 1210, 1722, 1104, 1151, 1821, 896, -1173, -1936, -1269, -1250, -1975, -1862, -1585, -1522, -742, -765, -2753, -4173, -3439, -2147, -2125, -2641, -2149, -1546, -1397, -1206, -1048, -558, 216, -150, -1622, -1813, -968, -248, 771, 641, -661, -1022, -289, 170, 73, -248, -1204, -2201, -1762, -476, 17, 198, 348, 540, 538, -652, -1834, -1477, -771, -888, -965, -345, 460, 287, -380, -81, 107, -514, -272, 697, 1063, 376, -193, 210, 13, -1068, -512, 1087, 647, -150, 853, 1596, 978, 240, 489, 1277, 962, -834, -2080, -1342, 4, -28, -1281, -1082, 823, 1347, 135, -614, 996, 2312, 589, -306, 423, 362, 795, 1437, 518, -1738, -3172, -1976, -300, 122, 390, -21, -692, -322, -314, -1058, -1485, -1543, -1862, -2344, -1906, -1287, -1607, -1696, -857, 77, 814, 1726, 2465, 1860, 661, 314, 266, -263, -1232, -2340, -2602, -1406, -216, -247, -1155, -1715, -723, 334, -447, -1794, -2162, -2242, -2310, -1498, -1086, -2237, -1999, -18, 160, -1249, -2415, -2540, -1619, -979, -470, 92, 113, 348, 595, 85, -624, -415, 587, 996, -433, -2503, -3221, -3226, -2917, -2819, -3423, -3949, -3441, -2496, -2710, -3451, -3619, -3259, -3160, -3263, -3573, -4325, -3911, -2315, -1591, -1923, -2539, -2507, -1432, -362, 525, 377, -926, -844, 894, 1637, 480, -1162, -2049, -1663, -1025, -1421, -1807, -1431, -1862, -2953, -2844, -2564, -2993, -2951, -2584, -2101, -1401, -1101, -951, -327, -76, -681, -681, 178, 399, -18, -410, -495, 5, 548, -233, -1429, -1345, -1093, -1007, -428, -836, -2070, -1555, -284, -240, -703, -839, -1431, -1945, -1161, -275, -370, -527, -684, -958, -878, -1233, -1956, -2755, -3434, -2691, -1653, -1526, -1711, -1776, -1473, -933, 326, 1982, 2285, 1533, 797, -464, -522, 1255, 2016, 807, -625, -1586, -1536, -773, -1487, -2619, -1534, 583, 770, 99, 848, 1376, -405, -2878, -3432, -2950, -3407, -3425, -2559, -1977, -1247, -116, 878, 275, -1529, -1865, -1015, -776, -1247, -1742, -1549, -885, -459, -599, -1865, -3282, -2465, -1482, -3249, -4416, -2859, -1595, -1925, -2239, -2158, -2004, -1593, -1171, -689, -685, -2032, -3530, -3466, -3011, -3822, -4412, -3309, -1999, -1483, -864, -97, 477, 643, 194, 182, 997, 1035, -1, -431, -1131, -1802, 94, 2090, -63, -3411, -4146, -4031, -4182, -4104, -3850, -3564, -3879, -4686, -4403, -3512, -3130, -2372, -1690, -1823, -1698, -1898, -2964, -3330, -3035, -2861, -1950, -787, -298, 201, 385, 295, 222, 318, 300, -15, 175, 146, -642, -1290, -541, 874, 603, 110, 1675, 3391, 3172, 2187, 1971, 1962, 1287, 901, 942, 103, -334, 458, 428, -398, -879, -1281, -1292, -818, -1177, -1521, -1085, -1897, -2916, -1703, -500, -1733, -2752, -1778, -1315, -1753, -1614, -2356, -3626, -3079, -1611, -1437, -1967, -1419, -325, -719, -1937, -1822, -953, -357, 194, 80, -538, -517, 15, 256, -14, -132, 277, 1365, 2817, 3553, 3137, 2033, 1416, 1416, 1519, 1952, 1609, 474, 130, -549, -2093, -2320, -1416, -1267, -1178, -421, -786, -2473, -2930, -2812, -3987, -4322, -2922, -1949, -2055, -2478, -2605, -2263, -1776, -883, 542, 1469, 1514, 1165, 342, 310, 1902, 1901, 478, 112, -476, -1341, -883, 331, 116, -962, -965, -569, -258, 220, -137, -664, -857, -2266, -4274, -5229, -5773, -6497, -6409, -5012, -3443, -2861, -2512, -1237, -314, -931, -2429, -3046, -2219, -2771, -4807, -5084, -4448, -4764, -4907, -4458, -4217, -4009, -3787, -4071, -4079, -2904, -1780, -1570, -813, 853, 1063, -450, -1221, -1253, -2412, -3914, -4452, -4584, -3806, -2889, -3288, -3777, -3402, -2176, -578, -109, -568, 109, 1127, 378, -951, -754, -96, -614, -1121, -1540, -2673, -2321, -240, 932, 428, -25, 542, 1528, 1898, 976, 43, 697, 1384, 274, -550, 80, 93, -1082, -1171, -31, -464, -2763, -4198, -4165, -4193, -5098, -6604, -6927, -5077, -2746, -1710, -1815, -2205, -1581, 197, 1121, 340, -325, 300, 1380, 1671, 852, 665, 1290, 1246, 533, 252, -57, -1063, -630, 573, 643, 987, 1804, 1975, 1401, -360, -1592, -798, -237, -966, -1569, -1884, -2579, -2853, -2363, -2285, -2319, -1439, -92, 798, 797, 1102, 1729, 1314, 735, 367, 344, 1189, 1574, 858, -420, -1037, -396, 139, 248, 597, 1008, 1162, 1308, 1696, 1664, 840, 381, 1358, 2361, 2411, 2238, 1759, 2416, 3633, 2400, 356, 264, 603, 550, 1047, 1185, 183, -391, 800, 1160, -251, -401, 961, 1637, 1289, 1001, 645, -104, -780, -1156, -1064, -112, 1319, 1790, 1258, 1399, 1972, 1901, 2153, 2515, 1683, 584, 132, -114, -424, 188, 1720, 2289, 1309, 99, 499, 1225, -505, -2527, -2586, -2185, -3147, -4387, -4084, -3278, -3342, -3118, -1681, -180, -47, -565, -596, -61, 737, 1247, 1265, 1055, 849, 41, -245, 1320, 2962, 3767, 4312, 4034, 3105, 2186, 1745, 1757, 1957, 2376, 2128, 227, -1265, -452, 231, -1147, 2195, -58, -540, 1159, 2843, 2119, -467, -2073, -1317, -311, -1455, -3710, -4430, -2943, -1127, -1331, -3381, -4718, -3984, -2704, -3053, -5150, -6771, -5614, -2592, -1037, -1762, -2129, -82, 2963, 3711, 1473, -809, -581, 1238, 1693, -112, -1861, -1285, 892, 1860, 368, -1963, -2757, -1314, 219, -513, -2735, -3517, -2165, -1160, -1990, -3681, -4363, -3187, -1784, -2268, -4318, -5223, -3528, -1319, -1076, -2748, -3955, -2578, -303, 6, -1591, -2899, -2009, 155, 821, -530, -1845, -1426, 464, 1407, -109, -2153, -2138, -328, 769, -132, -1756, -1950, -397, 587, -641, -2783, -3645, -2701, -1540, -2100, -3899, -4510, -2527, 165, 72, -2600, -4507, -4343, -3508, -3774, -5348, -5952, -4024, -1701, -1596, -3335, -4558, -3506, -1304, -786, -2572, -4230, -3555, -1368, -323, -1334, -2599, -2086, -30, 1073, -231, -2249, -2527, -1050, -164, -1378, -3286, -3512, -1497, 922, 1431, -87, -1312, -626, 268, -889, -3187, -4116, -2942, -1162, -855, -2251, -3010, -1611, 157, -115, -2158, -3742, -3464, -2257, -2407, -4237, -5447, -4489, -2379, -1571, -3254, -5242, -4495, -1615, 104, -622, -1703, -1109, 683, 2160, 2361, 1409, 941, 2050, 3167, 2169, -311, -1434, -304, 889, 262, -1192, -1378, -133, 956, 537, -638, -332, 2151, 4709, 4916, 3046, 1822, 2468, 3628, 3885, 2419, 366, 416, 2243, 2882, 1856, 1150, 1962, 3860, 5202, 4689, 3176, 2758, 4198, 5292, 3929, 1628, 777, 1489, 2468, 1956, -5, -1019, -227, 741, -83, -2079, -2736, -1687, -620, -1236, -3441, -4722, -3511, -1417, -1122, -3152, -5066, -4649, -3114, -3266, -5107, -5708, -3673, -1126, -513, -1676, -2632, -1809, 197, 860, -1135, -3678, -4024, -2442, -1379, -2520, -4642, -4974, -3341, -1990, -2304, -3634, -3875, -2062, -330, -1081, -3247, -3760, -2046, -595, -1531, -4267, -5984, -5063, -3440, -3846, -5798, -6295, -4258, -1905, -1452, -2669, -3560, -2626, -694, 129, -1035, -2676, -2485, -647, 262, -901, -1976, -616, 2179, 3705, 3109, 1837, 1808, 3234, 3688, 1431, -1271, -1169, 897, 1871, 942, -605, -999, 51, 553, -713, -2588, -3292, -2239, -818, -849, -2106, -2700, -1441, 330, 42, -2357, -3964, -3083, -1301, -942, -1931, -2180, -785, 1137, 1678, 142, -1424, -928, 936, 1908, 829, -683, -456, 858, 984, -741, -2751, -3084, -1583, -146, -468, -1911, -2379, -959, 615, -7, -2288, -3267, -1637, 411, 312, -1386, -1894, 186, 2789, 3113, 1267, 23, 1143, 3178, 3606, 1996, 438, 779, 2090, 2069, 72, -1896, -1522, 535, 1532, 340, -1436, -1639, -276, 548, -378, -1616, -1048, 1001, 2221, 1373, -455, -1171, -143, 799, -87, -2015, -2343, 15, 2595, 2976, 1966, 1901, 3540, 5048, 4482, 2332, 850, 1249, 2329, 1947, -234, -1777, -634, 1629, 2066, 353, -1289, -1071, 400, 1068, -300, -2131, -1899, 102, 1500, 1133, 356, 1131, 3155, 4129, 3002, 798, -512, 864, 3281, 3011, 504, -676, 416, 1821, 1692, -87, -1192, 184, 2161, 2248, 913, 412, 2082, 4488, 4770, 2646, 630, 542, 1357, 542, -2215, -4198, -3500, -1578, -1092, -2506, -3861, -3230, -1006, 276, -841, -2288, -1569, 534, 1504, 269, -1647, -1975, -594, 404, -421, -2184, -2697, -1071, 875, 724, -1104, -1919, -558, 1101, 385, -2143, -3238, -1492, 1280, 1970, 103, -1194, -27, 1890, 2091, 111, -1778, -1235, 844, 1578, -23, -1644, -1009, 1039, 2157, 1332, 109, 823, 3046, 3976, 2350, 34, -549, 686, 1677, 808, -710, -703, 990, 2439, 1661, -580, -1450, -207, 1172, 1146, 97, -198, 1315, 3149, 2963, 760, -890, -308, 1236, 1232, -787, -2381, -1319, 1357, 2536, 1435, 310, 874, 2471, 3009, 1437, -660, -876, 933, 2140, 881, -963, -505, 1845, 3165, 2116, 275, -23, 1684, 3147, 2597, 897, -221, 528, 2106, 1514, -988, -2110, -920, 430, -6, -1525, -1856, -107, 2016, 2211, 717, -870, -1608, -1228, -1184, -2521, -3603, -2659, -401, 569, -1077, -3175, -2940, -859, 359, -518, -2020, -2072, -652, 90, -1159, -3070, -3359, -1478, 323, -251, -2078, -2742, -2043, -1419, -1915, -3055, -3027, -1069, 970, 1074, -460, -1569, -699, 1185, 1475, -278, -1504, -558, 1044, 980, -738, -2040, -1445, 510, 1669, 900, -68, 902, 3386, 4794, 3835, 2397, 2973, 5167, 6071, 4042, 1026, 30, 1086, 1841, 851, -888, -1019, 959, 2737, 2211, 136, -705, 849, 2722, 2340, 264, -768, 258, 1519, 1152, -441, -1421, -650, 977, 1707, 1223, 814, 1888, 3995, 4696, 2915, 847, 1100, 3056, 3871, 2477, 835, 1039, 2503, 2736, 451, -2089, -1751, 790, 2498, 1864, -19, -726, 235, 955, 75, -1645, -1962, 31, 1908, 1202, -962, -1777, -405, 1515, 1663, -155, -1438, -654, 670, 376, -1610, -2784, -1292, 1325, 2454, 1481, 192, 895, 3113, 3834, 2230, 734, 1162, 2373, 2338, 792, -779, -554, 1507, 3066, 2354, 443, -333, 688, 1269, -401, -2449, -2427, -529, 1111, 826, -876, -1955, -1152, -48, -865, -2860, -3593, -2209, -58, 669, -601, -1485, 52, 2416, 2902, 1702, 1105, 2512, 5130, 6286, 4628, 2332, 2081, 3378, 3788, 2411, 739, 933, 2981, 4287, 3106, 994, 551, 1852, 2442, 812, -1321, -1713, -501, 684, 323, -1133, -1679, -588, 685, 307, -1167, -1413, 190, 1903, 1832, 156, -843, 395, 2484, 2672, 842, -314, 429, 1822, 2170, 947, -158, 823, 2750, 2933, 1383, 119, 233, 1028, 668, -1437, -3711, -4103, -2386, -634, -637, -1897, -2496, -1103, 823, 696, -726, -521, 1700, 3438, 2723, 415, -1005, -346, 880, 280, -2020, -3379, -2303, -346, 7, -1244, -1705, -57, 2341, 3049, 1346, -682, -467, 1431, 1951, 181, -1646, -1393, 609, 1997, 1153, -387, -133, 1714, 2757, 1517, -470, -559, 1165, 2408, 1685, -247, -1012, 405, 2035, 1412, -856, -1803, -319, 1597, 1481, -489, -1599, -515, 904, 487, -1426, -2523, -1381, 692, 1128, -657, -2413, -1998, -187, 426, -1462, -3735, -3291, -463, 1654, 1218, -63, 531, 2620, 3404, 1689, -706, -1389, -24, 1426, 1071, -233, -201, 1642, 3368, 2738, 375, -663, 646, 1983, 1107, -1193, -2300, -1065, 1054, 1810, 567, -1038, -1025, 142, 106, -1919, -3595, -2957, -1486, -1333, -2520, -3676, -3247, -1327, -273, -1423, -2896, -2259, 59, 1317, -14, -1786, -964, 1946, 3707, 2598, 209, -592, 993, 2551, 1626, -629, -1450, 16, 2181, 2678, 1425, 794, 2097, 3598, 2874, 361, -1437, -1028, 744, 1285, -444, -1863, -732, 1594, 2546, 1490, 192, 557, 2222, 2948, 1714, 140, 201, 1715, 2702, 1778, 299, 806, 3144, 4641, 3635, 1532, 1023, 2499, 3729, 2884, 1023, 375, 1488, 2865, 2493, 505, -689, 373, 1980, 1678, -136, -1001, 277, 2060, 1829, -671, -2768, -2260, -285, 550, -566, -1736, -1003, 789, 1443, 279, -992, -367, 1533, 2511, 1726, 441, 405, 1876, 3308, 2836, 1118, 1005, 2882, 4018, 2715, 272, -601, 559, 1379, 326, -1610, -2267, -758, 1161, 1072, -1095, -2752, -2282, -866, -527, -1850, -2870, -1871, -210, -34, -1434, -2599, -1669, 870, 2197, 1034, -423, 114, 2034, 2989, 1792, 99, 179, 1591, 1947, -12, -2467, -2699, -726, 1093, 859, -765, -1174, 530, 1870, 743, -1515, -2337, -1042, 685, 842, -663, -1812, -972, 474, 189, -1403, -1944, -592, 1228, 1523, 21, -1074, 34, 2246, 3027, 1311, -1105, -1425, 112, 580, -1014, -2579, -1889, 598, 2138, 1367, -89, -372, 466, 967, -145, -2262, -3021, -1587, -43, -486, -2383, -3275, -1984, -305, -595, -2515, -3348, -1640, 410, 129, -1722, -2637, -1567, 353, 916, -497, -1753, -1106, 434, 869, -379, -1380, -218, 1925, 2390, 434, -1707, -1599, 212, 1311, 525, -956, -1142, 268, 1310, 210, -2013, -2807, -1532, -395, -1640, -3916, -3942, -1423, 875, 894, -576, -1164, 16, 1243, 681, -1221, -2381, -1408, 631, 1387, 196, -993, -290, 1354, 1651, 89, -1639, -1587, -183, 227, -1174, -2601, -2082, 34, 1375, 768, -167, 611, 2866, 4197, 2967, 642, -120, 982, 1923, 905, -1571, -2865, -1447, 536, 337, -1377, -2039, -547, 1461, 1432, -335, -1048, 339, 1976, 1767, -56, -1205, -77, 2081, 2704, 1198, -321, 172, 1992, 2655, 940, -1115, -693, 1204, 1550, -194, -2004, -1683, 667, 2490, 1989, 679, 1040, 2948, 4003, 2560, -31, -981, 460, 2001, 1389, -431, -678, 1255, 2619, 1448, -655, -1379, -255, 1070, 534, -1579, -2871, -1726, 367, 454, -1623, -3064, -2181, -136, 843, -86, -1304, -666, 1687, 3396, 2764, 1059, 856, 2206, 2570, 859, -1065, -1008, 1046, 2926, 2679, 1230, 892, 2013, 2832, 1782, -261, -921, 313, 1478, 830, -1030, -1876, -534, 1340, 1092, -1210, -2873, -2151, -133, 518, -878, -1850, -407, 2158, 3165, 1840, 90, 305, 1846, 1906, 27, -1486, -881, 1308, 2861, 2325, 1045, 1313, 2910, 3473, 1816, -533, -1193, 61, 1100, 243, -1439, -1707, -146, 1312, 798, -868, -1244, 164, 1379, 968, -461, -1248, -306, 1458, 1873, 289, -1280, -753, 1076, 1682, 501, -383, 725, 2889, 3912, 2885, 1113, 858, 2284, 2805, 1268, -343, -97, 1528, 2458, 1533, -298, -1090, -14, 1262, 532, -1419, -1713, 467, 2754, 2495, 313, -536, 1223, 3452, 3639, 1936, 1021, 2579, 4646, 4565, 2655, 1225, 1639, 2779, 2454, 419, -902, 340, 2741, 3570, 2283, 806, 1163, 2890, 3403, 1494, -762, -838, 462, 404, -1546, -3370, -3305, -1620, -427, -1438, -3394, -3687, -2014, -460, -747, -2260, -3034, -2368, -1767, -2862, -5094, -6288, -5024, -2713, -2083, -3130, -3353, -1397, 1174, 1896, 770, 127, 1263, 2928, 3028, 1269, -352, 38, 1980, 2875, 1313, -565, -388, 1173, 1834, 539, -1267, -1467, -55, 822, -211, -2068, -2588, -1073, 714, 409, -1839, -3280, -2379, -946, -1320, -3131, -3920, -2176, 305, 625, -986, -2014, -1179, 300, 177, -1789, -3209, -2332, -345, 418, -612, -1468, -228, 1846, 2317, 741, -978, -813, 770, 1818, 1439, 430, 419, 1764, 2752, 1770, -40, -31, 2093, 3646, 2280, -843, -2390, -1319, -109, -805, -2414, -3215, -2440, -737, -364, -1983, -2947, -1638, -3, -200, -2012, -3298, -2114, 585, 1644, 108, -1518, -1086, 420, 496, -1424, -3239, -2952, -1264, -721, -2280, -4098, -3805, -1368, 453, -218, -1744, -1647, -6, 1165, 492, -1198, -1715, -401, 717, -415, -3074, -4665, -3964, -2577, -2701, -4377, -5293, -3635, -1069, -580, -2103, -2860, -1228, 1190, 1612, -285, -1846, -1000, 1149, 1936, 701, -483, 133, 1848, 2397, 841, -996, -1025, 313, 854, -495, -2446, -2820, -1310, -26, -802, -2635, -2822, -533, 1769, 1473, -430, -1060, 205, 1483, 975, -942, -1866, -533, 1360, 1495, -32, -823, 581, 2683, 2862, 931, -567, 156, 1947, 2099, 73, -1713, -1424, 188, 1091, -122, -2185, -2371, -697, 167, -1283, -3624, -4433, -3340, -2195, -2761, -4587, -5227, -3666, -2017, -2391, -3938, -4234, -2629, -1184, -1793, -3485, -3848, -2073, 49, 361, -739, -1007, 729, 2962, 2960, 613, -1062, -194, 1846, 2454, 849, -855, -322, 1783, 2511, 832, -984, -814, 650, 989, -949, -3425, -3642, -1602, -279, -1285, -2907, -2759, -593, 1313, 957, -476, -445, 1597, 3763, 3677, 1386, -289, 449, 1814, 1396, -591, -1908, -1173, 85, -508, -2727, -4006, -2879, -582, 560, -216, -912, 190, 1929, 2381, 1214, 85, 750, 2539, 2894, 922, -997, -521, 1489, 2481, 1276, -934, -1804, -812, -126, -1339, -3252, -3556, -1783, -150, -555, -1901, -1798, 210, 2009, 1686, -75, -1003, 183, 2140, 2410, 861, -121, 1023, 3033, 3428, 1549, -395, -292, 962, 1130, -450, -2156, -1889, -169, 498, -697, -2261, -2494, -1330, -746, -2328, -4371, -4286, -2580, -1386, -1811, -3175, -3324, -1466, 98, -767, -2900, -3602, -2197, -521, -337, -1124, -735, 1404, 3213, 2909, 958, -550, 76, 1877, 2370, 1007, -369, -11, 1721, 2316, 359, -1795, -1241, 1161, 2337, 1032, -974, -1243, 201, 1066, -330, -2580, -2907, -1330, -309, -1493, -3583, -3716, -1428, 500, -196, -2174, -2402, -420, 1320, 795, -1069, -1613, 20, 2002, 2152, 502, -895, -632, 603, 783, -913, -2390, -1408, 964, 1749, 343, -748, 228, 1954, 2098, 261, -1644, -1677, -298, 60, -1452, -2804, -2249, -237, 1501, 1246, -560, -1165, 218, 1172, 57, -1984, -2683, -1297, 497, 718, -515, -1230, -143, 1761, 2077, 158, -1422, -513, 1324, 1466, 77, -252, 1961, 4602, 4921, 2916, 870, 873, 2247, 2395, 467, -1599, -1667, -78, 704, -491, -2131, -2122, -344, 786, -786, -3625, -4577, -2957, -1366, -2313, -4700, -5533, -4018, -2245, -2402, -3728, -3795, -1738, 646, 990, -358, -988, 167, 1705, 1640, 141, -568, 631, 2408, 2660, 1042, -237, 545, 2146, 2340, 769, -872, -696, 964, 1527, -426, -2923, -2953, -720, 491, -862, -2744, -2727, -972, 179, -698, -2216, -2046, -118, 1215, 345, -1529, -2031, -615, 763, 119, -1927, -2774, -1396, 421, 481, -1188, -2212, -912, 1279, 1873, 576, -315, 1017, 3591, 4691, 3068, 1128, 1623, 3629, 4233, 2597, 850, 1394, 3848, 5156, 3892, 2221, 2382, 4055, 4948, 3450, 876, -143, 970, 2321, 1979, 490, 281, 2052, 3540, 2893, 1080, 251, 1260, 2738, 2782, 1355, 488, 1965, 4572, 5154, 3118, 1292, 1622, 2649, 2158, 124, -1493, -1074, 731, 1576, 470, -771, -470, 771, 1191, -299, -2309, -2225, -357, 507, -750, -2467, -2371, -420, 990, 348, -1254, -1532, 349, 2423, 2477, 1067, 665, 2207, 3893, 3777, 2111, 990, 1791, 3335, 3367, 1531, 29, 783, 2771, 3411, 2057, 886, 1710, 3166, 2663, 213, -1704, -1589, -283, 403, -435, -1800, -1727, -6, 1192, 339, -1125, -1055, 551, 1644, 583, -1428, -1907, -431, 1054, 920, -422, -857, 1013, 3550, 4096, 2657, 1641, 2563, 4131, 4058, 2143, 511, 868, 2305, 2499, 748, -931, -213, 1910, 2330, 608, -909, -586, 794, 1215, -204, -2054, -2113, -231, 1167, 299, -1434, -1638, -186, 728, -281, -2066, -2528, -1218, 61, -397, -1901, -2237, -831, 391, -257, -1889, -2373, -737, 1740, 2679, 1598, 595, 1636, 4015, 4868, 3189, 1394, 1756, 3393, 3599, 1691, 117, 1034, 3219, 3842, 2511, 1369, 1967, 3513, 4095, 2650, 293, -309, 1368, 2596, 1549, -413, -759, 1052, 2780, 2461, 738, -262, 530, 1513, 732, -1037, -1276, 940, 3380, 3328, 1271, 347, 1857, 3844, 3791, 1625, 88, 1119, 3228, 3630, 1886, 152, 595, 2522, 3111, 1240, -1099, -1447, -218, 2, -1800, -3673, -3345, -1212, 224, -589, -2224, -2194, -409, 795, -189, -2043, -2211, -77, 2273, 2535, 1033, 279, 1627, 3453, 3510, 1863, 632, 1496, 3712, 4656, 3344, 1967, 2498, 3813, 3385, 881, -1195, -980, 530, 1179, -87, -1771, -1458, 418, 1145, -392, -2544, -2874, -1193, -64, -1264, -3204, -3146, -1022, 536, 227, -746, -820, 565, 1915, 1033, -1166, -1739, 108, 2429, 2609, 652, -533, 238, 994, 558, -522, -1507, -991, 934, 1504, -325, -1869, -897, 1094, 1186, -992, -2986, -2630, -731, 138, -889, -2057, -1470, 468, 1592, 389, -1938, -2593, -1021, 338, -705, -3014, -3311, -804, 1548, 1004, -1165, -1793, -256, 1344, 1091, -486, -892, 1001, 3048, 2755, 670, -673, 221, 2117, 2477, 898, -380, 364, 2130, 2656, 1190, -321, 162, 1852, 2469, 1023, -1221, -1770, -352, 442, -644, -1840, -1031, 1693, 3751, 3048, 1027, 443, 1772, 3045, 2482, 941, 661, 2292, 4204, 4176, 2617, 2198, 3686, 4896, 3886, 1445, 32, 708, 2055, 1953, 326, -698, 223, 2172, 2855, 1098, -1167, -1610, -903, -1170, -2863, -4427, -3822, -1058, 1150, 932, -162, 251, 1823, 2363, 1094, -422, -252, 1527, 2982, 2400, 458, -7, 2063, 4354, 4264, 2242, 844, 1282, 2293, 1869, -15, -998, 98, 1739, 1889, 43, -1818, -1599, -395, -512, -2234, -3843, -3354, -1444, -677, -1698, -2776, -2209, -307, 697, -723, -2788, -2766, -948, 322, -422, -2118, -1923, 690, 2900, 2548, 718, -30, 1232, 2521, 1496, -944, -1926, -523, 1320, 1170, -941, -2423, -1523, 24, -349, -2236, -3558, -3112, -1701, -1481, -2846, -4047, -3793, -2726, -2697, -4266, -5439, -4491, -2304, -984, -1579, -2625, -1833, 444, 1506, 140, -1843, -2062, -254, 1286, 601, -891, -669, 950, 1665, 384, -1807, -2869, -1768, 54, 120, -1637, -2591, -1127, 1118, 1385, -588, -1913, -748, 1260, 1475, -272, -1402, -534, 896, 1108, -230, -1654, -1138, 817, 1357, -367, -2124, -1843, 116, 1280, 67, -1669, -1279, 1000, 2783, 2493, 1020, 556, 1889, 3120, 2217, 61, -774, 451, 1863, 1507, -215, -947, 413, 2063, 1694, -376, -1622, -669, 914, 846, -893, -2260, -1937, -709, -375, -1747, -3418, -3258, -1481, -709, -2005, -3673, -3865, -2568, -1612, -2187, -2969, -1976, 548, 2025, 1088, -513, -658, 800, 2093, 1698, 239, -331, 1114, 3030, 2914, 1205, 416, 1301, 2179, 1327, -594, -1536, -723, 550, 280, -1479, -2559, -1842, -419, -278, -1952, -3472, -3150, -1683, -998, -2176, -3672, -3157, -1031, 132, -1030, -2881, -2611, -73, 1916, 1480, 98, 394, 2246, 3255, 1964, -321, -783, 999, 2400, 1512, -631, -1724, -832, 445, -181, -2420, -3438, -2043, -435, -766, -2820, -4638, -4274, -2591, -2356, -4155, -5705, -5093, -3300, -2680, -3681, -4565, -3891, -1967, -515, -1132, -2747, -2597, -582, 682, -377, -2029, -1644, 585, 2178, 1194, -1450, -2632, -1332, 7, -607, -2200, -2473, -903, 627, 321, -1310, -2171, -1055, 849, 1012, -1214, -3184, -2420, -184, 599, -696, -1962, -1158, 914, 1534, -93, -1741, -1200, 1110, 2798, 2170, 513, 521, 2082, 2698, 1204, -954, -1288, 455, 1765, 985, -572, -559, 1335, 2910, 2038, -634, -2097, -1158, 47, -392, -1847, -2377, -1025, 940, 1177, -549, -1641, -484, 1304, 1479, -37, -1313, -694, 1029, 1409, -236, -1733, -1158, 433, 718, -877, -2715, -2918, -1497, -228, -527, -1526, -995, 1328, 3076, 2449, 383, -625, 411, 1723, 1270, -287, -613, 881, 2252, 1624, -7, 0, 2182, 4154, 3797, 1962, 995, 1846, 3227, 2812, 383, -1529, -1215, 38, -92, -1970, -3721, -3733, -2607, -2515, -4340, -6012, -5330, -3121, -2045, -3211, -4757, -4429, -2418, -1022, -2005, -4000, -3980, -1736, 205, 404, -242, 58, 1847, 3571, 3370, 1600, 696, 1904, 3509, 3338, 1938, 1533, 2975, 4865, 4599, 1952, -93, 209, 1332, 1086, -887, -2687, -2361, -773, -699, -2802, -4886, -5001, -3603, -3362, -5353, -7166, -6709, -4504, -2771, -3012, -3924, -3310, -1066, 873, 639, -1070, -1494, 156, 1902, 1682, -429, -1582, -258, 1315, 1022, -729, -1906, -946, 872, 957, -626, -1607, -737, 772, 711, -1030, -2630, -2505, -882, -204, -1676, -3113, -2264, -14, 634, -1431, -3858, -4028, -2080, -367, -819, -2398, -2264, -306, 975, 218, -1613, -2282, -871, 394, -675, -2869, -3787, -2548, -485, -129, -1596, -2248, -859, 1109, 1613, 431, -585, 346, 2554, 3391, 1987, 671, 1466, 3365, 4013, 2543, 326, -135, 1494, 2157, 302, -1799, -1750, 193, 1397, 113, -1897, -1590, 1108, 3133, 2586, 1058, 829, 2166, 3572, 3120, 1334, 1103, 3294, 5283, 4725, 2777, 2116, 3542, 5237, 4610, 1818, -108, 224, 1061, 589, -1169, -2546, -1911, -202, 234, -938, -1686, -625, 1262, 1988, 978, -280, 117, 2128, 3297, 2076, 161, 125, 1933, 3029, 1903, 73, 182, 2666, 4612, 3790, 1973, 1609, 2552, 3105, 2022, -98, -1474, -1038, 323, 460, -1070, -2036, -709, 1139, 939, -1216, -3237, -3256, -1953, -2058, -4303, -6286, -6025, -4436, -4042, -5476, -6364, -4802, -1947, -309, -927, -2396, -2289, -452, 651, -273, -1804, -1965, -560, 813, 628, -804, -1146, 663, 2476, 1977, -112, -1020, 124, 1148, 366, -1170, -2123, -1856, -397, 465, -501, -1568, -659, 1326, 1660, -325, -2584, -3120, -2047, -1484, -2876, -4834, -5049, -3719, -3079, -4054, -5342, -4903, -2508, -774, -1518, -3002, -2718, -763, 596, -112, -1610, -1814, -565, 372, -658, -2941, -4116, -3471, -2663, -3287, -4848, -5467, -4138, -2169, -1836, -3279, -4272, -3455, -2008, -1565, -2349, -3046, -1914, 571, 1335, -569, -2263, -1820, -305, 239, -1206, -3075, -2883, -1012, -93, -1325, -3170, -3415, -1901, -509, -869, -2159, -2154, -629, 491, -322, -2417, -3481, -2532, -1609, -2573, -4425, -5022, -3756, -2210, -2627, -4940, -6249, -4835, -2547, -1542, -1873, -2016, -280, 2547, 3630, 2159, 692, 1545, 3655, 4197, 2321, 553, 1165, 2856, 3402, 2316, 548, -100, 955, 1628, 157, -2104, -2702, -1409, -307, -1053, -2898, -3689, -2432, -704, -1059, -3115, -3532, -1297, 882, 707, -1111, -2075, -864, 942, 1024, -758, -2297, -1525, 778, -20038, -12278, 6427, 11556, -3460, -18032, -12651, 5617, 12204, -1592, -17517, -15539, 1129, 9896, -1508, -17610, -16083, 1934, 13748, 5416, -11125, -14210, 658, 13552, 5893, -12793, -18409, -4517, 9891, 5206, -13116, -21600, -9150, 8215, 8124, -8714, -18965, -8251, 8823, 9597, -6635, -18835, -11002, 6578, 10166, -5160, -19129, -13213, 5302, 12308, -637, -15175, -11300, 6384, 14724, 2929, -13293, -12971, 3245, 13773, 4239, -13218, -15640, 316, 12560, 3902, -14696, -19828, -5332, 9490, 4916, -12750, -20415, -8087, 8514, 7315, -10319, -19921, -7539, 10583, 10912, -6043, -17860, -9530, 7515, 9977, -6510, -21128, -15360, 2222, 7818, -5890, -20776, -16508, 2362, 11478, -396, -16985, -16442, 500, 10915, 144, -17831, -19363, -2553, 10468, 3291, -13832, -18081, -3385, 10686, 5168, -12809, -19730, -6494, 8916, 5885, -11397, -20235, -8683, 8389, 8404, -8419, -19521, -9865, 7906, 10039, -6152, -19387, -12436, 4964, 8836, -6356, -21057, -16174, 2290, 10164, -2719, -19199, -17800, -383, 9979, -77, -16400, -16766, -264, 11342, 2894, -14354, -17665, -2443, 10890, 4546, -12761, -18050, -3529, 12320, 8391, -10067, -19310, -8710, 6180, 4584, -12309, -22603, -11875, 6480, 8815, -6670, -18442, -10263, 7809, 11898, -3749, -18779, -14236, 2503, 8260, -5273, -21130, -18534, -764, 8469, -2694, -19556, -20585, -4647, 6464, -2947, -20489, -22544, -5982, 7710, 1208, -16467, -21438, -6175, 9300, 4611, -13710, -21952, -9892, 5674, 3290, -14496, -24948, -14598, 3092, 4910, -11225, -22948, -13359, 5369, 9441, -4835, -17846, -11429, 6928, 12695, -1828, -17385, -13952, 3679, 12008, -202, -17119, -16488, 1188, 12386, 2225, -15842, -18050, -1814, 10805, 3513, -13781, -18578, -4443, 9756, 4809, -12688, -19720, -7316, 7768, 4872, -12488, -21103, -9223, 7828, 7896, -9110, -21205, -12442, 5976, 10280, -4480, -17991, -11298, 7156, 12486, -2271, -17599, -13538, 4252, 11462, -1561, -17765, -16337, 897, 10922, 167, -16940, -17657, -1016, 10722, 2095, -15634, -19682, -4873, 9021, 3501, -14183, -20686, -6823, 9458, 6755, -10837, -20011, -8867, 7535, 7119, -9429, -20046, -10445, 7257, 9897, -6144, -19665, -12941, 4525, 9081, -5486, -20381, -16292, 1280, 8363, -5072, -21367, -19207, -2214, 6513, -4418, -20839, -21687, -5737, 5833, -2719, -19958, -22851, -7941, 4798, -809, -17170, -22597, -8752, 7056, 4262, -13046, -21403, -9604, 6358, 5474, -10942, -21447, -11508, 6140, 7909, -7882, -19943, -12726, 4595, 9367, -5078, -19587, -14599, 3442, 10524, -2515, -18159, -15947, 633, 8925, -3218, -20855, -21065, -3815, 7560, -1348, -17680, -19809, -4229, 9737, 3879, -14083, -19652, -4979, 9886, 4993, -13290, -21570, -9489, 6768, 5667, -10779, -19861, -8519, 8873, 9558, -6826, -18925, -11379, 5746, 9175, -6025, -19961, -14360, 3349, 9689, -3503, -18714, -15433, 2570, 11308, -746, -17493, -17457, -1224, 9723, 1009, -15642, -17443, -1346, 11006, 3094, -14674, -19201, -4801, 9303, 4681, -12481, -19492, -6237, 10166, 7781, -9713, -18719, -7256, 9896, 10616, -5480, -17312, -9445, 7797, 11366, -3221, -16625, -11207, 6135, 12158, -1084, -15574, -11927, 5128, 12730, 557, -15369, -13896, 3243, 13519, 3678, -13138, -14730, 1209, 13674, 6451, -10456, -14400, 511, 14918, 9913, -6988, -13092, -415, 14692, 12111, -5035, -13762, -2237, 14014, 13100, -4146, -15344, -5782, 11884, 14684, -365, -13253, -6917, 10476, 15565, 1194, -13743, -9709, 7257, 13757, 696, -15346, -13477, 4282, 14454, 3802, -13179, -13900, 2980, 15309, 6929, -10841, -14366, 1355, 15656, 9659, -9126, -16610, -2727, 13484, 10268, -7300, -15946, -4296, 12227, 11657, -4694, -14389, -4131, 12498, 13157, -3496, -16099, -7800, 11067, 15971, 1401, -13047, -8693, 8261, 14148, 50, -15853, -13309, 3278, 11483, 387, -16110, -16477, 192, 11189, 1794, -15199, -17556, -1949, 11340, 4971, -12214, -17212, -3077, 11889, 8093, -9256, -17120, -4659, 12186, 11510, -4670, -13876, -3377, 13054, 13335, -3192, -15169, -7319, 9384, 12643, -1654, -14831, -9392, 8159, 14475, 811, -14916, -12080, 5795, 14975, 3560, -12393, -11447, 5409, 16387, 7337, -9497, -11608, 4024, 16418, 9374, -7320, -11467, 2822, 16596, 10876, -7854, -15941, -3304, 12683, 10928, -5148, -13503, -2505, 13854, 14223, -1700, -12731, -4153, 12324, 14222, -1479, -14629, -8082, 9846, 15637, 1714, -13305, -9347, 8313, 16199, 4230, -11925, -11345, 5065, 14948, 4587, -12806, -14104, 2632, 14770, 6822, -9561, -12585, 1974, 15457, 10143, -7166, -13685, -969, 13743, 10719, -6217, -14718, -3027, 13620, 13580, -2629, -13639, -4417, 13179, 15712, 143, -12732, -5986, 11333, 15959, 1348, -13231, -8707, 8160, 14302, 1246, -14388, -12459, 4696, 14106, 3013, -13674, -13605, 3558, 15441, 6733, -10462, -13226, 2292, 15935, 10091, -7009, -12648, 645, 15303, 12012, -4769, -12894, -1093, 15416, 14607, -2462, -13147, -3313, 13757, 15390, -236, -12418, -4933, 12184, 15753, 778, -13426, -8160, 9966, 17098, 4553, -10275, -7432, 9355, 17062, 5057, -11007, -10796, 5015, 15165, 5649, -10814, -12485, 2890, 15509, 8686, -9080, -14485, -164, 15123, 11310, -5904, -12848, 300, 16571, 14760, -2475, -12474, -2448, 13717, 14054, -2453, -14404, -5903, 11641, 14899, 162, -12964, -6787, 11225, 17188, 3804, -10316, -6047, 11754, 20259, 8635, -7718, -7332, 8856, 18455, 7979, -9633, -12422, 2259, 14010, 6224, -11749, -16197, -1025, 13487, 8642, -8771, -15866, -3170, 12312, 10081, -6344, -14828, -3392, 13680, 14236, -1876, -12799, -3929, 13113, 15734, 231, -12798, -6125, 10826, 15542, 2212, -11655, -7255, 10434, 17935, 5300, -10314, -8080, 9221, 18864, 8098, -9050, -10168, 5978, 17591, 9254, -7755, -10568, 4993, 18613, 12752, -4491, -10363, 2973, 17766, 14214, -3488, -12648, -1402, 15023, 14852, -1059, -11177, -1646, 15167, 16661, 691, -12026, -5058, 12304, 16630, 2340, -11081, -5256, 12723, 19351, 6228, -9371, -7228, 9744, 18667, 7331, -9588, -10424, 5549, 17074, 9233, -7097, -9751, 6056, 20237, 14206, -3311, -8548, 5405, 19780, 15037, -3312, -11410, 1165, 16782, 14322, -2760, -12182, -1631, 15474, 16869, 594, -11835, -4120, 12417, 15052, 14, -13867, -9009, 8087, 14442, 1312, -13703, -9918, 8290, 17035, 5689, -9878, -8889, 7915, 18562, 8997, -7773, -9258, 6905, 19723, 12540, -5052, -9785, 4442, 18621, 14289, -2216, -8731, 3616, 18606, 16015, -1296, -11065, -963, 15145, 15385, -865, -11945, -3051, 14080, 17085, 2325, -10681, -4708, 11804, 15884, 1113, -14191, -10761, 6579, 14627, 2809, -12755, -11290, 5487, 15718, 6120, -10452, -11321, 5678, 18192, 10455, -6174, -9480, 5421, 19232, 13768, -3510, -9704, 3159, 17682, 14577, -2197, -10903, 444, 17225, 16745, -852, -12912, -4237, 12882, 15148, -36, -12030, -5000, 11751, 15702, 1033, -13098, -8113, 9110, 15619, 3119, -11893, -9603, 7618, 17467, 7345, -8939, -9104, 7658, 18766, 9362, -8227, -11450, 3759, 17664, 12058, -5650, -12221, 1044, 16610, 13819, -3425, -11693, 743, 17271, 15268, -2790, -13835, -4552, 12104, 14067, -1279, -13764, -6227, 11389, 15783, 2101, -10894, -5122, 12909, 20056, 7479, -7871, -5278, 12441, 21698, 9743, -7773, -7993, 8579, 19532, 10699, -5847, -8226, 6635, 18525, 10938, -6722, -11771, 2134, 16421, 12226, -4762, -12079, 83, 15575, 13795, -3250, -13209, -2591, 14562, 15502, -536, -12092, -4102, 12525, 15455, 444, -13109, -7700, 8764, 13715, 65, -14554, -10526, 7856, 17457, 6862, -8633, -7269, 9586, 19503, 9513, -7929, -10560, 5085, 18116, 11247, -6140, -10563, 4192, 18416, 13251, -4674, -12438, -365, 14539, 11120, -6829, -15714, -3863, 13076, 13523, -1846, -11747, -2182, 14869, 17105, 1423, -11897, -5402, 12268, 17757, 4021, -10943, -6863, 11411, 19147, 6300, -9893, -8395, 8710, 18013, 6133, -12213, -13912, 2432, 14637, 6640, -10282, -13527, 862, 13953, 8301, -9074, -15004, -1564, 12827, 8871, -8332, -16608, -5166, 11107, 11354, -3587, -12870, -2645, 15039, 17380, 1943, -10329, -3233, 13904, 18071, 3165, -11558, -6913, 10598, 17417, 4610, -10927, -8594, 8751, 17686, 5691, -12378, -14048, 1665, 12702, 4077, -12447, -14760, 1080, 14785, 8628, -8694, -14286, -964, 13162, 9015, -8155, -15840, -3681, 12124, 10632, -6170, -16452, -6780, 9686, 10611, -5254, -16764, -8209, 9780, 14097, -179, -13860, -8399, 9038, 14966, 2081, -12135, -8500, 8921, 17453, 6281, -9870, -10120, 6012, 16739, 7481, -8882, -10395, 5050, 17123, 9930, -7312, -12235, 2256, 16948, 11904, -5569, -12510, -5, 15806, 14010, -3157, -13059, -2446, 14464, 14892, -1659, -13310, -4754, 12488, 15553, 1041, -11275, -4228, 13839, 19296, 5190, -9721, -6033, 11004, 18360, 6042, -10040, -9355, 6917, 16853, 6769, -10221, -11606, 4603, 16653, 8484, -8859, -12837, 1241, 14637, 9884, -6616, -12481, 1533, 17715, 14807, -3162, -12548, -1350, 15206, 15337, -663, -11461, -2338, 14986, 17459, 1965, -11121, -4903, 11785, 15943, 1362, -13541, -9525, 7905, 15029, 2364, -13000, -10528, 7092, 17172, 6713, -10745, -12753, 2700, 13918, 5293, -11883, -15362, -187, 13867, 8167, -8739, -13219, 1348, 16363, 12860, -4255, -12260, -236, 15377, 13709, -2972, -13774, -4952, 12054, 14442, -918, -13346, -5987, 11392, 15360, 408, -13877, -8654, 8916, 15251, 1789, -14143, -11860, 5816, 15386, 3890, -13371, -13240, 4039, 15306, 6121, -11230, -14267, 921, 13939, 7006, -10800, -15635, -935, 14180, 10872, -5323, -12333, -95, 15567, 13485, -3825, -13580, -3257, 13410, 14495, -1737, -14271, -6599, 10913, 14822, 261, -13414, -7666, 10611, 17128, 3582, -11135, -7168, 10020, 17609, 5464, -11373, -11525, 5057, 15959, 6366, -11117, -13088, 3500, 16532, 8823, -9238, -14154, 465, 14895, 9509, -8629, -15833, -2873, 12899, 10526, -7219, -17991, -8429, 8052, 8702, -7499, -18828, -9864, 7925, 11183, -3923, -16742, -9942, 7408, 12143, -2116, -16940, -12744, 5519, 14162, 2541, -13334, -12341, 3878, 12999, 2064, -15194, -16322, 165, 11997, 3675, -12997, -15862, -489, 13842, 8664, -9087, -16384, -4298, 10268, 7136, -9442, -16855, -4522, 12503, 13017, -2988, -14158, -5055, 12321, 14331, -1549, -14334, -7575, 9554, 14058, -552, -15124, -10478, 7177, 15055, 3429, -12242, -10896, 5858, 15103, 4315, -11893, -11905, 4153, 14341, 4340, -13524, -16801, -2097, 10714, 4682, -11970, -16899, -2874, 12357, 9350, -7482, -15910, -4632, 11072, 9446, -7394, -16731, -5754, 12105, 14159, -1774, -13944, -5852, 11954, 16343, 1825, -12426, -7027, 11289, 17977, 4759, -10315, -7852, 8526, 16930, 5832, -10769, -11523, 4160, 14714, 5684, -11344, -14590, -6, 12614, 5445, -12388, -17087, -2558, 11703, 7189, -10073, -17885, -5754, 10513, 9335, -7307, -17027, -6984, 9180, 9536, -6584, -17799, -8842, 8890, 12371, -2546, -16103, -10052, 7949, 13909, 146, -15438, -13396, 2892, 10826, -1105, -17744, -17777, -1410, 9816, 1179, -15429, -17473, -1950, 10533, 3395, -13818, -17991, -2968, 11900, 7891, -8713, -15193, -1901, 14342, 12408, -4568, -13845, -2946, 14015, 14891, -704, -11697, -3548, 12817, 15032, -482, -13626, -7255, 10233, 15318, 888, -14297, -10816, 6400, 14810, 3609, -11936, -10474, 6403, 15959, 5105, -12200, -13566, 2392, 14396, 6512, -11001, -14980, -107, 13364, 6643, -11823, -17859, -4172, 10765, 7603, -9616, -18478, -7176, 9373, 9409, -6554, -16771, -7212, 9672, 11759, -3390, -16053, -9713, 7172, 11647, -2380, -16206, -11489, 5754, 12411, -726, -16680, -14981, 1797, 10962, -45, -16754, -17043, -181, 12024, 4291, -12067, -14613, 328, 12852, 6287, -10994, -16401, -2263, 12805, 8920, -8124, -16019, -4653, 11220, 10196, -7291, -18551, -8715, 8909, 10931, -4467, -16159, -8107, 9539, 13204, -2254, -16377, -10536, 7013, 12676, -718, -15461, -12168, 5399, 14501, 3430, -12943, -13090, 2889, 13001, 2982, -14292, -16291, -509, 12381, 5447, -12295, -17410, -2933, 11569, 6715, -10857, -18501, -6217, 9705, 7970, -8159, -16345, -4660, 12959, 13580, -3954, -16865, -9028, 7769, 10451, -4163, -17043, -11664, 5594, 12450, -253, -15446, -12252, 5654, 14546, 2653, -14059, -13551, 2843, 12628, 2858, -13904, -16019, -130, 13140, 6480, -11053, -16033, -1876, 11635, 6095, -10955, -17164, -4015, 11772, 10096, -5864, -14089, -2712, 13652, 13101, -4011, -15696, -7214, 9505, 11605, -3765, -15929, -8318, 9754, 15545, 2556, -11672, -8187, 8355, 15372, 2675, -13913, -13029, 3823, 13551, 3050, -13698, -14909, 764, 12312, 4381, -12629, -16550, -1652, 12900, 8307, -7850, -12496, 1927, 17506, 14448, -2795, -11480, -284, 15211, 13606, -3973, -16188, -8239, 8549, 10944, -4212, -16245, -8948, 8170, 12696, -1013, -14529, -9234, 8532, 15335, 2492, -12833, -10499, 6499, 15541, 4393, -12681, -13890, 1361, 11680, 2541, -14601, -17679, -2768, 10289, 4087, -13070, -17992, -2845, 13580, 10287, -7678, -16363, -4726, 10963, 9324, -8111, -19060, -9037, 8487, 10239, -5297, -17184, -9242, 8539, 12724, -1873, -15772, -10469, 7611, 14614, 1526, -13135, -9576, 6891, 14244, 2102, -14917, -15007, 1571, 12135, 3136, -12672, -14164, 1283, 13913, 6924, -10772, -15589, -900, 13465, 8538, -8631, -15706, -3768, 11516, 9639, -7856, -18457, -8203, 9073, 10167, -5791, -17125, -9014, 7924, 11394, -3549, -17510, -12057, 5333, 11591, -742, -14527, -10546, 6839, 14994, 3300, -13063, -12763, 4011, 14757, 4864, -12413, -14338, 1450, 13801, 6148, -11443, -15564, -407, 14012, 8788, -8975, -16127, -3552, 11547, 8341, -9475, -18893, -7604, 9416, 9697, -6466, -17369, -8606, 8167, 10485, -4881, -17624, -10762, 6473, 11490, -1714, -15781, -11827, 5520, 12970, 470, -15109, -13256, 3583, 13432, 3700, -12267, -12712, 3364, 14738, 6589, -10869, -15450, -1071, 13032, 7525, -10340, -16556, -2950, 12107, 8976, -7801, -16031, -4370, 11830, 11016, -5451, -15691, -5563, 11761, 13241, -2798, -15448, -8435, 8611, 12664, -1729, -16037, -11583, 6022, 13253, 877, -14358, -12028, 5366, 14598, 3381, -13022, -13073, 3326, 14716, 6192, -10915, -14071, 857, 13535, 6820, -10647, -16259, -2208, 13210, 9367, -8425, -16442, -4000, 12748, 12275, -4329, -15250, -5910, 10885, 11910, -4419, -16973, -9662, 7971, 12775, -1209, -14581, -8595, 9446, 16037, 3006, -12177, -9543, 7446, 15978, 3973, -13006, -12300, 5202, 16620, 7716, -9358, -12170, 3427, 16876, 10109, -7532, -12665, 1030, 15068, 10479, -7218, -14896, -2634, 12704, 10713, -5692, -14835, -4273, 12755, 14119, -1623, -13004, -4349, 13151, 16686, 2268, -10675, -4702, 12269, 17430, 3708, -11620, -9004, 7694, 15588, 3816, -11944, -10326, 7192, 17599, 7290, -10228, -12621, 2571, 14706, 7322, -9790, -13429, 2115, 16907, 12293, -4758, -11354, 1790, 17250, 14388, -3017, -12560, -2048, 14287, 13921, -3238, -14851, -6054, 10985, 13435, -1785, -14716, -8197, 9792, 15608, 1966, -12348, -8108, 9329, 16946, 4554, -11646, -10416, 5845, 14465, 3693, -12629, -13196, 3395, 15820, 8668, -7900, -11831, 2836, 16870, 11153, -7019, -13590, -78, 14698, 10973, -5431, -12778, -1392, 14351, 13730, -2702, -13190, -3820, 12824, 14572, -876, -13483, -6881, 9923, 14399, 974, -12171, -6805, 10911, 18070, 5892, -9224, -7479, 8766, 17486, 6314, -10585, -11447, 4504, 15522, 6091, -11865, -15191, -113, 13023, 6554, -10950, -16617, -3310, 10982, 7151, -9472, -16747, -4081, 12811, 12032, -4803, -15162, -5270, 11454, 12321, -4250, -17143, -9769, 7736, 11978, -1893, -15390, -10728, 5949, 11686, -1514, -16394, -13538, 3944, 13546, 2974, -13140, -12739, 4040, 14793, 5396, -11533, -13766, 1398, 13726, 7155, -9543, -13880, 832, 15350, 10771, -6237, -13143, -930, 13886, 11481, -5191, -14468, -3480, 14259, 15955, 532, -10345, -1827, 15022, 17801, 1968, -12689, -7607, 9487, 14834, 948, -13898, -10140, 7357, 15419, 3258, -13043, -11761, 5393, 15790, 6087, -11108, -13397, 2546, 15748, 8707, -9001, -13264, 1858, 15780, 9709, -8581, -15972, -3775, 11205, 8531, -8800, -17756, -5882, 11199, 11165, -5121, -15810, -6556, 10561, 12968, -2011, -14274, -7320, 10194, 15940, 3174, -11086, -7743, 9035, 16170, 3522, -12343, -10921, 5527, 15107, 5152, -11555, -13049, 2830, 14519, 6295, -11152, -15145, -313, 13469, 8110, -8539, -14126, -295, 15619, 12872, -4489, -13473, -2315, 13851, 13071, -3558, -13998, -4375, 12401, 13908, -1684, -14285, -7693, 9603, 14675, 475, -14062, -8812, 9675, 16751, 3967, -10868, -8406, 7844, 16173, 5108, -11441, -12139, 3915, 15121, 6175, -11164, -13884, 1726, 14964, 8156, -9990, -15724, -1753, 13005, 8929, -8553, -16368, -3799, 12525, 11002, -5612, -15322, -5192, 12162, 14307, -1366, -14001, -6743, 10343, 13718, -1020, -14191, -8876, 8041, 14756, 2354, -12795, -10079, 7167, 15899, 4812, -11081, -10598, 6092, 17121, 7847, -9458, -12169, 3048, 15976, 9389, -8156, -13690, -200, 14087, 9437, -8603, -15892, -2308, 14369, 13138, -3441, -13699, -3949, 12866, 14018, -2058, -13827, -5437, 11899, 15042, -266, -14505, -9315, 8219, 14218, 661, -13973, -10147, 7148, 15190, 3282, -13444, -13636, 2352, 12194, 1707, -15952, -17784, -1235, 12397, 6286, -10199, -14350, 137, 14393, 9643, -7574, -14218, -940, 14833, 12504, -4225, -13037, -2058, 14574, 15082, -1346, -12758, -3803, 12909, 14993, -601, -14476, -8964, 8066, 13405, -329, -15497, -12232, 5146, 12937, 448, -15702, -13966, 3523, 13603, 3604, -12972, -14652, 937, 13113, 5648, -11335, -15018, 281, 14714, 9502, -7921, -14449, -1126, 14238, 10979, -6118, -14528, -3511, 12193, 11490, -5145, -15808, -6270, 10469, 12024, -3918, -16955, -9959, 8052, 13318, -708, -14799, -10004, 7144, 14073, 1937, -13428, -11630, 5793, 16208, 5549, -12312, -14031, 2195, 14115, 5779, -11212, -14572, -425, 12273, 6506, -10090, -15155, -1466, 13026, 9470, -7086, -14876, -3629, 11416, 9732, -7064, -17109, -6550, 10957, 12651, -2970, -15218, -7795, 9486, 12954, -2675, -17286, -12588, 4217, 10751, -1509, -16182, -12957, 4970, 14339, 3386, -12558, -11853, 4953, 15834, 6801, -10048, -12566, 2798, 15532, 8337, -9614, -15076, -1137, 13402, 9390, -7726, -15658, -3585, 12406, 10573, -6301, -15728, -4820, 12843, 14395, -1433, -13165, -5250, 11172, 13338, -2264, -16232, -11207, 6201, 13078, 994, -13031, -9538, 7778, 16320, 4948, -11144, -11077, 4824, 15693, 6945, -10007, -12385, 3176, 15651, 8124, -9293, -13779, 164, 14007, 9079, -8643, -15834, -3205, 12082, 9833, -6777, -15548, -4309, 12313, 12378, -4150, -15760, -7292, 9685, 12184, -2875, -15408, -8863, 8539, 13901, 83, -14583, -10840, 6191, 13456, 802, -15254, -13521, 4047, 14765, 5289, -11115, -12030, 4330, 16298, 8242, -8819, -12231, 2862, 16674, 11018, -6323, -12526, 564, 15507, 12637, -3958, -12692, -1954, 14270, 14125, -2604, -13765, -4283, 13105, 15030, -1010, -14188, -7830, 8840, 13032, -906, -14724, -9771, 8623, 16407, 3553, -12053, -9511, 7810, 17354, 6887, -10149, -12050, 3007, 14091, 5694, -11297, -13911, 2045, 15915, 10145, -7067, -13084, 33, 14649, 10978, -6195, -14077, -2319, 12935, 10980, -6436, -17363, -7621, 9979, 12738, -2100, -14190, -6583, 11093, 15337, 288, -14254, -8553, 10109, 17090, 3858, -11851, -9331, 7947, 16760, 5787, -10386, -10395, 6441, 18014, 9252, -7754, -10662, 4493, 17900, 11579, -6280, -12168, 1315, 15871, 12028, -5195, -13002, -825, 15012, 13588, -2758, -12376, -1963, 15395, 16716, 127, -12650, -5217, 11718, 14982, 174, -13337, -7549, 10463, 17263, 4393, -10905, -8237, 9286, 18303, 6838, -9710, -10015, 5606, 15991, 6783, -10433, -13140, 1942, 14331, 7323, -9703, -13553, 1673, 16482, 11779, -5903, -13280, -933, 14560, 12605, -4065, -12896, -1202, 16072, 16454, 163, -11393, -3466, 13356, 16755, 2025, -11441, -5328, 12042, 16769, 2558, -12486, -9569, 6994, 14747, 2879, -13239, -12248, 4719, 15225, 5748, -11023, -13140, 2158, 13769, 5727, -10992, -14389, 196, 14124, 9175, -8322, -15172, -1803, 14176, 12277, -3140, -10375, 1227, 17687, 17586, 1155, -9660, -589, 16271, 18610, 3044, -10724, -4922, 11943, 15625, 72, -14813, -10327, 7271, 15126, 3518, -11806, -9910, 7641, 18031, 7796, -9386, -10803, 5164, 16456, 7596, -9909, -13701, 805, 14134, 8460, -8518, -14347, -1232, 13381, 10290, -6015, -13716, -1702, 14913, 14265, -2302, -12442, -2680, 13774, 14784, -1513, -14477, -7411, 9875, 13875, -449, -13893, -8429, 9267, 16055, 3360, -11925, -9610, 7858, 17756, 7306, -9408, -10376, 5632, 17007, 8035, -9839, -13553, 1212, 14259, 7833, -9629, -14662, -338, 14217, 10193, -6460, -13763, -2016, 13159, 11680, -4655, -14613, -4674, 12221, 13612, -1903, -13224, -4456, 13762, 17916, 2993, -11329, -6801, 9586, 14780, 422, -15639, -13235, 3580, 12330, 1452, -14826, -14784, 2128, 13532, 4611, -12077, -14240, 1337, 14553, 8282, -8812, -13775, 176, 14379, 9769, -7447, -14083, -767, 15316, 13390, -4009, -14659, -4738, 12067, 12577, -4112, -16123, -8076, 8978, 12557, -1202, -13508, -7532, 9423, 14924, 1526, -13676, -10948, 6281, 14995, 4052, -10777, -8418, 9190, 19180, 8992, -7537, -9020, 6621, 19022, 12037, -4657, -8750, 5652, 19703, 14034, -4515, -12169, -277, 14004, 10938, -5881, -14603, -3831, 12443, 13080, -2654, -13793, -5465, 10914, 13178, -2072, -15038, -8413, 9206, 14258, -78, -15446, -12452, 4440, 12260, 98, -15693, -13574, 4240, 14807, 5066, -11121, -11413, 5391, 17022, 8228, -8994, -12335, 2357, 16050, 10744, -7010, -13942, -984, 13897, 10510, -6577, -14926, -4016, 11031, 9830, -6360, -16033, -5558, 12290, 14556, -1776, -15471, -8974, 8378, 13215, -728, -14937, -10542, 6898, 13922, 1051, -14358, -11610, 6051, 15428, 4853, -10999, -11349, 4346, 15124, 6192, -11057, -13994, 1533, 14812, 8488, -8343, -13154, 647, 14728, 10242, -6811, -14177, -2456, 12832, 11380, -5296, -15615, -5998, 10630, 11928, -3834, -15907, -8559, 8109, 11596, -3023, -16882, -11437, 7032, 14625, 1960, -13396, -10944, 5936, 14760, 3909, -12133, -11750, 5015, 16358, 8132, -7928, -9666, 6146, 18355, 10033, -8646, -14534, -1133, 13174, 8765, -9077, -16677, -4100, 11413, 9458, -6861, -15522, -4336, 12573, 13605, -2097, -14326, -7466, 8855, 11863, -3160, -16753, -10967, 7030, 13754, 1019, -13545, -9925, 7776, 16127, 4330, -11507, -10405, 5768, 15024, 4933, -11726, -13536, 2091, 14566, 7577, -9266, -13522, 627, 14235, 9088, -2672, -3304, -3641, -3400, -2742, -2452, -2408, -2226, -2310, -2815, -2996, -2573, -2274, -2465, -2727, -2673, -2209, -1848, -2076, -2496, -2698, -2833, -2546, -1943, -2867, -4603, -4325, -2891, -1829, -963, -602, -709, -467, 566, 1960, 2256, 1557, 1516, 1487, 1091, 229, -2225, -4414, -4788, -5105, -5237, -4309, -3830, -3996, -3504, -2822, -2121, -940, -154, -199, -257, -11, 72, -345, -975, -1111, -914, -795, -571, -373, -707, -1815, -2503, -2147, -2225, -2906, -3178, -3747, -4073, -3365, -3758, -5915, -7301, -6966, -6262, -6079, -5814, -4705, -4023, -4589, -5198, -5782, -6367, -6164, -5761, -5974, -6488, -6731, -6154, -4451, -2964, -3524, -4807, -4738, -3826, -3580, -4296, -5242, -5641, -5378, -4741, -4133, -4244, -4488, -3448, -2707, -4095, -5367, -5436, -5322, -4826, -4489, -4679, -4388, -3519, -2867, -2735, -2651, -2256, -1791, -1682, -2053, -2535, -2865, -3017, -3237, -3888, -4279, -3815, -3324, -3459, -3693, -4413, -5513, -5609, -5342, -5385, -4601, -2919, -1561, -1704, -2554, -2245, -1336, -960, -812, -933, -1320, -1540, -1622, -1506, -1455, -1815, -2528, -3891, -5346, -6038, -7009, -8358, -7732, -5846, -5334, -5342, -4408, -3132, -2277, -1798, -2312, -4095, -5504, -5976, -6363, -6371, -5868, -6563, -8347, -8690, -8147, -8708, -9921, -10542, -10259, -9518, -8485, -7170, -6023, -4917, -4046, -3972, -3468, -2199, -1847, -2618, -2931, -3145, -4641, -5605, -5098, -5017, -5865, -6247, -5815, -5708, -5707, -5320, -4923, -4380, -3041, -1540, -1826, -3049, -2542, -1526, -2140, -3101, -3744, -4544, -4717, -4467, -4627, -5122, -5014, -3471, -2794, -4335, -5226, -5102, -5310, -5200, -4784, -4552, -4241, -3390, -2038, -1128, -1041, -1292, -1735, -2517, -3436, -3746, -2951, -2520, -3969, -4942, -4432, -4299, -4331, -3844, -3244, -3009, -2756, -2184, -1551, -1148, -1436, -1991, -1136, 92, -622, -1216, -438, -69, -347, -866, -1729, -2147, -1439, -108, 1349, 2621, 3531, 4143, 4909, 5989, 6705, 5969, 4102, 3515, 3957, 3219, 1722, 899, 750, 276, -765, -1333, -1417, -2044, -2726, -2873, -3540, -4901, -5243, -3850, -2537, -3255, -4561, -4686, -4190, -4193, -4419, -4098, -4163, -4706, -4687, -4605, -4915, -5056, -5104, -5374, -5849, -5975, -5285, -5610, -7096, -7046, -5684, -4886, -4332, -3430, -3105, -3981, -4996, -4950, -3989, -3024, -2730, -2723, -2337, -2164, -2234, -2008, -2022, -2722, -3147, -2747, -2204, -1630, -1008, -727, -603, -149, 291, 184, -265, -800, -1862, -3010, -2513, -1397, -2183, -2844, -1192, 892, 2009, 2828, 3438, 3407, 3091, 2776, 1990, 690, -686, -2036, -2426, -691, 1827, 2119, 1281, 2169, 3563, 3935, 3730, 3086, 2300, 1724, 628, -417, -153, 811, 1082, 974, 1125, 1587, 2387, 2925, 3128, 3914, 4490, 3887, 3793, 5029, 5972, 5984, 5769, 5536, 4938, 3396, 1285, -59, -368, -333, 0, 489, 708, 1174, 1702, 1563, 1385, 1768, 2327, 3037, 3814, 3394, 2656, 3676, 4495, 3650, 3897, 5089, 4481, 3324, 3737, 4476, 4443, 4404, 4451, 4390, 4703, 5102, 5056, 5060, 5436, 5840, 6200, 6518, 7308, 8816, 8930, 7405, 7080, 7853, 7929, 7031, 5886, 4890, 4048, 3991, 4505, 4606, 4413, 4511, 4807, 4763, 4631, 5697, 7096, 6319, 4569, 4408, 5126, 5329, 5135, 5530, 5851, 4965, 4355, 4736, 4294, 2963, 2174, 2311, 3106, 2929, 1336, 832, 1608, 2119, 2778, 3463, 3221, 3277, 4660, 5890, 5537, 4271, 3417, 3044, 2479, 2040, 2241, 2081, 1352, 1707, 3144, 4110, 4804, 5206, 4809, 4109, 3396, 2887, 2972, 3202, 3440, 4237, 4789, 3763, 2301, 1714, 1545, 1600, 2130, 2757, 2597, 2434, 3090, 3616, 3633, 3795, 3786, 3619, 3941, 3476, 1983, 1199, 893, 636, 735, 919, 469, -403, -297, 866, 2139, 3140, 3611, 4112, 5492, 5831, 3902, 3214, 4510, 4942, 4736, 4551, 3918, 3516, 3500, 3297, 3188, 2929, 2360, 2500, 3680, 4192, 2614, 1267, 1240, 919, 863, 1164, 863, 610, 957, 1562, 2586, 3889, 3949, 2748, 2389, 2806, 2639, 2203, 2568, 3799, 4413, 3665, 3235, 4299, 4955, 4094, 3791, 4437, 4958, 5410, 5282, 4132, 3145, 3315, 3766, 2937, 1639, 1446, 1875, 2309, 2590, 2235, 1404, 1339, 2353, 3450, 4094, 4489, 3887, 3003, 3600, 4788, 5852, 6650, 6802, 6758, 6400, 5991, 5781, 4885, 4452, 5260, 5835, 5870, 6318, 7587, 8206, 6811, 5124, 5615, 6962, 7323, 6973, 6334, 5956, 5600, 4932, 4656, 4828, 4570, 4104, 4405, 4032, 2449, 2124, 2714, 2315, 1547, 1353, 1353, 1468, 1565, 1236, 1500, 1909, 1354, 1526, 2765, 3636, 4052, 4492, 5158, 4991, 3781, 3649, 4058, 2844, 2081, 3175, 4051, 4080, 4234, 4562, 4453, 4952, 5586, 3996, 2419, 3109, 3727, 3400, 3438, 3787, 3715, 3900, 4841, 4972, 4270, 4779, 5419, 4523, 3116, 2187, 1856, 1907, 1684, 1666, 3104, 3767, 1498, -6, 1192, 2331, 2516, 2816, 3586, 4117, 4009, 4055, 4936, 5121, 3503, 2563, 2931, 2772, 2257, 2371, 2742, 2751, 2720, 2731, 2924, 3550, 3123, 1689, 1274, 2182, 3560, 4205, 3917, 3563, 3302, 2587, 1843, 1698, 444, -2097, -2895, -2237, -2530, -3405, -3546, -2840, -1969, -1458, -1380, -1462, -655, 721, 944, 971, 1681, 2346, 3003, 3488, 3596, 3552, 3693, 4904, 6057, 4816, 3383, 3595, 3488, 2604, 2230, 2391, 2494, 2560, 2176, 1847, 2593, 2784, 1071, -56, -129, -729, -893, -645, -768, -386, 339, 288, 991, 3228, 3533, 1923, 1464, 1507, 953, 555, 577, 751, 1016, 1171, 1573, 2295, 1870, 666, 443, -184, -2394, -4261, -4913, -5414, -5395, -4329, -3010, -1625, -46, 417, -213, -191, 389, 1108, 1772, 2000, 1346, 143, -473, -541, 244, 1529, 910, -369, 136, 812, 850, 737, 220, -243, -319, -674, -963, 62, 914, -10, -100, 1417, 2593, 3357, 3697, 3649, 3534, 3079, 2068, 921, 745, 953, -221, -1444, -999, -611, -832, -392, 575, 1034, 590, -232, -286, 527, -109, -2010, -2390, -1707, -1236, -462, 181, 56, 352, 1579, 1953, 967, 659, 1388, 2159, 2734, 3176, 3364, 3102, 2503, 2133, 2132, 2831, 4711, 6000, 5295, 4878, 5348, 4688, 3635, 2968, 1839, 922, 792, 1186, 2196, 2438, 776, -885, -1393, -1622, -1547, -1187, -1163, -1423, -1020, 290, 1681, 1484, 73, 77, 1101, 1234, 803, 492, 204, 248, 1066, 1563, 320, -415, 855, 1684, 1002, -167, -727, -207, 279, 289, 1020, 1259, -697, -2328, -2265, -2380, -2960, -3612, -4085, -3467, -1904, -1014, -1010, -147, 1407, 1741, 1614, 2237, 2481, 1840, 1104, 618, 1072, 2823, 3589, 2000, 1188, 2028, 2376, 2509, 2741, 2475, 2167, 1846, 1350, 673, -1087, -2718, -1754, 149, 834, 912, 980, 1417, 2146, 2431, 2635, 3207, 3390, 3594, 4472, 4223, 3106, 3425, 3944, 3316, 2397, 1725, 1510, 1769, 1798, 1685, 2291, 2796, 2074, 1355, 1437, 1012, 402, 764, 1065, 1318, 2131, 2576, 2879, 3508, 3029, 997, -39, 399, 233, -601, -1011, -1027, -1067, -1266, -1401, -842, -549, -2203, -3811, -4148, -5013, -6042, -5992, -5139, -4302, -4009, -3938, -2846, -551, 378, -1247, -2216, -1605, -1285, -1541, -1608, -1310, -1092, -534, -35, -919, -1658, -535, 565, 411, 77, 527, 1652, 2493, 2488, 2010, 2113, 2238, 572, -1112, -1164, -1465, -2216, -1984, -893, -364, -686, -4, 1949, 2248, 917, 1107, 2182, 2518, 2477, 1917, 894, 187, 346, 764, 1442, 2791, 2772, 1249, 862, 998, 418, -141, -823, -2045, -3149, -3288, -2590, -2366, -3529, -4814, -4495, -3146, -1788, -465, 241, -131, -765, -1081, -1569, -2449, -2898, -2307, -2226, -3284, -3818, -3511, -3113, -3077, -2993, -2453, -2675, -4077, -4289, -3263, -4150, -5416, -4003, -2072, -888, 290, 884, 1223, 2283, 2195, 186, -1068, -1157, -1307, -1393, -1492, -2019, -2561, -2888, -3524, -4135, -3515, -2354, -3093, -4669, -4090, -2360, -1459, -1621, -2381, -2856, -2863, -2701, -1930, -980, -847, -259, 1007, 1300, 844, 497, 317, 132, 246, 1022, 1950, 2982, 4001, 3645, 2734, 3295, 3889, 2943, 2275, 2963, 3312, 2716, 2347, 1233, -1147, -2164, -1674, -1682, -2033, -1764, -597, 746, 1100, 719, 593, 813, 1841, 2864, 1314, -1293, -2140, -1975, -1464, -886, -658, -419, -97, -399, -1488, -2069, -915, 578, -675, -3004, -2930, -1946, -2044, -2277, -1576, -720, -229, 177, 320, 223, -122, -127, 496, 199, -526, -296, -77, -275, -216, 326, 466, -23, 446, 1634, 1436, 96, -521, -475, -735, -1209, -1461, -1455, -858, -73, 143, 275, 620, -5, -1463, -1630, -757, -143, 460, 839, 566, 262, 408, 667, -114, -1377, -1339, -858, -877, -1304, -1737, -1106, 153, 647, 840, 1426, 2296, 3480, 3376, 2072, 1654, 1617, 1448, 1570, 1729, 2011, 2086, 1306, 444, 884, 2641, 3199, 400, -2476, -2497, -1735, -1598, -1253, -577, -275, 313, 1466, 1170, -718, -1310, -319, 288, 526, 897, 941, 817, 721, 641, 469, 33, 669, 2651, 3377, 2452, 2358, 3319, 3799, 3391, 2656, 1842, 1457, 1867, 2015, 1945, 1553, 171, -416, -45, -420, -1373, -1769, -1403, -1504, -2519, -3339, -3514, -2693, -1321, -1050, -1771, -2329, -3120, -4045, -4194, -3959, -3706, -3079, -2450, -1789, -1226, -1777, -2318, -1694, -1227, -1743, -2827, -3404, -2820, -2359, -2860, -3114, -2659, -1710, -1506, -2961, -3706, -2752, -1586, -664, 214, 990, 1507, 1449, 1150, 1263, 1394, 1716, 1978, 772, -631, -577, 62, 541, 891, 768, 112, -671, -1364, -1592, -994, -191, -411, -603, 336, 573, -479, -1359, -1552, -1566, -1791, -1860, -1806, -2293, -2506, -2350, -3788, -5410, -4918, -4162, -4281, -4383, -4523, -4779, -5107, -5539, -5593, -5362, -4610, -2961, -2679, -4379, -4659, -3544, -3064, -2660, -2219, -2367, -2226, -1449, -867, -343, 645, 748, -1159, -2598, -1940, -560, 229, -318, -1162, -1226, -1398, -1948, -2143, -1990, -1368, -878, -1862, -2570, -1731, -1433, -1426, -692, -915, -2019, -2215, -1532, -1398, -2280, -2302, -919, 150, 243, -78, -213, -102, -481, -1659, -2390, -2597, -3303, -3465, -3524, -4815, -4580, -2346, -1469, -1997, -1949, -1659, -1821, -2433, -3205, -2966, -1626, -265, -333, -1624, -1922, -997, -13, 580, 650, 55, -1369, -3148, -4092, -3702, -3580, -5115, -6180, -5553, -4554, -3688, -3467, -3718, -3700, -3780, -4552, -4754, -2911, -1607, -2801, -3099, -1669, -1084, -964, -593, -582, -507, -42, -14, -119, 164, 606, 1068, 26, -2452, -3085, -2024, -1713, -1883, -1790, -1794, -1969, -2098, -1709, -378, 609, -751, -2918, -3612, -3752, -3919, -4076, -4313, -4011, -3522, -3030, -1541, 278, 379, -504, -169, 601, 780, 1195, 1568, 1329, 1254, 1133, 443, 427, 582, -1186, -2917, -2710, -2615, -3210, -3533, -3640, -3472, -2913, -2309, -2161, -2191, -1225, 301, -112, -1633, -1590, -1117, -1694, -2479, -2712, -2751, -2699, -2261, -1879, -1937, -1893, -1253, 282, 863, -870, -1775, -713, -63, -32, 219, 211, -419, -1203, -973, -771, -2627, -4519, -4199, -3142, -2949, -3220, -3418, -3437, -3387, -3779, -4541, -4398, -2699, -1730, -3438, -5199, -4535, -3122, -2307, -1721, -1573, -2130, -2677, -3031, -3868, -4233, -3538, -4230, -5648, -5427, -5449, -6847, -7680, -7340, -6463, -4978, -3481, -2412, -1834, -2701, -4604, -5008, -3876, -3221, -2620, -1512, -1097, -1103, -725, -997, -1559, -1043, -1058, -1911, -1263, 87, 537, 636, 1243, 2409, 3365, 3463, 3242, 3335, 2215, -229, -1427, -1457, -1362, -952, -408, 127, -66, -1061, -1190, -481, -509, -456, 703, 1166, 233, 244, 1307, 1731, 1655, 1756, 1482, 327, -399, 379, 305, -1493, -1797, 166, 2004, 2598, 2425, 2021, 1265, 275, -112, -316, -787, -1254, -1145, -285, -255, -769, -442, -270, -55, 756, 995, 542, 472, 1340, 2648, 2905, 2398, 3388, 4952, 3635, 1090, 1018, 1530, 1131, 1164, 930, 119, 63, 140, 94, 553, 1034, 2005, 2601, 1093, -390, -188, -103, -542, -123, 337, -21, 62, 772, 955, 652, 764, 1021, 217, -559, 253, 894, 490, 141, -78, -338, -437, -463, -484, 37, 1128, 679, -1795, -2982, -2575, -2379, -2008, -1781, -1947, -1999, -1470, -530, -1097, -2611, -2606, -1537, -952, -1257, -1534, -1024, -187, 576, 1012, 1663, 2602, 1568, -398, -345, 295, 116, 396, 863, 704, 759, 1172, 1709, 2089, 1735, 1125, 1610, 2147, 903, -380, -380, -319, -296, 225, 394, -335, -922, -669, -819, -1298, -645, -126, -1673, -3171, -2932, -2310, -2014, -2080, -2327, -1799, -408, 614, 965, 1564, 2122, 1149, -164, -67, 258, 185, 244, 356, 425, 389, 682, 1875, 1828, 220, 218, 1239, 1455, 919, -280, -1391, -1799, -2416, -3143, -3019, -2439, -2187, -1273, 52, -647, -1920, -1337, -429, -508, -691, -827, -1446, -1371, -252, -58, -173, 813, 446, -1304, -1339, 73, 1252, 1765, 2150, 2556, 2649, 2598, 2534, 2582, 2507, 2055, 1332, 517, 146, -7, 63, 449, 569, 185, -191, -213, -81, 143, -47, -822, -501, 1512, 2012, 427, -10, 417, 155, -7, 167, -63, -495, -290, 384, 730, 748, 459, 107, 1259, 2633, 1191, -921, -674, 287, 625, 1398, 2334, 2204, 1666, 1557, 1477, 1019, 132, 292, 1545, 1408, 542, 535, 829, 1495, 2094, 1719, 1161, 1305, 1369, 1160, 1612, 1960, 1851, 3468, 5739, 5272, 3321, 2832, 3067, 2888, 2578, 1792, 1317, 2256, 2982, 2588, 2383, 2431, 2400, 3313, 4175, 2581, 953, 1800, 2801, 2570, 2206, 2164, 1671, 771, -112, -900, -754, -96, -924, -2037, -1810, -2464, -4176, -3695, -1376, -136, -80, 621, 1731, 1642, 915, 951, 833, -326, -727, 311, 344, -1040, -1288, -160, 910, 1653, 2254, 2706, 3140, 3311, 2814, 2230, 2812, 3699, 2693, 1333, 1748, 2613, 3080, 3722, 3876, 3293, 3091, 3271, 3028, 1495, -788, -1412, -197, 1087, 1319, 259, 136, 1739, 2175, 1341, 1766, 2890, 2872, 2513, 2788, 2742, 2140, 2222, 3306, 3535, 1871, 673, 926, 1155, 1687, 2948, 3291, 2836, 3295, 3674, 3254, 2878, 2913, 3601, 3795, 2239, 718, 655, 1297, 1600, 1376, 1332, 1535, 1206, 605, 1397, 2198, 940, -319, 125, 1300, 1564, 719, 557, 1050, 1064, 1457, 2197, 2036, 1590, 2338, 3541, 2650, 167, -699, 29, 254, -8, 284, 747, 541, -107, 176, 1241, 905, 96, 652, 1016, 890, 1080, 912, 435, 214, 401, 795, 657, 277, 998, 1756, 977, 279, 550, 791, 1231, 2041, 1678, 674, 604, 39, -1173, -1094, 56, 215, -743, -609, 208, -179, -956, -784, -259, -245, -333, 795, 2036, 1275, 720, 1508, 1473, 1405, 2195, 2259, 1885, 2061, 1875, 1151, 643, 374, 256, 812, 1519, 1078, 484, 760, 811, 385, 81, -456, -1319, -1467, -957, -484, -210, 176, 1002, 653, -926, -1069, 47, 522, 844, 1830, 2684, 2561, 2300, 2549, 3457, 4955, 5043, 3618, 3627, 4846, 4579, 2858, 1665, 874, -220, -561, -674, -1234, -357, 1662, 2002, 1305, 1473, 1368, 901, 865, 857, 585, 541, 783, 677, 1455, 3394, 3293, 1320, 1174, 2000, 1523, 798, 713, 1130, 1821, 1913, 1401, 1393, 1815, 1929, 1723, 987, 232, 422, 686, 800, 1423, 1930, 1756, 1706, 1810, 967, 66, 334, 70, -742, -426, 359, 762, 843, 307, -222, 20, 201, 56, 88, -411, -678, 729, 1518, 620, 996, 2455, 2737, 2565, 2644, 2248, 1154, 557, 1072, 1364, 1133, 1755, 1965, 762, 487, 1116, 1111, 994, 1155, 1392, 1373, 893, 552, 1007, 2115, 3517, 4096, 2781, 1797, 2455, 2638, 1492, 511, 790, 1115, 600, 409, 1076, 1019, -134, -24, 1505, 2385, 2262, 2313, 2859, 3256, 3368, 3305, 3407, 4080, 4660, 4162, 3322, 3453, 4505, 4299, 2028, 564, 864, 1481, 1518, 1182, 1243, 1458, 1331, 568, -337, -309, 287, -123, -726, 319, 1478, 1939, 2514, 2784, 2378, 1481, 745, 678, 897, 976, 1378, 2416, 2734, 1601, 1733, 3061, 3239, 2955, 2776, 2391, 1622, 1048, 1232, 1653, 1719, 1290, 1086, 1299, 1367, 1586, 1526, 1099, 1308, 1513, 1261, 1503, 2068, 2854, 4356, 5043, 3439, 2092, 2602, 3035, 2978, 3035, 2472, 1852, 2010, 2129, 1820, 1003, 608, 1441, 1023, -1102, -1825, -1038, -458, -253, 239, 450, -122, -695, -436, 1017, 1404, -441, -921, 458, 927, 471, 426, 1154, 1559, 815, 406, 1356, 1758, 849, 547, 1024, 1233, 1048, 618, 295, 56, -207, -169, 150, 214, 621, 1549, 1170, -379, -756, -338, -569, -870, -399, 481, 1060, 719, -98, -67, 190, -43, 578, 1750, 1006, -308, 121, 1127, 1510, 1016, 304, -200, -968, -1681, -1719, -1279, -586, -92, 345, 2226, 4070, 3082, 1336, 578, -150, -822, -1139, -1827, -2735, -3063, -2993, -2702, -2125, -1366, -1087, -1633, -1431, -329, -978, -2713, -2713, -2047, -2375, -2779, -2636, -2461, -2518, -2387, -2230, -2899, -3985, -3747, -2577, -3639, -5970, -5678, -3417, -1791, -1469, -1675, -1415, -1635, -2942, -3674, -3274, -2700, -2441, -2097, -1181, -994, -2248, -2288, -910, -420, -226, 588, 1372, 1649, 1478, 1180, 758, 184, 302, 1558, 2312, 1091, -97, 69, 371, 563, 416, 0, -131, -201, -817, -1488, -1477, -855, -216, -1077, -2253, -1145, 597, 515, -321, -104, 612, 935, 1107, 1609, 2750, 3415, 2399, 1415, 1684, 1527, 567, 168, 87, -168, -309, -697, -1220, -1131, -927, -1101, -742, -615, -1654, -2065, -1892, -2313, -2528, -2252, -2209, -2157, -1889, -1583, -566, 499, -509, -2103, -1847, -814, -535, -855, -911, -735, -993, -1885, -2328, -1499, -1340, -3039, -3754, -2584, -1904, -1879, -1498, -1853, -2841, -2638, -1457, -525, -75, -447, -1891, -3118, -2709, -1471, -1966, -3768, -4207, -3558, -3231, -2732, -1592, -753, -881, -1253, -1169, -1215, -1533, -1016, -380, -1432, -2610, -2144, -1149, -825, -865, -774, -577, -1026, -2240, -2662, -2429, -2893, -3121, -2704, -2557, -2469, -2292, -2164, -2848, -4042, -3854, -2473, -1476, -883, -205, 161, -326, -1452, -1720, -443, -222, -2656, -4515, -4117, -3669, -4167, -4476, -3869, -2582, -1391, -412, 934, 1722, 831, -313, -441, -1387, -3994, -5033, -3535, -2382, -2270, -1836, -1305, -748, 294, 725, -354, -1617, -1575, -1354, -1298, -589, -989, -2120, -1659, -428, 593, 1585, 2182, 2128, 1591, 798, 19, -220, 29, -527, -1513, -1620, -2289, -3315, -2870, -2402, -2746, -2769, -2389, -2583, -3685, -4052, -2475, -184, 746, 560, 1614, 2872, 1796, 198, 182, 304, -384, -779, -390, -733, -1322, -810, -1068, -1871, -1267, -365, -575, -1403, -1713, -1484, -1103, -698, -478, -615, -808, -1060, -1428, -1010, -219, 635, 2832, 4230, 3277, 3319, 4090, 3378, 2759, 2977, 3357, 3810, 3674, 2694, 2241, 3666, 4769, 2959, 774, 794, 1789, 2517, 2385, 1702, 2135, 3451, 3626, 2663, 1993, 2087, 2844, 2378, -561, -3210, -3619, -3572, -4443, -5408, -5675, -5837, -5669, -4576, -4106, -4371, -3092, -907, -977, -2158, -1009, 1092, 1225, 393, 398, 770, 1224, 1824, 2344, 2798, 2694, 2282, 3323, 4180, 1555, -1684, -1923, -1292, -1611, -1868, -1745, -1882, -2287, -2375, -2143, -2562, -3723, -4052, -2223, -1429, -3375, -3858, -2225, -1033, -704, -607, -9, 696, 382, -1083, -2266, -2253, -1506, -803, -58, 929, 1777, 1570, 1040, 1890, 2988, 3557, 3846, 2813, 1070, -164, -1376, -1700, -1314, -1994, -1841, 92, 590, -193, 1142, 2446, 605, -1500, -2062, -2608, -3704, -4078, -3575, -4260, -5352, -4919, -4345, -4082, -2764, -687, 912, 2043, 1996, -217, -1561, -523, -474, -2491, -3528, -3026, -2930, -2983, -2132, -1615, -2341, -2946, -2873, -2006, -821, -1520, -3796, -4089, -2250, -398, 1425, 2560, 1940, 463, -440, -119, 1009, 1168, 1, -435, -423, -80, 768, 12, -1038, -656, -668, -810, 200, 505, -848, -1470, -684, -219, -758, -1711, -2398, -2603, -1911, -760, -1342, -3067, -2686, -1191, -1425, -2495, -3197, -3448, -3600, -3838, -3289, -2722, -3334, -3377, -2219, -995, -267, -552, -1935, -3007, -2740, -2223, -2085, -1421, -76, 125, -1175, -1406, 23, 931, 592, 58, -298, 19, 1609, 1519, -922, -1298, 437, 579, -994, -1517, -912, -1395, -2377, -2523, -2854, -4019, -4695, -4366, -4071, -3791, -3352, -3573, -3690, -2609, -2137, -3115, -3365, -2863, -3609, -4416, -3612, -2277, -1966, -2460, -2292, -1441, 70, 1859, 719, -2294, -2349, -708, -639, -1370, -1566, -1058, -487, -635, -736, -70, 225, -474, -638, -702, -2289, -3088, -1454, 397, 1001, 1148, 1427, 766, -730, -1344, -1381, -1495, -1712, -2375, -2401, -1718, -1265, -329, 358, -554, -1675, -2280, -2525, -1463, -118, 374, 399, 104, 184, 705, 1000, 1646, 2861, 3007, 2496, 3199, 2953, 729, -225, 477, 915, 543, -410, -311, 1097, 631, -1377, -1557, -365, 228, -35, -461, 285, 2129, 1755, -1403, -3003, -2276, -2072, -2123, -1454, -943, -531, 252, 1159, 1448, 1183, -1618, -1722, -1757, -1365, -1021, -1053, -1357, -2033, -2725, -2842, -3122, -3498, -2833, -1593, -761, -282, 75, 277, 557, 1180, 1338, 137, -1624, -2943, -3335, -2750, -2281, -1961, -1222, -908, -1217, -1330, -1201, -961, -616, -480, -689, -600, 138, 316, -313, -589, -633, -861, -722, -369, -246, 182, 471, 37, 131, 875, 1039, 1085, 1564, 1400, 992, 1529, 2009, 1662, 1209, 945, 791, 621, 181, -628, -1350, -1513, -1344, -1248, -1500, -1853, -1978, -2657, -3449, -2845, -1653, -956, -205, 631, 696, 153, -46, 161, 56, -396, -641, -805, -991, -1176, -1354, -1496, -1991, -2224, -1375, -120, 781, 1202, 985, 0, -1207, -2138, -2675, -2880, -2507, -1604, -707, 126, 460, 226, 375, 921, 1112, 576, -569, -1657, -2262, -2674, -2899, -2884, -2835, -2844, -3019, -3119, -3035, -3138, -3185, -3060, -3100, -3222, -3094, -2403, -1386, -534, 177, 662, 804, 536, -120, -436, -114, 89, -350, -909, -751, 47, 657, 508, -177, -764, -1057, -1473, -2170, -2603, -2425, -2012, -1580, -1136, -1253, -2076, -3091, -3747, -3494, -2554, -2228, -2436, -1983, -1311, -618, 588, 1407, 1011, 555, 602, 182, -376, -193, 190, 360, 1099, 2509, 3534, 3722, 3742, 3723, 3244, 2706, 2246, 1488, 924, 905, 414, -982, -2288, -2898, -3169, -3264, -2924, -2431, -2484, -2618, -2506, -2725, -3120, -2932, -2438, -2521, -2965, -2896, -2245, -2085, -2545, -2455, -1533, -313, 926, 1859, 2021, 1580, 918, 437, 783, 1469, 1186, 262, -153, -582, -1350, -1312, -627, -218, 181, 598, 793, 1099, 1358, 1297, 1153, 906, 334, -180, -85, 195, 215, 368, 559, 416, 111, -33, -276, -869, -1715, -2388, -2395, -2188, -2217, -1917, -1136, -272, 800, 1596, 1656, 1914, 2473, 2335, 1841, 1658, 1538, 1393, 1098, 643, 315, 146, 128, -9, -513, -1233, -2067, -2740, -3123, -3340, -3280, -2980, -2740, -2551, -2076, -1389, -1017, -812, -126, 484, 436, 560, 1288, 1870, 1723, 1013, -116, -911, -338, 643, 1020, 1254, 1868, 2650, 2685, 2025, 1440, 1017, 409, -528, -1474, -1883, -1807, -1819, -2302, -3033, -3231, -2806, -2414, -2337, -2302, -2191, -1943, -1245, -505, -438, -570, -579, -898, -1231, -1005, -530, -356, -191, 320, 927, 1390, 1661, 1749, 1904, 2207, 2489, 2664, 2741, 2588, 2134, 1315, 205, -838, -1619, -2313, -2843, -2875, -2653, -2121, -911, 244, 228, -684, -1425, -1507, -1244, -1327, -1548, -1117, -809, -1493, -2147, -2247, -2323, -2202, -1730, -719, 686, 1376, 1095, 785, 550, 100, 19, 446, 587, 324, 466, 661, -37, -1178, -2237, -3383, -3989, -3676, -2982, -2383, -1863, -1134, -327, 214, 435, 543, 863, 1179, 1243, 1039, 590, 255, 183, 396, 549, 378, 643, 1284, 1187, 554, -66, -807, -1100, -907, -920, -807, -403, -79, 81, 64, -315, -1152, -1842, -1849, -1401, -751, -534, -770, -823, -1041, -1422, -1367, -1314, -1686, -1717, -1115, -644, -365, 169, 952, 2009, 2888, 2850, 2329, 1952, 1399, 255, -969, -1413, -982, -488, -601, -603, -276, -374, -743, -1191, -1892, -2200, -1587, -722, -573, -1093, -1268, -1052, -1188, -1130, -418, -124, -535, -518, -317, -582, -504, -114, 3, -1, -56, 13, 387, 467, 107, 102, 395, 502, 555, 515, 81, -420, -510, -142, 210, 48, -490, -1071, -1423, -1580, -1563, -1058, 86, 757, 221, -74, 535, 765, 689, 1143, 1348, 894, 559, 345, -442, -1561, -2269, -2475, -2533, -2522, -2443, -2075, -1031, 235, 951, 1033, 664, 171, 55, -111, -746, -1178, -1276, -1451, -1545, -1584, -1629, -1264, -733, -597, -721, -627, -550, -1055, -1565, -1414, -1335, -1730, -1878, -1633, -1411, -1317, -1225, -1090, -865, -288, 444, 893, 1359, 2021, 2590, 3286, 3973, 4345, 4433, 4135, 3804, 3330, 2494, 2223, 2653, 2421, 1390, 660, -239, -1730, -2958, -3646, -3810, -3331, -2690, -2075, -1309, -552, 190, 962, 1421, 1662, 1821, 1512, 753, -377, -1667, -2342, -1979, -737, 621, 1353, 1428, 1360, 1554, 1563, 1059, 785, 1078, 1080, 589, 342, 327, 536, 955, 906, 398, -42, -204, -388, -517, -208, 10, -340, -781, -715, -391, -203, -2, 252, 623, 1356, 1992, 2231, 2588, 2952, 2820, 2533, 2186, 1389, 724, 656, 864, 1144, 1279, 1099, 854, 1076, 1476, 1439, 1089, 776, 796, 948, 834, 627, 500, -66, -757, -672, -140, 354, 783, 1211, 1908, 2797, 3545, 4259, 4531, 3763, 2953, 2949, 2875, 2130, 1314, 870, 640, 241, -320, -739, -523, 541, 1841, 2551, 2388, 2141, 2356, 2457, 2156, 1775, 1677, 1925, 1722, 853, 271, 161, 11, -204, 136, 1121, 2007, 2444, 1917, 751, 5, -835, -1708, -1504, -506, 279, 737, 1323, 1934, 2018, 1561, 1403, 1683, 1473, 672, -315, -1030, -1179, -888, -431, 54, 701, 1131, 1362, 1925, 2479, 2733, 3013, 3312, 3290, 3100, 2926, 2435, 1599, 764, 190, 83, 439, 661, 390, -122, -454, -410, -418, -695, -747, -675, -976, -1234, -758, -198, -475, -859, -845, -964, -1376, -1600, -1226, -459, -1, 104, 393, 525, 247, 11, -87, -177, 171, 754, 895, 1113, 1505, 1689, 2277, 2803, 2084, 1279, 1607, 1950, 1761, 1713, 1561, 1099, 894, 814, 387, 90, 70, -131, -360, -206, 49, -131, -613, -671, -196, 93, 195, 477, 696, 530, 0, -281, -163, -181, -41, 102, -38, 253, 841, 987, 1085, 1144, 395, -420, 87, 992, 303, -1264, -2119, -2362, -2396, -2184, -1555, -780, -754, -952, -399, 202, 636, 1527, 2518, 2889, 2855, 2767, 2149, 1309, 1155, 866, -13, -449, -594, -1270, -2168, -2410, -2100, -1612, -1183, -1251, -1584, -1835, -1861, -1569, -1247, -1264, -1251, -875, -323, 66, 120, -22, 56, 494, 764, 898, 1547, 2445, 2627, 2159, 2091, 2723, 3448, 3864, 4009, 3966, 3448, 2414, 1537, 859, 82, -981, -2345, -3079, -2380, -1454, -1628, -1777, -1126, -931, -1497, -1882, -2089, -2277, -2201, -1840, -1583, -1705, -1474, -827, -465, -461, -637, -853, -1061, -1063, -722, -339, -66, 101, 190, 711, 1527, 1644, 1120, 636, -2, -712, -927, -914, -1188, -1332, -697, 172, 348, -20, -323, -387, -634, -1300, -1946, -2139, -2071, -2314, -2446, -2104, -1870, -1712, -1186, -581, -226, 39, 31, -87, 209, 695, 926, 1187, 1632, 1716, 1242, 784, 586, -11, -684, -664, -484, -486, -392, 296, 1499, 2282, 2837, 3434, 3427, 3095, 2642, 2049, 1876, 1723, 712, -505, -1193, -1378, -1163, -1025, -1179, -1113, -730, -414, -13, 735, 1830, 2685, 3000, 3322, 3638, 3583, 3273, 2934, 2757, 3084, 3587, 3424, 2965, 2746, 2490, 1878, 1006, 373, 120, -111, -309, -278, 31, 63, -612, -1271, -1548, -1587, -1362, -788, 52, 649, 858, 910, 944, 917, 702, 537, 794, 1388, 1544, 1133, 1053, 1392, 1643, 1803, 1413, 807, 1209, 1675, 1160, 1111, 1992, 2131, 1428, 1098, 1668, 2800, 3677, 3955, 3737, 3395, 2998, 1991, 837, 447, 448, 451, 655, 900, 922, 898, 1086, 1193, 1027, 965, 471, -556, -1244, -1454, -1301, -539, 622, 1202, 1108, 1319, 1635, 1294, 652, 587, 1122, 1403, 1164, 846, 533, -2, -736, -1578, -2348, -2314, -1636, -1184, -1074, -1207, -1292, -802, 19, 29, -1093, -2515, -3565, -4019, -4022, -3891, -3486, -2525, -1282, -150, 954, 2047, 2753, 3109, 3196, 3061, 2891, 2813, 3117, 3722, 3953, 3734, 3521, 2984, 2249, 1892, 1518, 836, 484, 629, 469, -328, -992, -1024, -739, -824, -1229, -1647, -2352, -3215, -3768, -4167, -4326, -3759, -3129, -2969, -2836, -2629, -2628, -2461, -1897, -1621, -1121, 27, 933, 1274, 1315, 1229, 1157, 998, 482, -6, 88, 428, 525, 670, 1238, 1588, 1416, 1112, 604, 253, 370, 429, 192, 1, -118, -276, -298, -470, -1047, -1537, -1614, -1842, -2379, -2451, -2327, -2493, -2383, -1916, -1735, -1759, -1563, -1057, -396, 568, 1726, 2371, 2373, 2220, 2303, 2521, 2730, 2876, 2857, 2470, 1809, 1473, 1202, 997, 1334, 1613, 1708, 2062, 2375, 2216, 1771, 852, -589, -1405, -1079, -622, -675, -536, 247, 1104, 1572, 1520, 1172, 620, -81, -438, -326, -204, -333, -228, 10, -199, -271, 175, 407, 362, 380, 92, -582, -858, -565, -239, 99, 937, 2382, 3818, 4931, 5469, 5181, 4849, 4796, 4280, 3367, 2536, 1880, 1428, 1144, 737, 320, 310, 661, 1213, 1670, 1680, 1601, 1750, 1649, 1181, 616, -60, -804, -1585, -2268, -2647, -2803, -2787, -2495, -1905, -957, 179, 1152, 1704, 1577, 1364, 1649, 2053, 2295, 2172, 1527, 1058, 1504, 2145, 2236, 2150, 1985, 1365, 443, -286, -473, -23, 732, 1249, 1654, 2180, 2297, 1695, 955, 559, -369, -1844, -2320, -1950, -1828, -1713, -1219, -511, 9, -40, -443, -588, -443, -324, -148, 678, 1806, 2228, 2317, 2641, 2734, 2378, 2271, 2532, 2382, 1802, 1617, 1871, 1726, 1062, 575, 176, -140, -72, -323, -791, -311, 557, 1022, 1677, 2682, 3279, 3277, 2699, 1212, -605, -1732, -2093, -1940, -1550, -1138, -623, -195, -77, -21, -154, -652, -1189, -1234, -618, -49, 509, 1330, 1742, 1459, 841, 844, 1442, 1464, 988, 817, 1118, 1475, 1333, 798, 422, 336, 62, -827, -1596, -1559, -1272, -1207, -1182, -1079, -1175, -1298, -783, -150, -440, -1256, -1635, -1371, -1128, -1372, -1412, -849, -146, 447, 757, 742, 1204, 2341, 3034, 3110, 3404, 3698, 3539, 3125, 2688, 2174, 1557, 1261, 1232, 937, 481, 244, -66, -458, -347, -24, 184, 462, 416, -60, -381, -249, -249, -650, -769, -380, 216, 614, 698, 285, -210, -200, -262, -398, 19, 580, 753, 992, 1650, 2325, 2334, 1881, 1714, 1571, 949, 298, 247, 350, 63, -215, -359, -801, -1334, -1856, -2319, -2147, -1672, -1334, -962, -862, -964, -593, -277, -618, -990, -1232, -1699, -2099, -2682, -3590, -3674, -2631, -1701, -1280, -548, 432, 835, 746, 937, 1259, 1166, 785, 702, 791, 553, 277, 129, 63, 7, -167, -371, -666, -1083, -1322, -1461, -1878, -2179, -2102, -2290, -2286, -1625, -1564, -2287, -2606, -2371, -2215, -2395, -2764, -2775, -2035, -1185, -796, -656, -534, -43, 901, 1481, 1407, 1345, 1853, 2498, 2445, 1922, 1724, 1859, 1952, 1957, 1966, 1528, 638, 74, -261, -703, -1308, -2003, -2032, -1603, -1872, -2251, -1747, -1201, -1433, -1874, -1830, -1904, -2314, -2155, -1506, -692, 86, 196, -123, 89, 920, 1361, 1053, 779, 842, 567, -228, -829, -831, -397, 441, 1291, 1504, 1521, 1648, 1293, 674, 519, 370, -214, -510, -278, -29, 71, 45, -99, -34, -10, -284, -381, -650, -1312, -1385, -865, -553, -126, 600, 967, 858, 768, 757, 587, 443, 674, 1354, 1866, 1706, 1255, 867, 885, 1175, 1064, 563, 54, -263, -148, 153, 235, 295, 362, -168, -1234, -1996, -2190, -2146, -1851, -1271, -361, 606, 1330, 2230, 3607, 4811, 5039, 4213, 2752, 1521, 761, -178, -950, -600, 281, 892, 1710, 2178, 1343, -97, -1347, -2167, -2444, -2221, -1366, -324, 166, 271, 606, 1245, 1911, 2372, 2344, 2318, 2508, 2019, 890, 218, 346, 649, 737, 757, 855, 644, -359, -1689, -2566, -2864, -3214, -3705, -3739, -3423, -3055, -2439, -1678, -1063, -357, 665, 1424, 1464, 1111, 819, 841, 1199, 1542, 1575, 1555, 1575, 1598, 1758, 1745, 1496, 1421, 1173, 344, -424, -216, 730, 1635, 2351, 2309, 1601, 1432, 1332, 701, 223, -266, -1099, -1615, -1549, -1033, -220, 298, 660, 1445, 2008, 1875, 1917, 2393, 2587, 2313, 1936, 1420, 757, 155, -171, -333, -268, 72, 110, -99, 174, 829, 856, 159, 41, 377, -48, -662, -483, -225, -722, -1426, -1373, -618, -209, -416, -891, -1373, -1844, -2384, -2359, -1332, -66, 782, 1094, 1072, 1040, 771, 549, 579, 544, 909, 1429, 1718, 2509, 3123, 2651, 1811, 1357, 1181, 848, 192, -646, -1325, -1502, -1278, -727, 210, 924, 1042, 1012, 829, 314, -65, -211, -528, -768, -715, -709, -1050, -1515, -1271, -305, 200, 175, 429, 777, 1007, 1447, 1949, 2025, 1670, 1454, 1423, 878, 400, 816, 1196, 1073, 1216, 1589, 2065, 2358, 1920, 1611, 1831, 1247, 98, -321, -528, -879, -672, -215, 36, 493, 1149, 1607, 1787, 1843, 1493, 422, -729, -1413, -1449, -868, 0, 1219, 2271, 2613, 2819, 2842, 2147, 1303, 834, 576, 339, 367, 644, 851, 1314, 1862, 1872, 1736, 1593, 836, -183, -535, -543, -657, -461, -854, -1979, -2294, -2251, -2503, -2530, -2376, -2060, -1463, -981, -714, -592, -660, -1016, -1683, -2247, -2050, -1397, -1505, -2020, -1868, -1268, -915, -874, -813, -633, -325, -138, -204, -551, -1173, -1535, -1247, -842, -948, -1093, -1072, -1477, -1820, -1681, -1831, -2188, -1894, -1235, -1004, -932, -875, -1099, -1139, -958, -788, -652, -565, -635, -1216, -1808, -1602, -907, -332, -147, -393, -685, -359, 731, 1696, 1807, 1632, 1612, 1447, 1329, 1715, 2224, 2467, 2543, 2243, 1593, 1088, 1047, 1209, 1082, 777, 716, 775, 970, 1113, 1025, 1029, 1341, 1794, 1996, 1961, 1811, 1628, 1546, 1473, 1291, 1111, 1026, 1282, 1867, 2377, 2373, 1702, 824, 424, 367, -22, -554, -599, -123, 638, 1567, 2677, 3758, 3816, 2792, 2015, 1864, 1791, 1677, 1622, 1624, 1645, 2188, 3082, 2979, 2110, 1592, 1232, 835, 699, 549, 285, 325, 406, 277, 222, 44, -329, -634, -644, -468, -830, -1327, -1016, -386, -189, -82, 219, 579, 1067, 1270, 952, 825, 1139, 1387, 1397, 1444, 1582, 1587, 1481, 1085, 477, 189, 256, 614, 836, 568, 485, 880, 824, -36, -702, -867, -1430, -2193, -2030, -1389, -1071, -712, -617, -771, -310, 60, -218, -667, -1212, -1594, -1706, -1910, -1813, -1304, -813, -405, -301, -537, -594, -83, 215, -200, -457, -148, -176, -631, -485, 75, 206, -147, -432, -544, -624, -769, -1286, -1678, -1364, -689, -324, -594, -1341, -2101, -2454, -2574, -2587, -2413, -2247, -2139, -1936, -1589, -1064, -620, -941, -1909, -2586, -2517, -2172, -1830, -939, 217, 849, 1259, 1665, 1924, 2065, 1714, 802, -24, -351, -293, 78, 695, 1203, 1300, 1205, 1055, 801, 947, 1004, 358, 34, -127, -794, -1045, -470, 370, 913, 504, -57, 356, 735, 461, 452, 931, 1428, 1845, 1931, 1785, 1991, 2244, 2156, 1795, 1219, 929, 1230, 1766, 2180, 2591, 3043, 3226, 3326, 3648, 3905, 3404, 2549, 2181, 1839, 976, 56, -291, -287, -400, -534, -545, -717, -1271, -1770, -1753, -1797, -2061, -1798, -1293, -1117, -795, -135, 153, 126, 197, -170, -966, -1372, -1306, -1203, -1322, -1693, -1887, -1612, -1487, -1735, -1786, -1681, -1708, -1705, -1658, -1835, -2160, -2215, -2244, -2473, -2446, -2093, -1879, -2002, -2297, -2511, -2426, -2343, -2361, -2026, -1486, -1399, -1877, -2455, -2756, -2670, -2298, -1866, -1338, -955, -1056, -1141, -483, 448, 385, -335, -611, -572, -629, -741, -696, -411, 210, 720, 636, 93, -564, -1056, -1335, -1594, -1769, -1680, -1403, -943, -454, -220, -266, -691, -1454, -2098, -2339, -2072, -1740, -1781, -1607, -1015, -791, -1035, -1431, -1601, -1223, -961, -911, -540, -359, -396, -104, 359, 811, 1107, 878, 327, 54, -22, -264, -564, -685, -583, -228, 292, 558, 433, 318, 176, -336, -741, -627, -777, -950, -638, -718, -1007, -736, 78, 832, 1021, 790, 491, 156, -237, -442, -295, -71, -189, -638, -1004, -1155, -1287, -1419, -1191, -562, -102, -9, -225, -433, 86, 749, 361, -103, 214, 270, -397, -1221, -1572, -1252, -690, -364, -256, -443, -781, -618, -34, 15, -429, -890, -1447, -1989, -2579, -3077, -2998, -2284, -1391, -1111, -1525, -1772, -1457, -1120, -1230, -1490, -1411, -1227, -1372, -1687, -1693, -1150, -714, -829, -960, -1008, -1349, -1564, -1375, -1665, -2341, -2747, -3142, -3451, -3390, -3148, -2841, -2580, -2555, -2518, -2313, -2294, -2294, -1946, -1699, -1836, -1854, -1610, -1484, -1669, -1908, -1621, -1293, -1722, -2090, -1737, -1379, -1406, -1471, -1506, -1623, -2083, -2804, -3139, -3154, -3224, -3048, -2564, -2075, -1669, -1576, -1844, -2128, -2322, -2449, -2535, -2703, -2770, -2227, -1226, -559, -539, -865, -1118, -1308, -1705, -2318, -2602, -2236, -1894, -1914, -1886, -1605, -1242, -998, -958, -1016, -1233, -1451, -987, -241, 136, 504, 690, 459, 279, -279, -1272, -1724, -1751, -1657, -1167, -648, -434, 34, 876, 1358, 1049, 182, -363, -534, -1251, -2177, -2402, -2044, -1446, -1181, -1469, -1431, -819, -442, -352, -359, -754, -932, -606, -617, -867, -873, -527, 443, 1381, 1533, 1358, 1290, 816, -296, -1312, -1869, -2022, -1809, -1080, 16, 724, 872, 1209, 1536, 671, -938, -1963, -2414, -2740, -2661, -2079, -1626, -1596, -1394, -963, -725, -722, -910, -1225, -1506, -1863, -2336, -2279, -1816, -1338, -1006, -1280, -1577, -1428, -1482, -2138, -2674, -2588, -2619, -2944, -2849, -2486, -2512, -2533, -2231, -2116, -2499, -3454, -4512, -4929, -4983, -5134, -5117, -4822, -4422, -4179, -4173, -4033, -3934, -4328, -4638, -4639, -4624, -4116, -3579, -3625, -3486, -3124, -3104, -3081, -2707, -2372, -2270, -2305, -2421, -2500, -2467, -2443, -2524, -2592, -2748, -2957, -2945, -2928, -3022, -2769, -2179, -1985, -2074, -2015, -2108, -2269, -2435, -2975, -3437, -3370, -3451, -3847, -3788, -3229, -2887, -2502, -1809, -1472, -1598, -1844, -2003, -2096, -2325, -2457, -2147, -1662, -1104, -490, -290, -422, -428, -156, 281, 312, -134, -247, -136, -492, -1046, -1230, -1064, -853, -660, -296, -132, -396, -484, -132, -39, -435, -429, -224, -633, -932, -671, -389, -235, -103, -7, -28, -127, -324, -819, -1114, -596, 193, 688, 685, 532, 959, 1339, 1025, 930, 1510, 2164, 2376, 2089, 1771, 1778, 1835, 1592, 1330, 1286, 1434, 1735, 1886, 1977, 2033, 1983, 2104, 2166, 1852, 1476, 1346, 1179, 745, 157, -336, -349, 222, 692, 612, 347, -16, -548, -867, -1315, -2029, -2511, -2738, -2880, -2986, -2804, -2421, -2166, -1720, -988, -512, -369, -488, -813, -930, -733, -529, -454, -216, 533, 1363, 1796, 2047, 1955, 1410, 897, 618, -123, -1285, -1935, -2149, -2158, -1880, -1222, -542, -520, -718, -325, 175, 221, 320, 600, 539, 573, 1162, 1682, 1891, 2222, 2375, 2130, 2089, 2053, 1567, 968, 461, -185, -738, -1185, -1923, -2448, -2657, -3210, -3877, -4250, -4499, -4514, -4391, -4203, -3948, -3932, -3785, -3742, -4500, -5087, -4975, -4920, -4534, -3536, -2870, -2621, -2248, -1695, -911, -168, 228, 461, 215, 62, 691, 1055, 825, 702, 727, 712, 600, 252, -412, -1155, -1559, -1522, -1185, -851, -534, -484, -1108, -2029, -2816, -3412, -3710, -3633, -3635, -3709, -3513, -3272, -3043, -2295, -1229, -560, -315, -592, -1164, -1530, -1487, -867, 184, 1214, 1837, 1971, 2162, 2811, 3439, 3460, 2822, 2476, 2477, 2008, 1772, 2135, 2439, 2456, 2188, 1463, 371, -72, 626, 1005, 272, -120, 496, 1015, 1134, 1631, 2554, 3335, 3608, 3307, 2823, 2413, 1794, 1177, 937, 696, 457, 301, -360, -1249, -1738, -2206, -2699, -2484, -1885, -1410, -566, 265, 437, 551, 1097, 1852, 2436, 2918, 3342, 3704, 4242, 4487, 4388, 4539, 5031, 5613, 5780, 5430, 4750, 3867, 3014, 2217, 1346, 432, -264, -864, -1591, -1892, -1306, -716, -926, -1358, -1150, -932, -1442, -1200, 224, 787, 239, 550, 2013, 2888, 2821, 2695, 2570, 2323, 2191, 1857, 1315, 723, -181, -1178, -1975, -2503, -2731, -2788, -2889, -2798, -2500, -2265, -2181, -2647, -3577, -4388, -4803, -4854, -4672, -4399, -3798, -2538, -1271, -871, -610, 210, 964, 1204, 1344, 1701, 1734, 1152, 589, 623, 907, 670, 411, 1381, 2982, 3571, 3157, 2731, 2407, 1795, 1210, 620, -494, -1600, -2380, -3162, -3895, -4649, -5397, -5344, -4482, -3767, -3282, -2796, -2526, -2499, -2528, -2535, -2339, -2183, -2080, -1344, -661, -1186, -2040, -2028, -1992, -2538, -2750, -2667, -2689, -2597, -2745, -3158, -3100, -2505, -1889, -1256, -653, -280, -3, 277, 434, 462, 702, 1330, 1822, 1568, 934, 466, 40, -520, -1071, -1449, -2051, -2843, -3214, -3671, -4561, -4945, -4386, -3649, -3330, -2886, -2034, -1545, -1348, -954, -897, -971, -471, 55, 282, 846, 1486, 1641, 1482, 1302, 1362, 1654, 2189, 2455, 2113, 1955, 2595, 3349, 3130, 2298, 1569, 931, 448, -17, -742, -1238, -1013, -550, -42, 323, 56, -451, -643, -447, 39, 345, 524, 1530, 2753, 2912, 2489, 2385, 2333, 1910, 1260, 669, 516, 931, 1287, 1156, 941, 925, 766, 290, -358, -1225, -2024, -2258, -2092, }; +int16_t hanning[256] ={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 19, 19, 19, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 28, 28, 28, 28, 27, 27, 27, 27, 26, 26, 26, 25, 25, 25, 24, 24, 24, 23, 23, 23, 22, 22, 22, 21, 21, 21, 20, 20, 19, 19, 19, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, 14, 14, 14, 13, 13, 12, 12, 12, 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; +int16_t log_amp[160] ={15022, 14435, 12589, 9857, 9560, 9683, 8512, 7275, 7640, 7282, 5392, 5513, 6802, 6592, 4961, 1288, -4195, 1906, 3608, 4537, 5307, 5826, 5776, 4966, 3716, 2832, 1292, -3881, -1812, -694, -124, 1155, 812, -1853, -2006, 275, 792, 237, -1249, -3606, -2837, -879, -319, -1163, -3881, -10316, -6280, -4832, -4362, -4430, -4281, -3217, -2147, -1981, -3217, -3855, -1383, -275, -841, -3922, -7282, -2152, -953, -1160, -2748, -7849, -6348, -4222, -6316, -6581, -2890, -2405, -3901, -6730, -7618, -6372, -4810, -5029, -9132, -6877, -4224, -3878, -3507, -2846, -2821, -2808, -2277, -2183, -3055, -5251, -9905, -6515, -4287, -3665, -3725, -3616, -3418, -3888, -4698, -4637, -5294, -7811, -6255, -5607, -7866, -11726, -10766, -5334, -2761, -1887, -1955, -2344, -2949, -4560, -7339, -5084, -4006, -4962, -7160, -5624, -4191, -4330, -6684, -7971, -3458, -1895, -1883, -3115, -5062, -5718, -4970, -3927, -3205, -3351, -4273, -3966, -2701, -2234, -2636, -3812, -5894, -8129, -7221, -6359, -5904, -5657, -6363, -8413, -8140, -6600, -6901, -10634, -9912, -6228, -5566, -6416, -8138, -8799, -7865, -7102, }; +//int16_t STFT_rearranged[48000] ={15022, 16390, 15545, 7388, 9791, 14435, 15910, 14934, 8889, 9029, 12589, 14368, 13003, 9548, 6344, 9857, 11479, 9461, 8476, -1914, 9560, 7842, 5972, 6077, 3300, 9683, 6443, 5918, 4306, 3938, 8512, 3724, 5741, 5023, 2931, 7275, 3649, 5604, 5232, 3039, 7640, 5448, 5155, 3191, 4248, 7282, 5707, 3886, -1395, 4874, 5392, 5566, 307, 3140, 5102, 5513, 5713, 2597, 3891, 5867, 6802, 5914, 4893, 3388, 6861, 6592, 6289, 5121, 3314, 7333, 4961, 6907, 3998, 3581, 7119, 1288, 7340, 1455, 3347, 6134, -4195, 7221, -649, 2575, 4133, 1906, 6413, 1158, 1360, 639, 3608, 4810, 1664, -862, -2161, 4537, 2477, 1308, -3721, -2389, 5307, 903, -4, -555, -6878, 5826, 1113, -906, 1167, -1543, 5776, 1199, 1884, 1762, 149, 4966, 11, 3047, 1390, -386, 3716, -5616, 2671, -203, 74, 2832, -1861, 1678, -2604, 1596, 1292, 161, 1333, -2384, 1575, -3881, 818, 667, -1833, -390, -1812, 1707, -740, -1805, -3086, -694, 1426, -453, -1980, -790, -124, -648, 361, -3457, 42, 1155, -1014, 791, -13091, -656, 812, 379, 1297, -3332, -2853, -1853, -235, 1618, -420, -3919, -2006, -4401, 1689, 1044, -2273, 275, -565, 1635, 1800, -2376, 792, 2138, 1102, 1969, -2561, 237, 2818, -543, 1624, -310, -1249, 2136, -4400, 904, 920, -3606, 71, -6615, -81, 501, -2837, -1532, -4246, -1490, -2411, -879, -159, -3977, -4394, -7388, -319, -37, -4141, -10580, -1874, -1163, -1711, -3155, -3770, -1572, -3881, -5011, -826, -3183, -2875, -10316, -4701, 956, -4547, -3369, -6280, -4795, 1932, -4555, -2151, -4832, -7088, 2278, -4062, -1050, -4362, -9139, 2188, -5250, -628, -4430, -6307, 1816, -7122, -665, -4281, -3722, 1238, -4499, -856, -3217, -2790, 465, -2960, -1433, -2147, -3077, -434, -3195, -2783, -1981, -2941, -1212, -5049, -5353, -3217, -1690, -1498, -5065, -11050, -3855, -942, -1402, -2999, -6061, -1383, -1013, -1582, -2083, -3332, -275, -1903, -2508, -2036, -2211, -841, -4324, -4298, -2542, -2304, -3922, -6944, -6426, -3393, -3771, -7282, -2375, -9088, -4619, -7090, -2152, -895, -13285, -6205, -9679, -953, -1090, -7111, -6943, -7333, -1160, -2657, -5178, -6399, -4361, -2748, -5439, -4401, -5331, -2684, -7849, -7725, -4121, -4253, -2323, -6348, -6897, -3765, -3744, -2985, -4222, -5344, -3340, -3952, -4292, -6316, -3943, -3635, -5099, -5501, -6581, -3258, -5395, -8104, -6121, -2890, -3694, -8349, -8938, -7267, -2405, -5253, -6570, -6183, -8317, -3901, -6728, -6160, -6023, -6129, -6730, -5623, -7081, -8065, -5117, -7618, -3654, -5993, -12612, -5517, -6372, -2633, -5248, -9541, -6669, -4810, -2844, -6076, -6778, -7488, -5029, -4130, -6289, -5302, -5846, -9132, -5152, -5290, -5980, -4321, -6877, -5027, -5471, -8488, -3290, 10948, 5340, 9881, -583, -1529, 10281, 3184, 9400, 6255, -1363, 7983, 1790, 7839, 8319, -1213, 2985, 5766, 4578, 8716, -1201, 5806, 5972, -7468, 8093, 239, 7278, 3992, 2631, 6914, 2658, 7007, 3013, 4259, 6183, 4335, 5657, 4920, 4879, 6103, 5026, 5172, 5662, 5285, 5893, 4883, 5509, 5524, 5613, 5378, 4402, 4184, 4538, 5872, 4553, 4309, 3084, 2519, 6053, 4412, 4533, 5541, 2182, 5884, 5410, 4304, 6269, 3345, 4957, 5653, 3045, 5565, 3276, 3046, 4418, 1028, 4272, 2407, 595, 1213, 734, 3636, 1612, -1021, -9, 1479, 3416, 1031, -324, 1364, 1998, 3255, 94, 588, 973, 1467, 3470, -317, 408, -256, -1566, 3966, 176, -148, -1555, -5910, 4403, -381, 149, -3399, -1218, 4406, -3162, 1043, -3706, -2034, 3699, -6969, 1255, 13, -2967, 2095, -928, 675, 2541, -309, -742, 1059, -55, 3772, 276, -5152, 1483, -1167, 3918, -918, -2310, 600, -2456, 3234, -4253, -629, -1699, -803, 2143, -8360, -748, -4480, 187, 920, -4510, -2796, -5722, -657, -732, -2852, -6555, -8562, -5101, -1617, -1578, -3238, -2751, -2692, -76, -473, -1770, -1006, 672, 1164, 146, -1307, -1054, 1972, 1728, -76, -1108, -747, 2401, 1777, -1105, -617, 737, 2292, 1237, -496, 491, 1494, 1811, -216, 1202, 1623, 1157, 1162, -1153, 1656, 2217, -332, 552, 898, 776, 2074, -3098, -150, 2083, -258, 1096, -4664, -1276, 2076, 269, -817, -3732, -2660, 1252, 403, -3595, -2332, -3627, 139, -804, -5568, -652, -4610, -491, -4906, -5112, 12, -5653, -40, -5243, -4091, -766, -6220, 444, -1562, -3606, -3645, -7870, -40, -1055, -4503, -10695, -8347, -1875, -1973, -6634, -7025, -5321, -3534, -3721, -6422, -10405, -3470, -2072, -5833, -8296, -6307, -2409, -1348, -8634, -8763, -3250, -1734, -1712, -13134, -3935, -2113, -1132, -2943, -10088, -2782, -1927, -552, -3587, -7851, -3207, -2420, -210, -2134, -5907, -4824, -3031, -288, -1175, -4432, -6584, -2800, -678, -1292, -3739, -5705, -2132, -1039, -2508, -3901, -3854, -1624, -1437, -5728, -4955, -2528, -1266, -2274, -7524, -5831, -2232, -1272, -3370, -2624, -5012, -3195, -2200, -3783, -947, -4277, -4836, -4802, -3420, -488, -3943, -4317, -5543, -2886, -691, -4040, -4122, -3597, -2892, -1142, -4925, -6452, -3758, -4002, -1519, -5252, -10060, -5054, -4808, -1904, -3326, -4930, -4535, -2874, -2275, -1642, -3491, -3392, -1585, -2128, -765, -3125, -2599, -1366, -1867, -687, -3101, -1848, -2227, -2471, -1521, -3092, -1584, -4873, -5110, -4002, -3221, -2450, -8948, -5746, -11796, -3989, -5450, -4673, -2300, -3014, -6275, -6993, -3629, -1265, -1233, -13060, -3994, -3325, -1129, -1401, -6473, -2795, -2634, -856, -3122, -4984, -1852, -2143, -668, -4531, -4954, -1543, -2277, -1158, -4444, 8135, 6088, 8626, -4024, 9938, 7329, 6317, 8147, 3034, 9253, 4904, 6099, 7090, 5534, 7062, 4788, 5168, 5821, 5756, 2868, 6323, 4576, 3219, 3312, 1833, 6494, 3735, 3133, -3194, 4473, 5760, 1781, 5247, 3503, 5033, 4322, 154, 5491, 4139, 2895, 2112, -1883, 5106, 3344, 1160, 567, -8604, 5398, 2834, 5248, 2441, -1097, 6168, 3530, 5936, 4900, 904, 6690, 4608, 5104, 6129, 2446, 6590, 5040, 5192, 6005, 3385, 5551, 4266, 6075, 4500, 3096, 3111, 1873, 6379, 1400, 1015, -337, -2432, 6535, -3148, -6312, 1153, -3379, 6387, -4178, -2431, 1960, -3097, 5323, -2846, -282, 1735, -1790, 2714, -1477, 1123, 1114, 483, -5178, -288, 2408, 349, 2279, -962, 828, 2867, -310, 3205, 602, 1651, 2089, 248, 3324, 1195, 1919, -836, 1723, 2724, 2721, 1435, -8160, 2498, 1506, 3795, -83, -1480, 2126, 141, 3702, -2304, -1676, 632, -186, 2139, -1688, -2840, -452, 758, 749, -1085, -1050, 84, 1955, 2587, -1448, -667, 47, 2776, 3314, -1334, -1973, -584, 3074, 2871, -1128, -4037, -927, 2914, 2029, -1831, -4223, -893, 2430, 1750, -3735, -1903, -725, 1721, 2124, -4438, 91, -814, 695, 2326, -1846, 1159, -718, -1112, 1779, -605, 1229, 953, -4285, 161, -1077, 226, 2278, -2549, -3196, -1597, -1233, 2448, -61, -10037, 1326, -207, 1631, 1238, -5459, 2800, 1173, 597, 1719, -2662, 2475, 1064, 234, 1395, -1008, 22, -931, 85, 225, -520, -10125, -1692, -101, -2013, -1056, -3239, -169, -365, -5623, -1918, -2721, -886, -713, -4148, -1070, -4144, -4883, -992, -3366, -504, -5371, -7334, -1451, -4299, -1722, -5860, -5572, -2058, -2407, -3307, -5420, -9669, -1902, -626, -800, -3278, -4000, -1470, -465, 514, -2492, -1965, -1758, -2323, 435, -3628, -1768, -2921, -5922, -956, -9229, -2309, -4942, -927, -4084, -4407, -2502, -9038, 836, -8231, -2095, -2284, -5389, 1066, -5365, -1906, -1985, -2756, 264, -3891, -3017, -2226, -2262, -1447, -4557, -4960, -3502, -3466, -3976, -11280, -5981, -3511, -5119, -4299, -3848, -5230, -2657, -3228, -2919, -1482, -4701, -3847, -1903, -2750, -1004, -4962, -9136, -1535, -4156, -1487, -5918, -5496, -1578, -9790, -2332, -7666, -4300, -1746, -6635, -2932, -11718, -5430, -1928, -3956, -3045, -13570, -7603, -2016, -3785, -2822, -9656, -7021, -2159, -4384, -2470, -5004, -4553, -2859, -3625, -2045, -2525, -3046, -5049, -2807, -1748, -1425, -2589, -10651, -3267, -2273, -1223, -2394, -5327, -4768, -4832, -1712, -1883, -4089, -3759, -6611, -2592, -1631, -4451, -2098, -3778, -2317, -1688, -4707, -1511, -4370, -1104, -1674, -5347, -1880, -7616, -511, -1990, -8962, -3392, -5659, -637, -3117, -7329, -6851, -5500, -1134, -4374, -4297, -12628, -9453, -1507, -3914, -3602, -7923, -7498, -4224, -5554, -4353, -4133, -2129, -3878, -7270, -2473, -2452, -1737, -3507, -7586, -2008, -2512, -2831, -2846, -5254, -3025, -3418, -5986, -2821, -3714, -5611, -3744, -7985, -2808, -3010, -13840, -2935, -6763, -2277, -2991, -6283, -2459, -7017, -2183, -3789, -3468, -3366, -5831, -3055, -6182, -2980, -5755, -4109, -5251, -13347, -4226, -3284, -3689, -9905, -6728, -7062, -1040, -4341, -6515, -5290, -10547, -88, -4173, -4287, -5037, -9538, 15, -3219, -3665, -4580, -5533, -670, -3366, -3725, -4293, -3755, -2433, -5426, -3616, -4979, -3342, -5897, -10483, -3418, -6809, -4226, -5644, -6907, -3888, -7436, -6950, -4348, -6768, -4698, -5425, -7290, -5661, -11547, -4637, -4024, -4705, -7820, -7789, -5294, -3717, -3606, -4001, -4241, -7811, -4602, -2791, -2423, -2364, -6255, -6510, -1775, -2276, -1164, -5607, -6340, -1017, -3077, -580, -7866, -4238, -901, -4310, -652, -11726, -3115, -1541, -5083, -1309, -10766, -3063, -2977, -5072, -2160, -5334, -3219, -5153, -4673, -2549, -2761, -2681, -5813, -4537, -2539, -1887, -2418, -4519, -5214, -2776, -1955, -2947, -4445, -6446, -3623, -2344, -4213, -5961, -6591, -5118, -2949, -6336, -7215, -6457, -7136, -4560, -9194, -6317, -7439, -9810, -7339, -9647, -7399, -9089, -8084, -5084, -8196, -10603, -8142, -4773, -4006, -6529, -5264, -6082, -3144, -4962, -5245, -3482, -4467, -2991, -7160, -4667, -3534, -3485, -4536, -5624, -4729, -5032, -3222, -8808, -4191, -5173, -6219, -3555, -16024, -4330, -5943, -5030, -4186, -8660, -6684, -6669, -4314, -4229, -3671, -7971, -6376, -4176, -3187, -1670, -3458, -5898, -4030, -2731, -1236, -1895, -5622, -3478, -3836, -1952, -1883, -5111, -2565, -7553, -3555, -3115, -4399, -1740, -7056, -5274, -5062, -4108, -1482, -5186, -5586, -5718, -5093, -2065, -5623, -4664, -4970, -9301, -3493, -7925, -3350, -3927, -8207, -4928, -13647, -2286, -3205, -5647, -5288, -11389, -1695, -3351, -5048, -5436, -10277, -1476, -4273, -3759, -5299, -11084, -1462, -3966, -2469, -4478, -12156, -1510, -2701, -2149, -3377, -9283, -1412, -2234, -3086, -2832, -6406, -1068, -2636, -6186, -3387, -5200, -747, -3812, -10087, -5553, -4196, -911, -5894, -5260, -12137, -2698, -2137, -8129, -4371, -9214, -1973, -5654, -7221, -4905, -7118, -2635, -11761, -6359, -5793, -7149, -5285, -7383, -5904, -6008, -8398, -8178, -8107, -5657, -6536, -9448, -5544, -5874, -6363, -8914, -8639, -5672, -4566, -8413, -10223, -8665, -9040, -4611, -8140, -6790, -7995, -9845, -5443, -6600, -5701, -5196, -5562, -6064, -6901, -5391, -3432, -4047, -5589, -10634, -4751, -2899, -3579, -5435, -9912, -4255, -3442, -3902, -5816, -6228, -4453, -4620, -5031, -6518, -5566, -5374, -5341, -6901, -8805, -6416, -7360, -5643, -8714, -17696, -8138, -11290, -6006, -9255, -12064, -8799, -7964, -6673, -10575, -9542, -7865, -5755, -8615, -10922, -5114, -7102, -4998, -11781, -6158, -3484, -4628, -2421, -3126, -2497, -6789, -5250, -4794, -4449, -4410, -7477, -9881, -6436, -5064, -3607, -3449, -4608, -4046, -5613, -2139, -2217, -2871, -2510, -6822, -1828, -2235, -3843, -2185, -5537, -2152, -3064, -6329, -3289, -4432, -2550, -4718, -4122, -6236, -4556, -2730, -8599, -3320, -6537, -4686, -2432, -7789, -4202, -4618, -4608, -2175, -3777, -6026, -3566, -6205, -2668, -2263, -7801, -2576, -13093, -4308, -2029, -9251, -1785, -4928, -7375, -3049, -8052, -1709, -2944, -9674, -6259, -5386, -2760, -2434, -9137, -6066, -4239, -5655, -2581, -6472, -3521, -4001, -10908, -3366, -5255, -3280, -3305, -4920, -6014, -6907, -4092, -2406, -3021, -9081, -10022, -4709, -2289, -2635, -3189, -5011, -4448, -3296, -3604, -1475, -4570, -4321, -5646, -6025, -1196, -5631, -5608, -5570, -5345, -1726, -3948, -8925, -3247, -3919, -2528, -2846, -4629, -2085, -3725, -3203, -2884, -1340, -1892, -3501, -3959, -2956, 213, -2570, -3436, -5344, -3247, 385, -3672, -4179, -7922, -4596, -782, -4517, -4623, -10663, -5247, -3613, -5710, -4269, -7357, -3805, -8204, -7537, -4200, -4774, -3261, -3386, -9210, -3521, -3260, -4029, -1266, -10245, -2801, -2777, -6779, -618, -8283, -3242, -3408, -5810, -806, -5770, -5696, -4816, -2843, -1404, -3474, -12002, -4835, -2324, -2230, -1947, -5336, -3635, -4445, -3446, -1253, -3757, -2754, -9328, -5841, -1357, -3536, -2539, -2725, -13317, -2351, -3881, -3123, -1220, -7147, -4485, -4898, -4220, -1221, -5824, -7862, -8392, -5317, -2285, -6768, -11502, -7970, -6846, -4558, -7862, -6879, -3544, -8386, -8920, -5639, -3193, -1802, -5582, -16426, -4403, -1478, -1162, -3322, -11213, -4289, -1030, -1320, -2236, -7203, -4753, -1637, -2259, -2066, -5910, -5082, -3287, -4154, -2592, -7050, -4526, -5607, -7379, -3425, -5504, -4246, -5552, -9774, -4065, -2373, -5163, -4380, -8617, -4242, -1009, -7160, -3989, -7901, -3963, -876, -8081, -4222, -6692, -3726, -1778, -6391, -4630, -5593, -4172, -3764, -4734, -4670, -5500, -5797, -7407, -4288, -4354, -7442, -8769, -8786, -5317, -4301, -11498, -6984, -5990, -8221, -4744, -5009, -4564, -5757, -9903, -4512, -3263, -3106, -7633, -8076, -3552, -3447, -2234, -11771, -6541, -3325, -5117, -1930, -12667, -4415, -4296, -5804, -2117, -11981, -2877, -7575, -5708, -2684, -12463, -2311, -10012, -7172, -3786, -17520, -2856, -5074, -5329, -5509, -11698, -4665, -4276, -3556, -6559, -7320, -4445, -5423, -3139, -6032, -4982, -2432, -6815, -3515, -5233, -3675, -1834, -5983, -4451, -4885, -3100, -2452, -6053, -5609, -4813, -3412, -3794, -7398, -6187, -4484, -5126, -5070, -8555, -5637, -4332, -8942, -6059, -7890, -4903, -4780, -8156, -5664, -6966, -5044, -5826, -7445, -4759, -6094, -6121, -7366, -8944, -5258, -4845, -7107, -8586, -12286, -7313, -4354, -6859, -8099, -16158, -6273, -5653, -6242, -7236, -8803, -5182, -11020, -6046, -6956, -5479, -6656, -1536, -2950, -4414, -6079, -3604, -1428, -2411, -7541, -5139, -1848, -1324, -2361, -9913, -4836, -1486, -1298, -2802, -4591, -3959, -2406, -1573, -3744, -2758, -1712, -4194, -2495, -5418, -2422, -42, -5054, -4591, -9189, -3442, 459, -3980, -9195, -8925, -4492, -230, -2899, -11097, -5822, -3678, -2121, -2792, -12465, -5374, -3936, -5487, -3382, -10965, -6491, -4860, -13201, -3897, -6980, -8176, -4223, -4575, -4537, -5943, -7331, -4482, -2722, -5484, -5427, -5826, -5564, -2821, -5674, -5105, -4386, -3766, -4394, -4608, -5164, -2664, -1603, -5443, -3593, -4710, -1555, -639, -4933, -2796, -3042, -1221, -1098, -6719, -1430, -1246, -1225, -3395, -11421, -447, -162, -1211, -8133, -7246, -627, 167, -1171, -4891, -10083, -2175, -139, -1219, -3020, -7058, -4571, -1084, -1635, -2768, -4466, -3412, -2470, -2518, -4109, -4079, -1188, -3285, -3544, -6015, -4011, 137, -3802, -3376, -4381, -3608, 518, -4965, -1353, -3572, -3037, -126, -7139, 168, -4533, -3447, -1934, -13471, 690, -7204, -6408, -3553, -5680, 417, -9220, -8269, -2607, -3936, -222, -8050, -5319, -2079, -4119, -761, -4771, -4550, -1746, -4482, -1413, -3437, -3790, -1023, -3611, -2864, -3832, -3177, -620, -2645, -4979, -5815, -2643, -652, -2136, -4731, -10493, -2648, -695, -2344, -4163, -10081, -3430, -880, -3418, -4701, -6001, -2792, -1648, -5340, -4910, -4263, -1434, -2959, -6768, -3486, -3360, -1291, -4215, -5259, -2557, -2870, -2715, -5327, -4127, -2717, -2591, -6908, -7188, -3928, -3565, -2566, -9345, -9250, -4424, -3837, -3153, -6026, -6089, -5596, -3329, -4823, -4115, -4029, -5332, -3093, -7403, -2244, -3228, -3730, -3423, -6394, -1321, -3169, -3120, -4030, -4822, -1391, -3856, -3352, -4019, -4452, -2389, -6223, -4162, -3507, -5531, -3885, -11595, -5537, -3763, -9584, -4454, -7117, -6049, -5539, -11492, -4732, -8537, -4404, -6531, -8904, -4400, -6582, -2673, -5208, -8826, -2727, -2659, -1747, -5819, -5655, -2061, -1277, -1705, -9453, -4239, -3059, -1187, -2241, -10353, -4868, -6682, -1802, -3158, -5447, -8286, -8509, -2649, -4713, -3619, -12757, -5460, -3539, -4764, -3014, -12636, -4901, -4068, -3348, -2840, -8742, -5394, -4270, -3392, -2768, -4667, -6856, -5074, -5305, -2984, -3324, -7579, -6296, -6783, -3459, -3532, -4949, -5979, -5328, -4029, -5532, -2721, -5319, -5970, -4667, -14849, -1369, -6133, -10401, -5585, -6837, -790, -12638, -8761, -7334, -5777, -937, -6287, -6741, -9955, -8368, -1808, -3420, -7326, -12278, -8497, -3363, -2912, -8770, -16695, -5559, -4951, -4095, -8610, -13416, -4846, -5025, -7435, -7926, -11937, -3580, -4428, -9001, -6381, -11803, -2464, -4303, -6744, -4580, -13182, -2617, -4979, -6343, -3508, -14602, -4359, -6610, -6657, -3260, -15423, -8127, -8838, -6860, -3720, -14890, -7968, -8299, -6477, -4389, -9173, -6467, -6679, -6249, -4327, -7138, -6132, -6455, -6392, 992, 7886, 7836, 5707, 2952, 5763, 7674, 7512, 5744, 3131, 7257, 7047, 6697, 5594, 2840, 6944, 6137, 5861, 5029, 1656, 6387, 5254, 5171, 4191, 1669, 6716, 4499, 4157, 3252, 2364, 6445, 3756, 2809, 2540, 1949, 4670, 3162, 2233, 3092, 910, 3710, 3344, 2679, 4147, 410, 5517, 4146, 3327, 4671, 452, 6178, 4380, 3727, 4620, 2149, 6053, 3711, 3627, 3805, 4693, 5401, 2486, 3007, 1193, 6237, 3584, 1501, 2138, -2809, 6624, -1377, 1312, 1430, 1631, 5874, -740, 1336, 1335, 2278, 3788, 1232, 544, 1760, 1376, -797, 984, -1787, 1610, 858, -4456, -16, -4421, 402, 1445, -841, -510, -1344, -1367, 1905, -616, -34, -459, -2302, 2253, -1120, 504, -1942, -2912, 2376, -1730, 720, -3838, -5891, 1875, -2627, 388, -695, -5800, 806, -4711, -673, 741, -1852, 50, -11015, -2310, 1308, -789, -233, -8245, -3429, 1893, -426, -743, -6045, -3855, 2501, -212, -1327, -3983, -5484, 2535, -521, -2006, -2393, -6745, 1562, -1584, -3385, -1364, -4140, -858, -3071, -6674, -598, -3454, -2410, -4007, -10510, -171, -4255, -203, -4907, -4974, -243, -6219, 582, -5832, -3180, -1018, -8783, -28, -4707, -1608, -2965, -5414, -2510, -3392, -581, -7330, -3019, -3582, -2700, -677, -6955, -1847, 35, -2277, -1773, -3219, -1611, 1252, -2376, -2733, -1083, -2530, 694, -4002, -2387, -716, -5145, -2053, -9433, -1461, -2429, -5676, -2719, -10283, -1021, -1831, -3878, -761, -5449, -1362, 475, -3664, -1287, -2617, -1862, 915, -3556, -2383, -2085, -1446, 149, -2817, -670, -4159, -375, -472, -2112, 394, -5643, 323, -35, -1757, 248, -2140, 192, 320, -1983, -1029, -1086, -983, -22, -2932, -3865, -1238, -3894, -1474, -4558, -9183, -1959, -7920, -3368, -5977, -7833, -2767, -2841, -1495, -4291, -6174, -3929, -1107, -176, -2147, -2464, -4110, -851, -181, -1039, -299, -2417, -2003, -1071, -1016, 578, -2123, -5311, -1919, -1861, 617, -3951, -4696, -2089, -1896, 235, -9294, -2333, -2652, -733, -288, -6439, -1996, -4479, -339, -1155, -4501, -2973, -7503, -1126, -2682, -2749, -3114, -5895, -3277, -4758, -822, -1788, -4046, -8511, -7487, 437, -1922, -3277, -7813, -5958, 551, -5066, -3319, -4848, -2147, -756, -6046, -3552, -4780, 106, -3455, -2730, -2710, -5057, 1332, -4293, -3013, -1523, -5034, 1646, -4528, -6230, -887, -6935, 891, -6414, -9181, -812, -4640, -1659, -7119, -6210, -1117, -2365, -14029, -5370, -6259, -1621, -1609, -3314, -5115, -7142, -1958, -1108, -2256, -7398, -7089, -1758, -994, -2106, -4836, -5489, -1371, -1982, -2098, -2545, -3927, -1402, -4561, -3066, -2233, -3486, -2416, -7078, -4875, -3155, -4911, -5524, -4643, -4758, -5020, -7861, -12217, -3992, -3582, -9911, -4628, -6038, -4259, -2813, -6597, -3333, -5671, 4431, 6956, 4647, 3404, 3214, 3330, 6394, 4445, 4636, 4919, -2018, 4626, 3869, 5670, 6749, 174, 1203, 3186, 5540, 7498, 1979, -3313, 3158, 4216, 7309, 89, 504, 3878, 1072, 6525, -7332, 2160, 4371, 83, 5384, -1885, 2720, 4121, 2851, 3793, -2387, 2886, 3245, 3140, 2596, -131, 3575, 2615, 2064, 2369, 2750, 4385, 2649, 2541, 1643, 4474, 4335, 2717, 3876, 2216, 5069, 3125, 2641, 4261, 3761, 4424, 1483, 2251, 3750, 4483, 2485, 1454, 1283, 2464, 4432, 1067, 1443, 85, 569, 3826, 2180, 401, 47, -1340, 3066, 2822, -1339, 182, -2231, 2563, 2587, -1558, -920, -2301, 1920, 1218, 336, -3313, -1700, 683, -1842, 1950, -4908, -599, -386, -1289, 2887, -5087, -836, 463, 149, 3227, -887, -4338, 1261, -594, 3167, 1502, -1816, 1038, -2955, 2939, 2548, 680, 327, -2472, 2629, 2745, 1043, 51, -1627, 2053, 2212, 948, -302, -2321, 933, 785, 1074, -1594, -3706, -838, -1956, 601, -3409, -3084, -3032, -6554, -656, -3464, -1611, -4914, -7763, -1656, -4244, -1174, -4880, -6737, -1234, -2011, -1233, -4355, -3618, -340, 526, 47, -5364, -1510, -318, 1544, 1463, -7198, -750, -1860, 1727, 1828, -5679, -1416, -7268, 1307, 931, -6528, -3862, -4626, 11, -1518, -4014, -6626, -1510, -2411, -4306, -437, -6696, -397, -3961, -3760, 1004, -6606, -513, -3297, -2746, 1013, -5990, -1930, -2778, -663, -172, -11236, -2111, -3063, 473, -2169, -4851, -144, -4907, 464, -3009, -1982, 781, -8275, -439, -1982, -1424, 776, -9936, -1390, -912, -1763, 71, -6078, -531, -87, -1362, -1265, -4817, 709, 402, -298, -2933, -7191, 1147, 411, 464, -3762, -5416, 641, -36, 858, -3242, -3244, -878, -725, 974, -2772, -4068, -3062, -1369, 786, -3532, -4200, -3880, -2030, 165, -5898, -1956, -3455, -3426, -1106, -5290, -1439, -3346, -6797, -3430, -3721, -2194, -3895, -5475, -7296, -2447, -2540, -5088, -2472, -7216, -1279, -1260, -6922, -1288, -5455, -683, -66, -6827, -1382, -4648, -376, 376, -4007, -2543, -4856, -190, 93, -2386, -3378, -5880, -477, -515, -2070, -2682, -4918, -1273, -1178, -3491, -2129, -3087, -1615, -2334, -12014, -1948, -2105, -1411, -4243, -2991, -1997, -1792, -1734, -8766, -470, -2496, -1876, -2784, -5016, 104, -3838, -1877, -4591, -1105, -731, -6301, -1746, -9082, 199, -3223, -8534, -2817, -6844, -58, -8548, -7309, -10561, -3983, -1936, -10120, -5995, -3376, -3673, -4603, -20985, -4612, -1454, -2665, -1776, -7189, -3343, -2512, -930, -299, -4932, -3211, -7404, -583, -305, -4692, -4774, -3010, -1973, -1335, -5472, -5595, -369, -4883, -2031, -6404, -3584, 783, -3635, -1048, -6310, -2819, 852, -2206, -154, -5323, -1834, -93, -1718, 30, -4480, -626, -1947, -1728, -541, 4174, 4649, 8112, 4717, 10466, 5280, 6423, 7948, 6862, 10222, 6501, 8002, 7664, 8295, 9563, 6769, 8408, 7456, 8429, 8561, 6127, 7730, 6905, 7644, 7034, 5048, 5903, 5514, 5941, 4594, 4185, 2543, 3305, 2660, 982, 3149, -888, 1426, -2564, -1865, 1011, 1471, 735, 1166, -1159, -5527, 2616, -306, 1632, 314, -106, 3024, -43, -844, 734, 2930, 3341, 2467, -2478, 2614, 3788, 3719, 3345, 2597, 4789, 2812, 3667, 2827, 4269, 5884, -511, 3317, 2219, 4869, 6290, 1704, 3473, 2860, 4963, 6365, 3274, 3591, 3308, 4690, 6044, 2644, 2936, 2953, 4056, 5092, -557, 1584, 1968, 2995, 3317, -4360, 179, 891, 1167, 815, 452, -215, 513, -2135, 86, 1319, 299, 907, -1288, 765, 870, 155, 1373, 1199, 403, 686, -2036, 1276, 2295, -1164, 1208, -6659, 115, 2607, -2310, 701, -1110, -2708, 2307, -1258, -1150, -328, -2530, 1467, -1410, -736, -1907, -296, 883, -2029, -52, -5263, 495, 1564, 553, -1306, -5543, 797, 2156, 1991, -3684, -3848, 1128, 1951, 1912, -3782, -1034, 1249, 1359, 895, -5389, 388, 952, 1349, 218, -6377, 657, 576, 1456, 759, -2880, 335, 729, 494, 1309, -1657, 478, 1458, -2099, 866, -473, 1422, 2292, -1460, -620, -50, 1993, 2768, -94, -1113, -2239, 1399, 2583, -751, -410, -4992, -1336, 1481, -2172, -510, -476, -3462, -839, -1211, -841, -618, -17, -2638, -555, 273, -3499, 496, -876, -1009, 1572, -1315, -297, 196, -2170, 2027, -228, -1264, 454, -3745, 1439, -1464, -2322, 81, -4717, -381, -5409, -4077, -907, -4231, -3575, -11310, -5445, -2337, -2910, -8052, -6921, -5310, -4192, -1845, -13976, -4606, -4917, -4348, -2024, -8954, -3415, -5146, -1546, -3490, -8070, -3267, -5532, -149, -4645, -5821, -3369, -4589, 86, -4673, -3846, -4033, -4557, -413, -2522, -2014, -7275, -7793, -1331, -262, -1161, -6355, -4242, -2505, 707, -1661, -2821, -1515, -4093, 563, -3620, -1675, -1146, -6469, -473, -6858, -1510, -2831, -7219, -1769, -5947, -1635, -7801, -5863, -2385, -4331, -2407, -5390, -5883, -3613, -4909, -5852, -2773, -7221, -9159, -8695, -6468, -1251, -7432, -3003, -8598, -3055, -955, -3342, -265, -7250, -2386, -2007, -710, 612, -7422, -1428, -3766, 347, 364, -4521, -496, -3947, -144, -697, -1507, -547, -3434, -2881, -2096, 292, -1598, -3256, -5414, -2594, 965, -3239, -3247, -2169, -2317, 652, -4359, -2603, -1742, -3337, -557, -4459, -1171, -2509, -10715, -2786, -4692, -227, -3927, -3425, -7108, -6957, -226, -4770, -818, -4731, -6172, -1041, -2897, -248, -2449, -1775, -2384, -1771, -697, -2684, -90, -5076, -1110, -1802, -6855, 99, -9796, -337, -4902, -5453, -1061, -2976, -36, -5415, -2246, -3853, -1317, -549, -918, -1705, -3747, -2112, -4001, -3034, -4635, -4213, -1260, -3727, -2473, -2438, -6982, -367, -3185, -1593, -982, -4534, 264, -2079, -1182, -222, -2747, 483, -2456, -1750, 35, -2512, 388, -5304, -3164, -88, -2206, 140, -4527, -3982, -532, -1428, -144, -2873, -3008, -1346, -1345, -365, -3984, -1784, -2639, -2397, -697, -6265, -1517, -3277, -2307, -1651, -4134, -2354, -1553, -288, -3640, -3791, -3550, 65, 652, -3861, -4141, -3568, 950, 228, -2067, -2900, -2781, 1302, -1954, -1289, -2053, -2108, 1342, -6273, -1345, -1988, -2096, 1204, -4779, -1906, -1653, -3694, 637, -5027, -1988, 82, -10105, -1492, -629, -486, 2110, -1648, -3002, 1882, 1459, 3378, 657, 1358, 2660, 2603, 3623, 1185, 2820, 2130, 2627, 2740, 637, 2565, 365, 1434, 560, -235, 841, -2650, -1067, -3141, -370, -1308, -5821, -3575, -5607, 47, -1692, -6442, -2726, -5532, -168, -2738, -4904, -1480, -7712, -1903, -4340, -3564, -672, -11754, -6389, -3800, -3243, -417, -5924, -5494, -2953, -3758, -816, -4087, -4188, -2255, -4726, -1998, -3790, -4542, -1674, -5694, -3952, -5810, -5381, -1442, -6169, -5589, -7299, -5101, -1910, -5950, -4971, -2468, -4109, -3935, -6223, -3510, -1109, -4084, -12610, -7526, -2798, -1748, -4875, -2691, -6655, -3009, -5180, -3571, -299, -4560, -3222, -5909, -1531, 345, -3402, -2278, -3277, -663, -382, -2929, -1166, -3916, -1028, -2305, -2012, -494, -7351, -2594, -3089, -610, -250, -8475, -5069, -3070, -48, -487, -5563, -7464, -4932, -943, -1479, -3054, -7030, -5903, -3367, -3876, -1946, -5475, -4377, -2021, -7366, -2306, -4082, -4492, -563, -4662, -4219, -2805, -3707, -1053, -3735, -9693, -2621, -1912, -4055, -3845, -8011, -3894, -912, -8948, -3433, -5298, -6418, -661, -3656, -2446, -5489, -10928, -1071, -2590, -1764, -7680, -8049, -2208, -2121, -1662, -6862, -3920, -4199, -1926, -2121, -4885, -2611, -7311, -2486, -3145, -4183, -2502, -6901, -3554, -5151, -3631, -2937, -4649, -4186, -7162, -2699, -4051, -3461, -4742, -5468, -2078, -6172, -2738, -5050, -5448, -2188, -5573, -2471, -5332, -7820, -3023, -4144, -2849, -8141, -9531, -4575, -4189, -3847, -6521, -7025, -4941, -5784, -4681, -3328, -4626, -2908, -10587, -4944, -2513, -3434, -1903, -8857, -6083, -3079, -3631, -2184, -6619, -7385, -4605, -4939, -3503, -7520, -4832, -5781, -5437, -4992, -16740, -3000, -5635, -4065, -5684, -7742, -2005, -6065, -2885, -6214, -5278, -1464, -7700, -2155, -7036, -4340, -1287, -9068, -1918, -8916, -4106, -1409, -10187, -2433, -8882, -4859, -1646, -9359, -4090, -7672, -7479, -1849, -6429, -6578, -10293, -11893, -2146, -5860, -5821, -9577, -9527, -2889, -7698, -5002, -5400, -10978, -4290, -10471, -5225, -4621, -9688, -5863, -8450, -5468, -6029, -7785, -7006, -10558, -5211, -9458, -7926, -8354, -10826, -5036, -5769, -9321, -8951, -3863, -401, -4910, -2323, -2099, -3046, -1484, -5082, -3636, -4300, -1990, -3768, -3293, -6039, -2892, -1020, -3385, -4360, -10286, -1381, -255, -1195, -8361, -4200, -844, 278, 114, -2769, -1775, -811, 435, 634, -894, -1206, -1477, -8, 381, -142, -2189, -3598, -1427, -717, 335, -4704, -8123, -5223, -2835, 417, -4946, -7597, -6079, -6358, -351, -3272, -5801, -2029, -7051, -2202, -2890, -3212, -1142, -3754, -3082, -3662, -1664, -2077, -2099, -2011, -3470, -1050, -5634, -1766, -1891, -1794, -940, -8934, -2247, -2760, -858, -1262, -3438, -2825, -4027, -444, -2366, -964, -2952, -3780, -62, -4754, 1092, -744, -1225, 785, -3777, 2671, 1289, 547, 1815, -1385, 3401, 2002, 1037, 2102, -919, 3093, 1419, 302, 1159, -2604, 1611, -615, -1667, -1151, -6590, -1305, -4651, -4417, -2579, -2497, -5931, -3787, -3795, -2262, -1112, -6328, -1578, -2133, -2192, -1282, -5249, -492, -1608, -1433, -1872, -5463, 56, -2829, -1033, -1877, -6735, 108, -8921, -1287, -2722, -7527, -461, -2687, -1650, -8005, -5833, -1891, -802, -2093, -3565, -4344, -4628, -1311, -2714, -996, -3912, -7108, -4596, -2647, -767, -3612, -5606, -7922, -2412, -2013, -1807, -5153, -3394, -3264, -3955, -187, -5528, -2571, -5326, -4593, 284, -4498, -2853, -4618, -4179, -632, -2208, -3530, -2875, -3441, -3109, -724, -4099, -2419, -2947, -2721, -181, -4229, -3471, -2999, -1022, -361, -3709, -7384, -3834, -599, -967, -3015, -8685, -5134, -711, -1899, -2887, -5903, -3554, -765, -3358, -3166, -5754, -1923, -714, -3785, -2993, -5364, -1627, -914, -2953, -2677, -4464, -2332, -1681, -3383, -2699, -3035, -3388, -3309, -3892, -3248, -1738, -3700, -6108, -2633, -5378, -1179, -2604, -4500, -2448, -6191, -1404, -1393, -2437, -4005, -3079, -2358, -977, -2288, -5299, -2310, -4056, -1572, -3908, -3726, -3124, -5777, -3196, -5321, -2909, -5437, -4515, -4846, -3710, -2791, -11497, -2689, -5536, -3021, -3005, -9364, -1774, -7165, -3170, -3541, -5741, -2088, -5895, -4048, -4716, -2782, -4370, -4907, -6604, -7144, -759, -6454, -7052, -7518, -8122, 162, -3555, -4903, -4158, -5895, 171, -3090, -2152, -3245, -5270, -458, -3873, -1626, -3560, -5052, -1399, -4831, -2721, -3192, -3680, -2242, -6011, -5172, -1962, -2520, -2037, -8181, -5573, -1320, -2241, -1316, -8217, -4278, -1378, -2414, -1338, -6014, -3858, -2009, -2515, -2295, -5196, -4232, -3320, -2881, -3690, -5759, -4847, -5692, -3846, -4289, -8306, -4073, -8223, -5282, -3679, -16164, -3100, -6849, -6858, -3166, -9936, -3173, -6371, -6714, -3424, -8925, -4364, -5933, -6648, -3920, -7339, -6037, -4464, -9019, -3779, -6133, -6647, -3996, -10396, -3640, -6068, -6735, -5136, -8205, -3995, -6796, -7047, -8061, -8816, -4599, -6902, -7482, -10407, -11258, -4973, -5821, -7887, -7805, -11952, -5019, -5191, -8094, -3997, -1225, -1726, 455, -2235, -1923, -1850, -2943, 550, -3777, -1445, -2087, -3342, -100, -5814, -1953, -2336, -3153, -1103, -4142, -2632, -4684, -3320, -1695, -2613, -2901, -8141, -4337, -1264, -1490, -2999, -2810, -6058, -562, -465, -3671, -2464, -7398, -133, 2, -5802, -5233, -7651, 29, -553, -6365, -4151, -6733, -20, -2718, -6204, -1790, -5319, -477, -5304, -14004, -1346, -5160, -1726, -2391, -5560, -1932, -7949, -4745, -808, -3556, -3041, -3434, -9599, -338, -2007, -3100, -831, -3094, -916, -500, -1744, -360, -1619, -2268, -816, -956, -1394, -1788, -2899, -8095, -2464, -3479, -2063, -2920, -96, -6021, -2134, -158, -528, 2698, 497, 628, 1616, 1838, 3059, 2030, 1896, 2141, 2847, 1232, 1605, 1912, 1225, 2745, -8986, -425, 926, -1296, 1901, -483, -2512, -753, -2453, 956, 843, -1462, -2673, -1688, 9, 95, -537, -4408, -2272, -2437, -1608, -347, -5766, -2994, -5430, -3559, -711, -6027, -2730, -1048, -6876, -1160, -5132, -2448, -191, -9054, -1174, -3723, -2641, -1234, -7680, -999, -2339, -3458, -3787, -4533, -1345, -1551, -4958, -4962, -1365, -2678, -1656, -4757, -4839, -255, -4576, -3032, -2895, -6716, -603, -5046, -6251, -2278, -6261, -1986, -4877, -5405, -3344, -5445, -3752, -4363, -3169, -7274, -8626, -5077, -4816, -2093, -8234, -4423, -6048, -8315, -1521, -5655, -2150, -7367, -4908, -1421, -4987, -2215, -8890, -2915, -1900, -3782, -4512, -8844, -3645, -2610, -2110, -11768, -7070, -6387, -2648, -642, -5088, -5925, -2978, -2638, 160, -3597, -6593, -1333, -4099, 112, -3402, -10426, -1467, -8395, -890, -3571, -6303, -2852, -3149, -3120, -4245, -3113, -4508, -964, -7471, -4544, -1674, -5138, -434, -8217, -3670, -1793, -6248, -1070, -7179, -3860, -3207, -11460, -2975, -7530, -5558, -2942, -8060, -6450, -4451, -7461, -2403, -5962, -4914, -1935, -10274, -3799, -6274, -3149, -605, -5873, -6762, -4510, -3147, -166, -3850, -6233, -2935, -4624, -373, -4159, -5653, -2806, -7555, -1092, -5467, -7347, -3662, -11322, -2169, -5232, -6273, -4987, -12250, -1931, -6186, -3310, -6732, -12012, -704, -11559, -2685, -8575, -6899, -460, -3157, -3793, -10286, -3554, -1608, -737, -6339, -9748, -1825, -4462, -94, -7832, -6802, -1348, -6603, -749, -7260, -7043, -2270, -5405, -2259, -6798, -13103, -5551, -4543, -3056, -6387, -5503, -8667, -4196, -3570, -6220, -3738, -5031, -5614, -4747, -6335, -4764, -4838, -14754, -2743, -6782, -10976, -6079, -6492, -839, -8010, -3814, -6350, -4274, -270, -10839, -1667, -4784, -3521, -885, -8579, -1418, -3388, -3149, -2850, -6281, -2455, -2546, -3133, -7300, -6330, -4263, -2585, -3700, -11042, -7839, -5477, -3646, -4679, -6705, -5640, -5430, -5216, -5187, -4908, -3996, -4950, -5622, -5062, -3597, -3962, -5171, -5520, -5080, -3056, -5109, -6746, -6170, -4909, -3343, 12256, 8004, 12464, 10904, 8416, 11661, 8838, 11745, 10292, 7837, 9829, 9223, 9416, 8226, 5859, 6696, 8767, 5290, 3434, 1111, 2977, 8757, 4969, 1397, -464, 2108, 8772, 5794, 2522, 410, 3623, 7901, 5356, 2679, -1019, 5245, 5907, 2704, 4437, 2837, 6340, 1941, -1646, 4585, 4770, 6369, -1679, 2483, 2553, 5902, 5187, 2214, 1437, -1825, 6887, 4304, 3741, 84, 2872, 7698, 4748, 5084, 4322, 4584, 8097, 3880, 6081, 5659, 4890, 7818, 404, 6185, 5249, 4249, 6527, -7291, 5006, 2951, 2881, 3497, -5240, 2206, -4488, 1561, -9294, -62, 927, -185, 1006, 283, 2058, 2088, 1229, 656, 1421, 2252, 1775, 1014, 258, 2453, 1699, 199, 430, -287, 3213, 2191, -2181, -57, -1054, 2911, 3325, -3151, -687, -1903, 1542, 3738, -1571, -2331, -1605, -940, 3089, 510, -6440, -368, -8987, 1177, 1854, -1607, -59, -1887, -1725, 2033, 1828, -1407, 592, -2381, 864, 3501, -5873, 1064, -2537, -1580, 3845, -3362, 542, -1505, -2445, 2886, -229, -405, 220, -2483, 444, 1400, -1286, 1392, -3217, -2656, 2135, -1229, 2661, -1199, -1080, 1981, -101, 3840, 256, 738, 747, 983, 4422, 182, 1386, -1648, 1393, 4214, -1355, 859, -838, 572, 3078, -2979, -575, 1179, -2779, 1287, -2136, -2727, 2186, -603, 978, -480, -6706, 2734, 2007, 1252, 808, -2298, 2885, 2142, 482, 891, -647, 2223, -222, -882, 48, -1264, 701, -928, -1442, -453, -2690, 1267, 2068, -781, -1361, -3028, 2620, 2817, -385, -2744, -5865, 2610, 2421, -936, -733, -3840, 1366, 1544, -2087, 10, -1101, -272, 683, -2789, -693, -877, -801, 163, -3096, -1309, -2391, -582, 299, -3274, -1850, -6029, 58, 616, -2384, -4761, -7028, 879, 179, -883, -6516, -4411, 1277, -1468, 34, -2535, -2780, 952, -4018, -129, -857, -2165, 261, -4386, -1751, 839, -3254, 107, -2568, -3835, 2081, -8946, 80, -1732, -2107, 2452, -4218, -605, -3095, -1867, 1838, -2078, -1614, -6924, -5828, -12, -2580, -2200, -2167, -3131, -2820, -2926, -3767, -1126, 719, -1176, 479, -6279, -2542, 2094, 49, 2495, -2044, -5879, 2347, -592, 3243, -1135, -5126, 1748, -3047, 3057, -3205, -4156, 138, -1356, 2208, -7246, -1605, -2387, 720, 1134, -3015, 104, -1286, 1267, 413, -3284, 616, 176, 843, 110, -6889, 398, 697, -193, -436, -11669, -33, 829, -1605, -2037, -10863, -448, 101, -2500, -5866, -5674, -1045, -2758, -2960, -12132, -2950, -1885, -5134, -5512, -10490, -2075, -2092, -2006, -4752, -10492, -2218, -1038, -1937, -3669, -4559, -1907, 129, -3237, -4189, -2470, -812, 589, -2988, -1045, -2067, -276, -42, -1464, 325, -2838, 109, -2212, -1060, 380, -3663, 1003, -7791, -1896, 621, -2976, 1814, -2913, -403, -258, 8045, 9550, 7186, 501, 120, 7325, 8675, 6888, 1718, -160, 4903, 5702, 5722, 2833, -1728, 3467, 5928, 3912, 3925, -1514, 5284, 7940, 4257, 4699, 1072, 4933, 8041, 4843, 5014, 3906, 1122, 6909, 4358, 5019, 5623, 1005, 5540, 3590, 4792, 6091, 4076, 4906, 3947, 3907, 5549, 3769, 3762, 4786, 890, 4882, 741, 1371, 5631, -291, 4994, 728, 1159, 6304, 4450, 4886, 3321, 2554, 6345, 5797, 3780, 3904, 2829, 5709, 5579, 1185, 3568, 1699, 4629, 4263, -2447, 2989, -2181, 3142, 3186, 129, 2449, -5138, 1168, 3525, 1168, 1787, -1819, 195, 3274, 742, 1218, -663, 1042, 1324, -866, 1954, 1364, 1572, 1662, -4443, 3379, 2084, 1684, 4019, -8671, 4064, 1194, 1955, 4407, -4026, 3688, 230, 2287, 3023, -2688, 2463, 1878, 2236, 1119, -1896, 1342, 2899, 2547, 2351, -1459, 192, 2690, 3911, 2889, -558, -3703, 1611, 4897, 2077, 1155, -4453, 1426, 4812, 253, 2535, -1286, 2192, 3359, -1729, 3156, -1705, 2219, -457, -1692, 2994, -4273, 1368, -6251, -398, 2085, -4517, -325, -1626, 744, 1019, -1348, -3731, -2295, 1545, 1093, 732, -3623, -5882, 1875, 1617, 2194, -270, -4617, 1827, 2031, 3166, 506, -916, 1703, 1981, 3615, -387, 1276, 1579, 173, 3603, -2179, 2473, 1186, -3435, 3314, -2054, 2724, 140, 1652, 3011, 491, 2149, 1076, 2844, 2872, 2244, 1128, 3283, 1936, 2805, 2588, 349, 3957, -821, 2510, 1202, -190, 2950, -1257, 1734, -4619, -1319, 204, -250, 544, -1348, -2007, 294, -875, -352, 1091, -997, 1688, -2024, -425, 1248, -1371, 1668, -855, -262, 382, -5691, 956, 510, -302, -817, -2914, 1049, 907, -595, -1920, 502, 1943, 448, -821, -2724, 1601, 2352, -661, -746, -3330, 1475, 2140, -2026, -671, -4629, 392, 1396, -2031, -648, -7270, -1545, -146, -264, -553, -5524, -5040, -3276, 1055, -589, -3499, -9133, -5950, 1530, -979, -2698, -4207, -2716, 1158, -1913, -2031, -4130, -1612, -210, -3641, -1409, -6419, -2059, -2883, -5326, -565, -1954, -4178, -5976, -4314, 748, 198, -8769, -5558, -2953, 1516, 195, -7740, -4682, -1797, 1192, -2740, -4010, -3483, -331, -413, -5649, -2104, -2098, 1117, -2120, -1314, -1318, -954, 2108, -357, -1250, -1381, -306, 2503, 958, -537, -1893, -644, 2144, 961, 741, -1843, -2192, 590, -137, 519, -1748, -1145, -2490, -1252, -1332, -2488, 606, -797, -2951, -2477, -3125, 1038, 190, -3824, -112, -2300, 779, -1038, 313, 1460, -1318, 19, -3384, 1074, 2146, -964, -1678, -3315, -616, 2249, -1141, -4332, 867, -1709, 1865, -1088, -9021, 3321, 629, 1195, -654, -782, 4100, 1998, 1048, -939, 2199, 3533, 2857, 1285, -2908, 3349, 1691, 3051, 932, 8460, 8764, 11352, 9229, 2753, 7994, 8949, 10816, 8749, 4209, 6432, 8797, 9288, 7514, 4087, 3028, 7763, 7221, 6280, 2883, 4307, 6429, 6286, 6063, 5151, 7170, 5960, 7057, 6742, 5915, 7885, 5807, 7424, 7641, 5033, 6634, 4701, 7023, 8459, 3040, 2317, 292, 6300, 8670, 1377, 4805, 1482, 5279, 7906, 2178, 6627, 4124, 3261, 6187, 1619, 6761, 5003, 2385, 4000, -1840, 6090, 5749, 4444, 149, 435, 4690, 5625, 4623, 68, 1056, 2124, 4213, 2140, 3875, -22, -3026, 2354, -1857, 4641, 1532, -8310, 1683, 2757, 4313, 3311, -7519, 872, 3382, 3707, 4183, -6729, -44, 2501, 2651, 4306, -3805, -1024, 1050, 4, 4095, -3055, -2232, 319, -2462, 4125, -2696, -1606, 834, 1370, 4268, -2410, -1369, 1480, 2791, 4182, -2101, -3471, 1399, 2977, 3828, -1520, -10223, 1, 2121, 3192, -775, -2869, -4311, -529, 2125, -186, -1618, -5470, -6680, 279, -352, -75, -2436, 917, -2823, -2656, 1519, -1145, 3016, -804, -4637, 1827, 182, 3785, 2504, 898, 1495, 964, 3725, 4232, 2812, 2149, 1390, 2948, 4710, 3434, 2418, 1520, 1436, 4089, 3316, 1374, 1283, -1088, 2899, 2824, 1657, 994, -7632, 2226, 2433, 2951, -5, -3054, 1144, 2270, 2699, -55, 100, -2935, 1379, 725, 3089, 1043, -1725, -2073, -2755, 4658, 399, 1008, -1394, -4091, 4839, -2461, 1439, 629, -1411, 3963, -2723, 695, -1442, -2145, 2462, 299, -1740, -1715, -2818, 1113, 1355, -2852, 2143, 2129, 732, 1797, 736, 2904, 3268, 1169, 2289, 1744, 1974, 1867, 1005, 2571, 1211, -754, -5190, -349, 2287, -231, -8360, 810, -1871, 1834, -1632, -3091, 2122, -1322, 2495, -2923, -1269, 1075, -755, 3536, -2198, -695, -2012, -865, 3776, -238, -991, -3860, -1450, 2933, 160, -2163, -644, -2220, 1230, -1354, -3734, 1575, -2364, 379, -5293, -4967, 2724, -1855, 144, -3369, -5844, 2915, -1599, -1240, -2022, -5521, 2148, -1625, -2487, -1109, -3257, 70, -1427, -1644, 471, -1981, -5198, -595, -705, 1684, -2131, -6811, 346, -443, 2197, -3951, -6458, 798, -2139, 1940, -8099, -3504, 634, -5089, 805, -6176, 47, 469, 671, -1372, -7883, 1266, 1254, 2689, -5451, -5118, 975, 2109, 3192, -9195, -643, -664, 2208, 2548, -3472, 822, -3077, 1423, 640, -719, 902, -5188, 621, -3357, 1233, 509, -7465, 1372, -8998, 2263, 412, -1372, 1921, -3528, 2170, 457, 1163, 1371, -1897, 689, 419, 2608, 199, -990, -2223, 406, 3461, -518, -285, -1417, 524, 3722, -721, -471, -59, 846, 3468, -3, -2518, -219, 1216, 2950, 769, -6634, -1664, 1267, 2254, 1212, -4126, -3522, 954, 1146, 1796, -4887, -2688, 562, -252, 2150, -5063, -1078, 15, -607, 1798, -1354, 64, -2422, 1217, -1222, 2356, -549, -826, 1359, 46, 2528, 77, 703, 1093, 540, 2047, 385, 1584, 810, 575, 906, 905, 1793, 607, -30, -280, 928, 1335, 127, -2231, -579, 524, 372, -1104, -3372, -1242, 594, -759, -2885, -1276, -2669, 1271, -2051, -1787, -2151, 731, 1607, -3941, -142, -2902, 2755, 1031, -2410, 257, 526, 3356, 338, 368, -416, 1648, 3127, 1169, 1554, -883, 1187, 2447, 1919, 1349, 35, -355, 1505, 2010, -49, 491, -1493, 290, 1885, -1012, -189, -706, -1402, 1835, -653, -1342, 414, -4049, 1445, -1380, -835, 1399, -2753, -656, -1061, 407, 2389, 328, -5594, 1578, 1699, 3256, 1557, 1803, 3104, 2721, 3595, 1262, 3600, 3538, 2988, 3157, -425, 3530, 3049, 2241, 2007, -2748, 1807, 1702, 292, 913, -2749, -1753, -271, -1737, 416, -410, -2780, -2211, -796, -825, 738, -3053, -3166, 224, -4159, 388, -6781, -1350, 778, -7538, -684, -6021, 40, 794, -8075, -1196, -2613, 194, 186, -5381, -1710, -796, -846, -876, -3076, -2264, 450, -3535, -2173, -2795, -2610, 1111, -3248, -2985, -3229, -2763, 942, -1127, -3091, -2968, -2029, -564, -957, -3445, -2602, -2077, -4367, -1931, -2600, -3586, -4953, -599, -2966, -1270, -6257, -3913, 1906, -3599, -1194, -3077, -125, 2630, -4263, -2647, -1461, 1024, 1879, -4804, -1485, -2161, 636, -401, -5464, 880, -7517, -1091, -1523, -7686, 1802, -3875, -3391, -522, -10960, 1715, -893, -3458, 65, -4600, 963, 83, -1659, 494, -638, -385, 426, -37, 215, 1234, -2347, 531, 777, -961, 1538, -3032, 550, 806, -2996, 382, -1489, 670, 104, -6353, -2430, -72, 764, -1070, -7499, -7218, 711, 512, -2166, -6543, -16015, 894, -116, -4145, -8256, -4972, 799, -1035, -9862, -3472, -1895, 662, -2096, -2376, -442, -683, 312, -2580, -257, 980, -586, -284, -2829, 219, 1468, -997, -665, -3893, -358, 1381, -1313, -924, -5072, -1739, 1043, -1979, -2041, -4316, -4271, 900, -3999, -5376, -3714, -10667, 1246, -9268, -12061, -4294, -2703, 1723, -5847, -6724, -5843, -451, 1670, -3115, -8155, -5466, -5, 553, -2213, -8196, -3675, -928, -2179, -2481, -5031, -2801, -2871, -5236, -2656, -4252, -2905, -3313, -4565, -1879, -5726, -3708, -2167, -4952, -1631, -9692, -4346, -1480, -4648, -2599, -3388, -4863, -1423, -3280, -5618, -1103, -6256, -2118, -2033, -7619, -369, -4822, -3878, -1391, -3919, -476, -2701, -7312, -1380, -2864, -804, -2024, -5814, -1760, -2468, -1219, -2327, -3750, -2191, -2058, -2263, -2831, -3560, -2300, -2160, -4133, -2731, -4973, -1943, -3298, -4746, -2163, -8332, -1633, -5245, -3793, -1897, -9267, -2145, -4547, -3877, -2678, -7678, -4342, -3610, -5656, -5583, -6145, -6009, -4297, -9752, -11844, -3874, -3231, -9564, 3317, -1712, 2495, -249, -4231, 2333, -4860, 1441, -2319, 472, 214, -2134, 332, -6326, 2920, -5387, -2290, -772, -1964, 3892, -958, -9231, -1652, 802, 3680, 1596, -2025, -1339, 1828, 2542, 1900, 188, -1396, 1656, 1022, 311, 218, -2450, 361, -494, -5238, -143, -2696, -2148, -2685, -3968, 428, -2002, -5779, -3974, -1723, 596, -1375, -7355, -2275, -1966, -382, -1209, -4313, -1981, -1460, -2295, -2147, -1661, -4310, -181, -3322, -3900, 111, -7570, -182, -3673, -3565, 1099, -2872, -1643, -4352, -1997, 1367, -1554, -2401, -4965, -514, 875, -433, -1869, -6022, 566, -330, 1229, -3502, -2602, 1703, -1157, 2667, -3167, -378, 2998, -711, 3240, 137, 101, 3765, -609, 2728, 1359, -902, 3624, -1976, 1083, 1316, -2345, 2389, -8600, -1322, 389, -1026, -309, -758, -3238, -266, 437, -6312, 2126, -4703, 816, 1101, -3475, 3235, -5948, 1770, 967, -999, 3122, -5564, 1828, -395, -227, 1573, -3359, 1194, -5735, 255, -3600, -2273, 303, -2483, 1032, -1824, -2752, -632, 326, 1326, 840, -5005, -1329, 466, 820, 941, -4284, -1794, -1498, -222, -125, -1421, -2664, -5865, -1489, -924, 146, -2813, -1618, -2149, -70, 669, -2351, 367, -1519, 961, -46, -1477, 1177, -1038, 1226, -1699, 628, 1361, -486, 532, -76, 2150, 963, 527, -1000, 1627, 2592, 101, 1346, -1927, 2020, 1908, -700, 1647, -1514, 1653, -332, -1236, 1406, -1411, 1325, -10068, -989, 667, -924, 1690, -1303, 515, -409, -10, 2410, 1293, 1728, -1478, -109, 2706, 2163, 2160, -2210, -2149, 2184, 1921, 1908, -2428, -9430, 658, 573, 1130, -1598, -8966, -2020, -2038, -112, -240, -6766, -3364, -3674, -1602, 690, -1499, -2217, -1771, -1832, 920, 140, -2417, -677, -1264, 421, -87, -4587, -576, -1291, -567, -1831, -8048, -1305, -1898, -875, -4965, -3671, -2780, -2956, 215, -9928, -2334, -4840, -3151, 960, -8429, -2557, -4926, -2364, 391, -4029, -3040, -2353, -2119, -1905, -2826, -2297, -703, -1551, -2284, -3370, -806, -431, -283, -701, -2411, 257, -1976, 712, -781, -110, 523, -5822, 1049, -1996, 1024, 18, -2396, 621, -3525, 1091, -1011, -1452, -564, -4353, 241, -1537, -3027, -1276, -3894, -1498, -1273, -1980, -230, -3036, -4200, -1669, 593, 335, -2142, -8792, -3426, 1475, -195, -1508, -9505, -5679, 1171, -1675, -1465, -6397, -4053, 5, -4040, -2016, -6187, -2771, -1603, -8102, -3353, -6786, -2667, -2941, -7881, -5242, -6067, -3708, -3427, -6175, -3917, -4149, -5051, -3540, -5787, -2668, -2366, -3368, -4009, -4915, -2502, -1633, -1766, -4810, -3513, -2509, -2258, -1212, -5520, -2392, -2325, -4518, -1430, -6411, -2023, -2446, -5615, -2144, -7517, -2545, -2686, -4291, -2848, -6527, -3844, -1880, -4841, -1145, -145, 628, 475, 457, -2957, -10, -1570, 1391, -133, -4206, 52, -6385, 1664, -1805, -3079, 145, -4327, 1253, -3114, -1486, -819, -975, 374, -2454, -1235, -5610, 467, -293, -1797, -3162, -3606, 815, -758, -304, -3796, -1578, 354, -1073, 797, -583, -2625, -499, -771, 551, 92, -2287, -1511, -778, -390, -1734, -786, -2860, -1886, 191, -5805, -598, -3619, -3831, 690, -130, -1444, -1214, -2643, 209, 1606, -3083, 1408, -614, -1114, 2381, -4094, 2906, 633, -6743, 2871, -2164, 3295, 1471, -1532, 2341, -551, 2600, 1803, 1710, -254, -1350, 670, 852, 2520, 1150, -2959, -1344, -3412, 1716, 3180, 1734, 1280, -675, -265, 2878, 3379, 3075, 1577, 593, 564, 3251, 3563, 1385, 2170, 651, 1874, 3033, -583, 2850, 2123, 884, 1686, -4414, 3101, 1837, 1719, -398, -9515, 2822, 99, 2401, -3167, -4597, 1589, -2826, 2676, -4771, -1401, -138, -5814, 2910, -6350, -610, -104, -6063, 3013, -8985, -1488, -619, -3875, 2957, -8283, -2294, -2217, -1501, 3230, -2237, -1782, -1127, 361, 3596, 688, -1570, -753, 1476, 3297, 1530, -1263, -1992, 1754, 1762, 584, -332, -3281, 1156, -2419, -2802, 614, -2246, -349, -3108, -5652, 727, -1032, -2545, -441, -2741, -363, -1151, -3433, -692, -2244, -2517, -3094, -2801, -2605, -2152, -2148, -5145, -2558, -3874, -1905, -258, -4390, -2293, -3149, -1464, 888, -6111, -1497, -3126, -774, 1634, -5495, -650, -2098, -295, 1935, -2774, -379, 67, -790, 1403, -1358, -1010, 1457, -3443, -11, -51, -2306, 1889, -3109, -284, 1057, -4607, 1583, 263, 789, 1584, -6906, 976, 1375, 1056, 1371, -1678, 582, 1247, 544, 460, -635, 136, 304, -188, -774, -1331, -1029, -952, -1160, -2151, -918, -1051, -1310, -2378, -3368, 140, 174, -419, -310, -2190, 673, -106, 227, 1558, -1586, 1039, -2416, -134, 2027, -2991, 893, -6580, -1703, 1269, -6484, -115, -5723, -4105, -856, -2971, -2238, -3554, -6704, -5229, -939, -6743, -2910, -7597, -3618, -429, -10337, -4056, -6796, -1566, -1561, -6673, -4428, -12669, -1216, -7896, -6061, -3668, -2993, -1485, -2882, -5866, -4362, -584, -1137, -280, -6184, -5742, -232, -590, 311, -7151, -6190, -1667, -693, 372, -10047, -5120, -7048, -1029, 73, -10798, -3369, -4997, -1002, -1285, -5770, -2927, -2547, -1148, -2374, -4233, -4789, -2791, -1988, -447, -4173, -8613, -4557, -3999, 457, -4995, -3105, -6255, -7731, -100, -6188, -1730, -7142, -5266, -2370, -6593, -2111, -11767, -3767, -5091, -5145, -3803, -7493, -3824, -2533, -4008, -6733, -4307, -4295, -1719, -4287, -10252, -3294, -4072, -2339, -5571, -8014, -3507, -3417, -3899, -3474, -6660, -4456, -2442, -6205, -1628, -7007, -4803, -1214, -10809, -1319, -8609, -4288, -465, -10738, 11098, 5212, 12300, 10731, -13274, 10442, 6685, 11667, 10185, -5310, 8302, 7186, 9625, 8459, -3020, 3785, 5776, 5462, 5253, -2244, 1023, 3996, -1424, 287, -1736, 2976, 4149, 407, -1784, -605, 3079, 3114, -722, 661, 89, 2958, 784, -5, 1303, 325, 3135, 1756, -86, -672, 1340, 3989, 2726, 137, -26, 2416, 4821, 2709, 1082, 3029, 3017, 4752, 3030, 538, 4385, 3491, 3277, 4047, -3489, 4673, 3810, -348, 4441, -1135, 3980, 3758, 216, 3628, 293, 2357, 3336, 1802, 1749, -2091, 829, 2509, 1505, 768, -891, 395, 811, 631, 636, 1899, 109, -4455, 226, -296, 2648, 168, -1596, -540, -1523, 2391, 272, 1368, -1774, -3220, 1437, 265, 1752, -1880, -5949, -332, 528, 741, -1641, -3799, -3154, 1030, -656, -1690, -2449, -3611, 1340, -1832, -1245, -2534, -2997, 1490, -4817, -374, -2040, -4587, 1682, -2789, -169, -908, -9040, 1674, -187, -1274, -1075, -8328, 1255, 257, -3880, -3698, -4611, 584, -873, -5979, -5615, -2235, 163, -3707, -9433, -1926, -1347, 160, -9210, -7969, -1200, -1870, 103, -12453, -4893, -2052, -4712, -220, -7170, -5432, -4455, -7397, -715, -3549, -7741, -7953, -2554, -1232, -1773, -5242, -5832, -1528, -1503, -1547, -2831, -3492, -2060, -1501, -3042, -1437, -1902, -3381, -1917, -4839, -896, -1487, -4409, -3751, -2231, -1335, -2925, -5361, -9173, -752, -2493, -11578, -7925, -5094, -347, -2519, -3585, -18176, -3398, -604, -1625, -1877, -10374, -3873, -1355, -1285, -2854, -12016, -6563, -2503, -1518, -6327, -12043, -7376, -3559, -2105, -3820, -7938, -4767, -3599, -2760, -2402, -6678, -4353, -3201, -3089, -2845, -6013, -5385, -3098, -2942, -4488, -4418, -8138, -3288, -2847, -6622, -2408, -14394, -3652, -3416, -8079, -1161, -5638, -4190, -4624, -8116, -831, -2668, -4954, -5222, -6976, -1189, -1206, -5770, -5339, -5479, -1860, -828, -5995, -6444, -4132, -2620, -1298, -5463, -7908, -3071, -3510, -2244, -4449, -6470, -2511, -4811, -3266, -3517, -4756, -2817, -6980, -3990, -3400, -4214, -4423, -6924, -3501, -4595, -5061, -7353, -5594, -2586, -6687, -5601, -7305, -5826, -2433, -5014, -4189, -6156, -7004, -3291, -3297, -3931, -4989, -7679, -4740, -2520, -5206, -4326, -7732, -5585, -2025, -5975, -4052, -6323, -7057, -1360, -4578, -2613, -4732, -12016, -683, -3435, -1212, -4410, -7504, -294, -2585, -828, -5621, -6556, -375, -2187, -1415, -5592, -8070, -1032, -2424, -2718, -3489, -9643, -1973, -3028, -4759, -3094, -7536, -2619, -3475, -9114, -5000, -4308, -3469, -3501, -6100, -6687, -2197, -4270, -3029, -3362, -3660, -1111, -3131, -3031, -2650, -3297, -786, -2407, -4677, -3325, -5145, -1064, -3122, -10750, -5078, -6277, -1863, -5590, -9095, -6716, -4257, -3437, -10057, -8470, -7109, -3506, -7310, -10609, -11511, -6290, -2969, -8178, -5305, 1585, 3305, 8481, 3947, -7373, 857, 2438, 7871, 4483, -5163, -1996, -93, 5893, 4989, -1325, -1659, 841, 2403, 4908, 1273, 2099, 2461, 2031, 4779, 2616, 3751, 2638, 2640, 5051, 3061, 4361, 2355, 1685, 5346, 2837, 4441, 2016, 406, 5189, 2082, 4328, 247, 1849, 4410, 1080, 4039, -3195, 3468, 3163, -336, 4027, 2040, 4662, 1497, -3365, 4988, 3859, 5658, -982, 38, 5693, 4172, 5994, -1242, 3006, 5278, 3567, 5174, -822, 4260, 3458, 2747, 2548, -2184, 4354, 706, 2516, 58, -2813, 3520, 445, 2291, 2562, -2896, 2005, 192, 1550, 2941, -4081, 194, -869, 734, 1859, -4434, -1360, -785, 930, 155, -3206, -2027, 300, 1899, -530, -2885, -1699, 1254, 2444, 93, -5182, -1408, 1767, 2207, 423, -10119, -1961, 1778, 1408, -459, -6219, -2644, 1226, 771, -1880, -1894, -2940, 111, 722, -634, 805, -3221, -589, 873, 577, 1830, -1550, 239, 766, 783, 1632, -334, 995, 95, 209, 354, -388, 892, -717, -877, -2339, -1423, -500, -449, -1883, -4972, -3426, -5195, -1, -1938, -2367, -8461, -3421, -187, -1485, -1279, -4852, -866, -240, -1510, -1196, -1826, -1293, 206, -2200, -1447, -684, -4666, -29, -3118, -1524, -475, -6737, -1703, -3556, -973, -677, -4775, -4770, -3481, -59, -841, -4117, -4457, -3387, 502, -1063, -2478, -3343, -3405, 513, -1847, -1872, -2763, -3513, 216, -3158, -1954, -3293, -3491, 6, -1841, -2078, -6307, -3108, -39, -34, -2676, -4200, -3202, -70, 295, -4143, -1613, -4699, 133, -1057, -5056, -933, -8726, 735, -5222, -4775, -1032, -7064, 1143, -6540, -5723, -1051, -4089, 856, -4798, -7549, -1215, -2400, -195, -7213, -5635, -2425, -1542, -1435, -6176, -4819, -4529, -1232, -2289, -3326, -6213, -3064, -863, -4036, -3085, -8323, -2295, -451, -4993, -4715, -5061, -4020, -749, -2752, -3877, -3576, -6565, -1875, -2479, -2051, -3764, -3560, -2217, -3992, -1880, -5381, -3341, -1708, -5812, -3022, -4445, -4321, -1992, -6653, -5129, -2650, -3498, -3241, -5129, -7028, -2528, -2897, -4728, -3051, -5802, -4167, -3519, -5969, -2871, -4319, -7325, -4670, -9996, -4331, -3595, -4791, -4604, -7482, -4786, -3318, -3351, -3509, -5488, -4479, -3763, -3662, -3008, -6282, -6129, -6270, -5514, -3122, -7904, -5156, -9061, -7791, -2629, -5439, -3320, -3932, -5454, -1852, -3039, -2650, -2778, -3742, -1820, -1611, -1754, -3548, -3505, -2607, -1143, -1164, -7063, -4740, -3944, -1745, -1874, -6602, -7379, -5275, -3118, -4641, -2947, -5731, -4220, -3162, -4582, -1783, -3739, -2276, -2644, -2088, -1782, -3252, -1601, -3260, -1424, -2322, -3649, -2494, -4660, -1975, -3063, -4196, -5663, -5993, -3845, -3228, -4619, -8550, -9567, -6095, -2124, -4831, -5158, -8780, -3685, -1638, -4736, -3700, -5019, -2600, -2706, 3707, 2638, 6935, 2367, -409, 2736, 2365, 6486, 3751, 2168, 1377, 1343, 5470, 4876, 3115, 3163, -681, 4488, 4624, 1773, 4089, -697, 2993, 2655, -2576, 3762, 1709, 329, -2962, -906, 2292, 2976, 233, -1112, 746, -870, 3029, 587, -145, 458, -5764, 1947, 2, -1787, -2017, -2262, -4, 430, -2562, -3108, -14, -1930, 1231, -1716, 1821, 1788, -2410, 1649, -1517, 3826, 2804, -1236, 1710, -143, 4544, 3057, -441, 1395, 1775, 4359, 2635, 418, 578, 2847, 3582, 1434, 1425, -1172, 2693, 2857, -1028, 1644, -3601, 1070, 2653, -6563, 865, -687, -76, 2631, -10669, -513, 830, 1328, 2475, -6428, -1739, 525, 1282, 2073, -2958, -2828, -1301, -1020, 1441, -2750, -4133, -3430, -16441, 646, -4168, -2603, -3920, -2047, 242, -486, -225, -4235, -270, 624, 1024, 1000, -3784, 359, 546, 493, 1237, -3623, 640, -679, -2010, 381, -3130, 969, -2732, -3305, -2278, -1646, 1447, -3567, -2123, -7752, -834, 1559, -1510, -2701, -3584, -997, 908, 148, -4190, -2956, -1853, -521, 587, -4177, -3973, -2802, -2053, 103, -3373, -5826, -3259, -2014, -1133, -3022, -7751, -3502, -801, -3851, -2864, -7128, -4058, 12, -6858, -2197, -5368, -4733, -156, -2515, -1500, -4914, -3531, -1289, -1601, -2129, -5401, -1761, -934, -3359, -5833, -5855, -929, 961, -7624, -2855, -4490, -885, 1960, -1611, -733, -2348, -960, 2037, 345, -1164, -1348, -729, 1452, 1044, -3845, -1594, -613, 382, 974, -4552, -3003, -778, -1558, 95, -3389, -5396, -859, -5068, -1692, -3932, -3957, -712, -2859, -2906, -4352, -1844, -920, -1314, -2445, -3971, -1383, -2114, -710, -2151, -3884, -2316, -5126, 123, -1625, -4171, -3896, -7733, 660, -1102, -4685, -3933, -2734, 588, -702, -5475, -3649, -655, 67, -528, -6936, -4077, -101, -1149, -1218, -10007, -4253, -984, -4323, -3259, -7527, -2958, -3909, -5933, -3525, -3866, -1383, -6203, -2006, -1102, -2139, -615, -2993, -907, 107, -2018, -870, -1857, -1267, 143, -3948, -1987, -1685, -2792, -1038, -8334, -3092, -2154, -4408, -3392, -4299, -3602, -3363, -4114, -3630, -3513, -4155, -6059, -3263, -2461, -5321, -4200, -9254, -2273, -2403, -14087, -3900, -5744, -1227, -3193, -4042, -4117, -5267, -476, -3996, -1661, -4803, -7994, -240, -3732, -892, -5842, -10145, -634, -3205, -1265, -7545, -5716, -1846, -2950, -2523, -9839, -4877, -4653, -3034, -3705, -7522, -4084, -5418, -3877, -4613, -4659, -3178, -2218, -5807, -7387, -3785, -3515, -1403, -8260, -11497, -4984, -6182, -2172, -9360, -6346, -6504, -6892, -4239, -7743, -4428, -4122, -4123, -6879, -7008, -3190, -3511, -4579, -10967, -6432, -2575, -3400, -5683, -7842, -4646, -2471, -1945, -3157, -3757, -4293, -2553, -1025, -2473, -2903, -5273, -2585, -1288, -3610, -4283, -4097, -9523, -5943, -2164, -5581, -2444, -7776, -7923, -2002, -6584, -1324, -6893, -10160, -3126, -8249, -1242, -5853, -5730, -6185, -7069, -1318, -4999, -4494, -11606, -4761, -1033, -4625, -4512, -9209, -2764, -895, -4675, -5093, -5432, -2392, -906, -5316, -6753, -2629, -4217, -506, -7343, -12258, -1117, -18640, -111, -9723, -7977, -691, -4660, -501, -6642, -6882, -1346, -3457, -2156, -5205, -9530, -3231, -4659, -6435, -3930, -12152, -6519, -8626, -5634, -3154, -7490, -9589, -6737, -2102, -3723, -7020, -9157, -4072, -731, -5013, -8657, -9415, -2941, -398, -4607, -10880, -9679, -2876, -754, -5311, -14843, -9054, -4567, -1638, -14356, -6364, -8733, -13294, -3056, -4994, -2996, -4463, -5328, -4725, -2286, -1904, -2246, -4056, -4127, -1121, -2429, -1557, -5177, -2582, -734, -4504, -1938, -7300, -2004, -1035, -7966, -3344, -7584, -2366, -1927, -7388, -7014, -5819, -3508, -3280, -5943, -7778, -3259, -5056, -4883, -5403, -3711, -1761, -6577, -5724, -3812, -2815, -1334, -10214, -6432, -2134, -3513, -1800, -7198, -8335, -1299, -5112, -3064, -4323, -6722, -1216, -6206, -5131, -3659, -5068, -1666, -8050, -8021, -4004, -4996, -2605, -8072, -11208, -4015, -6186, -4652, -4438, -10588, -3273, -8792, -9297, -3155, -7707, -2889, -9015, -5467, -3343, -5270, -3625, -6067, -3545, -4613, -3311, -6748, -5065, -2944, -6260, -2057, -9865, -6187, -2925, -7114, -1475, -5008, -6917, -3686, -7323, -1268, -4218, -3167, -5852, -7615, -1271, -4439, -1312, -6944, -8678, -1771, -3908, -680, -4782, -8846, -3161, -3446, -825, -4036, -8856, -5418, -4445, -1466, -4437, -10779, -6813, -5622, -2382, -5802, -4930, -7126, -3128, -3724, -7505, -1874, -8631, -1671, -6449, -8103, -453, -13228, -1267, -9744, -7564, -269, -10195, -1356, -6865, -6983, -1270, -7884, -1598, -7550, -8264, -3377, -6582, -1809, -13209, -10664, -5900, -4933, -2029, -6603, -7333, -6637, -3141, -2649, -4805, -5579, -4607, -2065, -3786, -4159, -4530, -3556, -1958, -4434, -4021, -3946, -3579, -2653, -4115, -5443, -4218, -3204, -3892, -4038, -9143, -6128, -2134, -4915, -5295, -4613, -13797, -1494, -3796, -8152, -2934, -8834, -1618, -2501, -3860, -2776, -7296, -2660, -1837, -2081, -3349, -6771, -4973, -1725, -2184, -4176, -7035, -10012, -2470, -3850, -4867, -10270, -8530, -4484, -7644, -4945, -11567, -5452, -7947, -13246, -4593, -7648, -4465, -13331, -8972, -4690, -7031, -4486, -11865, -9795, -5755, -7391, -4672, -9503, -9418, -6950, -7780, -4682, -16058, -7030, -6089, -6621, -4720, -7791, -5977, -5453, -5265, -4802, -5117, -5921, -6064, -4721, -5110, -5085, -8222, -8408, -4431, -5728, -7469, -7815, -12098, -3763, -6161, -10741, -3895, -8584, -3051, -5790, -8524, -2729, -7566, -2674, -5077, -9058, -3014, -8564, -2654, -4944, -7027, -4310, -8408, -2854, -6054, -5405, -6337, -6067, -3169, -7725, -5604, -8646, -5427, -3730, -6045, -7173, -9349, -5644, -2745, -4435, -3255, -5100, -10319, -2409, -5707, -5709, -3217, -4289, -2904, -8567, -10219, -1759, -1428, -4532, -10403, -10345, -2067, -360, -8814, -11601, -8343, -3550, -360, -6021, -10113, -5433, -2952, -1047, -2621, -6476, -3020, -2146, -2014, -1286, -3590, -1799, -3138, -3347, -1293, -2157, -2028, -4382, -6207, -2485, -2222, -3986, -3157, -6363, -4376, -3953, -6302, -2993, -3178, -4933, -8381, -5066, -4482, -2127, -4846, -12400, -4240, -7919, -2555, -6214, -8454, -3503, -7013, -4322, -5684, -6272, -2668, -4389, -4535, -3199, -3959, -1933, -3414, -2477, -2617, -2243, -1718, -3123, -1327, -3827, -1305, -2294, -2093, -1066, -7001, -1076, -3850, -801, -1632, -8388, -1685, -6329, -498, -2998, -7507, -3648, -5368, -1515, -4982, -7466, -7383, -3325, -2655, -7653, -7390, -5273, -2413, -1555, -14324, -6261, -3707, -2532, -1035, -9651, -4787, -3281, -3732, -1629, -5854, -4420, -3728, -5714, -2317, -4014, -5483, -5742, -5663, -2378, -3529, -7319, -8604, -4638, -3085, -4334, -6198, -5104, -4462, -5674, -6502, -5078, -3689, -4555, -14132, -11050, -5171, -3450, -4259, -13545, -9341, -5933, -3294, -3862, -8457, -5184, -6151, -2572, -4167, -4497, -3611, -5143, -1653, -5473, -3356, -3468, -3974, -1278, -6098, -3895, -4212, -3747, -2331, -4030, -5500, -5145, -5045, -7589, -2336, -6391, -5749, -7203, -4400, -1870, -5463, -6348, -6143, -2208, -2193, -4082, -7322, -4906, -2997, -1735, -2751, -4971, -3830, -7372, -806, -1731, -2704, -3698, -7334, -695, -1307, -1781, -5715, -4778, -1785, -1633, -1760, -9078, -4864, -4826, -2603, -2323, -4936, -5444, -10881, -3398, -3460, -4051, -6080, -4726, -3330, -5913, -4514, -9708, -2940, -3278, -9419, -5049, -7931, -2193, -3486, -4353, -4575, -4653, -2333, -3719, -1933, -3317, -4288, -3790, -4057, -585, -2619, -6018, -6452, -4951, -5, -3009, -13340, -4646, -7322, -224, -4531, -8298, -3373, -11910, -1415, -6536, -5687, -3711, -8413, -4246, -7867, -4259, -5131, -4938, -8504, -10451, -3386, -6804, -2993, -4161, -10671, -3469, -9349, -2556, -2815, -8378, -5085, -9094, -3620, -2359, -9030, -9748, -5670, -6663, -1707, -10671, -5964, -4925, -6982, -1238, -6904, -4084, -6098, -4870, -1593, -4780, -4367, -8449, -4262, -3044, -3837, -7028, -7802, -3321, -5930, -3460, -13684, -7987, -2254, -10288, -3088, -6700, -13398, -1980, -7907, -2537, -5443, -5852, -2529, -5309, -2281, -5477, -3144, -3454, -3354, -2779, -6270, -2284, -3982, -2010, -4131, -8456, -2577, -3993, -1443, -5248, -14405, -3869, -3884, -1780, -5301, -7072, -6484, -3667, -3182, -6687, -4773, -11855, -3411, -6299, -13380, -4030, -9727, -3625, -13249, -6993, -4150, -8273, -5127, -5833, -5646, -4561, -7768, -9798, -3523, -7344, -4823, -7563, -9133, -2409, -13634, -5072, -8797, -8460, -2152, -6157, -5646, -14285, -14051, -2812, -4474, -6838, -10685, -8765, -4529, -4371, -9026, -8921, -7190, -2538, -2793, -5336, -3947, -3232, -2447, -6203, -5527, -1346, -4646, -2657, -11648, -5577, -289, -7774, -3120, -5916, -4942, -409, -4535, -2327, -3789, -3437, -1664, -3652, -1306, -2676, -2158, -4312, -5043, -1433, -2688, -1550, -4704, -12021, -2924, -4046, -1718, -2938, -6369, -5811, -5486, -2140, -2456, -4418, -9238, -4771, -1672, -2623, -5173, -7536, -5012, -1027, -2916, -7563, -5388, -6455, -1047, -3534, -5747, -3857, -6470, -1762, -6188, -4386, -2362, -5764, -3270, -7302, -3486, -1317, -5339, -5938, -2043, -2596, -977, -5002, -5752, -567, -2031, -1364, -5686, -4356, -871, -1595, -2485, -9444, -4559, -3048, -1263, -4310, -9670, -4284, -9537, -1203, -5912, -6224, -3258, -4981, -1598, -5220, -6752, -3456, -3016, -2725, -4270, -13093, -3992, -2290, -3813, -4408, -7856, -1929, -1810, -2808, -6610, -6766, -300, -1490, -1837, -12281, -9620, 182, -1437, -1396, -4540, -5758, -268, -1434, -1067, -2260, -3563, -1245, -1335, -1237, -1190, -3551, -1476, -1500, -2333, -991, -4916, -812, -2049, -2009, -1888, -4600, -483, -2455, -390, -4537, -3079, -788, -2471, -38, -8360, -2618, -1859, -2379, -449, -5758, -2959, -4411, -2219, -90, -6016, -3160, -7765, -2225, 307, -9508, -2980, -4024, -2636, -255, -5505, -3532, -2875, -3524, -1276, -2591, -5988, -3067, -5231, -1555, -1350, -8221, -4186, -8034, -1763, -1154, -3675, -7696, -8156, -2892, -1762, -1783, -8195, -7268, -4659, -2969, -1119, -3649, -6626, -3255, -4262, -1365, -2163, -6289, -1846, -4546, -1670, -1498, -6156, -1979, -4453, -425, -943, -4181, -3783, -5071, 723, -488, -2102, -7526, -5890, 759, -454, -991, -7736, -5490, -412, -1108, -886, -9249, -5507, -2500, -2611, -1753, -11330, -8110, -3541, -4951, -3085, -6498, -11560, -2818, -6163, -3838, -5476, -7744, -1613, -4473, -4503, -4895, -10538, -787, -3815, -4152, -4471, -9289, -772, -5325, -2438, -4617, -7042, -1681, -12156, -1011, -4078, -11124, -3652, -4463, -221, -3429, -6484, -6516, -2117, -224, -4362, -3413, -8298, -1303, -1142, -8465, -2652, -10619, -1620, -3147, -4694, -2958, -9320, -3078, -5244, -2625, -3493, -7538, -4728, -4215, -2782, -3538, -7417, -5557, -4010, -5181, -3169, -3829, -6440, -6266, -8421, -2777, -1878, -4202, -11497, -4542, -2452, -1751, -2812, -4234, -3385, -2148, -2715, -2843, -2160, -3604, -1954, -2837, -3958, -1415, -4855, -2031, -2412, -5695, -1431, -6987, -2535, -2219, -6285, -1866, -8006, -3450, -1908, -5988, -2553, -5303, -4148, -2209, -7158, -3775, -2744, -4606, -3348, -12623, -6204, -1360, -6610, -3959, -7071, -11644, -1069, -13710, -4590, -5496, -9894, -1583, -5968, -8329, -6387, -6163, -2172, -4522, -6894, -9424, -4457, -2212, -4798, -3904, -7938, -4179, -2202, -6264, -3431, -5745, -5168, -2666, -9482, -4409, -5407, -7155, -4061, -10419, -6791, -6801, -8847, -7855, -5501, -8849, -10972, -7787, -7849, 11195, 15123, 10025, 6099, 8571, 11019, 14694, 9644, 5733, 7741, 10391, 13372, 8577, 4369, 4786, 9563, 11038, 6931, 1192, -2344, 9374, 7356, 4436, -3542, 1962, 9099, 3349, 1630, -2046, 1944, 7586, 6115, 2811, -531, 935, 5291, 7372, 2914, 1121, 1036, 6408, 7321, 1143, 1454, 2072, 7296, 6291, 1497, 1177, 3087, 6928, 5468, 3598, 1443, 4050, 5664, 5714, 4290, 2105, 4939, 3856, 6142, 3746, 2319, 5591, 727, 6849, 1885, 1557, 5915, -7395, 7137, -2519, -389, 5801, -1126, 6483, -4415, -2680, 5201, -1921, 4721, -769, -2403, 4188, -739, 1647, -162, -594, 2599, 794, 821, -656, 91, -466, 1178, 2644, -1822, -1098, -11217, 1390, 3262, -1618, -5779, -4820, 1147, 2935, 896, -7053, -5800, -464, 1555, 2522, -6062, -6045, -5268, -1479, 3020, -9656, -3864, -1743, 964, 2638, -5107, -3853, -203, 3374, 1760, -4036, -6396, -1279, 3921, 776, -4029, -16551, -3809, 2968, -236, -3220, -8143, -3589, 368, -1465, -2442, -7889, -10233, -2711, -3780, -2795, -5569, -709, -936, -8300, -5686, -3273, 2446, 737, -3423, -7181, -2279, 3543, 1442, -1155, -2180, -1762, 3392, 861, 137, -815, -746, 2232, -1795, 961, -896, 52, 239, -5979, 1433, -1863, -189, -2099, -897, 1622, -3121, -1718, -3985, 551, 1557, -3537, -2905, -5520, 686, 1261, -2232, -1677, -7394, 27, 715, -885, -1237, -8488, -1059, -213, -377, -2039, -4980, -2121, -1747, -830, -4073, -2595, -3249, -4097, -2325, -6630, -1691, -4229, -7405, -4772, -5486, -2005, -3586, -7187, -7279, -4017, -3260, -3248, -4533, -7752, -3357, -5022, -4191, -3047, -4702, -3228, -5988, -5489, -2174, -3104, -3376, -4316, -6122, -1603, -2904, -3414, -2785, -8958, -1317, -3641, -3062, -2009, -8828, -1351, -4858, -2576, -1824, -4507, -1595, -6319, -2447, -2153, -3322, -1869, -7238, -2943, -2892, -4009, -2192, -6063, -3927, -4048, -7471, -2810, -5060, -5006, -6336, -7996, -4013, -5153, -6513, -12027, -5008, -6226, -6290, -9703, -6730, -4456, -10684, -7420, -12876, -5063, -4618, -8828, -6957, -13355, -4465, -4695, -6007, -6580, -10569, -3031, -4757, -4748, -6951, -6650, -1852, -5345, -4392, -8115, -5484, -1897, -6110, -5073, -11001, -5880, -3632, -5574, -7318, -9674, -5604, -9235, -5218, -9011, -7118, -4163, -8010, -6298, -7697, -7118, -3950, -7467, -7900, -8856, -9572, -5670, -9525, -7093, -9777, -8870, -11966, -4224, -6722, -7543, -6720, -9695, -2019, -7078, -7268, -6368, -8813, -1415, -6884, -7908, -6644, -10736, -2124, -5611, -8390, -6536, -9810, -4488, -4537, -9472, -6533, -7881, -9121, -4070, -12403, -7430, -6232, -5549, -3898, -14521, -8280, -5120, -4089, -3925, -8328, -6393, -5058, -4425, -4379, -6126, -4521, -6278, -5827, -5537, -5533, -3452, -9027, -5927, -8372, -6073, -3144, -11883, -5083, -12795, -7374, -3693, -10706, 7471, 1317, 4615, -14033, 6451, 6761, -946, 3861, 2250, 6218, 4361, 2064, 1361, 3975, 5565, 1245, 4653, -2752, 3802, 4901, 3821, 4949, -1612, 2915, 4689, 5122, 3530, -928, 2833, 4410, 5379, 619, -784, 3273, 3654, 5126, 1850, -228, 3372, 2809, 4595, 4245, 1260, 3195, 2679, 3317, 5555, 3236, 3066, 3585, 2570, 6007, 4835, 3199, 5060, 5802, 5615, 5821, 3574, 6185, 7650, 4281, 6151, 3833, 6600, 8050, 1836, 5719, 3310, 6301, 7191, -1342, 4359, 947, 5430, 4988, -2155, 1953, -4581, 4275, 1230, -1996, -855, 1888, 3139, -1090, -3080, -2669, 3627, 1920, -848, -2718, -4740, 3998, -120, -600, -370, -6840, 3703, -4798, 942, 482, -5468, 3139, -1418, 2099, 270, -1744, 2580, 254, 2134, 83, 206, 1939, -599, 1174, 971, 901, 592, -4386, -109, 2158, 709, -1687, -3201, -668, 2771, -56, -1057, -2015, -653, 2568, -1020, 370, -4131, -1203, 1562, -1873, 813, -8413, -3746, 260, -2548, 481, -4924, -3734, 66, -3146, -998, -6771, -975, 696, -3602, -5177, -5184, -1115, 1081, -3284, -2797, -2198, -5771, 1062, -1997, 6, -1363, -1954, 769, -720, 941, -1541, 928, 396, -202, 718, -2197, 1581, 51, -822, -701, -3020, 1164, -226, -3019, -3831, -3029, 261, -275, -7997, -4819, -2221, -863, -369, -19659, -2074, -2177, -2305, -1211, -8690, -561, -3244, -3692, -3153, -4836, 423, -3537, -3659, -4844, -3733, 1030, -1982, -2668, -3175, -3808, 1179, -958, -1967, -1121, -3089, 819, -892, -1758, -304, -2016, 0, -1850, -1648, -1034, -1839, -1084, -3559, -1352, -3952, -2599, -2187, -4248, -1182, -6726, -3883, -3331, -3728, -1352, -4597, -5022, -4866, -3655, -1972, -5668, -6061, -5979, -4598, -3524, -7075, -7941, -4363, -6821, -7352, -4790, -10153, -3141, -8647, -7694, -4560, -8181, -3059, -8163, -5139, -5967, -6999, -3522, -7499, -4662, -4430, -7789, -3323, -7236, -5095, -2678, -13015, -2370, -8770, -6402, -2326, -8020, -1428, -15172, -5738, -2779, -5912, -718, -6714, -3872, -3293, -6246, -269, -4852, -3756, -3844, -8584, -248, -5726, -6181, -5197, -8974, -895, -9090, -9187, -7961, -7599, -2222, -3604, -4499, -7550, -8094, -3415, -1637, -3358, -5196, -9103, -3766, -1415, -3280, -4638, -8634, -4531, -2375, -3022, -6155, -8514, -6723, -3882, -2388, -12957, -8294, -10702, -4611, -2183, -6208, -6294, -8596, -4624, -3030, -4294, -4482, -6502, -4505, -5533, -4369, -3588, -5140, -4437, -9778, -5678, -3492, -4094, -5129, -8125, -5901, -3924, -3454, -7825, -6824, -5268, -4546, -3504, -13669, -6096, -6415, -5086, -4449, -6758, -6129, -8657, -5754, -5507, -5122, -6649, -5868, -7418, -4495, -4525, -6668, -4849, -10128, -3423, -4501, -6654, -5680, -9210, -3299, -5553, -7664, -8110, -9114, -4008, -9971, -8777, -8515, -9887, -5323, -8213, 2153, 1795, 3912, 3587, 5834, -1016, 1537, 4466, 5109, 5613, 2066, 1108, 5719, 6749, 5662, 4755, 1217, 6345, 7241, 5840, 4602, 781, 5804, 6512, 5032, 2445, -1165, 4060, 4580, 2896, 1283, -330, 1412, 1818, 314, 2223, 989, -1502, -594, 801, 1915, 805, -2466, -1993, 3264, 2110, 52, 1217, -2491, 4804, 3837, -370, 3461, 1191, 5229, 5129, 1590, 4442, 3359, 5230, 5439, 3535, 4021, 3458, 5420, 4640, 4053, 1234, 1504, 5143, 2771, 2996, -656, -252, 3689, 1434, 58, 2848, 505, 725, 1598, -723, 3135, -993, -1702, 1350, 456, 1419, -4105, -508, 626, 15, -3113, -8520, -826, -156, -918, -6508, -1488, -4348, -47, -1237, -2357, 1393, -258, 649, -1318, -869, 2277, 2002, 1054, -1786, 235, 2361, 2321, 970, -2298, 985, 2258, 1436, 338, -2189, 1162, 1883, 110, -861, -1995, 521, 926, -600, -2784, -1977, -1188, -663, -1187, -5786, -2009, -2750, -2117, -1153, -5734, -2331, -1468, -1559, -424, -3789, -3391, -846, -124, -271, -2616, -5094, -1425, 568, -635, -1514, -7855, -2307, 193, -1079, -957, -6199, -1955, -1183, -242, -1688, -1225, -674, -3158, 874, -4361, 557, 144, -2714, 775, -2997, 622, 45, -932, -462, -885, -746, -456, -966, -1615, -916, -3384, 16, -3805, -3124, -3523, -8639, 1030, -4263, -9598, -4733, -6012, 1482, -1416, -4817, -1442, -2525, 1284, -727, -3537, -1493, -2039, 938, -420, -4252, -4997, -2887, 726, -354, -6085, -5058, -2260, 126, -945, -11731, -2710, -1154, -1202, -1769, -7325, -3777, -1094, -2891, -2222, -4635, -9826, -1999, -3706, -3273, -3883, -7014, -3719, -3379, -6908, -5244, -4869, -5933, -2992, -7082, -10324, -5168, -7420, -3277, -4263, -5530, -7436, -7158, -4667, -4579, -4126, -15350, -6271, -7759, -7094, -4505, -11147, -6313, -8923, -7329, -4495, -10853, -8293, -6150, -3947, -3008, -9408, -7699, -4367, -1877, -2408, -9026, -4849, -2898, -1183, -3101, -12385, -3941, -1949, -1875, -4788, -11231, -4544, -1903, -3954, -6879, -9517, -6720, -3039, -5178, -8548, -9850, -8467, -5021, -4193, -7323, -13018, -5354, -5141, -3844, -6560, -9112, -2811, -4752, -4008, -7486, -4419, -1606, -4762, -4680, -7503, -2441, -1777, -4502, -5971, -6081, -1754, -3403, -4646, -6904, -7030, -1869, -5849, -5379, -6375, -17535, -2471, -5899, -5749, -5793, -5734, -3495, -5789, -5025, -5445, -3960, -5428, -6367, -4398, -4889, -4138, -9359, -7064, -5009, -4619, -5597, -7328, -7851, -7654, -5160, -7970, -5438, -9383, -9530, -6483, -9446, -5387, -12105, -8456, -7893, -9236, -6564, -11607, -10606, -7852, -10832, -7544, -11498, -9134, -6662, -15210, -6070, -8433, -6344, -5589, -10395, -4950, -6170, -5338, -4885, -8898, -5055, -5460, -5829, -4232, -8021, -6466, -5481, -9062, -3557, -8159, -9262, -5154, -10191, -3290, -10077, -5350, -5843, -8811, -5320, -9128, -7464, -3738, -10143, -7960, -8100, -9496, -3235, -12739, -9271, -7889, -5974, -4061, -12627, -9218, -7999, -4389, -6014, -9309, -7709, -7663, -4306, -6351, -8323, -6228, -6876, -6256, -4848, -8023, -5981, -6369, -22941, -3874, -7185, -6829, -7207, -7048, -3467, -7086, -8196, -10378, -6642, -3479, -9258, -9857, -7156, -11084, -3651, -9220, -14935, -5104, -7677, -3819, -5829, -12594, -4775, -5058, -4090, -4704, -10755, -5069, -4478, -4545, -4855, -12465, -4925, -4561, -5231, -5501, -8389, -4510, -4559, -6212, -5288, -5943, -4715, -4564, -6756, -4783, -5362, -6670, -5045, -5267, -4956, -6155, -12391, -5872, -3268, -5009, -7774, -4679, -6195, -2051, -4210, -7952, -2658, -5427, -1662, -3561, -6643, -2372, -4257, -1872, -3409, -5854, -3374, -3473, -2318, -3894, -6110, -5644, -3255, -2620, -5374, -7144, -8270, -3633, -2712, -6792, -7214, -7604, -4796, -2792, -5905, -6319, -6949, -7097, -2972, -6274, -5927, -6965, -8726, -3185, -10383, -6426, -6650, -7111, -3338, -7288, -8155, -5905, -6216, -3604, -4812, -10773, -5450, -6311, -4407, -4748, -8935, -5538, -7599, -6173, -6452, -7096, -5857, -10204, -9091, -10233, -5895, -5855, -9265, -11213, -18393, -4744, -5604, -7013, -10177, -15188, -3829, -5427, -5872, -8567, -13044, -3467, -5386, -5846, -7906, -14226, -3806, -5568, -7225, -8231, -15640, -4867, -6064, -7962, -8570, -15315, -6491, -6603, -5666, -8093, -12325, -8361, -6551, -4535, -7626, -8564, -10203, -5893, -4544, -7566, -6681, -10950, -5123, -5408, -7591, -5847, -10538, -4421, -7186, -7343, -5592, -11590, -3902, -11545, -6836, -5673, -13925, -3799, -10239, -6406, -6118, -7636, -4267, -5771, -6545, -7258, -5346, -5225, -3950, -7375, -9963, -4827, -6336, -3422, -8649, -19154, -5777, -7520, -3945, -11323, -9199, -8682, -8992, -5413, -13915, -6826, -13591, -9162, -7564, -8499, -5978, -9332, -7473, -9923, -7084, -6291, -8315, -6112, -12872, -7505, -7801, -8927, -5640, -20680, -9918, -9336, -11811, -6077, -12715, -18131, -8541, -12484, -7082, -9311, -15387, -8505, -8095, -7985, -7318, -16632, -10172, -6551, -8789, -6129, -15036, -11625, -6071, -10040, -5623, -14149, -10038, -5712, -12652, -5786, -8795, -8596, -5150, -17093, -6398, -6442, -7428, -4844, -10921, -6799, -6098, -6908, -5106, -9167, -6896, -7377, -7247, -5934, -9277, -6995, -10019, -8436, -7206, -11837, -6677, -11714, -9005, -8900, -14474, -6423, -10326, -7606, -10715, -8786, -7193, -9644, -7153, -10266, -6949, -9861, -9951, -8611, -9436, -6413, -15358, -10963, -12247, -10379, -6633, -11458, -15410, -11217, -13295, -7154, -11108, -12643, -12588, -9742, -7396, -11499, -9731, -11903, -7479, -7161, -11064, -10301, -8998, -6598, -6914, -11898, -16542, -9630, -6623, -7180, -13601, -11254, -10157, -7547, -8109, -9983, -8363, -6865, -9548, -8945, -8289, -6601, -5682, -12160, -8646, -8391, -5706, -5913, -11865, -8276, -10447, -5925, -6935, -9121, -8354, -7604, -6798, -9462, -6838, -4716, -6822, -6549, -8462, -7693, -4000, -6594, -7895, -6769, -7586, -4973, -6013, -8419, -5617, -7780, -7360, -5270, -5937, -5635, -9492, -7264, -4908, -4523, -7270, -15655, -6850, -5062, -4234, -9884, -13528, -8888, -5614, -4852, -7523, -10928, -7270, -6215, -5311, -6747, -7114, -4923, -6566, -4600, -7739, -4724, -4564, -7040, -4242, -8549, -3727, -5943, -8435, -4850, -7798, -3812, -9394, -9503, -6331, -8229, -4845, -8458, -8618, -8332, -10959, -6702, -8161, -9438, -10704, -9777, -8455, -12745, -8288, -18293, -7542, -8917, -6757, -5409, -10329, -7475, -8013, -4059, -4109, -6316, -7180, -5499, -2730, -3871, -4034, -4328, -3872, -1852, -4352, -2859, -2390, -3590, -1313, -5337, -2758, -1733, -4776, -1285, -6561, -3900, -2343, -8214, -2047, -8071, -6182, -4479, -13300, -4172, -9847, -5768, -6314, -8925, -10777, -7609, -4552, -4439, -8330, -7203, -5519, -4559, -3779, -8590, -5127, -4699, -4959, -4239, -9071, -5260, -4944, -4503, -5149, -10096, -6423, -6439, -3922, -5556, -12913, -7777, -9690, -4341, -5107, -11462, -9815, -12056, -6622, -4521, -7703, -10977, -13298, -11830, -4439, -5979, -7696, -10712, -5605, -5086, -5555, -6830, -6915, -3485, -6244, -6340, -8277, -5108, -2779, -6934, -8530, -14756, -4508, -3014, -6373, -12795, -8122, -4962, -3946, -5447, -20497, -5840, -6385, -5337, -5108, -16593, -5327, -8387, -7255, -5739, -11819, -6191, -10161, -7649, -7019, -10547, -9152, -10066, -5847, -6470, -14486, -10060, -8501, -5217, -5286, -9341, -5770, -7874, -5880, -5256, -5970, -3900, -8430, -7759, -6395, -5144, -3241, -9640, -11092, -7933, -6040, -3405, -10804, -14053, -8638, -9004, -4054, -13237, -11551, -9299, -12484, -5009, -14033, -10711, -9999, -8460, -6175, -9999, -11959, -10288, -7217, -6379, -8146, -14966, -9243, -7447, -6123, -7424, -10787, -8123, -8228, -7030, -7654, -9525, -8109, -7544, -8848, -8383, -10883, -8998, -5887, -8280, -8208, -19806, -10114, -4968, -7492, -8023, -12012, -11740, -5422, -7524, -9341, -8940, -12506, -8279, -6865, -13448, -6894, -7999, -13915, -5800, -15544, -6065, -5780, -8611, -5322, -10285, -6815, -5080, -9507, -5177, -8316, -10562, -5325, -9006, -5229, -8222, -10018, -6044, -6886, -5836, -10249, -6882, -7736, -7052, -6820, -14958, -6880, -13252, -7863, -7128, -11928, -9877, -7676, -7032, -6802, -11699, -13657, -5602, -7377, -6714, -12093, -8943, -5430, -10822, -6575, -10612, -8469, -6471, -9368, -5754, -10230, -9748, -8396, -7060, -5243, -10757, -16112, -9310, -7211, -5730, -10197, -11386, -7731, -8958, -7499, -9370, -9610, -6667, -10252, -10601, -8998, -11204, -6622, -9982, -9833, -8612, -10396, -7354, -10764, -8613, -8016, -8505, -7972, -13083, -8838, -7443, -9133, -7421, -22329, -9933, -7356, -13400, -6717, -12747, -10748, -8053, -11388, -6577, -9403, -10115, -9711, -8863, -6951, -8050, -9368, -13137, -8426, -7709, -8026, -9329, -16157, -9241, -8961, -9285, -10204, -10665, -4364, -6294, -3836, -7219, -9365, -3929, -6002, -5580, -4914, -8936, -4243, -7687, -8215, -4495, -10010, -5284, -8697, -7519, -5838, -12775, -6430, -8266, -7565, -10654, -11040, -7006, -10283, -10751, -9930, -10448, -7897, -13324, -7606, -7022, -9663, -9744, -8958, -4818, -6295, -6927, -10911, -7584, -3691, -5889, -5940, -10517, -7192, -3582, -5363, -7219, -9895, -7168, -4360, -5180, -9619, -8691, -7961, -5198, -5803, -5978, -7237, -10391, -4804, -7380, -4833, -6109, -10396, -4192, -9450, -5547, -5263, -9089, -3209, -10289, -6763, -4585, -6318, -1948, -8639, -6093, -4576, -4159, -1231, -6172, -5231, -5832, -3620, -1236, -4528, -3804, -6468, -4263, -1849, -3621, -2225, -4256, -4723, -2965, -2791, -1475, -3322, -4411, -4578, -1826, -1700, -3905, -4468, -6272, -1273, -2831, -6034, -4816, -5906, -1430, -4717, -8818, -4714, -4902, -2262, -6920, -8330, -4036, -4736, -3635, -8333, -7975, -3348, -5249, -4955, -8431, -7728, -2994, -6889, -5195, -8476, -6570, -3102, -13434, -5928, -9587, -5214, -3852, -6093, -7567, -11295, -4506, -5399, -3752, -5774, -9771, -4808, -6523, -3233, -4852, -8863, -5962, -6095, -3654, -5989, -8809, -6196, -6473, -4103, -7589, -9073, -5738, -7981, -4108, -5257, -8939, -6148, -8299, -4780, -3803, -6527, -6477, -6990, -7861, -3288, -4499, -6232, -6105, -10866, -3259, -3479, -6646, -5314, -6065, -3503, -3374, -7567, -4174, -5087, -3853, -4226, -8037, -3362, -5254, -4256, -6220, -8814, -3278, -6154, -5008, -9116, -10928, -3834, -7891, -6764, -9195, -9869, -4800, -10372, -11778, -8982, -7745, -6119, -11778, -10249, -10527, -7539, -7762, -9666, -7519, -11275, -9557, -9285, -7147, -7933, -10382, -14017, -13071, -6178, -12286, -10424, -9186, -10255, -7514, -11687, -8993, -7492, -6503, -9128, -10698, -7872, -7326, -5508, -4999, -16246, -7830, -8372, -6157, -3467, -8183, -8341, -9524, -8154, -3266, -6474, -8933, -10035, -9500, -3579, -6851, -9384, -10592, -9732, -3931, -8966, -10573, -9352, -10725, -4621, -8411, -12677, -8166, -8141, -5573, -6177, -10671, -6396, -7005, -5019, -5664, -8539, -4903, -7998, -4353, -6129, -7154, -4439, -8108, -5015, -6479, -6239, -4922, -6675, -6239, -7302, -5595, -5903, -7161, -5943, -9650, -5466, -6010, -10543, -6084, -7520, -6087, -5225, -15220, -7054, -5292, -6691, -4902, -11189, -6657, -4647, -6504, -5288, -11743, -5961, -5358, -6616, -6282, -13219, -6286, -7658, -6664, -7806, -14203, -7961, -9002, -6051, -8918, -12693, -12553, -6606, -6071, -8136, -9552, -11452, -5097, -7414, -7769, -7945, -8942, -4260, -9978, -9190, -7114, -9340, -4201, -10764, -13846, -5954, -15349, -5477, -9096, -10039, -4706, -9028, -10172, -7495, -8385, -4112, -5674, -7674, -6897, -8848, -4367, -4294, -4688, -7419, -10627, -5427, -3950, -3679, -8725, -9351, -7109, -4392, -3577, -9706, -6925, -9179, -5632, -4123, -9339, -5498, -11658, -7746, -5061, -8542, -4782, -13051, -8615, -5995, 10207, 11289, 9083, 11137, 8447, 9430, 10944, 8381, 10592, 8026, 7216, 9886, 6198, 8985, 6673, 6633, 8129, 4138, 6584, 4431, 7475, 6153, 5042, 4490, 3804, 6993, 5102, 5109, 3740, 4357, 5154, 4561, 3913, 3153, 3361, 3044, 3469, 1068, 2251, 46, 5734, 1797, -3758, 2245, -1866, 7030, 564, 1773, 1725, 1478, 6789, 625, 3127, -1614, 3713, 6222, 488, 3036, -562, 5623, 5979, 1255, 3515, 3295, 6951, 4547, 3822, 4257, 4597, 7390, -822, 4900, 3891, 4550, 6732, 826, 4401, 2104, 3719, 4627, 2534, 2473, -938, 2962, -219, 1731, -34, -1834, 2546, -1652, 296, -325, -1352, 2012, -161, 110, -52, -1516, 1491, -1138, 1025, -483, -1726, 1399, -1913, 1741, -1410, -987, 1403, -1115, 1689, -1125, -40, 831, -211, 353, 543, -80, -702, -268, -1854, 1470, -1423, -4196, -1443, 1014, 1393, -2236, -3751, -2075, 2777, 588, -92, 156, -1659, 3229, -489, 1328, 1353, -2081, 2877, -1334, 1669, 744, -1109, 1810, -1551, 1024, -2013, 743, 890, -1334, -573, -3908, 1664, 2001, -1130, -2663, -2071, 1890, 2865, -872, -2943, -3700, 1837, 2831, -270, -1210, -6507, 1574, 2720, -90, 239, -577, 784, 2899, -1803, 1098, 983, -818, 2646, -5786, 1519, 789, -3360, 1812, -615, 1551, -667, -9003, 940, 404, 1184, -1470, -3667, 193, -742, 497, -1471, -710, -601, -2693, -262, -4084, 478, -929, -1549, -687, -2203, 1135, -674, -381, -561, 895, 1537, -720, -271, -731, 1593, 1380, -1903, -1418, -2215, 596, 488, -5180, -3958, -6036, -2502, -1253, -8537, -4943, -11206, -5160, -4763, -5640, -3247, -5166, -1946, -7933, -5692, -1330, -1766, -398, -2854, -7819, -79, -219, 665, -1759, -10432, 51, -41, 1234, -2617, -5774, -1231, -1204, 1088, -5262, -3406, -5013, -4180, 88, -4682, -2510, -7221, -6368, -1986, -2630, -2390, -4973, -4483, -5984, -1756, -2469, -4899, -4610, -6454, -1856, -2687, -3228, -6005, -3629, -3222, -3783, -2565, -6734, -2752, -7600, -6444, -3639, -5262, -2601, -7169, -2645, -4663, -2591, -2349, -4601, -60, -3248, -847, -1804, -5712, 1000, -2539, -362, -1421, -7959, 1097, -3055, -943, -1731, -5327, 408, -4410, -1942, -2930, -5813, -1139, -4321, -2170, -3867, -7668, -4112, -3678, -1571, -3272, -4025, -6533, -4260, -973, -2701, -2626, -3591, -6282, -1033, -2514, -2780, -2551, -9603, -1826, -2444, -3987, -2360, -8058, -2500, -2464, -5667, -2311, -6635, -2500, -3015, -6611, -2884, -7232, -2174, -4393, -6850, -3689, -11287, -1442, -5914, -7380, -1876, -8607, -1157, -5547, -5864, -537, -7727, -2009, -4643, -3494, -603, -8298, -4132, -4745, -2530, -1954, -3908, -5005, -6482, -3294, -4320, -2201, -3564, -8216, -7161, -5690, -2257, -2733, -6127, -9394, -4781, -2998, -2583, -3481, -7349, 5426, 7847, 9313, 7297, 4636, 5085, 7058, 8906, 6891, 6119, 4043, 4658, 7771, 5909, 7459, 2156, 2417, 6234, 5217, 7788, -1435, 1624, 5049, 5095, 7408, -7233, -3838, 4569, 4327, 6644, -901, -94, 3901, 1247, 5628, 546, 2292, 3526, -2961, 4485, 1089, 2669, 4078, 1769, 4119, 257, 2406, 3876, 672, 4579, -46, 2191, 2664, 96, 5252, 4383, 2794, 2833, 4355, 5809, 6437, 3970, 3823, 5731, 5659, 6971, 4748, 3719, 5315, 4453, 6348, 4851, 2532, 2791, 2260, 4618, 4379, 1086, -8967, 813, 1747, 3504, 474, 1170, 1665, 656, 2502, -629, 2487, 2435, 1586, 1424, -1338, 2665, 2198, 903, -639, 1323, 2723, 670, -3224, -1740, 2583, 2562, -3183, -2303, 757, 2232, 1425, -3889, 1318, 1349, 528, -629, -666, 2355, 216, -310, 590, -34, 2543, -2223, 1015, 1222, -286, 2181, -3519, 1729, -234, -448, 874, -4004, 1344, -1421, -769, -2573, -5363, -1150, -254, -1731, -6367, -5754, -2257, -787, -1895, -884, -4020, 1781, -3247, -481, 896, -1826, 2605, -3712, -117, 1559, -668, 1196, -2059, -1999, 1519, -1375, -2616, -1751, -10551, 1487, -6260, -456, -2258, -1066, 1966, -3019, 589, -2636, 819, 2356, -1004, 39, -3487, 1438, 2445, -993, -1235, -4447, 1845, 2441, -462, -2703, -3742, 2280, 2201, 496, -1995, -2080, 2322, 1166, 981, -201, 444, 1756, -1499, 868, 431, 1756, 806, -3667, -112, -238, 1637, -78, -1968, -1412, -2136, 109, -646, -3260, -733, -5007, -2825, -1485, -9342, 109, -10058, -5639, -4041, -4338, 254, -9527, -5977, -12869, -2969, 285, -5502, -5068, -4607, -1379, 469, -3507, -3972, -3367, -219, 405, -2348, -2465, -3265, -347, -173, -1863, -1051, -3589, -1807, -931, -1612, -414, -4401, -4781, -861, -1242, -673, -5615, -13421, -194, -944, -1880, -6549, -7062, 327, -1004, -4253, -7672, -4454, 748, -1496, -5510, -13924, -3132, 923, -2578, -3646, -7889, -2116, 404, -5211, -3170, -5116, -1094, -1253, -7590, -3962, -4729, -190, -4422, -3925, -4724, -5366, 176, -4380, -3646, -4135, -5588, -196, -2938, -6095, -2935, -4876, -1312, -2734, -8116, -2162, -4472, -3171, -3102, -10162, -2307, -5976, -5890, -3760, -5903, -3491, -9974, -7713, -4368, -1577, -6112, -5954, -5608, -3784, 30, -7232, -4160, -3885, -2656, 375, -4147, -1974, -3448, -2591, -104, -2696, -669, -4437, -3507, -1342, -2292, -787, -6889, -3156, -3878, -2933, -2172, -8951, -2564, -14786, -4893, -3482, -6806, -3435, -5097, -4805, -2796, -4327, -5656, -3335, -3204, -1890, -3247, -6490, -4428, -3529, -1462, -2997, -4216, -10286, -6461, -1467, -2295, -3052, -2273, -15047, -1709, -1113, -4487, -3, -7242, -1887, -336, -7340, 491, -3356, -2034, -380, -1820, -228, -857, -2469, -1405, -209, -1899, 295, -2879, 9652, 7124, -6527, 7067, 8584, 9372, 7627, 4321, 7288, 8635, 8507, 8128, 6618, 7542, 8691, 6993, 7912, 7318, 7372, 8450, 5156, 7030, 7061, 6655, 7534, 4824, 5754, 6076, 5354, 5562, 5020, 4152, 4597, 3849, 2168, 3748, 1157, 3080, 3905, -862, -888, -4556, 1962, 4386, 440, 1776, 1834, -482, 3628, 2068, 4814, 2591, -2346, 2446, 1044, 6083, 3325, 3300, 3420, -8072, 6245, 4934, 4483, 3509, 1315, 5062, 5033, 2977, 2414, 1922, 1231, 2650, -7803, 3735, 4001, -994, -396, 3097, 4750, 6221, 2117, 3058, 4447, 4182, 6836, 1332, 3289, 3808, 2267, 6175, -2967, 1953, 2041, -705, 4531, -3984, 268, 555, -6472, 2323, -252, -245, 1111, -3071, 1547, 589, 90, 2149, 168, 2513, -158, -521, 2545, 1469, 3099, -3443, -3551, 2239, 1852, 3305, -5347, -5659, 1439, 1681, 3407, -1643, -2718, 664, 1044, 3140, -836, -3775, 451, -421, 1750, -909, -8705, 356, -2317, -2939, -1755, -3895, 55, 313, -1306, -2954, -3244, 290, 2307, 1473, -2253, -2582, 1121, 2993, 1894, -1241, -812, 1586, 2776, 1418, -694, -196, 1431, 1897, 301, -354, -91, 871, 447, -2935, -300, 497, 132, -1759, -1713, -692, 664, -1077, -5634, 1413, -1322, -130, -2534, -9987, 2011, -1774, -1518, 21, -4793, 692, -783, -4924, 2058, -2960, -3722, 1082, -4365, 2653, -2402, -2916, 1796, -616, 2184, -3321, -672, 892, -837, 1125, -5352, -197, -2158, -4373, -104, -2044, -116, -4696, -799, -1885, 108, -455, -3788, 609, -3943, 912, -1172, -5821, -365, -3853, 922, -1494, -10726, -3632, -4144, 351, -1992, -13746, -7281, -6012, -870, -4088, -7003, -8955, -9928, -2215, -10930, -4801, -4130, -9607, -1677, -6667, -4013, -2026, -7841, -1256, -4379, -3478, -2305, -7516, -2244, -2726, -3069, -5169, -7457, -3927, -1566, -3072, -5952, -8071, -4662, -1407, -3683, -3284, -12012, -6466, -2627, -5559, -2466, -8503, -8260, -7049, -12068, -1939, -6263, -5644, -5535, -5532, -1498, -8145, -3326, -1547, -2922, -1460, -8897, -1785, -83, -2035, -1681, -3586, -1615, 262, -2335, -1801, -1720, -3506, 34, -3925, -1776, -1105, -7138, -351, -7320, -2071, -1136, -2049, -1030, -13759, -3510, -1246, -409, -2428, -11366, -7703, -1434, -345, -3435, -6548, -4630, -2223, -1301, -2075, -4725, -2506, -3777, -3015, -810, -3991, -2467, -5095, -5961, -163, -3725, -3751, -5199, -6350, -106, -4025, -4216, -6003, -3078, -822, -4461, -2049, -9318, -1990, -2599, -3994, -206, -8426, -2517, -5395, -3002, 684, -5990, -5066, -4987, -2271, 701, -4272, -9414, -2754, -1898, 125, -2779, -4829, -1562, -1654, -710, -2591, -4261, -1492, -1627, -1909, -3583, -5441, -2417, -2053, -3650, -2863, -2625, -3523, -2894, -4334, -1597, -473, -3340, -4067, -3633, -1699, 232, -2580, -4067, -2308, -3084, -1180, -6092, -4239, -1293, -4354, -36, -2800, -3728, -1102, -5333, 72, -1672, -1911, -1753, -4297, -556, -1852, -986, -3200, -4189, -1704, -2067, -1346, -5424, -6356, -3116, -1528, -2690, -6495, -5987, -3808, -981, -3077, -4233, -4180, -3316, -640, -2510, -2383, -6287, -2277, -429, -2864, -1384, -5192, -1512, -475, -3355, -1349, -966, -1403, -881, -2271, -2630, 389, -1847, -1543, -1237, -4508, 338, -2645, -1930, -979, -2698, -646, -3822, -1645, -1614, -1494, -1975, -5789, -1433, -3747, -1685, -2633, -8070, -1757, -8432, -3345, -3061, -5691, -1998, -3004, -8269, -4698, -4254, -1247, -599, -4812, -2980, -4254, -336, 249, -2421, -411, -4544, -81, -145, -2301, 396, -4487, -860, -1777, -4124, -241, -4998, -3200, -3160, -8355, -2338, -5146, -7469, -2295, -9141, -5032, -3662, -5895, -1874, -5905, -5154, -2514, -5081, -2382, -4328, -6181, -2148, -4711, -4073, -4849, -8862, -2655, -3913, -8250, -4878, -8104, -4369, -3010, -6854, -3375, -5052, -6610, -2190, -4762, -2965, -3345, -5969, -1668, -5101, -3189, -3193, -5337, -1630, -7802, -3245, -4524, -4370, -2125, -8453, -3168, -6898, -3635, -3126, -6650, -3888, -6152, -4153, -4874, -7013, -7049, -4643, -6797, -8176, -7959, -7043, -4792, -14044, -4507, -7943, -3770, -7443, -6466, -1643, -7323, -3277, -7378, -5406, -580, -7269, -4736, -4354, -6025, -960, -8876, -6648, -4096, -7668, -2995, -12681, -3646, -6702, -9556, -6765, -12470, -1753, -6742, -7613, -4703, -9559, -975, -2850, -4852, -3019, -7457, -1062, -1342, -2897, -2641, -6713, -1993, -831, -1659, -2941, -6644, -3833, -972, -1070, -3118, -6411, -6991, -1778, -1119, -3081, -6290, -8705, -2943, -1677, -3203, -7092, -5220, -2945, -2155, -3704, -7188, -3990, -2399, -2346, -4409, -5589, -4399, -2796, -3158, -4166, -5033, -6164, -4740, -5073, -3487, -5275, -8020, -9252, -5519, -3013, -5280, -7049, -6241, -4112, -2602, -5002, -4342, -4485, -3499, -2209, -5353, -2726, -3989, -3586, -1779, -7542, -2447, -3624, -4131, -1538, -10178, -3316, -3414, -4716, -1680, -6510, -4780, -3717, -4943, -1959, -5807, -5592, -4417, -5193, -2187, -6896, -5312, -4970, -5971, -2826, -9528, -4553, -5374, -7619, -4631, -11720, -4032, -6466, -10981, -9776, -9626, -3596, -7883, -7643, -7926, -9450, -3189, -6556, -4514, -5081, -10063, -3555, -5838, -3001, -4330, -5326, -5705, -6934, -2437, -4379, -3222, -13828, -8629, -2534, -4638, -3081, -6308, -7829, -3122, -4884, -4988, -4575, -8347, -4172, -5425, -12266, -3980, -12652, -5641, -6592, -8644, -3517, -9681, -6087, -8262, -6792, -3360, -7437, -5156, -9033, -6179, -3928, -7239, -4846, -7804, -6242, -5451, -7585, -5468, -6124, -7393, -7578, -6948, -6962, -4992, -10180, -8464, -5689, -10150, -5007, -9271, -9298, -5037, -12223, -7211, -6436, -12225, -5674, -6543, -12220, -5783, -11803, -8592, -4992, -5941, -3157, -170, -3957, 419, -2841, -3929, -1142, -4620, -314, -3270, -2281, -2919, -3992, -1859, -5558, -532, -5426, -4294, -4450, -10597, 248, -5391, -4548, -9407, -3583, -35, -3340, -3159, -7880, -1402, -1515, -2693, -2726, -6853, -692, -4796, -3774, -3899, -7827, -1072, -6084, -8339, -5251, -6331, -2497, -3400, -7077, -4072, -4268, -4882, -2502, -4276, -3589, -3245, -7636, -2608, -3600, -4090, -3282, -9546, -3455, -3308, -4841, -4708, -8275, -4656, -2979, -5731, -9120, -5274, -5088, -2714, -6845, -9933, -3065, -4837, -2564, -7328, -5654, -1960, -4820, -2365, -6734, -3859, -2256, -5088, -1539, -5890, -4024, -4679, -4334, -322, -4506, -10133, -2871, -2397, 300, -2445, -3656, -186, -1113, -244, -1247, -620, 543, -552, -2311, -1136, 177, -4, -276, -3337, -1706, -466, -1231, -500, -2301, -2313, -2774, -2075, -2132, -3227, -2650, -6498, -2054, -7939, -3448, -2781, -5073, -1721, -3973, -1305, -3086, -6035, -1765, -1945, -533, -4356, -16899, -2541, -1818, -706, -6369, -5265, -4491, -2578, -1216, -4346, -3699, -10344, -3971, -1983, -3044, -4514, -7241, -6979, -2824, -3433, -10366, -5372, -9833, -3742, -6117, -5688, -5513, -3639, -6728, -9176, -3372, -5632, -1562, -6172, -3954, -3871, -4747, -992, -3247, -2446, -7278, -3462, -1548, -3282, -1876, -5573, -2696, -2417, -4861, -1604, -2894, -2699, -1627, -3137, -1879, -1806, -3529, -636, -1494, -2835, -1315, -5640, -629, -1268, -3994, -1102, -7340, -1609, -2153, -4626, -1179, -3667, -3165, -4117, -4095, -1683, -1811, -4122, -7872, -3229, -2724, -1385, -3690, -10671, -2923, -4360, -2363, -2690, -6183, -3171, -6327, -5682, -2145, -4540, -3834, -6881, -12452, -2398, -4211, -4850, -5589, -7662, -2900, -5063, -5796, -4179, -7179, -2366, -6936, -5940, -3622, -3547, -1541, -6389, -6049, -4282, -2157, -1368, -4364, -7178, -6198, -2702, -2154, -3233, -9029, -6981, -5334, -4461, -2787, -7655, -3614, -9777, -7026, -2835, -5070, -1319, -8361, -4223, -3253, -3094, -448, -9863, -3240, -3538, -2131, -806, -18134, -3532, -2913, -2198, -1992, -9332, -4367, -2200, -3003, -2578, -7431, -5050, -2440, -3693, -2335, -6507, -5188, -4258, -3720, -2648, -5348, -4864, -6207, -3824, -3727, -4056, -4372, -4311, -4385, -5038, -3425, -3762, -4365, -5165, -6263, -3861, -2949, -5523, -5803, -7267, -5535, -2440, -3450, -6491, -6583, -7471, -2905, -2155, -7149, -5838, -7255, -5139, -2232, -6117, -5664, -7448, -9986, -3195, -5670, -6103, -9060, -5480, -4686, -7828, -7515, -11807, -4176, -6412, -10395, -8694, -8353, -4366, -7673, -6264, -7269, -4235, -5007, -7954, -5487, -5539, -2070, -5206, -7984, -5717, -4639, -1338, -5335, -9191, -5433, -4683, -1827, -6415, -13691, -4209, -5045, -3519, -8156, -12743, -3118, -4772, -6756, -6671, -9288, -2765, -4329, -8963, -6039, -8329, -3145, -4475, -6576, -7427, -8702, -3934, -5309, -6314, -5477, -3410, -3167, -66, -2262, -5855, -3498, -5408, -1286, -2858, -5521, -3041, -5328, -4032, -4533, -6361, -2287, -3867, -20243, -4777, -10200, -2155, -2661, -5044, -3543, -9783, -3018, -1798, -4161, -3724, -4886, -4616, -1429, -7303, -5895, -2396, -4869, -1700, -6545, -6492, -949, -3431, -2717, -2493, -2300, -565, -2311, -4681, -1593, -456, -1694, -1798, -8494, -2401, -264, -6883, -1563, -11681, -4056, -1761, -3721, -1230, -5505, -3650, -5053, -947, -821, -2387, -3506, -3741, -358, -624, -405, -3536, -2328, -642, -790, 472, -970, -2018, -1064, -1438, 77, 912, -1657, -583, -2990, -2015, 1734, -664, 340, -4616, -3717, 1779, 565, 722, -2975, -1722, 1200, 1446, 669, -2045, -1682, 17, 1739, 477, -2367, -3931, -1958, 1421, -69, -3265, -7861, -5522, 510, -1234, -3364, -5265, -17262, -914, -2866, -2765, -4489, -7162, -2282, -3834, -2555, -3742, -5362, -3331, -3263, -2447, -3105, -3817, -6616, -3147, -1883, -3630, -2625, -6406, -4667, -1269, -5446, -2050, -2187, -9455, -626, -7359, -1879, -1076, -5427, 148, -6831, -1534, -1283, -2948, 483, -4340, -944, -2099, -2338, -155, -3232, -947, -2821, -3413, -2428, -3920, -2179, -3242, -7184, -12341, -7016, -4100, -3160, -5233, -3558, -14145, -3318, -2490, -3249, -1710, -7597, -2832, -2170, -3325, -1787, -6355, -3936, -2602, -4810, -2898, -5908, -5624, -3795, -8726, -3745, -5841, -3629, -5146, -8145, -4212, -6266, -1858, -3569, -3990, -6194, -5008, -1244, -2718, -2468, -10348, -2920, -1426, -4559, -2215, -7165, -2210, -2518, -10184, -2919, -6182, -3111, -6181, -2783, -4790, -6442, -3864, -3545, -859, -16235, -6619, -1850, -595, -2, -3783, -5489, -641, 56, 310, -930, -3593, -440, -895, -13, -139, -2242, -907, -3589, -963, -691, -2010, -1697, -8947, -1732, -1890, -2865, -1927, -12190, -1474, -2324, -3764, -1104, -6571, -1214, -2128, -3762, -508, -5101, -1675, -1924, -4087, -850, -5613, -2976, -2142, -5175, -2255, -4302, -4548, -3586, -6211, -4518, -3139, -4060, -8390, -5934, -6325, -4610, -2357, -7488, -5683, -6163, -7341, -1213, -4894, -4927, -6371, -2692, -1206, -5002, -3591, -9952, -1444, -3129, -5790, -2942, -8019, -1823, -13260, -5479, -3063, -4223, -3022, -3420, -5042, -3514, -3078, -3803, -1685, -5575, -3754, -3408, -4172, -1592, -8212, -3633, -5294, -4751, -2493, -10080, -3281, -8064, -4468, -4490, -5562, -2984, -6170, -3963, -7899, -4475, -3326, -5320, -4466, -5433, -4894, -5054, -5898, -6387, -3080, -5548, -10698, -6944, -9742, -2464, -5787, -7323, -7028, -11875, -3031, -6788, -4895, -6152, -15868, -3168, -8866, -4532, -5277, -7629, -2080, -10652, -5437, -4903, -5330, -1388, -10577, -7358, -5212, -4795, -1010, -9603, -9015, -6117, -5454, -606, -8182, -9363, -6617, -7009, -517, -6436, -9368, -6261, -6469, -1053, -6020, -8244, -6454, -4848, -2195, 6928, 7161, 7582, 9663, 3009, 6574, 6930, 7288, 8942, 2336, 5736, 5959, 6643, 6362, 551, 4880, 4033, 6077, -2389, 1134, 4115, 3344, 5678, 3457, 2681, 3483, 3649, 5306, 3935, 2660, 2102, 2126, 4541, 2237, 516, -2154, -289, 2802, 3058, -1716, 3671, 2723, 322, 4541, 2205, 5567, 3995, -57, 4703, 3907, 5418, 4148, -1085, 3697, 5001, 3807, 4239, -3546, 1478, 6029, 1668, 4889, 818, -144, 6718, 1282, 5574, 2393, 1204, 6736, 1982, 5516, 2036, 1773, 5835, 1456, 4272, -5, 1474, 3807, -453, 1723, -367, 723, 1272, 1176, 589, 1470, -87, -532, 1951, 1410, 2149, -182, -2145, 820, 1516, 1956, 714, 1835, 1723, 1139, 1227, 1601, 3241, 4201, 697, 407, 1961, 2985, 5495, 625, 86, 1831, 1753, 5665, 644, 258, 1375, 101, 4633, 408, 428, 591, 101, 1964, 73, 586, -1114, 1791, -3599, 341, 1153, -5101, 2327, -3064, 1556, 1648, -5711, 1436, -3218, 2393, 1225, -6239, -1028, -2614, 2159, -112, -3314, -6108, -490, 634, -104, -935, -7254, 1131, -2714, 266, -725, -2490, 2436, -5403, -995, -1625, 141, 3343, -2207, -1860, -1732, 1613, 3657, -1396, -380, -920, 2091, 3269, -2605, -115, -694, 1471, 2147, -8207, -1260, -1161, -634, 487, -5559, -2514, -1353, -5645, -720, -3252, -1475, -1312, -5870, -873, -3397, -1416, -2092, -3917, -921, -4442, -3653, -3683, -3276, -1468, -2817, -6368, -4562, -2547, -2602, -945, -5453, -3824, -2102, -3643, -496, -10197, -3446, -2567, -3957, -1277, -5898, -4932, -4097, -3617, -2940, -3369, -12484, -5700, -3037, -4624, -2317, -5191, -6881, -2797, -4694, -1040, -3485, -9315, -3042, -3857, -200, -3721, -8256, -3425, -3250, -339, -3769, -6949, -3035, -2842, -1585, -1973, -5703, -2145, -2747, -3759, -602, -4099, -1649, -3167, -5274, -249, -3214, -1890, -4350, -6286, -1009, -3009, -3173, -7507, -6186, -3358, -3037, -6044, -9712, -3886, -9717, -2858, -4379, -4317, -3178, -6481, -2575, -1477, -2575, -4203, -5782, -2697, -165, -2142, -5758, -7880, -3698, -55, -2516, -4626, -9078, -6360, -1198, -3214, -4071, -7936, -8296, -3909, -3814, -5051, -7098, -4863, -6324, -4723, -6959, -5957, -3596, -5381, -6863, -5569, -4869, -3771, -5398, -9812, -3639, -3449, -5759, -6330, -7022, -2587, -2509, -9998, -7825, -5322, -2124, -2606, -5872, -7187, -4567, -1959, -3973, -4872, -7178, -4412, -1840, -7693, -6145, -8514, -5065, -1816, -10338, -9791, -6354, -6935, -2090, -5574, -7507, -5249, -10146, -2684, -4477, -6408, -5846, -8380, -3063, -4549, -7633, -7512, -6250, -2611, -4874, -9968, -9417, -5461, -2196, -5033, -10329, -9230, -5494, -2565, -5050, -7495, -7770, -5990, -3404, -4994, -5494, -7295, -6686, -3496, -5244, -5669, -7175, -7101, -3513, -5959, -9259, -6859, -6415, -4417, -6444, -6359, -1981, 7876, 7695, 8495, 8237, -2844, 7481, 7270, 7862, 7545, 1019, 6019, 5665, 6034, 5202, 3039, 2185, 2306, 5340, -953, 3467, -1751, 3379, 6516, -117, 3658, 2522, 4529, 6607, 2003, 4490, 2914, 3987, 5438, 1648, 5270, 2903, 3379, 3369, -873, 5512, 2931, 3175, 1822, -2892, 5008, 2496, 1168, 220, -3019, 3421, 1830, -4198, -2965, -1917, 2406, 1767, 2827, 1174, 509, 4688, 2281, 4282, 2522, -37, 5930, 2738, 4040, 2101, -5544, 6003, 2823, 2793, 766, -3529, 5412, 2160, 1395, -503, -2334, 4763, 194, 657, -1395, -5836, 4156, -4541, -263, -2714, -6537, 2816, -3596, -1707, -728, -2451, -1709, -784, 231, 1996, -855, -251, 214, 1987, 2531, 152, 3082, 342, 2359, 300, 813, 3486, 164, 1775, -2561, 1035, 2136, 271, 621, 2147, 408, -696, 702, -1360, 3150, -1099, -2018, 944, -8521, 3171, 847, -1162, 473, -2446, 3282, 2751, 143, -1128, 31, 3279, 2878, 1415, -2750, 35, 2765, 1139, 2366, 390, -2352, 1736, -3317, 2803, 2860, -7559, 611, -4770, 2225, 4179, -3502, -87, -5472, -484, 4644, -5787, -1006, -3457, -4922, 4405, -4343, -2748, -1305, 943, 3514, -212, -2991, -843, 2521, 2064, 748, -836, -1403, 3056, 516, 233, 886, -1366, 2921, -400, -794, 2005, -3, 1891, -1284, -1647, 2547, 456, -449, -3947, -3161, 2391, -251, -4949, -10357, -2631, 1181, -1484, -7207, -6178, -821, -2308, -2560, -5659, -11313, -580, -5646, -2848, -3473, -2267, -1680, -967, -2630, -2106, 56, -3239, -401, -3008, -2384, 407, -4374, -1663, -3304, -4877, -627, -4487, -4751, -4659, -9247, -2585, -2020, -9640, -8211, -5383, -3012, -327, -11648, -2926, -5704, -2565, 378, -6753, -1507, -7532, -3347, 483, -4807, -2080, -3945, -4303, 264, -4548, -4391, -2012, -3684, -187, -4851, -6521, -1326, -3289, -980, -4349, -5678, -1515, -2131, -2063, -3427, -6038, -2768, -864, -2668, -2829, -7045, -6107, -792, -2995, -2743, -6596, -12351, -2175, -3964, -3177, -5050, -7948, -4977, -3998, -3949, -3822, -7796, -6941, -3381, -4913, -3246, -4481, -7580, -4051, -6255, -3220, -2724, -7102, -5431, -6488, -3589, -2407, -5400, -5885, -4847, -4463, -2929, -4341, -6888, -4257, -6679, -3643, -3892, -5181, -5014, -18357, -3975, -4023, -3273, -6397, -5969, -4322, -4631, -3067, -6547, -3801, -5631, -4851, -4139, -5174, -3317, -8692, -4473, -5120, -3951, -3770, -9338, -4609, -5421, -3673, -4699, -8021, -5558, -6945, -4439, -5838, -9140, -6951, -8590, -6337, -7444, -14789, -8155, -6678, -9408, -9408, -12676, -8249, -5398, -12206, -9098, -11849, -6063, -4893, -14348, -8102, -14796, -3920, -5688, -8043, -8041, -11395, -3023, -9351, -5778, -8808, -9526, -3716, -11085, -4731, -10442, -9287, -7182, -8530, -3985, -15913, -9585, -9185, -10307, -3460, -10567, 6844, 8184, 3420, 5950, 6590, 5716, 7520, 2915, 5650, 5578, 1323, 5655, 1526, 4481, 1420, 2109, 4602, 938, 2294, 15, 4468, 5518, 3231, 2469, 3187, 5793, 5964, 4592, 3694, 3339, 6224, 5655, 4528, 4454, 2352, 5057, 4221, 3430, 5324, 971, 1833, -301, 2190, 5579, 373, 2644, 850, 1098, 4721, 980, 4056, 3616, -1585, 2925, 537, 4012, 4156, -3087, 1117, -3988, 3210, 4093, 1451, -2670, -2487, 1519, 3634, 2380, -613, -810, -2387, 2590, 568, 2761, -6471, -488, 1010, -5312, 3534, 340, 1823, -1565, 1888, 3010, 3257, 1775, -3382, 3422, 2002, 4252, -685, -951, 3397, 1173, 4308, -3154, 168, 2609, -479, 3921, 1052, 588, 1830, -3238, 3553, 2378, 610, 1794, -208, 3373, 2364, 113, 2254, 1288, 3176, 1322, -1241, 2383, 1270, 2722, -950, -4485, 1628, 102, 1826, -5666, -8227, -513, -1899, 410, -4133, -3782, -6552, -905, -1388, -2513, -747, -3604, 1420, -3010, -3860, 972, -216, 2714, -628, -2463, 1139, 963, 3132, 1691, 105, 357, 731, 2731, 2376, 650, 659, -968, 1401, 1577, -86, 1151, -5024, -280, -273, -1284, 615, -7242, 329, -1523, -2322, -285, -1319, 1239, -3131, -4030, -1557, 1273, 1204, -2623, -4930, -4765, 2533, 382, 31, -3846, -2702, 2810, -1149, 1031, -2436, -2306, 2244, -3404, 1046, 817, -8994, 1047, -4395, 638, 2113, -1506, 182, -2293, 232, 1249, 408, 245, -443, 303, -2615, -457, 2, 388, 1146, -1225, -3270, -964, 114, 1823, 69, -1130, -1849, -1146, 1661, -1202, -555, -1365, -2727, 687, -4664, -2784, -860, -4224, -719, -8293, -6623, -1237, -5927, -2521, -5505, -3504, -1674, -4074, -4433, -3443, -3662, -1029, -1584, -4872, -3436, -5480, -604, 87, -4061, -6831, -6373, -954, 895, -2930, -4665, -5970, -1481, 869, -3005, -1678, -6194, -1725, 102, -4007, -1213, -7330, -2515, -1336, -4220, -2492, -4365, -4748, -3634, -3468, -6231, -2036, -8618, -7015, -2416, -10932, -1345, -8476, -5322, -2055, -7350, -2131, -10709, -3277, -3007, -7164, -4938, -10398, -2347, -5087, -6032, -11826, -6451, -1985, -5375, -5476, -6386, -5870, -1782, -5321, -6190, -5095, -7148, -1297, -6906, -7337, -4828, -9918, -793, -7903, -6343, -5432, -7696, -862, -6090, -4809, -7046, -5531, -1731, -4551, -4415, -5858, -5221, -3339, -4088, -5435, -4033, -6463, -4688, -4882, -8282, -4049, -8560, -3891, -6749, -9165, -6707, -8658, -2887, -8564, -7138, -10402, -6502, -2670, -9858, -6370, -4903, -4838, -3343, -10015, -6338, -3947, -4444, -5240, -7141, -7775, -4739, -5188, -6116, -4346, -12681, -6528, -6728, -3824, -2500, -6372, -8095, -9228, -2730, -1680, -4190, -7241, -11071, -2502, -1914, -3767, -4542, -8579, -2851, -3341, -4537, -3365, -7100, -4257, -5807, -6160, -3938, -6677, -8386, -5363, -6487, -5417, -4831, -5399, -3595, -6606, -5220, -4098, -3955, -2996, -6791, -5518, -4339, -2958, -3813, -5029, -4855, -6573, -2456, -5830, -3627, -3990, -10242, -2583, -6572, -3503, -3955, -5694, -3498, -5733, -4531, -4720, -4080, -4973, -6642, -6336, -5565, -3660, -5397, -11244, -7572, -5403, -3796, -4399, -9624, -6943, -4976, -4501, -3341, -7751, -6284, -4998, -6524, -2623, -7953, -6400, -5125, -13720, -2499, -7962, -6581, -4922, -9675, -3201, -6947, -6428, -4554, -8044, -5125, -5239, -7512, -4496, -6154, -8552, -3600, -12902, -5097, -3938, -6733, -2506, -12785, -7219, -2296, -6245, -2448, -8098, -6875, -793, -7453, -4342, -2270, -1398, 579, -2516, -2953, 237, 929, 1489, 27, 266, 986, 1584, 1656, 936, 1345, 322, 829, 893, 681, 786, -1675, -1400, -934, -484, -1650, -4605, -5233, -3661, -2148, -8273, -7098, -7983, -5542, -3463, -6495, -9317, -6325, -6176, -3798, -6445, -10349, -4891, -7107, -3570, -7094, -11108, -4375, -7870, -3322, -4857, -10823, -4363, -8390, -3422, -3691, -7608, -4723, -10417, -4252, -3535, -5257, -5565, -11499, -5773, -3891, -4566, -6740, -9103, -6320, -4558, -5707, -7907, -7989, -6022, -5807, -10570, -8858, -6677, -6372, -7130, -8773, -8440, -6381, -6672, -7034, -6078, -8636, -9076, -6136, -7177, -5651, -8736, -9553, -5450, -7590, -6840, -7336, -5381, -5011, -6630, -14294, -7488, -4801, -4871, -5848, -6136, -10098, -6286, -5008, -6046, -3235, -11529, -8986, -5317, -6412, -2186, -7462, -8587, -5614, -5608, -2127, -5546, -5993, -5602, -4895, -2768, -4953, -3879, -5369, -5200, -4091, -5580, -3164, -5477, -6772, -6470, -7886, -3903, -6183, -9649, -11308, -9200, -6437, -7719, -8945, -10678, -6182, -9302, -11853, -7614, -9572, -5189, -7009, -10482, -7855, -10849, -5754, -6670, -7654, -7960, -10133, -8021, -8450, -7492, -6982, -9424, -10234, -15495, -8411, -6733, -10228, -7509, -11577, -8767, -7567, -9477, -6263, -9487, -9857, -8789, -7763, -6036, -8615, -16894, -9219, -6594, -6453, -7945, -10252, -9583, -5649, -7061, -7302, -7813, -10419, -4963, -7236, -6595, -7004, -10903, -4924, -7947, -6179, -6655, -10453, -5878, -10923, -6142, -6372, -9527, -7202, -14480, -6401, -6149, -9032, -6310, -9481, -6657, -5984, -9602, -5378, -7495, -6427, -5769, -9697, -5650, -6850, -6403, -5592, -7339, -7131, -7150, -7731, -5749, -5664, -8298, -6849, -11449, -6429, -4910, -7086, -6298, -10534, -7720, -4908, -6514, -6999, -10839, -9769, -5924, -6860, -9561, -13612, -11400, -9204, -6920, -14357, -8162, -11150, -11068, -6493, -12766, -6878, -13047, -6942, -6884, -9274, -7453, -15660, -5989, -8558, -7535, -9432, -9547, -6401, -9898, -7434, -14187, -7718, -7893, -9707, -8867, -13166, -7538, -10498, -11141, -10755, -9815, -8900, -12875, -16967, -9262, -9781, -12291, -11937, -15404, -8060, -13327, -13354, -9920, -12630, -7888, -12745, -11948, -8216, -10002, -7989, -8788, -11573, -7404, -9210, -6686, -15004, -3289, -6328, -7919, -10176, -10887, -3489, -4414, -6566, -8259, -9697, -4196, -4142, -5503, -5290, -11864, -5981, -5954, -4598, -5677, -11430, -11060, -14555, -3737, -8789, -6780, -7117, -8086, -3108, -8413, -5414, -4226, -8755, -3056, -6295, -5370, -2921, -10658, -3642, -5938, -5817, -2362, -5959, -4464, -6230, -6351, -2305, -4802, -5318, -5661, -7355, -2605, -4648, -6030, -4788, -8877, -3153, -4318, -5904, -4916, -9187, -3968, -3807, -6158, -6283, -7416, -4581, -3478, -7312, -8938, -5776, -4128, -3614, -8987, -8870, -4994, -3576, -4325, -11480, -8343, -4380, -3152, -4685, -5002, -9948, -2766, -2348, -3502, -1091, -2435, -586, -914, -1095, 924, 162, 874, 420, 766, 1496, 868, 1184, 908, 1411, 666, 95, 131, 390, 762, -1920, -2085, -2922, -845, -1280, -7756, -4454, -16110, -1966, -4698, -6715, -3873, -5983, -2930, -5724, -6404, -2975, -5321, -4831, -4148, -8149, -2771, -6242, -8405, -2985, -11642, -3082, -7557, -10505, -2280, -10096, -3383, -5472, -15643, -2315, -5910, -3512, -4542, -9302, -3544, -4161, -4119, -5871, -6931, -7014, -3807, -6345, -9365, -7016, -10307, -4311, -9961, -7929, -7821, -5691, -5163, -6055, -8191, -8082, -4467, -6171, -4793, -9507, -9009, -4679, -7184, -4796, -7642, -11541, -6390, -7723, -5518, -7267, -10546, -7902, -8212, -6977, -8316, -7941, -5667, -8984, -8527, -8988, -6911, -4411, -8643, -6370, -8980, -7105, -3989, -8007, -4233, -8228, -7891, -4022, -8794, -3315, -6300, -7934, -4546, -11341, -3481, -5193, -7635, -5755, -12427, -4738, -5205, -8025, -8019, -10792, -7259, -5891, -8796, -13258, -7564, -11530, -6159, -9580, -11920, -5757, -17389, -5882, -11718, -8114, -5523, -15594, -6008, -10143, -6180, -6780, -17090, -6855, -7510, -5038, -8817, -11814, -7704, -6483, -4638, -7888, -8637, -7401, -6001, -5064, -6890, -6993, -7147, -5609, -6385, -7082, -6207, -7481, -5691, -7961, -8353, -5988, -7837, -6738, -7876, -11189, -5943, -7604, -9331, -7787, -19199, -5825, -7175, -12307, -8505, -11676, -5962, -6404, -9173, -8273, -9909, -6757, -5111, -8220, -8439, -9529, -8310, -4397, -8781, -9601, -10027, -9518, -4853, -9488, -6396, -11585, -8235, -6822, -10060, -4537, -9577, -6889, -10416, -8115, -4244, -7183, -6916, -8712, -5559, -5065, -6404, -7819, -6786, -4732, -6745, -6723, -6229, -6014, -5754, -8068, -7727, -4706, -6080, -9574, -6889, -9382, -4416, -6628, -7227, -5957, -10909, -4928, -6618, -5124, -6000, -10310, -5733, -5841, -5155, -6098, -9824, -6774, -5344, -7076, -5466, -9382, -8830, -5583, -13008, -5116, -9364, -14598, -6627, -10457, -5703, -10925, -13134, -7897, -9338, -7078, -17766, -11047, -8228, -10926, -7312, -12329, -10043, -8854, -14096, -6377, -9246, -8903, -12360, -12308, -6179, -7824, -7904, -11876, -9138, -6918, -7406, -6685, -7622, -7962, -8100, -8250, -5658, -6581, -8677, -8669, -11653, -5213, -7600, -11726, -9502, -6275, -7459, -7000, -6470, -3903, -4611, -8854, -5266, -3553, -3567, -3870, -4951, -3609, -2416, -4242, -4366, -4804, -3320, -2270, -5967, -6275, -6972, -4166, -3256, -8507, -10171, -12115, -5676, -6261, -8439, -11299, -12043, -7006, -8492, -5927, -10517, -10697, -7794, -4872, -3723, -11855, -6608, -8993, -3744, -2358, -13710, -4703, -11678, -3516, -1921, -10297, -4260, -14057, -3549, -2336, -7447, -5051, -12593, -3527, -3366, -6283, -7371, -9834, -3390, -4634, -6581, -9859, -7409, -3297, -5936, -8880, -6768, -5974, -3285, -6690, -13443, -5505, -5455, -2978, -6634, -11797, -7806, -6402, -2254, -6693, -7806, -5050, -6959, -1229, -6141, -2174, -264, -2380, 89, -2592, 260, 1781, 74, 1016, -20, 921, 2414, 1007, 941, 1072, 9, 1957, 705, -553, 924, -2636, 564, -799, -4597, -202, -5387, -1546, -3587, -7025, -1771, -6066, -3644, -7205, -3911, -3331, -9450, -4568, -8048, -3349, -4854, -7175, -5245, -7936, -3646, -6327, -6008, -6570, -8861, -4621, -11767, -7183, -7459, -9946, -5893, -6739, -11369, -7622, -9559, -5931, -3608, -13936, -8468, -8911, -4742, -2750, -10183, -10097, -8682, -4374, -2987, -9181, -8548, -8794, -5678, -3069, -8990, -5410, -10167, -9059, -2481, -10011, -3681, -11519, -7713, -2240, -12961, -3158, -7402, -7225, -2629, -14315, -3664, -4975, -8061, -3591, -8715, -5158, -3513, -6182, -5211, -6693, -7881, -2674, -4835, -7763, -6634, -13779, -2476, -4538, -10107, -9065, -12637, -3083, -4685, -6531, -13953, -9700, -4730, -4943, -4833, -7463, -8389, -7154, -5426, -5212, -5979, -7985, -7362, -6888, -8907, -5809, -8836, -7039, -10232, -9569, -6110, -10164, -7723, -6606, -5848, -6181, -8551, -9132, -4796, -5085, -5711, -7127, -12411, -5076, -5321, -5106, -7060, -8607, -7079, -7071, -4767, -8634, -5752, -7579, -8468, -4796, -9544, -5016, -6526, -4435, -5263, -7770, -5677, -6851, -2722, -6394, -7830, -5973, -6828, -2351, -7826, -8200, -4993, -5965, -2867, -7129, -6373, -4708, -5973, -3666, -6375, -5292, -5314, -6838, -3734, -7316, -5384, -6269, -7531, -3386, -10330, -6284, -7143, -7886, -3446, -9316, -7264, -8282, -7969, -3961, -8354, -7454, -9326, -7048, -4575, -9967, -6846, -9308, -6015, -5682, -12094, -6182, -9574, -5562, -8455, -10098, -6251, -8823, -5788, -7933, -10115, -7438, -7179, -5798, -6256, -12729, -9670, -6641, -4424, -6670, -16869, -11702, -7349, -3136, -8626, -11379, -12571, -8894, -2706, -10776, -9858, -12632, -10360, -3202, -9852, -9656, -14351, -11892, -4516, -8120, -10112, -9196, -14718, -6029, -7326, -11073, -6167, -20010, -7015, -7571, -13288, -4933, -16628, -8164, -8158, -15866, -4808, -13887, -8859, -8671, -13006, -5320, -12181, -7866, -10275, -11071, -5975, -11702, -6915, -13457, -9700, -6806, -12271, -6528, -11149, -8831, -8396, -13721, -6934, -8250, -8454, -9442, -13972, -9042, -6740, -8719, -7705, -11615, -17335, -6696, -9993, -6648, -9134, -8087, -7929, 11499, 9653, 11787, 11865, 10918, 10750, 9748, 11068, 11240, 10364, 8109, 9531, 8698, 9336, 8658, -392, 8420, 3495, 6224, 6048, 4468, 6188, -2829, 2992, 4944, 4836, 2886, -1034, 852, 4834, 3423, -314, 929, -354, 3400, 2873, -1496, 1653, 65, -323, 689, -2183, 2935, 767, -6658, -226, -1673, 3889, 816, -6654, 5189, 544, 3523, 1694, 727, 7001, 1280, 3374, 3183, 4394, 7543, 2819, 4609, 4414, 6201, 7338, 5335, 5343, 5008, 6784, 6524, 6594, 5248, 4727, 6186, 4964, 6532, 4685, 3373, 4034, 2635, 5338, 4042, 439, -1698, 1519, 3675, 3143, -3463, -868, 1737, 2813, 1237, 612, 987, 1363, 2305, -3363, 2166, 1556, 1643, 2080, -5536, 2433, 1979, 2425, 2309, -3356, 2424, 956, 2375, 2323, -5877, 2676, -9137, 1643, 1847, -2948, 2781, 1636, 1445, 565, -278, 2290, 4161, 1827, -51, 118, 1184, 4603, 2057, 2119, -766, 999, 3517, 1918, 3192, -1961, 1741, 351, 1084, 2772, -5075, 1823, -9009, -3, 1315, -3513, 1715, -3156, 754, 666, -1, 2060, -6758, 1223, 3, 894, 2448, -4417, -629, -2904, 789, 2644, -1501, -4193, -1362, 779, 2463, -342, 741, -280, 657, 1614, 444, 1940, -2432, -386, 302, 300, 1661, -5600, -2648, -116, -1426, 728, -517, -5816, 42, -8691, -478, 1020, -5590, -492, -2680, -2624, 1193, -3778, -1788, 222, -9612, 248, -3523, -2310, 1328, -4828, -1791, -4731, -1546, 1500, -3774, -4803, -6916, -1462, 950, -6641, -4848, -8218, -1770, 222, -7771, -1963, -6686, -921, 557, -3923, -756, -4622, 123, 1229, -2846, -872, -3909, 554, 1169, -2433, -1846, -5745, 413, 243, -2080, -2755, -6614, -278, -1394, -1921, -2331, -1802, -1389, -2957, -2013, -1209, -272, -2419, -2893, -1213, -627, -236, -2201, -2356, -14, -707, -987, -752, -2093, 439, -940, -1989, 234, -1770, 82, -885, -3121, 317, -1690, -747, -680, -4513, -297, -2330, -1287, -546, -7327, -631, -3621, -1505, -658, -4254, -147, -4817, -2767, -1298, -1704, 213, -5047, -6312, -2616, -1171, 99, -4591, -4520, -3856, -2233, -602, -4570, -3047, -4603, -5501, -2062, -4365, -3248, -5468, -13943, -3893, -2743, -3891, -4549, -8014, -5236, -1218, -3439, -4507, -10182, -5271, -339, -2017, -6499, -6396, -3095, 51, -1278, -5234, -4433, -1926, 180, -1582, -4112, -5251, -1997, 117, -3012, -4723, -5486, -2358, -140, -6067, -5077, -2875, -2262, -540, -4332, -4377, -2761, -2777, -1175, -1347, -4245, -6137, -3431, -2252, 198, -5646, -2423, -1844, -3110, 896, -10059, 0, -490, -2063, 662, -7959, 293, -39, -1037, -1028, -5465, -943, -84, -1061, -5569, -3676, -3524, -278, -2353, -4143, -3071, -6214, -1188, -5856, -2726, -4220, -11237, -4123, -9832, -3171, -6078, -4947, -2949, -10897, 1986, 7534, 7994, 8395, 5655, 1586, 6803, 7469, 7696, 4993, 986, 4683, 6042, 5302, 3663, 1176, 4020, 4165, -290, 3540, 1354, 5071, 1972, 1624, 3711, 1165, 4944, -498, 2650, 3436, 1305, 3929, -780, 2245, 3125, 2022, 2784, 1021, 1914, 2896, 2842, 2606, 2544, 1909, 2503, 3458, 2577, 3509, 1162, 2278, 4319, 2777, 4320, -1679, 3341, 5631, 4337, 5485, 591, 4894, 6571, 5188, 6487, 2665, 5846, 6695, 4848, 6546, 2448, 6016, 6031, 3962, 5257, 374, 5518, 4941, 3891, 1946, -1263, 4519, 4092, 3892, -9767, -732, 3047, 3742, 2274, -3403, 28, 1256, 3246, -4496, -6805, 1456, 9, 2179, -172, -5004, 2240, -1027, 1634, -109, -3777, 2227, -2661, 1529, -2955, -4061, 1781, -4333, -54, 227, -4123, 1286, -2738, -3606, 548, -7285, 702, 202, -2746, -36, -1668, -116, 2048, -502, 1178, -760, 320, 3206, 1792, 1855, -4693, 1439, 3944, 3000, 1660, -2152, 1418, 4259, 3060, 927, -29, -23, 4053, 2125, -517, -1139, -1610, 3269, 301, -1313, -3676, -661, 1878, -2420, 858, -3865, 454, -397, -6488, 1913, -3258, 1317, -4907, -6205, 1205, -992, 1933, -2414, -2780, -2487, 70, 2028, 163, -680, -3970, 142, 1003, 843, 334, -195, -40, -3085, 301, 112, -43, -188, -1548, -1011, -1459, -1898, -666, 1611, -2204, -1343, -6526, -1699, 2298, -2599, 591, -7144, -2901, 1715, -1844, 1237, -4046, -3598, 179, -140, 759, -2406, -3075, -2445, 1180, -335, -1952, -1899, -5612, 1415, -1094, -2214, -1360, -1893, 203, -1459, -1069, -1757, 481, -3330, -2097, 752, -2767, 1624, -7473, -1792, 1782, -2900, 1889, -7712, -101, 1912, -2068, 1430, -5585, 1149, 1283, -1498, 397, -866, 1524, 568, -963, -1106, 495, 954, 497, -188, -3461, -19, -412, 139, 324, -10632, -2949, -900, -1303, -35, -4678, -7384, -163, -3549, -1866, -2417, -2039, -90, -4801, -7138, -2238, -767, -899, -3789, -5957, -2726, -570, -2445, -1632, -2991, -2995, -898, -4903, -717, -1806, -1742, -1512, -8493, -1379, -1798, 585, -1549, -5539, -3625, -3504, 1770, -763, -3517, -3105, -8456, 1591, -119, -3114, -1345, -7055, 92, -21, -4398, -782, -9520, -2433, -808, -6538, -902, -6864, -4298, -3229, -2854, -1191, -3592, -3995, -7376, -1294, -667, -3069, -3510, -3439, -1592, -26, -2002, -4369, -1857, -2227, -397, -443, -3309, -1476, -1091, -2056, 221, -1094, -2369, -668, -4218, -5, -716, -6260, -1626, -3114, -970, -2628, -5218, -2561, -1129, -2134, -2523, -2555, -2529, 148, -2205, 324, -2183, -3484, 433, -2391, 994, -2104, -4388, -687, -4433, -147, -1845, -2974, -4487, -13025, -4452, -1215, -1607, -5702, -5079, -4621, -8, -769, -2473, -2682, -1284, 552, -657, -1852, -1952, -775, -338, 3403, 4132, 7641, 778, 5289, 2552, 4145, 7421, 2383, 6068, 4670, 4212, 7130, 4931, 6997, 6328, 4373, 6985, 5898, 7176, 6003, 4155, 6359, 5214, 6490, 3584, 2785, 4682, 2921, 4968, -3986, -778, 1301, -742, 3260, -539, -3989, -6344, -2274, 2502, -875, -1955, -2882, -434, 1798, -3591, -1851, -1994, 1043, 958, 3027, -70, 38, 2360, 1125, 5424, 2700, 1757, 2968, 1329, 6100, 4469, 1807, 2654, 1037, 5305, 4858, -175, 2820, 2749, 2728, 3599, 755, 3658, 4815, -3318, 76, 2620, 3579, 5670, -6116, 599, 2350, 2258, 5308, -2952, 1593, -76, 344, 3740, -1295, 197, -7631, -293, 1431, -414, -2083, -4705, -32, 454, 1193, -1037, -2916, 140, -87, 2307, -23, -1998, -320, -18, 2491, 240, -1222, -2065, 924, 1975, -38, -567, -6414, 1177, 977, -812, -86, -2158, 1569, -272, -2074, 62, 217, 2576, -712, -3867, -198, 1022, 2926, -117, -3578, -924, 905, 2160, -125, -1289, -2054, 12, 982, -1563, -215, -2503, -1765, 993, -6099, -47, -1659, -4728, 1308, -6373, -203, -670, -5335, 1637, -2661, -739, 229, -3261, 1850, -1322, -2303, 947, -1527, 1748, -928, -5554, 1239, 616, 2135, -1827, -11079, 834, 2152, 2999, -5832, -6189, -473, 2630, 3320, -3403, -2728, -1400, 2094, 2477, -572, -1483, -13, 1139, -474, 25, -1786, 1043, 931, -2991, -845, -3318, 1407, 776, 1042, -2630, -4489, 1405, -256, 2424, -987, -2810, 1333, -2287, 2747, 512, -1553, 1549, -5824, 2282, 279, -2049, 1871, -3869, 900, -1724, -5113, 1702, -1201, -1600, -2784, -3388, 568, -172, -2220, -895, -1663, -2290, 292, -362, -418, -2568, -9930, 580, 503, -1227, -7070, -2603, 429, 437, -2729, -5947, -436, -295, -560, -2611, -3597, 571, -1311, -2955, -1634, -2500, 779, -2367, -6798, -1580, -1228, 83, -3626, -2730, -1961, -159, -1607, -4533, -689, -1789, 222, -2814, -4019, 358, -1588, -452, -1013, -4088, 995, -2319, -2726, 767, -6820, 974, -4507, -8398, 1631, -11130, -303, -2578, -6953, 1518, -6724, -3262, -327, -6716, 421, -8780, -1524, 193, -8230, -1594, -5833, 225, -690, -4076, -3241, -2524, 550, -3379, -1911, -2869, -975, 320, -6486, -1262, -3444, -392, -71, -2338, -1737, -7273, -902, -761, -805, -3112, -5322, -3132, -1739, -753, -4756, -3052, -3407, -2524, -1795, -7989, -2173, -957, -2388, -3114, -6050, -1001, -97, -1763, -3563, -1277, -227, -19, -1780, -4053, 280, -333, -629, -3246, -5652, -96, -1690, -2562, -4260, -11515, -3068, -6057, -6844, -1570, -6403, -7864, -5955, -5304, -902, -3614, -3309, -3410, -4326, -2882, -2501, -2023, -1490, -3336, -7164, -1740, -36, 312, -1321, -2026, -1151, 996, 668, -883, -890, -1372, 643, -586, -3064, -910, -3402, -4482, -2190, -1270, -4262, -3070, -4590, -2040, -2520, -946, -3274, -9669, -4249, -9697, -56, -3661, -5978, -4859, -3848, -493, -3439, -3542, -2771, -1509, -504, -3120, -3970, -2516, -560, 163, -2938, -6862, -2398, -958, 411, -2723, -11590, -1025, -3975, 1108, -3014, -6531, 310, -5335, 1975, -3553, -4511, 957, -1340, 1873, -3638, -4597, 887, -704, 258, -5787, -7724, 248, -1979, -4020, -5723, -4889, -576, -6030, -5557, -1752, -1896, -1048, -5583, -3021, -961, -879, -994, -2977, -1828, -2324, -1161, -756, -2567, -894, -8329, -3006, -890, -3048, -336, -2419, -12398, -1434, -2230, 342, 771, -2734, -174, 527, 1344, 2390, -223, 1634, 2317, 2073, 3055, 210, 2246, 2721, 1891, 2870, -912, 1627, 1673, 245, 1928, -3573, -115, -1050, -3564, 507, -6432, -3262, -4038, -2351, -1054, -6372, -8754, -4753, -938, -2769, -7193, -2761, -4473, -1032, -3845, -10328, -1095, -2632, -1692, -3653, -2631, -1126, -2259, -2446, -3893, -256, -2771, -3310, -2791, -4961, 361, -8126, -5707, -2611, -5749, -245, -7360, -6102, -2940, -5490, -1830, -6736, -4501, -4546, -5568, -4055, -6866, -4259, -6523, -5735, -6537, -2456, -3944, -4694, -5152, -6281, -791, -2729, -3326, -5147, -4384, -636, -1952, -3614, -6397, -3150, -1511, -1616, -7073, -4951, -2081, -2980, -1332, -7338, -2755, -1670, -4406, -1259, -3640, -1452, -2662, -5710, -1451, -3615, -261, -5548, -7769, -1585, -5654, 706, -3476, -12844, -1737, -4974, 1109, -1569, -10018, -2414, -4155, 931, -1372, -8834, -4007, -7511, 348, -2417, -19835, -6770, -5193, -391, -4759, -5253, -7132, -1173, -1144, -7689, -1769, -4823, 228, -1928, -6624, -170, -3580, 522, -2723, -5276, 133, -3197, 312, -3832, -5133, -786, -3275, 86, -6741, -5275, -2979, -3246, -15, -9085, -3240, -6076, -2781, -346, -4076, -2116, -6898, -1822, -1476, -2444, -2481, -5099, -863, -3556, -1673, -3676, -3843, -402, -3266, -1569, -4468, -2131, -551, -2215, -3039, -4968, -340, -1284, -2389, -8551, -5841, 652, -2084, -3633, -3304, -6153, 803, -1768, -9006, -1361, -4735, 202, -833, -4478, -1044, -3627, -1151, -16, -1493, -1415, -3147, -3442, 294, -1194, -2076, -3305, -6063, -281, -2926, -2664, -4702, -3915, -1898, -6565, -2405, -6927, -2282, -3991, -4178, -1692, -5166, -2072, -5567, -3102, -1571, -4346, -2848, -8095, -4080, -2244, -5297, -3728, -11771, -6981, -3029, -8705, -3791, -10247, -6713, -3057, -9979, -3672, -6229, -4608, -3131, -5419, -4169, -4738, -3996, -4066, -3853, -5631, -5869, -5689, -6247, -3266, -7684, -20323, -11907, -7206, -2894, -8001, -5255, -3943, -5052, -2472, -5833, -3593, -2379, -3961, -2063, -4117, -4113, -2539, -3763, -1759, -4145, -4780, -3799, -3579, -1678, -7482, -3796, -5995, -3003, -2008, -6027, -3836, -9554, -3075, -3017, -2896, -5702, -14625, -1504, -2360, -3044, -1487, -4265, -3225, -3986, -9075, -3210, -4127, -2464, -6521, -5388, -6423, -916, -408, -6156, -3486, -9355, -571, 552, -4207, -4319, -8203, -1147, 569, -2249, -4905, -6750, -937, -72, -543, -2242, -4041, -863, -1216, 432, 114, -2699, -2014, -3629, 418, 1352, -3433, -2727, -10814, -681, 1366, -6282, -1958, -2590, -2952, -6, -3716, -2224, -513, -6937, -3433, -2625, -4043, -163, -7808, -13572, -3488, -9508, -1117, -3808, -5312, -4816, -6499, -2760, -1250, -3357, -2952, -2767, -2385, 163, -1731, -865, -1248, -1202, 216, -691, -552, -359, -1048, -1285, -1002, -3070, 1192, -999, -682, -3304, -1531, 2877, 478, 1448, -1240, 1840, 3908, 1324, 1752, 1094, 2880, 4142, 771, 68, 1497, 2483, 3577, -1142, -4927, 401, 872, 2279, -3574, -4789, -1818, -1422, 578, -4474, -4161, -2381, -2721, -792, -3274, -4035, -1915, -2841, -1498, -1655, -3202, -2845, -1530, -2122, -731, -4220, -4852, -346, -3911, -488, -8410, -3948, 17, -11601, -1054, -6930, -2428, -223, -4265, -3181, -5540, -1608, -827, -2590, -7168, -6787, -955, -1883, -2828, -1763, -8574, -293, -4050, -3295, 197, -4504, 297, -6437, -3468, 640, -2015, 398, -3753, -4356, 188, -1034, -732, -2281, -6113, -672, -1381, -4975, -1556, -7557, -1508, -2985, -3857, -829, -5404, -2414, -5159, -1358, 231, -3005, -3667, -5494, -1721, 1210, -1657, -2840, -4258, -4395, 1572, -946, -1003, -4242, -6830, 1068, -494, -228, -7851, -4250, -530, -338, -381, -6428, -3621, -3439, -768, -1361, -3066, -4154, -4575, -2020, -3706, -2565, -5873, -4091, -3450, -8764, -3454, -11360, -3994, -2473, -2757, -5121, -9430, -2536, -1171, -226, -6409, -6764, -1856, -666, 1078, -4370, -4805, -2973, -793, 1676, -2813, -3727, -5223, -1648, 1649, -2899, -4746, -2938, -3744, 960, -4358, -6558, -1958, -7719, -587, -4615, -3112, -2844, -8827, -3886, -3787, -1491, -5185, -4575, -6683, -4287, -1159, -6972, -1822, -2712, -6079, -1790, -7969, -556, -1786, -7156, -3885, -6150, -504, -1647, -6708, -10546, -3778, -1648, -662, -6693, -4053, -3151, -2948, 216, -6619, -2100, -4161, -2211, 7, -6241, -2150, -7819, -1901, -1619, -5625, -4201, -9236, -2125, -5359, -4772, -20035, -6203, -1695, -8961, -3936, -4620, -8137, -1423, -7771, -3168, -2625, -7866, -1884, -10407, -2637, -2134, -3678, -2511, -4562, -2875, -2186, -2574, -2759, -1385, -4470, -2603, -2829, -2964, -151, -5713, -3902, -4024, -2960, -285, -4488, -7391, -6273, -2378, -1600, -5924, -6123, -8840, -1575, -4013, -10024, -3258, -8351, -1241, -8567, -3585, -2348, -6904, -2097, -7621, -2694, -2456, -5419, -5432, -2881, -4705, -3130, -4781, -9225, -949, -11217, -3993, -5228, -5395, -421, -3792, -4698, -6520, -6366, -1110, -2417, -5091, -7604, -8282, -3182, -2698, -5569, -7999, -6149, -3058, -1149, -2782, -5494, -1655, -5423, -4878, -2823, -425, -4758, -4616, -5470, -3528, 1229, -4878, -3694, -2318, -7757, 1559, -807, -1796, -428, -3529, 926, 319, -670, 610, -1132, -507, -59, -806, 775, -582, -1285, -1894, -1604, -11, -1141, -280, -4756, -2209, -1942, -1683, 395, -4392, -3263, -5611, -859, 232, -5596, -6205, -10941, 8, -890, -9871, -9277, -6377, 262, -3581, -4485, -3242, -3582, -180, -7947, -3244, -492, -2391, -1929, -2648, -2125, 1089, -2467, -7535, -184, -1467, 1949, -3488, -1853, 927, -1118, 2048, -5434, -232, 1105, 12, 1109, -8568, -1789, 588, 134, -54, -1893, -2458, 90, -2350, 1154, 1134, 1625, 861, -2206, 1874, 2340, 2891, 1827, 813, 1064, 2174, 2645, 2115, 1368, -1399, 752, 1734, 1801, 465, -4924, -1875, 1555, 987, -998, -3232, -5678, 1800, -332, -737, -1065, -4665, 1480, -1490, 7, -36, -2542, 608, -1714, -508, 265, -2403, -86, -2104, -2181, 70, -4109, 53, -2358, -179, -995, -5926, 423, -1358, 1566, -3229, -3574, 424, -385, 1563, -2794, -2277, -289, 57, 211, -1662, -1919, -2226, 214, -608, -2548, -1864, -5770, 128, -489, -5510, -1845, -4538, -522, -1573, -2361, -2327, -3159, -2097, -2126, -19, -3712, -2801, -5200, -529, 895, -4192, -3067, -14878, 331, 844, -2237, -4676, -5338, 164, -106, -889, -10372, -2762, -871, -1700, -574, -4661, -1659, -1252, -2037, -1288, -1745, -1741, -415, -1122, -1881, -221, -2879, -431, -795, -27, 586, -2664, -1936, -1383, 1453, 760, -877, -5747, -3279, 1713, 230, 48, -9848, -6121, 743, -1223, 33, -6267, -4083, -1491, -4338, -683, -3873, -3319, -3890, -10951, -1470, -2171, -4353, -4587, -6234, -1877, -1456, -6665, -4400, -6122, -2562, -1490, -9262, -2215, -8824, -2936, -2028, -5486, -970, -12518, -1587, -2449, -3870, -1006, -5513, -81, -1884, -5070, -1852, -2270, 846, -1583, -9725, -2673, -446, 1035, -2785, -3642, -3626, 299, 384, -4071, -1697, -5615, 0, -845, -1718, -1073, -7410, -1367, -1028, -814, -935, -6894, -3471, -398, -1648, -916, -3548, -6133, -728, -4499, -965, -830, -6958, -2693, -7097, -1111, 409, -3086, -6713, -4160, -1165, 298, -1895, -3881, -2976, -907, -1067, -2241, -1851, -2797, -502, -2215, -3381, -910, -3517, -345, -1448, -4587, -507, -4985, -745, -742, -5417, -460, -4953, -1722, -290, -5442, -719, -2865, -2546, -433, -6672, -1408, -930, -2768, -1687, -15512, -2698, 113, -3871, -4079, -5756, -4240, 71, -8233, -6080, -4337, -4508, -951, -6482, -6111, -5045, -3690, -1837, -3879, -3679, -6100, -3119, -1430, -3633, -2205, -5399, -3187, -1123, -4720, -2134, -4594, -3773, -1525, -7034, -3457, -4808, -4327, -2954, -13724, -6477, -6667, -4058, -6774, -6851, -6498, -11831, -3388, -5873, 4533, 15493, 7130, 11099, 10872, 8971, 15079, 7409, 10372, 10215, 10477, 13792, 7275, 7939, 8110, 10115, 11471, 5974, 2071, 4093, 8807, 7904, 3893, -401, 596, 7640, 6406, 2632, 291, 246, 6353, 7830, 1705, 498, -2133, 5933, 8178, -99, 1669, -1466, 7015, 7495, -3209, 1380, 906, 6642, 5809, -2085, 420, 2649, 3011, 3101, 467, 890, 4060, 2610, 1239, 3134, 2438, 5095, 6134, 4168, 4923, 3666, 5672, 6390, 6574, 5504, 4339, 5666, 5175, 7432, 4771, 4364, 4716, 3611, 6811, 2487, 3671, 2068, 2734, 4441, 897, 2214, -1551, 1422, -1480, 1980, 145, 404, -1713, -829, 1479, -1429, -400, -2830, -620, -980, -1508, -4595, -937, -4509, -5950, -843, -3942, -436, -956, -3109, -86, -2002, -692, 253, -1534, 309, -1370, -1942, -1167, -2427, 197, -874, -4390, -7899, -2739, -461, -450, -4445, -2005, 564, -1706, -673, -4643, 937, 1953, -3334, -2247, -9197, 2447, 1896, -3203, -7384, -2865, 3140, 702, -1405, -4796, -1206, 3044, -1300, -192, -2152, -1597, 2136, -2908, 125, -1193, -3364, 442, -2540, -592, -655, -6300, -1686, -1452, -2733, -319, -2385, -3504, -1146, -6747, -114, 418, -6151, -1916, -7425, -50, 1525, -8056, -3061, -8010, -273, 1413, -4908, -3606, -8036, -740, 45, -4499, -3707, -9333, -1100, -3493, -4605, -2349, -7706, -1075, -5940, -4116, -1488, -4490, -1074, -2420, -4716, -2222, -4322, -1688, -1937, -7574, -5472, -7708, -3210, -2954, -9068, -8547, -8071, -5093, -4749, -6216, -4839, -4324, -4994, -4740, -5370, -4755, -3714, -4619, -3586, -5709, -6445, -4542, -5527, -3203, -6705, -7296, -6022, -7614, -3491, -7190, -5463, -5318, -7737, -3294, -6641, -3769, -3574, -6598, -2733, -6292, -2699, -2511, -6223, -3322, -7125, -2528, -1985, -6367, -6489, -9032, -3192, -1758, -6932, -10492, -10363, -3831, -1862, -7547, -5582, -7436, -3718, -2684, -7591, -4955, -4703, -3850, -5169, -7156, -5282, -3324, -4932, -15759, -6365, -5603, -2636, -7772, -5235, -5242, -5591, -2536, -7604, -3910, -4440, -5019, -3328, -4982, -4552, -4531, -4227, -5154, -4938, -6666, -5498, -4315, -7384, -6805, -10403, -6424, -6270, -8430, -6066, -14886, -5957, -8237, -9381, -4709, -7991, -4773, -6516, -15946, -5086, -4770, -4046, -7510, -8213, -7473, -3115, -3811, -5936, -6036, -13292, -2612, -3598, -3212, -6093, -7140, -2970, -3330, -2197, -7069, -5339, -3798, -3249, -2596, -7484, -4894, -4503, -3658, -4898, -7717, -5436, -4681, -5182, -7703, -9217, -6569, -4421, -10267, -4587, -15266, -5999, -3847, -8154, -4051, -14168, -5103, -3525, -4809, -5255, -9670, -5175, -3853, -3862, -7668, -5919, -5897, -4642, -4121, -8586, -4629, -7287, -5715, -5258, -7177, -5460, -9161, -7852, -7043, -6614, -7702, -10597, -16619, -8897, -6982, -6417, -13152, -8491, -8037, -7590, -5676, -7926, -5771, -7079, 8378, 264, 6883, 11011, 8143, 7556, 1695, 6137, 10467, 7604, 4780, 3511, 3566, 8760, 5905, -1905, 4481, 1645, 5576, 3317, -5876, 4662, 3831, 483, 3090, -657, 4234, 4030, 917, 3836, 2385, 3349, 2513, 2198, 3803, 3375, 2196, -346, 2695, 3488, 3584, 819, -176, 2702, 3452, 2746, 335, -412, 2651, 3857, 1787, 2832, 1422, 3444, 4373, 5252, 4678, 5194, 4458, 4573, 7185, 5288, 6970, 4627, 4164, 7558, 4889, 7263, 3451, 2960, 6666, 3846, 6129, 1351, 758, 4646, 2817, 2960, 2364, -3368, 1865, 2292, -15868, 3155, -5752, -564, 1822, -116, 2577, -2844, -2178, 610, -161, 1399, -2842, -3605, -1454, -690, 520, -2531, -955, -1400, -539, -353, -1441, 1152, -124, -2240, -2051, -868, 1843, 464, -11447, -4585, -824, 1495, 678, -1738, -5301, -1185, 281, 745, -280, -5586, -1797, -1825, 459, -992, -6544, -2607, -5670, -649, -4226, -6437, -4093, -9434, -2416, -5874, -4257, -7643, -4370, -1347, -2625, -2606, -5330, -3094, 283, -2130, -1978, -2963, -3396, 824, -3189, -1573, -2398, -5621, 448, -5830, -798, -2397, -12478, -642, -10395, -161, -1970, -5002, -2176, -11549, -242, -785, -3316, -4916, -7381, -1520, 502, -2597, -9442, -4302, -5125, 1082, -1579, -3107, -2656, -2112, 665, -1043, -2269, -1962, 1021, -494, -1698, -4389, -2045, 2453, -1441, -4094, -4653, -3063, 2833, -2423, -13200, -2195, -5171, 2263, -4770, -6279, -2685, -4206, 699, -11234, -4126, -5226, -2200, -889, -6141, -3336, -2471, -1746, -560, -3305, -3339, -1170, -2899, -506, -3067, -4504, -2083, -7249, -1161, -4422, -7364, -6452, -7606, -1149, -5031, -7721, -5413, -4786, -466, -5029, -5662, -2999, -6071, -230, -5115, -4645, -3330, -11883, -811, -4326, -4105, -5245, -6769, -2428, -3992, -4199, -6936, -6518, -5211, -4770, -5177, -5351, -9277, -5506, -7365, -5638, -2906, -9850, -3555, -18071, -4137, -2140, -6688, -2506, -11084, -3154, -3833, -4152, -2146, -9314, -3232, -7623, -2662, -2270, -6701, -4756, -2688, -2446, -2726, -5357, -10055, -1806, -3670, -3392, -5184, -7186, -3235, -6329, -4180, -5034, -5349, -8245, -7533, -4973, -4501, -5329, -6564, -8702, -5175, -4938, -4572, -3817, -13587, -3909, -6498, -3654, -2700, -8833, -2464, -4797, -3378, -2376, -7217, -1812, -3428, -3628, -2944, -6491, -2063, -3960, -3761, -4608, -6658, -3034, -6518, -2849, -6431, -8580, -3801, -7431, -2009, -6121, -16045, -3344, -5560, -2096, -5897, -10675, -2850, -5160, -3323, -6165, -8817, -3093, -5969, -6089, -6663, -8860, -4081, -8848, -13227, -7866, -10554, -5060, -9306, -10594, -9882, -12794, -4854, -5107, -7765, -7546, -9109, -4704, -3508, -6253, -4799, -6608, -5836, -3334, -5350, -3322, -5327, -9282, -4326, -4660, -2846, -5363, -7109, -5836, -3927, -3251, -7120, -4339, -5865, -3254, -4504, -9555, -3564, -5144, 1256, 8194, 9051, 8438, 6129, 650, 7937, 8480, 7806, 6110, 593, 6913, 6782, 5746, 5680, 1396, 4326, 4193, 1459, 4087, 699, -3885, 2269, -3077, 178, -1300, 2669, 2316, -3257, 1229, -395, 4207, 1878, -348, 2806, -745, 3878, -490, 2326, 2043, -6821, 2190, -9079, 2726, -404, 2215, 355, -1577, 2680, 1752, 5378, 1813, 1864, 4276, 4284, 6994, 4431, 3807, 5208, 5306, 7530, 5770, 4359, 4429, 4896, 6988, 5456, 3166, 388, 2751, 5161, 2708, -623, -360, 3728, 1734, -3842, 1396, 2724, 6103, -350, 2628, 2636, 1996, 6816, -647, 3185, 1600, -2459, 6482, -3023, 2185, -1368, -3164, 5709, -7149, 372, -6559, -756, 4888, -5411, -2287, -12196, -1359, 3713, -2871, -4511, -9419, -3677, 1748, -2653, -5209, -5848, -5567, -924, -4604, -8946, -3825, -3525, -2421, -15332, -4285, -2637, -2461, -1599, -5356, -2543, -1760, -1539, -2080, -2989, -3332, -1242, -553, -7473, -2254, -4298, -1333, 51, -966, -2558, -1966, -1802, 158, 1360, -3677, -1343, -2179, -240, 1463, -4227, -2395, -2938, -1199, -487, -3520, -3483, -4805, -2796, -7193, -2827, -3956, -7252, -5226, -2860, -2057, -5333, -12403, -8461, -1370, -1333, -4898, -4867, -4416, -1209, -1339, -4761, -1651, -1420, -763, -2458, -3962, -610, 30, -99, -4593, -2531, -997, 341, -220, -6698, -3370, -2282, -267, -1783, -5861, -10912, -1765, -1616, -2858, -4350, -3667, -232, -3596, -457, -4035, -2491, -17, -4169, 839, -4041, -4380, -1642, -2772, 1037, -3197, -3931, -6408, -1924, 423, -1948, -1864, -4142, -621, -571, -1301, -2064, -2997, 731, -961, -1589, -4497, -4267, 1250, -926, -2992, -8958, -8864, 917, -1474, -7457, -6750, -7896, 44, -2788, -5957, -6933, -5080, -899, -4510, -2528, -7146, -4167, -1538, -5667, -2113, -6172, -3159, -2182, -5590, -3646, -5813, -2198, -3796, -5537, -7502, -5014, -1999, -8334, -5487, -8382, -4255, -2704, -10080, -4584, -7250, -4315, -4114, -7922, -3508, -7169, -4759, -5307, -12536, -2807, -5831, -4859, -4921, -8245, -2569, -4107, -4743, -4018, -5103, -3040, -3088, -5043, -3730, -3963, -4918, -2810, -6461, -4368, -3629, -10136, -2912, -10574, -6007, -3890, -5810, -3042, -11332, -8360, -4947, -3876, -3399, -7554, -10480, -6989, -3516, -4362, -5965, -12544, -6735, -3533, -5859, -5315, -14505, -4827, -3209, -7345, -5893, -14616, -4171, -3017, -9808, -8271, -13590, -4636, -3677, -14120, -9644, -9215, -6100, -5605, -12666, -8331, -6548, -8048, -7381, -10863, -10016, -5139, -7709, -5938, -6204, -15211, -4551, -6454, -4807, -4875, -8887, -4491, -6128, -3721, -5659, -7500, -4682, -6747, -2556, -7675, -6139, -4864, -7890, -1964, -6667, -4402, -5188, -8256, -2320, -4996, -3710, -6703, -7762, -3806, -4001, -4335, -11670, -7648, -6396, -3930, -6030, -5334, -8387, -8283, -5021, -7927, -3020, -9673, -7495, -8041, -6548, -6351, -4577, -6923, -7329, -8284, -6631, -4061, -7063, -5307, -8390, -6378, -4222, -7515, -4424, -7435, -5524, -5190, -6242, -5340, -6891, -6092, -6443, -4482, -9412, -6512, -8504, -7151, -3780, -6509, -6541, -7944, -7748, -4030, -3881, -7323, -6572, -8041, -5028, -3184, -8845, -7005, -7553, -6481, -3803, -8940, -8206, -6558, -7744, -6040, -6500, -8761, -6037, -7925, -10519, -5080, -9533, -6506, -7240, -9368, -4760, -9287, -8232, -7063, -10010, -4792, -7236, -12589, -7486, -9919, -5057, -5658, -8648, -7374, -7534, -6010, -4564, -5838, -5932, -5664, -6665, -3232, -6002, -4453, -3240, -4373, -1650, -13290, -3202, -865, -1386, -185, -2610, -1208, 688, 185, 948, 143, 530, 1179, 389, 1454, 963, 1243, 482, -607, 1088, 355, 836, -1785, -2522, -295, -1720, -758, -8318, -4503, -2747, -4915, -3800, -5798, -5229, -5997, -5149, -7227, -3822, -5190, -8891, -5027, -5935, -4036, -5501, -11012, -5751, -5296, -5407, -5933, -14699, -6245, -5838, -7147, -5933, -7333, -6323, -7869, -6831, -5364, -5247, -6471, -12393, -6155, -4895, -4878, -6556, -8509, -6499, -4992, -5571, -6484, -6755, -7576, -5429, -6747, -6782, -6913, -8912, -5640, -6000, -7704, -8167, -8864, -5128, -4469, -8921, -8017, -6624, -4493, -4273, -9640, -7406, -5049, -4473, -5991, -9343, -7561, -4418, -5066, -13268, -8643, -6815, -4450, -5720, -8838, -8074, -5190, -4799, -5812, -7425, -8578, -3930, -4919, -5457, -8368, -10504, -3413, -4635, -5151, -10434, -8473, -3847, -4677, -5001, -14928, -6745, -5601, -5846, -4794, -13557, -6224, -9763, -9292, -4507, -10355, -6021, -7168, -9656, -4467, -9557, -6503, -4641, -8241, -5059, -8694, -8687, -3764, -11422, -6437, -8146, -8778, -3950, -7103, -7453, -9133, -6146, -5314, -4463, -7307, -13477, -5448, -8279, -4093, -8118, -10718, -6447, -8181, -5475, -10931, -8180, -10001, -7192, -8322, -15204, -7878, -10771, -9099, -7508, -16281, -8573, -8246, -11432, -6265, -15411, -7892, -8576, -7119, -6237, -10841, -6883, -9984, -5696, -6866, -8892, -7123, -7987, -5549, -7763, -7957, -8032, -6305, -6345, -8954, -7489, -7324, -5799, -7600, -10486, -7290, -6169, -5854, -7392, -9232, -7372, -5691, -6019, -6508, -7284, -7752, -5822, -6340, -6327, -6590, -8314, -6392, -7067, -6831, -6989, -8911, -6713, -8579, -7890, -7869, -9445, -6372, -10999, -9800, -7776, -9341, -6414, -10052, -11851, -7401, -8415, -7597, -8164, -10261, -8170, -7870, -9737, -7401, -10459, -10877, -8278, -9718, -7889, -16067, -13568, -9071, -9638, -9811, -10978, -12213, -8858, -12121, -9877, -8305, -12370, -8594, -13135, -9242, -7339, -8537, -8928, -9409, -11784, -6960, -6211, -9573, -8126, -11065, -7114, -5472, -10652, -8225, -8324, -8287, -5949, -10635, -9908, -8492, -11586, -7270, -8860, -15514, -11024, -18718, -8410, -7806, -11134, -12072, -14639, -8466, -7747, -8489, -10385, -18810, -8197, -8742, -7493, -9563, -13499, -2908, -6699, -7247, -4378, -5073, -3327, -10845, -5664, -6704, -5999, -5316, -12007, -4681, -6668, -8456, -11358, -7040, -4423, -5286, -14984, -5540, -5199, -5265, -5211, -8728, -3696, -4677, -7107, -6611, -6682, -3638, -5055, -7761, -13025, -6529, -4707, -5934, -7805, -8128, -7618, -5980, -6600, -9058, -5764, -8213, -6226, -6227, -8087, -6096, -7454, -6407, -5201, -6920, -7532, -7107, -6511, -4581, -7163, -6288, -7064, -6532, -4870, -6736, -5605, -7004, -7435, -6602, -5552, -6552, -6745, -7886, -12200, -5388, -7769, -6227, -6979, -6980, -5654, -7796, -5688, -6463, -4928, -6064, -6473, -4840, -4803, -5437, -11898, -3453, -2951, -2292, -4249, -3831, -573, -738, -575, -1265, -669, 1261, 600, -18, -52, 336, 1930, 743, -753, -352, -12, 1425, -450, -3087, -2171, -1392, -310, -3143, -7103, -6068, -3344, -3185, -5780, -7571, -8065, -5057, -5027, -6312, -6455, -6798, -6420, -4856, -6105, -4670, -7252, -9081, -4674, -4671, -4106, -7864, -13386, -4465, -4086, -5220, -8621, -10281, -4309, -4242, -8559, -9005, -10797, -4498, -4461, -7752, -8497, -7325, -5414, -4277, -5370, -7797, -5059, -7937, -3897, -4982, -6640, -4296, -11752, -3836, -6238, -6072, -4338, -6354, -4438, -6660, -6407, -4700, -4666, -5675, -4453, -7390, -5256, -4511, -6533, -3547, -8897, -6522, -4832, -6306, -4020, -11184, -10382, -4960, -6389, -5959, -13516, -10335, -6209, -7820, -11066, -12590, -6437, -14322, -12986, -10320, -10129, -5207, -6874, -10885, -6944, -7587, -4943, -4813, -8883, -5362, -5973, -5279, -5283, -7056, -4170, -5508, -6155, -8576, -4767, -3337, -6284, -7542, -11029, -3905, -3103, -7915, -10062, -6884, -4627, -3659, -6884, -16473, -5993, -7170, -5101, -5139, -8567, -5852, -10715, -7398, -4371, -6536, -5670, -11270, -10348, -4382, -5992, -5626, -18778, -9143, -5134, -5752, -6121, -9399, -6596, -6755, -5309, -7402, -6917, -5445, -8929, -5428, -9935, -6312, -5132, -10054, -7106, -10118, -6658, -5255, -9667, -13075, -7099, -6394, -5653, -7872, -8792, -5678, -5288, -6438, -6763, -7146, -5493, -4663, -7384, -6729, -7684, -6347, -4530, -7160, -7379, -9507, -7291, -4559, -6680, -8148, -11206, -6599, -4802, -7142, -8712, -10361, -5839, -5422, -8417, -9661, -8222, -5888, -6181, -9920, -13604, -6597, -6609, -6751, -11337, -11829, -5824, -7493, -7258, -12042, -7840, -5990, -8131, -7717, -10880, -6602, -7278, -8949, -8032, -9651, -6747, -10059, -10509, -8548, -9624, -8103, -13261, -12531, -9616, -10733, -10395, -12730, -10939, -9319, -11676, -10460, -12527, -9983, -8093, -10785, -9309, -12955, -10411, -7973, -9245, -8938, -13295, -9574, -8281, -8789, -9000, -9805, -9090, -8248, -9757, -9125, -7776, -10044, -8898, -9633, -9117, -7390, -9505, -10617, -8342, -8800, -8461, -8786, -12609, -8822, -8115, -10808, -10312, -19216, -11882, -7526, -10971, -18444, -11727, -11604, -7828, -9439, -10460, -9691, -10746, -10399, -8907, -8269, -10319, -6878, -9851, -2641, -8407, -6705, -6866, -10729, -3982, -6529, -7147, -5880, -8550, -8117, -5432, -9053, -5592, -6433, -7111, -4552, -9303, -5849, -4964, -5221, -3781, -6290, -6387, -3769, -5732, -3360, -4621, -6109, -2878, -8342, -3383, -4350, -4191, -2694, -9240, -3989, -5223, -3001, -3438, -6009, -5375, -6996, -3143, -5046, -4195, -6291, -10745, -4699, -6768, -3080, -5204, -10279, -7260, -7703, -2416, -4464, -6950, -7035, -7753, -2151, -4372, -6527, -6596, -7208, -2333, -4532, -8309, -8248, -6634, -3117, -4632, -15361, -9623, -5373, -4999, -4484, -9217, -6905, -4820, -12682, -4436, -6508, -6933, -4762, -5006, -3898, -3783, -3713, -1910, -1481, -1738, -1064, -643, 227, 177, -122, 543, 585, 909, 595, 257, 852, 386, 309, -314, -640, -275, -1112, -1534, -3212, -2963, -3566, -3883, -4501, -7127, -6597, -9483, -7485, -7128, -4571, -7375, -4444, -11865, -7870, -5313, -7155, -3428, -11077, -7770, -9125, -8310, -3381, -7399, -6912, -8765, -11503, -3966, -6346, -6521, -7168, -11360, -5531, -7257, -7706, -7116, -7068, -7660, -12054, -10682, -8340, -5558, -7006, -8854, -9587, -9526, -6069, -6389, -7118, -9337, -5638, -9274, -6453, -8845, -12604, -3441, -10968, -6227, -14733, -10009, -2529, -10137, -5697, -8539, -7247, -2413, -12264, -5425, -8522, -6545, -2854, -6333, -5646, -12419, -7328, -3787, -4279, -6259, -8824, -9771, -4800, -3838, -6481, -7261, -8563, -4664, -4541, -6203, -7890, -6232, -4045, -6420, -6541, -6816, -5547, -3955, -9842, -7972, -5009, -5959, -4435, -10213, -10475, -4682, -6963, -5504, -7886, -11744, -5499, -7792, -7511, -7102, -11514, -5834, -7854, -9814, -7475, -13256, -4957, -7573, -8841, -7927, -13400, -4683, -7644, -7727, -7390, -9887, -5684, -8306, -7013, -6861, -7521, -8562, -10015, -6961, -6447, -5779, -15776, -10543, -8142, -6028, -4576, -14903, -7085, -10275, -5988, -4022, -9449, -6034, -10182, -6406, -4355, -7039, -7576, -10481, -6594, -5971, -6042, -10735, -12139, -6102, -10077, -5147, -6540, -9336, -5684, -13039, -4449, -5644, -7173, -5861, -10946, -4710, -6404, -6152, -6929, -12656, -6287, -6600, -5901, -9247, -8756, -9140, -5629, -6384, -11170, -6098, -9513, -5078, -7412, -10098, -4956, -7975, -4866, -7864, -9491, -4904, -7755, -4930, -7681, -8716, -5856, -9063, -5549, -8024, -7235, -7838, -10883, -6812, -8157, -5775, -11198, -10213, -8346, -7342, -5226, -16470, -8954, -9620, -7158, -5899, -10835, -8071, -10983, -8544, -7222, -10022, -7876, -13422, -12045, -7091, -14439, -8548, -15395, -10606, -6787, -10761, -10332, -12884, -8817, -7185, -8085, -10652, -10287, -8365, -7504, -8403, -8478, -8341, -8698, -7538, -8349, -7415, -7562, -8799, -7687, -6477, -7272, -7897, -8144, -8004, -5823, -7833, -8661, -8029, -8453, -6541, -9320, -8159, -8876, -9742, -9087, -11904, -7116, -10415, -10815, -14632, -10865, -6658, -11041, -7507, -8806, -9105, -6804, -9543, -5818, -7707, 10155, 12746, 13112, 9384, 6364, 9425, 12279, 12488, 8807, 5785, 6856, 10838, 10468, 7169, 4021, -1794, 8320, 6370, 5113, 1089, 3338, 4773, 2049, 3570, -2031, 4578, 1878, 3081, 2124, -3039, 4190, 2224, 1344, 426, -4825, 2790, 3118, -1476, -3958, -4895, 1593, 3326, -3336, -3215, -40, 1441, 2672, -2582, -63, 2254, -2078, 622, -2736, 1020, 3521, -1089, -6869, -1708, 2853, 4154, 1811, 1747, 62, 4384, 4192, 1339, 4130, -49, 4952, 3521, 776, 4507, -2725, 4560, 2308, 2035, 3068, -3883, 3154, 2592, 2099, -2045, -1190, 368, 3919, 780, -955, -1675, -4758, 4235, -493, 1643, -5914, -2613, 3299, -102, 2175, -3555, -576, 1433, 323, 1824, -2409, 554, -344, 524, 616, -3957, 1226, -3936, 628, -124, -3020, 1340, -3346, 361, 1304, -944, 997, 114, -405, 2360, 69, 317, 418, -1152, 2405, 535, -1268, -1198, -1069, 1531, 603, -5980, -5265, -577, -49, 269, -6258, -4021, -918, -1856, -616, -3713, -1023, -2786, -3457, -2425, -4304, 609, -1514, -5701, -4607, -6379, 1493, 253, -5339, -5188, -10266, 1581, 28, -1870, -4916, -5895, 550, -2190, -734, -3085, -3294, -2146, -4314, -1378, -3039, -1655, -2526, -1846, -3501, -6895, -253, -421, -642, -5841, -5964, 766, 65, -417, -6885, -2925, 1104, -557, -677, -3422, -2869, 680, -2226, -977, -1882, -4846, -307, -5870, -1316, -2482, -7492, -1746, -5986, -1963, -3896, -4590, -4094, -2960, -2495, -1718, -4834, -5027, -2262, -2106, -268, -14176, -4192, -2772, -1617, -161, -4262, -5206, -3131, -1845, -1199, -2457, -5959, -2018, -2950, -3579, -2876, -5138, -300, -4511, -8852, -4098, -5770, 1085, -5111, -8511, -4172, -8071, 1678, -4856, -3797, -3774, -9588, 1229, -5366, -1471, -3627, -6087, -643, -7686, -479, -3710, -3453, -3701, -5377, -581, -3755, -2312, -1745, -2660, -1705, -3430, -2398, -620, -1427, -4016, -2901, -3232, -1016, -1039, -7903, -2776, -4205, -2516, -1344, -7185, -3750, -5736, -4869, -2431, -5456, -6694, -7873, -7378, -4341, -5246, -10595, -12277, -6725, -5936, -6069, -6533, -6152, -4723, -5557, -6075, -3954, -2296, -3849, -4801, -4137, -2590, -1009, -4258, -4566, -2724, -2469, -1338, -5936, -5982, -2265, -3786, -3074, -8221, -11402, -2912, -6822, -5872, -8258, -4370, -5367, -4966, -7581, -7360, -2243, -6281, -3751, -6287, -7066, -1808, -2884, -5122, -5047, -6901, -2359, -1531, -9857, -5059, -5925, -3686, -1311, -7128, -6167, -4822, -6161, -1804, -6896, -5863, -4475, -6151, -2600, -9974, -4072, -5347, -3663, -2725, -15938, -3560, -8575, -2717, -1770, -10213, -4551, -7879, -2768, -787, -9373, -4406, -4310, -3255, -205, -9962, -2890, -2963, -3422, 1, -6661, -3392, -2844, -3029, -170, -4916, -8209, -3539, -3108, -942, -4675, -3966, -3962, -3867, -2982, -4586, -1818, -3373, -4092, 7465, 10363, 10751, 7892, -896, 6569, 9725, 10121, 7108, 489, 3261, 7811, 8164, 4473, -38, 1488, 4891, 4774, -1000, -2812, 3807, 1945, 981, -1314, -4478, 3427, -937, 259, -2409, -518, 2267, -4716, 342, -3855, 954, 2702, -1194, -894, -4800, 1416, 3355, 2541, -24, -4117, 1331, 3433, 3956, 950, -5606, 1135, 2957, 4417, -231, -2425, 1451, 1445, 4334, -740, -4, 1960, -2938, 3566, 1676, -36, 2061, -443, 1518, 2270, -1102, 1814, 2329, -4486, 1457, -1257, 1751, 3119, -2316, 873, -678, 2230, 2757, -404, 1232, 550, 2768, 1250, -906, 1095, 1159, 2764, -1686, -2178, 629, 491, 1950, -1012, -2263, 502, -1620, 151, 803, -1032, 320, -5347, -2789, 1188, -332, -302, -9984, -2968, 1024, -469, -936, -8802, -1426, 921, -1322, -874, -4464, -1272, 774, -3355, -300, -1727, -1962, 407, -4289, 192, -290, -2721, -63, -741, 414, -45, -2883, -413, 1133, 417, -1107, -2659, -597, 1776, 49, -3274, -3075, -661, 1373, -1110, -2215, -5329, -642, -89, -3609, -769, -10998, -851, -2524, -9132, -735, -5260, -666, -4873, -5634, -1800, -3680, 670, -5591, -1939, -3299, -4235, 1397, -7483, -350, -4024, -6442, 682, -10761, 74, -5944, -1923, -2142, -4543, 208, -6266, 39, -12373, -2914, 956, -2055, -71, -3681, -2241, 2248, -784, -2158, -2380, -1894, 3287, -867, -2712, -2920, -1889, 3491, -1740, -699, -3844, -2384, 2524, -3659, -485, -2494, -3500, 9, -4356, -2160, -1864, -3123, -1755, -2585, -8293, -2174, -1722, -256, -2470, -4448, -2638, -1516, -185, -4057, -2350, -3833, -3287, -1331, -7535, -2298, -6043, -7242, -2531, -11586, -3140, -4751, -2519, -1968, -9226, -3707, -3978, -1185, -1044, -6128, -3021, -5076, -1576, -888, -4336, -2184, -6571, -3061, -1757, -3834, -2065, -5168, -5343, -3763, -4201, -2827, -3367, -9239, -5769, -4884, -4592, -2241, -8583, -5319, -6652, -7865, -1871, -5208, -5235, -6257, -10939, -1962, -4412, -6054, -2774, -7764, -2222, -5460, -5720, -1289, -4814, -2796, -6417, -5008, -886, -3633, -4235, -4891, -5366, -1022, -4116, -7967, -4810, -6575, -1521, -4923, -11224, -7129, -7925, -2409, -3956, -6990, -17269, -8064, -3622, -3433, -5957, -8662, -6873, -4986, -3865, -5455, -5338, -6159, -7519, -4616, -5257, -3224, -7325, -9523, -4790, -5156, -2448, -9371, -3567, -4489, -5697, -2821, -5314, -1640, -4708, -8441, -3770, -3707, -1381, -6199, -8236, -3921, -3471, -2251, -8708, -4559, -3491, -3836, -3328, -8789, -3216, -3637, -4449, -3813, -9644, -3129, -4424, -5738, -4748, -7124, -3965, -4513, -6723, -5711, -4060, -5275, -3835, -4397, -3995, -2311, -5990, -4048, -3026, -2356, -1567, -5673, -5713, -2770, -1660, -1904, -5196, -10226, -2655, -1716, -3442, -3897, -6594, -1813, -2358, -5478, -2519, -3534, -912, -3236, 2816, 10853, 11130, 7971, 5305, 2639, 10384, 10551, 7334, 5102, 1951, 8983, 8721, 5502, 4500, 472, 6733, 5317, 2994, 3652, -2632, 4136, 846, -685, 2731, -942, 2498, 250, -2235, 1608, 1547, 2032, -817, 2360, 1113, 2142, 1255, -1477, 3248, 2007, 2181, -258, -1515, 2199, 2816, 2574, -934, -2617, -551, 3123, 3037, -17, -2686, 1598, 2910, 3264, 1765, 319, 3044, 1515, 3095, 3165, 1646, 2554, -4918, 2191, 3454, 1129, 531, 1550, 591, 2469, -2124, -1176, 4667, 243, 798, -3351, -1221, 6207, 202, 977, -39, -1104, 6777, -1813, 1461, 366, -318, 6336, -1875, 1209, -607, -15, 4776, 1149, 936, -2417, -791, 2440, 2332, 1056, -3948, -2974, 1560, 2195, 1417, -3292, -8100, 1569, 929, 1661, -1614, -3619, 997, -930, 1448, -901, -1155, -156, -1963, 846, -2205, -348, -1919, -2811, 257, -8398, -214, -3453, -4946, -206, -1537, -170, -7124, -10364, -164, 402, 115, -4540, -12621, 588, 652, 896, -1195, -16424, 900, 60, 1597, -1237, -7107, 278, -1201, 1633, -3867, -3272, -858, -4112, 939, -2844, -900, -1321, -10210, -263, -1175, 454, -1039, -4481, -2017, -716, 561, -736, -6075, -5001, -71, -1380, -522, -4911, -1851, 211, -5301, -51, -100, 645, -415, -538, 199, 1670, 1488, -1398, 29, -730, 1896, 1173, -1821, -2739, -3889, 487, -216, -2279, -6894, -6878, -3666, -2184, -3296, -2486, -6489, -1177, -1264, -4863, -3892, -11466, 696, 258, -4590, -6984, -3988, 744, 570, -2274, -3033, -2936, -16, -459, -1090, -1224, -4081, -1101, -2535, -1339, 120, -7075, -3108, -1752, -3254, 546, -14394, -7204, -355, -3727, -306, -8928, -4062, 58, -1666, -2335, -5461, -2334, 28, -982, -2879, -4177, -2322, -84, -990, -2306, -3866, -3444, -366, -908, -3226, -3878, -5506, -1203, -564, -6448, -4126, -11451, -2910, -152, -8746, -4208, -6954, -3861, 100, -5412, -3887, -4327, -2458, 36, -4128, -4020, -4759, -1580, -462, -3551, -4817, -5465, -1384, -1518, -3568, -5537, -2972, -1548, -2904, -4034, -5937, -1743, -2046, -3334, -4066, -7162, -1717, -2720, -2923, -3738, -10740, -2582, -2337, -2918, -4108, -10690, -4479, -1383, -3176, -5674, -9109, -8246, -1332, -2751, -8263, -9485, -10896, -2741, -2023, -8803, -4645, -7508, -5089, -2009, -7045, -2053, -5038, -2886, -2801, -4004, -1291, -3449, -1253, -3022, -2556, -2207, -3232, -859, -2392, -2889, -4765, -5100, -1269, -2410, -4490, -4375, -12314, -2208, -3197, -4435, -3202, -5109, -3341, -4380, -3450, -3109, -3996, -4346, -6059, -1620, -2968, -4817, -5390, -7471, 117, -2499, -5740, -6338, -5152, 752, -2173, -6120, -6169, -4065, 257, -2365, -8440, -4260, -4972, -1232, -3283, -8427, -2650, -7703, -3235, -5008, -4629, -2540, -7609, -4511, -5536, -3071, -5195, -7715, -2229, -7725, -3696, -1743, -3123, -402, -3041, -2461, -2227, -3511, 82, -1098, -1439, -2126, -3625, -604, -1073, -1291, -1826, -3226, -2174, -2719, -2504, -1520, -3114, -3895, -6905, -3542, -946, -4190, -5272, -7702, -2073, -304, -9118, -7403, -5800, -2159, -127, -4725, -6445, -6421, -5627, -774, -2103, -3377, -9635, -5046, -2299, -1817, -1608, -11314, -1802, -3645, -3641, -607, -7169, -1155, -3617, -5895, -97, -5934, -1594, -3750, -2787, -76, -5338, -2697, -4602, -1917, -767, -3873, -3565, -4736, -2394, -2683, -2203, -2411, -3080, -3139, -8290, -1188, -1566, -2246, -3717, -6051, -1043, -2144, -2269, -4135, -3166, -1736, -4665, -1541, -3420, -2445, -2807, -5714, -428, -1720, -2671, -3901, -3742, -133, -304, -3534, -6730, -4461, -635, 196, -4999, -9280, -10084, -1368, -461, -6250, -3601, -7678, -1850, -2531, -4963, -1718, -6610, -2500, -5824, -3788, -911, -10839, -4332, -5219, -3619, -707, -7788, -9632, -2921, -4230, -945, -5913, -8131, -1636, -5498, -1431, -6064, -7834, -1339, -7316, -1910, -6401, -7193, -1225, -7706, -2012, -5833, -4882, -998, -6730, -1463, -4220, -3883, -1552, -7327, -1007, -3446, -3715, -3291, -9721, -1335, -4379, -4961, -4267, -8177, -2680, -8030, -7886, -4251, -8146, -4898, -11524, -5527, -6364, -9818, -4962, -9179, -4559, -12750, -7549, -3475, -7716, -5543, -10002, -6633, -2922, -5897, -8312, -16142, -5658, -3029, -4932, -15307, -9516, -4894, -3818, -4216, -12433, -8084, -5217, -6432, -3736, -10402, -5130, -4942, -11180, -3459, -8452, -2451, -4563, -6610, -3042, -5685, -1321, -6302, -7019, -2659, -3931, -1369, -14280, -10820, -2711, -3088, -2285, -9053, -9099, -3352, -2633, -3749, -11980, -9436, -4253, -2509, -5009, -8102, -13941, -4320, -3419, -4522, -5168, -12003, -4059, -7399, -3655, -4747, -14360, -4608, -6510, -3954, -5312, -8539, -5475, -3113, -6467, -5601, -6161, -5400, -2508, -12457, -6038, -5294, -5312, -3169, -5293, -7629, -4882, -5578, -4175, -3787, -8540, -4697, -6554, -3984, -4043, -7789, -5165, -8141, -2751, -6578, -7592, -7204, -6154, -2242, -11739, -5629, -15877, -4579, -3361, -5185, -3711, -7014, -3568, -8555, -3553, -2900, -4905, -2461, -5455, -2903, -3147, -4420, -1824, -2925, -2480, -4606, -4717, -2029, -2581, -2166, -8433, -5083, -3066, -3064, -2108, -11378, -5143, -4636, -3586, -2551, -7590, -5327, -5433, -4131, -3709, -8176, -6163, -4356, -4980, -5464, -13694, -8437, -3324, -5727, -7051, -11130, -12397, -3008, -6211, -8993, -9184, -8892, -3231, -7306, -7476, -9969, -7742, -3573, -10203, -4634, -12684, -7927, -3684, -16659, -3624, -17243, -8584, -3813, -9568, -3837, -13002, -8983, -4193, -7514, -4636, -10462, -8864, -4036, -5969, -5485, -8704, -8689, -3081, -4683, -6535, -7310, -7888, -2436, -3996, -7866, -6560, -7437, -2539, -3992, -9937, -6985, -9075, -3531, -4695, -11614, -9521, -14498, -5769, -6377, -8750, -6250, -2388, -2382, -792, -3844, -5568, -4195, -2097, -1896, -4692, -3336, -7965, -2214, -4281, -6960, -2085, -4817, -2960, -4738, -14538, -2011, -4251, -4964, -4203, -9271, -2839, -6000, -9238, -3609, -8753, -4399, -4727, -9798, -2251, -8970, -7127, -2190, -7635, -1894, -5336, -4922, -1187, -6424, -3022, -3667, -2114, -1209, -5803, -5445, -3153, -1059, -1714, -5782, -6155, -2981, -1207, -1976, -6663, -6096, -2844, -2311, -2135, -7195, -8362, -2705, -4110, -3132, -3972, -14535, -2467, -5510, -5792, -1921, -7078, -2310, -4635, -4818, -1135, -5387, -2569, -3822, -2402, -1269, -4121, -3458, -4663, -1609, -2134, -2080, -5044, -10175, -1910, -3693, -420, -7921, -5837, -3250, -6267, 390, -11087, -2919, -5527, -11392, 354, -4261, -2479, -5466, -12193, -474, -1930, -3810, -4357, -7850, -1864, -1383, -4977, -4058, -6027, -2994, -2375, -3743, -3166, -5115, -2870, -4993, -4345, -2099, -4091, -1980, -7257, -8726, -2171, -3207, -1416, -4962, -7049, -4404, -3282, -1581, -2328, -4625, -11970, -4971, -2512, -957, -4192, -3732, -8884, -3966, -954, -4571, -2315, -4916, -3980, -2717, -4787, -2467, -2751, -2466, -10008, -4276, -3237, -1999, -1585, -3612, -3781, -3062, -2151, -1621, -1599, -3895, -2077, -3195, -2708, -1552, -4783, -1739, -5405, -5519, -2732, -5996, -2242, -6747, -8327, -4793, -6178, -3120, -5205, -4868, -6877, -5084, -3574, -4568, -3278, -8116, -4178, -3346, -3155, -2751, -9489, -3357, -2974, -1424, -3687, -8878, -2607, -3122, -724, -7232, -7028, -2531, -4177, -1287, -8077, -4775, -3380, -6154, -3483, -8296, -2786, -5279, -7446, -9742, -7717, -2005, -6688, -8091, -7778, -4203, -2509, -3835, -9854, -6041, -3579, -3402, -2103, -5315, -6127, -4537, -3127, -1887, -2927, -7252, -5946, -3274, -3282, -2280, -8381, -6652, -4967, -7575, -3073, -6001, -7409, -8732, -10256, -5786, -4500, -10375, -14838, -7218, -12124, -4221, -8848, -10338, -7181, -5745, -4837, -5972, -6104, -7131, -3726, -6107, -5315, -4291, -6432, -3057, -7145, -5953, -4118, -5286, -3563, -7131, -7803, -4913, -4846, -5573, -7630, -12685, -4135, -5862, -5860, -8251, -10917, -2629, -9106, -3478, -5686, -7278, -1934, -6210, -2447, -3660, -6232, -1807, -4019, -2351, -2685, -6934, -1713, -3831, -2811, -2361, -10394, -1327, -5543, -3893, -2399, -11271, -924, -12006, -6556, -2697, -8086, -980, -6260, -8052, -3147, -7675, -1867, -3905, -4646, -3523, -8270, -4120, -3468, -3723, -3978, -8272, -9603, -4622, -4360, -5092, -6699, -5698, -8289, -6575, -7691, -4966, -3395, -7250, -13723, -9388, -3800, -2684, -5014, -8438, -5655, -3298, -2890, -4606, -5398, -3834, -3409, -3617, -4354, -4354, -3106, -3951, -4212, -3430, -4542, -3071, -4575, -4677, -2538, -5841, -3489, -4923, -5681, -2124, -8023, -4274, -4900, -7264, -2333, -8982, -5708, -4813, -8796, -3313, -8289, -8689, -5138, -7854, -5175, -8156, -10859, -6117, -5752, -5528, -4471, -2652, -6196, -11727, -8669, -4997, -2925, -1220, -9177, -4889, -4601, -3001, 373, -6932, -2599, -2013, -2167, 571, -6367, -2479, -1175, -1324, -277, -4778, -3825, -2284, -1048, -2049, -2983, -3926, -5524, -1465, -4418, -2204, -2113, -3979, -2658, -6428, -2456, -1106, -2602, -4177, -8465, -3291, -1040, -2746, -4047, -10954, -3643, -1595, -3662, -3529, -5062, -3396, -2253, -5660, -4050, -2701, -3635, -3181, -7993, -5894, -1968, -5269, -5613, -4906, -11586, -2387, -6787, -19755, -3199, -7378, -3991, -3393, -7052, -2632, -4643, -7713, -1496, -6389, -2867, -3961, -5292, -933, -8342, -3994, -3450, -2399, -1669, -13083, -6695, -1822, -1225, -4265, -6013, -7647, -205, -1037, -6638, -3330, -5317, 707, -1597, -4335, -2858, -4621, 846, -2926, -4878, -4668, -4337, 262, -4596, -10910, -8174, -5034, -934, -3779, -6660, -4125, -9053, -2616, -2219, -4445, -2773, -8275, -4516, -1280, -4806, -2834, -5603, -5921, -916, -7097, -3696, -5307, -7555, -1364, -9936, -4798, -5744, -9207, -3079, -8646, -5690, -7252, -5003, -6585, -8770, -6410, -10935, -3488, -5610, -8659, -6744, -9245, -4543, -3736, -6559, -7362, -6667, -9999, -3573, -4302, -8965, -5489, -3734, -5494, -2963, -5703, -5456, -1880, -11408, -2594, -2907, -6858, -1770, -4699, -2890, -1549, -6535, -2640, -2857, -3453, -1154, -4094, -4328, -2189, -4074, -1541, -3391, -7130, -2055, -4605, -2792, -4375, -8446, -2633, -4459, -5634, -6677, -6922, -3739, -4190, -16075, -7423, -5863, -3600, -4931, -5658, -5893, -4679, -3076, -6630, -3613, -3718, -3507, -3927, -7514, -2568, -2615, -2837, -7290, -8002, -1719, -2934, -2845, -6953, -8216, -1143, -4435, -3538, -4074, -8730, -1125, -4456, -5120, -3464, -9807, -1668, -3324, -8996, -4488, -7542, -2334, -3513, -9803, -7113, -5666, -2808, -5626, -6177, -5883, -4286, -3672, -12648, -5514, -4407, -3453, -5572, -8244, -5411, -5150, -3455, -8737, -7283, -4425, -10922, -4379, -13654, -5561, -3741, -5647, -6222, -14264, -3558, -4234, -2762, -6842, -13732, -2974, -6441, -1961, -4929, -7858, -3630, -11656, -2401, -3825, -4479, -4823, -8689, -3994, -3620, -2891, -5125, -7594, -6922, -3746, -2095, -4262, -6938, -10203, -3831, -1822, -3487, -5721, -7810, -4420, -2297, -3764, -5273, -5157, -6377, -3705, -5866, -5856, -3896, -8346, -5827, -11724, -7327, -3817, -6118, -6657, -5614, -9996, -4462, -5188, -5069, -3567, -23608, -5227, -5446, -3785, -2982, -9908, -6383, -6470, -3373, -2828, -7664, -9051, -7122, -3856, -2319, -7283, -14350, -6048, -5148, -1901, -7891, -10559, -5218, -6995, -2190, -8009, -8803, -5223, -9427, -3309, -6301, -8108, -5472, -11170, -5393, -4919, -7391, -5316, -14433, -7828, -4693, -6097, -5145, -7918, -5216, -5792, -4923, -5350, -4639, -3623, -8660, -4158, -5483, -3482, -3677, -8145, -3554, -4932, -3589, -5313, -5483, -2925, -4456, -4440, -9515, -4467, -2589, -4890, 3118, 146, 1330, 6913, -8593, 2225, -2169, 4462, 6442, -5307, 12, -2240, 6211, 5121, -3754, 1312, 1078, 6366, 3616, -3143, 2963, 2155, 5076, 3021, -2276, 3466, 3005, 1414, 2465, -1894, 3025, 3214, -157, 740, -4887, 1293, 2110, 3189, -4219, -2132, -4556, -1005, 3860, -2021, 2117, -988, -6969, 3108, 306, 3776, 2001, -3941, 546, -137, 4468, 2875, -3603, -7925, -958, 4940, 2381, -2086, -131, 1799, 5298, -257, -19, 1104, 3233, 5130, -1436, 755, 202, 3141, 3946, 2103, -996, -1421, 1700, 660, 2879, -1924, -391, -73, -827, 1894, 2690, 319, 1207, 2394, -865, 4090, 511, 2256, 2674, -2225, 3748, 735, 2067, 1310, -805, 1920, 526, 1172, -336, 316, 162, -206, 561, -4199, 1989, 568, -1159, 654, 72, 3204, 150, -3201, 1390, 3714, 3505, -472, -9209, 1725, 4733, 2879, -171, -1469, 729, 4091, 1390, -691, 396, -2601, 1674, -810, -2626, 295, -7749, -4042, -3765, -4460, -1820, -3734, -3146, -8464, -6383, -8245, -1372, -2356, -3271, -5291, -2978, 733, -1947, -1560, -1302, -1978, 1491, -432, -2768, 154, -3479, 940, 126, -7540, 9, -7941, -284, -776, -2313, -1679, -4676, -294, -3182, -1244, -3582, -2537, -44, -2447, -1635, -2579, -1208, -961, -777, -1382, -3078, -74, -3733, -602, -943, -3659, 674, -12982, -1533, -1950, -926, 812, -5139, -3127, -3137, 55, 385, -4789, -4648, -987, -234, 565, -5526, -5624, -483, -47, 1504, -2684, -7560, -1628, 61, 1754, -738, -8574, -1004, -1997, 1217, 92, -2497, 756, -4957, 887, 251, -78, 1558, -1276, 1105, -37, 864, 1478, -1042, 1072, -963, 840, 515, -1753, 612, -3097, 141, -1088, -1256, -163, -5478, -1065, -2240, -1733, -901, -2319, -3035, -2699, -4870, -1569, -198, -5528, -3643, -3113, -3722, 748, -2815, -6049, -748, -8112, 813, -1249, -10768, -477, -1404, 223, -1639, -9965, -1843, 436, -587, -4400, -7743, -5307, 600, -1048, -9887, -4784, -6827, -371, -1397, -3433, -2408, -4764, -1549, -3179, -1722, -763, -4034, -1054, -5471, -2083, 41, -3624, 844, -613, -5535, -199, -3123, 2355, 787, -6442, -1793, -3035, 2846, 197, -1717, -5117, -4639, 2196, -2325, 310, -4472, -17536, 255, -7013, 1172, -1994, -3928, -3289, -9853, 1038, -379, -1702, -10583, -4825, 59, 694, -786, -4575, -2715, -1504, 1229, -290, -574, -2738, -2659, 1129, -455, 1086, -4577, -2561, 147, -1698, 1292, -6912, -2028, -2223, -3573, 147, -4034, -1176, -6949, -4009, -2647, -2021, -691, -7117, -1952, -4681, -1034, -173, -5394, 544, -2675, -487, 966, -1670, 2086, -1898, -583, 1526, 1029, 2718, -1984, -2698, 884, 2329, 2530, -2503, -3246, -933, 2231, 1490, -2589, 810, -2167, 188, -256, -1535, 1951, -1852, 4277, 8809, 8073, 8894, 6117, 3705, 8169, 7263, 8200, 5739, 2140, 6120, 4511, 5897, 4409, 220, 2412, -1604, 1340, 1445, 146, 481, -1372, 1083, -3380, 1598, 78, -303, 1172, -534, 1779, 437, 2339, -180, 102, -96, 3588, 3941, 1896, -338, -7107, 5326, 4951, 4069, -568, -1001, 5674, 5616, 4464, 116, 533, 4623, 5794, 2535, 2085, -90, 2337, 5337, -650, 3534, -2172, 3173, 4030, 3689, 3828, -2848, 4564, 1813, 4696, 3088, -83, 4455, 1995, 3875, 1675, 2758, 3043, 3189, 1410, 215, 4450, 479, 2920, -1555, -385, 4934, -2987, 1382, 245, 524, 4125, -3666, -1159, 1789, 2241, 2386, -582, -2739, 2611, 3599, 3106, 367, 503, 3170, 3851, 4087, -163, 2224, 3834, 2505, 3466, -1465, 2628, 4288, -600, 1277, -2497, 2187, 3945, 1691, 460, -1772, 1456, 2627, 3462, 1714, 507, 977, 1390, 4027, 1833, 2274, 325, 1221, 3987, 747, 3308, -1273, 328, 3319, -1813, 3771, -4158, -1971, 1860, -2041, 3738, -8238, -6137, 140, 549, 3185, -8916, -8056, -245, 1533, 1988, -3807, -2856, 8, 1112, 86, -2567, -1311, 257, -1158, -625, -4053, -884, 724, -8202, 204, -5880, -549, 1493, -3115, -338, -1423, -598, 2289, -2715, -2811, 211, -2133, 2723, -5070, -3071, 611, -8399, 2597, -3161, -2561, 692, -3892, 1767, -1189, -3756, 1144, -1831, -48, -728, -3358, 1838, -1321, -3653, -891, -2556, 2279, -818, -5325, -1002, -2309, 2273, -755, -1921, -970, -3974, 1745, -2182, -462, -1343, -6567, 595, -4975, -109, -2688, -712, 98, -2412, -786, -4322, 515, 930, -1467, -2608, -3287, -363, 881, -3112, -5276, -1939, -1794, -198, -6744, -6453, -1216, -868, -1136, -1844, -4225, -1144, -463, -2293, -40, -2040, -1808, -1214, -5789, 735, -1162, -4271, -3008, -8304, 1061, -1156, -6402, -4590, -6784, 835, -1738, -1396, -3877, -4845, -72, -3918, -375, -3647, -2302, -1608, -8159, -1533, -3457, -957, -3636, -2085, -3981, -2984, -393, -6563, -454, -4316, -2912, -391, -7770, -154, -8634, -3245, -852, -4968, -428, -2861, -3898, -1510, -4373, -1559, 310, -5401, -2226, -5840, -5442, 1388, -5982, -3498, -12001, -6296, 1478, -2471, -6107, -5912, -2775, 1040, -626, -5956, -2526, -2580, 37, -222, -3260, -729, -3968, -2029, -982, -2254, 52, -7660, -4143, -1877, -1721, 0, -9829, -3081, -1249, -993, -278, -7732, -3697, -1019, -611, -13, -9038, -9054, -2074, -485, 538, -3289, -6787, -3741, -897, 1122, -1718, -5178, -3493, -3183, 1177, -2659, -4875, -1197, -3555, -370, -7024, -2896, 359, -1109, -10480, -3403, -1167, 750, -742, -682, -1152, -273, 631, -359, 1694, -417, -631, 967, 650, 2436, -396, -3188, 1408, 1224, 2455, -890, -4362, 1385, 1311, 1974, -2045, 6241, 8127, 8154, 3329, 3450, 5414, 7353, 7504, 4539, 2359, 2893, 4853, 5406, 5810, 1415, -1407, 256, 1137, 6393, 2869, -4026, -1018, -3143, 6315, 2155, 1049, 1256, -932, 5055, -2328, 1888, 2348, -688, 522, 392, 1371, 1929, -161, 1861, -383, 1944, 436, 605, 4813, 1599, 2704, -665, 78, 5335, 4973, 2879, 316, -4132, 4860, 5703, 2508, 552, -2180, 3700, 5143, 1233, -840, 1420, 1344, 4776, -241, -3382, 2340, -973, 4692, 1402, -6939, 1903, 1856, 4098, 2648, -7534, 271, 2871, 3474, 2561, -2175, -3392, 2245, 3982, 1263, 431, -5024, -271, 5016, -803, 2239, -404, -4052, 5332, -1549, 3452, 1413, 285, 4676, -1912, 4399, 2200, 1950, 4041, -4243, 5284, 2722, 2343, 5254, -7932, 5851, 3446, 2058, 6540, -3096, 5792, 3984, 1509, 7012, -79, 5012, 3853, 851, 6625, 1757, 3676, 2829, -245, 5303, 2223, 2010, 665, -2602, 2883, 1032, -577, -3711, -5186, -375, -2619, -5703, -5238, -928, -593, -1219, -2876, -1840, 1076, 1431, 735, -2153, -756, 1646, 2671, 1002, -3381, -237, 951, 2829, 384, -4943, 284, -1173, 1765, -810, -2245, 794, -1385, -1118, -718, -879, 1043, 812, -1580, 712, -1844, 617, 1873, 391, 1316, -2229, -997, 2264, -60, 984, 724, -1524, 2405, -3089, 20, 2026, 1053, 2434, -4403, -739, 2167, 2422, 2259, -839, -659, 1578, 2632, 1650, 247, -828, 419, 1795, 319, -694, -1902, -798, -256, -1868, -4354, -3589, -864, -1973, -3668, -3444, -3657, -939, -447, -4164, -3165, -2500, -2023, 36, -5331, -7651, -2047, -2187, -969, -5920, -3386, -2484, -1053, -2807, -5063, -1625, -3744, -1227, -2107, -4562, -1828, -5324, -3535, -728, -5042, -2414, -4339, -4821, -435, -5803, -1451, -1994, -2642, -1112, -3598, 21, -334, -3353, -2078, -1599, 842, 223, -10118, -2764, -810, 845, -733, -5822, -4143, -1101, -5, -3691, -6578, -4775, -1730, -1606, -2260, -4415, -2597, -1198, -2413, -567, -414, -1047, -116, -1646, -993, 475, -162, 1059, -1526, -3779, -725, 354, 1978, -2684, -12033, -4345, 581, 2077, -5734, -6570, -7242, 245, 967, -9861, -2620, -13415, -1008, -2056, -3860, -341, -4412, -3183, -16484, -1046, 515, -1713, -3196, -5242, 290, 709, -847, -1213, -3672, 196, 859, -581, 130, -2007, -1415, 1056, -926, 842, -1128, -1339, 832, -1558, 1039, -1686, 429, -331, -120, 936, -4188, 662, -2454, 1262, 705, -4660, -622, -3390, 1469, -124, -3031, -3537, -1024, 687, -2587, -4361, -8373, 1268, -716, -3647, -8348, -7906, 2426, -1858, -1745, -2939, -3338, 2563, -1919, -2562, -1240, -1319, 1873, -1528, -8172, -740, -557, 537, -905, -5316, -928, -343, -1343, -382, -3196, -2312, -285, -3772, -710, -2727, -4046, -461, -2665, -536, -163, 1395, -2433, 1451, 700, 744, 289, -3430, 3049, 1103, 669, 769, -1953, 3410, 273, -1166, 1312, 104, 3125, -2569, -3797, 1211, 1460, 2553, -9160, 187, 970, 1832, 1920, -2243, 1512, 854, 1220, 1268, -1188, 946, 536, 262, 486, -2287, -1878, -373, -200, -702, -7091, -6246, -1769, -1183, -2357, -3416, -2110, -2397, -3818, -3072, -1011, -1305, -1881, -3042, -1255, -866, -1461, -1339, -1058, 828, -1576, -1817, -975, -769, 1895, -384, -1716, -768, -1761, 1759, 840, -483, -1031, -4489, 255, 635, 564, -2962, -4338, -2924, -1584, 561, -6641, -1145, -3653, -8057, -1020, -37, -382, -2246, -1516, -6472, 2152, -2088, -1904, 192, -4472, 2868, -3651, -1567, -85, -2669, 2764, 450, -990, -2113, -2535, 2310, 1626, -728, -874, -1695, 1779, 891, -1428, 971, -1296, 972, -2200, -4166, 1114, -1924, -589, -5780, -7825, 221, -2285, -3323, -1691, -3487, -433, -1145, -6073, -230, -2525, 154, -513, -7508, 585, -2832, 982, -1242, -6886, 1164, -3535, 1293, -3821, -2967, 1527, -2951, 1074, -3743, -1304, 1347, -1822, 720, -957, -1811, 494, -1426, 611, -92, -6989, -125, -2038, 500, -931, -3428, -303, -4554, -223, -4165, -768, -1666, -8290, -1602, -9042, -497, -5360, -2436, -1486, -5364, -1441, -9835, -372, -324, -4806, -3517, -7210, 429, -68, -4413, -9929, -2532, 63, -987, -4720, -4172, -1231, -2332, -2607, -7687, -1449, -1587, -10531, -2300, -6691, -997, -1616, -2487, -1538, -2714, -1635, -947, -2399, -1748, -1546, -1794, -870, -4803, -2651, -1760, -1825, -737, -1535, -4039, -2533, -1711, 154, -150, -5934, -2753, -484, 1019, -933, -7073, -2866, 5, 1070, -3637, -5680, -4080, -1145, -109, -2894, -3903, -7681, -5198, -2927, -1149, -3309, -13945, -4640, -7076, -712, -4112, -8977, -2381, -8465, -1063, -5929, -6661, -2103, -10346, -2170, -6951, -5306, -1922, -8416, -3844, -6126, -3923, -918, -6938, -3284, -5098, -1641, 232, -4789, -1976, -5542, -320, 584, -2403, -1930, -9068, -89, -478, -1271, -3167, -8062, -453, -3539, -1173, -4139, -5769, -675, -2442, -1128, -3323, -5757, -424, -655, -992, -3463, -5377, -141, -554, -1804, -4584, -4849, -221, -1415, -3947, -3942, -5664, -758, -2821, -5311, -2857, -7407, -1807, -4706, -4203, -2952, -7839, -3364, -7523, -2643, -4658, -7175, -4285, -10408, -1974, -8684, -5055, -3850, -10031, -3020, -4467, -3341, -3543, -10283, -8030, -2506, -2501, -3456, -9502, -4641, -2462, -2508, -3156, -8393, -1826, -4311, -3506, -2583, -6880, -1017, -10471, -5698, -1943, -5264, -1200, -6114, -8872, -1308, -3958, -2024, -3779, -9555, -714, -3006, -3196, -2756, -7642, -318, -2665, -4451, -2181, -7800, -232, -3248, -5932, -1995, -9862, -387, -5214, -7985, -2473, -5118, -634, -10596, -6671, -590, 828, 1140, 897, -4455, 836, -453, 1020, -805, -8201, 1240, -3314, 1013, -1857, -4285, 878, -10100, 575, -1714, -2248, -534, -4527, -1053, -2108, -1398, -3738, -3428, -5782, -2540, -1106, -8967, -1979, -7322, -2507, -1225, -4764, -375, -5824, -3301, -1909, -188, 210, -5874, -5913, -2966, 2004, 13, -2887, -11871, -3077, 2628, -182, -2256, -7499, -2382, 1941, -20, -2963, -6365, -2134, -214, 85, -3343, -6950, -2664, -5440, -97, -2891, -9609, -4111, -6051, -512, -1859, -6414, -4387, -2835, -991, -1289, -3253, -1811, -2261, -1819, -1961, -2581, -154, -3716, -3708, -4248, -2866, 428, -5957, -4586, -5717, -1388, 250, -1362, -2812, -4076, -46, -232, 202, -2495, -3994, 145, -473, -293, -2952, -5457, -607, -394, -2999, -2029, -5329, -1868, -402, -1902, -730, -2852, -2581, -860, 88, 94, -1471, -1763, -1976, 154, 599, -1287, -409, -3449, -1277, 655, -2383, 311, -2279, -4613, -296, -5104, -67, -199, -7294, -3867, -8220, -1944, 800, -3967, -4647, -7273, -3447, 759, -2999, -810, -6999, -836, -375, -3924, 91, -6887, 602, -3578, -9585, 263, -6229, 989, -4598, -5303, 443, -5622, 594, -814, -1778, 190, -5693, -602, 161, -20, -1138, -6369, -3280, -345, 693, -4110, -7452, -10517, -2039, 522, -6520, -10090, -1877, -3949, -111, -3046, -10215, 153, -3469, -1228, -858, -4303, 197, -3005, -4583, 20, -1881, -1980, -3873, -6635, -204, -969, -12129, -6634, -2248, -1165, -1067, -3411, -14424, -1216, -2162, -1806, -3472, -10512, -1015, -3433, -2713, -8785, -8797, -1523, -4765, -3220, -6674, -6629, -2753, -1521, -3010, -5032, -4341, -2046, 556, -2567, -5564, -2743, -961, 1157, -2728, -4715, -2157, -1369, 577, -3680, -2853, -2554, -3246, -935, -4763, -1830, -3949, -5571, -2846, -4939, -2357, -7216, -5189, -5632, -5028, -5879, -6176, -3218, -5355, -6656, -7252, -2515, -2071, -1519, -8773, -3268, -1159, -1901, 43, -6697, -2751, -1582, -2470, 251, -5832, -3593, -4347, -3784, -472, -4930, -4996, -2333, -5359, -1016, -3163, -5633, 387, -3609, -360, -1554, -4434, 1352, -1620, 357, -653, -2786, 1356, -955, 589, -304, -1947, 814, -1709, 232, -331, -2133, -95, -4579, -960, -981, -3216, -1523, -9511, -3151, -2752, -5009, -4028, -4287, -3325, -6326, -7580, -8835, -2825, -1915, -12577, -9888, -6154, -2438, -1518, -16095, -8728, -4523, -2806, -1754, -12740, -4331, -4205, -4441, -2262, -10771, -1767, -4063, -7782, -2945, -5524, -579, -3885, -4925, -3475, -2923, -415, -3872, -3641, -3227, -1621, -1265, -3880, -3911, -2963, -1030, -3607, -3291, -2867, -3751, -882, -10713, -2529, -1312, -6123, -944, -7948, -2416, -1050, -9084, -1181, -7284, -3032, -2472, -8240, -1961, -10394, -3808, -7257, -8586, -3656, -7317, -4037, -6884, -10044, -5869, -5150, -3836, -5947, -2580, -1817, -63, -1113, -9139, -3509, -732, 2203, -2243, -7660, -666, -399, 3078, -3463, -3819, 709, -1157, 2992, -3260, -3360, 978, -3220, 2087, -1007, -5895, 413, -6009, 198, 468, -7010, -938, -5300, -2032, 601, -3241, -3022, -4062, -1096, -266, -2400, -3961, -3889, -541, -976, -2954, -2619, -4510, -1088, -1482, -3296, -1694, -3411, -1747, -2278, -2002, -1510, -1566, -1565, -2514, -1351, -1842, -731, -667, -2777, -2532, -1939, -895, -195, -2897, -6893, -1062, -1717, -852, -4150, -2542, -28, -2440, -3422, -5473, -890, 332, -3761, -6847, -2396, -1703, -569, -8831, -1617, -2322, -6028, -4802, -1462, 155, -5542, -3449, -3114, 1202, 196, -3242, -1460, 157, 2223, -1741, -982, -1798, 999, 2258, -4027, -504, -2424, 1102, 1597, -309, -858, -1269, 835, 568, 1041, -1503, -573, 96, -538, 860, -2239, -1024, -476, -2009, -584, -3420, -2146, -1219, -4215, -3154, -5719, -2372, -4291, -5754, -5190, -10646, -2435, -8020, -6840, -4674, -10945, -3730, -3218, -7367, -2206, -6945, -6626, -2250, -5292, -295, -4357, -7260, -2140, -4918, 608, -2141, -4577, -3272, -6137, 700, -806, -4059, -8068, -7767, 67, -862, -2626, -6891, -9693, -1233, -2828, -190, -4005, -13823, -3004, -7741, 1078, -2999, -7404, -4510, -6447, 1406, -1940, -6131, -1874, -7410, 1286, -1144, -5664, 323, -9777, 931, -869, -4100, 1027, -5152, 3, -929, -3232, 550, -2988, -2172, -960, -3351, -688, -2065, -5764, -756, -3666, -2056, -1780, -2930, -674, -3646, -3854, -1655, -605, -1363, -3738, -5948, -1755, 749, -3931, -4082, -4189, -2218, 1260, -7893, -3659, -2275, -2730, 775, -2651, -2921, -1098, -2917, -955, -1833, -3719, -945, -3060, -4225, -3916, -10150, -1887, -3949, -4420, -7190, -3920, -2446, -6648, -3020, -2013, -1590, -1372, -9080, -3407, -786, -1784, -739, -6573, -5994, -1196, -4625, -954, -5556, -5302, -2991, -6013, -1596, -3238, -2435, -6571, -2527, -1443, -1401, -1446, -12956, -1688, -623, -692, -1449, -9256, -1925, -434, -936, -2392, -6646, -2804, -1317, -1929, -6513, -7742, -4992, -3521, -3534, -4806, -5703, -11473, -7166, -5587, -1267, -2751, -6370, -6135, -5950, -694, -2614, -5122, -3782, -4633, -1739, -4493, -4723, -2648, -3777, -4008, -2574, -3483, -2485, -3100, -5203, -825, -2691, -3275, -2515, -3061, -688, -2771, -4995, -2296, -1519, -1502, -3411, -4819, -2533, -989, -1955, -4571, -3057, -3199, -1354, -1337, -6963, -2599, -4289, -2705, -1162, -9032, -3603, -5197, -5798, -2242, -8257, -6241, -4827, -14563, -5396, -9561, -8319, -4668, -6812, -10119, -13471, -6541, -5009, -7422, -5365, -9996, -4516, -3651, -8204, -3802, -6835, -2656, -2308, -3295, -3198, -5994, -1602, -2187, -1432, -3289, -6904, -1313, -3172, -1048, -4012, -7904, -1301, -4601, -1706, -5041, -7724, -1318, -5221, 9893, 6950, 9734, 7998, -3265, 9282, 6868, 9246, 7306, -879, 7376, 6226, 7886, 5027, 487, 4021, 4447, 6120, 1103, 1111, 198, 1432, 4432, 1914, 1731, -41, 270, 2231, 2670, 2032, 765, 1266, -1073, 2285, 1999, 57, 2064, -1174, 1420, 1713, -4, 2528, 18, 208, 1011, 2531, 2550, -774, -987, 247, 4302, 2273, -1992, -512, 1069, 5292, 2765, 601, 259, 2656, 5511, 3997, 1922, 615, 3785, 4756, 4676, 1487, 1453, 4497, 2866, 4353, -1937, 1953, 5063, 1640, 2681, -406, 1008, 5555, 2238, -1792, 3028, -2156, 5709, 1660, -707, 4037, -1697, 5139, 1333, 1563, 3710, 144, 3461, 2740, 1301, 2213, 216, 279, 3573, -1012, -915, -575, -2572, 4101, -6155, -5955, -974, 776, 4613, -6417, -2489, -160, 3507, 4596, -3033, -2042, 376, 4807, 3740, -543, -3313, -291, 4973, 2331, 90, -4669, -1893, 4219, 1493, -1212, -3760, -962, 2868, 1060, -4321, -2394, 350, 1828, 136, -1545, -2829, 486, 1568, -150, 91, -6332, -233, 1223, 791, 955, -972, -1221, 404, 1432, 1927, 1262, -538, -576, 1452, 2499, 1585, 1448, -604, 990, 2197, 668, 2686, -106, 401, 527, -548, 2888, -561, 375, -5179, -647, 2015, -2836, 934, -1038, -715, -143, -6899, 1233, 1224, -2034, -4156, -4439, 707, 970, -5586, -6884, -3377, -790, -1534, -10400, -6638, -2846, -2670, -2224, -4720, -4488, -2764, -3121, -458, -2227, -2505, -3033, -2467, -895, -1393, -2155, -2927, -2708, -2651, -2073, -2826, -2188, -5623, -2440, -4684, -3015, -1380, -7691, -1396, -8090, -3008, -1330, -2732, -1107, -4133, -4632, -2552, -1529, -1286, -2098, -8551, -5014, -1830, -1746, -1218, -6037, -4872, -2835, -2461, -1528, -5820, -4374, -3178, -3227, -2825, -7996, -6427, -3596, -3601, -3179, -7516, -5452, -5289, -4098, -2506, -5674, -2494, -6585, -5832, -2239, -5129, -1965, -6739, -7895, -2245, -6075, -3593, -12704, -6431, -2473, -5989, -8011, -5722, -6393, -2616, -3421, -7615, -2983, -6584, -2418, -2383, -7676, -2490, -4175, -2544, -2873, -5523, -3387, -2302, -3566, -4987, -4964, -5383, -1518, -5393, -9860, -6669, -8023, -1758, -6861, -8351, -5303, -8833, -3061, -5485, -5551, -3952, -6464, -5607, -3324, -4449, -4393, -4230, -9981, -2401, -4229, -6714, -2955, -12310, -2517, -4169, -5225, -2739, -8967, -3045, -3946, -2176, -3315, -6666, -3395, -4325, -1027, -3142, -4725, -3617, -6432, -1090, -1997, -3373, -3991, -8417, -1858, -1347, -2983, -4736, -5653, -2642, -1435, -3830, -5918, -4329, -3166, -2324, -6439, -7517, -2801, -3681, -4403, -7189, -8238, -1590, -3374, -9389, -3213, -5115, -866, -2799, -9122, -880, -2473, -394, -3240, -5616, 298, -980, -554, -4377, -4575, 393, -443, -1834, -4171, -5295, -725, -757, -4530, -2532, -10057, -2845, -1725, -8647, -698, 3683, 4463, 1825, -124, 2917, 3531, 4227, 4240, 35, 2671, 2782, 3483, 5662, 524, 2710, 504, 2319, 5436, 1115, 3175, -3508, 963, 3424, 1254, 3130, 543, -871, -2756, 521, 2540, 1362, -2417, 1540, 422, 1314, 82, -1317, 3275, 2037, -1669, -2950, 414, 3145, 2608, -6893, -6719, 2433, 1962, 1679, -5415, -244, 4197, -253, -665, -1236, 3013, 5400, -2164, -3883, 1545, 4445, 5907, -791, -4302, 2164, 4659, 5654, -2012, -1539, 953, 4030, 4641, -1671, 1948, -2540, 3135, 2907, 2284, 4142, -1780, 2362, 508, 3697, 5003, -104, 1246, -2934, 3750, 4673, -57, -356, -7216, 2959, 2988, 324, -1990, -788, 1999, -1190, 1584, -6384, 1481, 1711, -875, 2793, -3376, 1938, 1773, 816, 3392, -910, 903, 1359, -1253, 2831, -1619, 1642, -188, -731, 255, -5239, 3956, -4493, 2828, -8619, -2533, 4856, -4998, 3833, -1001, -1084, 4393, -3073, 3923, 618, -1142, 2651, -4611, 4240, 1265, -881, 210, -5301, 4501, 1122, -499, 193, -4510, 3983, 262, -1048, 1801, -4984, 2540, -291, -2398, 2929, -4414, 757, 537, -2886, 3307, -4481, 103, 1723, -996, 2971, -4340, -56, 2378, 779, 1931, -1460, -617, 2165, 1457, 356, 324, -1165, 1014, 957, -219, 749, -1223, -80, -772, 268, -53, -1566, 7, -3643, 100, -2097, -3244, -380, -5296, -443, -5329, -3409, -1484, -4828, -764, -7308, -397, -2607, -4755, -1428, -5650, 1043, -4558, -3782, -2276, -4608, 1365, -4631, -3248, -2331, -4564, 937, -3603, -4689, -1848, -5570, -114, -4942, -6652, -1041, -8989, -1444, -4558, -4670, -768, -8841, -1623, -2698, -3964, -1574, -4905, -1545, -2709, -3772, -1889, -3496, -2481, -4800, -3080, -487, -3199, -2491, -6607, -2057, -99, -3860, -956, -4339, -1413, -1421, -5906, -119, -5179, -1661, -4126, -6756, -18, -9412, -2886, -3466, -4567, -490, -4385, -3190, -3539, -4647, -1720, -3269, -2601, -6575, -8530, -4143, -4104, -3705, -7531, -6789, -4666, -5399, -6984, -4920, -3645, -2381, -3745, -4689, -3534, -2175, -1047, -1526, -3752, -2596, -1387, -478, -439, -5222, -2893, -1772, -690, -638, -9504, -5060, -3742, -1752, -2606, -5450, -5338, -4699, -3223, -8253, -2526, -2665, -3154, -3203, -3882, -1171, -1418, -2852, -1799, -2719, -769, -956, -3830, -592, -3001, -893, -876, -6593, -122, -2411, -1366, -712, -6676, -453, -1599, -2241, -174, -5179, -1158, -1393, -3593, 190, -8457, -1606, -1738, -5732, -191, -5409, -1791, -2832, -8734, -1571, -1648, -1687, -4201, -8852, -4170, -527, -1602, -4051, -5823, -9139, -730, -1987, -3716, -3907, -11209, -1602, -2843, -3955, -3356, -8787, -2174, -3993, -4651, -3786, -10514, -2840, -4097, -4885, -5179, -7967, -4623, -2429, -3972, -9638, -4419, -2540, -1185, -3861, -8437, -2446, -244, -882, -5374, 2071, 5274, 358, 3097, 2901, 3087, 5290, 179, 2440, 4240, 4286, 5227, 2071, 2279, 5543, 4640, 4868, 3722, 3871, 5615, 4256, 4036, 3915, 4598, 4038, 3599, 2603, 2792, 4107, -820, 2694, 333, 669, 2386, 1352, 545, -2228, -1132, -297, 2616, -4617, 66, -478, 928, 1899, -3609, 2059, 1131, 3144, 3561, -2802, 2953, 1802, 4341, 5646, 176, 3275, 1193, 4703, 6660, 1689, 3389, -406, 4168, 6646, 1494, 3245, -202, 2362, 5312, 546, 2550, 672, -1315, 1314, 539, 1039, 99, -305, -1380, 537, -1736, -2001, 1107, 2170, -629, -4142, -3126, 824, 2788, -3120, -323, -1983, -1179, 3342, -5279, 1431, -1203, -15504, 3500, -8644, 1589, -289, -1264, 2896, -1443, 1085, 870, 683, 1977, 1646, 1753, 1766, 762, 1584, 2523, 2441, 2014, -410, 1828, 1733, 2143, 1665, -2458, 1779, -580, 1122, 1333, -2289, 443, -2330, -694, 1141, -851, -5301, -1406, -4307, 201, -240, -704, -1220, -1759, -349, -231, 1902, -3224, -1091, 1012, -494, 2122, -3760, -3942, 1430, -685, 606, -911, -2434, 572, -741, -1792, -827, 187, -959, -812, -1344, -3080, 1182, -2765, -1219, -396, -2854, 1454, -6097, -2278, 349, -346, 984, -5858, -1832, 586, 208, 185, -3048, -159, 35, -1482, 5, -482, 323, -1365, -9304, -245, 965, -492, -2805, -809, -578, 1008, -2378, -2286, 462, 348, 162, -3310, -1562, -1082, 1163, 61, -1521, -886, -10256, 1089, 201, -321, -304, -1749, 651, -802, -186, -472, -786, 487, -3197, -700, -1998, -2250, 30, -5741, -1330, -5332, -5894, -1304, -5224, -2301, -5321, -7508, -3500, -4848, -4435, -5400, -4138, -5353, -5387, -4648, -5943, -2636, -4929, -5749, -2260, -5960, -2548, -4522, -5910, -1570, -11322, -3391, -4287, -4582, -2262, -5475, -4224, -5056, -2469, -3304, -3208, -5285, -15497, -1671, -2481, -3233, -7761, -3302, -2240, -1290, -4304, -7305, -748, -3313, -959, -4685, -8587, -138, -2873, -1691, -5040, -9775, -750, -2175, -3745, -8771, -4605, -2461, -1900, -7811, -6671, -3613, -5205, -1659, -16669, -3382, -4566, -5873, -1742, -7431, -2962, -7979, -4609, -2757, -3770, -4067, -8369, -3708, -5023, -1628, -5470, -4799, -3005, -7284, -787, -4821, -3364, -3245, -8660, -1205, -3282, -2386, -5394, -21635, -2749, -3176, -1431, -9820, -6374, -4620, -5153, -994, -7799, -3404, -5608, -4621, -1549, -4089, -1986, -5269, -2318, -3083, -733, -1068, -3624, -1497, -3572, 905, -463, -2247, -1346, -2685, 1208, -663, -1894, -1327, -2314, 308, -1739, -2844, -1368, -2315, -1855, -2198, -5478, -1863, -2681, -4685, -2098, -9135, -3094, -4042, -6115, -3475, -7313, -4275, -7120, -11604, -4665, -5881, -3958, -4008, -5829, -2099, -5042, -3526, -1499, -3020, -955, -4614, -3889, -628, -2335, -978, -5090, -5198, -6693, -2397, -2436, -6940, 413, -3124, -1150, -1766, -4277, 569, -1716, -1089, -821, -3726, -133, -1335, -2118, -574, -4771, -1118, -1788, -4533, -1089, -6483, -1203, -3295, -7803, -1687, -7666, -782, -7035, -5120, -1532, -8367, -640, -8173, -3809, -1042, -5039, -758, -4992, -2834, -766, -2795, -1257, -4148, -1562, -1042, -1781, -2915, -3268, -924, -2126, -1678, -6465, -2094, -1358, -3889, -2569, -2978, -1369, -2705, -4702, -4670, -1376, -1192, -2399, -4298, -3541, -1823, -1405, -688, -4292, -1129, -4441, -1744, 165, -4909, -83, -8700, -2234, 64, -6111, -44, -5034, -3463, -1129, -8544, -933, -3916, -5216, -4297, -9496, -3055, -4060, -5058, -6889, -5530, -6880, -5043, -5511, -3563, -3947, -5509, -4620, -9826, -3077, -3703, -4110, -2473, -9109, -3073, -4321, -4340, -1237, -6172, -2252, -4721, -5560, -1206, -4919, -1714, -3427, -5315, -2540, -3081, -2010, -2043, -3547, -5688, -1806, -3034, -1653, -2336, -6185, -1448, -4324, -2606, -1612, -4627, -1750, -5049, -5608, -1617, -4301, -2017, -4837, -10434, -3121, -3926, -1761, -4320, -6408, -8827, -3809, -1742, -3933, -5517, -7753, -4951, -2753, -3445, -5975, -8179, -10358, -5800, -2992, -6739, -8190, -6338, -11959, -2968, -4780, -3609, -3461, -5121, -3250, -2908, -2881, -3423, -3601, -3812, -2465, -4197, -6068, -3341, -5352, -3239, -7876, -8982, -3038, -5348, -4535, -9111, -5954, -1789, -3284, -4922, -5043, -5908, -801, -2898, -4112, -2754, -6412, -731, -4210, -3444, -1365, -6418, -1557, -7601, -3078, -1010, -6761, -2828, -12376, -2903, -2004, -8207, -3801, -7601, -3812, -5223, -8936, -4466, -7246, -7516, -7407, -6897, -5080, -11590, -5389, -3402, -4261, -6361, -6756, -2689, -1936, -2229, -7673, -4149, -1919, -1751, -1495, -5312, -3567, -2082, -2883, -2053, -4058, -3840, -2715, -6105, -3758, -4086, -4213, -3681, -9655, -7278, -5025, -4966, -5049, -5135, -8523, -6913, -6019, -5251, -3028, -3299, -7882, -4942, -4176, -1766, -1731, -6423, -4198, -3960, -1243, -1617, -6221, -5419, -4669, -1382, -2249, -7777, -9966, -5818, -2018, -2800, -11253, -7221, -7299, -2961, -2481, -11771, -6067, -8673, -4298, -1633, -8038, -7159, -8733, -5798, -1147, -5952, -6394, -8592, -4579, -1465, -5627, -4546, -7981, -3215, -2877, -6026, -3884, -7634, -3317, -6058, -4868, -4166, -8562, -4982, -14775, -3836, -5090, -10727, -6290, -6773, -4127, -5961, -10665, -4646, -4232, -6169, -5847, -7353, -4010, -3031, -13470, -5311, -4702, -4576, -2828, -9168, -5029, -3332, -5408, -3340, -7328, -5208, -3058, -5153, -4181, -7644, -6256, -3696, -5304, -5532, -8713, -9250, -4765, -7600, -6878, -7966, -7504, -4952, -13402, -4994, -6511, -4579, -4783, -7267, -3893, -6276, -3691, -5962, -6824, -4245, -7964, -4287, -11713, -9145, -5564, -10924, -6544, -7722, -13292, -6756, -7277, -10999, -4536, -12303, -6903, -6011, -8762, -3384, -8783, -7266, -5094, -1758, 539, -1365, -4791, -4721, -2575, 280, -2241, -2165, -6321, -5738, -745, -3091, -1159, -8461, -5071, -2328, -3748, -1559, -5463, -2303, -4316, -4237, -2643, -4484, -1084, -7260, -4257, -2386, -5808, -502, -9351, -3275, -2278, -5282, -685, -5953, -2327, -4449, -2162, -2211, -4664, -2235, -11079, -874, -6058, -3890, -3257, -3600, -1054, -5523, -3336, -5205, -2252, -3012, -4600, -3611, -4839, -2429, -12304, -6370, -4213, -3251, -3541, -3974, -8535, -3213, -2980, -5442, -2141, -8424, -1759, -4405, -5868, -2593, -9943, -955, -5322, -4002, -5310, -10303, -894, -3296, -3313, -9276, -8628, -1514, -3113, -4392, -6355, -6785, -2784, -5316, -8109, -6109, -6047, -4949, -6070, -7465, -6936, -5086, -6889, -2832, -7369, -6030, -3774, -4208, -1253, -8404, -3820, -3682, -2389, -679, -3868, -2504, -5052, -2034, -1099, -1895, -2037, -4638, -3185, -3038, -868, -2173, -2866, -6430, -9804, -424, -2733, -2356, -7989, -5663, -811, -3507, -2854, -5952, -4975, -1880, -4178, -3808, -6414, -5351, -2707, -4521, -4528, -8718, -2235, -4135, -4597, -4677, -8254, -804, -6268, -4446, -3836, -9373, -640, -2699, -4008, -2669, -9369, -1061, -1315, -3832, -2167, -3958, -1699, -1593, -4476, -2625, -2028, -2486, -3115, -4525, -4117, -1429, -3197, -5245, -3167, -6147, -1533, -3729, -5266, -2557, -5763, -2090, -4646, -4320, -2833, -3939, -3538, -6731, -4405, -3527, -2938, -8177, -7466, -5799, -4107, -3175, -6661, -4212, -7763, -3838, -5107, -3701, -2595, -6778, -3437, -9132, -3471, -2411, -6444, -3854, -5967, -4620, -3650, -7721, -4753, -4224, -4841, -6932, -4576, -5572, -3361, -3391, -7439, -2177, -7651, -2442, -2727, -4821, -1431, -15264, -1812, -3167, -3935, -2009, -9428, -2125, -4544, -3858, -4016, -8822, -3363, -6455, -4417, -8595, -10716, -3291, -9719, -6556, -7831, -9129, -2689, -14961, -11897, -5334, -6140, -4082, -10302, -5638, -4772, -4843, -9858, -6458, -4837, -4478, -4410, -4187, -4183, -5874, -3020, -4188, -2493, -3906, -4757, -1700, -4013, -2692, -5375, -4042, -1573, -4192, -4489, -7997, -4416, -3228, -4402, -8039, -8710, -3564, -6046, -3384, -5108, -7259, -3197, -3036, -2377, -2994, -7188, -4405, -1827, -2444, -2195, -9858, -5077, -1842, -3757, -2257, -9107, -4206, -2181, -6015, -3182, -8494, -4305, -2950, -6589, -4508, -13431, -5429, -4654, -6104, -3609, -6191, -7352, -4738, -6426, -2113, -4235, -6788, -3346, -7461, -1490, -4282, -4553, -3139, -9259, -1646, -5598, -2930, -3924, -11458, -2406, -7733, -2064, -5018, -10187, -3546, -10919, -2177, -5494, -8587, -4725, -11695, -3399, -5475, -7729, -5695, -6528, -5951, -5992, -7138, -6525, -4372, -11951, -6613, -5776, -6964, -4011, -9602, -4965, -4208, -6534, -5737, -7235, -3685, -3411, -5973, -14497, -7473, -3750, -3294, -5934, -5699, -9083, -5165, -3318, -6469, -4112, -8797, -8091, -3206, -7289, -4758, -7385, -13164, -983, -2618, -1430, -6237, -6901, -2444, -3226, -1698, -4829, -7651, -3930, -3933, -2127, -4045, -9454, -3907, -4364, -3061, -5928, -9154, -4016, -4725, -3306, -10267, -6507, -4147, -6880, -2790, -3706, -5966, -4041, -8154, -2811, -1877, -6466, -3886, -4459, -2223, -1488, -7046, -3697, -2987, -1109, -2058, -7563, -3708, -2432, -971, -3695, -8193, -2804, -2787, -2060, -8280, -9323, -1595, -4177, -3683, -6437, -12501, -1280, -6059, -3919, -2800, -11453, -1949, -6527, -3085, -1425, -9891, -3501, -3659, -2804, -1343, -11028, -5985, -1959, -4378, -2792, -6076, -9615, -1845, -9014, -5251, -3560, -11352, -3228, -4238, -3017, -2309, -8728, -5041, -3193, -1803, -1228, -6368, -2893, -4937, -2003, -375, -5447, -749, -9557, -3031, -201, -5586, 505, -3438, -4368, -737, -5887, 1022, -1503, -5542, -1723, -6895, 933, -961, -7023, -2900, -11516, 625, -1297, -12475, -4248, -9750, 605, -2522, -7218, -5872, -6866, 534, -4454, -4463, -8378, -6013, -297, -4135, -4382, -14230, -4859, -2286, -2914, -7407, -9845, -3623, -4097, -2763, -5304, -9005, -3696, -2495, -3462, -2115, -8544, -5963, -1348, -3882, -987, -4457, -7470, -1439, -3310, -899, -2184, -5336, -2739, -3180, -1397, -1390, -5633, -3845, -4027, -2116, -1766, -6484, -3335, -5731, -2782, -2970, -5438, -3612, -7501, -3358, -3969, -4071, -5267, -6485, -3966, -4561, -2938, -8219, -4049, -4750, -6253, -2217, -9780, -2429, -5805, -7919, -1982, -7617, -1792, -7054, -5938, -2146, -6167, -1846, -8343, -5433, -2438, -5843, -1846, -9650, -6905, -2410, -7158, -1193, -9534, -10417, -2000, -12900, -399, -6743, -7047, -1744, -7605, -143, -4190, -4915, -2287, -4745, -836, -2500, -4223, -4594, -3315, -2877, -1744, -4608, -11793, -2157, -6722, -1960, -6021, -5013, -913, -6898, -3122, -7735, -3919, -49, -4869, -4548, -7977, -4797, 55, -4032, -4615, -6303, -6967, -623, -4596, -4538, -4574, -7977, -1834, -6415, -4690, -4360, -7051, -2900, -7709, -3442, -6105, -5977, -3239, -7452, -2039, -4954, -4467, -3367, -4470, -1369, -2568, -3856, -3578, -2824, -1408, -2082, -5095, -3258, -2876, -2106, -3241, -9538, -3047, -4457, -3370, -6342, -6241, -4427, -7243, -4289, -10023, -5125, -7772, -8947, -3484, -8418, -7120, -5262, -7066, -2664, -8736, -10187, -4987, -4961, -2399, -13039, -5705, -7055, -3659, -2047, -8617, -4646, -5492, -3211, -1724, -6067, -4670, -3438, -3741, -2229, -5475, -3997, -2771, -5357, -4129, -5380, -3021, -3085, -7386, -7047, -5142, -2896, -3938, -7699, -6699, -4483, -3973, -5248, -8577, -6873, -3673, -6820, -8722, -9155, -7596, -3153, -15415, -11084, -7236, -7217, -2845, -10475, -6924, -7289, -7188, -2861, -10334, -6502, -11166, -7858, -3324, -9201, -5974, -8784, -9039, -3723, -6916, -4568, -5916, -8996, -3705, -6047, -3705, -5480, -8428, -3879, -6029, -3437, -5810, -8973, -4596, -5666, -3464, -5546, -8858, -5801, -5238, 15165, 2220, 10293, 9886, 8359, 14767, 5638, 9599, 9189, 10163, 13535, 6920, 7288, 6853, 10144, 11358, 6285, 2129, 1303, 9299, 8385, 4271, 475, 1013, 8251, 7587, 1764, 688, 1984, 6512, 8553, 128, -249, -611, 3759, 8828, -867, 256, -6937, 5346, 8283, -328, -509, -264, 6056, 6842, 1506, 1386, 1412, 4279, 4689, 3435, 3697, 2469, -3939, 3292, 4896, 4869, 3037, 1643, 3547, 5663, 5200, 3137, 1847, 4912, 5548, 4834, 2720, -1288, 5655, 4299, 3914, 1229, -7067, 4971, 1763, 2803, -2426, -3092, 2336, 631, 1807, -2942, -2819, -836, 1185, 836, -1536, -5055, 1715, 493, 50, -1759, -1808, 2202, -1063, -527, -2432, -664, 1002, -2089, -1745, -6010, -296, -2271, -1179, -4133, -3901, 1201, -5958, -318, -3961, -898, 2363, -3331, -739, -3644, -745, 2815, -2835, -2475, -6246, -1696, 2777, -3418, -2199, -6704, -874, 2129, -6288, -653, -4689, -13, 121, -6716, -278, -5560, -415, -8130, -1474, -1032, -5326, -1839, -1879, 429, -3153, -3739, -3077, -201, 1026, -7811, -3606, -2202, -740, 728, -17050, -3349, -857, -1628, -260, -9764, -3061, -223, -1872, -1284, -5219, -3867, -554, -3348, -1211, -3364, -4911, -2136, -5185, -949, -3196, -6153, -3803, -4069, -1546, -4273, -11220, -2293, -5814, -3211, -5874, -9225, -1543, -7654, -4453, -6492, -8702, -2022, -3445, -3538, -5984, -11835, -3137, -2778, -3033, -5314, -7909, -4071, -3630, -3184, -5341, -5343, -5856, -4960, -3531, -6565, -3590, -10830, -5853, -3938, -7846, -2905, -4797, -4374, -4549, -6669, -3654, -3344, -2147, -5170, -6659, -4874, -3849, -841, -5242, -9633, -3131, -5622, -363, -4773, -11108, -1937, -7477, -427, -4271, -6912, -1979, -7271, -877, -4149, -5375, -2753, -6536, -2024, -4627, -4488, -3442, -6879, -4657, -5827, -4222, -3640, -8266, -9185, -7401, -4772, -4017, -8267, -7768, -7331, -6096, -5318, -6145, -7204, -6757, -7470, -8929, -4211, -6455, -7478, -7380, -8746, -2915, -6007, -11402, -6159, -5388, -2385, -5302, -10046, -4972, -4620, -2669, -4366, -5827, -4223, -5372, -3708, -4377, -4049, -3955, -7320, -5222, -5567, -3183, -4157, -10406, -6307, -7145, -2926, -4542, -15272, -5720, -7004, -3214, -4562, -9529, -5296, -6641, -4069, -4579, -8847, -6434, -8733, -5309, -5471, -11759, -9022, -9436, -6037, -8163, -10258, -7918, -3794, -5935, -12911, -7705, -6644, -1835, -5753, -8442, -7612, -6550, -1397, -5687, -7383, -8925, -7595, -2077, -5466, -7698, -9273, -9340, -3655, -5085, -7302, -8444, -9286, -6043, -5029, -5724, -8654, -9691, -11093, -5857, -4828, -10089, -13643, -10036, -7491, -4924, -11296, -12769, -6573, -5603, -5821, -10109, -9007, -5561, -4060, -7081, -9241, -7857, -5062, -4361, -8146, -8987, -7778, -4128, -6806, -9337, -8181, -8017, -3304, -13477, -9510, -6888, -7578, -3356, -8468, -7269, -6063, -7039, 8741, 3952, 6975, 8689, 7461, 7965, 4037, 6240, 8235, 7088, 5365, 3753, 3586, 6965, 5982, -709, 2291, -8624, 5319, 4748, -4470, -1068, 620, 4040, 4512, -2797, -1090, 558, 3121, 4183, -367, 1438, -3119, 1993, 3133, -592, 3228, -56, 84, 2502, -3397, 4205, 2057, -3665, 3187, -7182, 4323, 3214, -7878, 4075, 583, 4282, 4808, -2543, 4389, 3794, 4987, 6275, 193, 3820, 5394, 5719, 6925, 1546, 2253, 5734, 5810, 6541, 1361, -167, 4882, 5234, 4868, 613, -2154, 2816, 4206, 1450, 2241, -1280, 161, 2891, 1105, 3465, -94, -137, 982, 2355, 3369, -380, 154, -1515, 1786, 2095, -2752, -326, -166, -31, -185, -7063, -1308, 1459, -1995, -2564, -3374, -2490, 1997, -3375, -4284, -2141, -2608, 1926, -5535, -3928, -2394, -1395, 1648, -6430, -2423, -3605, -709, 1407, -5782, -3505, -4673, -1148, 1209, -7441, -5364, -4258, -3250, 862, -14465, -1560, -2896, -10573, 87, -6434, -360, -1859, -5823, -1257, -4715, -237, -1667, -3697, -2150, -4467, -520, -2329, -2695, -1664, -4289, -1902, -3308, -2223, -1493, -3401, -7242, -3745, -2694, -1736, -3402, -4590, -3741, -4302, -1632, -5902, -1390, -3761, -6770, -1434, -5788, -121, -3823, -8089, -1653, -3119, 547, -3750, -5731, -2427, -3391, 832, -4036, -3416, -3804, -6366, 572, -5602, -2191, -5673, -6006, -681, -10616, -1883, -7549, -4492, -4344, -8372, -2417, -7063, -5091, -6680, -6508, -3977, -5308, -5015, -2084, -6696, -7297, -4537, -3235, -970, -5048, -11384, -4676, -2338, -1043, -3625, -6729, -5139, -2746, -1931, -4086, -4856, -6156, -4940, -3320, -7477, -4850, -11532, -9552, -4050, -10210, -7748, -6825, -6017, -2984, -5601, -10312, -3707, -5121, -1871, -4374, -5851, -3115, -5930, -1696, -4228, -5661, -4027, -6161, -2534, -4901, -7737, -4717, -5627, -4341, -5874, -10902, -3761, -6915, -7455, -6447, -7895, -3654, -18720, -13483, -6889, -6565, -5180, -7222, -9348, -7138, -6865, -9112, -5547, -8639, -6701, -8530, -8968, -6065, -11853, -6201, -8321, -7126, -7279, -10446, -6732, -6220, -6626, -6673, -6152, -9638, -4512, -6631, -6094, -4599, -9879, -3458, -7760, -6785, -4192, -6707, -3481, -12012, -8925, -4470, -6211, -4762, -10526, -11451, -5108, -7719, -7049, -7306, -11076, -5739, -13789, -8367, -6461, -9835, -5993, -8478, -7185, -7141, -8315, -5675, -5652, -6084, -9976, -7564, -5021, -4584, -6254, -17176, -7346, -4589, -4718, -7559, -9942, -7128, -4647, -6373, -9423, -8840, -7063, -4976, -12287, -15035, -9816, -7145, -5328, -7967, -9515, -11203, -6917, -5561, -4906, -6676, -8212, -6556, -4962, -3648, -6157, -6806, -6157, -4169, -3571, -6516, -7052, -5704, -4041, -4950, -6261, -8524, -5911, -4554, -8975, -5784, -10226, -7143, -5486, -8860, -5819, -10541, -7835, -6689, -7483, -6120, -10127, -7749, -7490, -9826, -6313, -10173, -9714, -7104, -11192, 4458, 2870, 7118, 7575, -11243, 3348, 1685, 6636, 7254, -4944, -609, -1185, 5416, 6456, -1588, -1007, 1479, 4418, 5674, 1846, -1635, 2980, 4191, 5048, 4140, -5635, 3251, 3899, 4070, 5286, -975, 2726, 3097, 2906, 5483, -3298, 1238, 1617, 2440, 4715, -1532, -1686, -609, 1671, 2256, 3037, -3160, -3006, -1311, -3579, 5003, 1111, -937, -2107, 2997, 5863, 4373, 1221, 1334, 4453, 5773, 5938, 1434, 2093, 3956, 4642, 5925, -301, 2054, 2136, 2482, 4000, 794, 3022, 2635, 1047, -3405, 2476, 3858, 4138, 880, 467, 2019, 3438, 4503, -16, 1300, -669, 1587, 4082, -466, -1437, -4634, -1483, 3305, -533, -8420, -6667, -6500, 2350, -889, -2601, -5765, -5648, 864, -804, -2077, -1985, -2407, -1520, -198, -1745, -1615, -1994, -1470, 346, -1230, -3470, -2001, -12, 236, -1557, -10862, -1871, 353, -839, -2868, -6024, -2304, -86, -3463, -4276, -3767, -3760, -1369, -9859, -4134, -3319, -5611, -3591, -4525, -3073, -3684, -3931, -4325, -3927, -2727, -4850, -3074, -2305, -7892, -3983, -7513, -5005, -645, -4649, -6189, -13061, -6612, -176, -1450, -2832, -12060, -2315, -1227, -694, -1063, -7551, -1224, -4165, -1451, -781, -4934, -1604, -4534, -3464, -1419, -4606, -2728, -3025, -4085, -2318, -5605, -3903, -2358, -3239, -3209, -5515, -5165, -1846, -3741, -4852, -5936, -7169, -2057, -5461, -7091, -9465, -8962, -3333, -6245, -6562, -7129, -9671, -4477, -6273, -6751, -5552, -11221, -3905, -7579, -9701, -7571, -6112, -4143, -9314, -11239, -9671, -3291, -6937, -9167, -8239, -4276, -1935, -9456, -8446, -5746, -2875, -1615, -5504, -7196, -4037, -2975, -2231, -6170, -5945, -3717, -3918, -3490, -11158, -4926, -4759, -4549, -3561, -4858, -4167, -5523, -4314, -2564, -3533, -3755, -4182, -4855, -2477, -4788, -3605, -3583, -8525, -3652, -11478, -3554, -4205, -6096, -5556, -7369, -3680, -5724, -2706, -6369, -5545, -4411, -7552, -1721, -6916, -6312, -6501, -9040, -2130, -7502, -9788, -11790, -7529, -3799, -6730, -11512, -10105, -6241, -7233, -5022, -7393, -9046, -6171, -8237, -3758, -6358, -8040, -7227, -5758, -3342, -6662, -6714, -10113, -5566, -3729, -8050, -6617, -7486, -7133, -4795, -10028, -7793, -5152, -9578, -6239, -9313, -9877, -4713, -9609, -7260, -7252, -11532, -5531, -9312, -8461, -5703, -11067, -7127, -9298, -11221, -5150, -9746, -8573, -9261, -7140, -6157, -8772, -8980, -9628, -4919, -11494, -8258, -8132, -10059, -4307, -7427, -8265, -6819, -8427, -4611, -4321, -8843, -6113, -6823, -4983, -3504, -9175, -6057, -6212, -4853, -3996, -8911, -5606, -6328, -5217, -5402, -9312, -4622, -7036, -6732, -7241, -10592, -4093, -8669, -7196, -8304, -10786, -4047, -11327, -6214, -7631, -8903, -4054, -8959, -6600, -8118, -8014, -3898, -6536, -8753, -12148, -8668, -3674, -5627, -9694, -9457, -10135, -3660, -6112, -7095, -7659, -4829, -7102, -6498, -5768, -7102, -6936, -6734, -7755, -5765, -7561, -4010, -6378, -10869, -5938, -7981, -2349, -6027, -9615, -5920, -8148, -2201, -6023, -9381, -5366, -7391, -3445, -6148, -9821, -4920, -5938, -6092, -5824, -8314, -5159, -5012, -5167, -5281, -8243, -6280, -5023, -3392, -4739, -11745, -8310, -6182, -3030, -4111, -11193, -10530, -9371, -3623, -3622, -7625, -10460, -15111, -4370, -3745, -6713, -8825, -9433, -4118, -4924, -6975, -8062, -9147, -3587, -7154, -9096, -8549, -11286, -3679, -7569, -12180, -8767, -15624, -4455, -6400, -7286, -7822, -10345, -5084, -4614, -4905, -9334, -7582, -4162, -2134, -2845, -6630, -3609, -2167, -17, -740, -1735, -452, -502, 1187, 862, 480, 1284, 214, 1356, 1522, 1168, 1752, -121, 484, 1039, 556, 972, -1504, -1278, -845, -1431, -1274, -3916, -3357, -4865, -5202, -5812, -7535, -5205, -8171, -12697, -8842, -10191, -6426, -6474, -10853, -7187, -8928, -6003, -6521, -7274, -6582, -9937, -5139, -7692, -6007, -6221, -12284, -5021, -11105, -5926, -5930, -9419, -6087, -10641, -6514, -5528, -7850, -8223, -8236, -7463, -5493, -7054, -9559, -7551, -8722, -6216, -6346, -8339, -8193, -10419, -7790, -6011, -6303, -10805, -11837, -9272, -6640, -4770, -9711, -11618, -9646, -9355, -4113, -7521, -11748, -11232, -9333, -4237, -7380, -13581, -16033, -5474, -4666, -8751, -16529, -14081, -4155, -4990, -11089, -10811, -10738, -4401, -5478, -11609, -8690, -8725, -5911, -6111, -9299, -8324, -8702, -6955, -6697, -7727, -9391, -11741, -6187, -8326, -7471, -11304, -13708, -5902, -16418, -8593, -8898, -9336, -6526, -8725, -11389, -6642, -8172, -7757, -6779, -15746, -5817, -7703, -7228, -7294, -15452, -6349, -7830, -5863, -10127, -14359, -8933, -9199, -5960, -13144, -13676, -12484, -12232, -8559, -10365, -13134, -8452, -10297, -12472, -8164, -12280, -8102, -9018, -8343, -7143, -11929, -10335, -9879, -9266, -7373, -13421, -14360, -10807, -12668, -8397, -14255, -10952, -8965, -8240, -9241, -9871, -10460, -7929, -7171, -9145, -8414, -11568, -7746, -7378, -8297, -8713, -11369, -7947, -6951, -7257, -9695, -10045, -8383, -5811, -6687, -9494, -9430, -8879, -4912, -7073, -9061, -8905, -9013, -4489, -8822, -8683, -8541, -8780, -4744, -10384, -8191, -8858, -8695, -6062, -8407, -8082, -9874, -9036, -9017, -7240, -8356, -11460, -9588, -8399, -6772, -8776, -14374, -9760, -6181, -6490, -9244, -12994, -9444, -5628, -6383, -9540, -9428, -9244, -6381, -6598, -9933, -7944, -9549, -8644, -6929, -11073, -8064, -10229, -13556, -7220, -13279, -10255, -10962, -15329, -7872, -12613, -25624, -11789, -13159, -9007, -9435, -12071, -12529, -9989, -9948, -7981, -11921, -12561, -7856, -9965, -8073, -14185, -12093, -6894, -9528, -9832, -11276, -11549, -6884, -9140, -13116, -9690, -11024, -7704, -8890, -12101, -9682, -10647, -8939, -8893, -11875, -10968, -10730, -9519, -9104, -13947, -13496, -11562, -9776, -9449, -13752, -11391, -13395, -6389, -9624, -16465, -6442, -7466, -6840, -8839, -10579, -6320, -6329, -8537, -9431, -11509, -6801, -5775, -12776, -11379, -15505, -7008, -5151, -9260, -9727, -9754, -6292, -4510, -7001, -7445, -9310, -5955, -4042, -6402, -6402, -11807, -6881, -3903, -7043, -6345, -13333, -10060, -4227, -9048, -7133, -11438, -15372, -5080, -11930, -8676, -8836, -9456, -6219, -8870, -8569, -6909, -7821, -6827, -6598, -6804, -6603, -7425, -6689, -6119, -6132, -7994, -8306, -6495, -7395, -6363, -12395, -10567, -6375, -10852, -6267, -12735, -12963, -6237, -13169, -5422, -8806, -12784, -6011, -8836, -5921, -9344, -7571, -5404, -4695, -11035, -7611, -3635, -3964, -1767, -2650, -2313, -810, -1627, -153, 156, 10, 820, 120, 134, 1037, 737, 1271, 736, -1071, 492, 190, 517, 160, -4510, -1503, -1532, -1610, -1669, -11587, -5463, -4267, -5254, -4741, -8280, -15162, -7212, -6867, -7758, -8927, -12272, -8991, -6882, -7694, -6603, -11110, -9255, -7925, -6672, -4942, -10171, -7343, -9089, -6634, -4274, -9386, -6059, -9577, -6845, -4610, -9093, -6397, -9470, -6499, -6164, -9931, -8640, -9571, -6537, -7640, -13149, -9624, -10646, -7687, -7070, -15768, -7213, -14142, -10798, -7979, -13044, -6278, -11236, -14927, -12957, -15540, -6364, -7963, -10746, -7243, -13890, -7234, -6878, -9893, -5107, -9341, -8881, -7192, -11066, -4954, -7535, -11376, -8430, -12321, -6650, -6869, -15032, -9283, -9100, -14197, -6967, -15599, -7797, -8152, -8514, -7974, -11753, -5950, -9176, -6387, -10935, -9870, -5311, -10894, -6324, -16341, -9195, -6390, -11663, -7128, -10019, -9261, -11025, -11791, -7568, -9002, -9379, -8652, -9165, -7394, -9352, -8714, -6234, -8158, -7802, -9070, -7488, -5989, -9042, -9344, -8042, -6586, -6864, -12293, -10880, -7590, -6404, -8422, -10823, -10168, -7802, -6856, -9588, -7647, -9961, -8530, -7155, -9057, -6166, -11078, -9897, -6731, -8667, -5798, -14226, -12170, -6542, -9721, -6427, -16335, -13202, -7267, -13399, -7961, -11308, -11535, -9159, -17204, -9854, -9240, -10689, -11900, -12876, -11019, -8235, -11085, -12564, -9966, -10665, -7782, -13555, -11505, -8935, -8942, -7669, -14441, -11151, -10175, -7768, -7950, -10255, -12934, -12839, -7580, -8995, -8485, -17870, -11892, -7973, -12074, -7532, -11100, -16350, -7935, -14477, -6916, -9097, -11120, -7431, -9535, -6860, -8405, -8211, -7274, -8373, -7644, -8478, -8013, -7825, -8867, -8892, -9286, -9248, -9057, -10672, -9452, -11033, -9892, -10176, -13720, -10212, -14444, -9741, -10905, -15857, -11506, -18255, -10059, -11254, -11994, -10817, -13174, -10355, -11549, -10362, -10549, -10748, -10769, -14835, -10895, -11818, -9494, -11104, -12061, -14763, -13702, -9219, -11137, -9622, -10427, -15396, -9879, -11703, -9868, -7912, -13792, -11483, -13580, -11679, -7388, -10885, -13456, -23639, -12058, -8362, -9625, -13018, -12653, -11652, -11247, -9247, -11012, -10383, -11355, -17928, -9261, -9521, -10202, -11240, -15208, -9977, -9045, -11615, -12414, -10114, -3970, -8334, -5869, -8970, -9229, -4310, -13488, -5688, -9313, -7789, -4518, -13098, -6176, -6320, -6221, -4871, -11503, -6972, -5298, -5173, -5314, -10167, -8163, -5540, -4841, -5239, -10524, -10875, -6467, -5194, -4537, -9662, -12428, -7536, -6002, -3813, -6677, -8850, -8483, -6964, -3407, -5263, -6918, -9347, -8347, -3453, -4954, -5744, -10223, -10946, -4005, -5209, -5377, -11445, -14886, -4655, -5733, -5939, -11334, -14268, -4448, -6726, -7298, -9502, -10389, -4105, -8853, -8121, -8992, -8542, -4941, -11153, -8126, -9763, -8478, -7911, -8585, -8538, -12136, -8421, -9635, -5953, -6932, -11206, -5318, -5835, -3192, -3692, -4885, -2082, -2022, -652, -966, -1735, -91, 56, 997, 624, -174, 646, 569, 1520, 996, 80, 193, -421, 798, 70, -999, -1448, -3357, -1397, -2473, -3820, -4221, -12012, -4667, -7935, -10437, -7136, -8222, -5044, -15169, -7808, -7900, -8154, -6085, -15738, -6267, -7565, -9659, -9547, -10544, -5693, -7656, -8504, -8180, -8827, -5122, -9644, -6047, -7165, -7995, -4756, -13342, -4937, -8674, -7220, -4943, -8547, -5094, -16086, -6744, -5605, -7958, -6338, -8025, -6950, -6103, -10312, -8173, -6047, -7703, -6154, -11872, -9040, -5874, -8139, -6608, -7372, -8626, -6821, -8573, -7953, -5926, -8458, -8241, -10022, -9390, -6105, -9443, -8828, -12613, -9850, -7899, -11362, -8784, -12567, -12242, -10835, -9466, -9091, -9564, -11749, -9632, -7662, -9057, -7084, -8390, -8928, -7209, -7888, -5694, -8031, -9046, -7896, -7005, -5408, -10131, -8701, -9926, -7092, -6175, -15552, -8263, -14198, -8416, -7737, -10128, -7893, -19648, -12171, -8898, -8567, -6952, -12958, -14097, -9430, -8408, -5916, -8995, -10367, -11185, -9023, -5393, -7523, -10380, -13151, -10173, -5283, -8047, -13643, -9635, -11738, -5285, -10362, -15064, -7977, -12013, -5510, -7585, -10676, -7525, -10252, -6394, -5210, -9757, -7497, -9468, -8360, -4284, -10698, -7487, -10423, -11830, -4265, -12672, -7843, -14152, -16256, -4728, -11014, -8814, -10652, -14344, -5211, -9543, -10244, -8002, -10937, -5613, -8743, -13338, -7280, -9437, -6035, -8430, -14408, -8177, -8749, -6535, -8710, -9385, -11559, -7945, -7557, -9657, -7736, -17573, -7224, -8791, -12450, -7361, -12250, -7151, -7702, -15480, -7544, -10976, -7976, -6557, -10490, -7928, -9773, -9783, -6497, -9302, -9016, -9029, -12423, -7322, -9630, -11402, -8466, -14060, -8830, -10799, -12772, -8346, -11323, -11245, -10842, -13624, -9383, -9700, -15633, -10561, -14654, -11197, -9269, -11468, -10332, -10460, -10194, -8898, -9169, -8613, -8676, -9056, -8087, -8695, -7213, -8226, -8841, -7587, -9421, -6443, -8782, -9153, -8005, -10086, -6048, -10301, -9820, -9972, -9947, -6109, -12165, -10936, -15691, -10654, -6898, -12113, -13707, -12451, -12240, -8843, -11489, -16271, -10362, -10891, -13140, -11680, -10329, -9403, -9133, -14873, -12631, -8537, -8669, -8325, -13261, -13581, -8354, -8244, -8241, -15671, -13412, -9423, 8813, 10397, 10659, 8490, 6718, 8016, 9942, 10005, 7905, 6152, 5336, 8532, 7937, 6131, 4406, 2646, 6102, 4708, 3216, 1406, 3898, 3039, 3748, -79, -1617, 3079, 1561, 2902, -2100, -2952, 1341, 2545, 195, -3053, -11033, 2008, 3509, -1404, -1508, 91, 3027, 3571, -1222, 373, 2781, 2993, 2556, -2068, 1033, 3773, 1180, -249, -3393, 1549, 3892, -1764, -2551, -5508, 3372, 3544, -603, 2574, -5315, 4896, 2781, -1798, 4386, -3700, 5320, 1226, -148, 4572, -3826, 4542, -1227, 1932, 3323, -4813, 2329, 722, 1888, 248, -3533, -2016, 2718, -179, -2923, -978, -4124, 3098, -7186, -240, 829, -3245, 2120, -3145, 966, 1626, -3372, 108, -941, 1235, 1246, -2906, -3208, -446, 1013, -730, -2199, -3670, -1099, 775, -5065, -1910, 888, -3410, 562, -3306, -711, 1797, -3112, -131, -1919, 646, 210, -1290, -1860, -506, 648, -8568, -1965, -5820, 1012, -1470, -2090, -1702, -7525, 1603, -13126, -1030, -82, -2749, 1247, -2015, -1730, -1340, -1634, 414, -49, -693, -8504, -2743, -122, 377, 1062, -158, -7438, -409, -30, 1753, 991, -4883, -600, -115, 826, 387, -4172, -381, 605, -3979, -874, -6606, -627, 1205, -1725, -2647, -4240, -2689, 1415, 1168, -7682, -3140, -14648, 1137, 1515, -4479, -2758, -2630, 193, 427, -1744, -839, -862, -819, -2238, -1687, 103, -714, -218, -9737, -3465, -557, -1492, 439, -5712, -4673, -1832, -2782, 106, -4317, -3455, -177, -3986, -1112, -3988, -2608, 1099, -5197, -2516, -2516, -2493, 964, -5540, -3544, -1251, -3593, -604, -3070, -5482, -744, -7616, -3978, -1337, -12462, -1125, -7786, -8380, -742, -8535, -2774, -4063, -11811, -1018, -7103, -5773, -3582, -5192, -1771, -6211, -6737, -4687, -2416, -2447, -3962, -9365, -5494, -1557, -2921, -2362, -8857, -3950, -1830, -3256, -1536, -4470, -3112, -2783, -2844, -1492, -2905, -3625, -3987, -1998, -2360, -2419, -5022, -5214, -1659, -4169, -2912, -6536, -5247, -2094, -6068, -4404, -12883, -4173, -3040, -5744, -6282, -6009, -3920, -3782, -4821, -8265, -3423, -4906, -4196, -4536, -11284, -3433, -6995, -4462, -4385, -7178, -6038, -8637, -4578, -3974, -5469, -12730, -7578, -4933, -3589, -5236, -6031, -5920, -5391, -3457, -5734, -5707, -5407, -5162, -3782, -6514, -8844, -6256, -4151, -4442, -7372, -9864, -8398, -3579, -5075, -8072, -5520, -11035, -4064, -5974, -7418, -4383, -9173, -5413, -7400, -6295, -4422, -7142, -6321, -8876, -5980, -5285, -6607, -6100, -9986, -6726, -6866, -7026, -5898, -9719, -9170, -9123, -7579, -6793, -8407, -14646, -18011, -8116, -10370, -8259, -10472, -8183, -8928, -11228, -11437, -10430, -5390, -8883, -8491, -7834, -9696, -4587, -7441, -8322, -4980, -7794, -5017, -6123, -8598, -4332, -6821, -6314, -5720, -8598, -4967, -5271, -8158, -6420, -8336, -6520, -3875, -5633, 5939, 7498, 3816, -4110, -683, 4949, 6931, 3325, -2868, 505, 1173, 5324, 1999, -103, -833, 276, 3248, -27, 688, -4897, 2082, 1688, -1912, -381, -3131, 840, -120, -967, -2153, -1680, 262, -8665, -1243, -4695, -1078, 2055, 581, -249, -3880, -118, 2793, 3291, 1934, -1310, 732, 2875, 4391, 2177, -864, 1025, 2300, 4922, -22, 1560, 741, 209, 5020, 664, 3346, 174, -5471, 4348, 3231, 3735, -310, 664, 2497, 3428, 3167, -723, 2976, -596, 1225, 2238, -952, 3683, -853, -10966, 1769, -404, 3105, 129, 580, 2038, 690, 982, 575, 1900, 2110, 1487, -2467, 895, 1792, 1323, 1460, -1122, 695, 1478, -612, 98, -272, -430, 1702, -4604, -3266, -769, -1265, 2188, -9726, -3476, -2752, -435, 2395, -4439, -2936, -3515, -479, 2059, -3641, -4340, -1159, -2214, 1049, -3233, -5523, -933, -5408, -557, -1956, -6331, -3005, -3736, -2091, -1428, -5164, -7148, -1484, -2616, -2569, -6325, -3510, -129, -2039, -5926, -8524, -1105, 286, -1427, -4879, -3383, 539, -554, -1496, -3624, -1878, 1532, -3859, -1822, -4389, -1500, 1812, -6993, -1536, -6968, -1613, 1247, -2806, -1111, -12036, -2403, -315, -3363, -1365, -10198, -5101, -3183, -6179, -2557, -4521, -3642, -10706, -2277, -4067, -1316, -846, -6087, -392, -4254, 2, -513, -3761, -8, -2085, -262, -2486, -3954, -700, 279, -1985, -7065, -7600, -2532, 1410, -3414, -3956, -5137, -6374, 1188, -3260, -3883, -1687, -7568, -775, -4153, -3148, -403, -4011, -7901, -6251, -1121, 12, -2929, -3366, -9076, -538, -175, -3405, -1694, -10890, -1364, -1269, -5414, -2133, -11695, -3369, -3862, -4455, -3469, -13321, -5873, -5912, -2569, -4727, -12900, -7660, -4463, -2150, -5530, -10061, -6325, -4875, -2331, -6140, -8754, -5603, -6225, -2366, -6844, -9310, -7169, -6174, -2398, -8265, -8591, -9419, -5748, -2759, -11208, -6633, -8630, -4414, -3587, -6956, -6090, -11112, -3346, -4689, -5276, -6994, -12638, -3257, -5399, -6281, -8506, -7850, -3844, -4581, -12244, -8998, -5467, -4606, -3000, -7437, -11024, -3982, -5235, -2214, -5741, -14559, -3415, -5922, -2329, -5662, -8330, -3771, -7270, -2936, -5776, -6914, -5191, -9555, -3375, -5683, -7191, -8282, -11319, -2918, -5387, -8629, -11193, -14322, -1951, -4908, -10776, -7617, -10083, -1392, -4472, -11289, -6296, -7170, -1536, -4382, -8472, -6262, -6463, -2432, -4708, -6520, -7024, -7264, -4142, -5191, -5795, -7500, -9399, -6018, -5687, -6166, -6950, -11079, -5344, -6695, -7335, -6520, -9568, -4151, -9366, -7915, -6668, -7892, -3664, -11859, -7509, -7343, -6626, -3604, -8203, -7554, -8792, -5775, -3673, -7738, -8497, -8781, -5335, -3895, -10352, -12172, -6126, -5371, -4573, -10832, -11214, -4691, -5896, -6076, -7233, -7274, -4370, -6438, -8981, -6794, -6313, -4781, -6075, -13189, -8392, -6425, -2794, -5014, 2094, 4062, 775, 920, -1146, 2417, 2589, 4936, 3051, 1403, 3034, -10342, 6765, 3262, 2457, 3411, 2193, 6895, 1430, 2447, 3277, 3251, 5772, -1085, 1645, 2595, 1631, 3600, 407, 163, 1554, 580, 1491, 38, -2249, 561, 2839, 709, 1250, -4808, -409, 3087, 963, 3247, -3035, -3537, 1405, 2691, 3955, 288, -2711, 1159, 3357, 3626, 2891, 2046, 2533, 2067, 2343, 4115, 3543, 1477, 434, -88, 3895, 3370, -3691, 2722, -1088, 1912, 1934, 1207, 3667, 520, -1062, 770, 2300, 4338, 568, 928, 733, 877, 5272, -1201, 1467, -155, -3759, 5542, -4377, 614, -2033, -7205, 4832, -1541, -509, -3463, -4153, 3246, 619, -614, -4077, -3923, 1866, 1284, 58, -3159, -5763, 2323, 970, 376, -1191, -9738, 2746, 571, -167, 163, -2991, 2090, 518, -1675, 606, -1285, -9, -5, -3919, -66, -1182, -4671, -1455, -6022, -2343, -1636, -6281, -3871, -8176, -6628, -825, -2241, -6933, -6604, -3550, 737, -1412, -7588, -3941, -1937, 1675, -2996, -5979, -3184, -1677, 1721, -5206, -4511, -3779, -2436, 861, -2233, -3094, -4685, -4646, -1042, -1167, -1844, -4323, -12324, -5943, -1999, -1198, -3691, -5630, -4199, -7219, -1373, -3991, -2125, -623, -4238, -1845, -4512, 48, 499, -2786, -1957, -3037, 1229, 646, -6367, -2558, -2054, 1263, 280, -2470, -2945, -2372, -233, -556, -172, -2081, -3973, -2944, -1700, -275, -2455, -10596, -1288, -1024, -2207, -5302, -4313, -725, 450, -5139, -15950, -1506, -2403, 849, -4575, -11619, -1381, -5521, 241, -3617, -10848, -3952, -4205, -629, -2762, -9008, -10166, -4152, -1251, -2646, -13814, -3670, -7243, -2545, -4078, -6141, -2909, -7624, -5308, -7177, -4140, -3531, -3071, -7346, -6519, -4223, -4333, -1660, -7726, -5860, -5727, -4502, -1749, -7183, -6056, -7503, -4412, -3281, -4656, -5271, -6772, -4827, -7504, -3650, -3645, -5648, -5674, -9299, -3597, -2461, -5263, -5178, -6334, -3368, -2197, -5509, -3935, -7568, -2920, -2855, -6093, -3293, -11061, -3300, -3975, -6699, -3216, -6724, -5529, -4297, -7015, -3670, -5820, -8424, -3813, -6821, -5098, -6949, -4491, -3662, -6529, -8867, -9136, -3331, -4482, -6795, -12447, -9999, -3576, -6464, -8371, -8162, -10053, -4297, -6243, -11225, -7268, -8150, -4944, -5010, -7377, -7233, -6136, -5842, -5271, -5335, -8012, -5435, -6803, -6653, -4850, -9710, -6171, -6797, -8058, -5448, -11619, -7080, -5864, -8252, -6766, -11448, -5552, -5293, -7839, -8005, -9893, -4396, -5711, -7421, -8020, -8635, -4153, -7208, -6681, -7290, -7992, -4352, -8804, -5837, -7035, -7624, -4365, -8369, -5335, -7635, -7078, -3812, -8074, -5399, -9177, -6562, -2998, -8894, -6445, -13334, -6483, -2447, -9350, -9490, -11962, -6895, -2528, -7762, -14601, -8024, -7449, -3536, -6936, -11336, -7346, -8039, -5960, -7576, -12136, -9686, -7937, -8472, -9287, -3496, -7503, -8433, -8897, -10383, -4426, -5678, -6649, -7783, -6855, -7695, -4832, -4747, -6722, -5148, -7399, -4425, -3662, -6695, -4683, -4367, -4128, -3404, -7448, -5218, -3807, -3883, -3796, -8240, -6667, -4906, -3967, -4597, -8482, -9104, -7851, -4858, -5533, -8476, -10049, -10036, -6751, -6587, -8181, -7837, -7628, -6463, -8581, -7612, -7054, -7060, -4725, -11410, -7441, -7732, -8435, -4225, -7490, -8598, -9807, -9328, -5025, -5693, -12061, -14319, -6423, -7758, -5131, -9252, -16790, -5234, -17193, -4865, -7176, -12803, -5477, -7934, -4707, -6494, -11724, -6881, -6387, -5316, -6151, -11360, -9805, -6221, -7437, -5109, -10351, -13271, -7217, -9062, -3882, -9080, -7205, -10676, -7973, -3569, -9486, -5212, -11092, -9780, -4564, -12814, -4973, -8225, -13128, -7084, -12401, -6159, -7772, -7994, -9596, -10001, -8795, -7764, -6861, -9734, -8743, -13018, -8587, -6936, -10458, -7666, -16832, -13248, -7464, -11157, -6865, -13350, -8835, -8364, -12259, -6464, -10412, -6063, -9754, -10762, -6847, -8698, -5100, -11149, -9803, -8488, -7883, -4924, -10474, -11642, -13066, -7668, -5416, -8495, -11305, -13263, -8182, -6834, -8020, -8702, -9646, -9635, -7661, -9712, -8259, -8472, -10820, -6223, -12439, -8311, -7929, -10802, -5712, -8917, -8296, -8237, -10867, -6521, -6645, -9213, -9927, -9922, -7500, -5195, -10675, -10293, -8680, -6508, -4594, -9877, -8656, -7971, -5540, -4911, -7628, -8495, -7962, -5331, -6144, -6128, -9506, -8988, -5546, -8410, -5828, -10408, -12057, -5777, -11265, -6702, -9785, -14430, -5836, -8674, -8660, -8797, -10904, -5568, -6489, -10644, -8964, -10424, -4712, -5601, -9813, -11439, -11621, -3802, -5747, -8579, -11469, -11915, -3544, -6736, -8169, -8615, -9917, -4222, -7571, -8891, -7903, -9164, -5899, -7390, -11613, -8061, -9634, -7748, -7776, -12381, -8261, -10773, -7733, -10101, -9310, -8382, -11118, -7290, -13743, -8720, -8758, -9523, -7255, -9444, -9833, -9839, -8479, -7638, -8215, -11816, -11469, -8316, -8413, -8325, -11585, -11035, -8254, -8751, -9150, -11193, -9967, -8321, -8034, -10605, -11760, -9553, -9412, -7233, -14406, -11946, -9279, -11210, -6727, -12462, -12255, -8889, -10244, -6605, -8051, -15851, -8480, -9993, -7124, -6429, -14108, -8135, -12885, -8908, -6275, -11362, -7831, -14963, -12904, -7163, -12241, -7476, -10451, -9523, -8431, -23659, -7144, -9732, -8050, -9233, -10722, -6999, -10200, -8585, -9996, -8487, -7020, -11260, -9236, -11182, -8138, -7204, -13736, -8276, -10763, -9119, -7783, -18582, -7917, -9568, -11103, -9010, -14757, -8302, -9259, -14129, -10997, -14171, -8989, -9768, -14633, -13936, -12129, -11061, -10782, -10645, -20938, -10071, -19054, -11648, -9323, -16545, -9286, -10579, -11734, -9386, -14180, -9455, -9479, -11729, -10118, -13190, -10268, -10695, -11622, -11141, -12357, -11626, -14135, -9898, -12644, -12714, -13309, -18135, -8553, -14126, -16128, -13935, -11560, -8260, -13613, -15183, -13687, -5460, -5452, -11196, -9790, -6817, -6056, -5513, -9729, -8527, -7462, -6792, -6547, -8323, -8116, -7521, -7897, -8488, -7397, -7994, -6971, -9023, -9701, -7447, -8062, -7417, -9471, -8606, -8319, -8659, -8879, -9053, -7016, -9132, -9522, -9267, -8717, -5973, -9771, -9712, -8848, -8000, -5820, -10974, -9332, -8454, -7183, -6355, -9140, -9043, -8340, -7705, -7043, -6816, -7799, -9236, -11026, -8276, -5938, -6492, -11037, -13919, -12229, -6516, -6059, -12418, -10092, -11244, -9211, -6435, -12527, -10279, -8786, -16235, -7044, -12617, -10954, -8149, -9443, -7371, -12099, -10423, -6895, -7777, -8077, -10603, -10177, -5797, -6952, -9957, -11431, -8600, -5629, -6369, -10092, -13096, -6683, -6349, -5890, -7907, -8525, -5796, -7962, -5661, -7485, -7186, -5890, -10650, -5852, -9032, -7611, -6651, -9081, -6749, -12763, -8409, -7470, -7463, -9612, -12106, -7683, -7599, -8078, -13115, -12183, -6457, -7475, -9603, -7910, -17086, -5794, -8052, -7818, -7213, -14571, -6190, -9540, -7204, -8812, -11549, -7308, -10768, -8684, -14668, -10139, -7048, -10197, -12322, -13194, -9157, -6602, -9200, -12084, -10056, -8285, -7252, -8627, -12810, -7922, -7328, -8022, -8385, -11429, -6773, -6689, -7771, -8045, -8789, -7003, -6466, -7631, -7573, -8432, -8996, -6556, -8270, -7469, -10263, -11910, -7045, -9701, -8035, -15432, -10726, -7968, -9492, -8998, -12569, -11408, -8956, -7808, -9465, -9476, -11573, -9228, -7152, -8629, -7377, -9487, -8537, -7727, -7552, -6347, -7904, -7637, -10031, -7612, -6232, -6806, -7240, -15664, -9616, -6842, -6692, -7670, -9481, -10893, -8064, -7899, -9089, -7650, -7844, -10338, -9958, -11632, -7788, -6743, -15399, -9672, -14526, -9735, -6879, -9602, -9141, -14182, -9734, -7913, -7734, -9744, -13034, -7855, -10075, -7958, -10335, -12388, -7859, -12946, -10337, -9381, -12022, -9788, -8896, -15956, -8627, -11608, -12881, -7129, -11091, -9218, -11313, -10909, -7331, -9856, -12378, -10599, -9289, -8453, -10636, -14063, -9657, -8366, -7316, -14168, -9587, -9603, -7885, -6435, -12406, -8310, -10827, -7918, -6999, -9890, -8193, -13505, -8799, -8627, -9652, -8718, -16357, -10594, -10108, -11474, -9647, -11601, -9607, -9776, -16771, -10976, -8973, -7534, -8982, -12427, -12469, -7884, -6626, -9249, -10560, -12453, -7916, -6818, -11029, -9956, -11459, -8787, -8394, -14866, -10541, -11158, -10044, -12984, -16609, -13795, -11623, -11747, -11577, -15079, -15484, -11876, -18280, -9348, -13700, -10976, -11500, -12031, -9298, -12239, -9985, -10336, -9195, -9849, -11672, -10390, -9080, -8701, -9727, -10923, -11246, -8823, -9799, -8697, -8961, -9886, -9284, -12383, -7919, -7485, -7816, -9307, -15202, -8285, -6939, -6696, -9471, -12960, -10168, -7129, -6570, -10868, -10858, -11686, -7784, -7360, -12979, -9968, -10203, -8744, -8974, -13473, -9813, -9332, -10319, -11144, -14184, -10010, -8908, -14214, -12825, -16374, -10464, -8726, -12654, -12828, -21747, -11321, -8842, -9372, -12247, -13544, -12614, -9218, -9057, -9536, -11694, -10012, -10812, -9707, -14010, -13820, -12716, -10251, -6857, -14040, -13994, -9343, -12918, -5936, -9919, -10056, -7413, -13393, -6025, -8555, -6813, -6237, -9227, -5917, -9202, -5305, -5587, -7527, -5636, -14629, -4851, -5726, -6898, -6312, -9374, -5153, -6618, -7181, -8660, -6488, -5724, -7500, -8430, -12088, -5575, -6115, -7335, -8971, -12970, -5820, -6878, -5845, -7404, -11189, -7265, -9106, -4676, -6434, -8058, -11195, -11526, -4566, -6239, -6886, -12075, -9203, -5535, -6462, -6907, -8017, -8769, -7501, -6576, -7458, -6817, -9307, -10182, -6217, -8087, -7065, -9381, -14000, -5790, -9111, -7695, -9273, -14013, -5530, -9469, -6265, -7964, -8628, -5245, -7611, -5366, -6227, -6624, -4801, -6887, -6173, -5867, -6126, -4380, -8080, -8235, -7523, -6694, -4270, -12832, -8111, -10652, -7851, -4643, -11482, -8314, -8778, -9029, -5509, -8708, -8613, -9667, -9666, -6783, -7574, -6763, -15752, -8621, -8420, -6630, -5875, -10426, -7571, -11014, -5964, -6041, -8652, -7110, -16756, -6136, -6739, -7334, -7024, -8682, -7497, -7024, -6649, -7826, -6229, -9272, -6467, -6947, -10813, -5450, -9178, -6030, -7863, -13031, -5848, -9559, -6195, -8376, -10567, -7039, -11033, -7016, -8152, -13587, -8136, -12396, -8158, -7953, -11075, -9305, -14775, -8235, -8296, -6976, -9759, -12712, -8007, -9244, -5595, -7951, -10772, -9307, -8603, -5583, -7666, -10898, -11411, -6726, -6690, -9241, -12558, -9605, -5889, -8239, -9273, -16695, -9047, -6261, -8320, -8281, -12356, -8355, -7796, -8204, -9367, -9069, -6581, -10290, -9000, -12092, -7293, -5492, -12402, -10646, -11428, -6309, -5349, -13143, -13503, -11224, -5961, -5992, -12181, -11390, -11425, -6118, -6902, -10596, -9237, -9379, -6499, -6978, -10052, -9085, -7620, -6983, -6004, -9964, -10892, -6877, -7917, -4814, -9631, -13976, -6852, -9618, -4085, -10410, -10403, -7118, -11857, -4145, -16169, -9094, -7372, -14266, -5161, -10884, -9700, -7793, -11879, -7035, -8524, -12626, -8692, -9682, -7916, -8797, -15806, -9044, -8925, -7578, -11683, -11961, -8553, -8639, -8371, -13669, -11163, -8835, -8225, -10796, -11336, -10129, -9206, -7826, -11944, -11962, -8899, -9312, -7680, -11506, -13009, -8766, -11443, -7934, -14209, -11887, -9428, -15040, -8677, -16195, -10058, -9453, -9580, -9204, -11942, -8270, -9110, -7994, -8292, -11405, -7274, -9576, -7425, -7484, -11145, -7187, -10667, -7253, -7809, -10004, -7976, -10382, -7373, -9628, -9389, -9718, -9708, -8018, -13756, -9756, -13145, -10434, -10148, -25925, -11243, -16287, -13292, -19021, -16248, -14065, -11228, -23071, -9222, -13028, -12224, -9445, -14471, -7451, -13009, -9687, -8828, -11633, -7669, -19763, -8689, -8807, -10563, -9429, -13228, -8834, -9196, -10590, -11230, -10881, -9994, -9838, -10660, -10238, -10778, -11866, -10049, -10486, -9334, -11957, -12076, -9901, -10670, -9106, -15188, -10807, -10374, -11336, -9513, -16229, -10619, -11442, -12249, -10440, -12259, -12338, -11888, -11873, -11920, -8255, 8218, 8518, 4703, 137, -5140, 7753, 8166, 5106, 540, -3250, 6287, 7108, 5555, 791, -1631, 3470, 5348, 5428, 570, 1156, -2180, 2995, 4792, 899, 3233, -668, 588, 3980, 1142, 3964, 991, -1786, 3029, -304, 3094, 702, -8279, 1340, -3512, -478, -1112, -2044, -2134, 1037, -733, -2611, 604, -2068, 3033, 1683, -1222, 1844, 96, 3771, 1510, 67, 2656, 175, 4017, 111, 1671, 3035, -950, 3948, -1754, 2724, 2612, -511, 3152, -2003, 2721, 832, 1060, 745, -727, 1420, -4550, 1752, -1065, -971, -2190, -886, 1588, 2265, -2517, -4913, 1840, 1015, 3345, -3708, -1224, 2726, 1227, 2817, -8670, -906, 2485, 2340, 982, -2849, -1446, 1054, 3226, 62, 537, -684, -2201, 3490, -115, 1737, -56, -7898, 3096, -4738, 1778, -982, -6826, 2077, -1031, 828, -3160, -10160, 152, 2222, -1483, -1212, -4060, -4423, 3118, -5594, 248, -2787, -2026, 2878, -3903, 324, -3570, 406, 1755, -1324, -124, -2496, 719, -230, -71, 80, -720, 417, -1210, -232, 469, -854, 1272, 220, -1195, 159, -4591, 2291, 1101, -1698, -765, -3671, 2406, 1309, -821, -1862, -197, 1487, 1173, 791, -3180, 112, -262, 591, 1361, -5797, -1610, -1179, -998, 493, -6925, -5420, -742, -4666, -1194, -1936, -3467, -1125, -7554, -890, 178, -2146, -2983, -3930, -629, 876, -2217, -5998, -2068, -2152, 306, -2729, -7022, -1218, -7188, -2206, -3760, -5448, -1174, -7687, -10954, -4143, -3419, -1516, -5093, -3138, -2143, -1985, -2057, -4052, -2775, -1117, -1170, -2641, -2138, -5550, -995, -1224, -2670, -735, -9578, -567, -2007, -2219, -342, -7692, 524, -3086, -1683, -948, -7077, 1296, -5370, -1194, -2221, -3256, 1257, -4950, -1069, -3383, -1472, 233, -1693, -1771, -4892, -1180, -1980, -419, -3866, -6621, -2138, -5474, -156, -6157, -4795, -4213, -5127, -339, -4524, -3590, -6570, -3194, -780, -4325, -3557, -8074, -2608, -1703, -5544, -4800, -8634, -3328, -3206, -6749, -7973, -8729, -5125, -3443, -7786, -7871, -10310, -6026, -2155, -10906, -7845, -13434, -5541, -1414, -10743, -15660, -9978, -4354, -1374, -6485, -6403, -8967, -2751, -1939, -3752, -4951, -9769, -1632, -2963, -1807, -5986, -10566, -1131, -3689, -669, -9595, -13136, -1276, -3427, -415, -12170, -10248, -2242, -3000, -1194, -7320, -5671, -4156, -2917, -3317, -4703, -3638, -4702, -3214, -6274, -3608, -2845, -3237, -3756, -5799, -3894, -3093, -2684, -4211, -6050, -5378, -4583, -3074, -4323, -7715, -6447, -7930, -4186, -4257, -7771, -5940, -12505, -5731, -4563, -6867, -5028, -13601, -5859, -5985, -5732, -4149, -8554, -4586, -10478, -4734, -3890, -6391, -4026, -10602, -4790, -4268, -6069, -4167, -7309, -6658, -5053, -6613, -4131, -6262, -15018, -6338, -8256, -3866, -5088, -7044, -8316, -12071, -4221, -4230, -5000, 5922, 2877, -2652, 7225, -1942, 5515, 2353, 3865, 6686, 1766, 4165, 730, 5510, 4940, 3051, 1358, 904, 5010, 2671, 2092, -5564, 2646, 2289, 3628, -1862, -4151, 2909, 607, 4154, -5251, -1857, 1644, 3858, 3041, -1910, 10, -602, 4972, 1045, -3599, 1195, 605, 4873, 810, -9585, 1429, 2420, 3718, -155, -2336, 1055, 3117, 1407, -5780, -222, 808, 2803, 890, -817, 1013, 1218, 2085, 3289, 1366, 1234, 2027, 2761, 4672, 1799, 198, 3034, 3583, 5051, 1359, -1866, 4040, 3129, 4518, 319, -2769, 4706, 813, 3008, -854, -1545, 4699, -3603, 235, -113, -1184, 3630, -1158, -2969, 2063, -2284, 709, -774, -662, 3467, -4019, -992, -2120, 629, 3772, -6185, 1582, -4819, 128, 3272, -7246, 1865, -11520, -1190, 3004, -2061, 812, -2624, 278, 2945, -906, -60, -184, 1228, 1770, -859, 174, 294, 611, -203, 858, 249, -1086, -1130, 369, 2022, 241, -1940, -1573, 174, 1316, 853, 929, -1203, -2489, -2748, 1830, 2295, -2578, -11287, -3262, 2455, 2604, -3068, -6488, -1289, 2326, 2428, -89, -5309, -4264, 1290, 1918, 846, -5271, -4314, -320, 742, -190, -8586, -2029, -1024, -1542, -4638, -9557, -2594, -476, -4319, -4176, -6330, -1582, 565, -4829, -1713, -7113, 14, 1462, -5858, -2051, -10818, 631, 1639, -10144, -3800, -2388, 300, 683, -5406, -5103, 539, -1099, -2281, -2988, -3971, 1757, -3044, -12130, -3151, -2522, 1792, -3792, -3819, -4758, -1578, 714, -4145, -3659, -3347, -1303, -1851, -4225, -5126, -1984, -1914, -7118, -4073, -6039, -1921, -3745, -4571, -3449, -5360, -3066, -4057, -3408, -2754, -3995, -5962, -2056, -3713, -2999, -3494, -8482, -1508, -4204, -3874, -4233, -7004, -2412, -4300, -3411, -6686, -7724, -5074, -4663, -2566, -11435, -8951, -9769, -6523, -2522, -4694, -8805, -5417, -11164, -3203, -2571, -9365, -3728, -7995, -4366, -2390, -9768, -3197, -6963, -5469, -3829, -5474, -3229, -6954, -5628, -4607, -3508, -4104, -6926, -5201, -3017, -3258, -6781, -6688, -5292, -1676, -4259, -8702, -5994, -6273, -442, -6137, -8217, -5305, -7539, 275, -8081, -8464, -5335, -7354, 147, -8731, -3499, -5803, -6249, -888, -7789, -2032, -5607, -5626, -2776, -5259, -2924, -6184, -5689, -5352, -4394, -5429, -9887, -5982, -8624, -5787, -2827, -11662, -5790, -12709, -12312, -1539, -7007, -5155, -13300, -9568, -1918, -4272, -4926, -10232, -7642, -3585, -2757, -5668, -7063, -6153, -6748, -2676, -6399, -5254, -5138, -17375, -4308, -5488, -4550, -5500, -8419, -9177, -5281, -4523, -7549, -5931, -6620, -6823, -4509, -7848, -5396, -5237, -11409, -4001, -5616, -6506, -6804, -9460, -3360, -5102, -6861, -10260, -7357, -3247, -6051, -4702, -6499, -6841, -4070, -8027, -3936, -5306, -6850, -6079, -8982, -4609, -5490, -7067, -9131, -7701, -6456, -6575, -7263, 7862, 3577, -3578, 6519, 8233, 7387, 3047, -265, 6189, 8002, 5799, 1670, 1362, 5358, 7334, 2052, 840, 1291, 4485, 6244, -1155, 1285, -128, 3838, 4508, 3300, 1833, -1630, 2803, 2706, 4122, 2146, -633, 1071, 4250, 3709, 1664, 733, 1908, 5011, 3086, 48, 1542, 2952, 3427, 2686, -1076, 1275, 2652, -882, 1801, -599, -870, 1956, 3469, -227, -932, -10134, 1353, 4678, -4543, -2031, 84, 400, 4984, -3068, -3364, 2172, 945, 5524, 86, -5368, 2475, 1878, 5646, 1514, -4784, 1380, 1394, 5202, 1857, -1441, -806, -1002, 4984, 1045, 477, -635, -4379, 4954, -1648, 1641, 644, -2797, 4288, -3253, 2644, 972, -1322, 3020, 397, 3596, 687, -101, 2814, 1834, 4182, 349, 33, 3996, 2236, 4101, 852, -964, 4939, 1990, 3145, 1720, -2451, 5058, 1103, 1231, 1760, -3097, 3923, -603, -635, 322, -2722, 262, -3038, -1189, -4472, -2620, -1060, -2899, -2015, -3919, -3436, 2012, -984, -1798, -597, -2320, 1947, 383, -902, 216, 171, 124, 1242, -747, -309, 1428, -2713, 1657, -1183, -2483, 1433, -3601, 1756, -1977, -7766, 72, -2811, 1657, -2306, -10583, -3253, -2841, 1340, -2238, -6886, -4297, -3968, 519, -1825, -2592, -2136, -5200, -1223, -213, -715, -1543, -4770, -2527, 325, 291, -1608, -3019, -1503, -1502, 1062, -2140, -1168, -526, -6645, 1322, -3678, -154, -132, -1217, 627, -7430, -550, -1186, -480, -1285, -4158, -3529, -5876, -1895, -3438, -2063, -7058, -5493, -3733, -3336, -2027, -2192, -3358, -3342, -3693, -3797, -2182, -4358, -3690, -4396, -7597, -4956, -6387, -3553, -4124, -8527, -3015, -6323, -2577, -4534, -6396, -614, -4495, -3322, -6881, -3609, -8, -3697, -7313, -9857, -2506, -696, -4470, -5693, -9221, -3224, -2436, -6633, -4554, -7967, -5896, -3135, -4783, -6263, -6039, -5094, -2310, -2602, -6682, -6548, -3167, -2169, -1943, -6395, -13476, -2639, -2628, -2692, -6610, -7486, -2796, -3263, -5452, -3570, -5008, -3103, -4128, -14413, -2148, -4189, -2920, -5986, -6298, -2296, -3889, -2034, -9934, -5030, -3815, -3879, -1032, -9400, -5194, -6892, -3773, -352, -10041, -6318, -11567, -3246, -68, -11535, -8678, -11611, -2635, -19, -9312, -9926, -10994, -2358, -75, -16555, -8034, -10548, -2571, -458, -5942, -7471, -10320, -3233, -1499, -3288, -7675, -10172, -3883, -3313, -2820, -7216, -10202, -3874, -5729, -3540, -5958, -9375, -3945, -8679, -3976, -4982, -6867, -4869, -14072, -4032, -4766, -5660, -6485, -12797, -5370, -5521, -6325, -7500, -10770, -7950, -7705, -9406, -7495, -9962, -5439, -14339, -7057, -8173, -7902, -3887, -8710, -4512, -9782, -6912, -3828, -6140, -3589, -7110, -7707, -5054, -5275, -3751, -5350, -11512, -8205, -5413, -4861, -5301, -10081, -12683, -6424, -6305, -6681, -6900, -8432, -8580, -7125, -8259, -5725, -8012, -8535, -8108, -5274, -4485, -4669, -8641, -6926, -6248, -6259, -5340, -11387, -7950, -6505, -7441, -6765, -6574, -10861, -6476, -5437, -8423, -4254, -15479, -7169, -4629, -8620, -3606, -12207, -9201, -5047, -7602, -3747, -8709, -11083, -6616, -6982, -3893, -6456, -10302, -9628, -7076, -3962, -5050, -8471, -12842, -7508, -4693, -4689, -7345, -11734, -6814, -6884, -5827, -7439, -11003, -5609, -12702, -10190, -7761, -10101, -5059, -13157, -9423, -6792, -8744, -5142, -9739, -6426, -5961, -7578, -5798, -7210, -5659, -6137, -6867, -7190, -5969, -5808, -7719, -6570, -8674, -6533, -6466, -11384, -6787, -10674, -10207, -6446, -6049, -8001, -9156, -4805, -4379, -2756, -6357, -4016, -2200, -2543, -1038, -3515, -1868, -1601, -1907, -492, -2414, -1319, -2497, -2527, -1066, -2857, -2123, -4310, -4353, -2907, -4978, -4412, -4906, -5775, -6566, -9626, -8518, -5234, -5106, -10306, -12933, -10710, -6888, -5272, -8755, -11421, -11443, -8847, -6832, -9574, -10006, -14369, -8444, -8294, -12115, -10349, -17059, -8218, -6559, -12109, -12793, -14743, -8958, -5232, -10175, -11258, -13735, -8599, -5377, -8724, -9164, -15455, -7532, -7007, -8339, -8083, -13265, -7816, -9196, -8268, -7815, -11564, -9832, -9775, -6952, -7926, -13187, -13063, -10765, -5906, -7782, -15584, -12379, -10490, -6108, -8448, -12091, -9122, -7745, -7751, -11906, -13267, -7103, -6600, -10677, -10751, -17622, -6265, -7042, -12941, -9065, -14011, -6049, -8883, -9876, -10813, -20246, -5982, -9756, -7965, -14369, -10195, -5954, -8426, -8195, -13464, -7762, -6066, -7427, -10571, -16908, -7728, -6619, -6541, -17431, -10379, -10433, -8506, -5986, -12697, -9069, -11079, -12715, -6155, -8603, -9403, -7391, -8120, -7531, -6590, -9741, -6131, -6525, -10710, -5535, -10606, -5838, -6682, -8170, -4985, -13638, -6081, -7904, -6235, -4881, -13114, -6427, -9614, -6178, -5447, -11671, -6425, -10083, -7648, -6948, -11728, -6684, -8257, -10462, -9234, -10779, -8225, -6923, -12661, -10619, -9710, -13744, -6671, -16022, -11446, -9270, -10943, -7321, -12995, -13079, -9065, -8320, -8063, -9957, -11276, -9036, -7934, -8312, -9468, -8819, -9467, -8590, -8967, -10645, -7828, -10501, -9496, -10112, -11590, -8063, -11299, -8770, -10139, -10255, -8887, -10595, -7676, -9236, -9306, -8792, -9146, -7960, -8973, -8622, -8151, -7974, -10602, -10019, -8011, -7899, -7927, -14595, -12994, -7918, -8135, -9534, -10919, -13005, -8829, -9017, -14014, -12278, -11690, -11613, -9955, -15600, -15036, -12645, -19515, -9337, -14409, -10368, -12627, -13603, -8850, -15890, -9811, -10021, -14068, -9407, -16778, -11374, -8387, -13052, -10373, -14304, -14554, -8023, -11012, -10984, -11336, -16887, -9066, -10720, -12363, -9353, -14030, -11340, -11317, -15637, -8510, -12135, -12642, -11503, -16126, -8884, -12226, -13096, -11769, -12705, -10963, -14302, -13279, -13499, -9957, -19172, -16625, -12660, -15562, -8688, -13533, -15111, -11206, -13165, -8805, -11767, -13777, -10342, -11808, -10262, -11397, -12807, -10458, -6477, -8783, -9156, -7244, -9578, -6328, -9733, -13536, -7400, -7805, -7936, -9056, -8489, -8789, -6259, -11497, -8573, -7079, -7972, -5792, -7806, -8781, -7542, -4974, -6663, -6561, -8910, -10156, -3840, -9021, -7269, -8634, -12588, -4296, -11760, -9368, -8887, -8988, -6455, -9678, -11606, -9632, -8275, -8061, -6691, -10323, -9533, -9416, -6173, -4993, -7891, -9118, -12433, -5687, -4293, -6883, -9419, -16123, -6407, -4190, -7167, -9529, -14934, -8109, -4288, -8700, -7897, -9795, -12745, -4326, -12059, -6700, -7222, -10335, -4404, -16733, -6277, -6233, -6387, -5099, -11768, -5417, -6268, -5291, -8062, -6109, -3571, -5826, -6571, -8834, -2852, -1710, -3620, -8090, -3887, -1178, -580, -1986, -3856, -2366, -779, -430, -1643, -2432, -2403, -1609, -1343, -2671, -2818, -3680, -3795, -3377, -4520, -4806, -5870, -7664, -6535, -4420, -8343, -7916, -15536, -10653, -4084, -12695, -9889, -11828, -13098, -5003, -9736, -11340, -8721, -12170, -7176, -7383, -8885, -7056, -10148, -10846, -7232, -7236, -6012, -8370, -17930, -8908, -6677, -6057, -7995, -20861, -13738, -7012, -7767, -9371, -11406, -14260, -7883, -13412, -16421, -7421, -10815, -8644, -11246, -10137, -5665, -9564, -9488, -9443, -7578, -5485, -9463, -9239, -9567, -7295, -6693, -9922, -7080, -9377, -8432, -8617, -7936, -5892, -8845, -9031, -9569, -6097, -6073, -8837, -8300, -9826, -5514, -7909, -9189, -8287, -8081, -5938, -13439, -9856, -8392, -6871, -6969, -11578, -10508, -7797, -7008, -8090, -9814, -9997, -7225, -8278, -9567, -10223, -9397, -7195, -10334, -11868, -10981, -8329, -7907, -12488, -10352, -11151, -6826, -9507, -13503, -9198, -11249, -6094, -11238, -11431, -9771, -11613, -6580, -9476, -9627, -10380, -12747, -9020, -7275, -8856, -10247, -13736, -16003, -6086, -8414, -11570, -11831, -8566, -5962, -8008, -16748, -11574, -7193, -7054, -8048, -14475, -13484, -7650, -9263, -8539, -11817, -12244, -8730, -9245, -8822, -10515, -10283, -8339, -8075, -8612, -9537, -8883, -7938, -7841, -8409, -8677, -7755, -8264, -8050, -8787, -7793, -7192, -8081, -8359, -10367, -7308, -6991, -7332, -8931, -14232, -8007, -6797, -7132, -9800, -13835, -11501, -6596, -7893, -9831, -11601, -12887, -6679, -9853, -9139, -11078, -8894, -7338, -11703, -8684, -11386, -8556, -8925, -10719, -8095, -12223, -9890, -12600, -10678, -7601, -13352, -10997, -14219, -12580, -7914, -14900, -10834, -10587, -17160, -9606, -17509, -11831, -9792, -14535, -14620, -15935, -13545, -10180, -13387, -14109, -12626, -11733, -11259, -12852, -11649, -10359, -9112, -13805, -10874, -12114, -8940, -7478, -11162, -8905, -13014, -8389, -7070, -8300, -7873, -12301, -8759, -7897, -7516, -7945, -11441, -9479, -9758, -8260, -9257, -10055, -8912, -11370, -10436, -12243, -9002, -8078, -11958, -13352, -17471, -8733, -8008, -12959, -11729, -16054, -8775, -8649, -14557, -9828, -16015, -8934, -9793, -14432, -9459, -15591, -9838, -11052, -12957, -10547, -15496, -12015, -11458, -12524, -12694, -8230, -7691, -5468, -9481, -8670, -9001, -7408, -5868, -8990, -6591, -9581, -7771, -6956, -7195, -6580, -10393, -7327, -8931, -6473, -7471, -7970, -5549, -11685, -6128, -7159, -7631, -4150, -11748, -5513, -7929, -9741, -3795, -10485, -4303, -17918, -8069, -4614, -8971, -3127, -7586, -6064, -6814, -7951, -2698, -5489, -5580, -10569, -7771, -3189, -5469, -5785, -11898, -7226, -4466, -6865, -6114, -10132, -6694, -6073, -9733, -6129, -6873, -7455, -7364, -13436, -5859, -5163, -9935, -8014, -13410, -5672, -4931, -11197, -8088, -11952, -5759, -5908, -8516, -8227, -10857, -6700, -7381, -6294, -7948, -7578, -7593, -6226, -4093, -5630, -4017, -4501, -4020, -2154, -3361, -1993, -2598, -2742, -1072, -1949, -1330, -2120, -2586, -1063, -1517, -1931, -2742, -3767, -2267, -2219, -3885, -4222, -6305, -5003, -4359, -7515, -6275, -6329, -9340, -7607, -12642, -7451, -5676, -9219, -6602, -13829, -5922, -6883, -7370, -5890, -10794, -4729, -10218, -5433, -6630, -9067, -4538, -15278, -4265, -8349, -8557, -5277, -15622, -4066, -8880, -8228, -7025, -17999, -4908, -8895, -7876, -9730, -20204, -6995, -10528, -7947, -8986, -15609, -11480, -8558, -8529, -6973, -14060, -13132, -6336, -9480, -6072, -14891, -8563, -5576, -9787, -5940, -12477, -6978, -5672, -9075, -6201, -9322, -6417, -6451, -8859, -6523, -7573, -6467, -7443, -9016, -6973, -6791, -7238, -7352, -8515, -7959, -6689, -8750, -7373, -7939, -9814, -6907, -8398, -8020, -7907, -11790, -7184, -6899, -8017, -8015, -10770, -7572, -6198, -8602, -7580, -9305, -7928, -6155, -12835, -6869, -8482, -8451, -6730, -11413, -6489, -8152, -9575, -7862, -8206, -6709, -8087, -8522, -9050, -7654, -7533, -7890, -6803, -9935, -8072, -8451, -7253, -6535, -11353, -8295, -8740, -6322, -7893, -15348, -7725, -8988, -5476, -11460, -13262, -7221, -9483, -4995, -10780, -10224, -7251, -9437, -5058, -8963, -8837, -7649, -9570, -5841, -9093, -8473, -8169, -11427, -7607, -10154, -9463, -9020, -13397, -10596, -9380, -11766, -10451, -10172, -10965, -8168, -11446, -11564, -8940, -9038, -8329, -11145, -11019, -8637, -7810, -10112, -13124, -9888, -8452, -7159, -12460, -13661, -8969, -8120, -7365, -11740, -11131, -8617, -7994, -9199, -10800, -9901, -8864, -8338, -18405, -9328, -9597, -9573, -8683, -9092, -8348, -10440, -11231, -8532, -7338, -8315, -13288, -13336, -8470, -7996, -8943, -11069, -10472, -9040, -11538, -10138, -8492, -9458, -10575, -12131, -12718, -7794, -10389, -12879, -10330, -17404, -8374, -12979, -12355, -11566, -15374, -10212, -15777, -12279, -12726, -16126, -12892, -15051, -17251, -12160, -15098, -11206, -13405, -13200, -12773, -12624, -9967, -12677, -10384, -12458, -10770, -10191, -12112, -9969, -12304, -9488, -11298, -11629, -10552, -12837, -9005, -12997, -11904, -11543, -11254, -9555, -14936, -12024, -13036, -10176, -11863, -16570, -11122, -14227, -10661, -18824, -15736, -10527, -14187, -13092, -11981, -10996, -10305, -17064, -21464, -10450, -9195, -11056, 4273, -1175, 9553, 9450, 3052, 4463, 3879, 9185, 8848, 3751, 3691, 5671, 8199, 6996, 2976, -6, 5626, 6835, 3747, -666, 792, 4574, 5106, -1149, 3063, 2037, 4190, 3092, -4209, 3800, -358, 4688, 1661, -2811, 2384, 554, 4827, 2424, -2806, 1978, 2707, 4521, 3968, -690, 2707, 2711, 3757, 4130, 2386, 1913, 2064, 2494, 2508, 3667, 712, 2465, 1624, -715, 3416, 4000, 3141, 2531, -43, 2698, 6322, 3113, 4058, 1241, 3628, 7327, 2097, 4876, 2277, 4319, 7299, 1273, 4438, 3268, 3504, 6323, 1854, 3006, 3946, 376, 4314, 1023, 3672, 4062, -5035, 714, -3398, 4912, 3429, -584, -8156, -3245, 4998, 1886, 697, -982, 327, 4263, -1023, 1589, 1056, 3814, 3295, -5086, 2308, 1972, 5817, 2295, -2104, 3082, 2652, 6521, 377, -467, 3600, 3493, 6229, -3459, -114, 3379, 4039, 5186, 1078, -559, 2118, 3913, 3637, 3134, -594, -248, 2957, 1526, 3430, -111, -1222, 986, -1358, 2163, -472, 56, -2241, -835, -1865, -2532, 1237, -4694, -594, -748, -9471, 2363, -695, -6239, 2071, -3963, 3385, 1107, -315, 2712, -1725, 4066, 1139, 2838, 1943, -850, 4185, 385, 3798, -1034, -810, 3729, 409, 3633, -3631, -1834, 2835, 188, 2725, 946, -4437, 1381, -1223, 1115, 1704, -6992, -1534, -2586, -1552, 193, -4345, -4134, -2019, -2514, -5752, -3653, -1077, -1083, -444, -2084, -4006, -412, -207, 462, -456, -2819, -1217, 425, 537, -907, -1298, -3329, 342, 278, -2320, -650, -6489, -974, -53, -2929, -765, -4640, -4479, -814, -2364, -1373, -2710, -9811, -2690, -2639, -2160, -1708, -7460, -5063, -4249, -3165, -1116, -6249, -2842, -5023, -4942, -960, -3882, -1322, -3471, -8502, -1330, -3190, -894, -2532, -9041, -1644, -3392, -1071, -1851, -6633, -1087, -3902, -1602, -1002, -5609, -598, -5119, -2438, -522, -4698, -1066, -6220, -3522, -1088, -4180, -3025, -5845, -4633, -3574, -4309, -9354, -5815, -5317, -8883, -4318, -4059, -5763, -4295, -4753, -3956, -1188, -5059, -3028, -5161, -4196, -282, -4459, -2775, -9570, -4659, -623, -4394, -3602, -6541, -2769, -1731, -5262, -4933, -5054, -1102, -2424, -8236, -4875, -4457, -759, -1695, -5776, -4752, -4278, -1699, -657, -3225, -5190, -6168, -3979, -402, -2833, -3816, -9388, -7674, -1212, -3869, -2747, -4540, -11357, -3107, -5078, -3168, -3531, -8642, -5995, -4722, -5514, -4313, -5362, -8466, -3742, -12373, -6390, -3513, -7445, -3093, -5643, -8647, -2786, -5096, -3357, -3478, -8699, -3144, -3019, -4871, -3100, -8418, -4030, -1802, -7819, -4520, -8160, -3842, -1386, -9033, -9826, -8837, -3438, -1593, -5964, -4630, -9426, -3444, -2068, -3661, -1901, -7578, -3273, -2546, -2794, -963, -6642, -3195, -3431, -3491, -1447, -6127, -3465, -3316, -6683, -3872, -5921, -3687, -2004, -9602, 6954, 9472, -4937, 4408, 9914, 6202, 9072, -277, 4177, 9310, 3917, 7959, 2087, 3212, 7388, 683, 6428, 3014, 2072, 3868, 582, 4826, 3459, 2377, 1248, 2628, 3240, 3879, 2178, 2305, 3044, 2265, 4056, 802, 3017, 977, 2908, 4021, -218, 2782, -1481, 3752, 3866, 9, 1238, 1895, 3814, 3406, -734, -1246, 2452, 2890, 2862, -2419, -2154, 1980, 744, 2974, 458, -160, 2350, -3684, 3764, 1833, 1209, 2987, -188, 4442, 1831, 1820, 3272, 3009, 4590, 1979, 2915, 3663, 4306, 4297, 2743, 3739, 4182, 4135, 3864, 3231, 3347, 4460, 2066, 3431, 3057, 1366, 4330, -4188, 2732, 2029, -2450, 3903, 673, 1244, 597, -4712, 3501, 1868, -1737, 1065, -6321, 3025, 1724, -4798, 2014, -4691, 2115, 726, -4126, 2091, -2153, 873, -214, -4141, 2340, 833, -948, 3005, -788, 3695, 2866, -1217, 4662, 580, 4650, 3917, 1403, 4843, 599, 4670, 4315, 2157, 4046, 1278, 4078, 4281, 968, 2668, 1969, 3638, 3946, -3127, 868, 1315, 3439, 3449, -3484, -1794, -954, 2896, 2900, -913, -7509, -3831, 2195, 2366, -124, -8891, -3278, 2169, 1966, 447, -9929, -2773, 2353, 1726, 974, -7235, -4046, 1859, 1446, 1041, -4166, -4206, 167, 963, 362, -4972, -2035, -4366, 733, -1274, -4793, -1814, -2747, 1230, -3148, -1473, -3520, -65, 1452, -1912, -365, -4497, 161, 630, -1234, -1045, -2661, -1458, -1577, -2481, -4519, -1881, -2648, -5054, -7214, -6705, -1632, -918, -5935, -5615, -2820, -1622, -958, -7067, -2567, -3478, -2015, -3264, -8679, -1535, -8165, -2000, -5201, -6614, -1732, -1751, -1280, -3369, -6594, -3178, 554, -656, -3463, -5552, -6775, 1130, -171, -4938, -3561, -8282, 471, 41, -5423, -2609, -2999, -1300, -94, -3325, -2318, -1368, -3745, -379, -1975, -2221, -1283, -5095, -900, -1983, -2245, -2265, -4743, -2068, -3757, -2644, -3826, -3992, -4546, -8374, -3572, -5080, -4028, -10704, -6822, -3868, -5142, -5987, -4616, -6468, -2488, -4351, -9791, -2110, -7995, -1434, -3764, -4731, -1066, -5576, -1032, -3972, -3632, -1165, -2801, -647, -4636, -4538, -2905, -1633, -126, -4203, -4911, -9326, -1965, -14, -3423, -3255, -5919, -3705, -551, -3487, -2473, -5154, -6023, -1571, -4266, -2469, -9219, -7353, -2958, -4869, -2960, -9120, -8008, -5357, -5053, -3932, -6637, -6305, -7577, -4855, -5276, -6676, -3559, -5508, -3928, -8032, -5416, -1765, -4957, -3400, -7311, -3173, -977, -5631, -3807, -3876, -1883, -1052, -7343, -5107, -2784, -1889, -2034, -7426, -6933, -2888, -2758, -3039, -5105, -7268, -3435, -3180, -1892, -4394, -6583, -3779, -3925, -902, -5305, -7276, -4089, -6806, -1123, -7841, -8526, -5036, -5094, -2829, -12767, -7115, -6830, -3640, -4196, -6814, -6351, -5633, -5165, -2616, -4037, -7365, -3552, -12596, -2570, -3857, 5615, 3635, 5008, 8307, 8560, 5276, 3327, 4031, 7670, 8181, 4450, 2321, 1492, 5751, 7141, 3678, 319, 2251, 3453, 5936, 3177, -3642, 2484, 2769, 5359, 2469, -8211, 83, 1311, 5080, 1111, -4452, -710, -1942, 4119, -1054, -5164, 75, -988, 1760, -2503, -5947, -2624, 1559, 2341, -664, -399, -3492, 2666, 4350, 1598, 1249, -3523, 2324, 4896, 3228, 1656, -2654, -128, 5228, 4019, 2532, 406, -2052, 5724, 3668, 2788, -39, 2565, 5583, 1650, 1405, -870, 3978, 4515, -2496, 933, 2143, 3757, 2798, -1109, 2023, 2958, 2232, 2025, -625, 1457, 2016, 114, 2601, -1397, 894, 15, -1423, 2450, -2000, 2236, -1643, -11317, 1123, -1329, 2933, -2148, -170, -824, 557, 2647, -1452, 2212, -2245, 2466, 1557, -1140, 2175, -1229, 3422, -218, -1811, -164, 581, 3061, -2526, -3445, -5945, 1800, 1065, -5835, -5227, 176, 2800, -702, -8766, -4097, 2096, 3326, 706, -3323, -2528, 2868, 3305, 365, -1412, -980, 3057, 3440, -2261, -908, 566, 2721, 4059, -3183, -1116, 1551, 1749, 4440, -1772, -1045, 1894, 359, 4158, -2445, -643, 1789, -242, 3144, -4745, -967, 1530, -193, 1520, -4033, -2696, 1308, -892, 52, -2012, -5652, 978, -2084, 18, -1076, -4025, 301, -647, -37, -1324, -2462, -748, 993, -756, -4055, -1989, -1544, 1716, -216, -4336, -1713, -798, 1934, 646, -734, -585, 182, 1874, 632, -120, 181, 146, 1506, 245, -1036, -461, -1386, 874, 294, -1857, -2886, -4885, 226, 715, -1534, -4240, -3475, -156, 764, -1498, -4122, -2271, -228, 6, -1893, -7978, -2968, -98, -1350, -2696, -7527, -3951, 161, -2049, -4314, -4112, -2768, 377, -2023, -6945, -2920, -1353, 292, -2319, -8120, -2399, -663, -146, -3012, -6529, -2890, -708, -576, -3730, -5428, -5567, -1452, -537, -4195, -5525, -6484, -3160, -453, -4817, -7842, -2593, -7125, -1080, -5487, -7095, -1935, -11674, -2918, -3832, -3255, -3267, -7803, -5583, -1555, -1853, -3193, -4682, -4558, -248, -2116, -1765, -1967, -3151, 143, -4549, -2223, -635, -3122, -199, -11564, -4887, -375, -5590, -1244, -3692, -4172, -974, -6671, -3216, -1978, -1813, -2305, -2030, -4099, -1808, -942, -4570, -619, -1963, -2460, -1148, -8696, -699, -693, -2703, -2454, -6312, -2090, -404, -2307, -4238, -5549, -5742, -910, -2557, -4134, -8368, -6972, -1986, -3818, -4147, -5337, -2869, -2843, -5667, -5483, -2721, -1442, -2606, -6727, -5661, -2118, -1262, -2025, -6217, -4312, -2781, -2241, -1803, -5391, -4079, -3978, -4918, -2132, -5481, -4602, -4163, -8880, -3134, -7374, -4419, -3967, -5455, -4967, -8361, -3621, -3249, -4093, -6857, -4338, -2503, -1548, -3482, -6420, -2519, -1318, -657, -3514, -4889, -2151, -979, -1116, -5343, -2908, -3067, -2029, -3077, -8158, -1527, -6560, -5790, -3832, -2206, -4127, -3399, -4292, -4940, -4974, -2793, -2362, -2653, -10980, -5415, -3649, -2321, -1871, -4721, -2919, -4537, -2595, -2070, -2139, -2575, -1729, -2704, -3356, -1931, -3305, -753, -2510, -6063, -3729, -5163, -1706, -2349, -9383, -5256, -11377, -5034, -2566, -7340, -2712, -5787, -9046, -3593, -6261, -1699, -3302, -9886, -6186, -6696, -1792, -2738, -7512, -8622, -9946, -2511, -3281, -3572, -4661, -8071, -3873, -4912, -2319, -2313, -4209, -6451, -7637, -2129, -1412, -2828, -5466, -7336, -2281, -2182, -2979, -2911, -6517, -2539, -6309, -4981, -2174, -6412, -2590, -4489, -7737, -3255, -4516, -1907, -1229, -3607, -5026, -1662, -835, -276, -1725, -2208, 222, -152, -496, -1159, -920, 934, -298, -1543, -1731, -1278, 570, -1511, -3107, -3860, -2520, -665, -4148, -5063, -9601, -3563, -2338, -7677, -6647, -9347, -5738, -4128, -5612, -6055, -8722, -11473, -5027, -4799, -5335, -10194, -3950, -3216, -5976, -4666, -6511, -2263, -1858, -11547, -3776, -4016, -2056, -1812, -6608, -3305, -3151, -2510, -3001, -3221, -3992, -3655, -3160, -3823, -2022, -7049, -4559, -3915, -3231, -2280, -10880, -4556, -4119, -3716, -3862, -5402, -5662, -3493, -5324, -6761, -3992, -12154, -3430, -4389, -10854, -3634, -7926, -4819, -3306, -7653, -3998, -6180, -8424, -3646, -7246, -5270, -5766, -6096, -5140, -8179, -8096, -4530, -3860, -7042, -4222, -14070, -3643, -3048, -7790, -2448, -6400, -3436, -2945, -7516, -2289, -3818, -3584, -3237, -8134, -3080, -2611, -3866, -3720, -8361, -3900, -2253, -4413, -4300, -4948, -5062, -2574, -5451, -4891, -3104, -9966, -3473, -6412, -4902, -2675, -7509, -4489, -6146, -4202, -3286, -5122, -4607, -6019, -3941, -4588, -5910, -4538, -6926, -4744, -5937, -9521, -5491, -8071, -6459, -6309, -11466, -8106, -7592, -7168, -5891, -9960, -11277, -5992, -5987, -5797, -9214, -8528, -4722, -4286, -6720, -6405, -6920, -4206, -3205, -6913, -3869, -6418, -4041, -3431, -4272, -2550, -7061, -4052, -5496, -2653, -2424, -7305, -4873, -5290, -2181, -3493, -5061, -7351, -2919, -2649, -5876, -3521, -9266, -2294, -4077, -10095, -2802, -7212, -2773, -5907, -8717, -2538, -7541, -3682, -5534, -5626, -2788, -11674, -4209, -5122, -4904, -3801, -7671, -4054, -5863, -6040, -5899, -5640, -3933, -6746, -7308, -9937, -6103, -4673, -7159, -6200, -11302, -8101, -6783, -8030, -6107, -10018, -8576, -9051, -8822, -7101, -11354, -9780, -10360, -7996, -7714, -12917, -14236, -12235, -6338, -6552, -11621, -9197, -7458, -5166, -4849, -8419, -7984, -6006, -4844, -3899, -6185, -7370, -5861, -5552, -3962, -5079, -6536, -5921, -7571, -5142, -4988, -5869, -5594, -8610, -7533, -6242, -5003, -4945, -7103, -8357, -10606, -4213, -4411, -7081, -6808, -6725, -4030, -4417, -8126, -6290, -3779, -4559, -5224, -8156, -7091, -2724, -5747, -6887, -7593, -10336, -2890, -7675, -7564, -7008, -10528, -9120, -3096, -4727, -4287, -7491, -4825, -4498, -3189, -5400, -5052, -2316, -9808, -3096, -4647, -2070, -1095, -6897, -3549, -5188, -1297, -802, -4170, -4566, -6792, -1008, -1259, -3154, -7079, -7195, -699, -2081, -2734, -15953, -4835, -883, -3234, -2323, -6262, -3110, -1629, -6398, -2055, -4209, -3242, -2189, -8191, -2449, -3915, -5945, -2211, -3292, -3650, -4302, -8079, -2289, -1759, -5461, -3952, -6295, -2647, -1335, -7280, -3541, -8559, -3380, -1636, -6264, -3789, -13940, -5077, -2738, -4418, -4242, -9014, -9489, -4759, -3781, -4495, -5163, -5181, -6342, -4922, -5022, -3683, -2458, -8291, -7631, -6580, -4346, -1075, -8462, -2754, -4878, -3071, -243, -2870, -537, -1919, -316, 204, -1089, 0, -670, 949, 296, -995, -644, -856, 1038, -27, -2143, -1944, -2630, 177, -943, -3767, -2880, -7857, -1420, -2684, -4335, -3313, -6982, -3321, -5534, -4204, -3754, -4830, -5405, -9695, -4094, -4340, -5866, -8479, -13551, -3983, -5277, -8131, -10593, -13952, -3253, -5526, -5080, -10748, -15480, -2255, -3728, -3198, -8577, -12923, -1884, -2381, -2588, -6205, -8805, -2267, -2100, -3295, -5584, -7718, -2484, -2385, -6230, -5795, -5552, -1869, -2196, -8137, -4130, -3618, -1475, -1783, -4668, -2520, -3253, -1644, -2018, -3820, -2332, -4373, -2114, -3077, -3941, -3940, -5092, -2411, -4569, -4179, -8094, -3619, -2672, -4884, -4497, -4430, -2644, -4021, -3878, -5995, -2571, -2405, -8544, -3126, -13961, -2273, -2688, -7916, -2867, -5187, -2779, -3384, -6460, -2694, -2522, -3542, -4525, -8638, -2424, -1563, -4042, -6247, -15573, -2544, -1488, -4321, -7301, -10773, -3226, -1982, -4677, -5448, -7491, -3714, -2968, -4713, -3784, -4511, -3859, -4348, -4788, -3045, -2910, -4707, -5446, -6259, -3197, -2664, -6729, -5219, -8369, -4314, -3598, -10067, -4589, -5702, -6900, -4468, -14336, -4819, -4702, -15129, -3976, -12010, -5059, -4953, -8456, -3869, -11674, -3651, -5724, -6693, -4473, -12949, -2778, -7384, -6712, -4823, -12265, -3244, -8545, -6116, -4636, -12510, -5433, -7265, -4422, -4448, -10423, -12733, -7066, -3619, -3561, -7027, -7660, -6530, -3902, -2370, -5509, -5134, -6155, -4675, -1971, -5581, -4506, -7476, -5309, -2794, -7460, -5683, -10713, -6690, -5356, -12984, -11029, -9099, -8566, -9806, -12260, -7688, -7849, -6230, -7807, -9346, -5945, -8325, -4902, -7786, -6910, -7009, -8612, -5072, -9369, -5536, -10069, -6354, -6591, -10282, -5508, -8597, -4974, -9521, -9013, -7028, -7475, -4960, -12767, -7785, -11313, -6752, -6424, -12740, -7696, -11893, -5091, -9821, -12027, -8870, -7707, -3872, -8602, -12424, -10914, -5108, -3573, -6720, -12253, -11214, -3706, -4009, -6618, -10520, -8551, -3648, -4646, -8112, -8389, -6121, -5259, -4687, -12149, -7513, -4632, -10013, -3921, -11291, -8555, -4036, -8911, -3076, -9212, -12275, -4365, -7671, -2822, -8690, -8791, -5970, -9197, -3530, -8578, -6469, -5236, -4781, -6658, -2943, -1061, -7932, -4475, -8167, -934, -1390, -5860, -2757, -4476, -89, -2212, -2857, -2192, -2450, 167, -3011, -1371, -1832, -1663, -238, -3480, -972, -1294, -1547, -1734, -4059, -1244, -897, -1830, -3042, -5447, -1757, -863, -2291, -1205, -7176, -2443, -1068, -2025, -309, -6780, -3996, -1493, -1345, -773, -7187, -6478, -2689, -1326, -2301, -8534, -3977, -5782, -2000, -3862, -7084, -2219, -12366, -2773, -4157, -5134, -1684, -8569, -3243, -4514, -3676, -1609, -7788, -3766, -5119, -3547, -1606, -7236, -4041, -5522, -4209, -2205, -8857, -3681, -5065, -3096, -4882, -10267, -5416, -4456, -2720, -5063, -4605, -5564, -5785, -5154, -1789, -1874, -728, -5549, -5346, -1221, -874, 786, -2209, -2249, -2372, -1341, 650, -767, -1850, -3870, -3180, -695, -403, -3195, -3004, -5858, -2351, -602, -6531, -2624, -7577, -2869, -893, -7728, -3960, -8577, -3177, -1114, -5156, -6189, -9822, -3652, -1729, -4802, -4580, -9729, -3535, -3155, -6991, -3884, -9499, -3153, -4561, -8089, -3763, -8259, -3177, -3769, -5249, -3167, -6487, -3448, -2869, -6451, -2904, -5645, -3415, -2875, -6168, -3025, -5571, -2856, -3942, -2709, -3116, -6335, -2206, -6728, -1971, -2853, -8948, -2071, -11805, -3066, -1838, -12433, -2644, -6024, -5840, -967, -6445, -3627, -4214, -8153, -878, -4446, -4481, -3426, -6547, -1549, -3317, -5099, -2609, -5216, -2762, -2450, -5268, -1988, -4438, -4504, -1871, -4618, -2094, -3854, -7470, -1826, -3355, -2869, -3289, -17753, -2802, -2154, -3651, -2710, -7254, -5823, -1379, -3810, -2387, -4293, -7421, -1022, -3262, -2595, -2864, -4888, -984, -2695, -3096, -2603, -5210, -1266, -3076, -3220, -3347, -6868, -1982, -5280, -2894, -3896, -7007, -3145, -17998, -2759, -3266, -7738, -4097, -6380, -3554, -3183, -10779, -3979, -4415, -6024, -4240, -12735, -3976, -3511, -9161, -6071, -12265, -5311, -2484, -10379, -6941, -7090, -10284, -1505, -12420, -5684, -4708, -7921, -1099, -7151, -3929, -4140, -4845, -1423, -7725, -2906, -5352, -4079, -2415, -10884, -2767, -9575, -4751, -3868, -4996, -3267, -11989, -7115, -5006, -3391, -3812, -11979, -10810, -5188, -3586, -3784, -8891, -6382, -5441, -5553, -3438, -5727, -3479, -5894, -12436, -3191, -4619, -2024, -5517, -7064, -3122, -4018, -1711, -4483, -4948, -3381, -3236, -2307, -3707, -4471, -4159, -2468, -3365, -3586, -4439, -5249, -1958, -4202, -4446, -4159, -5909, -2016, -4686, -7049, -3815, -5830, -2881, -5316, -8985, -3897, -5727, -4315, -6894, -6111, -4099, -6446, -5802, -10967, -5680, -3778, -8126, -8852, -12693, -6969, -3660, -9269, -11311, -8799, -8984, -4230, -10135, -6885, -6827, -8416, -4706, -12410, -6134, -6142, -7269, -4802, -11045, -6734, -6913, -6875, -5306, -7901, -7838, -8307, -6747, -5268, -6268, -8514, -7424, -6007, -4627, -6013, -7963, -6595, -4887, -4943, -6881, -6893, -6953, -4348, -6424, 8312, 5887, 763, 6240, -363, 8294, 6155, 1032, 5545, -1258, 8007, 5877, 1907, 2928, -1251, 7048, 3746, 3572, -1938, 911, 5242, -371, 4533, 2396, 1978, 3126, 3069, 3923, 2713, 1787, 2172, 4094, 719, 14, 481, 3186, 4027, -121, -4285, 838, 4514, 3804, 2625, 180, 2550, 4919, 3657, 2521, 1067, 3483, 4582, 3362, 258, 2969, 3998, 4482, 2739, -6911, 4973, 4239, 4254, 3194, -2381, 5869, 4139, 2316, 4698, -612, 5539, 3654, -2238, 5395, -864, 3736, 2454, 913, 5114, -2219, 274, -5, 1216, 4154, -2132, 1318, -2522, -67, 2602, -1085, 2215, -2412, 131, -283, -886, 1268, -4026, 1186, -8097, -1710, -1149, -6953, 1561, -4291, -3347, -4797, -2354, 1522, -1303, -3727, -6138, -433, 1412, 133, -2083, -4125, -87, 815, -292, 172, -1455, -1082, -27, -3173, 1392, 845, -3508, 747, -2476, 1285, 1824, -1900, 1521, -1280, 820, 1686, 181, 1523, -4127, 1264, 491, 504, 1582, -1000, 1071, -3544, -907, 1450, 2030, -655, -2890, -3654, 3, 2817, -492, 659, -651, -4158, 2016, 1441, 818, 725, -10322, -840, 1979, -1194, -2, -8915, -5398, 1183, -1790, -2223, -6956, -2149, -1520, -56, -1105, -3460, -2442, -10631, 261, -303, -1559, -3357, -1627, -200, -1439, 167, -1243, -98, -570, -2185, 1208, 270, -178, -341, 51, 1412, 678, -1143, 5, 1425, 1216, -292, -1832, -159, 1825, 1256, -3538, -1494, -1115, 1555, 1587, -1977, -404, -2659, 1059, 1717, 80, 665, -3520, 841, 1159, 162, 792, -3107, 657, -448, -835, -464, -2113, 58, -3922, -1838, -3144, -1636, -806, -10528, -1556, -2638, -2444, -1534, -4173, -477, -1284, -3701, -2217, -3028, 311, -1290, -1968, -2833, -2955, 532, -2286, -406, -2998, -3034, 207, -3360, 179, -3012, -2639, -619, -2785, -62, -3928, -1952, -1977, -1827, -1392, -7686, -1681, -4262, -1592, -5592, -9053, -1987, -8758, -2354, -5422, -6045, -2718, -7035, -4539, -1752, -6965, -3828, -5662, -10232, -853, -7632, -5907, -6125, -6723, -855, -6549, -8259, -5978, -3467, -1133, -6529, -4785, -4562, -2279, -1386, -6847, -3401, -3669, -2823, -1427, -7821, -3833, -3606, -6032, -1374, -8088, -6000, -4148, -7704, -1368, -5769, -7785, -4977, -4936, -1565, -4181, -5556, -6132, -5997, -2140, -3599, -3794, -7335, -13081, -3091, -4133, -2413, -7218, -7692, -4501, -5860, -1528, -6840, -6739, -7249, -6578, -1438, -8422, -8001, -17811, -5284, -2387, -10105, -7352, -7847, -4947, -4342, -5643, -6214, -7228, -6386, -5210, -4781, -7105, -8778, -13916, -4956, -6509, -11004, -8787, -7620, -5986, -13650, -7198, -9389, -6170, -8564, -12574, -5441, -18478, -7578, -14813, -12988, -5656, -9929, -14786, -9762, -8635, -6950, -8535, -8450, -6373, -7771, -7891, -9058, -5077, -5412, -8878, -7258, -9097, -3639, 1446, 4870, 5496, 3432, 778, 2169, 4055, 4926, 2644, 1374, 2487, 1165, 2583, 1077, 1593, 1238, -9366, -4050, 2166, 1722, -1745, -4241, 2422, 3098, 2608, -1709, -11737, 3101, 2365, 2776, -656, -3138, 698, 90, 1600, -336, -1552, 42, 1775, 821, 87, -2168, 3276, 3289, 2542, -194, -1324, 4464, 2620, 4013, -3154, 646, 5129, 658, 5289, -802, 2092, 5542, 3390, 6094, 2705, 3242, 5233, 4793, 6071, 3909, 3952, 3664, 4131, 5190, 3726, 4040, -489, 463, 3738, 2159, 3503, -3730, 867, 2626, -1511, 2218, -177, 3882, 2668, -891, -258, -454, 4726, 2825, 821, -1874, 271, 4810, 2074, 230, -1089, 2122, 4593, -88, -2783, -2625, 2683, 4179, -4117, -7287, -3032, 1897, 3611, -3947, -3767, -1114, 377, 3060, -3057, -3805, -1994, 650, 2579, -4042, -6118, -6273, 1787, 1891, -5161, -6898, -5117, 1980, 863, -4271, -2408, -6868, 696, -89, -3863, -556, -3126, -4108, -359, -1906, 282, -431, -1615, -145, 439, 855, 479, 930, -166, 1445, 1122, 957, 828, -616, 1130, 775, 1433, -1303, -1174, -415, -162, 1415, -1521, -1711, -2517, -798, 37, -129, -1913, -2753, -848, -5232, -1012, -1887, -1764, -1762, -2590, -3901, -2498, -512, -2482, -429, -2118, -3514, 660, -1072, -597, -614, -4241, 1327, -790, -1868, -22, -3086, 1275, -2170, -2804, 433, -738, 732, -5131, -1557, 660, 408, 493, -6968, -83, 401, 317, 544, -3263, 920, -609, -882, 79, -592, 1584, -2882, -2961, -889, 747, 1898, -6333, -3936, -1213, 1066, 1671, -4477, -3040, -1196, 501, 605, -3687, -2741, -2076, -948, -1863, -3725, -3608, -3615, -3514, -8203, -2846, -5675, -4626, -7676, -5780, -2051, -5646, -4864, -7906, -4712, -1879, -4707, -4460, -8375, -6614, -2083, -5367, -4632, -16250, -14775, -2613, -7158, -5467, -7373, -10453, -3500, -9096, -6113, -6672, -12921, -4584, -8025, -7107, -9112, -8602, -5586, -6671, -8545, -6273, -4569, -6001, -6944, -6493, -3572, -3106, -5768, -6814, -5466, -2070, -2986, -5942, -6051, -6991, -1191, -3900, -7742, -5497, -10539, -980, -5624, -12196, -4103, -5565, -1540, -7062, -9523, -2878, -3827, -2988, -7111, -10643, -2372, -3418, -5831, -7249, -6598, -2449, -3770, -9218, -7702, -3064, -2873, -4524, -5252, -7390, -1470, -3361, -5234, -3699, -6322, -1108, -3863, -5805, -3796, -5425, -1798, -4517, -5806, -5718, -5233, -3353, -5104, -5088, -8064, -5966, -4350, -5365, -4661, -4926, -7452, -3960, -5678, -4644, -3868, -8402, -3993, -6276, -4768, -4497, -7430, -4679, -6686, -5100, -6680, -6008, -5367, -6348, -5765, -9584, -5354, -5330, -5759, -6800, -8074, -5635, -5118, -5631, -8313, -6312, -6572, -5525, -6352, -9706, -5356, -8122, -6676, -8115, -9754, -5232, -11807, -8113, -11082, -8604, -5830, -12132, -9036, -11127, -6709, 6577, 2520, 4753, 4151, -6277, 5589, 1368, 4321, 3621, 3271, 1874, 1192, 3362, 3087, 5773, -3867, 3437, 3263, 3753, 6554, 33, 4131, 3884, 3777, 6045, 1716, 3607, 3956, 2241, 4189, 2850, 2007, 3377, 1367, 1161, 1951, -1589, 2473, 3501, -395, 715, -2136, 1248, 4026, 2129, 3597, 349, -3343, 2390, 4017, 5389, -34, 904, 1934, 3345, 6038, 2492, 4607, 4228, -325, 5722, 4891, 5595, 3828, 4094, 4293, 5306, 4624, -1214, 5181, 1633, 3550, 792, 2721, 3531, 821, -5316, 717, 4457, 1230, 1080, 1384, 2685, 3550, 4020, -580, 2553, 2205, 205, 4954, -2816, 1369, 590, -8658, 4742, -1698, -1211, -629, -6616, 3828, -646, -3831, -237, -7037, 2574, -273, -4698, 467, -3754, 2042, -103, -5349, 849, -1731, 1984, 182, -8257, 951, -381, 1267, -129, -15880, 728, 94, 47, -1664, -9613, -14, -844, -405, -4780, -6293, -1484, -3930, -408, -5712, -3936, -4110, -1411, -383, -5165, -3535, -12188, 935, -295, -5321, -4553, -5474, 1539, -921, -1715, -3578, -2731, 969, -1541, 604, -1873, -1981, -490, -371, 1661, -1224, -2605, -2349, 191, 1867, -915, -4072, -4724, -641, 1362, -614, -5444, -7437, -1715, 46, -997, -7221, -4130, -770, -2305, -2440, -4308, -2677, -259, -4370, -3465, -1358, -2415, -715, -2586, -2698, -199, -2647, -834, -516, -1834, -588, -2857, -569, 258, -1793, -2251, -2194, -1192, -898, -1937, -2191, -852, -2583, -7152, 351, -1356, 102, -3698, -2950, 1852, -1932, 359, -6144, -1220, 1854, -2172, 55, -6653, -2009, 546, -1185, -340, -2419, -4113, -1290, -1150, -478, -1239, -6890, -2098, -2300, -959, -1842, -9870, -3081, -3299, -2614, -4334, -6524, -5286, -2315, -6323, -8689, -6324, -7051, -1389, -9340, -7912, -11485, -6039, -1331, -5992, -8125, -7089, -4737, -2125, -3981, -10595, -4020, -4177, -3806, -3357, -10943, -3272, -5259, -6807, -3837, -5883, -3671, -7274, -11253, -4242, -4281, -4544, -3604, -11765, -3483, -4209, -5169, -1853, -10870, -3008, -4896, -5876, -1572, -6055, -3923, -5510, -7833, -2223, -4625, -8226, -5841, -12540, -3583, -5274, -6509, -6567, -8375, -5407, -8003, -3287, -8715, -6207, -7424, -13138, -2446, -9753, -5663, -9630, -15199, -2672, -7218, -6661, -6037, -12704, -3539, -6174, -10491, -3939, -8698, -4719, -5061, -8431, -3339, -7629, -5801, -3775, -6080, -3854, -8518, -6103, -3128, -5811, -5276, -7916, -5332, -3191, -6563, -6015, -7152, -4632, -3752, -7412, -5063, -9671, -4680, -4701, -7650, -4302, -9953, -5723, -6167, -7995, -4104, -6363, -8287, -8535, -10190, -4399, -5858, -9631, -15346, -16341, -5128, -6659, -6771, -9534, -9119, -6612, -7005, -5858, -6761, -7614, -10632, -5834, -6800, -5861, -5931, -9280, -4667, -11591, -5616, -4315, -6135, -4309, -8330, -5613, -3928, -5865, -4985, -5460, -6193, -6200, -8553, -6508, -7937, -3343, -9220, -7479, -7092, -7098, -3815, -7377, -7211, -10560, -7407, -4573, -4819, -7566, -10829, -9354, -4967, -4005, -9157, -7836, -11251, -4939, -4060, -12517, -7841, -9124, -5106, -4032, -9702, -9763, -8266, -5876, -3708, -8169, -12969, -8955, -7321, -4019, -8001, -13153, -12277, -7778, -5533, -8327, -10652, -9170, -6266, -8421, -8485, -7668, -6262, -5238, -12272, -9176, -5981, -5445, -4819, -11447, -10176, -5855, -6189, -5005, -9051, -7100, -7117, -8724, -5961, -11311, -5790, -8166, -15544, -6816, -9360, -5149, -8190, -8935, -5866, -9914, -6606, -9288, -12789, -10198, -444, -785, 22, -512, -111, 3825, 3700, 4011, 3732, 4105, 5934, 5876, 6050, 5867, 6151, 6562, 6530, 6678, 6554, 6749, 5860, 5810, 6005, 5934, 6042, 3714, 3491, 3871, 3867, 3881, -362, -1720, -451, -332, -462, -8244, -5334, -9966, -11060, -13928, -14965, -3825, -7231, -7838, -7538, -14237, -5644, -11454, -9635, -12447, -11333, -7218, -10735, -7740, -14281, -7785, -7484, -7030, -8134, -10768, -7984, -8501, -5343, -10237, -8640, -10149, -11186, -5127, -16213, -8201, -9637, -11594, -6077, -11188, -8957, -7394, -11445, -8346, -8459, -9894, -6577, -12171, -11157, -7507, -9402, -7244, -8254, -10331, -7807, -8790, -9451, -6069, -11115, -9174, -9743, -15000, -5165, -15623, -9049, -13810, -14946, -4951, -14153, -7619, -17394, -12244, -5271, -10076, -7398, -15090, -10956, -6246, -8342, -8767, -16558, -10643, -7892, -8455, -11276, -11013, -12434, -9863, -11098, -10564, -8306, -14245, -11683, -14496, -10210, -7352, -10358, -11766, -9902, -11844, -7797, -8521, -9587, -9240, -12672, -9598, -7539, -8180, -10056, -9348, -11558, -6969, -8082, -10771, -7471, -10510, -7045, -8843, -10586, -6675, -9127, -8457, -8768, -9414, -6932, -8309, -12611, -7940, -7554, -8612, -8127, -10569, -7552, -6501, -11995, -8345, -8661, -7566, -6721, -11127, -8660, -8710, -7776, -8403, -9893, -9024, -10124, -8184, -9859, -9545, -8899, -13021, -8806, -8623, -9544, -8291, -12631, -9539, -8508, -10086, -8184, -10718, -11079, -9891, -10988, -8798, -9846, -15501, -12770, -12005, -9506, -9090, -11859, -16988, -13076, -9577, -8205, -10545, -15281, -12434, -9458, -7601, -10825, -15101, -10698, -9846, -7697, -9290, -15813, -9752, -11370, -8616, -8167, -14591, -9649, -15588, -9597, -8495, -15462, -9906, -14673, -9892, -9926, -20536, -9793, -11426, -11057, -10986, -12734, -9231, -10131, -14054, -10780, -10743, -8703, -9892, -13703, -10864, -10543, -8545, -10911, -13096, -11370, -11418, -9104, -13976, -11827, -11626, -12918, -11025, -13271, -9958, -11491, -14768, -15232, -11312, -9615, -11615, -13200, -12779, -11637, -10649, -12531, -11272, -11775, -13881, -10788, -13604, -10618, -12568, -17230, -9775, -13103, -10832, -13373, -17598, -9893, -12065, -11959, -13262, -15866, -11391, -11454, -14518, -13114, -14350, -13728, -11407, -14804, -13246, -14622, -13285, -11845, -13064, -12030, -18307, -11760, -12159, -12305, -10412, -15123, -6324, -9477, -9400, -7057, -5710, -6352, -8487, -9278, -5078, -6096, -6298, -7707, -8482, -4442, -8448, -5661, -7246, -8358, -4752, -12692, -5302, -6206, -10007, -5788, -7182, -6166, -4983, -13270, -7494, -5273, -8510, -4454, -10594, -9438, -4780, -10193, -4690, -8615, -10919, -5125, -11052, -5489, -7798, -13036, -5854, -12236, -6499, -7745, -7401, -6635, -10632, -7170, -7794, -4840, -7557, -11145, -7431, -7733, -3910, -8096, -11765, -8948, -8494, -4135, -6962, -9891, -12542, -10049, -5225, -5766, -10963, -10163, -8393, -7226, -7008, -9025, -7379, -6072, -8597, -9535, -13454, -7980, -10483, -10619, -10454, -524, -357, -673, -521, -913, 3774, 3850, 3806, 3801, 3726, 5896, 5951, 5941, 5949, 5967, 6539, 6579, 6562, 6618, 6666, 5850, 5857, 5818, 5968, 6006, 3680, 3600, 3535, 3900, 3852, -704, -1039, -1074, -41, -442, -20425, -13137, -8880, -7008, -7180, -7676, -7249, -9812, -10616, -7360, -10279, -5481, -10821, -11285, -6744, -11031, -5069, -9065, -12055, -6518, -9991, -6225, -8756, -16333, -8667, -10592, -8419, -8312, -11250, -10011, -12191, -13430, -7967, -10377, -10608, -12739, -13080, -6812, -11457, -12300, -13509, -10314, -6313, -16158, -13876, -18989, -8759, -6995, -16806, -12813, -11600, -7944, -8763, -18811, -7810, -8523, -8087, -8626, -13671, -5455, -7530, -9310, -6986, -10603, -4667, -7855, -10926, -6627, -10213, -5114, -9406, -10426, -7630, -10276, -6652, -10178, -9082, -9365, -9640, -9105, -8955, -8049, -10069, -9361, -12141, -8768, -8044, -10018, -10155, -15871, -8742, -9890, -9962, -13161, -22128, -8200, -13833, -10789, -16792, -13824, -8273, -10713, -12965, -14624, -10183, -8548, -10172, -10605, -20387, -7962, -7851, -11897, -8350, -13740, -6838, -7172, -13924, -7292, -11677, -6817, -7315, -12211, -6859, -11522, -8153, -8547, -10846, -6858, -11643, -11284, -10893, -10119, -7332, -10993, -11217, -11394, -10115, -8360, -10006, -9632, -11033, -10993, -9848, -9822, -9397, -11758, -12169, -11656, -11314, -9647, -10253, -11377, -15028, -17323, -9926, -8792, -9976, -15320, -14192, -10389, -8646, -9355, -11446, -12505, -11423, -9549, -9778, -10204, -13602, -12870, -11143, -11814, -10021, -18248, -12820, -12849, -14717, -10517, -16157, -11201, -13626, -10610, -12078, -13136, -9927, -13163, -8579, -14304, -11833, -9257, -12540, -7856, -12246, -10955, -9144, -12407, -8209, -10861, -10350, -9797, -13195, -9967, -10891, -10379, -11896, -15556, -14905, -11801, -11591, -19418, -16477, -13344, -11845, -15351, -14372, -14073, -11411, -10850, -18659, -12416, -13199, -12060, -10790, -15823, -12264, -12718, -14280, -12046, -18986, -12902, -11598, -15084, -12664, -17066, -13984, -10396, -15153, -11569, -16303, -14781, -9857, -17401, -11389, -22830, -13452, -10185, -27068, -12151, -13558, -11746, -11330, -16623, -13653, -11224, -11074, -13063, -14198, -16091, -10707, -11621, -15303, -13355, -14189, -11493, -13829, -17195, -14040, -11965, -13852, -18027, -14642, -17286, -11045, -17219, -15206, -12429, -22284, -10583, -15085, -14255, -5111, -8181, -6549, -4897, -8234, -8490, -18312, -7810, -5765, -17195, -9800, -10653, -8301, -7841, -9189, -8646, -14834, -8803, -9710, -7281, -9213, -10024, -8625, -9340, -7338, -8926, -7689, -7824, -9330, -9147, -8812, -8023, -6553, -11359, -13026, -9700, -9056, -5691, -13529, -8406, -8745, -9062, -5610, -9201, -6813, -7212, -9078, -5853, -7526, -6881, -7424, -9496, -6434, -7064, -7710, -9464, -9887, -8019, -8062, -9180, -11192, -8688, -9004, -14243, -11558, -10074, -6315, -7134, -10315, -9984, -10918, -5924, -6393, -10145, -11123, -9806, -6673, -6775, -7294, -7563, -10028, -6767, -6627, -6054, -8211, -673, -269, -153, -410, -462, 3658, 3899, 3790, 3794, 3863, 5808, 6013, 5839, 5920, 5990, 6444, 6660, 6471, 6571, 6643, 5689, 5989, 5790, 5895, 5987, 3325, 3884, 3647, 3761, 3929, -1754, -187, -639, -440, 50, -8211, -8616, -11834, -10163, -5789, -7590, -10466, -8996, -13313, -6715, -11943, -10600, -9727, -8406, -6591, -9097, -9376, -8364, -7190, -6668, -9015, -8462, -8907, -8539, -6303, -8460, -7343, -9806, -10953, -6011, -7663, -6472, -10571, -9496, -6413, -6880, -6655, -11790, -8082, -7031, -6522, -8223, -11268, -8737, -7692, -7118, -10117, -11663, -12041, -8448, -9533, -9593, -15313, -12392, -9478, -18602, -8816, -11429, -8895, -12054, -11179, -8822, -9217, -7784, -14643, -9564, -9603, -8496, -7855, -9020, -8861, -10482, -8191, -8705, -7733, -9082, -10202, -8062, -11167, -8627, -11604, -8907, -8473, -16546, -10658, -11858, -7812, -9627, -9355, -8890, -8190, -7538, -10633, -7706, -7730, -6849, -8080, -9108, -7559, -8057, -6720, -9112, -7655, -8306, -9830, -7647, -9889, -7064, -9763, -12763, -10007, -9471, -7045, -11985, -12538, -15469, -8243, -7479, -13782, -13003, -15736, -7151, -8434, -12474, -20353, -12992, -6507, -9800, -11537, -12301, -10376, -6345, -10815, -11652, -9995, -9366, -6590, -10528, -12500, -9541, -10271, -7098, -9549, -13197, -9750, -10632, -7794, -8985, -12956, -10146, -8248, -8486, -9275, -12169, -11215, -7216, -8669, -10398, -11343, -13727, -7454, -8569, -11756, -11006, -18229, -8521, -8946, -12224, -11114, -19315, -9737, -10248, -12077, -11015, -19702, -10458, -12370, -12977, -10475, -14351, -10803, -11973, -16841, -9938, -11685, -11222, -10314, -13740, -9705, -10829, -11841, -9569, -11818, -10113, -11856, -11386, -9666, -11946, -12096, -16134, -10401, -10214, -12794, -20737, -13145, -10467, -10065, -13294, -10923, -11149, -11854, -9264, -13455, -8919, -11022, -12777, -9041, -13589, -8787, -12370, -11861, -9846, -15421, -10085, -14716, -11869, -11867, -17826, -12719, -11822, -12688, -15281, -12752, -15662, -10433, -12735, -18034, -11246, -19506, -10818, -12305, -15670, -11170, -13583, -11790, -12741, -14857, -11642, -11180, -10749, -14781, -16906, -11816, -10866, -9400, -21844, -15369, -11386, -12020, -8669, -18289, -11859, -10840, -13480, -8294, -17206, -10414, -10607, -13398, -8217, -16096, -10103, -10802, -13232, -8573, -14197, -10582, -11426, -13681, -9469, 13787, 14482, 4978, 9252, 11837, 13142, 13944, 4781, 8623, 11115, 11041, 12305, 4122, 6636, 8769, 6500, 9549, 4653, 3113, 4014, 364, 6117, 5897, 1273, -1449, 4622, 4026, 5912, 1807, -4079, 4377, 4233, 4397, 762, -2972, 2131, 4306, 2088, -94, -1821, 731, 3764, 2965, 2827, 2767, 3262, 3394, 4029, 4634, 4859, 3406, 3613, 4412, 5302, 5672, 1375, 4227, 4558, 5029, 6061, -3400, 4918, 4488, 3616, 6377, -5761, 5197, 3982, 355, 6282, -1053, 4744, 2957, 363, 5315, 1144, 3424, 2115, 2646, 3131, 1395, 1044, 2637, 3056, 656, 956, -3300, 3401, 2110, 1208, 105, -6609, 3508, 681, 1312, -4040, -3827, 2964, 2051, 978, 1360, -3994, 2019, 3680, 1426, 4160, -4790, 653, 4368, 1589, 4987, -2691, -1786, 4311, 977, 4326, -936, -2880, 3675, -26, 1433, -152, -260, 2708, -1196, -3895, -336, 944, 2077, -1140, 1532, -1804, 1016, 2018, -230, 1660, -1298, -2, 1662, -783, -759, 725, -2655, 492, -2131, -5217, 1363, -4750, -1417, 88, -5661, 1034, -2778, -3746, 1317, -4242, 311, -3574, -8503, 817, -373, -340, -2916, -7619, -68, 2394, -443, 58, -4328, 1397, 3818, -149, 1292, -2863, 2312, 3943, -590, 1294, -1452, 1738, 2645, -2903, 176, -1242, -587, -913, -3009, -2557, -3482, -6100, -3543, -97, -9954, -8191, -6916, 150, 820, -8630, -3025, -6507, 1377, 444, -7535, -2068, -5282, 1773, -1119, -5293, -1568, -3256, 1565, -4468, -4636, -860, -2027, 631, -6159, -6005, -239, -1157, -1430, -4037, -5551, 152, -397, -5342, -3689, -2472, 10, 41, -3431, -3131, -596, -819, -40, -1561, -2261, 413, -2281, -549, -1152, -1936, 780, -3916, -1306, -1405, -1886, 549, -3835, -2180, -1917, -1818, -387, -2792, -3422, -2357, -2055, -2215, -2501, -6241, -2373, -2782, -4704, -3033, -8393, -2033, -4217, -6929, -4108, -6246, -1681, -8068, -11620, -5597, -7465, -1732, -6024, -6720, -8259, -13971, -2807, -3209, -4535, -10705, -11232, -6537, -2961, -4340, -6189, -8549, -6525, -4973, -5306, -4475, -6917, -3450, -8409, -6693, -4114, -8079, -3555, -4950, -7082, -4463, -11262, -6691, -4196, -5694, -5222, -4124, -9836, -4855, -3625, -6954, -1699, -5164, -4765, -1928, -14286, -663, -4169, -4080, -956, -6668, -472, -3927, -4223, -808, -4050, -927, -4054, -4659, -1518, -3273, -2043, -4659, -4806, -2857, -3485, -4026, -5012, -5753, -3289, -4506, -7114, -4157, -8458, -2383, -6814, -8776, -3046, -10124, -1919, -9729, -8006, -2438, -8481, -2476, -7223, -8942, -2651, -8119, -4495, -6713, -10699, -3729, -9751, -9391, -8462, -9084, -4869, -12085, -14189, -11420, -7217, -4537, -9290, -6958, -10445, -5602, -3890, -8713, -2884, -7885, -5075, -4081, -6824, -993, -5433, -6297, -5445, -6813, -581, -4298, -11537, -8013, -10279, -1352, -4068, -9035, 8985, 6518, 7563, 8877, 9046, 8234, 6594, 7027, 8347, 8532, 6331, 5677, 5772, 6952, 6924, 5024, 981, 5111, 5260, 4061, 3806, 2037, 5742, 3558, 440, 967, 4386, 6629, 2409, -783, -883, 3656, 7114, 1283, -349, 2952, 2413, 7141, -2137, -67, 5129, 3158, 6509, -1857, 1100, 5734, 3958, 4491, -2596, 2334, 5404, 4255, -814, -4981, 2856, 5080, 4016, 3871, 763, 3031, 5362, 3360, 5969, 2332, 2827, 5563, 3133, 6510, 2666, 2052, 5428, 3497, 6210, 2579, 1018, 5290, 3136, 5414, 2374, 388, 5181, 962, 4383, 1588, 226, 4666, -8481, 3193, -1021, -410, 3159, -2200, 1715, -119, -2705, -842, -2369, 539, 2781, -10846, -1682, -8065, 649, 3237, -2652, 2167, -6821, 272, 1411, -187, 3126, -4139, -1393, -1419, 809, 2593, -188, -2666, 1660, 526, 549, 1751, -2642, 2880, -2175, -3542, 2355, -1774, 3630, -3843, -7162, 2117, -33, 4132, 594, -10058, 1187, 935, 3783, 1152, -5997, -1100, 903, 2279, -742, -2986, -9530, -343, -685, -1943, -1738, -800, -4534, -5764, -203, -1451, 1532, -3386, -6807, -385, -1934, 2482, 154, -5475, -748, -492, 2676, 1176, -4795, -405, 1741, 2257, 901, -4046, -832, 3050, 1426, -528, -2648, -2209, 3695, 768, -3119, -495, -2869, 3888, 478, -7138, 1492, -1466, 3557, -528, -7174, 2892, -1106, 2438, -2650, -3884, 3745, -2364, -20, -2147, -2024, 4007, -3977, -5755, -2340, -122, 3501, -3717, -2271, -6275, 838, 1949, -2174, -28, -2191, 445, -1442, -698, 540, -615, -1399, -6006, -537, -92, -1203, -4365, -1382, -2154, -1656, -2113, -3715, -389, -7872, -2267, -1547, -2291, -928, -3354, -1762, -1495, -2020, -2464, -599, -1845, -2575, -2336, -4021, 372, -2314, -4497, -2622, -4010, 282, -2952, -6128, -2952, -3405, -535, -3805, -5759, -4534, -3411, -1497, -3776, -4343, -9672, -3453, -2263, -3392, -3115, -3355, -2792, -3364, -4273, -2577, -1414, -2260, -5289, -5577, -3117, -1496, -2341, -8298, -4319, -5022, -3242, -2912, -10586, -3495, -6735, -4189, -3526, -8272, -2519, -5886, -3111, -3694, -6397, -1252, -4882, -4093, -3443, -5273, -804, -4317, -8079, -3204, -5308, -1356, -5169, -5436, -3218, -6950, -2610, -7845, -5021, -3555, -7503, -3948, -7689, -5972, -4387, -6617, -5066, -6911, -3284, -5760, -8977, -5918, -6541, -1693, -5689, -10069, -5800, -5469, -1504, -3599, -6215, -5202, -4553, -2416, -2353, -5588, -4994, -3747, -4273, -2588, -5373, -5430, -3370, -6208, -5044, -4717, -6317, -4029, -6065, -5950, -4743, -6737, -6835, -5706, -3061, -5988, -6782, -8754, -7073, -2705, -8530, -6424, -4552, -7345, -4113, -12075, -5777, -3244, -3463, -6001, -15697, -6055, -2947, -1629, -6014, -9874, -7633, -2862, -1191, -6825, -7375, -9082, -2771, -1903, -6828, -6079, -12057, -3123, -3750, -5684, -5858, 7254, 3780, 5352, 8324, 7066, 7171, 3086, 5094, 7895, 6213, 6727, 851, 4354, 6526, 3843, 5390, -2087, 3193, 4117, 3207, 2262, -2314, 1654, 2565, 3126, 2013, 745, -46, 3361, 1325, 4042, 3062, -104, 3836, 2767, 4176, 3288, 1227, 4010, 3783, 3360, 1017, 1727, 3485, 2176, 2138, -2184, 1294, 1347, -6664, 531, 1541, -80, -1763, 1195, -1041, 2582, -3103, -380, 1419, -1732, 2633, 1146, -1351, 1509, -3214, 1956, 3383, 707, 3109, -4593, 393, 3552, 2910, 2673, 1140, -2294, 1842, 3182, 2083, 3269, -1350, -478, 1649, 4232, 3696, 858, 1509, -3165, 5058, 2523, 1699, 2458, -4177, 4411, -2484, 2717, 2408, -2617, 2814, 58, 3860, 2037, -6038, 2143, 3316, 4150, 1901, -3622, 2863, 4118, 3282, 2190, -1326, 3523, 3616, 979, 2192, -1138, 3638, 1956, -3769, 1246, -1925, 2589, -1005, -4772, -664, -3082, 144, -4808, -5487, -1236, -3921, 1631, -3920, -4314, -289, -1963, 3125, -997, -878, 536, 568, 3125, 1100, -87, 1132, 2375, 2481, 2173, -588, 916, 3384, 1815, 2460, -1252, -670, 3538, 1108, 2340, -1871, -4154, 2703, 850, 1950, -2672, -4339, 499, 1269, 1169, -3861, -2132, -4124, 1562, 169, -6132, -261, -2596, 1437, -843, -2396, 722, -781, 871, -1632, -1151, 484, -292, -168, -807, -2771, -188, -270, -1242, 784, -14377, 384, -752, -1214, 1457, -2334, 652, -2146, -1095, 669, -88, -423, -4151, -2159, -1953, 663, -2218, -4541, -2894, -2170, 348, -3093, -5154, -892, -404, -488, -3708, -4906, 109, -283, -802, -2311, -3105, -386, -1719, -713, -1343, -2995, -2943, -6075, -972, -1948, -5119, -4035, -6812, -2209, -3295, -11489, -1136, -4506, -5033, -2868, -7918, -847, -5278, -7842, -2304, -3639, -2461, -4408, -11924, -2104, -1206, -4600, -2108, -7483, -1639, -277, -4610, -1091, -4659, -1884, -464, -3838, -1260, -5409, -3828, -1361, -2961, -2613, -11108, -7331, -2289, -3521, -5412, -5253, -5834, -2362, -7268, -7961, -3699, -5927, -1680, -7667, -6690, -4054, -7101, -1061, -4319, -6204, -4494, -5229, -805, -4567, -6323, -4150, -3547, -893, -8945, -6568, -4867, -2577, -1066, -7158, -7404, -8847, -2021, -890, -4696, -10328, -8292, -2006, -644, -5885, -7639, -5119, -2603, -1086, -10119, -4971, -4890, -3480, -2684, -5412, -4289, -6038, -4012, -5439, -4182, -4826, -6486, -4081, -6591, -4286, -6108, -5920, -4195, -6369, -4245, -8101, -5814, -4660, -6888, -4094, -8298, -5812, -5539, -7734, -4961, -5751, -5919, -6810, -8659, -8082, -4912, -6634, -7885, -10439, -10783, -5265, -8314, -7614, -11534, -7287, -5005, -10458, -6328, -7728, -6504, -3880, -9864, -5156, -6502, -6430, -3550, -9472, -4517, -7652, -6597, -4643, -8696, -4595, -11083, -7127, -7788, -6724, -5271, -8046, -8521, -10178, -5892, -5092, -6057, -10780, -9513, -5852, -2958, -4130, -5138, -9591, -4239, -4771, -4595, -3537, -7593, -4988, -6791, -6457, -3617, -5186, -9184, -8984, -9752, -5332, -3757, -9695, -8023, -9904, -8192, -3567, -7496, -5663, -6636, -10251, -4988, -10139, -4265, -5209, -8259, -7312, -10026, -4064, -4842, -5919, -6798, -9178, -5491, -4279, -5506, -4718, -6877, -7453, -4436, -4938, -5641, -10793, -7051, -8165, -5146, -6237, -5783, -3706, -5657, -6567, -6163, -7552, -5332, -4544, -7934, -4428, -7473, -7132, -2816, -3669, -7263, -5272, -6182, -5161, -8287, 1297, 1380, 382, 427, 1207, -5695, -8279, -4121, -8316, -6680, 8561, 8618, 8700, 8553, 8437, 13004, 13007, 12983, 12916, 12893, 15159, 15134, 15101, 15057, 15049, 15814, 15765, 15745, 15709, 15700, 15123, 15045, 15056, 15018, 15001, 12934, 12800, 12884, 12824, 12786, 8481, 8155, 8507, 8337, 8234, -6212, -3159, -3672, -8783, -6067, 355, 1573, 140, 692, 704, -6870, -5118, -3656, -13381, -7976, -3363, -8489, -2432, -4041, -3085, -13187, -6128, -4945, -14447, -7311, -7663, -3928, -4995, -7782, -6564, -11356, -5002, -6850, -10812, -11615, -6916, -5388, -8674, -8337, -12006, -7994, -4573, -8011, -5441, -11762, -8180, -4139, -6462, -4421, -16667, -10089, -4886, -7481, -4405, -7607, -13750, -5921, -8591, -4365, -5118, -9873, -7548, -9934, -5196, -5328, -8781, -10656, -14920, -6792, -7727, -9037, -11447, -11389, -8594, -14847, -9884, -10947, -8958, -9617, -6934, -9289, -10973, -8780, -9326, -5223, -7221, -8742, -8512, -9119, -5599, -6083, -6824, -7067, -9787, -7035, -6014, -5755, -6035, -12388, -7980, -7264, -5557, -6080, -13525, -8373, -10795, -6081, -7427, -10104, -7020, -11727, -7375, -11093, -7431, -5927, -8775, -8995, -13316, -5955, -5824, -8544, -9358, -9168, -5567, -6647, -11194, -9332, -7582, -5880, -8291, -12999, -10338, -6506, -6668, -9652, -8827, -10795, -6129, -8010, -10285, -7865, -9139, -6920, -9528, -11676, -7471, -8425, -8858, -9571, -11366, -7427, -8712, -10255, -9618, -10512, -8751, -8954, -9471, -11316, -11523, -14983, -9112, -8722, -16038, -13343, -10452, -10208, -9099, -11641, -9484, -7683, -10772, -11344, -9792, -7278, -7034, -11116, -15446, -10288, -6693, -7359, -16187, -12218, -11828, -7788, -7894, -9483, -11724, -10789, -12571, -8252, -6930, -13333, -10655, -11221, -8965, -6238, -12123, -12075, -8249, -10092, -6645, -9684, -12421, -8088, -9963, -7965, -8294, -11999, -9632, -8837, -10239, -7443, -12000, -13315, -8706, -11505, -7439, -12416, -14043, -10646, -10071, -8528, -13571, -10865, -15017, -8877, -10497, -11921, -8804, -11247, -7730, -13069, -10791, -7478, -11828, -6398, -15423, -12001, -7192, -20448, -5201, -16101, -13201, -8376, -13641, -4585, -14289, -9748, -13001, -13041, -4645, -11616, -8328, -11523, -14627, -5170, -11110, -8451, -8356, -13502, -5950, -12049, -9883, -7761, -10373, -7152, -12526, -12659, -8455, -8713, -9156, -11939, -16142, -9589, -8459, -12138, -11687, -14965, -9961, -10498, -4366, -6670, -6268, -6777, -7229, -6131, -9281, -8240, -7699, -8929, -7196, -10164, -9029, -7444, -11207, -7603, -9629, -8669, -5848, -6033, -7414, -11634, -7184, -5213, -4398, -8612, -8062, -6308, -5370, -3304, -13810, -6177, -7408, -4579, -2825, -7811, -5579, -7973, -3825, -3546, -6430, -4992, -8108, -3809, -4781, -4527, -4429, -6506, -4269, -4491, -4848, -3487, -4891, -7768, -3571, -7588, -2584, -3465, -8846, -7026, -5220, -5205, -4060, -11604, -5445, -2622, -4630, -3540, -3661, -13629, -16253, -13092, -4810, -7932, 231, 618, -82, 543, 843, -6248, -7054, -4917, -3788, -8231, 8605, 8622, 8675, 8654, 8498, 12929, 12970, 12956, 12954, 12918, 15061, 15099, 15067, 15070, 15063, 15710, 15741, 15699, 15705, 15706, 15022, 15042, 14988, 14999, 15003, 12839, 12842, 12761, 12787, 12794, 8398, 8357, 8181, 8271, 8320, -6355, -9827, -5114, -8031, -11445, 742, 449, 897, 548, -492, -6196, -9566, -10589, -7494, -5073, -8525, -3144, -3699, -3026, -2223, -5070, -7672, -10938, -5874, -3889, -3862, -8293, -8123, -6864, -3393, -7232, -5562, -14238, -6677, -5029, -8078, -4318, -11472, -7169, -5990, -6359, -5438, -12955, -9248, -7282, -4699, -6061, -8298, -7138, -7975, -4437, -5255, -4977, -7199, -7408, -4404, -5040, -4346, -6498, -8164, -4424, -5932, -5922, -6287, -13094, -5022, -6947, -8673, -7353, -11799, -6385, -7265, -8889, -6892, -9465, -7244, -8190, -8641, -5854, -8326, -7533, -11441, -8925, -6478, -7704, -8121, -12430, -8424, -8580, -8303, -8555, -9459, -7952, -11706, -10874, -8801, -7781, -7932, -11601, -11746, -9392, -6681, -8702, -9492, -10771, -8897, -6269, -11134, -7989, -10751, -7531, -6453, -13250, -7211, -8926, -7404, -7610, -10312, -7486, -7607, -8600, -12793, -8181, -8674, -7479, -10202, -9162, -6921, -8904, -7697, -11286, -6098, -6608, -7722, -7804, -11937, -5398, -6998, -6592, -8510, -11931, -6006, -7656, -5732, -10168, -11643, -7700, -7865, -5153, -9670, -11404, -9945, -7621, -4734, -7718, -11938, -10592, -7930, -4469, -6955, -14370, -10031, -9183, -4556, -7329, -15667, -10284, -10498, -5050, -8892, -12373, -11084, -10118, -5802, -11839, -10744, -9393, -8932, -6557, -10599, -9939, -8174, -8555, -6929, -8379, -9147, -8371, -9724, -6772, -7539, -8646, -9213, -12563, -6454, -7698, -9055, -8331, -11230, -6225, -8717, -10672, -6809, -10830, -6241, -10608, -14785, -6331, -14765, -6812, -12383, -14279, -7241, -12980, -8388, -10530, -11516, -10115, -9969, -11681, -8633, -11517, -17696, -8967, -17098, -7730, -9999, -15671, -8469, -13164, -7734, -8058, -16219, -8806, -10957, -8309, -7622, -12298, -10108, -10766, -8402, -8250, -10221, -11010, -13232, -7994, -8410, -9360, -11065, -14546, -7912, -7768, -9280, -10873, -10923, -7989, -7800, -10287, -9905, -10087, -8439, -9129, -12060, -9325, -10332, -10265, -12743, -9949, -9270, -9962, -11686, -19639, -8180, -9033, -9152, -9150, -14519, -7532, -8746, -9194, -8408, -10822, -6541, -4087, -5366, -7217, -12242, -8318, -3539, -5595, -5565, -10054, -10115, -3416, -6678, -5715, -9487, -10487, -3463, -9138, -5286, -11194, -7805, -3598, -8649, -4087, -14458, -5912, -3513, -5294, -3330, -15491, -5595, -2995, -4509, -2842, -9703, -5078, -2744, -5044, -2878, -6441, -4684, -3510, -5504, -3700, -5324, -5093, -4428, -5770, -3850, -7746, -5534, -4368, -9431, -3672, -6965, -5120, -3532, -8148, -3980, -5835, -12972, -4140, -6914, -7836, -3209, -4326, -4421, -2653, -4978, -4388, -5867, -4333, -6509, -8827, 759, 1307, 1420, -92, 441, -7569, -6729, -8428, -3816, -5727, 8547, 8521, 8509, 8797, 8689, 12911, 12937, 12918, 13017, 12962, 15045, 15072, 15054, 15101, 15063, 15687, 15707, 15695, 15716, 15688, 14985, 14996, 14991, 14996, 14973, 12773, 12778, 12783, 12769, 12751, 8257, 8274, 8289, 8231, 8207, -5729, -13222, -9847, -7725, -6606, 365, -216, 347, 366, 774, -5794, -4154, -13970, -10100, -11214, -3024, -1610, -5056, -3311, -4302, -8556, -5486, -9925, -10494, -10449, -8816, -15377, -7035, -9377, -10897, -9692, -6966, -10351, -7962, -7623, -6415, -5614, -6263, -6224, -6176, -8085, -6004, -8928, -7974, -8482, -8961, -6683, -15713, -8733, -11044, -8909, -9524, -9595, -6530, -10027, -9220, -16761, -7156, -6052, -9278, -8183, -10191, -6519, -8056, -10499, -7503, -8314, -6524, -9726, -8568, -7912, -7454, -6168, -7788, -6564, -8006, -7323, -6360, -6623, -5660, -7513, -8958, -7956, -6270, -5558, -7624, -12761, -8830, -6275, -5664, -9072, -13250, -8080, -6211, -5807, -11441, -10268, -8066, -6481, -6255, -11688, -8512, -8791, -7602, -6731, -9345, -7804, -8950, -9074, -6544, -7603, -7631, -7568, -9252, -6544, -6215, -7159, -6531, -8562, -7341, -5194, -6266, -6163, -8140, -8458, -4865, -5520, -6092, -7987, -7760, -5326, -5329, -6243, -7926, -6852, -6405, -5870, -6721, -8345, -7595, -7663, -7234, -7119, -10125, -10775, -8350, -8534, -7286, -16410, -8787, -7965, -7840, -7968, -12117, -7281, -7110, -7247, -9360, -9899, -8670, -6584, -7114, -10510, -9248, -13548, -6732, -6288, -10753, -9136, -8383, -7539, -5229, -10635, -9847, -7519, -8798, -4756, -9004, -10133, -9215, -10716, -5047, -7250, -7926, -15045, -11737, -6079, -6478, -6366, -13869, -9279, -7261, -6801, -6041, -12884, -8079, -7599, -8272, -7054, -12862, -8067, -7855, -10268, -10148, -11724, -8568, -8570, -10879, -14031, -10273, -8699, -9357, -11814, -9495, -8848, -8366, -10098, -12661, -8400, -7876, -8351, -10997, -11791, -8652, -7701, -8922, -10359, -10201, -9356, -8575, -9593, -9505, -8288, -9822, -11194, -10080, -11126, -7323, -10529, -21742, -10828, -10949, -7205, -11905, -11172, -12073, -7210, -7450, -13675, -9491, -14562, -6110, -8045, -13884, -9622, -13397, -6723, -9438, -11220, -11368, -11545, -9052, -12156, -10030, -16389, -12288, -12561, -18890, -10493, -15268, -16791, -11629, -15410, -12913, -14502, -14921, -11217, -12042, -19888, -28647, 13098, 8550, 12481, 11510, 6595, 12477, 8828, 11738, 10975, 6030, 10405, 8846, 9290, 9300, 4418, 5407, 8596, 4699, 6340, 3498, 4144, 8868, 3899, 2446, 4495, 6787, 8970, 2932, 1036, 4904, 6608, 8465, 1355, 3923, 4740, 4907, 7665, 1149, 4657, 4591, 551, 6910, 744, 2513, 4346, 634, 6196, 1842, -279, 3940, 3736, 5306, 2460, 4698, 3741, 4214, 4093, 2261, 6028, 3943, 2999, 3252, 2051, 5861, 4558, -1126, 3221, 2513, 4490, 5250, -2272, 2371, 2501, 2731, 5767, 1238, 375, 1447, 3380, 5850, 1900, 2377, 1045, 3946, 5011, 2334, 3950, 2051, 3233, 2580, 3282, 3982, 2613, 1159, 159, 3710, 2869, 2481, 487, 1210, 3661, 1243, 1716, 2588, -657, 4677, 1926, -421, 3542, -546, 5690, 3141, -7300, 3727, 2018, 5486, 2751, 1503, 3443, 2021, 4042, 1177, 3537, 2839, 305, 2858, 2208, 3935, 2313, -2395, 2622, 2907, 3506, 1766, -2201, 820, 1286, 2877, 816, -25, -2138, -2230, 2460, -253, 1158, -185, 2089, 2181, -948, 1834, -429, 3619, 1837, -1815, 2181, -2963, 3555, 1253, -3382, 1436, -7497, 2318, -221, -1989, -2519, -3937, 466, -5658, -553, -383, 130, 109, -2147, -554, 2605, 1478, 993, 944, -327, 2950, 1038, 1962, 1665, 621, 1470, -1293, 2675, 1147, 637, -1902, -6527, 2557, -113, -766, -2756, -2414, 1072, -1280, -3066, -1732, 176, -407, -1687, -1358, -1275, 1793, 1532, -1903, 714, -738, 2727, 2283, -2128, 1424, -1013, 2830, 1480, -1826, 1085, -2187, 1872, -748, -1223, 504, -1724, -540, -3577, -1331, 302, -372, -3290, -3077, -2456, -212, 453, -1665, -2179, -2590, -1244, 769, -958, -2758, -1194, -2220, 646, -1298, -5466, -206, -3085, 298, -2484, -13396, 244, -3976, -448, -5072, -6577, 67, -3844, -1491, -15234, -3075, -866, -2785, -1116, -7562, -1541, -2665, -2528, -294, -7910, -1687, -5553, -3298, -160, -10161, -3578, -10016, -3192, -472, -3439, -5625, -9486, -2319, -951, -1201, -4550, -9342, -2459, -1431, -458, -4420, -6978, -3757, -1541, -854, -3911, -4840, -6298, -1450, -2480, -2853, -3829, -7433, -2031, -5517, -2518, -2354, -5552, -3672, -8558, -2856, -980, -3831, -4039, -6818, -3270, -177, -2357, -3496, -4436, -2980, 111, -1947, -5155, -3473, -2306, -187, -2633, -5752, -3380, -2078, -1182, -3664, -3089, -3429, -2692, -2826, -3918, -2817, -3812, -4573, -4250, -3465, -4590, -5220, -9117, -4231, -3124, -8516, -7993, -11830, -4338, -3576, -11939, -7717, -7077, -4823, -4840, -12315, -4104, -4608, -4103, -4752, -7408, -1875, -3730, -3127, -3489, -5600, -790, -4849, -3237, -3361, -3940, -662, -9472, -4932, -4740, -2668, -1493, -4366, -5298, -7908, -2498, -3603, -2126, -3150, -9119, -3642, -8609, -1767, -2772, -5899, -6106, -6767, -2754, -4208, -3280, -5059, 6690, -8153, 10131, 7048, -919, 6500, -1237, 9535, 7554, 1466, 5763, 2689, 7584, 8134, 2435, 4781, 4620, 3350, 8012, 1830, 5661, 5048, 658, 7105, 778, 6783, 4105, 3704, 5783, -74, 6618, 2593, 4285, 5187, 720, 5186, 2589, 3617, 5421, 1199, 4084, 2423, 1579, 5335, -518, 3879, 2804, -894, 4502, 692, 1989, 4329, 1791, 2961, 3354, 1889, 5035, 3692, 1175, 4608, 4214, 4861, 3955, 476, 5123, 4452, 4207, 2604, 1752, 4949, 2423, 3388, 1864, 3468, 3937, -2942, 2577, 4006, 4407, 2053, 2979, 2078, 5120, 4232, -451, 4465, 1539, 5069, 2721, -2834, 4398, -366, 4056, -1059, -4394, 3825, -1555, 2553, -3650, -4648, 3783, 984, 1518, 220, -2108, 4223, 1564, 1432, 1126, -416, 4287, 927, 1765, 985, -266, 3353, 180, 1171, 1319, -1422, 700, 323, -1087, 2497, -1730, -3577, 986, -4078, 3156, -379, -145, 804, -5633, 3189, 347, 692, -838, -2836, 3184, 591, 372, -3742, -1062, 3175, 815, 775, -4880, -1859, 2491, 1139, 1429, -2167, -6691, 487, 1412, 1693, -494, -3217, -4289, 1377, 2490, -297, -193, -6386, 972, 3451, -977, 1287, -4593, 571, 3687, -1970, 2053, -4635, 521, 3061, -3478, 2249, -3130, 572, 2009, -2216, 1942, -2060, 642, 1428, 431, 1191, -2079, 677, 1189, 1781, 15, -3089, 122, 430, 2063, -996, -816, -1523, -2164, 1360, -575, 1708, -3664, -6231, -374, 368, 2832, -4666, -355, -2308, 889, 2960, -3159, 1093, -1614, 588, 2495, -820, 1216, -287, -1047, 1888, -233, 463, 180, -5792, 1396, -1210, -1699, -456, -5831, 827, -1932, -4360, -1542, -3116, -181, -1081, -1611, -1293, -2754, -1835, -1012, -752, -892, -3009, -3416, -1665, -1331, -1022, -3744, -2976, -2081, -3307, -1008, -5304, -1919, -2296, -6978, -599, -9515, -1543, -2617, -2689, -324, -5503, -2134, -2837, -849, -552, -2105, -4034, -2991, -641, -1427, -987, -9344, -3313, -1334, -3026, -1507, -5572, -3958, -2143, -3900, -4232, -2728, -4591, -2131, -2097, -11497, -1606, -4683, -1188, -635, -4314, -772, -4588, -392, -95, -3143, 504, -5553, -420, -401, -3153, 1642, -12972, -1425, -1560, -3376, 2085, -5530, -3346, -3278, -3476, 1682, -3339, -6006, -4696, -2954, 318, -3931, -8714, -4326, -1709, -2490, -3776, -10887, -1777, -777, -10400, -1479, -12866, -745, -686, -5189, -826, -8513, -1537, -1478, -4025, -1742, -7835, -3353, -2888, -5665, -3837, -6347, -2788, -3952, -17953, -6267, -4056, -2692, -4012, -4997, -8544, -3186, -4337, -4604, -2943, -5270, -3660, -6473, -9815, -2948, -2994, -3978, -7759, -4141, -4830, -1837, -2409, -9588, -365, -8098, -1245, -1044, -7724, 1152, -7450, -1150, -518, -3907, 1373, -5088, -1650, -941, -1635, 501, -2392, -2714, -2385, -835, -1466, -920, -3973, 8763, 8553, -1506, 9043, 5045, 8329, 7818, 4856, 8679, 5189, 7124, 5235, 6475, 7547, 4899, 5539, -2724, 5978, 5518, 3051, 4243, 1960, 3948, 2257, -764, 3257, 2827, 3653, -4867, 3192, 1750, 1546, 4642, -1789, 4821, -503, -1688, 4092, 759, 4430, -877, -10154, 1867, 814, 540, 675, -6481, 292, -964, 1989, 2501, -5274, 1801, -2428, 5702, 3249, 984, 1939, -1699, 6847, 2841, 3143, 325, -4114, 7089, 2120, 3203, -449, -1716, 7005, 1932, 879, 1514, 1679, 6616, 1470, -1494, 1524, 2209, 5686, 383, 1209, -1306, 129, 4051, -917, 274, -2145, -4903, 1958, -3227, -10316, 421, -2018, 2525, -6570, 1371, 165, -7468, 4230, -1425, 3275, -1489, 652, 4741, 506, 3377, -3377, 3027, 3845, 1603, 2098, -3518, 3347, 845, 2379, -1130, -505, 2476, -1302, 2437, -2395, 1055, 832, 1731, 1313, -13, 1424, -1240, 1930, -1705, 66, 1181, -2536, -493, -10492, -1451, 1033, -3839, -1341, -10204, -4003, 1254, -2854, 2599, -4882, -4488, 1321, 1188, 3988, -429, -2851, 976, 3064, 4135, 1534, -2062, 521, 3641, 3510, 2383, -2765, 362, 3398, 2477, 2512, -4557, 551, 2803, 1501, 1934, -2537, 731, 2299, 1677, 334, -1009, 638, 1833, 3102, -2805, -1109, 447, 969, 4139, -2513, -2382, 332, 160, 4254, -556, -4855, 342, 1225, 3384, 230, -9011, 901, 2469, 1469, 344, -1342, 1682, 2800, -1616, -299, 1071, 1871, 2211, -4908, -1796, 1832, 1146, 841, -4058, -3723, 1510, -467, -884, -1918, -4119, 501, -1711, -2314, -531, -2890, -225, -1369, -3129, -539, -2156, -60, -1479, -3522, -2704, -2097, -308, -2167, -4943, -4489, -2310, -2024, -1823, -6980, -1326, -2668, -4405, -951, -3549, -759, -3620, -2580, -708, -1778, -1286, -4578, -2603, -1275, -1417, -1385, -4056, -6586, -2563, -2143, -1543, -3927, -5338, -3925, -3430, -2858, -3746, -2880, -4848, -3057, -6455, -3291, -3926, -5108, -1669, -7064, -3807, -11714, -3433, -786, -2551, -3780, -5750, -2579, -553, -530, -2358, -3964, -3609, -1075, 313, -1908, -4017, -7855, -2455, 274, -2862, -4266, -6328, -4246, -274, -4876, -3763, -3283, -5502, -747, -4153, -2845, -1491, -8382, -1394, -2877, -2209, -403, -9169, -2948, -2452, -2235, -95, -4587, -3623, -1834, -3028, -594, -2742, -2108, -1247, -4172, -2123, -1891, -1002, -1352, -4534, -5646, -1920, -289, -2096, -4388, -7798, -3139, -214, -3092, -5273, -5865, -6345, -1249, -3905, -8090, -9013, -7257, -4051, -3610, -4638, -7809, -5399, -7985, -2443, -2722, -4250, -5762, -4407, -1562, -2710, -3316, -6933, -2448, -1343, -3403, -2966, -9019, -1554, -1776, -3475, -3180, -8528, -1840, -2636, -4344, -4117, -2747, -3535, -3723, -9379, -4126, -312, -3640, -5202, -6598, -3572, 711, -1680, -6312, -3807, -3978, 831, -1188, -4245, -4310, -7584, -1936, -2416, -3598, -3759, -6397, -1902, -1112, -4363, -2385, -4368, -2542, -971, -7739, -1412, -4526, -2295, -1956, -5969, -909, -9751, -1952, -3951, -3203, -1013, -5079, -2482, -5007, -2823, -1841, -2115, -3485, -3893, -4508, -3042, -1813, -3944, -2476, -8390, -3065, -3524, -3411, -1102, -5568, -2684, -5474, -2825, -289, -5226, -3652, -2696, -2998, -310, -5345, -8172, -1250, -4284, -1246, -3334, -6708, -857, -7354, -2712, -2274, -3151, -1019, -9777, -2957, -2140, -2087, -1432, -5676, -2471, -2637, -2178, -2087, -3877, -2453, -4159, -3341, -3348, -3197, -2388, -7626, -5980, -5700, -3484, -2026, -4123, -5319, -5244, -4475, -1800, -1513, -2944, -2875, -4371, -1973, -696, -2443, -2122, -3853, -2977, -1062, -3546, -2808, -4503, -5683, -1769, -6391, -4870, -4615, -6658, -1760, -9873, -6902, -2950, -4382, -1757, -8724, -7033, -1944, -4151, -2451, -6731, -8317, -1880, -5179, -3833, -5847, -8860, -2768, -5707, -5330, -5913, -6610, -4725, -4401, -5875, -6154, -6022, -5516, -3292, -6049, -6410, -6349, -4202, -2875, -6326, -6422, -5028, -3904, -2945, -6690, -5428, -4164, -4081, -3296, -7285, -3982, -5411, -4086, -4066, -7589, -3160, -9155, -4876, -6195, -8635, -3481, -6154, -7075, -13717, -17795, -5003, -5407, -6101, -4434, -6576, -5973, -6237, -4436, -2085, -3952, -5654, -5689, -4266, -1523, -3278, -7182, -4895, -5054, -2485, -4046, -8509, -5342, -6065, -5898, -5987, -3994, -6742, -6265, -7377, -5848, -2032, -6876, -4901, -3902, -4456, -1474, -5497, -3380, -3330, -4201, -2127, -4147, -2510, -4583, -4967, -4416, -3244, -1952, -8653, -6811, -11506, -3228, -1339, -6706, -10673, -7462, -4530, -996, -4300, -9813, -5660, -7329, -1301, -3779, -7764, -4954, -5833, -2200, -4394, -8093, -4546, -4186, -3206, -5595, -9355, -4807, -4028, -4239, -6176, -8076, -5462, -4511, -6117, -5945, -6543, -5732, -4528, -9712, -5220, -5844, -5094, -4086, -9797, -4710, -5940, -3813, -4005, -6182, -4521, -7039, -3016, -4075, -4228, -3924, -8014, -2996, -3576, -3577, -3383, -6866, -3434, -3182, -3886, -3540, -6838, -3964, -3752, -4418, -4241, -8312, -4467, -5897, -4328, -4970, -7845, -4810, -10414, -4067, -5665, -7341, -5217, -8887, -4270, -6873, -8852, -6348, -9758, -5437, -10058, -9898, -8191, -11707, -8987, -10901, -9673, -6973, -7642, -9459, -6637, -15261, -6045, -7429, -5868, -5225, -6272, -7219, -10226, -4687, -5036, -3421, -10001, -13849, -4330, -5559, -2544, -8478, -12205, -4389, -6394, -3113, -7046, -11090, -4939, -7445, -5228, -6198, -9975, -6280, -9031, -9711, -5579, -11368, -6788, -10330, -11091, -5669, -10241, -4890, -8679, -8822, -6936, -7734, -3785, -6695, -7786, -7611, -6787, -3772, -5455, -7664, -6296, -6440, -4766, -5136, -8690, -6163, -5953, -6939, -6212, -9519, -7597, -5168, -8792, -10846, -8362, -11220, -4762, -7115, -7982, -8059, -14884, -5349, -6460, -5340, -4174, -1237, -4037, -530, -4954, -4174, -2522, -3614, -994, -6100, -2920, -3954, -2632, -2247, -9287, -1616, -4426, -2914, -4583, -5939, -845, -4044, -3528, -6908, -2561, -797, -4028, -2921, -4638, -1136, -1577, -4795, -2614, -3579, -1038, -3496, -5431, -3322, -3708, -2270, -7766, -4628, -3843, -4251, -5138, -7506, -3381, -3110, -4437, -7679, -4581, -2569, -2639, -4356, -7414, -3575, -2247, -2931, -4870, -6583, -3313, -2108, -3925, -6622, -4064, -3390, -1943, -5490, -7479, -2462, -3729, -1799, -7472, -5139, -1960, -4159, -1785, -11648, -3484, -2290, -4479, -1986, -10230, -2910, -2944, -5338, -2099, -6642, -4165, -4211, -8715, -1448, -5782, -8041, -8232, -8483, -722, -5205, -3221, -5106, -4944, -913, -4297, -1544, -3085, -3364, -2204, -3838, -1820, -3118, -1824, -2690, -3507, -4098, -3537, -968, -1757, -2774, -21301, -3335, -1385, -1588, -1829, -4718, -2810, -3704, -1814, -1186, -3376, -2211, -21827, -1887, -1290, -4445, -2342, -4557, -2236, -2360, -8339, -3652, -3064, -2763, -3372, -6379, -6009, -3624, -2998, -2490, -4106, -8994, -6324, -3087, -2093, -4128, -13751, -9152, -2466, -3083, -7281, -11801, -4567, -1805, -4833, -8001, -10322, -3041, -2281, -3630, -4067, -9236, -3017, -4560, -1911, -3684, -8263, -4517, -10479, -1119, -5675, -6364, -10327, -20358, -1023, -10732, -4767, -6247, -8368, -1528, -4746, -4216, -2983, -4246, -2913, -2574, -4841, -1884, -2734, -6145, -1727, -7198, -2100, -2697, -11135, -1772, -7530, -3580, -3827, -7508, -2708, -4040, -6147, -6024, -7296, -4290, -2445, -7961, -8740, -5872, -4995, -2092, -7900, -10261, -4057, -5117, -2828, -5617, -9008, -3259, -6224, -4583, -4048, -7363, -3309, -7746, -6672, -3700, -7212, -4105, -7622, -9777, -3554, -8676, -6131, -6578, -5873, -2582, -10892, -12501, -5608, -2886, -1768, -7949, -6930, -5185, -2165, -1734, -4853, -4810, -5409, -3225, -2563, -3271, -4393, -6393, -6190, -4328, -2921, -4492, -5464, -6662, -6721, -3605, -4504, -2806, -5473, -7027, -5113, -4566, -1484, -5975, -6032, -6411, -5262, -1418, -7516, -5429, -5497, -7180, -2201, -8448, -5025, -4215, -8562, -2727, -7362, -4902, -3800, -7443, -2685, -6053, -5415, -4525, -7229, -3456, -5082, -6395, -6904, -6703, -5888, -4365, -6522, -9974, -5301, -7193, -3975, -5716, -6555, -4081, -6234, -4262, -4815, -4722, -3544, -8030, -5932, -4538, -3835, -4174, -10042, -12196, -5802, -3681, -7210, -5852, -8365, -11229, -4208, -10922, -4575, -6589, -6415, -5101, -5875, -4948, -7750, -4057, -6052, -5357, -6997, -11230, -3570, -7159, -6148, -12133, -7698, -3994, -8878, -6703, -11760, -4551, -4813, -13831, -7419, -7405, -2793, -5913, -12081, -9096, -5796, -2280, -7953, -9445, -8924, -5801, -2982, -14337, -9974, -7061, -6966, -4944, -8875, -10837, -5828, -7896, -8018, -6489, -8304, -5412, -7048, -8014, -6504, -6799, -5686, -6278, -6303, -8279, -6485, -6170, -6540, -5936, -5547, -3390, -4884, 313, -2275, -5205, -3825, -4419, -712, -6002, -6433, -4252, -3189, -2211, -7314, -9619, -4710, -2507, -3601, -3322, -6767, -6094, -2362, -3490, -2405, -4586, -10020, -2379, -3266, -2906, -3675, -10631, -2392, -4206, -4625, -3173, -8286, -2611, -5431, -5448, -2849, -8566, -3250, -4016, -2558, -2961, -7528, -4419, -2752, -883, -4098, -5385, -6192, -2356, -731, -8262, -3910, -8129, -2542, -2219, -5083, -2952, -5691, -3190, -5673, -1978, -2423, -2901, -4317, -4986, -924, -2528, -1423, -5413, -3747, -850, -3729, -1128, -4775, -3680, -1003, -7519, -2264, -3471, -3324, -746, -8795, -6607, -2657, -2284, -461, -4480, -6069, -2310, -1272, -796, -3395, -3008, -2363, -836, -1808, -3736, -3082, -2986, -1026, -2795, -5576, -5211, -4724, -1269, -3337, -11530, -5590, -9675, -898, -3985, -7161, -3814, -7127, -399, -4453, -4459, -3717, -4424, -272, -4145, -3612, -4997, -3564, -698, -3620, -3438, -7013, -3593, -2199, -3800, -3317, -8395, -4469, -7607, -5528, -3399, -7366, -5659, -4618, -14263, -3532, -5910, -5974, -1672, -5954, -2692, -4889, -4994, -1074, -3646, -1954, -3507, -3351, -1526, -3297, -2598, -2770, -2700, -2589, -3889, -6451, -3521, -3070, -4159, -4155, -5944, -6990, -3590, -6149, -3818, -2166, -9168, -4215, -7917, -3963, -1372, -4878, -6426, -7147, -4834, -2278, -3570, -10798, -4734, -5753, -5726, -2839, -6221, -3579, -5617, -9161, -2446, -4039, -3903, -4882, -4570, -2575, -2848, -5119, -4334, -4000, -2973, -2471, -5503, -4278, -4478, -2937, -2861, -6736, -4598, -5032, -2978, -4320, -9367, -4628, -6017, -4192, -10281, -4014, -4672, -8068, -5377, -5145, -1725, -5761, -10937, -3245, -2092, -688, -4328, -10058, -1908, -1239, -363, -1743, -6145, -1607, -1582, -580, -715, -4074, -2175, -2512, -1221, -956, -3665, -3863, -3144, -2089, -1971, -5056, -4436, -3419, -2881, -2545, -9684, -2025, -3608, -3396, -2396, -12097, -994, -3362, -3588, -2442, -10976, -1438, -2872, -3295, -3008, -11353, -3386, -2753, -2876, -4564, -8431, -7063, -3675, -2700, -9427, -7128, -8582, -6544, -2614, -7480, -6192, -8026, -6297, -2497, -4253, -4874, -8420, -3969, -2731, -3707, -3623, -8860, -3467, -4105, -4764, -2854, -8585, -3975, -7415, -5983, -2595, -7169, -4972, -5572, -5020, -2861, -5735, -6013, -3911, -4773, -3655, -5287, -7482, -3890, -5173, -4776, -6153, -10354, -4815, -4027, -5856, -7702, -8618, -6613, -2938, -6685, -6564, -6505, -8551, -3061, -7454, -5335, -5890, -6235, -4488, -8389, -5273, -6417, -4250, -6685, -7292, -6254, -8490, -3528, -7534, -5091, -8071, -16270, -3670, -8866, -3933, -8751, -10555, -4230, -13174, -3898, -7635, -7917, -5234, -11510, -4896, -6785, -6733, -6968, -9992, -6789, -6312, -6186, -6140, -10876, -9400, -6279, -6354, -4174, -14447, -13489, -6691, -7307, -3387, -9865, -9254, -7337, -6874, -3650, -8955, -6250, -8217, -5054, -4855, 6703, 3204, 1586, 6835, -3668, 6345, 2720, 1801, 6394, -1134, 5365, 1177, 1741, 5107, 1061, 4119, -2197, 898, 3222, 2289, 3167, -8615, 284, 1169, 2993, 2409, -2027, 1073, -2036, 3106, 1086, -1293, 1938, -5374, 2331, 547, -1753, 2523, 5, 797, 1067, -24, 2946, 1931, 656, -1071, 1855, 2833, 2952, 2201, 1457, 3108, 1416, 3439, 3749, 4705, 4256, -32, 3213, 5112, 5749, 5414, 2752, 1872, 5989, 5477, 6280, 3819, -160, 6105, 4546, 6504, 2810, 1047, 5312, 3980, 5820, -433, 1945, 3821, 3567, 3844, 2125, 1419, 2976, 2419, -320, 3857, 176, 2403, 1613, 164, 3877, -1456, -24, 2528, 1172, 2732, -3532, -1812, 2889, -517, 1047, -144, -435, 2003, -408, 292, 1904, -883, -362, 1147, -1093, 2728, 1437, -5296, -94, -8915, 2993, 2659, -7021, -10282, 1091, 2931, 1639, -4613, 811, 3232, 2468, -3024, -2828, 2863, 3548, 1460, 1274, 126, 3568, 2711, -394, 3262, 1813, 3683, 1363, -4406, 3223, 2242, 3312, 403, -1225, 1673, 1474, 2497, 23, 1854, -1056, -1611, 1466, 825, 3183, -2861, -3901, 473, 1839, 3504, -5223, 1113, -398, 1868, 3128, -6163, 2229, -1538, 795, 2285, -3406, 1855, -2338, -252, 1237, -3807, 544, -276, -252, 395, -4846, -970, 948, -1082, -25, -2043, -860, 533, -2352, -229, 9, 484, -1634, -993, -505, 1165, 1547, -3511, -590, -974, 1707, 2050, -2970, -2518, -1589, 1697, 2108, -5249, -2631, -2542, 1152, 1867, -7052, -177, -3760, 137, 1291, -3246, -75, -3836, -1175, 229, -3124, -2183, -2316, -2709, -1316, -3948, -6511, -993, -4539, -3187, -2271, -6249, -588, -4778, -5457, -695, -10341, -1169, -3864, -4383, 156, -7273, -2097, -4081, -2309, 567, -4283, -1895, -5611, -1484, 490, -3179, -1638, -6577, -1538, -352, -2336, -2480, -5376, -2014, -2253, -1795, -4154, -4983, -2025, -3769, -2038, -3711, -5141, -1714, -2523, -3799, -2234, -4715, -2128, -1522, -9073, -1593, -3986, -4264, -1285, -7244, -1632, -3726, -5375, -2149, -8677, -1852, -4676, -1688, -4917, -7194, -1826, -8096, -492, -12282, -2964, -1637, -7885, -1091, -6994, -2175, -1556, -5414, -3828, -5926, -3777, -1687, -4540, -20328, -5444, -8621, -1951, -4144, -6359, -4912, -3849, -2310, -4653, -5526, -4968, -2186, -2929, -6903, -5798, -5746, -2091, -4192, -8093, -5356, -6310, -2948, -6581, -5592, -4002, -6308, -4391, -7763, -5412, -2773, -7445, -5002, -6596, -8029, -2051, -14411, -4477, -7266, -10649, -1923, -8147, -4639, -10554, -7352, -2289, -6031, -5873, -13132, -8828, -3032, -6298, -7359, -9153, -7857, -4502, -7934, -7195, -6047, -4379, -7915, -9677, -5741, -4285, -3318, -9178, -9480, -4826, -3693, -3636, -5388, -7589, -5189, -4258, -4850, -4741, -5690, -7230, -6325, -6145, -6763, -4460, -9858, -11254, -6214, 1293, 6143, 1369, 3002, -6919, 2589, 5625, 2395, 2359, 1396, 3514, 3919, 3497, -60, 4035, 2884, 548, 3781, -7328, 5095, 458, -776, 3353, -198, 5134, 590, 749, 2328, 1795, 4407, 3217, 1141, 412, 2568, 3058, 4693, 983, -4580, 2762, 858, 5438, 119, -3118, 2391, -2306, 5534, 1281, -1659, 1589, -3437, 5182, 4135, -72, 1068, -106, 5599, 5719, 3958, 1330, 2715, 6580, 6093, 5937, 1590, 3934, 6784, 5487, 6334, 1391, 3827, 6024, 4268, 5213, 2532, 2476, 4725, 2996, 1936, 4331, -143, 3626, 1903, -1202, 5311, -3511, 2869, 75, 1116, 5583, -4604, 1661, -5912, 358, 5407, -3736, -1659, -312, -3236, 4889, -4575, -6926, 993, -10314, 4077, -4774, -2910, -919, -8073, 3183, -3574, -2594, -1749, -4815, 2386, -4578, -223, 2025, -402, 1379, -3131, 1151, 3552, 1653, -307, -1652, 1588, 4067, 2550, -1863, -2704, 1634, 3913, 2716, 128, -4038, 1601, 3233, 2298, 1743, -976, 1691, 2509, 1212, 2014, 106, 1861, 2459, -545, 910, -530, 1893, 2695, -1881, -2392, -3240, 1653, 2586, -1497, -7493, -4522, 1314, 1810, -577, -1369, -554, 1343, -279, -149, -17, 1383, 1717, -1704, -736, -337, 2342, 1784, 1357, -2468, -1523, 2672, 1083, 2579, -4590, 301, 2526, -625, 2299, -4465, 2389, 1926, -3639, 566, -2154, 3378, 857, -5484, -3344, -534, 3636, -375, -2516, -12965, 58, 3478, -860, -379, -4807, -35, 3069, -38, 1062, -567, -587, 2468, 1059, 1903, 1600, -1397, 1548, 1590, 2101, 2320, -1832, -55, 1443, 1640, 1993, -2134, -1309, 726, 561, 1127, -3168, -521, -312, -1202, 354, -4864, -373, -945, -4005, -663, -6055, -1355, -869, -4117, -2990, -5865, -3041, -902, -2457, -8170, -5027, -4746, -1442, -2935, -10249, -4432, -5016, -2340, -7190, -6067, -4864, -4258, -3037, -6829, -2751, -6363, -3300, -3169, -4239, -1698, -5350, -2072, -3388, -5548, -2701, -3534, -1137, -4792, -7117, -7722, -2995, -814, -8137, -3626, -6399, -3808, -1096, -7043, -2003, -4058, -6258, -1518, -6399, -1569, -4900, -9322, -1486, -6839, -2077, -8802, -7117, -1405, -5116, -3519, -8928, -5047, -1596, -3431, -5787, -5447, -4194, -1928, -2840, -6319, -3920, -4545, -2079, -3631, -4603, -3377, -5533, -1722, -6507, -3148, -3755, -5508, -1590, -10105, -2108, -5016, -5074, -2436, -9812, -1715, -6540, -5372, -4575, -11719, -2270, -6622, -6098, -6740, -5126, -4204, -5991, -7256, -5343, -3221, -8612, -5590, -9812, -4101, -3040, -8594, -5369, -9472, -3783, -4275, -6415, -5323, -8459, -4783, -6485, -5315, -5352, -9788, -9495, -5953, -4822, -5571, -10721, -6150, -5775, -5135, -6381, -10666, -3189, -8294, -6049, -7777, -12603, -2586, -7554, -6878, -8223, -10970, -3410, -5760, -6977, -5866, -9642, -5563, -6499, -6528, -4094, -9282, -9337, -8436, -6019, 6460, 8585, 6506, -1671, 2320, 6263, 7904, 6607, 4638, 4738, 5687, 6070, 6838, 6771, 5155, 4927, 4654, 6804, 7110, 3835, 3991, 3955, 5957, 5941, 436, 2319, 1879, 3752, 2813, -1564, 1025, -2462, 1189, 481, -1290, 1768, -6966, 2144, 1278, -4873, 1698, -2827, 2060, 2646, -3446, 695, -839, 2309, 5169, 1280, 485, -121, 3583, 6523, 3448, 1856, 216, 3940, 6911, 4334, 2638, 242, 2952, 6260, 4036, 2291, -887, -240, 3493, 2322, 858, -4898, -6552, 1023, -1619, -2154, -1399, -694, 5282, -1276, -6278, 670, -750, 6114, 394, -1566, 783, -2170, 5681, -62, -1027, -185, -2775, 5170, -2306, -3586, -1760, -3144, 4729, -7322, -3833, -3287, -1245, 3711, -19766, -589, -3358, -222, 2242, -8093, 27, -3191, -970, 1022, -4243, -1122, -3548, -3359, 209, -3298, -4685, -2986, -5363, -298, -4225, -7646, -1347, -5386, -964, -8173, -6611, -132, -5248, -1823, -6344, -5415, 315, -4457, -999, -2598, -2179, 144, -3868, 105, -1560, -1501, -509, -3549, 279, -2197, -2952, -1794, -3053, -246, -3620, -5376, -3607, -2577, -1222, -2705, -4183, -4144, -3278, -3791, -1762, -2836, -2395, -6206, -5145, -1087, -2115, -305, -1526, -1274, 104, -2627, 818, 929, -498, 781, -4614, 704, 1460, -1142, 253, -4524, -603, 434, -2681, -2192, -2584, -777, -2499, -5398, -5049, -1574, 712, -11590, -2509, -2376, -1586, 1435, -3710, -250, -3423, -1846, 1829, -1418, 701, -2715, -487, 2131, -1248, 1073, 867, 716, 1818, -3331, 1106, 2047, 902, 523, -12523, 682, 1608, 253, -1466, -6181, -499, -528, -912, -1687, -5199, -2605, -6409, -2194, -639, -4671, -4952, -5239, -3145, -138, -4332, -7433, -3721, -3566, -337, -4663, -12593, -5254, -3552, -1391, -4762, -7195, -8644, -3370, -3758, -4647, -6089, -5053, -3458, -6957, -4791, -6491, -3648, -4299, -5356, -4950, -5986, -4012, -6366, -4894, -5337, -4762, -5765, -9859, -5770, -6680, -4250, -7849, -8077, -6539, -8993, -4049, -7880, -5595, -7021, -7878, -3440, -7817, -4289, -9246, -6359, -2550, -7828, -3690, -14931, -5444, -2002, -6701, -3536, -8096, -4238, -2251, -5883, -3852, -7104, -3132, -3703, -6021, -5128, -8187, -2707, -7868, -6281, -9567, -9829, -3158, -8433, -6121, -7803, -9826, -4530, -4120, -6513, -4211, -8745, -6605, -2590, -7734, -3280, -8554, -8064, -2129, -8656, -3965, -8337, -8232, -2411, -7856, -6265, -5359, -8473, -3191, -6319, -7133, -3973, -8603, -3961, -5119, -5602, -4297, -8081, -4038, -4657, -4597, -5804, -7912, -3391, -5386, -4008, -6926, -8704, -2602, -7435, -4229, -8161, -11275, -2156, -7266, -5466, -9710, -14398, -2307, -7574, -7933, -7565, -8732, -3190, -11110, -10776, -7046, -7437, -4874, -5258, -8394, -8759, -8230, -6787, -3350, -6713, -15560, -10338, -6749, -3291, -6291, -10373, -10250, -6686, -8081, -3861, -7544, -12242, -5296, -4990, -3638, -6283, -9534, -4842, -4384, -3611, -6077, -7659, -5782, -4796, -3644, -6173, -6376, -8535, -5620, -3851, -5851, -6373, -7229, -7298, -4720, -5509, -7419, -6000, -7694, -6763, -5797, -6459, -6692, -5630, -10988, -6929, -4902, -7763, -4236, -14770, -8883, -4496, -7651, -3452, -10059, -11134, -5015, -7245, -3129, -8703, -10550, -5908, -5993, -3172, -8592, -8335, -6287, -4910, -3536, -8320, -7303, -6516, -4655, -4341, -7341, -6919, -7810, -5046, -6037, -7272, -6556, -9608, -5551, -10399, -8040, -6681, -8608, -5595, -11077, -7942, -7533, -8245, -5352, -7727, -7381, -8621, -9242, -5506, -7582, -6260, -8946, -12264, -6541, -9181, -4954, -6697, -9602, -8278, -11606, -4501, -5073, -6425, -8221, -10750, -5169, -4816, -5116, -7345, -8677, -7055, -5554, -4801, -7546, -6583, -8102, -6044, -5165, -9019, -5398, -6459, -5659, -6100, -11315, -5408, -5590, -5940, -7048, -10794, -6623, -5433, -7994, -6872, -9456, -8768, -5395, -11278, -6691, -8343, -10468, -5121, -8059, -7592, -7063, -9210, -4766, -7158, -9540, -5863, -7060, -4729, -7870, -9096, -5170, -6140, -5375, -10321, -6839, -5354, -6402, -6812, -17832, -5637, -6724, -7307, -7519, -9106, -5496, -8705, -7919, -6604, -7291, -6224, -7896, -8120, -6267, -7301, -7367, -7235, -7994, -6827, -8576, -7996, -7929, -7577, -8062, -10179, -7451, -9083, -7175, -9730, -10866, -6625, -8186, -7108, -10845, -10002, -6490, -6085, -7891, -10350, -8082, -6925, -4784, -9322, -9988, -7385, -7246, -4706, -9306, -9214, -8374, -7127, -6081, -8930, -7544, -11900, -6299, -9353, -8191, -6706, -12636, -5464, -8912, -7071, -7185, -9948, -5367, -7078, -7114, -8801, -8905, -6146, -6768, -9244, -9259, -7689, -7835, -6756, -14682, -8430, -6448, -10286, -6334, -9283, -8936, -5805, -10398, -6232, -8215, -11595, -5907, -8780, -6925, -9266, -12734, -6654, -8245, -8377, -13011, -10854, -7601, -9180, -10070, -16819, -9726, -8044, -13164, -10194, -12386, -8277, -8308, -11393, -8966, -11102, -7739, -9389, -8107, -7966, -9149, -8758, -12630, -7110, -7712, -7642, -12974, -16843, -7381, -8716, -7506, -12816, -12094, -8807, -12294, -9444, -9445, -12427, -11430, -13088, -13175, -9000, -11861, -13592, -11056, -8018, -9609, -8138, -13507, -13650, -6437, -9416, -6223, -13215, -10254, -6645, -8461, -5572, -11994, -7187, -8797, -8068, -5900, -11103, -6167, -12028, -8353, -7192, -10938, -6353, -8272, -9002, -9690, -9898, -7507, -7329, -9624, -12416, -8870, -9500, -8506, -10184, -12048, -9132, -11676, -11289, -10610, -13399, -10614, -12017, -9963, -10329, -17632, -12277, -10225, -9342, -10059, -11794, -12810, -8551, -11024, -11152, -9739, -10594, -7666, -13738, -16279, -9015, -8973, -7541, -10362, -14029, -8803, -8840, -8188, -8717, -11141, -8518, -10270, -9868, -8657, -10411, -8097, -13847, -13647, -9581, -10752, -7837, -17834, -19148, -9836, -12529, -7931, -20091, -13792, -9977, -11735, -8497, -13887, -12597, -5991, -3744, -8902, -11410, -8909, -5391, -4875, -9033, -8824, -11574, -4686, -7483, -10082, -6786, -9772, -4221, -8386, -11713, -5534, -7215, -4427, -7160, -11370, -5162, -6295, -5663, -6160, -9608, -5567, -4910, -8094, -5465, -8462, -6479, -3906, -10248, -5571, -7955, -7540, -4028, -12081, -6664, -7881, -8728, -5443, -11211, -8168, -8236, -8905, -8792, -8369, -8285, -8463, -7148, -12392, -7433, -7569, -6835, -6183, -8421, -7292, -7064, -5297, -6863, -7661, -6998, -7198, -5058, -10533, -8750, -6326, -8437, -5922, -10417, -12173, -5678, -11215, -5797, -7091, -13441, -5301, -12537, -4946, -6199, -9546, -5184, -10470, -5456, -6234, -8400, -5204, -9073, -7572, -6855, -8838, -5254, -8304, -8123, -8270, -9406, -5340, -6641, -7515, -10446, -8337, -5466, -4801, -9911, -9273, -7318, -5471, -4036, -10924, -7826, -6955, -5336, -4542, -5788, -7617, -7424, -5559, -6493, -4346, -7735, -8804, -6796, -10525, -4645, -7064, -9692, -8022, -24960, -6532, -6083, -8804, -5864, -12193, -8419, -5556, -7612, -4576, -9891, -7835, -5563, -6365, -4740, -9331, -8463, -5905, -5533, -6383, -9772, -10027, -6335, -5503, -10656, -11335, -8994, -6706, -6632, -12304, -14695, -8003, -7338, -10125, -8839, -10698, -8142, -9166, -11785, -8201, -8931, -8256, -12605, -7731, -8399, -9187, -7673, -13029, -6747, -8740, -10575, -6812, -18001, -7123, -9667, -10123, -6003, -8773, -8340, -10541, -9335, -6346, -6194, -9319, -7978, -8672, -9434, -5109, -9667, -6188, -7126, -11739, -4909, -10658, -5687, -6117, -7850, -5786, -12360, -6263, -6042, -7688, -7843, -10842, -7874, -6553, -7756, -7997, -9353, -10055, -7000, -6986, -6754, -9075, -10057, -6836, -6558, -6460, -9185, -8933, -6373, -6269, -6889, -9051, -8414, -6409, -6204, -7961, -9056, -8596, -7465, -7027, -9355, -10020, -9444, -9167, -9397, -10302, -13686, -10432, -8710, -12956, -12171, -13586, -10825, -7945, -10608, -20602, -9473, -11381, -8347, -9115, -11084, -8096, -11883, -9886, -8625, -9771, -8113, -11845, -12840, -9157, -11089, -9648, -13506, -17357, -11322, -15611, -10725, -12426, -12935, -11703, -15018, -8182, -9198, -11329, -8610, -14320, -6861, -8047, -12005, -7322, -9497, -6595, -8139, -16254, -7258, -7208, -7013, -8970, -11442, -7916, -6760, -8093, -10028, -9065, -8420, -7990, -10361, -10859, -9035, -7877, -11779, -17250, -11230, -11400, -7004, -17858, -11925, -11498, -11424, -6944, -12917, -9719, -12969, -8998, -8374, -11280, -9195, -13799, -8777, -12118, -10145, -9121, -10062, -10183, -12353, -10403, -9174, -8311, -11381, -11711, -11370, -9726, -7643, -9668, -11575, -10860, -10616, -7382, -8398, -9651, -10141, -9582, -7492, -7666, -8988, -10232, -7922, -8451, -7308, -10074, -11430, -7321, -10715, -7654, -12915, -12854, -7852, -10677, -9120, -11435, -11781, -9380, -8932, -12507, -9987, -11731, -11085, -9085, -16788, -10218, -12420, -11560, -12065, -13337, -11069, -11049, -11568, -15013, -12380, -10784, -10065, -11213, -10293, -11080, -10060, -10459, -10470, -4645, -7279, -8322, -10262, -8200, -7235, -10412, -8067, -11503, -7272, -7172, -11788, -8851, -12891, -5541, -5762, -10109, -10237, -24390, -5888, -5896, -11184, -11610, -11714, -8864, -8080, -13501, -12644, -10258, -8987, -10534, -9757, -11648, -13154, -6682, -6602, -7124, -11465, -13310, -6786, -5208, -5621, -14978, -9388, -9169, -5411, -4955, -14351, -8002, -12895, -7435, -4944, -10748, -6909, -8310, -12699, -5243, -9682, -6661, -7229, -8543, -5389, -9297, -7954, -7459, -6961, -5349, -9556, -11466, -8024, -6584, -5736, -11375, -10080, -9118, -6553, -7427, -10460, -7665, -10338, -6999, -11786, -7307, -6465, -8590, -8550, -13963, -5895, -6046, -7109, -10132, -14164, -4839, -6536, -6678, -7674, -8115, -3733, -8272, -7110, -6862, -6329, -3312, -11836, -8294, -7997, -6689, -3960, -10943, -9089, -9066, -8144, -5551, -8517, -7720, -8118, -8383, -6593, -7131, -6316, -8435, -8351, -6436, -6196, -5747, -9933, -9374, -7091, -5701, -5978, -9258, -11383, -10144, -5677, -6655, -7256, -11110, -12618, -5888, -6986, -5780, -10439, -7687, -5980, -6480, -4776, -8935, -6403, -6059, -5546, -4204, -6751, -6283, -6454, -4842, -4038, -5731, -6589, -7155, -4825, -4279, -5682, -6878, -7933, -5746, -5162, -6189, -7117, -9120, -7767, -7193, -6874, -7464, -11775, -10395, -9418, -7089, -8237, -10760, -10105, -8380, -6914, -10549, -8362, -8312, -8602, -7812, -14282, -7759, -7345, -11042, -11655, -9857, -8144, -7312, -13243, -12635, -9634, -8513, -7797, -12732, -10126, -12235, -8198, -8174, -13280, -8696, -11478, -8139, -8563, -13062, -7110, -10727, -9314, -9222, -17312, -6665, -13161, -12697, -10077, -11454, -7278, -14893, -13504, -12326, -7911, -8250, -8763, -11000, -13215, -6521, -8694, -6221, -10134, -9276, -6203, -8828, -5189, -10501, -7422, -6533, -9168, -5264, -13122, -6549, -7343, -9686, -6382, -14479, -6508, -8844, -10154, -9085, -10108, -7377, -10863, -10607, -17692, -8197, -9145, -10507, -11689, -9599, -7331, -11922, -10398, -11527, -8239, -7226, -16751, -13203, -9232, -9399, -7455, -11164, -13717, -8828, -13202, -7527, -8539, -11117, -11690, -10044, -7620, -6948, -11590, -12705, -8974, -7925, -6103, -12496, -8686, -10038, -8381, -6360, -10878, -8348, -12467, -8828, -8132, -9960, -9718, -13730, -8801, -11835, -9764, -10661, -11965, -8838, -14391, -9139, -10330, -10710, -9810, -12038, -7957, -10940, -10779, -11834, -8383, -7025, -12421, -11755, -13472, -6596, -6669, -12898, -13153, -14344, -6041, -6955, -12086, -15793, -14101, -6451, -7941, -11562, -21332, -10627, -8039, -9853, -12192, -22607, -8947, -11731, -13727, -15488, -17383, -8963, -12440, -17614, -16423, -13197, -10609, -11382, -13433, -12505, -11141, -13491, -14398, -12776, -11681, -10186, -13165, -16676, -12033, -11957, -10227, -11562, -13239, -11000, -11789, -11349, -10535, -13464, -10916, -10743, -12834, -10362, -12974, -11947, -10160, -12579, -11610, -13058, -12664, -10771, -12170, -16505, -12734, -11097, -13525, -11957, -12217, -10174, -9629, -13331, -11881, -9968, -8909, }; diff --git a/sw/applications/trans_versasense/dense_layerC.c b/sw/applications/trans_versasense/dense_layerC.c new file mode 100644 index 00000000..37d06f02 --- /dev/null +++ b/sw/applications/trans_versasense/dense_layerC.c @@ -0,0 +1,73 @@ +// +// Created by alireza on 10/6/23. +// + +#include "dense_layerC.h" +#include + +void createDense(Dense* dense, size_t input_dim, size_t output_dim, quant_bit_width *weight, quant_bit_width* bias) { + dense->input_size_ = input_dim; + dense->output_size_ = output_dim; + dense->weight = weight; + dense->bias = bias; +} + +void destroyDense(Dense* dense) { + // Free the memory allocated for the Dense struct + free(dense); +} + +void multiplyweight(Dense* dense, size_t seq_len, int32_t* input, int32_t* output) { + for (int length = 0; length < seq_len; length++) { + for (int out_idx = 0; out_idx < dense->output_size_; out_idx++) { + int32_t* weight_ptr = dense->weight + out_idx; + int32_t* output_ptr = output + (length * dense->output_size_) + out_idx; + int32_t* input_ptr = input + (length * dense->input_size_); + int32_t sum = 0; + for (int i = 0; i < dense->input_size_; i++) { + sum += MUL_HQ(*weight_ptr, *input_ptr); // MUL_HQ macro + input_ptr++; + weight_ptr += dense->output_size_; + } + *(output_ptr) = (int32_t) (sum >> NUM_FRACTION_BITS); // NUM_FRACTION_BITS macro + } + } +} + +void addbias(Dense* dense, size_t seq_len, int32_t* output) { + for (size_t idx = 0; idx < seq_len; idx++) { + for (size_t feature_idx = 0; feature_idx < dense->output_size_; feature_idx++) { + output[idx * dense->output_size_ + feature_idx] += dense->bias[feature_idx]; + } + } +} + +void computeDenseOneRow(Dense* dense, size_t seq_len, int32_t* input, int32_t* output){ // 1x16x16 + multiplyweight(dense, seq_len, input, output); +} + +void computeDense(Dense* dense, size_t seq_len, int32_t* input, int32_t* output) { + //multiplyweight(dense, seq_len, input, output); + //printf("\rMul %dx%dx%d\n", seq_len, dense->input_size_, dense->output_size_); + multiply_cgra(input, seq_len, dense->input_size_, dense->weight, dense->output_size_, output); + if (dense->bias != NULL) { + addbias(dense, seq_len, output); + } +} + +void activation(Dense* dense, size_t length, int32_t* input, int32_t* output) { + float in_float, in_tanh; + int32_t x3, in_tanh_fxp; + for (int i = 0; i < length; i++) { + x3 = MUL(MUL(input[i], input[i]), input[i]); + x3 = MUL(x3, 183); // 183 = 0.044715 in fixed-point 12 bit + x3 += input[i]; + x3 = MUL(x3, 3268); // 3268 = sqrt(2/PI) in fixed-point 12 bit + in_float = (float) x3 / (float) (1 << NUM_FRACTION_BITS); + in_tanh = tanhf(in_float); + in_tanh_fxp = (int32_t) (in_tanh * (1 << NUM_FRACTION_BITS)); + in_tanh_fxp += (1 << NUM_FRACTION_BITS); + output[i] = MUL(in_tanh_fxp, input[i] >> 1); + } +} + diff --git a/sw/applications/trans_versasense/dense_layerC.h b/sw/applications/trans_versasense/dense_layerC.h new file mode 100644 index 00000000..e0438f8d --- /dev/null +++ b/sw/applications/trans_versasense/dense_layerC.h @@ -0,0 +1,31 @@ +// +// Created by alireza on 10/5/23. +// + +#ifndef FVLLMONTITRANSFORMER_DENSE_LAYERC_H +#define FVLLMONTITRANSFORMER_DENSE_LAYERC_H + + +#include +#include +#include +#include "param.h" +#include "cgra.h" + +// Define the struct +typedef struct { + size_t input_size_; + size_t output_size_; + int32_t* weight; // quant_bit_width is a typedef for int32_t + int32_t* bias; // quant_bit_width is a typedef for int32_t +} Dense; + +void createDense(Dense* dense, size_t input_dim, size_t output_dim, quant_bit_width *weight, quant_bit_width* bias); +void destroyDense(Dense* dense); +void multiplyweight(Dense* dense, size_t seq_len, int32_t* input, int32_t* output); +void addbias(Dense* dense, size_t seq_len, int32_t* output); +void computeDense(Dense* dense, size_t seq_len, int32_t* input, int32_t* output); +void computeDenseOneRow(Dense* dense, size_t seq_len, int32_t* input, int32_t* output); +void activation(Dense* dense, size_t length, int32_t* input, int32_t* output); + +#endif //FVLLMONTITRANSFORMER_DENSE_LAYERC_H diff --git a/sw/applications/trans_versasense/main.c b/sw/applications/trans_versasense/main.c new file mode 100644 index 00000000..6a26f77e --- /dev/null +++ b/sw/applications/trans_versasense/main.c @@ -0,0 +1,143 @@ +// +// Created by alireza on 10/6/23. +// + +#include +#include +#include "main.h" +//#include "data_cpp/signal.cpp" +//#include "data_cpp/signal_fft.cpp" +#include "SYLT-FFT/fft.h" +#include "weightsAndBiasesC.h" +#include "transformerBlockC.h" + +// For the cgra +#include "multiply_cgra.h" + +// FFT +//#include "stftVec.h" +#include "data_cpp/array_output.h" + + +float error_check(const quant_bit_width* groundTruth, const quant_bit_width* output, size_t length){ + long error = 0; + for (int i=0; i> NUM_FRACTION_BITS); + return (float) error/ (float) length; +} + +void prototype_distances(quant_bit_width* prototypeVec, const quant_bit_width* modelOutput, int32_t* distVec, size_t prototypeLength, int prototypeNums){ + for (int p=0; p< prototypeNums; p++){ + long dist = 0; + quant_bit_width * prototypePtr = prototypeVec + (p * prototypeLength); + for (int i=0; i> NUM_FRACTION_BITS); + distVec[p] = (int32_t) dist; + } +} + +void transformerInference(quant_bit_width * transformerInput, quant_bit_width * transformerOutput, quant_bit_width* input_normalized, quant_bit_width* qkv, quant_bit_width* intermediate, quant_bit_width * aux_padding, void* kperf){ + quant_bit_width * weightVec[NUM_LAYERS*(3*NUM_HEAD+5)+5]; + quant_bit_width * biasVec[NUM_LAYERS*(3*NUM_HEAD+5)+5]; + getWeights(weightVec); + getBiases(biasVec); + quant_bit_width * clsTokenVector = getClassToken(); + quant_bit_width * posMatrix = getPosEmbedding(); + TransformerBlock* selfatten = createTransformerBlock(D_SEQ, D_MODEL, D_Q, NUM_HEAD, D_FF, weightVec, biasVec, clsTokenVector, posMatrix); + computeFixedPoint(selfatten, D_SEQ, transformerInput, input_normalized, transformerOutput, intermediate, qkv, aux_padding, kperf); +} + +quant_bit_width compute_log_amp(int32_t real, int32_t imag){ + real = MUL_HQ(real, 25) >> (NUM_FRACTION_BITS - 9); + imag = MUL_HQ(imag, 25) >> (NUM_FRACTION_BITS - 9); + int32_t real2 = MUL_LONG(real, real) >> NUM_FRACTION_BITS; + int32_t imag2 = MUL_LONG(imag, imag) >> NUM_FRACTION_BITS; + float pow2 = (float)(real2 + imag2) / (float) (1<< NUM_FRACTION_BITS); + float amp = sqrtf(pow2); + float stft = logf(amp+ 1e-10f); + quant_bit_width stft_int = (quant_bit_width) (stft * (1< +#include +#include "param.h" + +float error_check(const quant_bit_width* groundTruth, const quant_bit_width* output, size_t length); +void prototype_distances(quant_bit_width* prototypeVec, const quant_bit_width* modelOutput, int32_t* distVec, size_t prototypeLength, int prototypeNums); +void transformerInference(quant_bit_width * transformerInput, quant_bit_width * transformerOutput, quant_bit_width* input_normalized, quant_bit_width* qkv, quant_bit_width* intermediate, quant_bit_width* aux_padding, void * kperf); +quant_bit_width compute_log_amp(int32_t real, int32_t imag); + +#endif //FVLLMONTITRANSFORMER_TRANSFORMER_H diff --git a/sw/applications/trans_versasense/matMulC.c b/sw/applications/trans_versasense/matMulC.c new file mode 100644 index 00000000..0212afe3 --- /dev/null +++ b/sw/applications/trans_versasense/matMulC.c @@ -0,0 +1,22 @@ +// +// Created by alireza on 10/6/23. +// + +#include "matMulC.h" +#include + + +void MatMul_multiply(size_t seq_len, quant_bit_width* input, quant_bit_width* weight, + quant_bit_width* output, size_t input_size, size_t output_size) { + //printf("\rMul %dx%dx%d\n", seq_len, input_size, output_size); + multiply_cgra(input, seq_len, input_size, weight, output_size, output); +} + +void MatMul_scale(quant_bit_width* input, int shift_scale, size_t mat_size) { + + for (size_t i = 0; i < mat_size; i++) { + *input = (*input) >> shift_scale; + input++; + } +} + diff --git a/sw/applications/trans_versasense/matMulC.h b/sw/applications/trans_versasense/matMulC.h new file mode 100644 index 00000000..9844b787 --- /dev/null +++ b/sw/applications/trans_versasense/matMulC.h @@ -0,0 +1,21 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_MATMULC_H +#define FVLLMONTITRANSFORMER_MATMULC_H + + +#include +#include "param.h" +#include "cgra.h" + +#define BLOCK_SIZE 4 + +typedef struct { +} MatMul; + +void MatMul_multiply(size_t seq_len, quant_bit_width* input, quant_bit_width* weight, quant_bit_width* output, size_t input_size, size_t output_size); +void MatMul_scale(quant_bit_width* input, int shift_scale, size_t mat_size); + +#endif //FVLLMONTITRANSFORMER_MATMULC_H diff --git a/sw/applications/trans_versasense/multiply_cgra.c b/sw/applications/trans_versasense/multiply_cgra.c new file mode 100644 index 00000000..1222d3f2 --- /dev/null +++ b/sw/applications/trans_versasense/multiply_cgra.c @@ -0,0 +1,178 @@ +/* + ******************* +******************************* C SOURCE FILE ******************************* +** ******************* ** +** ** +** project : HEEPsilon ** +** filename : main.c ** +** version : 1 ** +** date : 01/10/23 ** +** ** +***************************************************************************** +** ** +** Copyright (c) EPFL ** +** All rights reserved. ** +** ** +***************************************************************************** +*/ + +/***************************************************************************/ +/***************************************************************************/ + +/** +* @file main.c +* @date 01/10/23 +* @brief An application to run a matrix multiplication. +* +*/ + +/****************************************************************************/ +/** **/ +/* MODULES USED */ +/** **/ +/****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "cgra_x_heep.h" +#include "cgra_bitstream.h" +#include "multiply_cgra.h" + +// For interrupt handling +#include "csr.h" +#include "handler.h" +#include "rv_plic.h" +#include "rv_plic_regs.h" +#include "hart.h" +#include "cgra.h" + + +/****************************************************************************/ +/** **/ +/* DEFINITIONS AND MACROS */ +/** **/ +/****************************************************************************/ + +// Size of the input buffer for the CGRA +#define CGRA_COL_INPUT_SIZE 4 + +/****************************************************************************/ +/** **/ +/* PROTOTYPES OF LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + + +// Handler for the CGRA interruption +void handler_irq_cgra(uint32_t id); + + +/****************************************************************************/ +/** **/ +/* GLOBAL VARIABLES */ +/** **/ +/****************************************************************************/ + +// Plic controller variables +volatile bool cgra_intr_flag; + +// CGRA variables +static cgra_t cgra; +static uint8_t cgra_slot; + +// CGRA input and output buffers +static int32_t cgra_input[CGRA_N_COLS][CGRA_COL_INPUT_SIZE] __attribute__ ((aligned (4))); + + +/****************************************************************************/ +/** **/ +/* LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + +// Output needs to be multiple of 4 by 4, ex 12x16 +void multiply_cgra(int * matrixA, int ROWS_A, int COLS_A, int * matrixB, int COLS_B, int * matrixC) +{ + int ROWS_B = COLS_A; + int ROWS_C = ROWS_A; + int COLS_C = COLS_B; + // Prepare the input vector for the CGRA + // Col 0: &B[0][0], nItLoopColsC, &A[0][0], &C[0][3] + cgra_input[0][0] = &matrixB[0]; + cgra_input[0][1] = COLS_C/CGRA_N_ROWS; + cgra_input[0][2] = &matrixA[0]; + cgra_input[0][3] = &matrixC[3]; + // Col 1: &C[1][0], &B[0][1], nItLoopsColsA, &A[1][0] + cgra_input[1][0] = &matrixC[COLS_C]; + cgra_input[1][1] = &matrixB[1]; + cgra_input[1][2] = COLS_A; + cgra_input[1][3] = &matrixA[COLS_A]; + // Col 2: &A[2][0], &C[2][1], &B[0][2], nItLoopColsC + cgra_input[2][0] = &matrixA[2*COLS_A]; + cgra_input[2][1] = &matrixC[2*COLS_C+1]; + cgra_input[2][2] = &matrixB[2]; + cgra_input[2][3] = COLS_C/CGRA_N_ROWS; + // Col 3: nItLoopRowsC, &A[3][0], &C[3][2], &B[0][3], + cgra_input[3][0] = ROWS_C/CGRA_N_COLS; + cgra_input[3][1] = &matrixA[3*COLS_A]; + cgra_input[3][2] = &matrixC[3*COLS_C+2]; + cgra_input[3][3] = &matrixB[3]; + + // Set CGRA kernel L/S pointers + for(int col_idx = 0 ; col_idx < CGRA_N_COLS ; col_idx++){ + cgra_set_read_ptr ( &cgra, cgra_slot, (uint32_t) cgra_input[col_idx], col_idx ); + } + + // CGRA Execution + cgra_intr_flag = 0; + cgra_set_kernel( &cgra, cgra_slot, 1 ); + // Wait until CGRA is done + while(cgra_intr_flag==0) { + wait_for_interrupt(); + } +} + +// Initialize the CGRA +void initCGRA(){ + // Init the PLIC + plic_Init(); + plic_irq_set_priority(CGRA_INTR, 1); + plic_irq_set_enabled(CGRA_INTR, kPlicToggleEnabled); + plic_assign_external_irq_handler( CGRA_INTR, (void *) &handler_irq_cgra); + + // Enable interrupt on processor side + // Enable global interrupt for machine-level interrupts + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + // Set mie.MEIE bit to one to enable machine-level external interrupts + const uint32_t mask = 1 << 11;//IRQ_EXT_ENABLE_OFFSET; + CSR_SET_BITS(CSR_REG_MIE, mask); + cgra_intr_flag = 0; + + // Load kernel + cgra_cmem_init(cgra_imem_bitstream, cgra_kmem_bitstream); + + cgra.base_addr = mmio_region_from_addr((uintptr_t)CGRA_PERIPH_START_ADDRESS); + // Select request slot of CGRA + cgra_slot = cgra_get_slot(&cgra); +} + +// Interrupt controller variables +void handler_irq_cgra(uint32_t id) { + cgra_intr_flag = 1; +} + +void countersInit(){ + // Enable and reset the CGRA performance counters + cgra_perf_cnt_enable(&cgra, 1); + cgra_perf_cnt_reset( &cgra ); +} + +/****************************************************************************/ +/** **/ +/* EOF */ +/** **/ +/****************************************************************************/ diff --git a/sw/applications/trans_versasense/multiply_cgra.h b/sw/applications/trans_versasense/multiply_cgra.h new file mode 100644 index 00000000..d43ba4fd --- /dev/null +++ b/sw/applications/trans_versasense/multiply_cgra.h @@ -0,0 +1,6 @@ +#include "performance.h" + +// Multiply the matrix in the cgra +void multiply_cgra(int * matrixA, int rowsA, int colsA, int * matrixB, int colsB, int * matrixC); +void countersInit(); +void initCGRA(); \ No newline at end of file diff --git a/sw/applications/trans_versasense/param.h b/sw/applications/trans_versasense/param.h new file mode 100644 index 00000000..a48ed700 --- /dev/null +++ b/sw/applications/trans_versasense/param.h @@ -0,0 +1,26 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_PARAM_H +#define FVLLMONTITRANSFORMER_PARAM_H +#include "stdint.h" + +#define D_Q 4 +#define D_SEQ 12 +#define D_MODEL 16 +#define NUM_HEAD 4 +#define NUM_LAYERS 4 +#define D_FF 4 +#define D_EMBEDDING 400 + + +#define NUM_FRACTION_BITS 12 +#define MUL(x, y) (int32_t) (((int32_t)(x) * (int32_t)(y)) >> NUM_FRACTION_BITS) +#define MUL_LONG(x, y) (int64_t) (((int64_t)(x) * (int64_t)(y))) +#define MUL_HQ(x, y) (int32_t) (((int32_t)(x) * (int32_t)(y))) +#define SHIFT(x) ((x) >> NUM_FRACTION_BITS) + + +typedef int32_t quant_bit_width; +#endif //FVLLMONTITRANSFORMER_PARAM_H diff --git a/sw/applications/trans_versasense/performance.c b/sw/applications/trans_versasense/performance.c new file mode 100644 index 00000000..421d39be --- /dev/null +++ b/sw/applications/trans_versasense/performance.c @@ -0,0 +1,62 @@ +#include "performance.h" + +// For the timer +#include "rv_timer.h" +#include "soc_ctrl.h" +#include "core_v_mini_mcu.h" + +// Timer +static rv_timer_t timer; + +void kcom_perfRecordStart( kcom_time_diff_t *perf ) +{ + timeStart( perf ); +} + +void kcom_perfRecordStop( kcom_time_diff_t *perf ) +{ + timeStop( perf ); +} + +void timeStart( kcom_time_diff_t *perf ) +{ + perf->start_cy = getTime_cy(); +} + +void timeStop( kcom_time_diff_t *perf ) +{ + perf->end_cy = getTime_cy(); + perf->spent_cy += perf->end_cy - perf->start_cy; +} + +uint64_t getTime_cy( ) +{ + static uint64_t out; + rv_timer_counter_read( &timer, HART_ID, &out ); + return out; +} + +//Initialize the timer +void timerInit() +{ + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + uint32_t freq_hz = soc_ctrl_get_frequency(&soc_ctrl); + + mmio_region_t timer_0_reg = mmio_region_from_addr(RV_TIMER_AO_START_ADDRESS); + + rv_timer_init( timer_0_reg, (rv_timer_config_t) { .hart_count = 2, .comparator_count = 1 }, &timer ); + + rv_timer_tick_params_t tick_params; + + // The same frequency is provaided to get one tick per cycle. + rv_timer_approximate_tick_params( freq_hz, freq_hz, &tick_params ); + rv_timer_set_tick_params(&timer, HART_ID, tick_params); + + // Juan: see if i cannot remove this! + rv_timer_irq_enable(&timer, HART_ID, 0, kRvTimerEnabled); + rv_timer_arm(&timer, HART_ID, 0, 1); + + rv_timer_counter_set_enabled(&timer, HART_ID, kRvTimerEnabled); + +} \ No newline at end of file diff --git a/sw/applications/trans_versasense/performance.h b/sw/applications/trans_versasense/performance.h new file mode 100644 index 00000000..9324381e --- /dev/null +++ b/sw/applications/trans_versasense/performance.h @@ -0,0 +1,64 @@ +#include +#include "cgra.h" + +typedef long int kcom_time_t; +typedef kcom_time_t kcom_param_t; + +typedef struct kcom_col_perf +{ + uint32_t cyc_act; + uint32_t cyc_stl; +} kcom_col_perf_t; + +typedef struct kcom_time_diff +{ + kcom_time_t start_cy; + kcom_time_t end_cy; + kcom_time_t spent_cy; +} kcom_time_diff_t; + +typedef struct kcom_timing +{ + kcom_time_diff_t sw; + kcom_time_diff_t cgra; + kcom_time_diff_t load; + kcom_time_diff_t input; + kcom_time_diff_t output; + kcom_time_diff_t reprogramCols; + kcom_time_diff_t bitstream; + kcom_time_diff_t infer; + kcom_time_diff_t proto; +} kcom_timing_t; + +typedef struct kcom_perf +{ + kcom_col_perf_t cols[CGRA_N_COLS]; + kcom_col_perf_t cols_max; + uint32_t cyc_ratio; // Stored *CGRA_STAT_PERCENT_MULTIPLIER + kcom_timing_t time; +} kcom_perf_t; + +typedef struct kcom_run +{ + kcom_param_t sw; + kcom_param_t conf; + kcom_param_t cgra; + kcom_param_t repo; +} kcom_run_t; + +typedef struct kcom_stats +{ + kcom_run_t avg; + uint32_t n; + uint32_t errors; + uint8_t *name; +} kcom_stats_t; + +#define HART_ID 0 + +void timerInit(); +uint64_t getTime_cy( ); +void timeStop( kcom_time_diff_t *perf ); +void timeStart( kcom_time_diff_t *perf ); +void kcom_perfRecordStop( kcom_time_diff_t *perf ); +void kcom_perfRecordStart( kcom_time_diff_t *perf ); \ No newline at end of file diff --git a/sw/applications/trans_versasense/selfattentionC.c b/sw/applications/trans_versasense/selfattentionC.c new file mode 100644 index 00000000..7edfff50 --- /dev/null +++ b/sw/applications/trans_versasense/selfattentionC.c @@ -0,0 +1,99 @@ +// +// Created by alireza on 10/6/23. +// + +#include +#include "selfattentionC.h" + + +void create_SingleHeadSelfAttn(SingleHeadSelfAttn* self_attn, size_t pre_seq_len, size_t input_dim, size_t head_hidden_size, int32_t** weightVector) { + self_attn->pre_seq_len = pre_seq_len; + self_attn->head_hidden_size = head_hidden_size; + createDense(self_attn->query_layer, input_dim, head_hidden_size, weightVector[0], NULL); + createDense(self_attn->key_layer, input_dim, head_hidden_size, weightVector[1], NULL); + createDense(self_attn->value_layer, input_dim, head_hidden_size, weightVector[2], NULL); +} + +void destroy_SingleHeadSelfAttn(SingleHeadSelfAttn* self_attn) { + free(self_attn->query_layer_out); + free(self_attn->key_layer_out); + free(self_attn->key_transposed_layer_out); + free(self_attn->value_layer_out); + free(self_attn->attention_scores); + + destroyDense(self_attn->query_layer); + destroyDense(self_attn->key_layer); + destroyDense(self_attn->value_layer); + + free(self_attn); +} + +void removeExtraCols(int32_t* input, size_t rows, int cols) { + int nElems = 3; + for(int r = 1; r < rows; r++, nElems+=3){ + for(int c = 0; c < cols -3; c++){ + input[r*cols+c -nElems] = input[r*cols+c]; + } + } +} + +void add_padding(int32_t *input, int32_t *output, int rows, int columns, int padding_width) { + // Calcular el nuevo ancho de la matriz con el relleno + int new_columns = columns + padding_width; + + // Crear una nueva matriz con el nuevo ancho y copiar los elementos de la matriz original + for (int i = 0; i < rows; i++) { + for (int j = 0; j < columns; j++) { + output[i * new_columns + j] = input[i * columns + j]; + } + // Rellenar las nuevas columnas con ceros + for (int j = columns; j < new_columns; j++) { + output[i * new_columns + j] = 0; // O cualquier otro valor de relleno que desees + } + } +} + +void remove_padding(int *matrix, int rows, int columns, int padding_width) { + // Calculate the new width of the matrix after removing padding + int new_columns = columns - padding_width; + + // Shift the elements of each row to remove the padding + for (int i = 0; i < rows; i++) { + for (int j = 0; j < new_columns; j++) { + matrix[i * new_columns + j] = matrix[i * columns + j]; + } + } +} + + +void compute_SingleHeadSelfAttn(SingleHeadSelfAttn* self_attn, int32_t* input, int32_t* output, int32_t* qkv, int32_t* intermediate, int32_t* aux_padding) { + self_attn->query_layer_out = qkv; + self_attn->key_layer_out = qkv + self_attn->pre_seq_len * self_attn->head_hidden_size; + self_attn->value_layer_out = qkv + 2 * self_attn->pre_seq_len * self_attn->head_hidden_size; + self_attn->key_transposed_layer_out = qkv + 3 * self_attn->pre_seq_len * self_attn->head_hidden_size; + + // This 3 mmul need to think they have 16 rows instead of 13 + int padding = 3; + // TODO: Check that the outputs have enough space for the extra padding rows and cols + computeDense(self_attn->query_layer, self_attn->pre_seq_len + padding, input, self_attn->query_layer_out); // 13x16x4 (16x16x4) + computeDense(self_attn->key_layer, self_attn->pre_seq_len + padding, input, self_attn->key_layer_out); // 13x16x4 (16x16x4) + computeDense(self_attn->value_layer, self_attn->pre_seq_len + padding, input, self_attn->value_layer_out); // 13x16x4 (16x16x4) + + transpose_quant(self_attn->key_layer_out, self_attn->key_transposed_layer_out, self_attn->pre_seq_len +3, self_attn->head_hidden_size); // 4x13 + MatMul_scale(self_attn->key_transposed_layer_out, 1, self_attn->pre_seq_len * self_attn->head_hidden_size); //4x13 + + // Add padding 4x13 -> 4x16 + add_padding(self_attn->key_transposed_layer_out, aux_padding, self_attn->pre_seq_len, self_attn->head_hidden_size, padding); // 4x16 + + // 13x4x13 (16x4x16) + MatMul_multiply(self_attn->pre_seq_len + padding, self_attn->query_layer_out, aux_padding, intermediate, self_attn->head_hidden_size, self_attn->pre_seq_len + padding); + + // 13x16 -> 13x13 + remove_padding(intermediate, self_attn->pre_seq_len, self_attn->pre_seq_len, padding); + + //printf("\rSoftmax\n"); + computeSoftmax(intermediate, self_attn->pre_seq_len); + + // 13x13x4 + MatMul_multiply(self_attn->pre_seq_len + padding, intermediate, self_attn->value_layer_out, output, self_attn->pre_seq_len, self_attn->head_hidden_size); +} diff --git a/sw/applications/trans_versasense/selfattentionC.h b/sw/applications/trans_versasense/selfattentionC.h new file mode 100644 index 00000000..9206418b --- /dev/null +++ b/sw/applications/trans_versasense/selfattentionC.h @@ -0,0 +1,35 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_SELFATTENTIONC_H +#define FVLLMONTITRANSFORMER_SELFATTENTIONC_H + +#include +#include +#include +#include "dense_layerC.h" +#include "softmaxC.h" +#include "transposeC.h" +#include "matMulC.h" +#include "param.h" +#include "cgra.h" + +typedef struct { + Dense* query_layer; + Dense* key_layer; + Dense* value_layer; + int32_t* query_layer_out; + int32_t* key_layer_out; + int32_t* key_transposed_layer_out; + int32_t* value_layer_out; + int32_t* attention_scores; + size_t pre_seq_len; + size_t head_hidden_size; +} SingleHeadSelfAttn; + +void create_SingleHeadSelfAttn(SingleHeadSelfAttn*, size_t pre_seq_len, size_t input_dim, size_t head_hidden_size, int32_t** weightVector); +void destroy_SingleHeadSelfAttn(SingleHeadSelfAttn* self_attn); +void compute_SingleHeadSelfAttn(SingleHeadSelfAttn* self_attn, int32_t* input, int32_t* output, int32_t* qkv, int32_t* intermediate, int32_t* aux_padding); + +#endif //FVLLMONTITRANSFORMER_SELFATTENTIONC_H diff --git a/sw/applications/trans_versasense/softmaxC.c b/sw/applications/trans_versasense/softmaxC.c new file mode 100644 index 00000000..f9f8bd2b --- /dev/null +++ b/sw/applications/trans_versasense/softmaxC.c @@ -0,0 +1,38 @@ +// +// Created by alireza on 10/6/23. +// + +#include "softmaxC.h" + + +void computeSoftmax(int32_t* input, size_t seq_len) { + size_t width = seq_len; + float input_float = 0.0f; + for (int i = 0; i < seq_len; i++) { + // Look for the biggest value of the row + int32_t max_val = input[i * seq_len]; + for (int j = 1; j < width; j++) { // Assuming its squared (width = seq_len) + if (input[i * seq_len + j] > max_val) { + max_val = input[i * seq_len + j]; + } + } + for (int j = 0; j < width; j++) { + input[i * seq_len + j] = (int32_t) fmax(input[i * seq_len + j] - max_val, -32767); + } + // Sum all values on the row + int32_t sum = 0; + for (int j = 0; j < width; j++) { + input_float = (float) input[i * seq_len + j] / (float) (1 << NUM_FRACTION_BITS); + input_float = expf(input_float); + input[i * seq_len + j] = (int32_t) (input_float * (1 << NUM_FRACTION_BITS)); + sum += input[i * seq_len + j]; + } + float sum_float = (float) sum / (float) (1 << NUM_FRACTION_BITS); + float sum_inv = (float) (1 / (sum_float + 0.00001)); // prevent zero divide! + int32_t sum_inv_int = (int32_t) (sum_inv * (1 << NUM_FRACTION_BITS)); + for (int j = 0; j < width; j++) { + input[i * seq_len + j] = (int32_t) MUL(input[i * seq_len + j], sum_inv_int); + } + } +} + diff --git a/sw/applications/trans_versasense/softmaxC.h b/sw/applications/trans_versasense/softmaxC.h new file mode 100644 index 00000000..fa47176f --- /dev/null +++ b/sw/applications/trans_versasense/softmaxC.h @@ -0,0 +1,17 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_SOFTMAXC_H +#define FVLLMONTITRANSFORMER_SOFTMAXC_H + +#include +#include +#include +#include +#include "param.h" + +void computeSoftmax(int32_t* input, size_t seq_len); + + +#endif //FVLLMONTITRANSFORMER_SOFTMAXC_H diff --git a/sw/applications/trans_versasense/stftVec.h b/sw/applications/trans_versasense/stftVec.h new file mode 100644 index 00000000..62243064 --- /dev/null +++ b/sw/applications/trans_versasense/stftVec.h @@ -0,0 +1,3 @@ +#include + +int32_t stftVec[49920] = {14912, 16305, 15424, 7300, 9641, 14329, 15823, 14833, 8710, 8912, 12488, 14281, 12956, 9398, 6336, 9702, 11379, 9458, 8448, -1345, 9383, 7575, 5905, 6193, 3111, 9534, 6388, 5963, 4307, 3857, 8353, 3661, 5646, 4840, 2974, 7109, 3348, 5522, 5048, 3034, 7513, 5345, 5058, 3058, 4169, 7233, 5680, 3618, -1939, 4739, 5392, 5531, 33, 3007, 4967, 5296, 5527, 2470, 3793, 5821, 6674, 5596, 4762, 3355, 6805, 6530, 6062, 5061, 3296, 7232, 4892, 6914, 3984, 3459, 7001, 1128, 7354, 1476, 3216, 6049, -4246, 7120, -809, 2509, 4113, 1815, 6269, 1109, 1261, 649, 3559, 4808, 1742, -1118, -2260, 4541, 2638, 1333, -3683, -2573, 5324, 1096, -41, -624, -6914, 5797, 1474, -749, 1036, -1670, 5676, 1178, 1827, 1675, -136, 4838, -524, 2920, 1334, -531, 3606, -5997, 2613, -295, 48, 2645, -2879, 1699, -2664, 1454, 969, -350, 1126, -2504, 1496, -4513, 428, 343, -2119, -288, -2229, 1388, -1021, -1983, -3119, -993, 1492, -842, -2102, -953, -1, -371, 77, -3653, -82, 1169, -1377, 613, -13738, -824, 674, 323, 1161, -3526, -3042, -2042, -359, 1511, -495, -3982, -2008, -5367, 1620, 1015, -2366, 202, -646, 1594, 1724, -2351, 739, 1997, 1015, 1845, -2589, 177, 2716, -743, 1526, -470, -1415, 2187, -4764, 870, 808, -3751, 227, -6828, -105, 405, -2589, -2027, -4123, -1632, -2546, -762, -542, -3523, -4738, -7353, -263, -416, -3632, -11115, -1954, -1127, -2297, -2954, -4223, -1644, -3840, -5020, -878, -3430, -2904, -10526, -3978, 912, -4403, -3360, -6759, -4464, 1940, -4478, -2115, -5273, -6310, 2291, -4053, -1078, -4874, -7426, 2178, -5158, -729, -4946, -5026, 1817, -7019, -795, -4583, -3242, 1282, -4693, -973, -3386, -2762, 493, -3012, -1475, -2270, -2920, -526, -3119, -2724, -2058, -3040, -1411, -4985, -5214, -3154, -2122, -1653, -5183, -11004, -4021, -1058, -1492, -3140, -6113, -1651, -856, -1647, -2264, -3441, -398, -1874, -2567, -2166, -2328, -798, -4980, -4395, -2596, -2396, -3644, -6692, -6640, -3482, -3798, -7317, -2442, -9695, -4718, -7081, -2114, -1099, -12776, -6194, -10210, -933, -1213, -7281, -6705, -7503, -1230, -2569, -5561, -6399, -4361, -2941, -5049, -4606, -5694, -2735, -8393, -7371, -3951, -4559, -2440, -6246, -6732, -3286, -3792, -3112, -4097, -4957, -3010, -3817, -4315, -5844, -3629, -3569, -5020, -5387, -6388, -2664, -5189, -8333, -6113, -2933, -3172, -7335, -9106, -7623, -2443, -5793, -6899, -6885, -8790, -3850, -8549, -6246, -6705, -6422, -6173, -5584, -6214, -8112, -5561, -6842, -3056, -5853, -11115, -5960, -6204, -2619, -5710, -8982, -6899, -5422, -3612, -6354, -6516, -7562, -5662, -4805, -6666, -5380, -5988, -8942, -4464, -5836, -6103, -4564, -7665, -3820, -5569, -8363, -3404, 10828, 5093, 9764, -637, -1552, 10180, 2996, 9296, 6157, -1414, 7937, 1593, 7768, 8228, -1236, 3042, 5579, 4561, 8634, -1291, 5745, 5866, -6705, 8019, 155, 7198, 3995, 2562, 6854, 2672, 6888, 2944, 4211, 6122, 4286, 5550, 4832, 4819, 6019, 4892, 5059, 5588, 5210, 5793, 4758, 5333, 5427, 5537, 5286, 4384, 4038, 4426, 5806, 4500, 4318, 2973, 2464, 5976, 4362, 4433, 5399, 2003, 5762, 5286, 4124, 6167, 3180, 4809, 5521, 2925, 5501, 3242, 2970, 4332, 1057, 4220, 2436, 677, 1175, 673, 3549, 1524, -996, -167, 1419, 3283, 855, -620, 1349, 1891, 3126, 21, 330, 1025, 1342, 3396, -364, 327, -259, -1672, 3904, 71, -113, -1710, -6133, 4303, -450, 51, -3479, -1414, 4283, -3264, 810, -3551, -2265, 3610, -6553, 1101, -15, -3014, 2068, -975, 654, 2445, -489, -830, 960, -122, 3656, 93, -5306, 1371, -1404, 3822, -1012, -2156, 480, -2754, 3166, -4172, -672, -1771, -874, 2085, -8220, -826, -4369, 125, 855, -4587, -2741, -5810, -768, -817, -3047, -6434, -8304, -5387, -1710, -1638, -3329, -2813, -2703, -143, -570, -1822, -1158, 622, 1100, -62, -1450, -1265, 1921, 1670, -287, -1317, -885, 2352, 1712, -1175, -749, 658, 2223, 1136, -476, 383, 1404, 1729, -347, 1100, 1501, 1061, 1107, -1263, 1494, 2095, -436, 523, 769, 671, 1946, -3210, -247, 1958, -288, 949, -4718, -1497, 1982, 172, -953, -3906, -2817, 1200, 314, -3714, -2514, -3680, 118, -902, -5827, -757, -4795, -515, -4974, -5055, -82, -5592, -101, -5554, -3961, -884, -5933, 355, -1759, -3638, -3811, -7708, -148, -1153, -4611, -11004, -9064, -1975, -2050, -6628, -7066, -5638, -3629, -3916, -6914, -10138, -3680, -2139, -5897, -8982, -6516, -2553, -1392, -8304, -9106, -3362, -1838, -1752, -14784, -4184, -2143, -1250, -3007, -9936, -2855, -1925, -717, -3695, -7644, -3151, -2452, -369, -2181, -5988, -4708, -3049, -406, -1225, -4564, -6602, -2813, -792, -1364, -3741, -5897, -2208, -1155, -2590, -3824, -4028, -1736, -1501, -5768, -5031, -2655, -1393, -2299, -7426, -5979, -2328, -1391, -3447, -2811, -5085, -3314, -2265, -3927, -1129, -4344, -5091, -4821, -3474, -589, -3947, -4532, -5623, -2869, -734, -4086, -4238, -3644, -2960, -1232, -4991, -6388, -3824, -4195, -1711, -5189, -11115, -5121, -4853, -2061, -3415, -5208, -4620, -2935, -2325, -1779, -3653, -3518, -1713, -2205, -884, -3294, -2666, -1488, -1954, -786, -3284, -1922, -2323, -2517, -1617, -3324, -1739, -4929, -5037, -4168, -3501, -2587, -9479, -5646, -10613, -4234, -5299, -4821, -2382, -2999, -6504, -7066, -3704, -1370, -1359, -28777, -4180, -3334, -1195, -1571, -6457, -2863, -2720, -882, -3203, -4974, -1921, -2339, -720, -4649, -4918, -1642, -2490, -1214, -4693, 8017, 5947, 8461, -2751, 9815, 7223, 6127, 8022, 2956, 9154, 4829, 5941, 7036, 5360, 7050, 4691, 5145, 5777, 5602, 3055, 6247, 4556, 3163, 3280, 1784, 6437, 3659, 2851, -3773, 4380, 5688, 1593, 5111, 3385, 4920, 4215, -50, 5408, 4045, 2722, 2053, -1742, 5027, 3237, 1031, 686, -10526, 5369, 2846, 5125, 2484, -1146, 6142, 3540, 5804, 4808, 926, 6608, 4504, 5018, 5994, 2364, 6477, 4881, 5104, 5893, 3248, 5468, 4141, 5982, 4460, 3000, 3115, 1903, 6320, 1467, 1021, -374, -2309, 6455, -3121, -5933, 1092, -3853, 6291, -4226, -2543, 1916, -3034, 5247, -2984, -312, 1637, -1636, 2669, -1564, 1060, 993, 444, -5085, -348, 2313, 309, 2137, -1156, 752, 2779, -235, 3077, 440, 1579, 2012, 269, 3224, 1158, 1843, -941, 1646, 2635, 2681, 1328, -8165, 2411, 1417, 3713, -223, -1668, 2049, 42, 3602, -2294, -1941, 537, -310, 2031, -1652, -2813, -577, 669, 624, -1099, -1117, 2, 1906, 2465, -1414, -852, -10, 2704, 3213, -1290, -2107, -628, 2970, 2815, -1178, -3975, -987, 2822, 2019, -1959, -4119, -1014, 2387, 1699, -3856, -2022, -896, 1673, 1995, -4500, -99, -984, 548, 2192, -1913, 1011, -757, -1355, 1698, -643, 1138, 883, -4408, 100, -1165, 162, 2147, -2661, -3259, -1635, -1216, 2327, -155, -10284, 1244, -206, 1579, 1159, -5793, 2667, 1028, 571, 1620, -2739, 2356, 869, 144, 1279, -1083, 29, -1014, -14, 96, -609, -8754, -1797, -161, -2169, -1144, -3281, -350, -385, -5554, -1973, -2571, -1009, -768, -4274, -1250, -3947, -4929, -1129, -3638, -687, -5509, -7464, -1615, -4331, -1858, -6204, -5584, -2211, -2430, -3557, -5531, -10001, -2042, -703, -856, -3471, -4115, -1611, -507, 467, -2635, -2046, -1894, -2326, 329, -3692, -1847, -2990, -6007, -1055, -9479, -2388, -5020, -991, -3992, -4559, -2541, -9936, 756, -8718, -2172, -2325, -5115, 971, -5266, -1954, -2102, -2722, 152, -3879, -3031, -2394, -2316, -1551, -4837, -4810, -3609, -3436, -3927, -12123, -5960, -3615, -4980, -4319, -4003, -5380, -2853, -3299, -3027, -1630, -4795, -4064, -1941, -2835, -1077, -4963, -9238, -1576, -4226, -1491, -5836, -5735, -1713, -9873, -2353, -7484, -4478, -1912, -6666, -3025, -11629, -5509, -2004, -3923, -3124, -14195, -7503, -2003, -3735, -2847, -9238, -6928, -2170, -4550, -2569, -5020, -4597, -2973, -3876, -2259, -2514, -3147, -5360, -2971, -1992, -1383, -2703, -12319, -3367, -2531, -1215, -2447, -5524, -4674, -5043, -1759, -1943, -4270, -3930, -6719, -2637, -1755, -4555, -2320, -4064, -2416, -1813, -4743, -1622, -4659, -1259, -1760, -5422, -1971, -7774, -641, -2088, -9479, -3574, -5638, -733, -3194, -6943, -7034, -5465, -1246, -4307, -4230, -12319, -8942, -1642, -3947, -3735, -8220, -7464, -4545, -4420, -4100, -4527, -2182, -4157, -5654, -1990, -2831, -1894, -4089, -5888, -1433, -2648, -3083, -3365, -4659, -2673, -3172, -6225, -3215, -3261, -5988, -3647, -8333, -3191, -2580, -17034, -2939, -6928, -2590, -2912, -6553, -2438, -6759, -2232, -4230, -3594, -3465, -5718, -2718, -5988, -3135, -5599, -4219, -4365, -10069, -4274, -3331, -3748, -9022, -6842, -6225, -1217, -4238, -7408, -4980, -8304, -146, -4067, -4145, -5906, -8683, 89, -3286, -3362, -5638, -5031, -634, -3577, -3580, -4491, -3430, -2642, -5726, -3621, -6173, -3378, -6246, -11356, -3455, -7445, -4523, -5793, -7644, -3968, -5710, -6640, -4858, -7066, -4805, -5429, -7004, -5906, -10899, -4968, -3444, -4923, -7752, -8165, -5576, -3114, -3680, -4319, -4242, -7464, -4991, -2851, -2485, -2437, -6615, -8165, -1779, -2273, -1313, -5662, -7523, -1053, -3326, -705, -6870, -4858, -1173, -4831, -749, -9064, -3311, -2031, -5415, -1427, -10069, -2891, -3342, -4951, -2348, -6103, -2977, -4957, -4532, -2809, -3076, -2952, -5444, -4826, -2731, -1731, -2861, -4093, -5810, -2825, -1404, -2952, -3801, -6492, -3680, -1752, -3650, -5759, -6553, -5444, -2937, -5726, -8942, -6958, -7623, -5638, -10526, -5906, -7865, -9429, -6828, -12534, -6434, -8903, -8086, -4597, -10442, -11004, -8363, -4935, -4299, -7687, -5554, -6516, -3232, -5743, -5374, -3609, -4754, -3067, -8276, -4270, -3554, -3560, -4713, -6045, -4278, -4847, -3149, -8942, -4550, -4946, -6354, -3537, -14784, -4759, -5970, -5202, -4319, -8549, -6759, -7050, -4035, -4390, -3710, -6885, -6540, -3653, -3415, -1844, -3763, -5531, -3883, -2969, -1482, -2312, -4912, -4184, -4003, -2247, -2188, -4399, -3309, -7752, -3923, -3301, -3820, -2055, -7503, -5615, -5227, -3609, -1579, -5279, -5694, -5879, -4555, -2116, -5607, -4698, -5145, -7842, -3476, -7960, -3543, -4082, -8138, -4592, -15615, -2543, -3187, -5260, -5227, -10442, -1836, -3163, -4455, -6007, -9585, -1480, -4130, -3920, -5997, -12319, -1490, -4219, -2982, -4688, -13365, -1631, -2859, -2295, -3259, -9238, -1475, -2268, -2720, -2843, -7019, -1047, -2589, -5592, -3754, -5670, -787, -3692, -9238, -6321, -4211, -1091, -5776, -4779, -13738, -2752, -2452, -8247, -4616, -9936, -2111, -6016, -6856, -5170, -7644, -2749, -13365, -5951, -5170, -7623, -5115, -7936, -5646, -5458, -9238, -8393, -8192, -5480, -6153, -9193, -6214, -6143, -6354, -7464, -7912, -5862, -4718, -9380, -9238, -8517, -8304, -4523, -8165, -6800, -8304, -10799, -5183, -6504, -5380, -5437, -5630, -6133, -7796, -5026, -3741, -4028, -6153, -28777, -4455, -3261, -3717, -5844, -8582, -4258, -3707, -4254, -5836, -7113, -5020, -4464, -5554, -6163, -7179, -6679, -4842, -7130, -8009, -7353, -8718, -5266, -7960, -13049, -7503, -9585, -6214, -8034, -11945, -6973, -9106, -8192, -9284, -10284, -6267, -6899, -13738, -10613, -5487, -6246, -5408, -12776, -6007, -3717, -4555, -2540, -3259, -2526, -6814, -5214, -5014, -4513, -4361, -7665, -12123, -6914, -5266, -3850, -3689, -4858, -4176, -5827, -2472, -2419, -2973, -2615, -6773, -2116, -2401, -3982, -2319, -5759, -2344, -3165, -6540, -3404, -4683, -2664, -4759, -4100, -6299, -4611, -2778, -8683, -3279, -6528, -4625, -2470, -7623, -4097, -4718, -4555, -2247, -3804, -5801, -3741, -6143, -2831, -2311, -7623, -2743, -13365, -4674, -2091, -9429, -1872, -4946, -8165, -3203, -7603, -1785, -3001, -10284, -6516, -5208, -2929, -2557, -8942, -6288, -4315, -5924, -2735, -6528, -3817, -4093, -12534, -3441, -5592, -3449, -3399, -5333, -5897, -7523, -4003, -2567, -3135, -9639, -9753, -4518, -2483, -2655, -3329, -5121, -4509, -3479, -3701, -1581, -4810, -4541, -5599, -6173, -1304, -5743, -5768, -5480, -5319, -1830, -3889, -8333, -3281, -4104, -2596, -2847, -4564, -2084, -3893, -3220, -2945, -1420, -1892, -3641, -4003, -3096, 102, -2587, -3659, -5487, -3447, 272, -3763, -4395, -8086, -4784, -888, -4620, -4880, -10526, -5234, -3698, -5374, -4365, -7730, -3863, -8192, -6516, -4149, -5091, -3463, -3504, -8192, -3656, -3490, -4416, -1397, -10138, -2937, -2999, -7213, -731, -8982, -3296, -3635, -5221, -890, -6376, -5694, -4923, -2714, -1481, -3723, -12319, -4874, -2390, -2344, -1961, -5702, -3717, -4592, -3653, -1198, -4086, -2877, -9022, -6204, -1377, -3788, -2650, -2819, -13738, -2488, -4149, -3184, -1308, -7464, -4654, -5221, -4282, -1307, -6016, -8009, -8549, -5480, -2356, -6692, -11781, -8485, -7019, -4486, -7644, -6732, -3779, -8393, -8304, -5960, -3269, -1903, -5654, -17034, -4644, -1553, -1214, -3482, -13738, -4352, -1036, -1380, -2472, -8009, -4743, -1560, -2359, -2308, -6288, -5133, -3135, -4307, -2809, -7213, -4743, -5494, -7503, -3603, -5784, -4509, -5615, -10001, -4127, -2594, -5333, -4513, -9022, -4149, -1202, -7162, -4199, -7984, -3883, -1068, -8009, -4373, -6640, -3795, -2002, -6332, -4573, -5694, -4336, -4024, -4759, -4518, -5718, -5997, -7644, -4369, -4274, -7644, -9022, -9064, -5429, -4344, -10526, -7019, -6422, -8192, -4800, -5061, -4578, -6173, -9873, -4578, -3417, -3196, -8165, -8276, -3589, -3656, -2383, -12319, -6516, -3309, -5260, -2084, -11356, -4469, -4274, -6083, -2228, -10799, -3010, -7623, -6123, -2733, -12319, -2455, -10526, -7281, -3827, -28777, -2960, -5480, -5670, -5524, -10799, -4743, -4635, -3903, -6388, -6928, -4698, -5702, -3324, -6007, -4810, -2557, -7264, -3592, -5465, -3603, -1878, -6480, -4486, -5183, -3126, -2516, -6267, -5569, -5008, -3509, -3985, -7389, -5960, -4644, -5319, -5394, -8683, -5387, -4469, -9936, -6310, -8138, -4874, -4874, -8683, -5638, -6943, -5247, -5694, -7603, -4800, -5862, -6577, -6842, -8982, -5339, -4858, -7687, -8060, -12534, -7408, -4583, -7066, -8615, -17034, -6434, -5924, -6173, -8276, -8827, -5253, -12319, -6007, -7687, -5646, -6553, -1616, -3168, -4523, -6016, -3795, -1521, -2644, -7130, -5091, -1944, -1469, -2478, -11115, -4863, -1434, -1404, -2879, -4795, -4006, -2223, -1601, -3860, -2770, -1831, -3982, -2524, -5458, -2497, -198, -5026, -4698, -9064, -3600, 328, -4013, -9380, -8754, -4429, -321, -2904, -11004, -5844, -3707, -2216, -2825, -12123, -5630, -3964, -5827, -3476, -12319, -6773, -4853, -12776, -3989, -7445, -7752, -4569, -4837, -4644, -6093, -7066, -4597, -2904, -5524, -5654, -6054, -5170, -2916, -5401, -5569, -4455, -3735, -4420, -4344, -5451, -2621, -1704, -5630, -3493, -4674, -1621, -745, -5472, -2865, -2960, -1343, -1158, -7353, -1661, -1247, -1313, -3352, -12319, -744, -222, -1299, -7247, -7936, -858, 81, -1263, -4896, -10613, -2191, -231, -1343, -3261, -7644, -4482, -1159, -1726, -2947, -4679, -3474, -2504, -2605, -4142, -4053, -1219, -3286, -3913, -6183, -4010, 40, -3726, -3574, -4795, -3732, 355, -4880, -1321, -3883, -3208, -275, -7299, 124, -4630, -3463, -1966, -13049, 606, -6988, -6007, -3563, -5906, 326, -8942, -8865, -2741, -4278, -326, -8247, -5465, -2248, -4491, -836, -5292, -4601, -1898, -4635, -1391, -3729, -3827, -1090, -3551, -2791, -3971, -3175, -619, -2560, -5133, -6016, -2642, -662, -2094, -5008, -10704, -2646, -816, -2348, -4266, -11115, -3352, -1060, -3471, -4688, -6246, -2737, -1822, -5451, -4912, -4203, -1507, -3085, -6899, -3671, -3304, -1426, -4262, -5319, -2751, -2895, -2861, -5360, -4203, -2811, -2619, -6928, -7196, -3982, -3580, -2599, -10138, -9812, -4523, -3944, -3227, -6376, -6528, -5686, -3430, -4991, -4299, -4149, -5333, -3161, -7984, -2364, -3189, -3923, -3476, -6958, -1409, -3163, -3412, -3999, -5109, -1477, -3961, -3606, -3957, -4601, -2559, -6299, -4348, -3653, -5751, -4130, -11356, -5670, -4086, -10704, -4504, -7050, -5915, -5897, -10526, -4601, -8009, -4254, -7196, -8827, -4211, -6870, -2685, -5662, -8582, -2813, -2803, -1836, -5906, -5516, -2305, -1349, -1816, -9380, -4447, -3247, -1220, -2386, -10799, -5240, -6422, -1849, -3294, -5735, -8363, -8582, -2821, -4644, -3833, -17034, -5546, -3795, -4703, -3045, -15615, -5067, -4250, -3535, -2887, -8582, -5718, -4331, -3644, -2931, -4929, -7130, -5014, -5531, -3147, -3476, -7503, -6343, -7066, -3482, -3554, -4805, -6354, -5394, -3889, -5607, -2731, -5531, -5686, -4550, -28777, -1501, -6133, -9429, -5592, -6719, -926, -12534, -9331, -7130, -5988, -990, -6214, -6640, -9238, -9331, -1743, -3326, -7353, -11945, -8220, -3261, -2889, -9106, -17034, -5776, -4991, -4226, -8086, -13738, -5253, -5195, -8165, -7960, -11488, -3695, -4559, -9284, -6856, -10799, -2517, -4336, -6928, -4640, -11629, -2720, -4923, -6615, -3447, -13365, -4513, -6640, -6786, -3314, -13049, -8333, -9064, -6692, -3916, -28777, -9022, -8333, -6133, -4500, -9429, -7213, -7034, -6064, -4258, -7264, -6434, -6705, -6666, 932, 7831, 7734, 5628, 2792, 5612, 7584, 7412, 5643, 3008, 7135, 6918, 6604, 5495, 2765, 6849, 6058, 5777, 4981, 1614, 6250, 5237, 5093, 4168, 1506, 6575, 4429, 4081, 3167, 2167, 6332, 3603, 2703, 2383, 1879, 4534, 3082, 2056, 3001, 993, 3610, 3376, 2564, 4093, 389, 5459, 4085, 3280, 4615, 372, 6118, 4222, 3667, 4530, 2164, 5969, 3504, 3511, 3670, 4618, 5289, 2286, 2860, 1070, 6124, 3514, 1379, 2043, -2992, 6525, -1364, 1278, 1404, 1455, 5802, -978, 1386, 1268, 2186, 3730, 1196, 584, 1598, 1340, -866, 922, -1921, 1457, 769, -4713, -145, -4564, 368, 1357, -1004, -636, -1618, -1302, 1839, -702, -80, -725, -2412, 2166, -1106, 443, -2079, -3261, 2277, -1727, 577, -3618, -6365, 1796, -2718, 249, -744, -6045, 720, -4863, -707, 556, -2038, -108, -10799, -2226, 1149, -860, -359, -9193, -3430, 1821, -474, -807, -6528, -4184, 2401, -299, -1386, -4168, -5853, 2410, -639, -2007, -2487, -6786, 1465, -1693, -3311, -1512, -4365, -930, -3110, -6628, -773, -3529, -2578, -3985, -10526, -262, -4290, -251, -4918, -5121, -291, -6492, 561, -6153, -3378, -1169, -9064, -98, -4918, -1758, -3326, -5516, -2714, -3444, -714, -7796, -3103, -3788, -2713, -804, -6988, -1880, -81, -2328, -1839, -3184, -1669, 1150, -2536, -2733, -1206, -2677, 582, -4258, -2391, -935, -5333, -2257, -9753, -1548, -2621, -5702, -2871, -9936, -1141, -1943, -4082, -887, -5353, -1427, 350, -3735, -1374, -2737, -1841, 835, -3507, -2276, -2207, -1448, 107, -2900, -716, -4191, -453, -520, -2289, 295, -6045, 217, -106, -1898, 182, -2333, 101, 222, -2008, -1052, -1240, -1064, -119, -2873, -3853, -1394, -4017, -1567, -4482, -8865, -2108, -7842, -3399, -5710, -7984, -2900, -2879, -1551, -4290, -5960, -4082, -1188, -263, -2294, -2567, -4242, -932, -254, -1130, -479, -2597, -2079, -1087, -1029, 454, -2294, -5339, -1921, -1894, 557, -4003, -4779, -2204, -1987, 202, -8827, -2457, -2797, -806, -339, -6376, -2121, -4527, -431, -1240, -4416, -3027, -7464, -1214, -2699, -2728, -3126, -5879, -3220, -4743, -864, -1900, -3940, -7842, -7665, 373, -2057, -3213, -8247, -6016, 477, -5055, -3386, -4923, -2300, -848, -6354, -3683, -4738, -13, -3650, -2904, -2813, -5002, 1256, -4523, -3051, -1623, -5227, 1543, -4611, -6093, -971, -6958, 712, -6256, -9812, -884, -4713, -1903, -7066, -6288, -1225, -2655, -15615, -5686, -6225, -1772, -1821, -3577, -5422, -7317, -2079, -1233, -2217, -7247, -7445, -1820, -1109, -2010, -4940, -5494, -1430, -2050, -2150, -2705, -3873, -1524, -4513, -3163, -2322, -3577, -2619, -7019, -5031, -3140, -5279, -5718, -5026, -4885, -4991, -7842, -12534, -4254, -3726, -10362, -4728, -6204, -4262, -2906, -6565, -3512, -5678, 4316, 6840, 4580, 3259, 2961, 3196, 6302, 4364, 4515, 4850, -2189, 4595, 3767, 5579, 6678, -8, 1191, 3113, 5479, 7398, 1764, -3457, 3130, 4156, 7223, -72, 553, 3813, 980, 6468, -7371, 2078, 4266, -23, 5328, -2265, 2586, 4023, 2669, 3707, -2463, 2829, 3190, 2994, 2463, -102, 3540, 2562, 2035, 2297, 2715, 4283, 2588, 2467, 1653, 4380, 4206, 2668, 3759, 2099, 4951, 3010, 2580, 4152, 3622, 4324, 1384, 2176, 3648, 4382, 2404, 1373, 1205, 2377, 4348, 941, 1380, -7, 487, 3747, 2119, 362, -75, -1494, 2973, 2771, -1351, 64, -2320, 2439, 2497, -1677, -1025, -2226, 1842, 1102, 224, -3422, -1604, 663, -1923, 1872, -5061, -679, -443, -1422, 2804, -5139, -1046, 330, -8, 3132, -1012, -4578, 1123, -743, 3080, 1385, -1940, 966, -3101, 2873, 2456, 533, 283, -2601, 2558, 2671, 941, -133, -1694, 1944, 2146, 846, -549, -2331, 805, 739, 952, -1741, -3735, -908, -1928, 513, -3463, -3203, -3018, -6256, -680, -3647, -1755, -5115, -8034, -1650, -4564, -1343, -5266, -6856, -1319, -2139, -1374, -4611, -3732, -501, 441, -37, -5494, -1592, -474, 1434, 1374, -7162, -797, -1931, 1590, 1724, -5924, -1475, -7162, 1209, 792, -6732, -3999, -4774, 4, -1714, -3957, -7019, -1597, -2432, -4399, -515, -7004, -533, -4433, -3830, 886, -7213, -678, -3360, -2885, 914, -6469, -2046, -2772, -823, -221, -12123, -2254, -3201, 351, -2128, -5020, -269, -5043, 406, -3049, -2102, 720, -8247, -453, -2027, -1515, 723, -9429, -1477, -926, -1857, -35, -6288, -644, -118, -1424, -1418, -5121, 610, 332, -336, -3010, -7130, 1036, 334, 407, -3726, -5509, 532, -84, 788, -3266, -3337, -942, -752, 896, -2929, -4046, -3027, -1414, 705, -3738, -4258, -3944, -2129, 86, -6064, -2058, -3638, -3543, -1160, -5387, -1560, -3501, -6914, -3441, -3671, -2279, -3978, -5561, -7146, -2516, -2531, -5202, -2555, -7213, -1473, -1336, -7179, -1366, -5509, -786, -174, -6958, -1460, -4743, -383, 263, -4089, -2606, -4890, -250, -23, -2473, -3457, -5818, -641, -581, -2185, -2791, -4957, -1481, -1194, -3626, -2176, -3158, -1772, -2403, -12776, -1952, -2175, -1504, -4482, -3018, -2062, -1852, -1760, -9331, -537, -2648, -1958, -2752, -4946, 15, -3985, -1967, -4592, -1143, -841, -6267, -1828, -9429, 148, -3334, -8485, -2964, -6856, -115, -8827, -7796, -11004, -4234, -1987, -10069, -6469, -3603, -3989, -4429, -28777, -4774, -1689, -2833, -1841, -7196, -3425, -2690, -1066, -410, -4980, -3259, -7162, -712, -360, -4816, -4733, -3135, -2079, -1277, -5546, -5415, -506, -4842, -1949, -6411, -3717, 630, -3686, -1086, -6679, -3085, 724, -2351, -227, -5539, -1996, -194, -1837, -24, -4536, -775, -2095, -1846, -600, 4204, 4660, 8026, 4595, 10348, 5216, 6364, 7879, 6734, 10114, 6388, 7902, 7603, 8184, 9483, 6672, 8301, 7352, 8347, 8510, 6065, 7650, 6789, 7585, 6985, 4981, 5876, 5470, 5887, 4510, 4088, 2554, 3362, 2625, 913, 3100, -926, 1407, -2228, -1682, 1032, 1499, 500, 1081, -984, -5374, 2541, -499, 1444, 74, -63, 2881, -21, -1083, 380, 2868, 3249, 2361, -2468, 2511, 3658, 3656, 3250, 2448, 4665, 2668, 3597, 2784, 4143, 5772, -546, 3238, 2202, 4779, 6199, 1526, 3364, 2774, 4899, 6270, 3139, 3512, 3183, 4641, 5958, 2564, 2909, 2858, 4004, 5026, -600, 1562, 1949, 2914, 3245, -4270, 109, 896, 1058, 679, 400, -274, 447, -2273, 42, 1204, 271, 808, -1407, 771, 785, 102, 1315, 1105, 385, 659, -2121, 1218, 2230, -1169, 1082, -6705, -6, 2556, -2267, 537, -1325, -2918, 2243, -1235, -1197, -490, -2675, 1355, -1544, -853, -1973, -450, 731, -2145, -220, -5415, 436, 1433, 489, -1404, -5630, 824, 2053, 1834, -3647, -3933, 1111, 1895, 1760, -3840, -1071, 1164, 1358, 889, -5561, 379, 857, 1312, 299, -6332, 591, 524, 1344, 648, -3080, 239, 679, 365, 1063, -1778, 463, 1396, -2128, 683, -575, 1417, 2220, -1558, -613, -261, 1921, 2688, -201, -1114, -2478, 1256, 2491, -850, -483, -5234, -1437, 1384, -2399, -648, -747, -3603, -914, -1382, -941, -779, -244, -2722, -688, 270, -3504, 390, -1014, -1146, 1486, -1465, -367, 121, -2292, 1870, -288, -1530, 429, -3773, 1307, -1486, -2531, 51, -4728, -401, -5480, -4028, -988, -4352, -3476, -12123, -5531, -2524, -3031, -7912, -7213, -5569, -4536, -1974, -28777, -4620, -5085, -4674, -2094, -10210, -3367, -5170, -1721, -3471, -8304, -3213, -5561, -277, -4826, -6256, -3444, -4784, -27, -4951, -4164, -4286, -4907, -532, -2670, -2130, -7796, -8192, -1419, -372, -1249, -6640, -4365, -2580, 615, -1821, -2967, -1713, -4282, 474, -3883, -1777, -1338, -6705, -574, -6958, -1553, -2962, -7050, -1909, -6083, -1713, -7644, -5979, -2574, -4601, -2608, -5319, -6133, -3795, -5234, -6194, -2805, -7299, -9064, -9238, -6692, -1369, -7281, -3161, -8517, -3201, -1020, -3444, -403, -6773, -2432, -1950, -828, 488, -7819, -1538, -3638, 235, 262, -4816, -647, -3883, -250, -765, -1513, -668, -3428, -2956, -2107, 221, -1687, -3294, -5240, -2637, 845, -3227, -3321, -2197, -2455, 567, -4211, -2766, -1743, -3438, -578, -4429, -1332, -2407, -10362, -2926, -4923, -359, -3801, -3609, -7842, -7603, -317, -4810, -877, -4469, -6143, -1126, -2950, -247, -2541, -1842, -2576, -1837, -697, -2922, -164, -5480, -1197, -1926, -7004, 63, -9531, -408, -5319, -5942, -1040, -2975, -67, -5183, -2497, -3692, -1281, -558, -960, -1859, -3840, -2176, -4053, -3080, -4795, -4290, -1389, -3754, -2438, -2566, -7335, -483, -3187, -1656, -1071, -4769, 227, -2231, -1377, -274, -2779, 499, -2701, -1962, 11, -2603, 361, -5465, -3194, -105, -2339, 37, -4569, -3883, -603, -1494, -218, -2971, -3071, -1480, -1470, -339, -4112, -1980, -2726, -2605, -705, -6814, -1701, -3227, -2447, -1825, -4382, -2442, -1534, -464, -3982, -3964, -3574, 24, 504, -4017, -4219, -3662, 867, 149, -2107, -2889, -2908, 1201, -1943, -1336, -2090, -2165, 1240, -6093, -1559, -2105, -2086, 1110, -4968, -2231, -1734, -3692, 520, -5049, -2076, 39, -10526, -1695, -603, -447, 2042, -1748, -2943, 1814, 1402, 3282, 518, 1279, 2560, 2470, 3513, 1056, 2696, 2051, 2503, 2648, 589, 2458, 359, 1399, 535, -181, 801, -2617, -1019, -3023, -357, -1397, -6343, -3801, -5654, -84, -1883, -7562, -2964, -5743, -332, -2805, -5584, -1599, -7687, -1928, -4464, -3846, -705, -12776, -6123, -4013, -3334, -459, -6045, -5784, -3062, -3769, -902, -3975, -4278, -2322, -4764, -2051, -3680, -4644, -1726, -5906, -3795, -5726, -5646, -1544, -6577, -5299, -7408, -5576, -2053, -6399, -4968, -2601, -4390, -4042, -6553, -3650, -1226, -4191, -14195, -7445, -2893, -1850, -4968, -2821, -6528, -3083, -5319, -3546, -393, -4718, -3373, -5951, -1532, 218, -3704, -2361, -3401, -735, -517, -3306, -1231, -4067, -1150, -2356, -2257, -607, -7445, -2686, -3257, -765, -349, -8485, -5127, -3430, -172, -510, -5599, -7523, -5472, -1054, -1458, -3213, -7389, -6422, -3496, -3814, -2080, -5951, -4587, -2158, -7503, -2356, -4315, -4504, -671, -4880, -4168, -3005, -3814, -1130, -3843, -9585, -2867, -2065, -4028, -3833, -8165, -4142, -1002, -9106, -3319, -5554, -6732, -713, -3850, -2398, -5853, -11945, -1125, -2774, -1831, -7842, -8034, -2292, -2248, -1784, -6958, -4191, -4311, -2020, -2216, -5079, -2853, -7371, -2562, -3237, -4242, -2608, -6842, -3612, -5227, -3618, -2962, -4606, -4223, -7050, -2762, -4053, -3415, -4708, -5524, -2214, -6133, -2776, -5026, -5415, -2317, -5836, -2592, -5374, -7752, -3060, -4172, -3025, -8112, -10138, -4500, -4013, -4046, -6565, -6988, -4885, -5592, -4901, -3311, -4654, -2900, -10799, -5152, -2507, -3420, -1932, -8718, -6214, -3187, -3580, -2276, -6745, -7408, -4918, -4968, -3626, -7730, -5055, -5997, -5743, -5152, -14784, -3206, -5827, -4282, -5924, -8034, -2182, -6422, -2920, -6528, -5387, -1613, -7936, -2179, -7408, -4386, -1411, -8718, -2104, -9238, -4138, -1513, -9639, -2728, -8942, -4842, -1716, -8683, -4226, -7842, -7335, -1868, -6288, -6288, -10526, -12123, -2152, -5888, -5933, -9753, -9380, -2941, -7708, -5067, -5458, -10799, -4442, -10284, -5195, -4587, -10001, -6035, -8649, -5494, -5888, -7774, -7081, -10799, -5306, -10442, -8009, -8304, -11356, -5055, -5988, -9812, -8615, -3900, -553, -5221, -2473, -2213, -3140, -1576, -5247, -3701, -4282, -2123, -3837, -3425, -6026, -2889, -1109, -3563, -4412, -11629, -1478, -291, -1218, -8333, -4157, -894, 217, 97, -3012, -1869, -830, 310, 567, -1073, -1373, -1528, -156, 288, -260, -2328, -3626, -1521, -787, 241, -4698, -8165, -5253, -2875, 333, -5026, -8060, -6054, -6565, -417, -3383, -6214, -2006, -7213, -2264, -3049, -3509, -1206, -3723, -3184, -3906, -1796, -2219, -2139, -2108, -3659, -1083, -5662, -1870, -1939, -1976, -998, -10001, -2316, -2718, -1005, -1446, -3650, -2795, -3978, -562, -2661, -972, -2877, -3735, -168, -4985, 1098, -740, -1271, 673, -3735, 2599, 1206, 435, 1678, -1448, 3280, 1886, 935, 1957, -1076, 2983, 1328, 255, 1045, -2863, 1566, -630, -1661, -1194, -6422, -1276, -4564, -4630, -2668, -2473, -5988, -3824, -4078, -2334, -1148, -6469, -1571, -2292, -2235, -1289, -5561, -511, -1786, -1513, -1826, -5710, -14, -3038, -1143, -1943, -6828, 6, -9380, -1432, -2883, -7408, -558, -2845, -1815, -8192, -5871, -1991, -925, -2204, -3817, -4482, -4858, -1420, -2675, -1124, -4006, -7389, -4784, -2574, -812, -3650, -5472, -7912, -2470, -1980, -1889, -5067, -3479, -3441, -3903, -280, -5509, -2686, -5576, -4723, 199, -4550, -2943, -4654, -4348, -712, -2378, -3554, -2825, -3597, -3244, -867, -4142, -2356, -3092, -2935, -259, -4315, -3455, -3172, -1121, -393, -3763, -7445, -4038, -624, -1052, -2999, -8649, -5312, -716, -2066, -2893, -6163, -3686, -813, -3447, -3247, -5970, -2030, -804, -3866, -3203, -5465, -1772, -1001, -3182, -2877, -4578, -2606, -1740, -3638, -2863, -3094, -3701, -3378, -4195, -3417, -1825, -3735, -6310, -2845, -5531, -1286, -2517, -4606, -2580, -6492, -1435, -1390, -2545, -4089, -3215, -2314, -1072, -2380, -5394, -2340, -4071, -1687, -3900, -3863, -3151, -5988, -3208, -5360, -3098, -5630, -4597, -4795, -3817, -2967, -12319, -2807, -5638, -3137, -3140, -9585, -1914, -7371, -3344, -3683, -5879, -2235, -6225, -4242, -4901, -2847, -4478, -5299, -6814, -7426, -826, -6310, -7445, -7603, -8220, 71, -3704, -4896, -4254, -5942, 63, -3269, -2205, -3373, -5319, -536, -3954, -1660, -3665, -5002, -1393, -4800, -2724, -3232, -3665, -2205, -5970, -5176, -2031, -2599, -2107, -8393, -5444, -1426, -2375, -1440, -8086, -4149, -1504, -2529, -1431, -5768, -3788, -2152, -2610, -2323, -5091, -4327, -3485, -2952, -3671, -5871, -5127, -5906, -3843, -4340, -8615, -4207, -8363, -5214, -3827, -28777, -3175, -6928, -6745, -3289, -10442, -3254, -6480, -6719, -3471, -8827, -4442, -6204, -6800, -3954, -7523, -6173, -4784, -9284, -3893, -6590, -6870, -4226, -10138, -3785, -6376, -6773, -5158, -8220, -4134, -6640, -6732, -7819, -9149, -4733, -6653, -6899, -10069, -12319, -5139, -5942, -7484, -7865, -13738, -5273, -5353, -8247, -4115, -1217, -1712, 369, -2442, -2083, -1941, -2851, 474, -4053, -1533, -2184, -3225, -137, -6163, -1936, -2447, -3096, -1098, -4438, -2583, -5008, -3352, -1674, -2681, -2956, -7371, -4386, -1320, -1531, -3135, -2855, -5979, -676, -577, -3817, -2679, -7196, -238, -143, -6026, -5561, -7644, -40, -688, -6565, -4266, -6988, -80, -2787, -6399, -1821, -5592, -539, -5312, -15615, -1349, -5415, -1734, -2429, -5494, -2051, -8304, -4578, -805, -3615, -3213, -3609, -10704, -387, -2097, -2969, -955, -3321, -1073, -650, -1614, -438, -1816, -2465, -1057, -992, -1442, -1947, -2954, -9022, -2679, -3498, -1970, -2764, -199, -5924, -2047, -73, -560, 2556, 351, 586, 1562, 1676, 2931, 1882, 1790, 2018, 2694, 1170, 1523, 1804, 1111, 2643, -8086, -394, 860, -1328, 1838, -705, -2546, -795, -2574, 862, 729, -1582, -2835, -1761, -163, 56, -617, -4748, -2222, -2720, -1583, -416, -6045, -2931, -5569, -3592, -790, -6045, -2737, -1166, -6958, -1225, -5319, -2470, -295, -8865, -1251, -3964, -2666, -1258, -7912, -1126, -2514, -3563, -3571, -4532, -1563, -1660, -5202, -4847, -1441, -2992, -1781, -4774, -4611, -322, -4997, -3198, -2952, -5942, -603, -5394, -6214, -2440, -6411, -1917, -4901, -5584, -3543, -5793, -3729, -4390, -3415, -7264, -8582, -5234, -5014, -2235, -8942, -4395, -6310, -8549, -1569, -6054, -2170, -7603, -5002, -1463, -5195, -2267, -9149, -2964, -1978, -3792, -4644, -9022, -3714, -2735, -2034, -13365, -7146, -6480, -2779, -635, -5444, -6256, -2807, -2774, 63, -3879, -7247, -1273, -4226, -70, -3677, -11781, -1544, -8138, -1093, -4003, -6590, -2997, -3151, -3254, -4810, -3279, -4555, -983, -7247, -5014, -1831, -5227, -463, -7984, -4195, -1944, -6565, -1102, -6828, -4395, -3334, -12319, -2986, -7146, -5784, -3218, -7936, -6246, -4250, -7371, -2606, -6074, -4935, -1803, -10526, -3769, -6045, -3198, -607, -6256, -6565, -4455, -3161, -278, -4082, -6692, -3105, -4649, -535, -4199, -6045, -3027, -7842, -1292, -5279, -7264, -3944, -13049, -2367, -5202, -6457, -5299, -13738, -2007, -6445, -3586, -6828, -13365, -764, -10704, -2758, -8549, -6988, -510, -3187, -3717, -10704, -3529, -1626, -918, -6365, -9695, -1779, -4504, -310, -7819, -7050, -1367, -7264, -937, -7179, -7583, -2398, -5516, -2448, -7050, -12776, -5827, -4523, -3203, -6565, -5415, -8517, -4331, -3549, -6376, -3776, -5097, -5888, -4764, -6615, -4748, -4816, -28777, -2793, -6988, -10362, -5862, -6469, -875, -7796, -4006, -6035, -4331, -367, -10001, -1756, -4693, -3635, -1064, -8903, -1414, -3436, -3360, -3012, -6422, -2417, -2677, -3375, -6973, -6225, -4344, -2743, -3863, -14195, -7484, -5836, -3795, -4578, -7213, -5546, -6016, -5374, -4935, -4896, -3975, -5380, -5759, -4842, -3415, -4010, -5374, -5437, -4980, -2817, -5221, -6928, -5844, -5037, -3156, 12134, 7964, 12326, 10783, 8293, 11562, 8697, 11639, 10187, 7721, 9797, 9075, 9413, 8177, 5757, 6745, 8684, 5434, 3553, 1036, 2902, 8678, 4881, 1333, -516, 1823, 8693, 5646, 2537, 403, 3576, 7805, 5197, 2556, -1100, 5226, 5757, 2662, 4307, 2672, 6239, 1909, -1969, 4505, 4656, 6247, -1849, 2392, 2524, 5823, 5138, 2186, 1376, -1860, 6818, 4252, 3845, 103, 2758, 7621, 4605, 5084, 4192, 4503, 8004, 3809, 5968, 5470, 4831, 7712, 622, 6074, 5073, 4209, 6425, -6679, 4972, 2877, 2824, 3429, -5164, 2167, -4142, 1406, -8549, -254, 641, -189, 942, 154, 1927, 1996, 1319, 726, 1413, 2212, 1668, 1070, 265, 2423, 1716, 12, 453, -417, 3108, 2143, -2306, -3, -1206, 2777, 3224, -3244, -712, -1927, 1433, 3625, -1742, -2493, -1672, -996, 2959, 346, -6504, -480, -8304, 997, 1689, -1503, -141, -2200, -1954, 1909, 1933, -1517, 408, -2375, 799, 3496, -6666, 976, -2447, -1733, 3721, -3311, 504, -1611, -2677, 2714, -318, -471, 66, -2573, 362, 1279, -1383, 1364, -3261, -2514, 2050, -1263, 2640, -1199, -1031, 1912, -97, 3743, 202, 656, 674, 932, 4287, 22, 1240, -1732, 1284, 4099, -1622, 768, -1030, 436, 3021, -3128, -625, 1057, -2791, 1251, -2083, -3056, 2130, -644, 832, -490, -7230, 2697, 1892, 1129, 612, -2488, 2826, 2021, 417, 637, -804, 2143, -284, -901, -111, -1250, 718, -1130, -1436, -548, -2861, 1279, 1877, -849, -1431, -3532, 2499, 2692, -522, -2977, -6074, 2475, 2350, -1123, -951, -3923, 1304, 1465, -2312, -112, -1156, -249, 583, -3003, -787, -954, -804, 120, -3309, -1418, -2543, -593, 238, -3344, -2008, -5960, 15, 460, -2340, -5049, -6759, 779, 33, -949, -6469, -4242, 1171, -1478, -87, -2747, -2863, 889, -3827, -225, -1086, -2411, 233, -4278, -1848, 671, -3433, -26, -2569, -4119, 1954, -8549, -109, -1791, -2231, 2352, -4382, -702, -3220, -2050, 1745, -2109, -1562, -7050, -6343, -110, -2562, -2239, -2225, -3133, -2871, -2801, -4003, -1242, 602, -1289, 430, -6064, -2657, 1996, -53, 2403, -2204, -5879, 2294, -654, 3164, -1335, -5465, 1706, -2933, 2983, -3291, -4184, 44, -1375, 2118, -8138, -1631, -2612, 607, 1069, -3158, 0, -1480, 1163, 425, -3184, 521, 27, 762, 102, -6705, 352, 610, -302, -556, -12534, -36, 795, -1710, -2253, -10899, -454, 87, -2580, -6133, -5702, -1070, -2807, -3187, -15615, -3076, -1921, -5208, -5487, -11004, -2322, -2148, -2003, -4743, -9812, -2473, -1118, -1889, -4003, -4620, -1991, 36, -3135, -4230, -2651, -848, 485, -2877, -1197, -2191, -399, -140, -1445, 146, -2805, -40, -2277, -1081, 335, -3644, 906, -6885, -1855, 568, -3094, 1723, -2910, -586, -256, 7955, 9431, 7065, 269, 75, 7232, 8576, 6787, 1631, -256, 4806, 5686, 5683, 2868, -1796, 3336, 5812, 3812, 3894, -1495, 5162, 7834, 4017, 4552, 1094, 4830, 7956, 4750, 4861, 3850, 1106, 6837, 4338, 4962, 5514, 800, 5479, 3551, 4794, 5981, 3929, 4838, 3787, 3849, 5465, 3666, 3666, 4655, 627, 4800, 720, 1166, 5579, -280, 4901, 572, 944, 6224, 4326, 4821, 3216, 2376, 6230, 5673, 3729, 3832, 2642, 5575, 5501, 1086, 3499, 1583, 4508, 4214, -2672, 2922, -1994, 3126, 3119, 8, 2423, -5915, 1204, 3471, 1033, 1761, -1943, -24, 3162, 631, 1150, -714, 851, 1134, -949, 1902, 1243, 1468, 1570, -4369, 3274, 1994, 1620, 3885, -9479, 3924, 1147, 1842, 4298, -4270, 3576, 129, 2110, 3005, -2621, 2410, 1788, 2122, 1103, -1865, 1274, 2796, 2517, 2250, -1522, 116, 2496, 3813, 2815, -591, -3668, 1378, 4765, 2004, 1073, -4718, 1297, 4694, 198, 2431, -1400, 2068, 3266, -1733, 3082, -1815, 2156, -550, -1699, 2937, -4331, 1401, -6093, -469, 2000, -4669, -324, -1580, 643, 947, -1557, -3957, -2226, 1428, 1061, 608, -3518, -5509, 1763, 1542, 2110, -519, -4974, 1758, 1922, 3083, 211, -1113, 1653, 1831, 3528, -551, 1174, 1511, -43, 3505, -2153, 2361, 1082, -3671, 3210, -2075, 2579, 86, 1497, 2916, 341, 2010, 1027, 2721, 2776, 2116, 1060, 3151, 1887, 2684, 2497, 299, 3847, -784, 2382, 1115, -347, 2894, -1433, 1655, -4779, -1533, 159, -313, 523, -1456, -2114, 157, -871, -383, 966, -1124, 1575, -2049, -438, 1143, -1455, 1545, -898, -255, 324, -5465, 849, 421, -349, -858, -3003, 1005, 757, -693, -2019, 380, 1884, 276, -930, -2885, 1472, 2254, -768, -871, -3412, 1381, 2043, -2011, -793, -4635, 364, 1345, -2132, -786, -7752, -1583, -157, -411, -743, -5607, -5208, -3289, 990, -759, -3560, -8790, -5827, 1501, -1095, -2847, -4348, -2801, 1092, -2051, -2086, -4412, -1752, -335, -3856, -1374, -6577, -2093, -3007, -5654, -554, -1904, -3978, -5960, -4611, 637, 121, -8942, -5569, -3087, 1370, 16, -7542, -4541, -1814, 1094, -2973, -3982, -3354, -391, -429, -6016, -2182, -2138, 1014, -2211, -1538, -1358, -1084, 2016, -374, -1303, -1492, -436, 2426, 943, -672, -2139, -757, 2059, 875, 559, -1998, -2170, 494, -265, 449, -1837, -1204, -2453, -1385, -1280, -2470, 446, -954, -3457, -2635, -3062, 911, 1, -3814, -233, -2333, 724, -1087, 166, 1384, -1346, -17, -3606, 818, 2076, -1003, -1745, -3692, -859, 2164, -1148, -4644, 820, -1743, 1766, -1029, -9639, 3229, 533, 1085, -708, -874, 4011, 1923, 925, -1191, 2077, 3458, 2779, 1197, -3196, 3238, 1601, 2975, 871, 8368, 8649, 11217, 9089, 2759, 7908, 8822, 10713, 8645, 4004, 6361, 8682, 9264, 7484, 3829, 3050, 7720, 7245, 6263, 2746, 4369, 6465, 6179, 5962, 5013, 7078, 5942, 6877, 6620, 5809, 7743, 5666, 7310, 7571, 4972, 6510, 4500, 6983, 8385, 3025, 2319, 222, 6253, 8565, 1389, 4631, 1123, 5188, 7790, 1940, 6545, 3968, 3206, 6076, 1376, 6721, 4951, 2413, 3870, -2165, 6022, 5664, 4337, -24, 72, 4580, 5524, 4530, -49, 1007, 2039, 4130, 2161, 3787, 149, -2783, 2257, -2276, 4606, 1418, -10284, 1590, 2613, 4302, 3173, -8363, 838, 3291, 3659, 4100, -7708, -81, 2399, 2572, 4251, -4191, -1082, 909, -69, 4001, -3121, -2404, 161, -2764, 3990, -2610, -1734, 696, 1203, 4170, -2382, -1397, 1343, 2686, 4120, -2219, -3580, 1245, 2895, 3752, -1654, -9479, -172, 2030, 3066, -842, -2916, -4509, -654, 1982, -244, -1865, -5253, -6800, 166, -472, -228, -2414, 789, -2945, -2887, 1391, -1107, 2896, -760, -4669, 1701, 112, 3687, 2489, 765, 1401, 839, 3641, 4129, 2694, 2037, 1305, 2869, 4570, 3362, 2311, 1486, 1344, 3977, 3261, 1359, 1306, -1243, 2830, 2727, 1584, 920, -8220, 2106, 2319, 2777, -212, -2982, 993, 2216, 2533, -28, 17, -3172, 1340, 677, 3016, 933, -1860, -2178, -2514, 4559, 302, 906, -1548, -3811, 4762, -2580, 1320, 453, -1516, 3905, -2883, 544, -1645, -2470, 2311, 152, -1839, -1755, -2768, 859, 1208, -2805, 1956, 2011, 659, 1685, 626, 2727, 3104, 1089, 2186, 1663, 1896, 1687, 889, 2434, 1138, -647, -5097, -473, 2128, -377, -8192, 684, -2125, 1721, -1707, -3170, 1992, -1529, 2441, -2756, -1328, 978, -908, 3470, -2191, -883, -1999, -1055, 3681, -430, -1117, -3741, -1670, 2816, -52, -2023, -705, -2356, 1098, -1448, -3433, 1467, -2311, 187, -4980, -5067, 2617, -1736, -55, -3577, -6469, 2823, -1540, -1337, -2260, -5810, 2055, -1671, -2555, -1247, -3549, -59, -1492, -1813, 482, -2118, -5422, -679, -877, 1674, -2066, -6928, 259, -607, 2092, -3903, -6590, 744, -2232, 1816, -8615, -3498, 622, -5260, 741, -5951, -43, 421, 526, -1446, -8517, 1176, 1159, 2573, -5702, -4821, 908, 2032, 3070, -8903, -768, -686, 2148, 2411, -3515, 585, -3067, 1365, 545, -609, 695, -5202, 537, -3163, 1236, 374, -7113, 1267, -11115, 2140, 292, -1455, 1836, -3683, 2020, 391, 1074, 1342, -1850, 595, 377, 2525, 211, -986, -2414, 302, 3370, -620, -451, -1466, 393, 3637, -941, -732, -7, 729, 3411, -223, -2720, -287, 1064, 2898, 603, -6732, -1899, 1126, 2168, 1134, -4234, -3701, 909, 1051, 1792, -4837, -2735, 567, -326, 2142, -5208, -1141, -38, -755, 1773, -1419, -35, -2401, 1021, -1310, 2214, -734, -1046, 1163, 74, 2339, -108, 464, 995, 557, 1910, 256, 1384, 727, 460, 861, 786, 1638, 420, -148, -433, 848, 1214, -147, -2297, -672, 503, 272, -1359, -3692, -1173, 571, -866, -2984, -1435, -2510, 1166, -2139, -1773, -2351, 640, 1466, -3843, -179, -2956, 2624, 940, -2248, 163, 338, 3240, 331, 359, -603, 1445, 3055, 1130, 1453, -1188, 1111, 2416, 1872, 1213, -124, -178, 1485, 1970, -125, 468, -1385, 265, 1849, -1076, -142, -824, -1423, 1800, -827, -1193, 336, -4258, 1409, -1427, -650, 1351, -2988, -710, -1215, 416, 2394, 176, -5670, 1344, 1570, 3240, 1391, 1708, 2979, 2617, 3518, 1122, 3488, 3494, 2930, 3063, -448, 3412, 3022, 2164, 1990, -2592, 1725, 1634, 104, 907, -2585, -1732, -379, -2039, 152, -460, -2986, -2271, -920, -1273, 602, -3189, -2933, 222, -4464, 280, -6745, -1325, 733, -7603, -761, -6204, -55, 617, -7819, -1402, -2612, 224, -39, -6026, -2046, -805, -556, -965, -3798, -2642, 364, -2829, -2007, -3232, -2904, 971, -3247, -2889, -3337, -2813, 791, -1196, -3291, -3029, -1963, -700, -923, -3744, -2615, -2053, -4455, -1889, -2841, -3417, -4923, -636, -3083, -1414, -6153, -3876, 1858, -3523, -1351, -3177, -231, 2562, -3971, -2929, -1513, 890, 1812, -4997, -1550, -2245, 528, -386, -6225, 776, -7623, -1071, -1521, -7819, 1657, -4082, -3128, -616, -8903, 1601, -1009, -3269, -108, -4153, 939, 41, -1668, 287, -778, -379, 368, -191, 91, 964, -2500, 350, 587, -994, 1328, -3215, 340, 657, -3062, 306, -1489, 529, 10, -6299, -2411, -92, 619, -1182, -6928, -7371, 616, 356, -2316, -6565, -15615, 762, -194, -4331, -8220, -5043, 724, -1022, -9753, -3471, -1832, 663, -2186, -2314, -533, -711, 320, -2711, -301, 909, -782, -392, -2819, 108, 1408, -1240, -881, -3863, -496, 1299, -1441, -1028, -5145, -1819, 965, -2118, -1966, -4464, -4215, 864, -4266, -5139, -3843, -10799, 1222, -9812, -11945, -4180, -2918, 1641, -5979, -6365, -5615, -599, 1531, -3311, -7984, -5793, -119, 402, -2430, -8276, -3853, -1016, -2244, -2673, -5127, -2871, -2861, -5380, -2668, -4573, -3003, -3344, -4805, -1763, -6204, -3795, -2265, -4985, -1516, -9812, -4348, -1511, -4723, -2566, -3632, -5026, -1407, -3471, -5662, -1293, -6504, -2102, -2140, -6842, -448, -4774, -3944, -1350, -3906, -475, -2825, -7819, -1278, -2950, -890, -2205, -6093, -1735, -2419, -1524, -2390, -3866, -2319, -2043, -2599, -2626, -3546, -2411, -2305, -4172, -2416, -4688, -1973, -3526, -4826, -2057, -7542, -1689, -5002, -4274, -2111, -10210, -2322, -4486, -4311, -3189, -7752, -4748, -4097, -5531, -6504, -5670, -6143, -4929, -8485, -11356, -3801, -3299, -9238, 3235, -1902, 2421, -281, -4365, 2278, -5073, 1347, -2247, 385, 134, -2239, 163, -5871, 2801, -5576, -2430, -974, -1976, 3776, -934, -9812, -1749, 750, 3595, 1489, -2077, -1443, 1740, 2481, 1780, 87, -1497, 1524, 992, 272, 130, -2540, 224, -483, -4923, -157, -2887, -2162, -2630, -4108, 423, -2018, -5569, -3779, -1699, 562, -1319, -7113, -2305, -1973, -482, -1226, -4340, -2170, -1603, -2545, -2254, -1782, -4486, -334, -3671, -4089, 69, -8138, -297, -3876, -3735, 1142, -3133, -1600, -4378, -2064, 1357, -1610, -2348, -5103, -598, 705, -423, -2036, -6064, 479, -488, 1160, -3695, -2672, 1635, -1005, 2546, -3362, -512, 2897, -660, 3138, 23, -3, 3646, -692, 2680, 1304, -940, 3516, -2080, 1062, 1287, -2497, 2303, -9284, -1376, 345, -1213, -399, -787, -3074, -334, 340, -6235, 2101, -4532, 731, 1017, -3665, 3170, -6054, 1665, 884, -1263, 3003, -5670, 1733, -465, -434, 1425, -3479, 1125, -5853, 66, -3594, -2391, 197, -2545, 872, -2211, -2926, -792, 240, 1239, 624, -5195, -1469, 345, 758, 845, -4564, -1862, -1661, -366, -134, -1559, -2641, -6256, -1721, -965, 75, -2863, -1780, -2279, -163, 570, -2445, 247, -1578, 870, -191, -1463, 1078, -1081, 1164, -1765, 586, 1244, -565, 472, -182, 2058, 841, 456, -1163, 1455, 2495, 43, 1297, -2098, 1862, 1844, -686, 1570, -1537, 1555, -361, -1224, 1274, -1375, 1274, -10362, -1018, 535, -955, 1616, -1261, 475, -446, -188, 2302, 1276, 1669, -1429, -372, 2583, 2101, 2073, -2245, -2432, 2063, 1842, 1812, -2569, -9531, 558, 522, 1053, -1720, -9149, -2040, -2024, -170, -332, -6828, -3370, -3900, -1635, 590, -1777, -2311, -1914, -1857, 782, -68, -2460, -760, -1298, 254, -149, -4569, -642, -1302, -681, -1680, -8454, -1348, -2018, -824, -4723, -3782, -2827, -3261, 206, -10613, -2435, -5002, -3378, 828, -8086, -2610, -4968, -2524, 239, -4172, -2967, -2427, -2184, -1878, -3108, -2229, -861, -1519, -2374, -3521, -867, -620, -313, -913, -2350, 98, -2163, 597, -901, -191, 355, -5836, 905, -1969, 892, -116, -2500, 510, -3485, 959, -1134, -1562, -630, -4587, 113, -1826, -3038, -1367, -4199, -1613, -1599, -1941, -333, -3213, -4323, -1772, 531, 251, -2314, -9238, -3264, 1372, -247, -1668, -9238, -5678, 1039, -1707, -1516, -6640, -4219, -130, -4071, -1967, -6814, -2912, -1719, -8247, -3304, -7281, -2829, -3089, -8060, -5202, -5915, -3779, -3615, -6173, -4067, -3944, -4968, -3665, -5897, -2977, -2437, -3391, -4093, -5133, -2817, -1864, -1847, -4907, -3723, -2681, -2473, -1310, -5836, -2555, -2420, -4541, -1505, -6759, -2175, -2599, -5888, -2142, -7299, -2673, -2969, -4382, -2797, -6528, -3883, -2191, -4573, -1230, -335, 645, 429, 357, -3038, -152, -1412, 1329, -229, -4348, -47, -6083, 1594, -1982, -3309, 23, -4635, 1187, -3170, -1646, -1013, -1054, 323, -2394, -1340, -5879, 314, -334, -1773, -3301, -3720, 584, -752, -361, -3698, -1733, 174, -1032, 678, -538, -2670, -549, -864, 491, 78, -2460, -1508, -953, -411, -1808, -976, -2973, -2054, -21, -5844, -672, -4075, -4093, 532, -251, -1414, -1376, -2827, 120, 1505, -3189, 1322, -685, -1286, 2352, -4664, 2820, 588, -7162, 2829, -2247, 3202, 1410, -1640, 2225, -732, 2496, 1687, 1589, -426, -1668, 523, 713, 2413, 912, -3003, -1305, -3247, 1645, 2977, 1544, 1310, -897, -313, 2760, 3205, 2988, 1433, 430, 603, 3140, 3446, 1385, 2077, 454, 1813, 2967, -406, 2819, 1991, 766, 1707, -4138, 3058, 1834, 1570, -371, -9149, 2707, 181, 2282, -3537, -4693, 1413, -2916, 2590, -5810, -1620, -276, -6732, 2826, -6988, -743, -284, -6786, 2924, -9193, -1535, -798, -4013, 2843, -7865, -2470, -2460, -1686, 3096, -2430, -1810, -1476, 143, 3503, 435, -1444, -855, 1322, 3261, 1347, -1227, -1814, 1695, 1779, 552, -487, -3208, 1165, -2364, -2550, 436, -2545, -395, -3334, -6528, 641, -1313, -2999, -573, -3005, -353, -1292, -3947, -842, -2326, -2500, -3001, -2988, -2835, -2207, -2135, -5127, -2670, -4433, -2040, -279, -4683, -2328, -3615, -1618, 769, -6732, -1543, -3242, -848, 1473, -5429, -742, -2061, -292, 1818, -2673, -499, -46, -804, 1349, -1369, -1100, 1304, -3738, -24, -104, -2344, 1780, -2843, -290, 1044, -4759, 1564, 381, 749, 1582, -6256, 1045, 1368, 939, 1323, -1788, 626, 1164, 359, 375, -843, 32, 220, -337, -773, -1428, -1186, -939, -1168, -2023, -988, -1232, -1241, -2205, -3378, 86, -133, -473, -340, -2383, 686, -380, 89, 1460, -1666, 1007, -2470, -263, 1945, -2977, 793, -6093, -1781, 1250, -6973, -227, -5599, -4211, -789, -2994, -2270, -3792, -6528, -5031, -938, -6376, -3144, -7371, -3498, -517, -12534, -4211, -7034, -1516, -1733, -7445, -4654, -13365, -1254, -8112, -6469, -3769, -3266, -1563, -3103, -5879, -4369, -751, -1213, -395, -6183, -5718, -361, -640, 288, -7371, -6332, -1802, -691, 277, -10704, -5260, -7523, -1131, -162, -10362, -3227, -4997, -1278, -1484, -5662, -2720, -2657, -1381, -2382, -4164, -4688, -2956, -2107, -587, -4153, -9238, -4738, -4078, 349, -5139, -2992, -6310, -8247, -127, -6504, -1722, -7213, -5103, -2330, -6565, -2236, -12534, -3509, -4890, -5164, -3886, -7081, -3656, -2385, -4123, -6492, -4258, -4416, -1680, -4295, -13365, -3482, -4455, -2478, -5599, -7562, -3662, -3656, -4215, -3866, -6153, -4078, -2550, -6504, -1831, -7113, -4361, -1401, -10526, -1369, -9064, -4327, -696, -12776, 10974, 5133, 12179, 10614, -15615, 10339, 6509, 11570, 10083, -5710, 8267, 7039, 9596, 8403, -3137, 3870, 5751, 5533, 5286, -2242, 966, 3967, -1683, 389, -1745, 3039, 4025, 615, -2125, -725, 3074, 3004, -787, 404, -66, 2859, 647, -159, 1152, 251, 3039, 1753, -97, -867, 1275, 3871, 2657, 291, -122, 2316, 4697, 2636, 1038, 3007, 2920, 4654, 3017, 300, 4325, 3402, 3192, 3945, -3589, 4568, 3727, -441, 4302, -1647, 3895, 3687, 164, 3558, -93, 2359, 3268, 1703, 1790, -2194, 715, 2426, 1429, 682, -1157, 245, 689, 605, 508, 1833, 125, -4669, 152, -366, 2668, 92, -1704, -620, -1566, 2372, 146, 1236, -1799, -3266, 1346, 211, 1634, -1900, -5942, -366, 469, 661, -1627, -4021, -2935, 903, -746, -1696, -2648, -3751, 1215, -1950, -1262, -2507, -3151, 1423, -4901, -391, -1911, -4644, 1646, -2849, -174, -1012, -8423, 1633, -298, -1270, -1283, -7389, 1189, 127, -3923, -3889, -4728, 492, -991, -6256, -5726, -2366, 48, -3744, -9585, -2028, -1419, 43, -9064, -8485, -1286, -1956, 16, -12534, -5214, -2153, -4774, -291, -6800, -5599, -4464, -7984, -796, -3540, -8165, -7752, -2726, -1325, -1898, -5380, -5988, -1576, -1583, -1682, -2815, -3597, -2080, -1550, -3076, -1475, -1975, -3441, -1987, -4743, -1014, -1593, -4500, -3850, -2366, -1427, -3124, -5561, -9585, -850, -2361, -12123, -8165, -5554, -393, -2359, -3707, -28777, -3741, -652, -1657, -2057, -10284, -4142, -1452, -1378, -3018, -11629, -6800, -2621, -1553, -6354, -12123, -7562, -3580, -2061, -3975, -8138, -4816, -3641, -2711, -2571, -7264, -4378, -3311, -3114, -3018, -6445, -5374, -3189, -3012, -4601, -4550, -7960, -3349, -2900, -6590, -2473, -17034, -3729, -3422, -8086, -1169, -5862, -4258, -4679, -8304, -848, -2760, -5067, -5422, -7066, -1276, -1302, -5997, -5444, -5465, -2008, -968, -6173, -6376, -4134, -2722, -1477, -5576, -7774, -3142, -3490, -2425, -4611, -6354, -2621, -4759, -3401, -3695, -4748, -2914, -7081, -4038, -3577, -4331, -4486, -7097, -3618, -4769, -5176, -7335, -5768, -2735, -6759, -5607, -7542, -5906, -2531, -5176, -4395, -6365, -6842, -3375, -3425, -4168, -5176, -7603, -4985, -2557, -5353, -4447, -7912, -5702, -2040, -6007, -4191, -6469, -6870, -1432, -4842, -2811, -4688, -10799, -782, -3656, -1336, -4203, -7389, -400, -2703, -899, -5312, -6692, -471, -2238, -1490, -5638, -8220, -1081, -2448, -2841, -3632, -9064, -1976, -3158, -4847, -3301, -7050, -2688, -3677, -8903, -5401, -4311, -3615, -3452, -6246, -6692, -2340, -4504, -3056, -3455, -3665, -1210, -3301, -3276, -2726, -3362, -831, -2499, -4957, -3393, -5339, -1122, -3126, -10613, -5103, -6590, -1967, -5487, -9380, -6666, -4278, -3686, -9753, -8220, -7034, -3373, -8138, -10704, -11004, -6235, -2895, -8034, -5374, 1449, 3197, 8375, 3840, -7960, 766, 2347, 7777, 4367, -4940, -1927, -133, 5842, 4880, -1305, -1580, 693, 2403, 4831, 1131, 2049, 2339, 1975, 4742, 2473, 3660, 2578, 2608, 5005, 2976, 4273, 2325, 1635, 5258, 2788, 4387, 1910, 339, 5076, 1996, 4280, 63, 1772, 4314, 901, 3961, -3168, 3391, 3087, -510, 3944, 1918, 4603, 1415, -3362, 4884, 3749, 5577, -1033, 0, 5577, 4087, 5888, -1456, 2902, 5178, 3504, 5074, -1015, 4127, 3391, 2664, 2516, -2295, 4236, 613, 2383, 76, -3089, 3453, 332, 2188, 2452, -3065, 1995, 160, 1504, 2824, -3989, 165, -862, 661, 1778, -4319, -1510, -815, 798, 159, -3383, -2204, 245, 1772, -533, -3182, -1799, 1191, 2324, -12, -5408, -1462, 1702, 2092, 276, -9812, -1961, 1717, 1328, -549, -6321, -2754, 1152, 741, -1920, -2046, -3163, 25, 663, -727, 677, -3247, -632, 751, 513, 1750, -1624, 202, 608, 711, 1575, -453, 946, -73, 120, 269, -470, 832, -861, -948, -2514, -1427, -582, -556, -1909, -5183, -3452, -5221, -79, -2022, -2472, -8718, -3471, -247, -1626, -1334, -4918, -1045, -310, -1642, -1216, -1966, -1503, 105, -2305, -1482, -828, -4853, -154, -3242, -1581, -565, -7113, -1817, -3720, -1001, -713, -5020, -4810, -3606, -92, -903, -4223, -4625, -3444, 437, -1189, -2597, -3393, -3474, 438, -1976, -1954, -2776, -3592, 166, -3103, -2003, -3360, -3532, -40, -1821, -2192, -6445, -3184, -114, -146, -2861, -4361, -3352, -154, 150, -4352, -1705, -4874, 68, -1157, -5183, -974, -8827, 680, -5139, -4847, -1104, -7484, 1084, -6745, -5735, -1184, -4311, 786, -4790, -7542, -1326, -2522, -276, -7097, -5702, -2488, -1661, -1495, -6194, -4985, -4523, -1326, -2377, -3401, -6492, -3203, -922, -4282, -3286, -8333, -2480, -599, -5037, -4869, -5121, -4142, -968, -2825, -3961, -3695, -6719, -2038, -2608, -2208, -3889, -3701, -2312, -4112, -1963, -5333, -3388, -1825, -5960, -2990, -4464, -4348, -2090, -6640, -5067, -2737, -3632, -3326, -5164, -7130, -2590, -3025, -4869, -3225, -5897, -4238, -3603, -6299, -3054, -4336, -7687, -4748, -10442, -4425, -3624, -4885, -4769, -7752, -4769, -3391, -3457, -3632, -5509, -4513, -3853, -3773, -3074, -6083, -6163, -6225, -5599, -3151, -8165, -5260, -8942, -7644, -2745, -5380, -3471, -4013, -5480, -2030, -2992, -2743, -2835, -3820, -1931, -1673, -1823, -3580, -3549, -2599, -1216, -1275, -6973, -4733, -3964, -1741, -1987, -6528, -7281, -5422, -3054, -4659, -3083, -5853, -4138, -3222, -4649, -1944, -3999, -2292, -2743, -2148, -1918, -3523, -1709, -3362, -1462, -2440, -3837, -2587, -4790, -2038, -3140, -4348, -5569, -6194, -3999, -3274, -4800, -8865, -9936, -6354, -2197, -5008, -5183, -8903, -3866, -1736, -4885, -3671, -5183, -2751, -2791, 3552, 2546, 6803, 2428, -607, 2619, 2288, 6397, 3673, 1962, 1236, 1293, 5440, 4737, 2974, 2997, -807, 4409, 4499, 1728, 3993, -904, 2855, 2610, -2696, 3693, 1618, 148, -2758, -1072, 2198, 2870, -14, -1298, 672, -1000, 2921, 490, -235, 318, -5979, 1866, 38, -1825, -2166, -2345, -23, 446, -2661, -3222, -109, -1863, 1191, -1836, 1712, 1648, -2407, 1575, -1586, 3739, 2695, -1357, 1647, -262, 4435, 2996, -539, 1369, 1681, 4231, 2582, 322, 530, 2755, 3487, 1325, 1291, -1313, 2575, 2805, -1219, 1520, -3701, 933, 2599, -6679, 799, -839, -231, 2571, -11781, -520, 673, 1176, 2401, -6399, -1760, 423, 1187, 1965, -3137, -2926, -1317, -990, 1329, -3036, -4361, -3415, -15615, 606, -4282, -2655, -4123, -2158, 219, -583, -251, -4382, -323, 477, 922, 934, -3846, 267, 371, 410, 1118, -3665, 532, -796, -2006, 247, -3266, 866, -2875, -3342, -2342, -1843, 1332, -3798, -2236, -7865, -941, 1451, -1651, -2768, -3757, -1011, 825, 1, -4250, -2979, -1875, -568, 486, -4278, -3927, -2897, -2071, 45, -3409, -5836, -3360, -2050, -1226, -3067, -7819, -3554, -848, -4138, -2843, -7230, -4180, -67, -7264, -2155, -5592, -4885, -265, -2637, -1579, -5103, -3501, -1388, -1746, -2314, -5480, -1786, -1016, -3496, -6026, -5853, -1022, 890, -7687, -3031, -4523, -960, 1892, -1701, -917, -2473, -996, 1951, 293, -1295, -1526, -839, 1363, 995, -3788, -1756, -767, 320, 890, -4698, -3094, -832, -1592, -26, -3615, -5292, -838, -4963, -1790, -4130, -3957, -792, -3010, -3010, -4550, -1954, -1098, -1471, -2610, -4082, -1511, -2256, -771, -2268, -3947, -2411, -5109, 87, -1683, -4270, -3957, -8393, 608, -1141, -4890, -4049, -2707, 521, -784, -5710, -3754, -679, -22, -643, -7179, -4112, -211, -1247, -1275, -10613, -4207, -1117, -4455, -3201, -7464, -2971, -3900, -6045, -3479, -3840, -1497, -6163, -2075, -1089, -2219, -770, -3083, -1019, 77, -2185, -1022, -1958, -1396, 53, -4093, -2083, -1809, -2891, -1158, -8423, -3108, -2282, -4509, -3430, -4433, -3665, -3463, -4142, -3695, -3512, -4303, -6093, -3259, -2548, -5208, -4378, -9812, -2316, -2468, -14195, -4003, -5818, -1296, -3237, -4021, -4180, -5279, -531, -4097, -1752, -4901, -8333, -295, -3866, -1062, -5970, -9695, -686, -3284, -1441, -7542, -5776, -1918, -3031, -2626, -10442, -5031, -4874, -3140, -3804, -7708, -4017, -5561, -3961, -4774, -4779, -3117, -2331, -5853, -7603, -3964, -3577, -1508, -8393, -11945, -5170, -6565, -2225, -9380, -6343, -6602, -7066, -4161, -7819, -4447, -4266, -4303, -6773, -7247, -3220, -3618, -4831, -12123, -6480, -2613, -3441, -5784, -7623, -4723, -2512, -2097, -3242, -3937, -4482, -2564, -1195, -2500, -3137, -5374, -2617, -1416, -3597, -4442, -4203, -10362, -6153, -2210, -5827, -2538, -8304, -8549, -1947, -7034, -1447, -7389, -10704, -2833, -9812, -1377, -6310, -6225, -5702, -8086, -1451, -5247, -4853, -11629, -4754, -1137, -4654, -4559, -9064, -2745, -972, -4644, -5008, -5592, -2411, -985, -5387, -6759, -2653, -4199, -622, -7484, -12534, -1134, -28777, -234, -10210, -8192, -774, -5031, -609, -7146, -6958, -1491, -3698, -2265, -5516, -9106, -3367, -4723, -6653, -4046, -12776, -6480, -8454, -5694, -3119, -7960, -10284, -6958, -2222, -3635, -7019, -11488, -4006, -849, -5067, -8165, -10210, -2893, -477, -4698, -10704, -9479, -3051, -798, -5451, -28777, -9936, -4980, -1666, -17034, -6759, -10284, -11629, -3163, -5067, -3126, -4918, -5615, -4991, -2438, -2012, -2438, -4303, -4211, -1262, -2540, -1617, -5273, -2624, -861, -4532, -1962, -7317, -2075, -1135, -7687, -3441, -7484, -2468, -1991, -7097, -7644, -5662, -3618, -3324, -6064, -7583, -3220, -5145, -4858, -5451, -3795, -1769, -6745, -5810, -3701, -2984, -1371, -10362, -6602, -2211, -3644, -1822, -7353, -8333, -1469, -5509, -3040, -4523, -7583, -1289, -7708, -4985, -3804, -5735, -1540, -9936, -7562, -4064, -5195, -2403, -8192, -10362, -4042, -5933, -4550, -4592, -10899, -3367, -8393, -9193, -3259, -8165, -3020, -8790, -5502, -3438, -5502, -3766, -5960, -3674, -4795, -3496, -6786, -5183, -3007, -6540, -2176, -10613, -6422, -2895, -7426, -1522, -5279, -6988, -3689, -7389, -1313, -4348, -3391, -6074, -7774, -1412, -4442, -1439, -7034, -9429, -1988, -3968, -693, -4880, -9064, -3375, -3668, -825, -4093, -8942, -5599, -4733, -1587, -4323, -11356, -7281, -5694, -2637, -5592, -5145, -7774, -3218, -3923, -7687, -2138, -9284, -1734, -6445, -8683, -714, -15615, -1277, -10362, -8060, -463, -10210, -1379, -7130, -7213, -1375, -7687, -1668, -7888, -8304, -3415, -6640, -1912, -12534, -11356, -6016, -4997, -2139, -6800, -7113, -6928, -3096, -2752, -5234, -5401, -4555, -2047, -3903, -4504, -4616, -3409, -2040, -4541, -4168, -4191, -3543, -2809, -4270, -5569, -4460, -3306, -3992, -4211, -9284, -6163, -2253, -4826, -5394, -4640, -13049, -1625, -3801, -8086, -2997, -8942, -1742, -2637, -4067, -2887, -7081, -2728, -2027, -2256, -3463, -6705, -4929, -1902, -2330, -4238, -7004, -9873, -2606, -3978, -4951, -10138, -9064, -4606, -7912, -5055, -11945, -5979, -8192, -12776, -4606, -7774, -5026, -14784, -9022, -4583, -7335, -4853, -10799, -10138, -5576, -7842, -4754, -9331, -9873, -6653, -7842, -4703, -17034, -7179, -5862, -6399, -4929, -8138, -5988, -5422, -5306, -5170, -5472, -6026, -6214, -4997, -5360, -5422, -8615, -8615, -4583, -5726, -7687, -8009, -12534, -3744, -5933, -11115, -4157, -9331, -3092, -5546, -9380, -2975, -7912, -2829, -4974, -10284, -3168, -8192, -2883, -5097, -7752, -4357, -8485, -3020, -6745, -6035, -6445, -6958, -3182, -7687, -6163, -8982, -6103, -3644, -5531, -7464, -9331, -5678, -2807, -4495, -3326, -5183, -10362, -2509, -5554, -5646, -3329, -4527, -2958, -7888, -10069, -1869, -1568, -4486, -9873, -10799, -2146, -470, -8615, -11781, -8754, -3540, -470, -6054, -10138, -5569, -3001, -1149, -2688, -6422, -3101, -2306, -2075, -1407, -3671, -1899, -3344, -3337, -1431, -2316, -2138, -4473, -6133, -2612, -2375, -4035, -3259, -6376, -4486, -3996, -6267, -3085, -3264, -5115, -8138, -5189, -4545, -2274, -5049, -13365, -4262, -8276, -2774, -6434, -8276, -3449, -7034, -4569, -5776, -6288, -2651, -4315, -4630, -3281, -4134, -2014, -3490, -2548, -2696, -2383, -1828, -3452, -1414, -3920, -1431, -2363, -2319, -1207, -7066, -1259, -3863, -895, -1834, -8683, -1945, -6267, -589, -3151, -7687, -3889, -5524, -1604, -4980, -7644, -7299, -3401, -2783, -7583, -8112, -5494, -2427, -1750, -14784, -6602, -3896, -2526, -1144, -9531, -4795, -3417, -3707, -1616, -5888, -4495, -3798, -5546, -2303, -4149, -5718, -5784, -5615, -2473, -3662, -7562, -8865, -4805, -3242, -4408, -6256, -5353, -4532, -5810, -6469, -5189, -4060, -4433, -13738, -10899, -5286, -3893, -4180, -15615, -9812, -6035, -3609, -4024, -8549, -5292, -6173, -2653, -4541, -4644, -3644, -5073, -1612, -5801, -3404, -3471, -3978, -1255, -6123, -3798, -4149, -3833, -2344, -4100, -5339, -4980, -5121, -7445, -2521, -6376, -5531, -7264, -4723, -2119, -5539, -6183, -6376, -2442, -2383, -4145, -7408, -5085, -3147, -1805, -2809, -5073, -3957, -7445, -888, -1777, -2801, -3827, -7464, -804, -1374, -1879, -5933, -4738, -1888, -1745, -1844, -9380, -4774, -4853, -2701, -2369, -5103, -5678, -11004, -3465, -3476, -4234, -6640, -4946, -3512, -5862, -4620, -10362, -3062, -3476, -9284, -4997, -8615, -2197, -3540, -4416, -4573, -4963, -2325, -3686, -1999, -3474, -4518, -3896, -4149, -665, -2825, -6343, -6732, -5266, -92, -3147, -14195, -4831, -7774, -307, -4532, -8942, -3543, -11781, -1481, -6528, -6064, -3741, -8304, -4311, -8086, -4295, -5026, -4968, -8363, -10442, -3383, -6988, -3089, -4153, -10899, -3507, -9531, -2644, -2912, -8942, -5020, -9149, -3689, -2510, -9331, -9193, -5735, -6528, -1839, -10526, -6332, -4918, -6958, -1345, -7004, -4282, -6083, -5097, -1682, -4918, -4425, -8582, -4408, -3094, -4010, -6800, -7912, -3433, -5915, -3615, -28777, -8247, -2378, -10526, -3163, -6988, -13738, -2036, -7912, -2605, -5458, -5776, -2507, -5227, -2369, -5374, -3249, -3433, -3388, -2819, -6267, -2448, -4067, -2142, -4127, -8754, -2724, -4180, -1590, -5266, -13049, -3937, -4017, -1875, -5339, -6928, -6516, -3723, -3239, -6745, -4874, -13049, -3487, -6553, -13738, -4149, -10613, -3824, -12534, -7066, -4180, -8790, -5408, -5718, -5853, -4532, -8165, -9873, -3612, -7819, -4940, -8086, -9753, -2531, -14195, -5353, -9479, -8827, -2228, -6288, -5915, -13738, -13738, -2887, -4669, -6856, -11629, -9193, -4659, -4569, -8683, -9812, -7445, -2651, -2851, -5401, -4168, -3496, -2574, -6246, -5429, -1510, -4963, -2764, -11781, -5710, -402, -8165, -3218, -5827, -5292, -525, -4708, -2366, -3776, -3498, -1852, -3714, -1358, -2694, -2216, -4578, -5067, -1531, -2730, -1665, -4728, -12123, -3014, -4082, -1831, -3025, -6310, -5827, -5494, -2228, -2522, -4555, -9193, -4997, -1787, -2619, -5422, -7644, -5333, -1144, -2908, -7730, -5662, -6565, -1139, -3618, -6026, -3940, -6365, -1816, -6480, -4532, -2347, -5768, -3299, -7299, -3493, -1326, -5480, -5951, -2170, -2601, -1012, -5208, -5924, -677, -2071, -1429, -5726, -4545, -934, -1721, -2573, -9022, -4669, -3047, -1401, -4395, -10284, -4331, -9284, -1276, -5818, -6321, -3365, -5170, -1650, -5208, -6842, -3549, -3194, -2776, -4352, -14784, -4078, -2419, -3840, -4527, -7708, -2091, -1914, -2960, -6870, -6800, -401, -1620, -1995, -11781, -9639, 142, -1557, -1474, -4527, -5827, -284, -1511, -1121, -2282, -3726, -1313, -1456, -1343, -1242, -3735, -1643, -1672, -2497, -1083, -5031, -950, -2163, -2130, -2026, -4703, -581, -2521, -537, -4713, -3244, -871, -2573, -167, -8683, -2751, -2004, -2424, -558, -6016, -3027, -4654, -2225, -245, -6256, -3261, -7665, -2297, 176, -9284, -3184, -4161, -2778, -287, -5437, -3723, -2962, -3656, -1282, -2713, -6123, -3054, -5312, -1651, -1511, -8304, -4172, -8165, -1834, -1285, -3677, -7752, -8827, -2931, -1833, -1797, -8423, -7484, -4748, -3051, -1197, -3785, -6759, -3360, -4408, -1485, -2270, -6422, -1912, -4509, -1774, -1575, -6173, -2083, -4344, -549, -1022, -4180, -3971, -5091, 589, -576, -2121, -7408, -6074, 661, -530, -1054, -7562, -5576, -424, -1143, -1001, -9479, -5584, -2398, -2606, -1882, -11488, -8086, -3455, -4951, -3135, -6666, -12776, -2883, -6133, -3863, -5638, -8304, -1753, -4455, -4518, -5091, -11004, -903, -3900, -4219, -4625, -10069, -860, -5494, -2472, -4669, -7562, -1756, -12534, -1041, -4145, -11945, -3763, -4541, -302, -3560, -6692, -6773, -2211, -329, -4583, -3577, -8517, -1398, -1249, -8549, -2731, -10362, -1701, -3254, -4674, -2941, -9753, -3074, -5494, -2747, -3436, -8138, -4679, -4365, -2937, -3526, -7281, -5862, -3992, -5247, -3201, -3893, -6653, -6183, -8517, -2817, -2072, -4215, -11781, -4683, -2528, -1878, -2902, -4311, -3447, -2253, -2690, -2971, -2300, -3665, -2051, -2855, -4021, -1583, -5026, -2118, -2545, -5576, -1572, -7371, -2589, -2406, -6278, -1963, -8363, -3465, -2069, -6246, -2642, -5374, -4226, -2273, -7542, -3876, -2853, -4842, -3306, -13365, -6153, -1499, -6973, -3985, -7523, -10613, -1173, -14195, -4698, -5879, -9531, -1611, -6103, -8485, -6577, -6113, -2189, -4611, -7097, -9193, -4601, -2317, -4821, -3999, -8034, -4429, -2361, -6256, -3476, -5970, -5387, -2823, -9585, -4460, -5793, -7196, -4157, -10362, -6800, -7353, -8615, -7687, -5592, -8683, -11629, -7865, -7665, 11108, 15036, 9902, 5969, 8435, 10914, 14606, 9535, 5610, 7636, 10259, 13280, 8492, 4280, 4800, 9422, 10943, 6856, 1240, -2483, 9204, 7308, 4388, -3235, 1828, 8919, 3366, 1632, -1922, 1982, 7442, 5799, 2713, -651, 980, 5082, 7154, 2829, 935, 942, 6232, 7188, 1098, 1365, 1948, 7247, 6255, 1483, 1173, 2999, 6938, 5352, 3522, 1440, 3995, 5610, 5482, 4188, 2033, 4887, 3614, 5927, 3668, 2194, 5521, 584, 6675, 1852, 1440, 5831, -8423, 7046, -2606, -424, 5716, -1380, 6420, -4464, -2599, 5131, -1733, 4583, -901, -2407, 4112, -1003, 1460, -264, -729, 2474, 691, 817, -635, -73, -609, 1211, 2572, -1883, -1241, -9936, 1423, 3290, -1665, -5759, -5026, 1054, 3031, 860, -7389, -6113, -782, 1510, 2398, -6299, -6828, -5353, -1940, 2896, -10442, -4161, -1883, 801, 2600, -5380, -4071, -463, 3135, 1766, -4195, -6516, -1500, 3716, 680, -4149, -13365, -3989, 2859, -453, -3299, -7819, -3741, 332, -1673, -2477, -8034, -13365, -2952, -3846, -2815, -5897, -589, -1263, -8138, -5776, -3362, 2448, 594, -3504, -7146, -2363, 3450, 1412, -1259, -2282, -1884, 3247, 756, -2, -934, -848, 2118, -2114, 877, -981, -23, 214, -5988, 1408, -1870, -234, -2158, -1113, 1581, -3126, -1725, -4013, 441, 1466, -3629, -3014, -5208, 718, 1164, -2359, -1782, -7081, 44, 663, -1002, -1315, -7912, -1241, -240, -489, -2153, -4885, -2417, -1843, -955, -4250, -2749, -3383, -4390, -2438, -6653, -1816, -4049, -7523, -4831, -5678, -2068, -3551, -7162, -7335, -4180, -3393, -3331, -4664, -7842, -3417, -5472, -4042, -3049, -4907, -3252, -6143, -4980, -2152, -3254, -3449, -4104, -6354, -1642, -2969, -3523, -2670, -11115, -1391, -3680, -3133, -2073, -7888, -1386, -4935, -2653, -2008, -4331, -1605, -6411, -2569, -2317, -3225, -1934, -7371, -3098, -3040, -3999, -2350, -6194, -4112, -4215, -7708, -2956, -5176, -5279, -6310, -8754, -4093, -5253, -6928, -11629, -5646, -6246, -6388, -10284, -6321, -4890, -10526, -7464, -12776, -4703, -4616, -8942, -6973, -13365, -4784, -4601, -6123, -6666, -10799, -3365, -4901, -4890, -7066, -6842, -1870, -5615, -4578, -8304, -5694, -1904, -6399, -5227, -11356, -6035, -3769, -5997, -7281, -9936, -5654, -9639, -5299, -8942, -7281, -4278, -8454, -6133, -8165, -7371, -4130, -7665, -7912, -9479, -10069, -5844, -10210, -6399, -9479, -8790, -12123, -4429, -6204, -7445, -6732, -9639, -1990, -7603, -7146, -6469, -8517, -1330, -7665, -7936, -6719, -9936, -2139, -5367, -8903, -6615, -9479, -4683, -4164, -9753, -6602, -7888, -9284, -4195, -11781, -7542, -6365, -5915, -4532, -17034, -8517, -5170, -3999, -4331, -8517, -6434, -5091, -4108, -4184, -6299, -4573, -6422, -5623, -5260, -5662, -3557, -9284, -6278, -9873, -6064, -3254, -11945, -5979, -8982, -7146, -3795, -11356, 7346, 1030, 4464, -12776, 6407, 6665, -1088, 3741, 2106, 6164, 4364, 1993, 1345, 3857, 5496, 1284, 4528, -2681, 3721, 4783, 3733, 4839, -1622, 2856, 4553, 5041, 3469, -864, 2763, 4348, 5302, 546, -810, 3205, 3649, 5070, 1732, -354, 3293, 2757, 4538, 4194, 1158, 3094, 2563, 3228, 5489, 3174, 2986, 3516, 2562, 5913, 4779, 3166, 5004, 5725, 5512, 5750, 3532, 6105, 7544, 4199, 6060, 3726, 6505, 7944, 1810, 5627, 3153, 6212, 7105, -1287, 4297, 784, 5368, 4947, -2125, 1953, -4997, 4230, 1269, -2118, -881, 1771, 3053, -1202, -3259, -2867, 3564, 1792, -908, -2815, -4997, 3953, -231, -569, -514, -6973, 3645, -4728, 873, 382, -5429, 3074, -1582, 1973, 239, -1874, 2533, 100, 2028, 55, 79, 1891, -702, 1148, 898, 817, 513, -4230, -68, 2067, 650, -1868, -3409, -704, 2675, -138, -1249, -2279, -801, 2473, -1144, 212, -4278, -1384, 1477, -1967, 688, -8865, -3850, 209, -2587, 414, -5319, -3801, 34, -3170, -1018, -6814, -1080, 633, -3594, -5240, -5630, -1246, 1007, -3227, -2851, -2353, -5906, 1011, -1982, -62, -1427, -2010, 733, -754, 838, -1663, 798, 344, -266, 609, -2386, 1455, -24, -885, -784, -3168, 1090, -282, -3023, -3883, -3051, 228, -322, -7603, -4810, -2347, -897, -449, -15615, -2098, -2375, -2336, -1301, -8517, -621, -3301, -3659, -3203, -4997, 351, -3430, -3551, -4853, -3920, 980, -2036, -2698, -3232, -3870, 1142, -1050, -2136, -1216, -3168, 779, -988, -1918, -419, -2175, -38, -1907, -1711, -1141, -1970, -1097, -3574, -1369, -3999, -2659, -2160, -4311, -1197, -6958, -3920, -3331, -3744, -1381, -4703, -5145, -4968, -3717, -2034, -5662, -6299, -6054, -4774, -3597, -7281, -8192, -4500, -7066, -7445, -4901, -10526, -3324, -8683, -8009, -4601, -8165, -3189, -8086, -5319, -6035, -6899, -3515, -7665, -4816, -4587, -7730, -3314, -7708, -5299, -2776, -13738, -2440, -9284, -6653, -2396, -8363, -1484, -15615, -5862, -2859, -6214, -724, -6842, -3989, -3378, -6565, -286, -4912, -3808, -3923, -8942, -328, -5818, -6173, -5346, -9106, -998, -8865, -10001, -8304, -7665, -2295, -3635, -4659, -7687, -8138, -3501, -1721, -3485, -5367, -9149, -3900, -1484, -3373, -4790, -8582, -4625, -2366, -3062, -6235, -8485, -6800, -3748, -2465, -12776, -8247, -11232, -4545, -2345, -6225, -6332, -8718, -4713, -3249, -4412, -4555, -6679, -4495, -5776, -4616, -3683, -5319, -4307, -10704, -5979, -3554, -4184, -5031, -8393, -6103, -3951, -3490, -7865, -6786, -5408, -4625, -3551, -13738, -6083, -6354, -5266, -4486, -6958, -6267, -8582, -5988, -5531, -5387, -6973, -6016, -7523, -4616, -4713, -7066, -4940, -10069, -3532, -4578, -7097, -5784, -9380, -3301, -5662, -8138, -8363, -9479, -3933, -10704, -8754, -8790, -10526, -5279, -7960, 1875, 1724, 3700, 3654, 5666, -1330, 1474, 4377, 5065, 5505, 1877, 1044, 5653, 6627, 5593, 4579, 1016, 6246, 7116, 5737, 4478, 542, 5706, 6436, 4948, 2431, -1265, 3984, 4567, 2879, 1205, -512, 1353, 1792, 371, 2124, 888, -1480, -779, 830, 1858, 794, -2540, -2176, 3201, 2063, 23, 1239, -2311, 4719, 3801, -450, 3452, 1213, 5149, 5054, 1528, 4350, 3267, 5136, 5319, 3439, 3872, 3312, 5286, 4516, 3922, 1105, 1387, 5024, 2733, 2864, -738, -414, 3647, 1405, -5, 2700, 306, 816, 1501, -937, 3033, -975, -1782, 1262, 335, 1386, -4223, -699, 548, 18, -3023, -9284, -965, -222, -907, -6814, -1691, -4412, -163, -1271, -2443, 1211, -400, 546, -1384, -898, 2188, 1882, 979, -1953, 214, 2303, 2226, 905, -2548, 940, 2185, 1392, 268, -2336, 1093, 1793, 107, -954, -2075, 442, 810, -690, -2947, -2019, -1257, -802, -1338, -6016, -2049, -2764, -2194, -1307, -5654, -2447, -1529, -1536, -550, -3827, -3535, -967, -178, -353, -2626, -5133, -1504, 415, -710, -1543, -8333, -2259, 45, -1111, -1052, -5879, -1926, -1219, -310, -1749, -1318, -795, -3119, 721, -4184, 411, -32, -2720, 632, -3054, 525, -70, -1071, -512, -956, -748, -454, -1151, -1681, -1015, -3396, 0, -3930, -3299, -3788, -9284, 946, -4469, -9479, -4907, -6045, 1387, -1624, -5164, -1598, -2766, 1209, -843, -3723, -1680, -2244, 870, -495, -4282, -5103, -2902, 655, -458, -6103, -5346, -2322, 90, -1083, -12319, -2809, -1287, -1212, -1908, -7484, -3692, -1202, -2933, -2319, -4723, -9193, -2071, -3811, -3428, -4060, -7196, -3748, -3509, -7299, -5451, -4912, -5970, -3119, -7247, -9873, -5299, -7623, -3393, -4425, -5702, -7774, -7371, -4748, -4674, -4365, -17034, -6343, -7708, -7130, -4853, -11356, -6457, -9479, -7730, -4616, -10613, -8615, -6411, -4104, -3067, -9380, -7752, -4373, -1994, -2516, -9193, -4946, -2906, -1286, -3194, -12319, -4086, -2028, -1984, -4821, -12534, -4703, -2011, -4119, -6943, -9695, -6800, -3098, -5286, -8649, -9479, -8276, -4946, -4230, -7353, -13365, -5286, -5139, -3944, -6732, -9106, -2881, -4842, -4187, -7888, -4532, -1735, -4957, -4842, -7542, -2574, -1898, -4659, -5988, -6225, -1827, -3471, -4764, -6928, -7281, -1880, -5942, -5524, -6565, -28777, -2460, -6163, -5924, -5879, -6133, -3537, -5942, -5103, -5509, -4097, -5531, -6411, -4536, -5097, -4119, -9531, -7113, -5286, -4810, -5686, -7603, -7984, -8220, -5170, -8615, -5607, -9812, -9812, -6411, -10001, -5487, -12776, -8615, -7936, -9064, -6653, -11781, -10799, -8060, -10704, -7623, -11356, -9238, -6814, -15615, -6035, -8615, -6411, -5694, -10001, -4935, -6528, -5516, -4946, -9022, -5103, -5735, -6045, -4242, -8393, -6504, -5546, -9106, -3569, -8247, -9064, -5164, -10899, -3299, -9936, -5979, -5292, -8582, -5480, -9429, -7230, -3843, -10442, -8454, -8247, -9429, -3194, -15615, -9193, -8060, -5979, -3540, -13049, -9022, -8192, -4357, -5139, -9064, -8009, -7665, -4669, -5793, -8165, -6332, -6732, -7523, -4940, -8165, -6016, -6278, -12319, -4038, -7179, -6943, -7281, -8333, -3130, -6899, -8393, -10442, -7984, -2920, -9064, -10138, -7299, -9106, -3218, -9149, -15615, -5247, -8827, -3846, -5702, -13049, -4901, -5670, -4659, -4578, -11488, -5227, -4344, -5152, -4774, -12319, -5145, -4340, -5260, -5630, -8192, -4630, -4649, -5871, -5451, -6035, -4764, -4587, -6842, -4853, -5429, -6914, -5079, -5702, -5152, -6026, -11781, -6299, -3438, -5247, -7484, -4616, -6679, -1875, -4369, -8112, -2758, -5273, -1447, -3689, -6914, -2505, -3916, -1950, -3512, -5979, -3441, -3319, -2772, -3989, -6163, -5554, -3444, -3130, -5380, -7353, -8363, -4060, -3020, -6577, -7389, -7842, -4826, -2945, -5951, -6246, -7034, -6332, -3023, -6422, -5871, -6870, -9479, -3271, -10362, -6553, -6492, -7774, -3717, -7066, -8517, -5933, -6143, -4112, -4654, -11781, -5662, -5924, -4469, -4541, -9936, -5710, -6705, -5451, -6113, -7603, -5915, -8220, -7774, -9873, -5951, -5827, -7819, -11232, -28777, -4606, -5576, -6204, -13365, -13738, -3760, -5401, -5465, -9380, -12534, -3512, -5333, -6007, -7408, -13365, -3900, -5516, -8034, -7264, -28777, -4863, -6123, -8165, -7503, -28777, -6434, -6759, -5924, -7247, -11945, -8549, -6666, -4985, -7247, -8582, -10526, -6007, -5103, -7623, -6640, -10899, -5240, -5960, -7936, -5662, -11004, -4447, -7464, -7583, -5367, -13049, -3903, -10526, -6928, -5623, -13049, -3923, -11232, -6565, -6480, -7865, -4592, -6267, -6914, -8138, -5710, -5615, -4295, -7865, -11356, -5085, -6540, -3732, -8754, -17034, -5844, -7623, -4207, -10442, -9479, -8517, -8982, -5546, -28777, -6988, -13365, -9064, -7687, -8790, -6163, -9064, -7464, -10442, -6786, -6602, -8165, -6083, -13738, -7230, -8304, -9331, -5670, -28777, -10362, -10210, -13738, -6214, -14784, -15615, -9064, -12534, -7213, -10069, -28777, -8754, -8276, -7888, -7247, -14195, -10362, -6590, -8718, -5836, -13738, -11004, -5960, -10442, -5444, -12319, -9331, -5759, -13738, -5710, -8086, -8363, -5380, -15615, -6278, -6653, -7644, -5020, -10442, -6870, -6321, -7247, -5176, -9064, -7050, -6800, -7623, -5979, -9585, -6973, -8112, -8790, -7426, -12776, -6759, -9695, -8903, -9429, -14195, -6732, -10613, -7542, -10799, -9193, -7426, -10899, -7335, -10069, -7299, -9936, -11115, -9064, -9812, -6399, -28777, -12776, -13365, -10799, -6365, -11945, -28777, -11232, -12776, -6988, -14784, -11232, -13049, -9753, -7644, -11781, -9873, -11115, -7523, -7562, -8865, -12319, -8615, -6590, -7004, -9193, -15615, -9936, -6615, -6814, -10362, -10362, -10210, -7665, -7562, -8718, -8903, -6516, -10001, -8865, -7752, -7865, -5387, -13365, -8454, -8393, -6653, -5599, -11629, -7842, -10526, -5970, -6666, -8827, -8138, -7317, -7179, -9936, -6870, -4800, -6388, -6828, -8982, -7708, -4207, -6153, -7912, -6988, -7644, -5176, -5810, -8683, -5718, -7842, -7623, -5208, -6083, -5793, -9429, -7819, -4896, -4550, -7603, -14784, -7019, -5008, -4361, -10001, -14195, -8454, -5451, -5158, -7623, -11004, -7281, -5979, -5458, -6899, -7196, -4935, -6365, -4592, -7730, -4784, -4532, -6973, -4319, -8423, -3801, -6007, -8423, -4951, -7888, -3886, -9639, -9064, -6299, -8304, -4896, -8485, -7960, -8192, -10704, -6719, -8086, -8754, -11115, -10069, -8582, -11629, -8790, -28777, -7819, -9064, -7097, -5759, -10362, -7644, -7936, -4112, -4442, -6445, -7389, -5576, -2668, -4266, -4100, -4495, -4042, -1848, -4698, -2920, -2499, -3773, -1382, -5415, -2851, -1803, -4907, -1347, -6388, -4035, -2419, -8220, -2045, -7912, -6310, -4555, -12776, -4142, -9639, -5906, -6399, -8718, -10704, -7984, -4654, -4606, -8192, -7179, -5933, -4500, -3978, -8754, -5279, -4980, -4748, -4365, -9479, -5554, -5115, -4386, -5145, -10442, -6759, -6504, -3920, -5546, -13365, -8363, -9429, -4438, -5247, -12319, -11004, -13738, -6870, -4733, -7687, -10899, -14784, -12123, -4569, -5844, -7542, -11004, -5638, -5055, -5472, -6814, -7464, -3583, -6045, -6376, -8649, -5531, -2871, -6745, -8754, -28777, -4790, -3025, -6376, -14195, -7774, -5189, -3840, -5494, -28777, -5726, -6565, -5152, -5139, -28777, -5286, -8454, -7034, -5743, -14195, -6123, -10001, -7603, -6988, -11781, -9106, -9695, -6016, -6492, -17034, -10362, -8615, -5367, -5319, -9380, -5942, -8276, -5924, -5247, -6045, -4097, -8615, -7665, -6299, -5240, -3417, -9479, -10799, -7842, -6299, -3493, -11781, -13738, -8423, -9753, -4028, -28777, -11488, -8903, -13738, -4912, -13365, -10704, -9812, -8942, -5988, -10069, -11629, -10284, -7623, -6288, -8112, -15615, -9380, -7730, -6256, -7281, -10704, -8112, -8485, -7389, -7523, -9429, -7912, -7464, -8982, -8683, -11115, -8754, -5768, -8138, -8982, -28777, -10069, -4951, -7445, -8549, -13049, -12319, -5494, -7335, -9331, -9429, -13049, -8333, -6628, -12319, -7299, -8138, -14784, -5862, -17034, -6365, -5862, -8982, -5561, -9639, -7097, -5085, -9936, -5360, -7984, -11004, -5319, -9284, -5286, -8220, -10001, -6113, -7050, -5784, -10284, -6885, -7687, -7335, -6692, -15615, -6943, -13049, -8304, -7113, -12319, -10138, -7752, -7162, -6973, -11629, -13738, -5539, -7484, -6885, -12534, -9106, -5374, -10899, -6602, -10799, -8582, -6399, -9479, -5743, -10442, -9639, -8276, -7247, -5247, -11115, -14784, -9238, -7389, -5759, -10210, -11781, -7842, -9106, -7665, -9429, -9936, -6842, -10526, -10799, -9639, -11115, -6773, -10069, -9812, -9812, -9585, -7317, -10613, -8827, -9064, -8393, -7774, -13738, -9193, -7842, -9812, -7335, -28777, -10210, -7113, -17034, -6759, -12776, -10799, -7503, -11232, -6540, -9873, -10284, -9149, -9149, -6800, -8454, -9585, -13365, -8827, -7542, -8192, -9585, -28777, -9585, -8982, -9238, -10442, -10799, -4473, -6516, -3817, -7464, -9936, -4089, -5979, -5458, -4907, -9429, -4357, -7484, -8034, -4344, -10138, -5299, -8942, -7665, -5615, -13049, -6457, -8517, -7842, -10362, -12123, -7146, -10362, -11356, -10362, -10526, -8060, -13738, -7888, -7130, -9479, -10001, -9238, -5061, -6469, -7034, -11629, -7708, -3873, -6007, -6026, -10799, -7196, -3656, -5422, -7213, -10001, -7130, -4369, -5360, -9429, -8754, -7888, -5260, -5997, -6235, -7317, -10704, -4896, -7113, -5133, -6225, -11629, -4219, -8363, -5871, -5401, -9753, -3230, -9284, -7162, -4733, -6256, -2040, -8517, -6457, -4640, -4082, -1359, -6376, -5247, -5776, -3707, -1356, -4592, -3710, -6332, -4532, -1954, -3589, -2300, -4215, -5002, -3110, -2768, -1620, -3354, -4545, -4805, -1815, -1807, -3992, -4447, -6434, -1261, -2851, -6163, -4683, -5871, -1434, -4688, -9106, -4659, -4980, -2270, -6943, -8754, -4172, -4918, -3600, -8582, -8304, -3560, -5465, -4826, -8423, -7819, -3108, -6988, -5139, -8086, -6553, -3085, -11356, -6074, -9193, -5266, -3808, -6093, -7644, -11781, -4597, -5487, -3798, -5924, -9479, -4918, -6943, -3306, -5202, -8649, -6045, -6411, -3751, -6516, -8790, -6354, -6492, -4161, -8034, -8683, -5951, -7389, -4215, -5465, -8333, -6343, -7708, -4968, -3900, -6480, -6705, -7146, -8247, -3393, -4532, -6411, -6343, -10704, -3444, -3507, -6666, -5253, -6083, -3624, -3407, -7562, -4112, -5170, -3801, -4299, -8138, -3415, -5401, -4250, -6332, -8942, -3370, -6256, -5214, -8942, -11488, -3876, -7960, -6943, -9149, -9639, -4713, -10613, -11004, -9479, -7503, -5924, -13365, -11781, -11115, -7464, -7796, -10704, -7960, -11629, -9753, -10210, -7644, -7960, -10899, -13365, -17034, -6457, -11488, -10284, -9238, -10362, -7644, -12534, -8982, -7687, -6565, -8903, -11781, -8034, -7623, -5422, -5014, -15615, -7912, -8517, -5879, -3535, -7936, -8333, -9331, -7774, -3357, -6434, -9022, -10069, -9639, -3594, -6828, -9812, -10799, -10442, -3910, -8485, -11115, -10001, -10899, -4708, -8304, -13738, -8549, -8454, -5751, -6457, -12123, -6565, -7503, -5202, -5942, -8754, -5097, -8549, -4583, -6163, -7066, -4564, -9022, -5214, -6163, -6074, -4912, -7213, -6480, -6943, -5584, -5862, -7317, -6388, -9639, -5630, -6153, -10069, -6445, -7484, -6246, -5472, -17034, -7097, -5319, -6773, -5049, -11488, -6469, -4826, -6602, -5253, -12123, -5871, -5569, -6615, -6183, -13365, -6422, -7842, -6653, -7865, -13049, -8304, -9695, -6074, -9022, -12776, -13049, -6705, -5970, -8220, -10069, -13365, -5049, -7146, -8034, -8454, -10138, -4303, -9695, -9585, -7484, -9812, -4399, -10799, -13738, -6026, -13738, -5759, -9639, -10001, -4640, -9812, -10138, -8034, -8582, -4149, -5646, -7752, -7034, -9284, -4559, -4112, -4837, -7264, -10899, -5718, -3856, -3817, -8423, -9531, -7426, -4569, -3720, -9639, -7004, -9753, -6045, -4238, -9380, -5531, -13365, -7984, -5189, -8423, -4826, -17034, -8827, -6204, 10085, 11221, 8963, 11018, 8334, 9316, 10859, 8285, 10493, 7927, 7109, 9776, 6180, 8944, 6627, 6461, 8059, 4071, 6596, 4456, 7327, 6182, 4924, 4416, 3687, 6875, 5014, 5059, 3515, 4214, 4988, 4298, 3876, 2967, 3293, 2754, 3230, 899, 2199, 122, 5608, 1801, -3779, 2184, -2036, 6931, 770, 1667, 1695, 1483, 6717, 487, 2971, -1433, 3730, 6108, 9, 2941, -490, 5580, 5814, 1001, 3414, 3220, 6865, 4438, 3648, 4125, 4494, 7290, -670, 4812, 3796, 4447, 6636, 531, 4412, 2070, 3617, 4561, 2454, 2450, -1029, 2858, -167, 1760, -304, -2020, 2464, -1854, 314, -278, -1401, 1950, -249, 50, -185, -1652, 1419, -1168, 992, -816, -1865, 1288, -1944, 1695, -1462, -1035, 1282, -1156, 1557, -1074, -138, 745, -301, 145, 338, -193, -773, -409, -1961, 1326, -1428, -4545, -1606, 840, 1391, -2253, -3656, -2188, 2628, 590, -206, 146, -1766, 3111, -645, 1245, 1269, -2146, 2745, -1472, 1586, 646, -1205, 1636, -1472, 912, -2046, 621, 718, -1254, -677, -3996, 1552, 1851, -1340, -2597, -2210, 1793, 2748, -1003, -2853, -3837, 1757, 2764, -220, -1321, -6528, 1499, 2660, -245, 117, -692, 697, 2803, -2121, 1046, 881, -893, 2547, -5599, 1485, 710, -3420, 1743, -892, 1465, -765, -9695, 847, 294, 1035, -1621, -3744, 60, -765, 367, -1573, -816, -704, -3252, -262, -4336, 410, -996, -1746, -635, -2386, 1060, -803, -526, -674, 787, 1419, -916, -433, -969, 1473, 1277, -2055, -1387, -2391, 458, 445, -5031, -3714, -5827, -2699, -1258, -8454, -4991, -10704, -5516, -4816, -5630, -3177, -5002, -2000, -8192, -5487, -1236, -1732, -415, -3034, -7583, -54, -280, 585, -1935, -10442, -31, -159, 1112, -2766, -5970, -1386, -1286, 969, -5561, -3653, -5061, -4115, 9, -4890, -2635, -8060, -6540, -2042, -2758, -2328, -5176, -4573, -6194, -1894, -2409, -4779, -4754, -6365, -1980, -2873, -3457, -6321, -3600, -3294, -4258, -2686, -6870, -2791, -7708, -6653, -3498, -5292, -2637, -7213, -2648, -4774, -2666, -2345, -4728, -148, -3404, -991, -1798, -5942, 881, -2534, -497, -1494, -7984, 964, -3080, -1008, -1873, -5480, 294, -4723, -1962, -3080, -6035, -1210, -4311, -2273, -3951, -7644, -4149, -3563, -1740, -3286, -4184, -6870, -4278, -1111, -2703, -2793, -3827, -6267, -1123, -2571, -2918, -2766, -9149, -1928, -2541, -4127, -2485, -8034, -2679, -2534, -5784, -2323, -6399, -2679, -3054, -6553, -2873, -7162, -2289, -4451, -6899, -3729, -13365, -1483, -5951, -7665, -1936, -8304, -1236, -5451, -6163, -606, -8138, -2143, -4649, -3626, -686, -8718, -4191, -4890, -2596, -2069, -3843, -4946, -6577, -3386, -4408, -2314, -3720, -8333, -7353, -5554, -2406, -2975, -6214, -9585, -4800, -3147, -2778, -3468, -7464, 5303, 7699, 9187, 7182, 4567, 4998, 6945, 8808, 6800, 6044, 4016, 4641, 7734, 5870, 7372, 2124, 2279, 6223, 5179, 7694, -1627, 1455, 4947, 4994, 7330, -6590, -3557, 4399, 4182, 6588, -993, -433, 3796, 1087, 5559, 501, 2203, 3461, -3198, 4384, 1062, 2649, 4003, 1569, 4012, 14, 2320, 3825, 506, 4519, -168, 2061, 2599, 225, 5207, 4308, 2727, 2718, 4269, 5699, 6329, 3881, 3698, 5604, 5512, 6863, 4638, 3582, 5193, 4359, 6259, 4768, 2425, 2746, 2310, 4553, 4327, 1066, -8363, 817, 1687, 3442, 421, 985, 1515, 656, 2389, -848, 2451, 2318, 1567, 1285, -1548, 2667, 2153, 802, -781, 1189, 2677, 623, -3449, -1863, 2437, 2450, -3399, -2374, 653, 2143, 1299, -4115, 1206, 1239, 557, -672, -877, 2275, 137, -340, 442, -147, 2466, -2253, 976, 1057, -322, 2106, -3583, 1713, -346, -583, 853, -3846, 1280, -1516, -992, -2467, -5002, -1289, -382, -1966, -6786, -5561, -2173, -867, -2024, -953, -3735, 1651, -3235, -468, 821, -1702, 2434, -3665, -100, 1454, -754, 1052, -2165, -2054, 1425, -1578, -2705, -1941, -10442, 1399, -6332, -615, -2427, -1236, 1845, -3179, 545, -2807, 660, 2260, -1174, 79, -3618, 1333, 2397, -1057, -1225, -4486, 1769, 2385, -526, -2787, -3879, 2168, 2090, 369, -2082, -2198, 2192, 1022, 839, -326, 302, 1657, -1595, 736, 328, 1621, 759, -3808, -205, -284, 1520, -113, -2126, -1482, -2129, 10, -749, -3329, -886, -5020, -2924, -1653, -9936, -6, -9695, -5793, -4149, -4564, 217, -10210, -6113, -14195, -3114, 243, -5539, -5020, -4754, -1482, 361, -3546, -3906, -3354, -311, 278, -2435, -2505, -3291, -413, -266, -1920, -1134, -3698, -1820, -953, -1626, -478, -4573, -4831, -901, -1300, -715, -5726, -14195, -316, -1038, -1913, -6457, -7523, 226, -1105, -4336, -7888, -4733, 698, -1600, -5654, -28777, -3191, 860, -2720, -3798, -7730, -2130, 313, -5408, -3354, -5306, -1169, -1352, -7665, -4157, -4842, -298, -4491, -4093, -4869, -5202, 100, -4500, -3846, -4270, -5339, -226, -2999, -6299, -3101, -4847, -1356, -2743, -8333, -2342, -4601, -3360, -3094, -10613, -2462, -6026, -6163, -3680, -5906, -3580, -10001, -7503, -4270, -1680, -6143, -6310, -5615, -3910, -100, -7371, -4303, -4086, -2900, 241, -4226, -2191, -3665, -2779, -208, -2799, -864, -4564, -3529, -1405, -2465, -897, -6828, -3137, -3961, -3156, -2231, -8865, -2653, -28777, -5221, -3689, -6885, -3580, -5014, -4885, -3007, -4433, -5638, -3444, -3326, -2057, -3362, -6235, -4703, -3735, -1624, -3071, -4195, -9812, -6679, -1640, -2300, -3220, -2326, -17034, -1880, -1144, -4837, -67, -7146, -2072, -453, -7299, 484, -3294, -2210, -548, -1998, -191, -911, -2596, -1527, -374, -1921, 206, -2990, 9559, 7043, -6183, 6970, 8473, 9287, 7540, 4242, 7206, 8535, 8438, 8037, 6533, 7465, 8612, 6931, 7830, 7230, 7288, 8385, 5091, 6974, 6978, 6565, 7458, 4710, 5715, 6004, 5247, 5457, 4882, 4077, 4551, 3744, 2095, 3670, 937, 3061, 3880, -710, -698, -4254, 1885, 4317, 484, 1705, 1691, -752, 3453, 1833, 4786, 2420, -2163, 2260, 608, 6022, 3268, 3204, 3217, -7179, 6134, 4795, 4331, 3255, 1001, 4940, 4841, 2835, 2286, 1770, 1232, 2483, -8247, 3633, 3913, -1412, -585, 2881, 4654, 6081, 1930, 2905, 4320, 4163, 6732, 1310, 3242, 3768, 2312, 6124, -2728, 1981, 2061, -740, 4500, -4089, 265, 512, -6411, 2225, -305, -331, 978, -3114, 1372, 487, 6, 2036, 32, 2416, -278, -552, 2470, 1348, 3030, -3526, -3490, 2160, 1784, 3221, -5638, -5702, 1329, 1637, 3304, -1798, -2912, 588, 965, 3035, -994, -4031, 389, -566, 1631, -1134, -8683, 247, -2347, -3194, -1934, -4176, -10, 254, -1407, -3054, -3482, 306, 2206, 1354, -2420, -2764, 1077, 2902, 1785, -1372, -919, 1499, 2692, 1317, -777, -231, 1376, 1797, 150, -448, -109, 870, 348, -3137, -437, 418, 109, -1810, -1811, -833, 539, -1189, -5662, 1290, -1392, -226, -2524, -10001, 1924, -1753, -1592, -15, -4869, 653, -828, -5380, 1940, -3172, -3674, 944, -4226, 2535, -2639, -3151, 1641, -765, 2104, -3507, -800, 766, -1104, 1027, -5654, -257, -2217, -4654, -283, -2302, -188, -4858, -967, -2071, -43, -587, -3860, 476, -4021, 818, -1277, -5592, -405, -3913, 852, -1505, -9695, -3526, -4207, 227, -1956, -12319, -7353, -6143, -1072, -3947, -7004, -9238, -9936, -2320, -10526, -4800, -4311, -10001, -1716, -6870, -4021, -2198, -8060, -1390, -4373, -3600, -2490, -7484, -2427, -2781, -3124, -5367, -7523, -4119, -1721, -3012, -6103, -8582, -4968, -1534, -3698, -3365, -13049, -6885, -2672, -5768, -2490, -8615, -7960, -7247, -11629, -2020, -6590, -5380, -5326, -5768, -1643, -8454, -3360, -1516, -3089, -1556, -9149, -1952, -158, -2075, -1707, -3692, -1761, 150, -2348, -1825, -1774, -3549, -32, -4053, -1852, -1175, -7113, -372, -7623, -2175, -1237, -2192, -1107, -13365, -3586, -1344, -520, -2596, -10799, -7542, -1507, -454, -3444, -6705, -4583, -2282, -1439, -2034, -5164, -2522, -3876, -3124, -815, -4303, -2545, -5319, -5718, -198, -3944, -3846, -5401, -6288, -160, -4307, -4230, -6183, -3179, -900, -4764, -2032, -9695, -2094, -2779, -4223, -257, -8454, -2651, -5561, -3108, 589, -5960, -5312, -5091, -2297, 614, -4266, -10210, -2999, -1944, 83, -2891, -4963, -1704, -1814, -748, -2793, -4361, -1597, -1838, -1921, -3738, -5487, -2557, -2182, -3551, -2916, -2722, -3717, -2988, -4344, -1685, -503, -3521, -4299, -3785, -1759, 237, -2698, -4161, -2540, -3201, -1264, -6492, -4254, -1427, -4442, -132, -3196, -3729, -1206, -5437, 23, -1994, -1991, -2014, -4348, -570, -2107, -1103, -3635, -4323, -1759, -2247, -1505, -5408, -6773, -3220, -1610, -2956, -6434, -6163, -3933, -984, -3367, -4425, -4307, -3515, -668, -2754, -2282, -6457, -2435, -517, -3058, -1276, -5170, -1661, -564, -3474, -1444, -986, -1564, -981, -2311, -2924, 375, -1932, -1674, -1232, -4369, 301, -2655, -1935, -1002, -2731, -760, -3930, -1590, -1680, -1602, -2168, -6256, -1473, -3795, -1616, -2827, -8192, -1865, -8683, -3029, -3194, -5776, -2040, -3016, -8138, -4764, -4541, -1183, -594, -4853, -2869, -4620, -291, 217, -2458, -436, -4997, -117, -229, -2540, 269, -4748, -985, -1822, -4420, -393, -5073, -3347, -2914, -7888, -2388, -5299, -7774, -2262, -8304, -5031, -3732, -6225, -2130, -5584, -5387, -2650, -5037, -2815, -4478, -6103, -2445, -4451, -4550, -5079, -8304, -2979, -3726, -8220, -5394, -7774, -4550, -2956, -6540, -3811, -5049, -6759, -2213, -4963, -3198, -3314, -5915, -1666, -5394, -3438, -2984, -4896, -1567, -7819, -3680, -4172, -4108, -2055, -8454, -3589, -6602, -3621, -3225, -6628, -4093, -6054, -4157, -5279, -7034, -6828, -4625, -6745, -8942, -8582, -7665, -4795, -15615, -4611, -8423, -3989, -7335, -6628, -1768, -7464, -3386, -7445, -5516, -681, -6988, -4912, -4382, -6246, -1021, -7819, -6943, -4176, -7842, -3005, -10526, -3833, -6666, -8754, -6422, -11629, -1928, -6628, -7162, -4545, -9873, -1080, -3096, -4880, -3121, -8165, -1126, -1561, -3080, -2785, -7004, -2165, -931, -1746, -3016, -6540, -4290, -949, -991, -3264, -6388, -7960, -1656, -944, -3360, -6516, -9238, -2843, -1525, -3526, -7299, -5607, -3049, -2195, -3978, -7162, -4315, -2562, -2458, -4545, -5678, -4573, -2952, -3154, -4242, -5061, -6183, -4826, -4923, -3569, -5103, -8220, -9106, -5524, -3074, -5079, -7299, -6842, -4340, -2672, -5061, -4442, -4816, -3811, -2339, -5584, -2774, -4064, -3820, -1939, -7623, -2497, -3650, -4219, -1680, -11232, -3415, -3498, -4837, -1778, -6800, -4929, -3801, -5079, -1995, -5623, -5702, -4545, -5214, -2173, -6422, -5266, -5049, -5793, -2785, -9022, -4597, -5286, -7196, -4532, -10138, -4315, -6376, -10442, -9284, -8790, -3748, -7936, -7819, -7865, -10069, -3175, -6653, -4640, -4974, -9193, -3615, -5960, -3126, -4223, -4923, -5879, -7213, -2540, -4399, -3331, -11232, -9149, -2585, -4779, -3438, -6528, -8060, -3121, -4935, -5387, -4708, -8454, -4180, -5260, -11781, -3971, -12319, -5638, -6445, -10001, -3674, -9429, -6113, -8683, -7317, -3704, -7281, -5234, -10001, -5979, -4142, -7196, -4929, -8304, -5638, -5240, -7842, -5599, -6332, -6800, -7247, -7371, -7264, -5014, -10362, -8982, -5942, -10210, -5002, -8865, -9022, -5055, -17034, -7335, -6434, -10442, -5422, -7752, -12123, -6035, -11004, -8060, -5516, -5793, -3130, -236, -4142, 321, -2964, -3846, -1086, -4779, -411, -3373, -2334, -2833, -4307, -1961, -5546, -639, -5569, -4578, -4559, -10704, 158, -5374, -4550, -9331, -3751, -90, -3321, -3213, -8086, -1527, -1549, -2776, -2756, -6732, -836, -4826, -3913, -3837, -7503, -1241, -6054, -8549, -5279, -6332, -2613, -3401, -7213, -4184, -4274, -4885, -2507, -4266, -3695, -3257, -7730, -2594, -3618, -4223, -3331, -10069, -3479, -3476, -5067, -4743, -8333, -4805, -3140, -6153, -8903, -5121, -5139, -2735, -7281, -10284, -2910, -4795, -2502, -7503, -5718, -1936, -4874, -2342, -6705, -3951, -2385, -5415, -1580, -5933, -4093, -4805, -4447, -434, -4369, -9380, -3058, -2414, 136, -2390, -3866, -399, -1215, -426, -1308, -730, 367, -624, -2422, -1214, 94, -143, -300, -3342, -1780, -573, -1341, -574, -2416, -2420, -2895, -2159, -2264, -3468, -2696, -6399, -2192, -7865, -3546, -2739, -5516, -1920, -3992, -1381, -3071, -6828, -1953, -1986, -627, -4438, -14195, -2675, -1817, -783, -6759, -5429, -4545, -2529, -1280, -4578, -3751, -9753, -3906, -1992, -3179, -4357, -7842, -6973, -2774, -3563, -9873, -5531, -9936, -3833, -6235, -5801, -5472, -3763, -6988, -9284, -3349, -5654, -1719, -6267, -4157, -3870, -4885, -1131, -3433, -2553, -7299, -3586, -1625, -3430, -1965, -5726, -2724, -2450, -4885, -1753, -3130, -2713, -1726, -3279, -2045, -2039, -3677, -778, -1615, -2952, -1468, -6133, -805, -1362, -4064, -1174, -7408, -1804, -2257, -4640, -1264, -3776, -3375, -4361, -4108, -1838, -1954, -4295, -8549, -3249, -2900, -1471, -3782, -10001, -2904, -4429, -2339, -2827, -6054, -3056, -6183, -5465, -2378, -4583, -3650, -6516, -13738, -2657, -4286, -4733, -5415, -7730, -3047, -5061, -5997, -4215, -7389, -2510, -6914, -6225, -3785, -3804, -1699, -6679, -6278, -4573, -2396, -1465, -4390, -7389, -6590, -2912, -2189, -3232, -9149, -6943, -5554, -4399, -2912, -7426, -3677, -10001, -6666, -3010, -4985, -1450, -8485, -4119, -3344, -3254, -568, -10284, -3244, -3529, -2336, -888, -17034, -3594, -2933, -2283, -2065, -9149, -4478, -2283, -2912, -2756, -7503, -5247, -2583, -3626, -2553, -6565, -5539, -4464, -3866, -2741, -5346, -5273, -6590, -4067, -3624, -4100, -4664, -4616, -4523, -4968, -3509, -3985, -4597, -5266, -6492, -3944, -3124, -5524, -6225, -7583, -5662, -2516, -3460, -7213, -7019, -7865, -2841, -2186, -7371, -6540, -7503, -4896, -2291, -6143, -6153, -7408, -9873, -3326, -5726, -6113, -8393, -5759, -4869, -7819, -7317, -10362, -4311, -6615, -11488, -8865, -8034, -4395, -8034, -6422, -7299, -4203, -4923, -8485, -5509, -5654, -2205, -4985, -8304, -5646, -4847, -1551, -5103, -9064, -5339, -4800, -2020, -6332, -13049, -4226, -5002, -3574, -8192, -12319, -3304, -4858, -6528, -6628, -9284, -3101, -4683, -9193, -6054, -8649, -3589, -4912, -6705, -7299, -9106, -4344, -5561, -6163, -5654, -3549, -3222, -81, -2244, -5694, -3554, -5638, -1350, -2713, -5339, -3027, -5408, -4119, -4455, -6194, -2274, -3850, -28777, -5121, -9812, -2179, -2739, -5367, -3698, -10613, -3042, -1953, -4399, -3656, -5152, -4536, -1574, -7644, -5623, -2448, -4790, -1786, -6492, -6653, -946, -3504, -2783, -2534, -2347, -607, -2427, -4805, -1712, -595, -1822, -1884, -8790, -2567, -433, -7146, -1591, -12776, -4104, -1813, -3913, -1258, -5810, -3748, -4625, -1117, -894, -2475, -3647, -3804, -437, -716, -436, -3507, -2452, -641, -852, 417, -1026, -2107, -1092, -1494, -59, 838, -1694, -742, -3096, -2222, 1690, -683, 137, -4674, -3689, 1758, 488, 596, -3029, -1825, 1156, 1340, 616, -2158, -1854, -73, 1654, 396, -2458, -4157, -2088, 1349, -157, -3281, -8333, -5662, 427, -1249, -3362, -5234, -17034, -968, -2817, -2841, -4482, -7066, -2256, -3999, -2679, -3804, -5247, -3457, -3509, -2519, -3239, -3860, -7097, -3284, -1890, -3830, -2747, -6553, -4869, -1263, -5646, -2155, -2383, -10799, -657, -7371, -1975, -1187, -5415, 69, -6565, -1622, -1250, -3103, 421, -4373, -1006, -1950, -2528, -141, -3349, -964, -2803, -3560, -2305, -3954, -2142, -3493, -7247, -11629, -6870, -4097, -3428, -5360, -3638, -15615, -3401, -2622, -3266, -1790, -7603, -2939, -2188, -3276, -1917, -6399, -4086, -2624, -4790, -3067, -6083, -5539, -4172, -9106, -3989, -6083, -3444, -5509, -8086, -4536, -6388, -1885, -3647, -4112, -6343, -4816, -1435, -2997, -2596, -10362, -2791, -1630, -4869, -2279, -7562, -2232, -2659, -10138, -2918, -6332, -3230, -6016, -2855, -4790, -6376, -3893, -3465, -755, -14195, -6516, -1941, -690, 113, -3804, -5465, -770, -83, 316, -1040, -3686, -543, -1045, -65, -259, -2401, -954, -3692, -983, -763, -2179, -1711, -8649, -1742, -1899, -3078, -1957, -14784, -1571, -2358, -4134, -1236, -6885, -1391, -2152, -3996, -703, -5333, -1912, -1945, -4191, -1024, -5933, -3208, -2184, -5319, -2294, -4601, -4723, -3624, -6310, -4336, -3391, -4115, -8485, -5871, -6093, -4826, -2345, -7796, -5759, -6214, -7623, -1213, -5061, -5292, -6516, -2841, -1245, -5183, -3723, -9812, -1501, -3203, -5979, -2939, -8112, -1826, -12534, -5710, -3144, -4319, -3117, -3329, -5422, -3677, -3105, -3913, -1615, -6083, -3788, -3393, -4130, -1546, -8718, -3612, -5306, -4901, -2473, -9585, -3274, -8683, -4951, -4365, -5599, -2956, -6399, -4184, -7503, -4478, -3347, -5444, -4365, -5662, -4837, -5279, -6123, -6133, -3142, -5743, -12776, -7196, -9753, -2478, -6183, -7299, -7146, -11356, -3168, -6773, -5260, -6267, -28777, -3349, -8276, -4929, -5339, -8192, -2032, -9936, -5599, -4896, -5546, -1317, -10210, -7281, -5260, -4764, -1018, -9531, -9812, -6183, -5221, -639, -8718, -11232, -6602, -6732, -524, -7213, -10138, -6504, -6719, -1026, -6480, -8517, -6856, -5158, -2107, 6798, 7074, 7441, 9543, 2855, 6478, 6828, 7179, 8840, 2171, 5702, 5860, 6589, 6326, 401, 4828, 4017, 6047, -2122, 1098, 3984, 3277, 5626, 3316, 2604, 3289, 3498, 5202, 3879, 2561, 1875, 2019, 4429, 2168, 451, -1842, -115, 2741, 2939, -1832, 3531, 2571, 365, 4447, 2033, 5403, 3833, -34, 4609, 3804, 5307, 4087, -1236, 3605, 4946, 3812, 4262, -3680, 1407, 5968, 1780, 4856, 708, -262, 6632, 1250, 5453, 2222, 1059, 6630, 1805, 5377, 1890, 1673, 5727, 1285, 4189, -82, 1402, 3735, -469, 1713, -524, 663, 1218, 1025, 533, 1409, -74, -756, 1815, 1403, 2102, -127, -2165, 789, 1467, 1872, 660, 1720, 1703, 1005, 1135, 1470, 3094, 4127, 567, 369, 1856, 2864, 5396, 582, 70, 1788, 1698, 5552, 653, 202, 1342, 115, 4523, 342, 326, 482, -8, 1890, -92, 520, -1235, 1628, -3653, 246, 1153, -4935, 2207, -3187, 1469, 1582, -6332, 1355, -3179, 2284, 1064, -6492, -1092, -2778, 2077, -247, -3641, -6045, -616, 583, -208, -1200, -7752, 1076, -2776, 116, -852, -2553, 2368, -5333, -1078, -1647, 123, 3239, -2182, -1962, -1747, 1543, 3547, -1483, -493, -948, 1965, 3185, -2791, -188, -767, 1346, 2088, -8220, -1372, -1261, -671, 383, -5933, -2661, -1453, -5472, -871, -3399, -1666, -1409, -6143, -949, -3535, -1652, -2146, -3889, -1023, -4890, -3830, -3594, -3247, -1568, -2897, -6225, -4365, -2619, -2571, -1023, -5451, -3766, -2181, -3563, -591, -9695, -3543, -2599, -4046, -1336, -6163, -5079, -4078, -3833, -2941, -3535, -13049, -5793, -3144, -4659, -2505, -5494, -7213, -2893, -4826, -1204, -3671, -9639, -3225, -3923, -315, -3814, -8333, -3468, -3264, -473, -3833, -7162, -2914, -2906, -1773, -2008, -5836, -2130, -2827, -3913, -676, -4223, -1717, -3281, -5387, -372, -3316, -1943, -4486, -6553, -1151, -3105, -3126, -7644, -6214, -3471, -3128, -5960, -9936, -3982, -10069, -2975, -4541, -4340, -3294, -6615, -2720, -1559, -2567, -4258, -5871, -2841, -264, -2189, -5743, -8138, -3833, -190, -2597, -4669, -9585, -6516, -1363, -3203, -4123, -8247, -8333, -4075, -3811, -5152, -7213, -4842, -6528, -4901, -7050, -5960, -3583, -5480, -7162, -5630, -4901, -3808, -5451, -10442, -3692, -3507, -5768, -6434, -7484, -2633, -2631, -10138, -7796, -5465, -2197, -2778, -5988, -7503, -4683, -2079, -4142, -4923, -7687, -4688, -1940, -7752, -6225, -8454, -5380, -1899, -10284, -9429, -6565, -7050, -2239, -5458, -7353, -5487, -9936, -2929, -4491, -6457, -5784, -8393, -3230, -4764, -7583, -7179, -6399, -2646, -5037, -9531, -9193, -5615, -2264, -5079, -10069, -9064, -5546, -2677, -5121, -7583, -7687, -5988, -3529, -5158, -5638, -7162, -6653, -3629, -5465, -5793, -6899, -7050, -3609, -6183, -9429, -6577, -6679, -4469, -6590, -6332, -2286, 7785, 7586, 8379, 8107, -3208, 7386, 7148, 7748, 7426, 846, 5927, 5541, 5936, 5140, 2902, 2135, 2276, 5262, -603, 3380, -1943, 3251, 6434, -509, 3575, 2411, 4432, 6523, 1883, 4396, 2794, 3957, 5366, 1586, 5210, 2766, 3328, 3344, -922, 5465, 2846, 3027, 1746, -3360, 4925, 2466, 976, 66, -3331, 3307, 1795, -4311, -3189, -1952, 2354, 1665, 2686, 980, 243, 4576, 2192, 4186, 2379, -316, 5805, 2692, 3983, 1994, -5592, 5902, 2750, 2765, 734, -3968, 5346, 2049, 1378, -448, -2512, 4722, 95, 611, -1438, -5472, 4100, -4644, -379, -2910, -7484, 2689, -3837, -1771, -695, -2590, -2022, -836, 109, 1915, -835, -314, 152, 1830, 2369, 168, 2944, 271, 2218, 117, 767, 3371, 119, 1649, -2699, 925, 2096, 265, 517, 1989, 268, -653, 674, -1380, 3055, -1068, -2062, 842, -8138, 3049, 722, -1236, 346, -2594, 3098, 2574, 36, -1193, -40, 3165, 2749, 1334, -2954, -41, 2734, 1090, 2301, 283, -2465, 1732, -3276, 2716, 2783, -7484, 565, -4816, 2094, 4090, -3689, -180, -5299, -632, 4546, -6093, -1008, -3526, -4985, 4304, -4500, -2683, -1453, 797, 3432, -379, -3060, -976, 2427, 2034, 624, -874, -1425, 2972, 531, 188, 855, -1370, 2824, -466, -794, 1954, -140, 1800, -1478, -1714, 2464, 280, -494, -4207, -3301, 2270, -372, -5026, -11232, -2791, 1055, -1574, -7503, -6492, -1003, -2345, -2666, -5592, -11356, -742, -5879, -2997, -3638, -2393, -1761, -1065, -2847, -2280, -33, -3264, -443, -3130, -2528, 336, -4491, -1681, -3474, -5037, -690, -4679, -4790, -4963, -8754, -2661, -2170, -9873, -7888, -5367, -3058, -441, -11488, -3018, -5710, -2650, 279, -6828, -1573, -7665, -3430, 375, -4831, -2123, -4258, -4373, 148, -4592, -4469, -2175, -3801, -292, -5014, -6973, -1410, -3373, -1063, -4536, -5942, -1623, -2213, -2129, -3554, -6083, -2990, -933, -2785, -2904, -7004, -6457, -852, -3110, -2779, -6615, -12319, -2250, -4031, -3187, -5158, -8138, -5067, -4145, -3971, -3900, -7984, -6973, -3554, -5037, -3232, -4826, -7464, -4164, -6480, -3165, -2950, -7097, -5524, -6666, -3626, -2472, -5531, -6007, -5043, -4654, -2933, -4429, -6899, -4460, -6856, -3754, -3954, -5312, -5145, -28777, -4215, -4082, -3367, -6469, -6299, -4469, -4779, -3087, -6516, -3883, -5607, -5067, -4134, -5158, -3329, -8615, -4611, -5208, -3937, -3893, -9331, -4718, -5465, -3686, -4997, -8192, -5743, -6870, -4527, -6083, -9753, -7196, -8615, -6640, -7542, -17034, -8393, -6692, -9812, -9585, -12123, -8276, -5401, -13365, -9064, -11629, -5951, -5026, -14195, -7842, -14195, -3837, -5951, -8138, -8034, -13049, -3003, -9753, -5970, -9022, -10526, -3754, -11232, -4831, -10442, -9695, -7389, -8649, -4067, -14784, -9639, -9429, -10704, -3600, -11356, 6658, 8051, 3191, 5852, 6426, 5577, 7421, 2768, 5544, 5464, 1428, 5620, 1553, 4373, 1558, 2037, 4506, 1016, 2219, -204, 4467, 5472, 3102, 2415, 3090, 5690, 5947, 4428, 3626, 3214, 6069, 5574, 4416, 4380, 2260, 4960, 4051, 3397, 5238, 1077, 1852, -454, 2164, 5482, 453, 2458, 649, 988, 4630, 834, 3979, 3454, -1805, 2821, 243, 3994, 4088, -2935, 907, -4373, 3141, 4061, 1336, -2793, -2906, 1326, 3585, 2243, -795, -1146, -2617, 2485, 467, 2605, -6007, -622, 865, -5768, 3440, 133, 1673, -1535, 1741, 2965, 3133, 1685, -3512, 3312, 1936, 4194, -718, -1045, 3316, 1025, 4256, -3311, 146, 2550, -603, 3830, 950, 521, 1779, -3362, 3464, 2255, 508, 1732, -360, 3331, 2248, 3, 2168, 1211, 3124, 1261, -1391, 2269, 1214, 2613, -934, -4644, 1496, 18, 1691, -5509, -8683, -625, -1999, 343, -3817, -4108, -6565, -1026, -1347, -2552, -908, -3659, 1291, -3007, -4100, 854, -258, 2611, -597, -2462, 1039, 870, 3040, 1617, -75, 242, 609, 2647, 2241, 480, 571, -1064, 1349, 1493, -95, 1096, -4991, -310, -230, -1198, 551, -7687, 247, -1626, -2499, -439, -1502, 1179, -3249, -4583, -1799, 1162, 1165, -2823, -4923, -4597, 2471, 329, -63, -3814, -2795, 2747, -1219, 1003, -2331, -2619, 2139, -3496, 996, 671, -10526, 918, -4728, 536, 1922, -1693, 58, -2460, 160, 1144, 243, 81, -548, 326, -2391, -519, -113, 261, 1099, -1476, -3321, -964, -23, 1681, -98, -1402, -1852, -1229, 1539, -1240, -712, -1507, -2756, 604, -4442, -2833, -1025, -4327, -877, -8363, -6653, -1325, -5988, -2664, -5451, -3615, -1683, -4017, -4266, -3482, -3792, -1126, -1661, -4743, -3717, -5531, -734, -39, -4153, -7371, -6214, -1065, 761, -3076, -4698, -5942, -1607, 739, -3020, -1880, -6343, -1837, -11, -3961, -1380, -7445, -2548, -1373, -4262, -2569, -4527, -4764, -3577, -3463, -6173, -2239, -8615, -6914, -2425, -11115, -1532, -8649, -5422, -2115, -7371, -2241, -11781, -3468, -3117, -7146, -4929, -10001, -2541, -5164, -6321, -12534, -6666, -2105, -5569, -5662, -6457, -6133, -1836, -5546, -6235, -5115, -7247, -1349, -6814, -7389, -4935, -10138, -908, -7603, -6504, -5615, -7865, -984, -6123, -5026, -7264, -5584, -1760, -4853, -4536, -6103, -5394, -3247, -4344, -5444, -4203, -6692, -4664, -4946, -8220, -4134, -8615, -4049, -6705, -8903, -6814, -8582, -3007, -8827, -7019, -10001, -6540, -2745, -9873, -6516, -4880, -5002, -3444, -9812, -6759, -4108, -4625, -5346, -7050, -8247, -5031, -5273, -5970, -4433, -13365, -6615, -6786, -3769, -2615, -6399, -7865, -9429, -2733, -1760, -4134, -7162, -11945, -2538, -1992, -3729, -4774, -9064, -2952, -3537, -4674, -3621, -7264, -4412, -6163, -6469, -4053, -6786, -8582, -5408, -6343, -5888, -4968, -5422, -3647, -6705, -5592, -4119, -4038, -3119, -7179, -5686, -4246, -3096, -3951, -5353, -4997, -6540, -2613, -5888, -3843, -4089, -10704, -2698, -6732, -3710, -4003, -5759, -3529, -5979, -4831, -4728, -4282, -4940, -6943, -6786, -5546, -3795, -5480, -11629, -7912, -5353, -3792, -4536, -9812, -7247, -4963, -4500, -3518, -7865, -6705, -5195, -6653, -2859, -7912, -6732, -5494, -14195, -2716, -8086, -6615, -5152, -10284, -3339, -7247, -6267, -4616, -8454, -5164, -5494, -7408, -4527, -6480, -8718, -3748, -13738, -5127, -4089, -6899, -2610, -13738, -7213, -2345, -6434, -2613, -7960, -7317, -853, -7353, -4597, -2216, -1503, 455, -2504, -2910, 184, 805, 1343, -59, 191, 874, 1438, 1525, 822, 1243, 203, 718, 790, 591, 720, -1761, -1390, -1001, -513, -1610, -4592, -4980, -3698, -2163, -8009, -6692, -7819, -5710, -3612, -6565, -8942, -6399, -6246, -3999, -6214, -12534, -4863, -7113, -3618, -6973, -13738, -4195, -8165, -3337, -4957, -11232, -4184, -8363, -3566, -3735, -7888, -4597, -10210, -4509, -3543, -5710, -5487, -10799, -6093, -3947, -5037, -6504, -8718, -6504, -4693, -6064, -7583, -8138, -5960, -5897, -10613, -9331, -6842, -6214, -7113, -8549, -9238, -6469, -6759, -7004, -5942, -9022, -9380, -6343, -7130, -5735, -8865, -9380, -5569, -7730, -7353, -7371, -5415, -5037, -7019, -14195, -7464, -4974, -4901, -6194, -6504, -10362, -6480, -5115, -6310, -3580, -11629, -8942, -5465, -6528, -2353, -7335, -8485, -5810, -5776, -2136, -5776, -5997, -5933, -5103, -2770, -5312, -4035, -5726, -5394, -4361, -5646, -3370, -5654, -6943, -7247, -7542, -4038, -6133, -10069, -13049, -10704, -6388, -7542, -8827, -12123, -6492, -9064, -11356, -7426, -10613, -5253, -6943, -10526, -7774, -10704, -5942, -6653, -7936, -8060, -10001, -8393, -8754, -7708, -6870, -9531, -9753, -28777, -8393, -6565, -10899, -7819, -11232, -8718, -7408, -10704, -6732, -9695, -9639, -8790, -7730, -6183, -9149, -14784, -9284, -6288, -6376, -8485, -10899, -9479, -5561, -7066, -7603, -7984, -10526, -5152, -7408, -6856, -7019, -11945, -5158, -8276, -6540, -6759, -11945, -5853, -11115, -6411, -6705, -10001, -7179, -13738, -6376, -6516, -8982, -6577, -9936, -6376, -6173, -9585, -5339, -7542, -6267, -5836, -9695, -5444, -6800, -6422, -5630, -7542, -7113, -7113, -7752, -5844, -5988, -9064, -6973, -11004, -6434, -5061, -7264, -6745, -10442, -7644, -4896, -6163, -7623, -11356, -9812, -5951, -6123, -9873, -13738, -11629, -9873, -6388, -13049, -8649, -11232, -10069, -6628, -13738, -7464, -13049, -6590, -7464, -10442, -7752, -28777, -6035, -9022, -8276, -9284, -9936, -6786, -9585, -7542, -13365, -7960, -8517, -9936, -8423, -13365, -7730, -11115, -12319, -10362, -9585, -9193, -13365, -17034, -8790, -9331, -13049, -12776, -14784, -7708, -11781, -13049, -10526, -13738, -8086, -13738, -12319, -8582, -11115, -8454, -8903, -13049, -7623, -9479, -6759, -15615, -3457, -6278, -8247, -10069, -10613, -3647, -4331, -6679, -8517, -10442, -4348, -4270, -5408, -5539, -14195, -6194, -6480, -4550, -5871, -11356, -11945, -17034, -3843, -8790, -7146, -7299, -8582, -3242, -8790, -5678, -4336, -9639, -3069, -6504, -5401, -2992, -11356, -3498, -5960, -5726, -2420, -6299, -4295, -6103, -6388, -2374, -4923, -5253, -5531, -7503, -2694, -4733, -5951, -4784, -9064, -3299, -4482, -5784, -5085, -9380, -4134, -3840, -6074, -6615, -7842, -4569, -3507, -7097, -9639, -6278, -4211, -3692, -8423, -9238, -5367, -3763, -4315, -11781, -9022, -4469, -3220, -4654, -5061, -9064, -2776, -2306, -3537, -1168, -2399, -686, -940, -1132, 793, 53, 718, 307, 677, 1358, 724, 1026, 774, 1301, 571, -17, 17, 304, 671, -1900, -2108, -2881, -880, -1281, -7888, -4451, -14784, -2030, -4541, -6928, -4010, -6183, -3018, -5776, -6278, -3170, -5360, -4940, -4123, -8009, -2947, -6299, -8393, -2945, -11945, -3225, -7484, -10526, -2359, -9936, -3551, -5844, -28777, -2485, -5862, -3710, -5043, -8718, -3671, -4238, -4295, -6204, -6679, -6773, -3923, -6540, -8754, -7019, -12123, -4357, -11004, -8060, -7912, -5988, -5067, -6246, -8333, -8276, -4469, -6143, -5055, -8754, -9531, -4688, -7562, -5152, -7097, -11629, -6528, -7912, -5844, -7004, -10210, -7752, -8220, -7247, -8304, -8220, -5576, -8942, -8865, -8865, -7247, -4513, -8754, -6354, -8718, -7281, -4191, -8423, -4295, -8138, -7752, -4258, -9193, -3512, -6007, -7523, -4733, -10899, -3726, -4923, -7389, -5793, -11356, -4831, -5115, -8304, -7936, -10526, -6958, -6093, -9695, -13365, -7888, -10704, -6553, -10284, -13049, -6035, -28777, -6123, -11356, -8942, -5615, -13738, -6035, -10899, -6445, -6628, -14195, -6928, -8034, -4980, -8683, -12534, -7888, -6732, -4592, -7842, -9149, -7247, -6103, -5189, -6885, -7034, -6943, -5686, -6640, -7281, -6163, -7503, -5726, -7796, -8903, -6064, -8112, -6745, -7426, -11629, -6083, -7842, -9238, -7583, -28777, -5942, -7353, -14195, -8582, -13738, -6093, -6540, -9380, -8615, -10362, -6988, -5109, -8138, -8942, -9380, -8485, -4378, -8827, -9936, -9695, -9812, -4985, -9873, -6773, -11115, -8683, -7081, -10899, -4759, -9585, -7317, -10362, -8112, -4270, -7146, -7247, -9022, -5353, -4963, -6113, -7819, -6973, -4578, -6719, -6332, -6388, -6083, -5810, -8220, -7708, -4991, -6288, -10613, -6899, -9873, -4640, -7050, -6958, -5888, -10284, -4974, -6692, -5020, -6007, -9873, -5638, -5694, -5221, -6225, -9639, -6800, -5319, -7281, -5422, -9380, -9479, -5694, -13738, -5115, -8982, -28777, -6759, -10799, -5933, -9873, -13738, -8086, -9753, -7179, -15615, -11945, -8865, -11629, -7247, -11629, -10442, -9639, -14195, -6814, -8393, -9238, -12776, -12534, -6705, -7281, -8060, -13738, -9812, -6928, -7213, -6628, -8220, -8485, -7299, -8220, -5670, -6773, -8865, -7912, -11629, -5387, -7464, -10899, -9193, -6246, -7523, -7113, -6602, -4049, -4616, -8363, -5576, -3701, -3626, -3933, -4703, -3866, -2564, -4127, -4416, -4805, -3449, -2429, -5871, -6299, -7299, -4238, -3412, -8754, -10442, -11629, -5915, -6332, -8827, -12123, -13049, -7583, -8485, -5933, -11781, -10613, -8276, -5008, -3714, -13738, -6666, -9149, -3840, -2499, -14784, -4826, -11945, -3580, -2023, -10210, -4223, -14784, -3549, -2270, -7583, -4837, -12534, -3468, -3227, -6602, -7247, -10138, -3319, -4790, -6943, -10899, -7603, -3321, -6445, -8903, -6914, -6016, -3415, -7066, -13738, -5465, -5451, -3112, -6745, -12534, -7819, -6422, -2366, -6602, -7445, -4985, -6759, -1265, -5844, -2259, -255, -2435, 46, -2403, 132, 1713, -43, 902, -53, 802, 2295, 890, 780, 936, -73, 1840, 631, -684, 803, -2672, 524, -828, -4532, -246, -5306, -1502, -3626, -7213, -1797, -5768, -3714, -7464, -3968, -3457, -8790, -4800, -8423, -3339, -5195, -7264, -5415, -8112, -3701, -6640, -6103, -6590, -8865, -4800, -11004, -7426, -7353, -10069, -6204, -7264, -12123, -8138, -10001, -6299, -3710, -13738, -9936, -9695, -4997, -2754, -10704, -11232, -9380, -4486, -3065, -9585, -7960, -8942, -5646, -3222, -9193, -5208, -9812, -9022, -2548, -9873, -3751, -11232, -8165, -2231, -13738, -3266, -7353, -7665, -2639, -11781, -3621, -5008, -8582, -3726, -7796, -4985, -3586, -6376, -5451, -6615, -8009, -2733, -4946, -7888, -6973, -28777, -2571, -4564, -10613, -9429, -11629, -3257, -4644, -6773, -14784, -10001, -4997, -4907, -5037, -7819, -8517, -7464, -5516, -5299, -6035, -7583, -7774, -7264, -8582, -5710, -7984, -7130, -11232, -10613, -6074, -9331, -7426, -6914, -6045, -6399, -8060, -8865, -5085, -5020, -6007, -6719, -12319, -5183, -5360, -5260, -6885, -8942, -6828, -7523, -4769, -8485, -5997, -7603, -8942, -4842, -9531, -5115, -6732, -4536, -5509, -8363, -5710, -7004, -2764, -6786, -8247, -6103, -6958, -2388, -7623, -7912, -5091, -6035, -2941, -6856, -6267, -4759, -6035, -3773, -6457, -5374, -5346, -6958, -3900, -7426, -5554, -6376, -7842, -3580, -9936, -6528, -7445, -8276, -3603, -9812, -7503, -8582, -8276, -4108, -8485, -7644, -9064, -7162, -4790, -9238, -7130, -8942, -6123, -5988, -12123, -6692, -9149, -5670, -8615, -10899, -6653, -8549, -5827, -8485, -9695, -7389, -7389, -5607, -6628, -11945, -9429, -6914, -4250, -6640, -14784, -12534, -7353, -3112, -8086, -10442, -14784, -8333, -2827, -10362, -9936, -13049, -9639, -3422, -10069, -10526, -12534, -11488, -4728, -8192, -10799, -9380, -14195, -6133, -7445, -11115, -6388, -17034, -7196, -7644, -13365, -5103, -28777, -8485, -8034, -28777, -4918, -14195, -9695, -8982, -12776, -5374, -11488, -8363, -11356, -10362, -6183, -11356, -6899, -12534, -9585, -7299, -13049, -6365, -11356, -9380, -9284, -15615, -6800, -8754, -9380, -10210, -28777, -8827, -6773, -9380, -7408, -13365, -17034, -6553, -9936, -6194, -9331, -8903, -8086, 11376, 9600, 11660, 11728, 10794, 10645, 9661, 10965, 11136, 10261, 8080, 9419, 8674, 9319, 8615, -18, 8340, 3679, 6278, 6050, 4297, 6180, -3083, 2848, 4811, 4815, 2931, -853, 375, 4712, 3398, -367, 841, -643, 3351, 2719, -1859, 1574, 86, -243, 545, -2462, 2805, 696, -6745, -297, -1544, 3809, 558, -6745, 5101, 348, 3513, 1460, 543, 6903, 1140, 3359, 3129, 4304, 7444, 2841, 4499, 4339, 6106, 7259, 5262, 5216, 4899, 6658, 6464, 6493, 5168, 4629, 6041, 4908, 6444, 4650, 3293, 3916, 2536, 5282, 3973, 311, -1635, 1323, 3644, 2994, -3650, -1062, 1611, 2734, 1071, 469, 991, 1308, 2214, -3412, 2037, 1585, 1509, 2032, -5458, 2347, 1907, 2238, 2269, -3266, 2357, 791, 2229, 2248, -5422, 2591, -10210, 1589, 1720, -2922, 2683, 1545, 1385, 414, -449, 2201, 4051, 1681, -218, -28, 1164, 4505, 1891, 1978, -683, 1006, 3441, 1794, 3098, -1833, 1661, 361, 980, 2706, -5326, 1731, -9873, -128, 1255, -3420, 1665, -3563, 609, 528, -83, 1988, -6899, 1023, -182, 822, 2326, -4764, -818, -3080, 789, 2510, -1636, -4416, -1648, 747, 2369, -395, 464, -533, 563, 1582, 348, 1789, -2585, -454, 230, 171, 1626, -6163, -2612, -261, -1567, 690, -712, -5623, -11, -9022, -642, 887, -5670, -553, -2770, -2791, 1072, -3910, -1872, 156, -8683, 157, -3659, -2248, 1306, -5487, -1837, -4831, -1674, 1494, -3961, -4831, -6928, -1717, 914, -6365, -5091, -8138, -1934, 148, -8192, -2128, -6602, -1076, 504, -3913, -887, -4703, -1, 1157, -2837, -1026, -4153, 495, 1065, -2509, -2064, -6278, 377, 131, -2153, -2997, -6469, -308, -1456, -1927, -2485, -1819, -1437, -2975, -2003, -1340, -322, -2673, -3010, -1298, -769, -276, -2409, -2447, -143, -840, -1041, -825, -2165, 321, -1030, -2071, 107, -1844, -8, -941, -3194, 137, -1774, -805, -729, -4536, -425, -2424, -1370, -618, -6943, -654, -3714, -1699, -795, -4262, -197, -4821, -3071, -1489, -1746, 121, -4997, -6628, -2735, -1214, -4, -4654, -5014, -3916, -2289, -681, -4723, -3365, -4743, -5539, -2107, -4408, -3354, -5784, -14784, -4003, -2754, -3876, -4991, -8517, -5339, -1248, -3521, -4800, -10442, -5444, -396, -2247, -6615, -6705, -3049, -21, -1444, -5516, -4654, -1859, 102, -1650, -4262, -5326, -2053, 59, -3062, -4669, -5401, -2490, -141, -6354, -4896, -2895, -2370, -507, -4630, -4361, -2871, -2778, -1177, -1438, -4258, -6565, -3380, -2364, 127, -5569, -2495, -2071, -3347, 786, -10001, -135, -656, -2253, 525, -7960, 125, -63, -1122, -1137, -5487, -1067, -40, -1082, -5531, -3773, -3457, -352, -2497, -4319, -3165, -6399, -1491, -6565, -2819, -4226, -12534, -4438, -8942, -3215, -5509, -4698, -3083, -11945, 1793, 7416, 7860, 8286, 5452, 1371, 6707, 7367, 7598, 4865, 859, 4671, 6004, 5249, 3697, 1201, 3925, 4138, -188, 3502, 1367, 4927, 1968, 1484, 3547, 1083, 4869, -311, 2595, 3202, 1199, 3943, -770, 2255, 2986, 2004, 2805, 798, 1919, 2818, 2829, 2493, 2401, 1837, 2409, 3360, 2435, 3461, 1020, 2198, 4199, 2700, 4312, -1683, 3264, 5536, 4216, 5425, 452, 4817, 6465, 5055, 6365, 2468, 5736, 6588, 4760, 6417, 2299, 5879, 5957, 3956, 5170, 312, 5403, 4907, 3864, 1965, -1370, 4463, 4040, 3762, -8718, -732, 3017, 3628, 2079, -3647, 5, 1101, 3116, -4664, -6943, 1374, -280, 2106, -571, -5195, 2164, -1166, 1542, -359, -3782, 2141, -2699, 1374, -2999, -4017, 1695, -4361, -142, -58, -4564, 1226, -3076, -3683, 394, -7299, 659, 12, -2952, -183, -1849, -163, 1972, -465, 1043, -1064, 175, 3156, 1730, 1835, -4821, 1291, 3878, 2879, 1654, -2385, 1302, 4166, 2946, 817, -301, -126, 3942, 2059, -691, -1304, -1654, 3174, 283, -1281, -3726, -618, 1811, -2470, 796, -3954, 438, -478, -6504, 1793, -3386, 1220, -5333, -6123, 1070, -1175, 1843, -2470, -2900, -2622, -39, 1965, 110, -788, -4195, 73, 922, 774, 211, -345, -154, -3286, 238, -9, -127, -353, -1614, -1113, -1513, -1868, -778, 1504, -2358, -1355, -6278, -1746, 2188, -2576, 517, -7162, -2918, 1649, -1753, 1130, -4164, -3612, 174, -191, 631, -2526, -3149, -2462, 1037, -441, -2036, -2006, -5871, 1282, -1180, -2265, -1462, -1961, 118, -1614, -1123, -1900, 403, -3347, -2291, 688, -3014, 1543, -7484, -1928, 1715, -3124, 1816, -7819, -171, 1837, -2129, 1362, -5569, 1082, 1220, -1526, 336, -955, 1433, 536, -1068, -1154, 340, 843, 424, -287, -3515, -196, -471, 35, 240, -10526, -3040, -931, -1404, -147, -4625, -7912, -232, -3683, -1975, -2468, -2130, -132, -4901, -7097, -2363, -719, -894, -3846, -6278, -2897, -536, -2411, -1727, -3049, -3065, -987, -4880, -815, -1836, -1671, -1654, -8549, -1481, -1872, 526, -1587, -5686, -3680, -3629, 1639, -788, -3650, -3189, -8247, 1469, -235, -3208, -1495, -7230, 58, -191, -4408, -921, -10069, -2302, -912, -6692, -979, -7034, -4266, -3189, -2900, -1201, -3804, -4278, -7960, -1328, -752, -3135, -3850, -3504, -1635, -181, -2008, -4495, -1849, -2219, -498, -514, -3284, -1613, -1161, -2030, 177, -1225, -2644, -818, -4250, 22, -892, -6480, -1725, -3067, -911, -2745, -5487, -2646, -1057, -2191, -2666, -2741, -2821, 89, -2427, 166, -2277, -3714, 265, -2612, 874, -2207, -4278, -848, -4532, -226, -1957, -3027, -4500, -12776, -4495, -1318, -1769, -6035, -4940, -4743, -55, -906, -2462, -2648, -1382, 517, -714, -1779, -2086, -870, -413, 3125, 4077, 7513, 329, 5137, 2368, 4078, 7330, 2346, 5914, 4496, 4120, 7077, 4812, 6870, 6162, 4241, 6907, 5747, 7093, 5901, 4017, 6273, 5135, 6445, 3593, 2714, 4624, 2982, 4950, -3704, -676, 1298, -573, 3187, -516, -3903, -6732, -2302, 2372, -807, -1953, -2929, -599, 1732, -3726, -1857, -1777, 933, 969, 2994, -108, 189, 2259, 1100, 5327, 2648, 1713, 2849, 1221, 5969, 4394, 1652, 2570, 933, 5191, 4743, -337, 2764, 2724, 2707, 3459, 601, 3544, 4731, -2994, -82, 2471, 3461, 5554, -6469, 336, 2253, 2219, 5207, -3247, 1469, -86, 388, 3696, -1460, 270, -7426, -368, 1416, -454, -2015, -4795, -135, 303, 1089, -1209, -3034, 67, -227, 2194, -100, -2114, -395, -81, 2402, 201, -1272, -2277, 886, 1891, -98, -612, -6399, 1092, 871, -943, -174, -2201, 1433, -395, -2229, -45, 100, 2453, -821, -3808, -306, 952, 2811, -228, -3597, -1055, 861, 2073, -232, -1474, -2223, -70, 931, -1636, -308, -2646, -1899, 910, -6045, -82, -1747, -4718, 1230, -6553, -297, -722, -5487, 1521, -2622, -855, 190, -3609, 1725, -1241, -2361, 899, -1630, 1705, -921, -5539, 1178, 565, 2127, -1912, -11232, 733, 2054, 2927, -5970, -6204, -594, 2509, 3207, -3566, -2813, -1411, 1982, 2359, -720, -1594, -82, 1084, -559, -83, -1879, 952, 872, -3218, -927, -3314, 1339, 668, 961, -2615, -4420, 1314, -327, 2380, -1076, -2819, 1241, -2238, 2687, 352, -1664, 1511, -5584, 2189, 137, -2259, 1823, -3951, 807, -1777, -5339, 1587, -1368, -1627, -2950, -3455, 416, -294, -2294, -1077, -1773, -2355, 233, -465, -544, -2626, -9753, 520, 412, -1343, -6856, -2722, 345, 363, -2819, -6332, -479, -383, -635, -2681, -3788, 496, -1391, -3036, -1817, -2631, 649, -2460, -6842, -1766, -1320, -39, -3804, -2833, -2022, -242, -1637, -4669, -749, -1838, 117, -2737, -4172, 351, -1682, -605, -1030, -4399, 968, -2404, -2937, 672, -7179, 867, -4352, -8582, 1503, -12123, -470, -2603, -6914, 1408, -7130, -3367, -386, -6885, 355, -8790, -1598, 179, -9022, -1652, -6143, 178, -691, -4295, -3388, -2548, 541, -3463, -2015, -3023, -894, 301, -6692, -1305, -3618, -388, -122, -2510, -1773, -7503, -1050, -809, -1005, -3210, -5394, -3337, -1807, -894, -4831, -3269, -3603, -2675, -1827, -8138, -2294, -1187, -2514, -3089, -6007, -972, -224, -1807, -3597, -1361, -187, -99, -1843, -4086, 148, -406, -730, -3357, -5743, -237, -1953, -2622, -4420, -11945, -3124, -6553, -6376, -1752, -6365, -8247, -6267, -5487, -1097, -3683, -3441, -3615, -4482, -3124, -2567, -2076, -1518, -3329, -7081, -1771, -180, 215, -1460, -2073, -1183, 856, 567, -1010, -923, -1428, 553, -630, -3040, -942, -3635, -4315, -2251, -1484, -4226, -3468, -4688, -2135, -2475, -1104, -3741, -9639, -4207, -7389, -309, -4086, -6666, -5049, -3957, -702, -3632, -3989, -2831, -1501, -596, -3191, -4115, -2514, -586, 129, -3025, -6705, -2534, -976, 439, -2861, -13365, -1102, -3923, 1053, -3177, -6786, 293, -5853, 1860, -3738, -4779, 885, -1515, 1766, -3830, -4795, 757, -824, 165, -5933, -7603, 154, -2038, -4046, -5702, -5195, -627, -5951, -5784, -1778, -2076, -1206, -6074, -3218, -931, -1020, -1165, -3276, -1953, -2197, -1397, -771, -2762, -1080, -7984, -3566, -936, -3147, -509, -2615, -11945, -1678, -2280, 304, 632, -2681, -179, 325, 1363, 2254, -344, 1602, 2122, 2034, 2937, 100, 2137, 2605, 1773, 2796, -949, 1536, 1657, 104, 1900, -3507, -96, -987, -3583, 480, -6354, -3210, -4017, -2514, -1136, -6299, -9106, -4810, -968, -2801, -7371, -2893, -4527, -937, -3773, -9531, -1233, -2573, -1604, -3662, -2502, -1258, -2289, -2458, -3856, -224, -2875, -3447, -2845, -4640, 336, -8060, -5576, -2699, -5678, -279, -8276, -5759, -3054, -6288, -1724, -7562, -4527, -4513, -5970, -3744, -7230, -4412, -6267, -5227, -6628, -2641, -4386, -4880, -4738, -6411, -968, -3119, -3471, -4991, -4348, -782, -2090, -3659, -6143, -3149, -1591, -1651, -6828, -5133, -2176, -2992, -1445, -7842, -2910, -1830, -4433, -1449, -3817, -1525, -2807, -5836, -1595, -3698, -371, -5718, -7984, -1610, -5561, 637, -3701, -13365, -1774, -4974, 1135, -1673, -10362, -2592, -4319, 973, -1406, -9331, -4319, -7774, 277, -2432, -28777, -6814, -5487, -603, -4723, -5353, -6653, -1424, -1394, -7603, -2031, -4718, 68, -2140, -7130, -436, -3635, 450, -2914, -5836, -59, -3301, 278, -4067, -5451, -911, -3271, 2, -7213, -5195, -3112, -3098, -164, -8982, -3271, -6445, -2731, -503, -4348, -2165, -7130, -1869, -1571, -2731, -2497, -4985, -930, -3509, -1847, -3754, -3757, -513, -3344, -1672, -4738, -2248, -679, -2409, -3130, -5333, -476, -1378, -2596, -8485, -6045, 553, -2087, -3850, -3279, -6045, 736, -1773, -9429, -1341, -4527, 148, -930, -4703, -1067, -3603, -1199, -164, -1736, -1507, -3365, -3463, 149, -1435, -2150, -3521, -6225, -406, -3170, -2720, -4769, -4219, -1961, -6516, -2540, -6577, -2608, -4089, -3927, -1720, -5055, -2448, -6214, -2881, -1466, -4495, -3177, -9429, -3814, -2119, -5759, -3814, -12534, -6528, -3036, -9812, -3689, -10526, -6553, -3042, -9873, -3574, -6565, -4625, -3096, -5718, -4258, -5152, -4134, -4078, -4161, -6035, -6267, -5879, -6163, -3441, -8112, -28777, -12534, -7371, -2939, -7687, -5718, -4184, -5502, -2482, -5279, -4031, -2505, -4365, -2140, -3873, -4469, -2521, -4038, -1940, -4416, -4985, -3707, -3850, -1894, -9380, -4234, -6123, -3344, -2119, -5286, -4365, -10210, -3319, -2939, -2799, -6093, -11629, -1542, -2366, -3201, -1569, -4416, -3449, -4104, -8582, -3261, -4230, -2619, -6745, -6103, -6376, -1076, -517, -6343, -3856, -10069, -669, 406, -4238, -4513, -8393, -1117, 415, -2236, -5097, -6565, -1002, -163, -583, -2331, -4003, -1060, -1210, 310, 52, -2735, -2211, -3543, 244, 1264, -3518, -2847, -11945, -851, 1255, -6457, -2040, -2617, -3012, -118, -4021, -2223, -628, -6800, -3540, -2887, -3954, -380, -7708, -12319, -3621, -9695, -1351, -3704, -5306, -4644, -6194, -2843, -1240, -3476, -2776, -2768, -2480, 116, -1819, -907, -1489, -1339, 132, -782, -722, -650, -1144, -1346, -1181, -3271, 1068, -1040, -735, -3378, -1696, 2818, 351, 1279, -1225, 1663, 3821, 1190, 1568, 958, 2741, 4022, 696, -42, 1361, 2391, 3459, -1100, -4774, 352, 804, 2211, -3515, -5247, -1807, -1492, 565, -4606, -4195, -2516, -2778, -787, -3425, -4097, -1961, -2841, -1460, -1834, -3482, -2845, -1598, -2148, -859, -4438, -4997, -460, -4071, -542, -8276, -4112, -56, -11629, -1088, -7730, -2701, -218, -4555, -3319, -5942, -1887, -793, -2879, -7708, -6814, -1078, -1925, -3027, -1839, -8718, -303, -4254, -3383, 105, -4390, 327, -6540, -3496, 557, -1976, 392, -3906, -4262, 150, -1095, -813, -2468, -5879, -665, -1458, -5085, -1777, -7426, -1503, -2954, -4123, -1046, -5429, -2472, -4946, -1647, 120, -3034, -3779, -5367, -1913, 1154, -1711, -2893, -4365, -4352, 1504, -1025, -1050, -4495, -7299, 960, -618, -275, -8582, -4254, -661, -454, -437, -6354, -3367, -3540, -830, -1450, -3110, -4003, -4769, -2076, -3886, -2587, -6194, -4278, -3597, -9064, -3352, -13049, -3964, -2543, -2785, -4863, -9238, -2435, -1218, -270, -6214, -6540, -1810, -726, 1002, -4559, -4795, -2999, -891, 1576, -3117, -3968, -5367, -1825, 1555, -3168, -5031, -3071, -3964, 897, -4464, -6288, -2057, -7819, -626, -4929, -3067, -2863, -9022, -3982, -4134, -1598, -5273, -4703, -6732, -4361, -1378, -7426, -1883, -2803, -5979, -1983, -8615, -586, -1935, -7752, -3830, -6565, -557, -1762, -6814, -10069, -3896, -1704, -771, -6480, -4311, -3276, -2956, 83, -6914, -2112, -4416, -2372, -117, -6388, -2111, -8423, -2065, -1687, -5299, -4238, -8982, -2241, -5319, -4611, -17034, -6321, -1842, -8790, -4021, -4659, -8393, -1534, -7644, -3198, -2781, -8333, -1922, -9193, -2581, -2244, -3954, -2531, -4442, -2851, -2197, -2745, -2833, -1551, -4513, -2659, -2926, -3076, -324, -5906, -4176, -4153, -3098, -378, -4810, -7819, -6565, -2507, -1616, -6422, -6074, -8982, -1713, -4097, -9936, -3455, -8276, -1388, -8827, -3870, -2514, -6914, -2191, -7603, -2986, -2519, -5576, -5326, -3042, -4907, -3140, -5043, -9695, -1066, -11232, -4064, -5502, -5554, -455, -3913, -4738, -6732, -6504, -1077, -2425, -5067, -8060, -8982, -3133, -2677, -5726, -8683, -6278, -3161, -1181, -2789, -5743, -1790, -5607, -4918, -2787, -532, -5055, -4863, -5437, -3438, 1153, -4923, -3968, -2285, -7936, 1457, -939, -1872, -441, -3521, 789, 191, -697, 563, -1176, -606, -186, -867, 711, -702, -1288, -2086, -1765, -68, -1274, -346, -5115, -2460, -1966, -1774, 337, -4664, -3515, -5546, -960, 213, -5793, -6354, -11629, -85, -884, -9873, -9479, -6204, 186, -3551, -5115, -3321, -3644, -237, -8276, -3537, -497, -2560, -1990, -2730, -2142, 1089, -2578, -7752, -346, -1516, 1883, -3474, -1892, 753, -1222, 1911, -5319, -316, 1015, -157, 984, -8865, -1908, 604, -58, -97, -1940, -2442, 101, -2462, 1006, 1032, 1535, 786, -2319, 1736, 2215, 2780, 1759, 652, 996, 2082, 2543, 2055, 1236, -1352, 728, 1643, 1718, 336, -4723, -1878, 1452, 877, -1159, -3218, -5735, 1720, -448, -791, -1093, -4703, 1435, -1644, -20, -108, -2698, 551, -1859, -581, 153, -2569, -187, -2229, -2216, -45, -4238, -26, -2438, -266, -1116, -5888, 353, -1402, 1424, -3571, -3638, 339, -416, 1442, -3114, -2412, -388, 29, 143, -1792, -2065, -2305, 182, -778, -2512, -2000, -5615, 77, -606, -5145, -1980, -4433, -566, -1487, -2422, -2414, -3142, -2107, -2069, -94, -3811, -2821, -5214, -569, 790, -4311, -3101, -15615, 275, 718, -2225, -4644, -5170, 80, -188, -922, -10284, -2774, -1011, -1732, -682, -4545, -1800, -1369, -2178, -1427, -1727, -1899, -487, -1194, -1952, -300, -2926, -540, -804, -103, 464, -2677, -2123, -1423, 1369, 671, -915, -5862, -3334, 1645, 235, -12, -10613, -5853, 708, -1123, -92, -6516, -4258, -1471, -4172, -824, -3896, -3543, -3843, -11115, -1507, -2291, -4420, -4703, -6173, -1923, -1647, -6577, -4532, -5970, -2681, -1674, -8582, -2305, -8333, -3047, -2119, -5615, -1080, -12123, -1630, -2419, -4262, -1087, -5546, -86, -1908, -5408, -1884, -2348, 810, -1678, -9531, -2799, -546, 935, -2883, -3975, -3798, 191, 250, -4024, -1848, -5638, -80, -929, -1782, -1066, -7752, -1378, -1106, -938, -870, -7264, -3433, -510, -1741, -928, -3592, -6540, -792, -4331, -1053, -951, -6928, -2651, -6914, -1189, 250, -3067, -6528, -4254, -1197, 169, -1952, -3933, -3020, -957, -1095, -2309, -1879, -2895, -608, -2228, -3401, -973, -3729, -478, -1579, -4469, -606, -5195, -864, -886, -5247, -554, -5008, -1788, -425, -5584, -799, -2973, -2552, -508, -7146, -1484, -1085, -2841, -1664, -14784, -2701, -54, -4049, -4028, -5970, -4031, -53, -8517, -6194, -4569, -4262, -1013, -6640, -6026, -5109, -3707, -1882, -4089, -3779, -5960, -3417, -1490, -3808, -2288, -5429, -3549, -1206, -4858, -2153, -4810, -3944, -1691, -7113, -3438, -5208, -4191, -3161, -13738, -6411, -7196, -3923, -6828, -7113, -6256, -11781, -3471, -6183, 4555, 15411, 7007, 10967, 10737, 8875, 14992, 7271, 10267, 10109, 10369, 13697, 7163, 7923, 8085, 9998, 11391, 5948, 2320, 4153, 8634, 7948, 3896, -513, 552, 7384, 6331, 2489, 442, 440, 6092, 7580, 1513, 355, -2028, 5616, 7957, -317, 1608, -1364, 6813, 7370, -3060, 1339, 780, 6555, 5815, -2195, 251, 2419, 3138, 3196, 430, 757, 3938, 2245, 1437, 3113, 2371, 5047, 5984, 4148, 4832, 3588, 5594, 6338, 6446, 5374, 4266, 5513, 5190, 7346, 4652, 4298, 4535, 3562, 6799, 2430, 3586, 1997, 2533, 4485, 765, 2135, -1617, 1314, -1242, 1843, 164, 184, -1490, -1172, 1405, -1369, -411, -3232, -1131, -1009, -1508, -4093, -927, -3632, -6332, -879, -4119, -297, -1135, -3237, -139, -2075, -671, 60, -1756, 223, -1356, -2143, -962, -2730, 109, -877, -4718, -7097, -2726, -515, -497, -4759, -2241, 518, -1817, -808, -4890, 893, 1886, -3748, -2483, -9695, 2311, 1818, -3444, -7247, -2799, 3001, 615, -1488, -5037, -1157, 3018, -1370, -308, -2401, -1672, 2199, -2904, -13, -1314, -3766, 387, -2545, -743, -705, -6504, -2024, -1526, -2924, -419, -2208, -3449, -1261, -6943, -254, 319, -6026, -1999, -7865, -143, 1382, -8718, -3133, -8393, -323, 1337, -4769, -3677, -8112, -806, 21, -4592, -3751, -9238, -1176, -3632, -5133, -2502, -7665, -1149, -5827, -5026, -1637, -4664, -1204, -2470, -5615, -2340, -4378, -1817, -2118, -8220, -5686, -7264, -3172, -3140, -8827, -8582, -8718, -4708, -4743, -5710, -4858, -4460, -4912, -4573, -4708, -4764, -3769, -4754, -3563, -5133, -6365, -4748, -5607, -3496, -6469, -7484, -6278, -7819, -3827, -6602, -5623, -5319, -8276, -3227, -5539, -3820, -3603, -6732, -2855, -5306, -2772, -2517, -6411, -3729, -6602, -2637, -1956, -6885, -6973, -8582, -3266, -1771, -7408, -11356, -8827, -3827, -1948, -7583, -5915, -6480, -3744, -2819, -7562, -5247, -4518, -3889, -5292, -7408, -5646, -3441, -4940, -17034, -6434, -5607, -2545, -7687, -5422, -5202, -5189, -2416, -7644, -4067, -4555, -5026, -3543, -5158, -4635, -4703, -4683, -5599, -5026, -6577, -5502, -4583, -6973, -6773, -9873, -6246, -5924, -7730, -6153, -17034, -5960, -8060, -9936, -4800, -7960, -4880, -6628, -14784, -5221, -4759, -4127, -7464, -8138, -7774, -3222, -3846, -6074, -6602, -12776, -2809, -3603, -3208, -6288, -7281, -3203, -3375, -2325, -6615, -5472, -3985, -3417, -2935, -7708, -4880, -4635, -3843, -5189, -9585, -5306, -4821, -5279, -8304, -11356, -6516, -4573, -10704, -5103, -13738, -6016, -3951, -7960, -4046, -14784, -5240, -3594, -5020, -4929, -9429, -5306, -3824, -4250, -7730, -7019, -5879, -4601, -4344, -9479, -5401, -7247, -5853, -5189, -8112, -5312, -9429, -7984, -7050, -6732, -7230, -11629, -15615, -9639, -6267, -6267, -12776, -9106, -8582, -6943, -4573, -8138, -5951, -7264, 8226, 411, 6776, 10899, 8024, 7438, 1696, 6047, 10370, 7498, 4785, 3410, 3550, 8707, 5851, -1383, 4361, 1496, 5573, 3279, -6615, 4550, 3681, 387, 2930, -1050, 4148, 3959, 966, 3766, 2183, 3331, 2484, 2219, 3780, 3329, 2233, -378, 2612, 3424, 3556, 789, -265, 2591, 3346, 2596, 234, -611, 2600, 3792, 1704, 2757, 1456, 3414, 4338, 5176, 4562, 5128, 4379, 4499, 7056, 5170, 6859, 4481, 4032, 7438, 4820, 7148, 3264, 2816, 6602, 3842, 6041, 1187, 666, 4649, 2801, 2942, 2185, -3294, 1847, 2180, -28777, 3045, -6235, -819, 1672, -245, 2564, -3208, -2505, 535, -232, 1386, -2964, -3465, -1451, -786, 438, -2538, -942, -1457, -669, -469, -1540, 1080, -175, -2370, -2226, -1040, 1762, 391, -11488, -4907, -976, 1432, 604, -1869, -5408, -1245, 210, 656, -377, -5487, -1874, -1962, 337, -1040, -7097, -2851, -5836, -747, -4168, -6759, -4504, -9064, -2438, -6163, -4278, -8112, -4473, -1415, -2795, -2837, -5584, -3074, 223, -2270, -2149, -2984, -3286, 756, -3321, -1587, -2331, -5584, 356, -5906, -846, -2378, -12319, -710, -10284, -286, -1996, -5195, -2247, -11629, -341, -776, -3580, -5152, -7644, -1509, 500, -2709, -9284, -4536, -4946, 1008, -1621, -3225, -2841, -2102, 543, -1136, -2386, -2075, 960, -628, -1855, -4500, -2111, 2341, -1690, -4286, -4940, -3112, 2706, -2705, -12776, -2372, -5202, 2177, -4738, -6615, -2807, -4327, 689, -9695, -4295, -5247, -2340, -1011, -6528, -3460, -2610, -1849, -776, -3592, -3482, -1296, -2954, -621, -3225, -4718, -2172, -7335, -1218, -4486, -7644, -6411, -7603, -1245, -5360, -7542, -5576, -4858, -559, -5214, -5630, -3112, -6288, -321, -5202, -4587, -3417, -11945, -932, -4564, -4097, -5286, -6973, -2536, -4307, -4315, -6856, -6692, -5097, -5097, -5240, -5273, -8982, -5353, -7445, -5735, -2914, -10704, -3597, -28777, -4408, -2203, -6885, -2507, -10526, -3301, -3951, -4199, -2107, -9284, -3291, -8034, -2779, -2259, -6928, -4923, -2902, -2630, -2743, -5465, -10899, -2016, -3860, -3331, -5429, -7097, -3391, -6457, -4056, -5346, -5494, -8220, -7842, -4991, -4616, -5422, -6870, -9022, -5253, -5020, -4774, -3920, -17034, -3910, -6602, -3927, -2772, -9022, -2550, -5079, -3441, -2510, -7281, -1973, -3665, -3563, -3140, -6528, -2169, -4028, -3748, -4764, -6553, -2960, -6278, -2954, -6469, -8304, -3717, -7730, -2132, -6103, -14784, -3433, -5678, -2176, -5924, -11004, -2855, -5109, -3339, -6411, -9284, -3042, -5960, -6103, -7019, -9238, -4134, -9106, -14784, -8009, -10362, -5145, -9429, -9873, -10210, -12776, -4853, -5260, -7389, -7842, -9585, -4774, -3644, -6278, -4874, -6870, -5906, -3438, -5576, -3380, -5509, -9238, -4438, -4733, -2918, -5584, -7247, -5979, -3843, -3347, -7464, -4361, -5793, -3266, -4625, -10001, -3638, -5091, 1053, 8110, 8914, 8307, 6042, 624, 7849, 8377, 7697, 6023, 614, 6830, 6761, 5694, 5584, 1187, 4282, 4227, 1468, 3982, 547, -3409, 2171, -3076, 110, -1225, 2598, 2072, -3543, 1042, -665, 4111, 1684, -506, 2658, -964, 3751, -446, 2235, 1984, -7146, 2103, -7936, 2601, -337, 2168, 462, -1580, 2579, 1717, 5343, 1916, 1908, 4177, 4251, 6921, 4386, 3752, 5080, 5244, 7424, 5647, 4202, 4292, 4783, 6883, 5311, 2971, 305, 2614, 5111, 2609, -777, -620, 3635, 1736, -4464, 1146, 2544, 5977, -629, 2458, 2514, 1870, 6709, -634, 3097, 1606, -2359, 6413, -2823, 2131, -1302, -3342, 5643, -7623, 316, -6773, -908, 4793, -5487, -2306, -13049, -1451, 3640, -3151, -4555, -9695, -3574, 1736, -2908, -5234, -6388, -5592, -904, -4759, -9238, -3996, -3723, -2510, -17034, -4274, -2615, -2599, -1828, -5394, -2601, -1887, -1611, -2331, -2945, -3496, -1453, -538, -7752, -2242, -4464, -1450, 44, -1051, -2606, -2166, -1784, 49, 1245, -3773, -1528, -2204, -388, 1328, -4429, -2473, -3158, -1272, -587, -3686, -3594, -5085, -2728, -7081, -2881, -4123, -7408, -5202, -3215, -2132, -5339, -11629, -8982, -1488, -1471, -5031, -4940, -4299, -1189, -1473, -4923, -1805, -1452, -797, -2510, -4010, -677, -91, -222, -4545, -2633, -1019, 204, -349, -6666, -3563, -2386, -385, -1899, -6183, -11356, -1821, -1716, -3036, -4620, -3710, -342, -3817, -531, -4149, -2615, -216, -4386, 781, -4013, -4518, -1874, -2895, 948, -3194, -4010, -6590, -2019, 322, -2008, -1979, -4344, -670, -624, -1414, -2191, -2979, 628, -990, -1710, -4597, -4071, 1114, -976, -3110, -8982, -8754, 807, -1502, -7665, -6914, -7984, -33, -2829, -6045, -7179, -5170, -977, -4620, -2677, -7299, -4336, -1666, -5743, -2254, -6183, -3319, -2350, -5615, -3647, -5853, -2339, -3933, -5539, -7130, -5158, -2069, -8423, -5546, -8903, -4438, -2690, -10069, -4640, -7644, -4403, -4149, -7865, -3586, -7213, -4784, -5494, -12319, -2897, -5686, -4940, -4985, -8485, -2608, -4108, -4847, -4130, -5247, -3027, -3239, -5133, -3940, -4064, -4935, -2950, -6553, -4532, -3683, -10526, -2933, -10613, -5951, -3927, -5735, -3038, -11945, -8333, -5037, -3930, -3433, -7730, -11232, -7146, -3647, -4473, -6016, -13049, -6719, -3629, -6083, -5451, -14195, -4940, -3299, -7960, -6083, -13365, -4331, -3172, -10526, -8304, -17034, -4733, -3843, -15615, -10069, -9695, -6113, -5584, -15615, -9149, -6492, -8220, -7230, -12319, -11004, -5195, -7960, -6123, -6719, -17034, -4759, -6615, -4907, -5043, -9193, -4523, -6376, -3748, -5584, -7644, -4523, -7081, -2651, -7484, -6113, -4698, -8192, -2111, -6640, -4438, -5195, -8363, -2429, -5145, -3795, -6914, -7842, -3843, -4067, -4408, -13049, -7936, -6469, -3840, -5988, -5638, -8718, -8718, -4940, -7708, -3201, -9812, -7936, -7960, -4748, -6653, -4769, -7050, -7603, -6332, -6615, -4513, -7019, -5942, -7299, -6388, -4869, -7774, -4805, -6225, -5879, -5710, -6828, -5429, -5654, -6388, -6590, -4460, -11356, -5879, -8582, -7113, -3680, -5710, -6842, -7960, -7796, -4157, -3375, -7819, -6469, -8333, -5253, -3296, -7445, -6928, -7774, -6528, -4620, -6870, -8247, -6640, -7708, -7445, -6528, -8754, -6153, -8247, -14784, -5844, -9812, -6602, -8009, -11629, -5415, -9753, -8333, -7603, -9193, -5306, -7464, -17034, -7146, -8790, -5554, -5569, -8718, -6786, -7774, -7066, -4482, -5818, -5933, -5569, -8304, -3415, -6064, -4795, -3247, -4890, -1853, -13049, -3291, -1092, -1488, -282, -2670, -1180, 441, 194, 903, 44, 464, 1064, 369, 1400, 853, 1121, 561, -758, 998, 249, 726, -1463, -2859, -374, -1779, -805, -6988, -4679, -2714, -4863, -3757, -5401, -4923, -5784, -5367, -7335, -3383, -5055, -8942, -5374, -6343, -3744, -5951, -12534, -6045, -5638, -5524, -7050, -12534, -6365, -5960, -7730, -6914, -7484, -6516, -7842, -6973, -5879, -5654, -6602, -11488, -6026, -5509, -5085, -6173, -7353, -6602, -5933, -5312, -6045, -6235, -8649, -6422, -6113, -6814, -6928, -11004, -6083, -5888, -8276, -8615, -10284, -5073, -4659, -9380, -8582, -6745, -4238, -4442, -9753, -7865, -4733, -4153, -6083, -9238, -7644, -3954, -4800, -12776, -8582, -6628, -4071, -5686, -9064, -8192, -5079, -4728, -6074, -7464, -8982, -3937, -5189, -5810, -8393, -10613, -3512, -5026, -5509, -11004, -8549, -3954, -5109, -5394, -17034, -7113, -5654, -6434, -5061, -15615, -6666, -9479, -11004, -4438, -11488, -6288, -7353, -9753, -4064, -9695, -6422, -4918, -8485, -4373, -8454, -8060, -4089, -13049, -5408, -8165, -9022, -4226, -6988, -6376, -9331, -6422, -5465, -4482, -6885, -13738, -5623, -8485, -4246, -8276, -10799, -6666, -8718, -5646, -11629, -8423, -10613, -7281, -8363, -13738, -7960, -10899, -9149, -8112, -13365, -8304, -8582, -11945, -6653, -15615, -8138, -9193, -7034, -6235, -11356, -7464, -10069, -5726, -6800, -8615, -7389, -7796, -5743, -8423, -7264, -7774, -6310, -6516, -10442, -7179, -7264, -5776, -7687, -11232, -7819, -6343, -5686, -7445, -9064, -8138, -6123, -5827, -6422, -6870, -7912, -6256, -6278, -6278, -5988, -8165, -6590, -7097, -7004, -6343, -9380, -6745, -8615, -8304, -7562, -11781, -6480, -11115, -10526, -7503, -11356, -6376, -10069, -15615, -7050, -10210, -7353, -7819, -11781, -7960, -9639, -9753, -7162, -10799, -11356, -9380, -10799, -7936, -14784, -15615, -9380, -10284, -10069, -11356, -12776, -8903, -11945, -10210, -8192, -12123, -8903, -13738, -9639, -7130, -8192, -11004, -9380, -11629, -6928, -5853, -11488, -7888, -11356, -7389, -5115, -9193, -8138, -9238, -8790, -5678, -10001, -10362, -9531, -12123, -7230, -11115, -28777, -11356, -28777, -8683, -8903, -10284, -11488, -14784, -8683, -8615, -7960, -10362, -12776, -7984, -10362, -7179, -9380, -11781, -3117, -6870, -7644, -4630, -5247, -3659, -11232, -6016, -7146, -6422, -5561, -12319, -5026, -6457, -8754, -10362, -7130, -4679, -5103, -17034, -5801, -5158, -5346, -5176, -8903, -3801, -4674, -6914, -6842, -6692, -3668, -5195, -7819, -14195, -6719, -4874, -6133, -8112, -8304, -8112, -6288, -6602, -9331, -6054, -8423, -6354, -6093, -8034, -6267, -7774, -6814, -5286, -6899, -7113, -7708, -6842, -4847, -7213, -6045, -7583, -6422, -5103, -6842, -5726, -7066, -7213, -6640, -5437, -7034, -6870, -7708, -13365, -5145, -8790, -6914, -7162, -6928, -5531, -8790, -6153, -6814, -4929, -6054, -6615, -4880, -5055, -5554, -11004, -3296, -2813, -2438, -4230, -4082, -524, -733, -656, -1370, -833, 1182, 493, -67, -185, 223, 1807, 608, -783, -417, -86, 1336, -519, -3058, -2075, -1452, -316, -3094, -6988, -5694, -3417, -3130, -5871, -7603, -7936, -5189, -4963, -6516, -6388, -6885, -6705, -4698, -6299, -4918, -7562, -9812, -4616, -4649, -4348, -8649, -12776, -4518, -4060, -5333, -9695, -10210, -4258, -4344, -9149, -10210, -11945, -4195, -4679, -7796, -9284, -8165, -4912, -4460, -5152, -8009, -5546, -7371, -4035, -4869, -6943, -4532, -12319, -3989, -6074, -6516, -4282, -6343, -4601, -6469, -6786, -4504, -4635, -5759, -4611, -7583, -5133, -4464, -6615, -3751, -8790, -6602, -4790, -6332, -4184, -10899, -10704, -4997, -6365, -6103, -13738, -10799, -6388, -7936, -11488, -12319, -6640, -17034, -13365, -10069, -9812, -5306, -6856, -11004, -7034, -7426, -5008, -4963, -9064, -5646, -5997, -5286, -5465, -6828, -4451, -5710, -6035, -8683, -4754, -3509, -6553, -7389, -11356, -4064, -3194, -8034, -10704, -6842, -4774, -3680, -7162, -13738, -5702, -7213, -5085, -5266, -8034, -5458, -11356, -7371, -4290, -6528, -5444, -11945, -10210, -4258, -6123, -5569, -28777, -9331, -5170, -5836, -6007, -9022, -6958, -6943, -5444, -7097, -6759, -5623, -8903, -5735, -9873, -6480, -5079, -9585, -7644, -10284, -6958, -5103, -9149, -14784, -7019, -6679, -5702, -8034, -9106, -5735, -5554, -6814, -7066, -7353, -5554, -4764, -7708, -6899, -7562, -6332, -4425, -7066, -7353, -8865, -7464, -4455, -6516, -8034, -10613, -6856, -4863, -7004, -8754, -10613, -5836, -5592, -8276, -10069, -8549, -5836, -6153, -9873, -13738, -6732, -6719, -6590, -11356, -12123, -5844, -7603, -7162, -13365, -8165, -5997, -8247, -7752, -10799, -6885, -7389, -9284, -8009, -9106, -7113, -10362, -11488, -8333, -9284, -8718, -14195, -14784, -9380, -10799, -11115, -13365, -11232, -9585, -11781, -10799, -12776, -10284, -8582, -10362, -9331, -13365, -11004, -8333, -9106, -8903, -13365, -10284, -8333, -9193, -9331, -9585, -9380, -8333, -10001, -9936, -7730, -9429, -9238, -8942, -10069, -7523, -8649, -11004, -8247, -9331, -8754, -8454, -12776, -9380, -8220, -11629, -10799, -28777, -14784, -7583, -11356, -14784, -11488, -13049, -8086, -9531, -9022, -9380, -11356, -10899, -9064, -7562, -9873, -7081, -9429, -2805, -8718, -6899, -6800, -10899, -4226, -6653, -7179, -5718, -8827, -8517, -5401, -9193, -5638, -6480, -7034, -4518, -9531, -6133, -4946, -5306, -3804, -6246, -6732, -3830, -5759, -3444, -4527, -5933, -3014, -8192, -3485, -4344, -4138, -2827, -9238, -4056, -5387, -3203, -3523, -5915, -5480, -7162, -3352, -5152, -4282, -6565, -10442, -4649, -6958, -3316, -5437, -11232, -6943, -7665, -2574, -4592, -7081, -7213, -7445, -2163, -4395, -6492, -6376, -7113, -2312, -4460, -8276, -7583, -7146, -3191, -4578, -28777, -8790, -5801, -5183, -4559, -9193, -6885, -5127, -12776, -4545, -6516, -6828, -4769, -5292, -3920, -3900, -3447, -1899, -1621, -1802, -1198, -706, 111, 92, -225, 391, 418, 753, 503, 157, 682, 253, 191, -422, -702, -432, -1141, -1561, -3304, -2975, -3615, -3853, -4532, -7603, -6759, -10284, -7503, -7389, -4901, -7426, -4688, -12123, -7623, -5458, -6928, -3546, -10613, -7299, -9238, -8086, -3482, -7196, -6800, -9106, -11356, -4053, -6469, -6434, -7130, -11356, -5531, -7503, -7353, -7247, -7066, -7752, -11488, -11232, -8903, -5576, -7196, -9380, -11004, -9064, -6153, -6267, -7464, -9380, -5638, -9531, -6225, -8903, -11488, -3592, -10704, -6153, -28777, -9585, -2642, -10069, -5678, -8582, -7179, -2483, -12123, -5516, -8393, -6615, -2912, -6376, -5818, -11945, -7562, -3879, -4323, -6388, -8865, -10704, -4912, -3876, -6553, -7426, -8982, -4774, -4555, -6332, -8034, -6354, -4115, -6399, -6540, -7130, -5592, -4075, -10069, -7774, -5374, -6103, -4640, -10799, -10284, -4985, -7281, -5751, -7888, -12776, -5670, -8138, -7542, -7113, -11488, -5853, -7819, -9531, -7888, -11945, -5008, -7281, -9022, -8615, -28777, -4774, -7371, -7912, -7445, -11115, -5810, -8276, -7213, -6773, -7960, -8615, -10899, -7179, -6565, -6035, -15615, -10442, -8060, -6204, -4759, -15615, -7113, -9873, -6083, -4153, -9429, -6376, -10210, -6422, -4447, -7213, -7960, -10138, -6504, -6074, -6194, -10362, -11232, -5960, -10442, -5234, -6786, -9429, -5630, -12319, -4597, -5768, -7179, -5979, -10799, -4912, -6133, -6026, -7196, -12123, -6376, -6133, -5743, -9380, -8086, -8865, -5415, -6343, -11004, -5793, -9695, -5176, -7583, -10442, -4935, -8423, -5164, -8220, -9531, -5127, -8247, -5164, -7936, -8333, -6310, -9380, -5702, -8333, -6988, -8582, -10704, -6973, -8192, -5897, -12534, -9873, -8485, -7004, -5561, -28777, -8549, -9331, -6800, -6225, -12534, -7888, -10526, -8247, -7281, -11232, -7888, -14195, -11781, -7162, -17034, -8517, -28777, -10704, -6885, -10613, -10001, -17034, -8754, -7196, -8009, -11232, -11004, -8247, -7708, -8247, -8683, -8165, -8790, -7796, -8582, -7162, -7247, -8549, -7687, -6602, -6943, -7796, -7730, -7730, -5784, -7730, -9064, -7936, -8165, -6577, -9429, -8333, -9106, -9936, -9380, -11781, -7066, -10069, -11115, -14195, -11356, -6602, -9429, -7247, -8982, -9429, -6653, -8903, -5735, -7984, 10044, 12648, 12998, 9252, 6231, 9325, 12187, 12390, 8700, 5681, 6793, 10765, 10421, 7132, 3998, -1825, 8281, 6402, 5122, 1148, 3219, 4758, 1900, 3557, -2152, 4456, 1711, 3145, 2012, -3412, 3991, 1942, 1400, 204, -5079, 2605, 2961, -1604, -3856, -5020, 1397, 3208, -3417, -3557, -71, 1218, 2542, -2979, -39, 2241, -2135, 353, -2745, 1046, 3469, -1404, -6856, -1711, 2768, 4068, 1609, 1799, -53, 4306, 4109, 1189, 4070, -76, 4861, 3454, 671, 4427, -2467, 4441, 2259, 1918, 3028, -3788, 3064, 2550, 1989, -1738, -1385, 411, 3822, 681, -1108, -1853, -4693, 4093, -654, 1442, -5979, -2592, 3171, -213, 1945, -4064, -520, 1371, 312, 1726, -2731, 491, -451, 514, 673, -4172, 1095, -4067, 545, -219, -3140, 1267, -3468, 233, 1160, -1015, 1002, -20, -487, 2224, -2, 267, 293, -1090, 2237, 417, -1484, -1315, -949, 1348, 442, -6399, -5152, -560, -150, 79, -6399, -4038, -1063, -1862, -811, -3961, -1042, -3078, -3600, -2512, -4491, 588, -1589, -6153, -4420, -6528, 1425, 177, -5374, -5133, -10284, 1468, -12, -1979, -4847, -6480, 442, -2155, -888, -3274, -3468, -2145, -4403, -1535, -3281, -1610, -2664, -1884, -3529, -7004, -258, -546, -685, -5539, -6235, 641, 7, -525, -6856, -3087, 948, -599, -815, -3659, -3047, 583, -2345, -1077, -2153, -5145, -396, -6235, -1402, -2756, -7162, -1909, -5979, -2105, -3910, -4583, -3996, -3094, -2743, -1780, -4957, -5085, -2401, -2268, -343, -15615, -4616, -2809, -1703, -181, -4509, -5380, -3105, -1949, -1173, -2628, -6235, -2039, -3087, -3465, -2982, -5509, -391, -4491, -8060, -4035, -5827, 967, -4918, -9331, -3944, -7796, 1574, -4774, -3798, -3540, -9429, 1143, -5394, -1564, -3490, -6064, -731, -7752, -671, -3748, -3551, -3738, -5437, -746, -3889, -2417, -1854, -2714, -1722, -3521, -2465, -738, -1511, -3910, -2918, -3286, -1072, -1174, -8060, -2807, -4382, -2477, -1487, -7464, -3817, -6016, -4826, -2521, -5726, -6679, -8034, -7542, -4395, -5539, -10526, -12319, -6828, -5979, -6256, -6480, -6123, -4918, -5584, -5862, -3933, -2470, -4038, -4816, -4071, -2659, -1201, -4303, -4592, -2883, -2589, -1456, -5793, -6035, -2460, -4028, -3042, -7984, -11781, -2988, -7230, -5751, -8138, -4491, -5227, -5043, -7865, -7523, -2336, -6590, -3916, -6553, -7426, -1857, -3170, -5299, -5031, -7230, -2367, -1790, -10362, -4985, -6054, -3674, -1497, -7583, -6204, -4935, -6256, -1909, -7162, -5751, -4733, -6225, -2686, -10001, -4097, -5646, -3695, -2793, -28777, -3757, -8649, -2722, -1804, -11232, -4800, -7984, -2733, -812, -9695, -4464, -4357, -3196, -222, -9936, -3005, -3025, -3399, -19, -6719, -3529, -2975, -3094, -215, -4831, -8060, -3659, -3218, -1018, -4541, -4097, -3975, -3947, -2937, -4491, -1958, -3487, -4134, 7316, 10225, 10623, 7748, -1098, 6444, 9621, 10019, 6996, 330, 3271, 7799, 8140, 4473, -135, 1316, 4928, 4844, -755, -2958, 3602, 1795, 905, -1315, -4578, 3296, -1449, -120, -2182, -543, 2161, -5133, 69, -4108, 879, 2607, -1265, -838, -5164, 1283, 3323, 2438, -72, -4365, 1191, 3383, 3844, 822, -5299, 1048, 2823, 4299, -288, -2566, 1369, 1264, 4253, -757, -248, 1858, -2958, 3479, 1529, -219, 1962, -613, 1344, 2185, -1117, 1743, 2218, -4821, 1460, -1255, 1702, 3058, -2541, 806, -793, 2155, 2695, -548, 1142, 382, 2651, 1144, -873, 1061, 1030, 2641, -1772, -2039, 567, 433, 1850, -1000, -2305, 388, -1616, 94, 759, -1155, 220, -5524, -2779, 1119, -359, -388, -10899, -3128, 900, -437, -1029, -9149, -1604, 812, -1352, -970, -4518, -1346, 688, -3425, -397, -1838, -1963, 276, -4455, 54, -450, -2752, -201, -922, 230, -180, -3003, -514, 990, 258, -1194, -2776, -737, 1673, -29, -3391, -3191, -772, 1287, -1143, -2430, -5487, -663, -184, -3641, -919, -10704, -869, -2573, -9695, -833, -5286, -739, -4790, -5662, -1888, -3846, 539, -5654, -2054, -3289, -4486, 1249, -8009, -517, -4003, -6640, 580, -10442, -43, -6183, -2065, -2142, -4805, 189, -6194, -122, -14195, -3130, 952, -2241, -240, -3769, -2325, 2173, -986, -2333, -2605, -1918, 3172, -964, -2885, -3222, -2003, 3383, -1800, -835, -3850, -2724, 2442, -3811, -587, -2578, -3824, -47, -4564, -2234, -1983, -3083, -1844, -2789, -8276, -2234, -1771, -329, -2622, -4606, -2673, -1662, -251, -4112, -2457, -3860, -3425, -1346, -7371, -2355, -6083, -7196, -2443, -11781, -3168, -4929, -2754, -1961, -9331, -3760, -4238, -1298, -1088, -6083, -3130, -5299, -1543, -916, -4344, -2309, -6457, -2969, -1777, -3951, -2170, -5145, -5394, -3850, -4348, -2918, -3509, -9695, -6016, -4991, -4784, -2406, -9022, -5451, -6602, -8138, -1928, -5480, -5387, -6235, -10362, -1952, -4592, -6278, -2902, -7523, -2291, -5599, -5960, -1404, -4907, -2952, -6480, -5121, -990, -3817, -4327, -4968, -5286, -1119, -4254, -7687, -4957, -6457, -1582, -5055, -12123, -7371, -8086, -2442, -4067, -6973, -15615, -8423, -3707, -3422, -5871, -8304, -7050, -5183, -3773, -5516, -5437, -6267, -7888, -4573, -5451, -3518, -7179, -9585, -4837, -5408, -2683, -9380, -3714, -4545, -5844, -2918, -5599, -1799, -4779, -8649, -3846, -3863, -1524, -6225, -8165, -3985, -3600, -2374, -8718, -4541, -3449, -4021, -3447, -9149, -3344, -3635, -4630, -3937, -9639, -3329, -4564, -5818, -4795, -7162, -4089, -4616, -6469, -5776, -4067, -5221, -3886, -4378, -4028, -2320, -5897, -4134, -3110, -2399, -1634, -5801, -5662, -2855, -1746, -2036, -5458, -9531, -2724, -1821, -3624, -4003, -7113, -1902, -2417, -5615, -2626, -3698, -1022, -3235, 2765, 10743, 11015, 7835, 5167, 2573, 10288, 10453, 7230, 4978, 1899, 8926, 8676, 5477, 4404, 431, 6717, 5342, 2971, 3601, -2510, 4089, 826, -759, 2738, -1116, 2331, 280, -2247, 1585, 1335, 1862, -849, 2278, 958, 2037, 1137, -1499, 3142, 1914, 2121, -359, -1606, 2056, 2766, 2493, -1087, -3067, -531, 3083, 2981, -162, -2845, 1494, 2837, 3208, 1678, 256, 2898, 1355, 2995, 3017, 1510, 2431, -5353, 2078, 3266, 983, 412, 1537, 495, 2329, -2220, -1382, 4611, 45, 753, -3692, -1259, 6111, 41, 850, -150, -1056, 6663, -1833, 1379, 313, -442, 6245, -1875, 1210, -688, -234, 4738, 1059, 939, -2566, -954, 2413, 2204, 1007, -4013, -2999, 1451, 2071, 1366, -3296, -7984, 1487, 869, 1630, -1712, -3840, 921, -915, 1398, -1065, -1305, -226, -2019, 816, -2412, -412, -1913, -2990, 328, -8865, -255, -3626, -5214, -124, -1636, -262, -8009, -10138, -168, 335, -17, -4482, -14784, 497, 609, 795, -1324, -17034, 752, -8, 1509, -1330, -7583, 127, -1352, 1536, -3714, -3417, -922, -4438, 861, -2962, -956, -1306, -9695, -311, -1326, 369, -1134, -4601, -2112, -830, 420, -911, -6376, -5164, -172, -1578, -598, -4880, -1971, 136, -5286, -43, -182, 497, -448, -712, 141, 1578, 1353, -1463, -152, -869, 1793, 1056, -1937, -2879, -3883, 367, -338, -2367, -7353, -7230, -3760, -2299, -3354, -2711, -7644, -1205, -1284, -5008, -3989, -10210, 633, 187, -4754, -7335, -4127, 682, 458, -2353, -3213, -2992, -90, -576, -1166, -1239, -3876, -1210, -2589, -1417, 41, -6577, -3225, -1869, -3316, 408, -13365, -7353, -451, -3827, -439, -9238, -4060, 7, -1758, -2403, -5844, -2334, -20, -1021, -2962, -4555, -2334, -169, -989, -2364, -4046, -3504, -466, -932, -3279, -3856, -5735, -1293, -626, -6565, -4161, -12534, -3003, -228, -8649, -4386, -7066, -3961, 29, -5592, -4071, -4536, -2517, -22, -4327, -4258, -4885, -1637, -541, -3723, -5097, -5494, -1446, -1642, -3689, -5678, -3083, -1635, -3085, -4115, -6064, -1838, -2204, -3523, -4100, -7371, -1822, -2881, -3096, -3833, -11004, -2730, -2391, -2975, -4250, -11115, -4578, -1473, -3105, -5784, -8982, -8060, -1479, -2754, -8138, -9284, -10899, -2883, -2100, -8754, -4425, -7583, -5097, -2042, -6870, -2015, -5121, -3005, -2716, -3999, -1423, -3546, -1384, -3054, -2741, -2403, -3342, -965, -2557, -3194, -4880, -5253, -1343, -2505, -4606, -4733, -11629, -2238, -3184, -4307, -3326, -5139, -3401, -4395, -3393, -2979, -4038, -4601, -6163, -1689, -2849, -4784, -5818, -7335, -26, -2541, -5776, -6577, -5260, 622, -2262, -6278, -6173, -4270, 176, -2344, -8485, -4395, -5164, -1242, -3154, -9064, -2849, -8034, -3225, -4912, -4940, -2698, -8034, -4611, -5646, -3286, -5240, -7665, -2419, -6615, -3482, -1846, -3281, -626, -3304, -2130, -2175, -3569, -105, -1262, -1182, -2008, -3566, -743, -1087, -1198, -1819, -3225, -2300, -2635, -2576, -1603, -3257, -4060, -7146, -3626, -1013, -4438, -5437, -7936, -2214, -312, -9238, -7708, -5997, -2372, -132, -4957, -6666, -6958, -5862, -837, -2285, -3566, -10613, -5049, -2419, -1986, -1772, -13365, -1771, -3680, -3837, -688, -7752, -1085, -3624, -5906, -101, -5844, -1654, -3683, -2975, -80, -5067, -3108, -4336, -2094, -818, -3653, -4071, -4399, -2458, -2770, -2002, -2608, -3158, -3163, -8423, -1108, -1685, -2458, -3751, -6204, -1100, -2282, -2364, -4010, -3210, -1825, -4769, -1646, -3237, -2445, -2762, -5240, -595, -1689, -2711, -3840, -3751, -258, -376, -3744, -6745, -4738, -699, 97, -5367, -9812, -10613, -1406, -557, -6256, -3866, -7796, -1864, -2613, -5008, -1892, -6528, -2502, -5915, -3961, -1087, -9585, -4365, -5387, -3766, -939, -8549, -9753, -3092, -4323, -1217, -6153, -8827, -1828, -5444, -1731, -6246, -7984, -1501, -6745, -2312, -6492, -7230, -1312, -7335, -2475, -4923, -5374, -1098, -7081, -1852, -3586, -4395, -1695, -7842, -1203, -3354, -3992, -3412, -9873, -1341, -4654, -5026, -4382, -8982, -2635, -8649, -8247, -4403, -9022, -4907, -10799, -5801, -6434, -11004, -4858, -9284, -4644, -13049, -8086, -3537, -8060, -5623, -10526, -6469, -3049, -6173, -8683, -28777, -5607, -3119, -4968, -28777, -9753, -5273, -3900, -4161, -13049, -8276, -5437, -6540, -3833, -11232, -5214, -4831, -10526, -3760, -8517, -2564, -4592, -6814, -3386, -5818, -1433, -6528, -7317, -2829, -4082, -1436, -14784, -11945, -2726, -3085, -2257, -8582, -11488, -3365, -2514, -3656, -10799, -11629, -4482, -2470, -4985, -8333, -28777, -4611, -3554, -4597, -5319, -12319, -4361, -7730, -3785, -4858, -13738, -5026, -6773, -4104, -5408, -8942, -5784, -3362, -6615, -5768, -6214, -5451, -2619, -12534, -6026, -5221, -5127, -3054, -5415, -7130, -4951, -5319, -3954, -3927, -8220, -4940, -6590, -3920, -4246, -7936, -5333, -8549, -2853, -6759, -7888, -7213, -6553, -2364, -12319, -5801, -28777, -4863, -3415, -5576, -3668, -6759, -3641, -8517, -3741, -2813, -4764, -2541, -5615, -2982, -3177, -4518, -1999, -2945, -2505, -4918, -4963, -2257, -2580, -2165, -9429, -5158, -3309, -3096, -2128, -11488, -5020, -4929, -3529, -2610, -7960, -5189, -5615, -3927, -3827, -8517, -6204, -4460, -4718, -5678, -13365, -8827, -3455, -5623, -7389, -11945, -13738, -3135, -6388, -9429, -9753, -9479, -3319, -7644, -7503, -10138, -7752, -3583, -10442, -4723, -11945, -7562, -3635, -28777, -3735, -17034, -8517, -3804, -9585, -3906, -12319, -9639, -4282, -7247, -4640, -9531, -9022, -4042, -5942, -5437, -8363, -8582, -3038, -4912, -6492, -7774, -7774, -2550, -4207, -8060, -7335, -7019, -2895, -4024, -10362, -7603, -7936, -4172, -4532, -14195, -9812, -13365, -6786, -6153, -9380, -6365, -2564, -2516, -966, -3968, -5607, -4513, -2347, -2244, -4991, -3339, -8304, -2545, -4968, -7317, -2173, -4764, -3215, -5097, -14784, -2146, -4278, -5037, -4323, -9812, -2937, -6054, -9479, -3662, -8903, -4408, -4728, -9936, -2453, -8827, -7034, -2265, -7426, -2132, -5429, -4929, -1286, -6422, -3182, -3776, -2223, -1296, -5888, -5502, -3196, -1202, -1811, -5793, -6256, -2943, -1328, -2093, -6480, -6133, -2835, -2396, -2184, -7162, -8754, -2781, -4199, -3110, -4028, -12123, -2592, -5638, -5630, -1975, -6759, -2487, -4837, -4847, -1230, -5487, -2758, -3999, -2492, -1394, -4138, -3523, -4718, -1697, -2239, -2191, -4935, -10138, -2014, -3671, -654, -8112, -5951, -3362, -6074, 198, -10284, -3029, -5531, -11629, 268, -4164, -2677, -5743, -12319, -477, -2062, -4038, -4640, -8333, -1868, -1537, -4963, -4060, -6422, -3038, -2447, -3910, -3110, -5240, -2929, -5164, -4550, -2166, -3957, -2080, -7819, -8649, -2393, -3112, -1543, -4907, -7004, -4748, -3357, -1671, -2475, -4649, -12776, -5079, -2528, -1033, -4278, -4123, -8942, -3893, -933, -4640, -2488, -5561, -3583, -2696, -4805, -2419, -3087, -2260, -9639, -4344, -3094, -2082, -1644, -3624, -3923, -3018, -2107, -1825, -1752, -4046, -2219, -3201, -2922, -1724, -4821, -1952, -5584, -5726, -2803, -5871, -2374, -6679, -8138, -4718, -6183, -3114, -5286, -4795, -6773, -5158, -3580, -4759, -3337, -8304, -4242, -3420, -3222, -2967, -9873, -3468, -3083, -1514, -3916, -8942, -2737, -3196, -851, -7213, -7371, -2628, -4290, -1397, -8220, -5031, -3441, -6565, -3518, -8517, -2924, -5306, -7623, -9639, -7936, -2083, -6666, -7730, -7623, -4199, -2509, -3910, -10526, -5871, -3420, -3331, -2225, -5279, -6113, -4307, -3147, -2053, -2893, -7335, -5879, -3314, -3463, -2398, -8393, -6870, -4980, -7542, -3314, -5915, -7484, -8683, -11115, -5979, -4420, -10442, -15615, -7389, -12319, -4319, -9695, -10284, -6973, -5924, -5227, -5862, -5997, -7162, -3720, -6615, -5133, -4323, -6786, -3023, -7230, -5853, -4336, -5623, -3650, -7179, -7730, -5115, -4974, -5862, -7687, -13049, -4153, -5818, -5997, -8247, -10210, -2795, -8754, -3618, -5836, -6928, -2115, -6332, -2590, -3686, -6343, -1878, -4246, -2450, -2675, -7371, -1699, -4067, -2889, -2369, -11004, -1353, -5678, -4017, -2450, -11781, -1020, -12123, -6745, -2751, -8247, -1076, -6615, -8165, -3114, -7426, -1890, -4056, -4616, -3412, -7960, -4046, -3571, -3707, -3883, -8485, -10069, -4754, -4386, -5079, -6786, -5662, -8423, -6732, -7865, -4957, -3373, -7281, -14195, -9753, -3906, -2778, -5152, -8982, -5784, -3501, -3058, -4748, -5853, -3961, -3641, -3707, -4429, -4616, -3227, -4086, -4274, -3487, -4587, -3154, -4559, -4918, -2617, -5735, -3507, -4880, -6074, -2248, -8034, -4307, -5109, -7335, -2512, -9064, -5924, -5292, -8086, -3463, -8276, -8754, -5502, -7299, -5170, -8393, -9639, -6204, -5646, -5638, -4606, -2845, -6278, -11115, -8718, -5008, -3045, -1236, -9106, -4946, -4323, -2920, 372, -6540, -2630, -1996, -2108, 535, -6123, -2531, -1262, -1384, -353, -4842, -3879, -2378, -1149, -2111, -3078, -3910, -5561, -1536, -4319, -2291, -2204, -4134, -2692, -6288, -2541, -1237, -2711, -4199, -8649, -3375, -1152, -2827, -4142, -11004, -3729, -1662, -3744, -3720, -5176, -3523, -2288, -5599, -4286, -2929, -3856, -3194, -7960, -5988, -2138, -5387, -5710, -4963, -10362, -2385, -6492, -28777, -3114, -7299, -3850, -3624, -7146, -2550, -4644, -7583, -1693, -6800, -2875, -4097, -5286, -1039, -9064, -4064, -3615, -2458, -1752, -12319, -6679, -1793, -1298, -4336, -5888, -8165, -202, -1070, -6828, -3449, -5686, 616, -1634, -4664, -3074, -4821, 710, -2984, -5145, -4810, -4425, 164, -4664, -10899, -8192, -5014, -985, -3856, -6870, -4464, -8790, -2733, -2241, -4433, -2904, -8485, -4890, -1319, -4754, -2799, -5561, -6399, -1020, -7264, -3626, -5360, -7730, -1508, -9812, -4946, -6113, -9429, -3215, -8827, -5924, -7984, -5502, -6692, -9284, -6480, -12123, -3989, -5387, -8649, -6786, -8247, -4985, -3609, -6653, -7562, -6267, -9695, -3594, -4460, -9106, -5487, -4013, -5662, -3119, -5726, -5670, -2075, -11781, -2709, -2931, -7004, -1868, -4805, -2964, -1551, -6422, -2709, -2941, -3504, -1157, -4134, -4464, -2254, -4161, -1587, -3487, -7317, -2155, -4810, -2900, -4460, -8754, -2803, -4826, -5751, -6590, -7146, -3889, -4504, -28777, -7213, -5768, -3692, -5085, -5933, -5906, -4532, -3161, -6653, -3729, -3814, -3504, -3971, -7623, -2557, -2758, -2924, -7081, -8112, -1713, -3179, -2924, -6705, -8790, -1219, -4863, -3566, -3968, -9149, -1239, -4611, -5158, -3357, -9380, -1735, -3342, -9106, -4344, -7353, -2398, -3518, -9380, -6943, -5654, -3014, -5561, -6321, -6064, -4365, -3944, -12319, -5710, -4611, -3526, -5710, -8485, -5444, -5312, -3474, -8549, -7004, -4395, -10899, -4382, -14195, -5539, -3729, -6007, -6354, -14784, -3732, -4262, -2947, -6988, -12776, -3108, -6504, -2071, -4940, -7665, -3644, -11629, -2495, -3804, -4541, -4748, -8903, -4082, -3624, -2947, -5152, -7752, -6973, -3900, -2166, -4416, -7146, -10899, -4112, -1940, -3644, -6016, -8138, -4644, -2419, -3853, -5524, -5319, -6492, -3795, -5810, -5997, -4053, -8754, -5933, -13738, -7542, -3896, -6299, -6828, -6093, -10899, -4455, -5353, -5145, -3837, -17034, -5253, -5710, -3860, -3184, -9812, -6399, -6705, -3479, -2956, -7936, -8865, -7146, -3964, -2407, -7371, -14195, -5979, -5208, -2008, -7484, -10899, -5109, -7162, -2302, -7603, -8903, -5214, -10001, -3428, -6480, -8060, -5584, -11781, -5654, -5227, -7335, -5408, -15615, -7865, -4858, -6204, -5176, -8304, -5214, -5751, -5043, -5266, -4963, -3804, -8718, -4153, -5292, -3769, -3951, -8034, -3407, -4951, -3840, -5702, -5091, -2760, -4688, -4616, -10442, -4168, -2538, -5170, 2924, -234, 1360, 6807, -8942, 2066, -2370, 4384, 6357, -5810, -141, -2316, 6118, 5078, -3900, 1102, 864, 6272, 3574, -2939, 2871, 2029, 4982, 2947, -2191, 3429, 2929, 1313, 2390, -2148, 2957, 3148, -353, 643, -5437, 1123, 2033, 3041, -4403, -2204, -4885, -1104, 3754, -2053, 1954, -1183, -6719, 3043, 205, 3676, 1865, -4172, 491, -267, 4413, 2821, -3653, -7752, -1049, 4868, 2344, -1888, -199, 1694, 5207, -359, -9, 972, 3120, 5050, -1632, 595, 83, 3046, 3874, 1955, -1268, -1515, 1653, 578, 2733, -2034, -634, -75, -912, 1786, 2552, 214, 1121, 2255, -864, 3972, 473, 2128, 2530, -2273, 3661, 640, 1934, 1253, -825, 1861, 457, 1079, -446, 292, 123, -219, 514, -4874, 1881, 460, -1259, 630, 63, 3071, 42, -3388, 1278, 3589, 3387, -516, -9639, 1572, 4619, 2800, -265, -1659, 633, 4027, 1366, -817, 320, -2517, 1686, -799, -2762, 270, -7665, -3930, -3968, -4713, -1864, -3692, -3304, -8718, -6299, -8363, -1474, -2526, -3249, -5234, -3128, 612, -2094, -1855, -1449, -2152, 1371, -497, -3147, -19, -3518, 798, 62, -7562, -156, -7317, -391, -900, -2639, -1790, -4858, -388, -3518, -1365, -3726, -2659, -173, -2541, -1549, -2762, -1254, -1080, -837, -1402, -3177, -87, -3883, -672, -1136, -3546, 612, -14195, -1556, -2185, -1011, 683, -5189, -3092, -3299, -127, 255, -4810, -4674, -1074, -408, 469, -5158, -5810, -458, -152, 1380, -2644, -7730, -1654, -81, 1634, -864, -9193, -1208, -2163, 1154, -51, -2672, 674, -4991, 832, 155, -175, 1435, -1433, 1013, -131, 761, 1314, -1182, 998, -1065, 724, 444, -1811, 564, -3135, 65, -1033, -1320, -218, -5221, -1064, -2295, -1850, -1008, -2359, -3001, -2817, -4985, -1698, -306, -5472, -3717, -3147, -3766, 626, -2825, -5915, -875, -8517, 689, -1373, -9695, -643, -1522, 110, -1799, -10284, -1952, 328, -645, -4550, -8393, -5158, 462, -1073, -10704, -4880, -6958, -523, -1486, -3526, -2364, -4800, -1611, -3433, -1904, -806, -4017, -1034, -5607, -2280, -95, -3671, 811, -744, -5607, -347, -3247, 2261, 644, -6480, -1863, -3210, 2734, 110, -1799, -5103, -4810, 2098, -2285, 184, -4659, -28777, 205, -6692, 1041, -2109, -4049, -3264, -9531, 934, -473, -1838, -10704, -5037, -22, 605, -915, -4630, -2875, -1556, 1152, -403, -688, -2859, -2705, 1070, -564, 939, -4733, -2610, 57, -1773, 1155, -6814, -2105, -2377, -3521, 70, -4006, -1277, -6842, -3920, -2624, -2128, -785, -7230, -2054, -4800, -1131, -268, -5480, 427, -2743, -550, 863, -1591, 1982, -1959, -690, 1399, 994, 2627, -2102, -2931, 751, 2205, 2455, -2624, -3235, -981, 2081, 1425, -2661, 732, -2168, 111, -357, -1579, 1804, -2049, 4113, 8691, 7936, 8773, 6012, 3561, 8072, 7149, 8102, 5618, 2114, 6090, 4494, 5874, 4286, 385, 2467, -1467, 1335, 1442, 105, 335, -1512, 891, -3557, 1448, 19, -294, 1187, -653, 1670, 457, 2284, -59, 86, -162, 3511, 3895, 1882, -446, -6310, 5241, 4882, 3950, -804, -1085, 5595, 5534, 4332, 72, 356, 4540, 5713, 2430, 2068, -210, 2264, 5244, -849, 3407, -2129, 3099, 3913, 3563, 3660, -2831, 4469, 1707, 4593, 2972, -179, 4352, 1895, 3800, 1685, 2669, 2937, 3096, 1376, 261, 4384, 420, 2850, -1704, -616, 4854, -2821, 1300, 224, 367, 4011, -3808, -1286, 1808, 2210, 2310, -734, -2758, 2566, 3511, 3004, 259, 414, 3084, 3724, 3945, -255, 2119, 3767, 2385, 3371, -1544, 2519, 4192, -706, 1226, -2429, 2071, 3811, 1582, 282, -1773, 1347, 2525, 3374, 1664, 379, 898, 1309, 3933, 1804, 2168, 288, 1062, 3877, 646, 3217, -1270, 233, 3216, -1975, 3667, -4164, -1948, 1802, -2098, 3631, -8333, -6113, 150, 474, 3106, -8790, -8220, -278, 1453, 1924, -3837, -2977, -114, 1011, 19, -2664, -1399, 94, -1305, -645, -4176, -949, 577, -9064, 109, -5988, -689, 1392, -3321, -468, -1586, -771, 2221, -2843, -2881, 62, -2235, 2652, -4847, -3319, 490, -8304, 2491, -3296, -2752, 628, -4119, 1624, -1343, -3792, 1106, -1913, -182, -769, -3468, 1773, -1367, -3732, -871, -2650, 2176, -909, -5394, -1065, -2475, 2162, -896, -2016, -1130, -4299, 1644, -2359, -556, -1455, -6422, 532, -5037, -201, -2679, -824, 28, -2585, -882, -4451, 369, 777, -1683, -2733, -3365, -473, 747, -3401, -5387, -1928, -1848, -261, -6692, -6365, -1282, -987, -1277, -1773, -4270, -1254, -573, -2485, -30, -2253, -1887, -1288, -5897, 664, -1411, -4299, -3025, -8718, 914, -1321, -6528, -4620, -6973, 688, -1803, -1524, -3971, -5121, -178, -4003, -500, -3689, -2490, -1697, -8112, -1699, -3574, -1091, -3811, -2169, -4250, -3142, -530, -6928, -593, -4357, -3040, -547, -7842, -284, -8138, -3349, -1001, -5195, -504, -3089, -3996, -1679, -4620, -1564, 149, -5561, -2452, -6064, -5333, 1287, -5960, -3624, -12534, -6640, 1418, -2448, -5915, -6133, -2910, 947, -686, -5979, -2606, -2756, -117, -344, -3409, -751, -4266, -2165, -1087, -2391, 30, -7960, -4119, -1837, -1825, -57, -11356, -3225, -1303, -1099, -336, -8549, -3779, -1152, -668, -39, -9022, -8517, -2114, -534, 504, -3420, -7484, -3543, -1040, 1034, -1859, -5415, -3301, -3321, 1024, -2789, -4985, -1226, -3566, -591, -7281, -2912, 223, -1232, -11781, -3479, -1176, 639, -825, -757, -1218, -333, 583, -482, 1616, -476, -729, 900, 508, 2382, -451, -3326, 1327, 1147, 2418, -949, -4473, 1318, 1271, 1921, -2132, 6050, 7975, 8032, 3262, 3201, 5282, 7235, 7407, 4445, 2276, 2882, 4845, 5384, 5737, 1543, -1581, 449, 1204, 6321, 2762, -4365, -1218, -3344, 6202, 1952, 697, 1027, -807, 4913, -3001, 1699, 2207, -634, 394, 156, 1344, 1875, -264, 1794, -994, 1845, 390, 450, 4710, 1510, 2609, -843, -70, 5194, 4848, 2799, 63, -4254, 4680, 5567, 2411, 370, -2308, 3521, 5001, 1114, -894, 1299, 1143, 4606, -326, -3257, 2247, -1267, 4612, 1278, -6666, 1843, 1748, 4153, 2514, -7819, 240, 2820, 3522, 2479, -2283, -3457, 2246, 3871, 1252, 316, -4963, -251, 4898, -861, 2145, -449, -4184, 5257, -1712, 3381, 1314, 194, 4585, -2030, 4337, 2095, 1821, 3929, -4491, 5204, 2646, 2246, 5191, -8220, 5754, 3360, 2008, 6461, -3023, 5697, 3878, 1433, 6915, -40, 4936, 3757, 724, 6530, 1680, 3604, 2780, -300, 5228, 2082, 1923, 676, -2526, 2835, 897, -653, -3668, -5103, -394, -2621, -5853, -5176, -921, -537, -1319, -3142, -1849, 1016, 1414, 647, -2320, -801, 1527, 2562, 925, -3433, -294, 822, 2712, 282, -4842, 242, -1181, 1703, -850, -2309, 769, -1463, -1062, -781, -1052, 1003, 651, -1707, 543, -2061, 541, 1790, 194, 1207, -2345, -1065, 2238, -233, 958, 605, -1566, 2360, -3110, -13, 1942, 931, 2335, -4238, -883, 2114, 2319, 2134, -1013, -851, 1496, 2564, 1534, 32, -915, 278, 1735, 223, -847, -1878, -919, -350, -1991, -4403, -3606, -914, -2020, -3996, -3729, -3729, -993, -544, -4340, -3279, -2585, -2173, -113, -5266, -7774, -2133, -2378, -1091, -6113, -3526, -2512, -1154, -2937, -5458, -1749, -3840, -1378, -2273, -4929, -1987, -5646, -3798, -779, -5286, -2500, -4223, -4698, -480, -5979, -1443, -1889, -2670, -1206, -3674, -34, -395, -3515, -2195, -1741, 739, 45, -10613, -2889, -1006, 747, -929, -6163, -4176, -1250, -63, -3677, -7353, -4800, -1811, -1627, -2330, -4378, -2793, -1310, -2519, -720, -535, -1182, -200, -1823, -1173, 333, -240, 992, -1736, -3930, -823, 254, 1875, -2877, -14195, -4327, 429, 1936, -5827, -6504, -7523, 100, 813, -9531, -2797, -14784, -1054, -2146, -3889, -581, -4420, -3133, -14195, -1062, 378, -1799, -3269, -5465, 192, 678, -927, -1330, -3866, -7, 821, -670, 64, -2156, -1573, 914, -1065, 811, -1184, -1349, 635, -1633, 984, -1702, 282, -463, -217, 855, -4344, 555, -2393, 1105, 618, -4805, -601, -3294, 1347, -242, -3110, -3362, -1070, 658, -2683, -4420, -8615, 1182, -686, -3766, -8086, -7708, 2334, -1922, -1963, -3096, -3438, 2464, -2055, -2703, -1314, -1462, 1785, -1641, -7865, -740, -628, 493, -1010, -5702, -958, -332, -1390, -484, -3337, -2440, -311, -4017, -811, -2766, -4013, -576, -2857, -601, -209, 1245, -2673, 1298, 661, 654, 252, -3543, 2971, 1013, 516, 721, -1936, 3338, 131, -1375, 1236, 68, 3018, -2696, -3785, 1177, 1327, 2426, -9479, 78, 947, 1651, 1838, -2398, 1391, 788, 1071, 1239, -1269, 853, 440, 207, 422, -2348, -1860, -494, -280, -847, -6943, -6679, -1943, -1402, -2452, -3386, -2319, -2529, -4097, -2941, -1127, -1404, -1853, -3172, -1189, -1047, -1489, -1293, -1244, 742, -1659, -1798, -999, -860, 1749, -437, -1694, -812, -1739, 1622, 713, -542, -1050, -4649, 172, 485, 468, -2975, -4469, -2941, -1694, 432, -6943, -1207, -3695, -9064, -1197, -156, -526, -2305, -1646, -6842, 2017, -2334, -1990, 112, -4635, 2738, -3665, -1633, -169, -2789, 2674, 337, -998, -2152, -2605, 2265, 1508, -769, -989, -1740, 1727, 820, -1605, 824, -1331, 879, -2153, -4486, 998, -2066, -701, -5726, -7984, 154, -2473, -3347, -1741, -3680, -452, -1129, -5988, -295, -2648, 89, -513, -7912, 518, -2935, 827, -1335, -6973, 1122, -3586, 1136, -4013, -3137, 1470, -3014, 998, -3760, -1580, 1242, -1921, 720, -1046, -2050, 383, -1482, 581, -225, -6828, -213, -2076, 381, -1055, -3856, -468, -4669, -379, -4119, -941, -1887, -8086, -1652, -10001, -525, -5319, -2455, -1481, -5686, -1408, -8865, -498, -429, -4764, -3586, -6988, 264, -220, -4340, -10899, -2564, -67, -1095, -4790, -4145, -1311, -2416, -2619, -7752, -1577, -1593, -10442, -2425, -6814, -1118, -1611, -2668, -1617, -2906, -1637, -1051, -2626, -1753, -1652, -1893, -945, -4769, -2670, -1755, -2032, -746, -1679, -4130, -2514, -1775, 111, -362, -5871, -2797, -574, 893, -1074, -6800, -2849, -138, 908, -3609, -5531, -4003, -1267, -211, -3094, -3923, -7542, -5208, -2813, -1256, -3373, -15615, -4963, -6692, -761, -4184, -9479, -2522, -8517, -1169, -5979, -6856, -2100, -11232, -2406, -6870, -5458, -1852, -8942, -4112, -5924, -4089, -900, -7146, -3294, -5002, -1823, 169, -4784, -1973, -5638, -466, 480, -2480, -2023, -9753, -169, -562, -1384, -3373, -7819, -484, -3529, -1255, -4242, -5793, -726, -2587, -1207, -3507, -5960, -532, -732, -1140, -3689, -5531, -269, -583, -1970, -4805, -4896, -342, -1430, -4010, -4089, -5630, -886, -2861, -5097, -2887, -7281, -1953, -4728, -4042, -2988, -7936, -3518, -7408, -2683, -4901, -7230, -4425, -10799, -2119, -8582, -4974, -4064, -10799, -3194, -4486, -3365, -3757, -10069, -8220, -2703, -2653, -3603, -9149, -4718, -2659, -2714, -3249, -8086, -1904, -4378, -3665, -2720, -6870, -1067, -10284, -5718, -2090, -5480, -1219, -6480, -8718, -1369, -4104, -2034, -3975, -9331, -729, -3105, -3286, -2929, -7484, -376, -2741, -4723, -2309, -7665, -337, -3261, -6411, -2066, -9812, -478, -5091, -8517, -2555, -5152, -695, -9873, -6679, -709, 749, 1073, 789, -4541, 740, -577, 904, -1058, -8549, 1156, -3551, 870, -2166, -4386, 753, -10001, 436, -1854, -2253, -719, -4433, -1178, -2129, -1395, -3856, -3428, -5888, -2566, -1168, -8363, -2084, -7562, -2633, -1356, -4616, -531, -5942, -3401, -2072, -258, 85, -6183, -5810, -3054, 1888, -54, -3161, -11781, -3119, 2511, -246, -2468, -7644, -2450, 1853, -121, -3147, -6278, -2181, -247, 11, -3612, -7066, -2650, -5299, -127, -3151, -10284, -4038, -6445, -541, -1998, -6173, -4527, -3045, -1063, -1405, -3321, -2004, -2385, -1916, -2125, -2698, -337, -3695, -3870, -4395, -3023, 292, -6045, -4863, -5502, -1621, 209, -1432, -3023, -4172, -233, -193, 118, -2617, -4299, 0, -488, -440, -2986, -5768, -739, -495, -3142, -2155, -5333, -2004, -517, -1988, -821, -2964, -2662, -907, -31, 89, -1550, -1799, -1979, 87, 592, -1302, -483, -3498, -1293, 585, -2385, 208, -2361, -4738, -436, -5170, -160, -283, -7097, -4053, -8220, -2018, 734, -3827, -4635, -7730, -3386, 706, -3060, -911, -8060, -798, -471, -4067, -11, -7912, 597, -3827, -9531, 182, -6480, 923, -4578, -5437, 365, -5429, 456, -925, -1790, 118, -5394, -811, 63, -111, -1167, -6064, -3532, -400, 533, -3989, -7213, -10526, -2068, 359, -6422, -10138, -2003, -4071, -239, -3110, -10069, 33, -3732, -1289, -949, -4361, 77, -3266, -4464, -87, -2066, -2130, -4056, -7019, -314, -1101, -13365, -6628, -2339, -1238, -1084, -3460, -15615, -1271, -2168, -1814, -3509, -10001, -1096, -3409, -2799, -8683, -8247, -1614, -4874, -3360, -6885, -6653, -2813, -1683, -3244, -5127, -4592, -2119, 410, -2815, -5607, -2984, -1017, 1034, -2849, -4718, -2339, -1382, 479, -3621, -2865, -2699, -3227, -1015, -4659, -1931, -4149, -5623, -2973, -5037, -2545, -7389, -5353, -5997, -5189, -6256, -6074, -3352, -5306, -6457, -7317, -2653, -2153, -1521, -8304, -3496, -1321, -1957, -14, -6899, -2977, -1733, -2514, 171, -5933, -3723, -4425, -3744, -520, -5008, -4946, -2383, -5299, -1011, -3349, -5472, 306, -3824, -392, -1729, -4344, 1274, -1784, 296, -718, -2797, 1281, -1105, 520, -301, -2020, 748, -1867, 155, -361, -2268, -138, -4649, -1076, -1074, -3468, -1559, -11115, -3370, -2871, -5312, -4112, -4620, -3449, -6256, -7665, -8982, -2952, -1940, -11488, -9753, -5960, -2522, -1542, -15615, -8192, -4390, -2945, -1807, -14195, -4412, -4115, -4620, -2347, -10210, -1902, -4075, -7888, -2982, -5509, -675, -3999, -5240, -3449, -3098, -513, -3982, -3792, -3249, -1768, -1423, -4031, -3923, -2986, -1088, -3837, -3493, -2879, -3624, -915, -10704, -2670, -1344, -5810, -1065, -8247, -2505, -1144, -9022, -1416, -7389, -3147, -2672, -7912, -2207, -9284, -3971, -7562, -8112, -3779, -7179, -4153, -7264, -10001, -5844, -5319, -3853, -6204, -2741, -1903, -147, -1215, -9380, -3463, -862, 2102, -2152, -7247, -632, -530, 3003, -3222, -3889, 647, -1274, 2930, -3201, -3563, 860, -3294, 2001, -1062, -5997, 307, -6035, 89, 314, -7426, -960, -5480, -2146, 416, -3436, -3007, -4295, -1282, -359, -2462, -4108, -4172, -637, -1090, -2999, -2728, -4853, -1076, -1717, -3485, -1733, -3686, -1728, -2482, -2156, -1543, -1748, -1637, -2655, -1439, -1873, -858, -793, -2897, -2606, -1940, -1012, -339, -3375, -7004, -1064, -1882, -1002, -4718, -2574, -63, -2596, -3474, -5465, -942, 266, -3837, -6434, -2720, -1802, -687, -9106, -1718, -2477, -5915, -5026, -1501, 50, -5247, -3540, -3177, 1141, 87, -3487, -1670, 33, 2131, -1875, -1046, -1908, 910, 2149, -3886, -485, -2378, 1063, 1523, -375, -819, -1366, 804, 560, 919, -1498, -714, 76, -571, 758, -2396, -1143, -510, -2152, -573, -3776, -2192, -1300, -4564, -2908, -6016, -2500, -4373, -6194, -4951, -9936, -2613, -8549, -7004, -4728, -10899, -3792, -3515, -7912, -2312, -6590, -6388, -2443, -5979, -383, -3996, -6679, -2241, -5422, 538, -2018, -4698, -3393, -6332, 634, -883, -4149, -8423, -7445, -6, -973, -2641, -6773, -9479, -1308, -2745, -347, -4053, -14195, -3140, -7113, 920, -3114, -7503, -4654, -6914, 1292, -2040, -6204, -1914, -7299, 1184, -1188, -5615, 295, -8718, 830, -897, -4295, 986, -5458, -97, -1002, -3512, 450, -3354, -2265, -1050, -3529, -858, -2170, -5751, -827, -3760, -2152, -1726, -3038, -749, -3804, -3773, -1651, -663, -1448, -3906, -5888, -1802, 726, -3982, -4060, -4108, -2247, 1211, -7353, -3526, -2184, -2785, 685, -2774, -2952, -1182, -3014, -1072, -2000, -3860, -1123, -3142, -4266, -4056, -10138, -1974, -4038, -4395, -7912, -4238, -2404, -7130, -3103, -2256, -1768, -1397, -10284, -3603, -916, -1850, -798, -6565, -6310, -1300, -4536, -1077, -5509, -5437, -3175, -5960, -1790, -3274, -2552, -7034, -2596, -1533, -1529, -1532, -13738, -1816, -679, -836, -1527, -8942, -2083, -526, -1005, -2541, -6786, -2910, -1432, -1894, -6899, -8333, -5020, -3597, -3455, -4831, -5607, -11945, -7130, -5623, -1396, -2879, -6422, -6225, -6299, -824, -2887, -5152, -3893, -4764, -1813, -4630, -4784, -2783, -3754, -3951, -2653, -3551, -2612, -3087, -5176, -1005, -2781, -3347, -2534, -3244, -877, -2825, -4929, -2350, -1650, -1693, -3433, -4779, -2696, -1063, -2150, -4769, -3076, -3452, -1459, -1511, -7445, -2646, -4403, -2964, -1259, -9193, -3714, -5097, -6332, -2214, -8615, -6399, -4940, -13365, -5091, -10001, -7960, -4918, -7335, -11356, -13049, -6235, -5429, -8060, -5367, -9753, -4523, -3903, -8138, -3621, -6914, -2847, -2291, -3521, -3144, -6163, -1782, -2057, -1672, -3535, -7004, -1395, -3130, -1264, -4482, -7842, -1332, -5002, -1865, -5465, -7984, -1394, -5776, 9769, 6855, 9619, 7873, -3078, 9177, 6752, 9152, 7200, -1055, 7333, 6116, 7837, 4981, 348, 4069, 4419, 6083, 1119, 1049, 119, 1465, 4351, 1858, 1673, -395, 163, 2094, 2644, 1980, 500, 1204, -1384, 2232, 1923, -56, 1983, -1361, 1315, 1625, 5, 2429, -92, 134, 947, 2500, 2451, -816, -968, 213, 4231, 2225, -1921, -654, 1059, 5210, 2732, 574, 95, 2593, 5428, 3905, 1860, 549, 3684, 4655, 4581, 1394, 1347, 4413, 2737, 4293, -2031, 1791, 5014, 1532, 2643, -494, 881, 5499, 2091, -1937, 2910, -2235, 5614, 1513, -798, 3929, -1957, 5017, 1211, 1418, 3626, 37, 3356, 2627, 1121, 2149, 162, 263, 3491, -1133, -964, -645, -2483, 3994, -6299, -5951, -1007, 677, 4492, -6745, -2576, -229, 3384, 4505, -3089, -2109, 219, 4694, 3663, -587, -3254, -430, 4865, 2234, 59, -4447, -1858, 4118, 1442, -1265, -3632, -1008, 2796, 1035, -4451, -2447, 231, 1771, 52, -1766, -3049, 359, 1503, -253, -28, -6492, -305, 1201, 696, 906, -1032, -1226, 422, 1320, 1853, 1128, -576, -569, 1342, 2422, 1451, 1376, -663, 898, 2146, 613, 2591, -229, 323, 491, -535, 2781, -729, 332, -5139, -770, 1932, -3034, 880, -1125, -904, -161, -7113, 1135, 1081, -2159, -4097, -4513, 594, 806, -5662, -7371, -3449, -813, -1595, -10899, -7066, -3012, -2521, -2262, -4683, -4597, -2924, -3058, -570, -2429, -2622, -3135, -2624, -941, -1569, -2289, -2967, -2924, -2677, -2184, -2869, -2228, -5726, -2550, -4863, -3085, -1432, -8086, -1446, -8333, -3189, -1390, -2975, -1159, -4145, -4748, -2608, -1704, -1385, -2234, -8649, -5026, -1918, -1864, -1439, -6365, -5014, -2857, -2550, -1763, -5942, -4569, -3294, -3296, -2954, -8009, -6516, -3683, -3726, -3254, -7623, -5326, -5152, -4262, -2592, -5784, -2538, -6640, -6007, -2288, -5260, -2069, -7019, -8165, -2334, -6246, -3744, -13049, -6666, -2601, -5979, -8754, -5997, -6565, -2720, -3487, -8034, -3163, -6814, -2534, -2499, -7665, -2601, -4254, -2698, -2969, -5784, -3449, -2380, -3665, -4997, -5247, -5429, -1660, -5415, -9531, -6899, -8165, -1889, -6773, -8220, -5509, -8982, -3121, -5509, -5561, -4078, -6504, -5569, -3474, -4412, -4399, -4246, -9812, -2548, -4119, -6445, -3020, -14784, -2606, -4082, -5133, -2853, -9479, -2988, -3978, -2267, -3388, -6773, -3291, -4504, -1141, -3154, -4831, -3632, -6666, -1165, -2105, -3554, -4089, -8393, -1857, -1498, -3124, -4795, -5638, -2644, -1553, -3873, -5906, -4311, -3276, -2347, -6434, -7389, -2920, -3846, -4299, -7213, -7752, -1706, -3476, -9284, -3194, -5008, -933, -2935, -9284, -941, -2543, -461, -3339, -5827, 185, -1084, -645, -4373, -4880, 258, -545, -1922, -4184, -5623, -864, -852, -4545, -2571, -10704, -3014, -1778, -8363, -777, 3635, 4384, 1687, -227, 2784, 3471, 4154, 4135, -37, 2584, 2680, 3439, 5566, 480, 2660, 359, 2276, 5339, 1050, 3081, -3546, 859, 3326, 1143, 3028, 373, -932, -2956, 435, 2454, 1205, -2433, 1387, 454, 1202, 35, -1587, 3163, 1920, -1775, -2811, 337, 3076, 2428, -7752, -6246, 2418, 1908, 1587, -5576, -198, 4141, -330, -500, -1397, 2932, 5306, -2173, -3518, 1349, 4328, 5803, -968, -4486, 2056, 4561, 5567, -2273, -1465, 946, 3988, 4576, -1794, 1865, -2495, 3117, 2839, 2138, 4000, -1786, 2268, 392, 3583, 4893, -155, 1083, -3105, 3671, 4613, -186, -471, -7247, 2895, 2933, 226, -2122, -812, 1924, -1329, 1588, -6786, 1411, 1640, -888, 2786, -3391, 1831, 1708, 652, 3294, -1073, 817, 1269, -1542, 2676, -1802, 1615, -347, -745, 171, -5079, 3858, -4738, 2705, -10138, -2724, 4731, -5195, 3710, -1281, -1320, 4285, -3326, 3817, 496, -1303, 2613, -4683, 4140, 1152, -981, 266, -5266, 4415, 1026, -591, 143, -4545, 3915, 175, -1142, 1680, -5020, 2466, -375, -2482, 2820, -4523, 624, 506, -2887, 3223, -4523, -28, 1665, -1000, 2880, -4234, -139, 2264, 731, 1805, -1455, -680, 2045, 1351, 251, 232, -1189, 946, 817, -297, 610, -1208, -155, -841, 144, -186, -1581, -113, -3496, 22, -2140, -3326, -461, -5183, -444, -5176, -3457, -1548, -4912, -760, -7264, -489, -2770, -4779, -1446, -5743, 929, -4738, -3870, -2353, -4738, 1264, -4842, -3449, -2497, -4669, 861, -3893, -4784, -1963, -5638, -160, -5145, -6914, -1119, -9064, -1499, -4683, -5031, -849, -9064, -1748, -2772, -4006, -1664, -5014, -1656, -2716, -3717, -1998, -3615, -2504, -4748, -3208, -611, -3316, -2483, -6516, -2253, -227, -3927, -1044, -4583, -1548, -1515, -5988, -241, -5569, -1716, -4219, -6786, -118, -10210, -2982, -3695, -4620, -555, -4703, -3471, -3677, -4821, -1762, -3460, -2817, -6492, -8903, -4219, -4067, -3837, -8086, -6870, -4821, -5234, -7213, -5008, -3754, -2370, -3830, -4743, -3474, -2236, -1043, -1611, -3773, -2659, -1469, -546, -485, -5183, -3020, -1864, -786, -695, -8942, -5061, -3785, -1819, -2730, -5422, -5415, -4863, -3309, -8549, -2685, -2799, -3294, -3334, -4049, -1298, -1514, -2941, -1864, -2835, -819, -1047, -3975, -666, -3074, -938, -987, -6745, -243, -2578, -1491, -806, -6602, -575, -1707, -2417, -263, -5333, -1176, -1434, -3668, 77, -8903, -1542, -1819, -5615, -327, -5451, -1773, -2916, -8615, -1697, -1753, -1809, -4348, -9022, -4207, -614, -1748, -4331, -5960, -8754, -801, -2046, -3804, -4006, -12534, -1666, -2893, -3944, -3468, -9531, -2319, -4086, -4703, -4021, -11356, -3038, -4031, -5152, -5487, -8112, -4784, -2420, -4234, -9873, -4491, -2608, -1307, -4067, -8982, -2578, -325, -1029, -5561, 2080, 5215, 106, 2922, 2841, 3014, 5221, 172, 2269, 4181, 4165, 5141, 2035, 2117, 5452, 4538, 4770, 3580, 3754, 5490, 4196, 3956, 3785, 4526, 3901, 3537, 2557, 2738, 4043, -932, 2591, 269, 703, 2291, 1136, 458, -2306, -1136, -365, 2445, -4555, 45, -577, 826, 1757, -4031, 1951, 1058, 3043, 3471, -2994, 2842, 1736, 4276, 5582, -12, 3222, 1102, 4634, 6587, 1515, 3365, -537, 4061, 6540, 1412, 3187, -369, 2224, 5179, 512, 2445, 532, -1320, 1188, 389, 926, 4, -310, -1679, 422, -1736, -2046, 1038, 2003, -644, -3957, -3179, 699, 2666, -3080, -385, -2058, -1343, 3228, -5394, 1313, -1268, -15615, 3414, -8615, 1454, -339, -1452, 2847, -1385, 980, 822, 629, 1934, 1523, 1624, 1683, 733, 1499, 2381, 2301, 1903, -531, 1708, 1669, 2042, 1588, -2626, 1667, -601, 1059, 1265, -2390, 326, -2688, -727, 972, -1036, -5638, -1495, -4199, 37, -371, -735, -1308, -2012, -371, -271, 1794, -3417, -1298, 900, -525, 1968, -4035, -4046, 1326, -799, 465, -1141, -2648, 552, -834, -1868, -967, 96, -976, -816, -1463, -3040, 1115, -2933, -1254, -476, -2918, 1369, -6278, -2399, 238, -440, 928, -5906, -1975, 454, 118, 163, -3007, -295, -71, -1624, -79, -549, 188, -1409, -9106, -364, 849, -588, -2843, -907, -671, 917, -2383, -2450, 312, 221, 113, -3261, -1683, -1227, 1036, -36, -1566, -969, -10613, 1015, 105, -454, -418, -1932, 620, -840, -350, -629, -864, 409, -3156, -802, -2172, -2226, -97, -5735, -1373, -5422, -5801, -1458, -5374, -2366, -5686, -7603, -3621, -4980, -4500, -5615, -4282, -5451, -5509, -4578, -6035, -2720, -5091, -5933, -2382, -6256, -2559, -4679, -6007, -1722, -12319, -3438, -4420, -4625, -2339, -5531, -4327, -5253, -2594, -3436, -3321, -5387, -28777, -1814, -2631, -3339, -8138, -3324, -2372, -1339, -4378, -7562, -854, -3415, -992, -4885, -8683, -247, -2984, -1777, -5387, -10069, -818, -2282, -3804, -9149, -4743, -2475, -1983, -7562, -6692, -3710, -5189, -1753, -28777, -3463, -4625, -6007, -1887, -7335, -2960, -7888, -4784, -2910, -3662, -3954, -8393, -3811, -5121, -1665, -5319, -5037, -3124, -7583, -941, -4764, -3551, -3441, -8754, -1377, -3311, -2442, -5678, -28777, -2803, -3274, -1479, -10362, -6553, -4659, -5346, -1108, -7796, -3422, -5844, -4738, -1702, -4100, -2047, -5240, -2448, -3170, -890, -1210, -3600, -1640, -3665, 753, -627, -2344, -1449, -2829, 1092, -773, -2008, -1364, -2458, 217, -1782, -2875, -1402, -2453, -1925, -2336, -5234, -1950, -2683, -4625, -2229, -8754, -3213, -3886, -6163, -3509, -7523, -4460, -7196, -12123, -4644, -5836, -4134, -4042, -5897, -2203, -4957, -3603, -1553, -3175, -1107, -4733, -3910, -755, -2407, -1088, -5326, -5202, -6577, -2509, -2453, -7034, 339, -3108, -1198, -1880, -4611, 522, -1729, -1155, -1035, -4093, -162, -1394, -2205, -734, -4997, -1186, -1895, -4601, -1124, -6615, -1296, -3428, -7936, -1670, -8060, -843, -7179, -5509, -1585, -8423, -717, -8942, -4028, -1123, -5115, -886, -5387, -2975, -822, -2891, -1418, -4469, -1714, -1076, -1874, -3045, -3441, -1076, -2173, -1815, -6388, -2205, -1487, -3940, -2799, -3103, -1495, -2825, -4816, -4880, -1481, -1315, -2566, -4611, -3650, -1877, -1534, -854, -4659, -1245, -4438, -1843, 29, -5152, -156, -9238, -2306, -47, -6225, -106, -5208, -3509, -1227, -8827, -1007, -4006, -5043, -4425, -10899, -3062, -4119, -4901, -6973, -6035, -6553, -5133, -5584, -3707, -4145, -5670, -4858, -10210, -3237, -3769, -4270, -2587, -9193, -3149, -4464, -4438, -1303, -6183, -2316, -4929, -5623, -1301, -4759, -1826, -3417, -5367, -2683, -3016, -2108, -2034, -3535, -5793, -1842, -3069, -1681, -2369, -6445, -1514, -4331, -2621, -1698, -4918, -1800, -5195, -5422, -1742, -4420, -2125, -5115, -10526, -3284, -3978, -2004, -4486, -6786, -8942, -3930, -2014, -3846, -5751, -8333, -5189, -2939, -3337, -6074, -8865, -10799, -5776, -2990, -6553, -8086, -6321, -12776, -3042, -4826, -3738, -3606, -5266, -3352, -3119, -2979, -3569, -3689, -3947, -2644, -4172, -6163, -3430, -5554, -3227, -7687, -9479, -3103, -5387, -4378, -9331, -6163, -1904, -3347, -4997, -4968, -5897, -969, -2984, -4331, -2747, -6278, -912, -4278, -3563, -1466, -6332, -1704, -7796, -3220, -1170, -6745, -2935, -12123, -3112, -2130, -8276, -3896, -7264, -3903, -5079, -9284, -4597, -7050, -7583, -7562, -7299, -5429, -10899, -5810, -3603, -4382, -7066, -6800, -2811, -2087, -2317, -8192, -4242, -2045, -1884, -1615, -5444, -3689, -2297, -3012, -2181, -4195, -3971, -2937, -6288, -3876, -4286, -4295, -3798, -9753, -7523, -5227, -4907, -5115, -5127, -8423, -6928, -5844, -5115, -3049, -3449, -8112, -5085, -4089, -1868, -1882, -6814, -4403, -4056, -1379, -1733, -6354, -5561, -4869, -1489, -2331, -7583, -9585, -5988, -2086, -2914, -10526, -7247, -7623, -3083, -2637, -11004, -6083, -9193, -4473, -1753, -8138, -7503, -9064, -6026, -1228, -6267, -6759, -8942, -4837, -1526, -5879, -4578, -8393, -3393, -2933, -6113, -3913, -8138, -3422, -6103, -4869, -4242, -9331, -5037, -17034, -3788, -5097, -11781, -6133, -6653, -4028, -5888, -11115, -4597, -4138, -5997, -6016, -7603, -4112, -2997, -13365, -5576, -4853, -4759, -2861, -9380, -5152, -3455, -5480, -3436, -7408, -5227, -3163, -5253, -4315, -7665, -6173, -3798, -5429, -5726, -8649, -8827, -4826, -7542, -7113, -8138, -7542, -4991, -28777, -5049, -6899, -4769, -4800, -7936, -3916, -6719, -3944, -5960, -7213, -4187, -8165, -4611, -11945, -9106, -5422, -10899, -6928, -7264, -12534, -6786, -8009, -10799, -4266, -11488, -7317, -6445, -8790, -3370, -8582, -7865, -5326, -1923, 445, -1426, -4795, -4847, -2690, 167, -2256, -2211, -6480, -5630, -872, -3276, -1275, -8423, -5279, -2445, -4130, -1697, -5494, -2369, -4429, -4464, -2703, -4683, -1072, -7503, -4086, -2482, -6064, -546, -9429, -3133, -2452, -5367, -837, -6183, -2417, -4587, -2292, -2488, -4929, -2435, -11488, -959, -6399, -4056, -3399, -3683, -1087, -5735, -3532, -5061, -2276, -3054, -4795, -3833, -4683, -2465, -12776, -6411, -4307, -3189, -3689, -4089, -8903, -3306, -2969, -5718, -2326, -8865, -1875, -4486, -5970, -2785, -10138, -1058, -5678, -4112, -5394, -10704, -986, -3468, -3449, -9479, -9149, -1589, -3142, -4491, -6457, -7050, -2855, -5183, -7984, -5942, -6035, -5055, -6214, -7503, -6759, -5139, -6786, -2931, -7665, -6123, -3968, -4149, -1355, -8485, -3996, -3824, -2482, -812, -3856, -2655, -5002, -2176, -1260, -1868, -2128, -4693, -3274, -3227, -845, -2239, -2988, -6267, -10284, -485, -2859, -2531, -8485, -5654, -959, -3710, -3051, -6267, -4826, -2011, -4420, -3975, -6653, -5312, -2865, -4708, -4683, -9022, -2411, -4373, -4698, -4901, -8549, -892, -6422, -4523, -3975, -10069, -684, -2960, -4108, -2791, -9064, -1157, -1516, -3856, -2325, -3947, -1793, -1693, -4369, -2791, -2102, -2478, -3137, -4395, -4282, -1538, -3194, -5234, -3239, -6267, -1655, -3792, -5326, -2733, -5718, -2198, -4733, -4460, -2994, -4042, -3624, -7050, -4523, -3600, -3133, -8333, -8086, -5818, -4134, -3286, -6814, -4373, -7730, -3910, -4997, -3788, -2737, -6786, -3569, -9022, -3526, -2536, -6615, -3954, -6183, -4698, -3748, -7912, -4805, -4262, -5014, -6885, -4630, -5718, -3365, -3597, -7097, -2336, -7819, -2472, -2997, -4790, -1603, -13049, -1875, -3485, -3978, -2115, -9284, -2236, -4810, -3893, -3964, -9022, -3535, -6732, -4469, -8276, -12123, -3425, -10362, -6759, -8304, -9380, -2873, -14784, -12319, -5437, -6388, -4307, -10442, -5879, -4805, -4968, -9193, -6376, -5073, -4486, -4390, -4199, -4282, -5942, -3034, -4138, -2601, -4086, -4951, -1771, -4104, -2847, -5472, -4290, -1703, -4382, -4659, -7842, -4541, -3388, -4403, -8549, -8649, -3632, -6235, -3329, -5367, -7484, -3244, -3177, -2453, -3089, -7445, -4464, -1921, -2560, -2260, -9479, -5465, -1873, -3814, -2337, -8827, -4478, -2213, -6103, -3264, -8754, -4408, -3007, -6842, -4592, -13738, -5584, -4748, -6007, -3856, -6528, -7542, -4869, -6123, -2351, -4541, -6692, -3409, -7230, -1662, -4473, -4569, -3135, -9429, -1779, -5615, -3067, -3856, -11356, -2540, -7687, -2231, -4991, -10001, -3680, -11115, -2276, -5630, -8549, -4790, -12534, -3386, -5768, -7665, -5599, -6679, -5871, -6225, -7389, -6332, -4451, -12319, -6679, -6064, -7004, -4067, -10138, -5253, -4266, -6602, -5862, -7665, -3944, -3501, -5888, -17034, -7752, -3833, -3496, -5942, -5960, -8865, -5049, -3425, -6666, -4412, -8903, -7819, -3239, -7408, -5037, -7687, -13365, -1137, -2559, -1426, -6299, -6773, -2512, -3158, -1682, -5109, -7730, -3886, -3940, -2182, -4250, -10069, -3964, -4513, -3198, -5810, -9149, -4134, -4980, -3474, -11115, -6565, -4250, -7146, -2964, -3732, -6123, -3999, -8276, -3007, -1831, -6615, -3788, -4578, -2322, -1531, -7097, -3726, -3103, -1208, -2194, -7523, -3853, -2533, -1122, -3773, -8192, -2969, -2809, -2204, -7960, -9479, -1736, -4035, -3707, -6828, -12534, -1417, -5801, -3940, -2853, -10899, -2083, -6411, -3269, -1472, -9585, -3624, -3707, -3067, -1500, -10442, -6074, -1999, -4559, -3010, -6045, -9429, -1872, -8649, -5346, -3710, -11356, -3259, -4482, -3281, -2531, -9022, -5145, -3347, -2011, -1359, -6640, -3025, -5014, -2111, -419, -5623, -885, -9695, -3080, -238, -5670, 387, -3463, -4416, -812, -5951, 943, -1497, -5702, -1848, -7066, 897, -952, -7247, -2997, -12123, 607, -1319, -12534, -4238, -9479, 547, -2557, -7230, -5888, -6842, 461, -4403, -4509, -8790, -6113, -341, -4258, -4491, -28777, -5020, -2248, -3092, -7562, -10613, -3804, -4021, -2849, -5273, -9695, -3903, -2533, -3444, -2191, -8454, -6246, -1432, -3923, -1086, -4578, -7371, -1526, -3415, -994, -2309, -5367, -2815, -3182, -1505, -1452, -5784, -3944, -3933, -2242, -1813, -6842, -3449, -5694, -2891, -3074, -5776, -3674, -7796, -3407, -4082, -4361, -5253, -6732, -3975, -4654, -3108, -8086, -4195, -4769, -6343, -2264, -10284, -2543, -5853, -8086, -1987, -8060, -1844, -7066, -6133, -2216, -6399, -1868, -8517, -5584, -2578, -6016, -1864, -10362, -7066, -2487, -7317, -1236, -10210, -12123, -1979, -11945, -479, -6759, -7230, -1711, -7230, -266, -4180, -4935, -2328, -4644, -981, -2559, -4234, -4718, -3342, -2958, -1860, -4541, -11781, -2242, -6457, -2057, -5836, -5176, -1033, -6828, -3130, -7503, -3957, -168, -4963, -4532, -8034, -4693, -21, -4238, -4874, -6469, -6814, -643, -4816, -4963, -4592, -8165, -1863, -6480, -4991, -4352, -7213, -2982, -7819, -3535, -6153, -5906, -3269, -7464, -2111, -5020, -4408, -3425, -4640, -1471, -2707, -3916, -3668, -3010, -1532, -2277, -5234, -3386, -3027, -2238, -3452, -9585, -3279, -4513, -3430, -6343, -6411, -4659, -7097, -4307, -9380, -5286, -7888, -8649, -3592, -8485, -7130, -5678, -6988, -2737, -9284, -11488, -5202, -5026, -2416, -14195, -5997, -6745, -3795, -2051, -8718, -4733, -5312, -3331, -1759, -6299, -4698, -3487, -3788, -2305, -5623, -4089, -2847, -5367, -4274, -5339, -3163, -3117, -7426, -7353, -4907, -3056, -3957, -7730, -7034, -4336, -4130, -5312, -8615, -7097, -3879, -6870, -8549, -9149, -7623, -3444, -15615, -12123, -7408, -7299, -2933, -11356, -7335, -7687, -7213, -2813, -10704, -6856, -12319, -7687, -3296, -9238, -5942, -9106, -8754, -3856, -7130, -4425, -6310, -8754, -3856, -6332, -3723, -5751, -8112, -3933, -6321, -3668, -5951, -8615, -4597, -5836, -3766, -5827, -8942, -5776, -4082, 15079, 1996, 10173, 9749, 8284, 14678, 5449, 9501, 9080, 10074, 13441, 6789, 7260, 6834, 10033, 11279, 6239, 2289, 1501, 9131, 8396, 4271, 379, 853, 8032, 7499, 1618, 725, 1957, 6314, 8352, 35, -328, -609, 3415, 8633, -837, 177, -7019, 5102, 8143, -501, -542, -380, 5954, 6802, 1346, 1343, 1246, 4327, 4699, 3374, 3619, 2342, -3430, 3032, 4847, 4777, 2973, 1407, 3215, 5570, 5121, 3062, 1920, 4733, 5418, 4779, 2581, -1020, 5585, 4180, 3864, 1055, -6773, 4934, 1705, 2704, -2482, -3741, 2161, 513, 1702, -3133, -2997, -1296, 1091, 825, -1759, -4896, 1491, 453, 65, -1928, -2165, 1940, -1082, -638, -2567, -645, 977, -2097, -1932, -6173, -178, -1760, -1270, -4157, -3879, 1276, -5827, -543, -4104, -904, 2354, -3018, -950, -3820, -853, 2725, -2578, -2445, -6565, -1860, 2679, -3512, -2155, -6988, -956, 2077, -6577, -713, -4550, -176, 74, -6928, -394, -5158, -589, -9064, -1549, -1189, -5339, -1860, -1729, 496, -3284, -4046, -2935, -333, 1063, -7774, -3754, -2238, -1078, 587, -28777, -3401, -946, -1641, -483, -9812, -3161, -315, -1799, -1278, -5214, -3999, -675, -3441, -1319, -3465, -5189, -2244, -5472, -1206, -3326, -6365, -3863, -4382, -1671, -4373, -10799, -2475, -5615, -3269, -6007, -9429, -1656, -8754, -4620, -6628, -8683, -2049, -3674, -3286, -5979, -12534, -3177, -2743, -2646, -5333, -8086, -4238, -3600, -2829, -5554, -5266, -6256, -5139, -3321, -6943, -3635, -10001, -6074, -3738, -8034, -3087, -4951, -4323, -4123, -6786, -3840, -3526, -2317, -4635, -6719, -5055, -3860, -1154, -4929, -9429, -3347, -5380, -554, -4630, -11629, -2049, -7299, -448, -4161, -6899, -2022, -7371, -976, -3996, -5451, -2807, -6615, -2339, -4541, -4664, -3476, -6973, -5061, -6035, -4403, -3647, -8615, -9531, -7644, -4896, -4089, -8333, -7865, -6973, -6074, -5494, -6246, -7542, -6411, -7230, -9380, -4373, -7034, -7445, -7317, -9106, -3005, -6083, -11629, -6225, -5569, -2430, -4974, -9936, -5055, -4733, -2701, -4130, -6376, -4307, -5429, -3741, -4340, -4323, -4078, -7281, -5247, -5743, -3130, -4274, -10284, -6267, -7644, -2817, -4625, -14195, -5793, -7687, -3309, -4649, -9531, -5465, -6800, -4395, -4649, -9064, -6565, -8649, -5480, -5509, -12319, -9193, -8903, -5818, -8333, -11115, -8009, -3612, -5970, -13365, -8454, -6540, -1952, -6299, -8754, -8165, -6577, -1671, -6343, -7523, -9331, -7842, -2169, -5801, -7687, -9479, -9639, -3396, -5061, -7281, -8485, -9380, -5827, -4880, -5710, -8718, -9639, -11629, -5853, -4980, -10362, -13365, -9873, -7708, -5158, -11004, -13738, -7004, -6422, -5879, -9753, -9106, -5906, -4573, -6943, -9429, -7752, -5067, -4336, -8276, -9331, -7774, -3683, -6445, -10210, -8582, -8423, -2869, -12776, -9380, -7264, -8138, -3291, -6800, -7445, -6332, -7299, 8604, 3945, 6864, 8571, 7383, 7855, 3964, 6139, 8137, 7006, 5364, 3619, 3539, 6914, 5897, -274, 2199, -7523, 5283, 4622, -5240, -1046, 484, 3958, 4359, -3119, -1418, 512, 3032, 4121, -662, 1403, -3342, 1925, 3168, -599, 3199, -151, 3, 2474, -3054, 4122, 1936, -3827, 3063, -7081, 4206, 3093, -8683, 3985, 714, 4162, 4738, -2758, 4335, 3758, 4887, 6199, 115, 3745, 5275, 5632, 6833, 1408, 2127, 5620, 5737, 6451, 1162, -254, 4831, 5174, 4797, 469, -1992, 2837, 4148, 1409, 2100, -1279, 135, 2813, 989, 3339, -287, -241, 872, 2252, 3304, -571, 65, -1625, 1699, 2089, -2726, -411, -245, -88, -215, -6745, -1345, 1370, -2047, -2749, -3498, -2432, 1928, -3498, -4486, -2320, -2672, 1882, -5743, -3824, -2580, -1515, 1601, -6640, -2564, -3609, -797, 1335, -5933, -3824, -4669, -1195, 1133, -7353, -5702, -4460, -3244, 810, -14784, -1836, -3078, -10069, 47, -6943, -506, -2064, -6173, -1304, -4946, -315, -1832, -3735, -2182, -4486, -667, -2311, -2621, -1766, -4299, -2057, -3177, -2264, -1648, -3551, -7281, -3738, -2849, -1826, -3597, -4664, -3886, -4395, -1638, -6143, -1424, -3824, -6577, -1468, -5862, -165, -3698, -7865, -1752, -3187, 485, -3720, -5906, -2541, -3430, 761, -4130, -3529, -3817, -6246, 486, -5694, -2200, -5615, -6133, -790, -11356, -1873, -7644, -4630, -4486, -8790, -2473, -7162, -5133, -6814, -6577, -4078, -5360, -5008, -2217, -6411, -7247, -4606, -3309, -1123, -5133, -11115, -4784, -2452, -1197, -3937, -6640, -5319, -2845, -2043, -4266, -4816, -6299, -4997, -3362, -7230, -4929, -11232, -9695, -4112, -11004, -7842, -7146, -6016, -3092, -5546, -11004, -3837, -5133, -2020, -4327, -6288, -3187, -5951, -1836, -4331, -5970, -4123, -6163, -2664, -5121, -7774, -4842, -5718, -4523, -5988, -10899, -3824, -7097, -7752, -6457, -8112, -3662, -28777, -13365, -7019, -6745, -5103, -7603, -9429, -7371, -7050, -8942, -5853, -8549, -6914, -8790, -9149, -6278, -11488, -6457, -8192, -7146, -7408, -10704, -6958, -6016, -6615, -6814, -6235, -9429, -4532, -6719, -6173, -4693, -9639, -3674, -7865, -6870, -4331, -6745, -3714, -11945, -9106, -4597, -6256, -4816, -10899, -11781, -5170, -7730, -6885, -7464, -11629, -5853, -13049, -8454, -6577, -10362, -6143, -8582, -7687, -7213, -8615, -5735, -5592, -6540, -10001, -7644, -4974, -4573, -6628, -28777, -7281, -4564, -4795, -7842, -10069, -7179, -4728, -6434, -9149, -8942, -7299, -5158, -11629, -13365, -10069, -7542, -5480, -8582, -9531, -11781, -7162, -5607, -5049, -6615, -8517, -6615, -5067, -3729, -6214, -6958, -6235, -4348, -3729, -6553, -7097, -5933, -4226, -5240, -6299, -8517, -6133, -4708, -9284, -5979, -10362, -7317, -5686, -8982, -5924, -11115, -8112, -7066, -7583, -5960, -10526, -7842, -7774, -9531, -6163, -10069, -9429, -7213, -12776, 4310, 2708, 6990, 7471, -15615, 3226, 1575, 6534, 7170, -5319, -565, -1330, 5369, 6403, -1790, -1323, 1284, 4390, 5600, 1713, -1967, 2902, 4127, 4938, 4045, -6163, 3210, 3792, 3977, 5217, -1403, 2642, 2997, 2856, 5416, -3629, 1050, 1590, 2355, 4620, -1743, -1913, -605, 1507, 2126, 2935, -3040, -3168, -1542, -3626, 4946, 1173, -948, -2146, 2887, 5787, 4314, 1140, 1218, 4354, 5668, 5813, 1252, 2007, 3854, 4538, 5779, -493, 2074, 2001, 2451, 3882, 611, 2980, 2509, 942, -3210, 2276, 3721, 4021, 702, 231, 1892, 3317, 4409, -103, 1213, -609, 1603, 4021, -608, -1343, -4495, -1340, 3247, -650, -9429, -6540, -6540, 2242, -958, -2698, -6093, -5871, 719, -927, -2102, -2073, -2619, -1591, -356, -1857, -1686, -2222, -1594, 196, -1391, -3626, -2175, -136, 147, -1688, -11356, -1900, 259, -920, -2887, -6246, -2314, -224, -3656, -4234, -3863, -3866, -1571, -10001, -4176, -3259, -5516, -3729, -4527, -3187, -3635, -4021, -4299, -3996, -2847, -5008, -3314, -2316, -7708, -4093, -7912, -5121, -761, -4759, -6299, -13738, -6870, -336, -1613, -2912, -12776, -2495, -1371, -860, -1158, -7562, -1300, -4199, -1588, -863, -5176, -1625, -4532, -3463, -1439, -4784, -2737, -3071, -4053, -2289, -5509, -4010, -2447, -3242, -3225, -5524, -5509, -1953, -3671, -4974, -6093, -7603, -2178, -5286, -7445, -9429, -9022, -3444, -6246, -6885, -7335, -9695, -4532, -6399, -6928, -6026, -12123, -3971, -7623, -9639, -8247, -6590, -4219, -9331, -12319, -9753, -3422, -6988, -9429, -8454, -4469, -2002, -9753, -8615, -5853, -3005, -1741, -5646, -7299, -4142, -3119, -2416, -6310, -5979, -3814, -4138, -3618, -11232, -4946, -4885, -4688, -3571, -5008, -4226, -5554, -4442, -2670, -3707, -3840, -4176, -5067, -2688, -4918, -3680, -3644, -8865, -3886, -11356, -3580, -4307, -6354, -5646, -7603, -3683, -5784, -2825, -6602, -5584, -4473, -7503, -1782, -7146, -6235, -6653, -8982, -2195, -7426, -9753, -11629, -7708, -3913, -6679, -11781, -9873, -6411, -7353, -5091, -7603, -9106, -6214, -8220, -3846, -6553, -8363, -7281, -5871, -3436, -6719, -6973, -10613, -5751, -3798, -8060, -6759, -7644, -7371, -4821, -10210, -7888, -5299, -9873, -6214, -9064, -9873, -4831, -9753, -7353, -7113, -11629, -5584, -9479, -8790, -5793, -11781, -7081, -9812, -11232, -5374, -10442, -8649, -9753, -7484, -6457, -8903, -9238, -10069, -5183, -11945, -8247, -8454, -10442, -4464, -7708, -8423, -7113, -8517, -4679, -4513, -9149, -6411, -6870, -4997, -3621, -9380, -6235, -6376, -4951, -4086, -9284, -5735, -6528, -5415, -5524, -9695, -4759, -7066, -6914, -7353, -10613, -4168, -8649, -7335, -8333, -10899, -4013, -11629, -6354, -7687, -9284, -4010, -8827, -6732, -8192, -8192, -3947, -6565, -9331, -13049, -8333, -3773, -5818, -9149, -9331, -9531, -3785, -6321, -6773, -7623, -5139, -5897, -6973, -6074, -7230, -7281, -6365, -7912, -6256, -7842, -4587, -6288, -10799, -6628, -8454, -2613, -5768, -10526, -6504, -8754, -2219, -5970, -9149, -5561, -7445, -3540, -6528, -9873, -4946, -5879, -6914, -6288, -8517, -5266, -5133, -5576, -5183, -8138, -6628, -5214, -3916, -4060, -11945, -8790, -6343, -3549, -3386, -11004, -10899, -9639, -3801, -3409, -7865, -10799, -14195, -4215, -4157, -6973, -8903, -8827, -4078, -5539, -6914, -7752, -8942, -3551, -7730, -9022, -7912, -12319, -3751, -7865, -12123, -8517, -14195, -4654, -6204, -7445, -7912, -10362, -4957, -4478, -5202, -9639, -7774, -4093, -2210, -3027, -6814, -3580, -2316, -69, -818, -1828, -467, -735, 1194, 803, 382, 1201, 75, 1347, 1438, 1068, 1630, -57, 377, 925, 464, 862, -1274, -1599, -921, -1469, -1321, -3863, -4031, -4774, -5121, -5686, -8615, -5997, -8827, -12319, -8942, -15615, -6602, -6492, -10001, -7603, -12319, -6204, -6434, -7179, -6899, -11115, -5844, -7888, -6163, -6194, -10613, -6183, -11629, -5888, -5970, -9284, -7464, -11781, -5997, -5897, -8423, -8790, -8393, -6577, -6035, -7484, -8423, -7146, -7960, -6719, -6007, -7912, -7464, -10284, -7960, -5422, -6773, -9936, -11781, -8982, -6469, -5139, -10362, -11232, -9639, -11629, -4211, -7888, -11488, -11356, -8009, -4097, -7623, -13365, -15615, -5055, -4369, -8942, -14784, -14195, -4286, -4616, -11629, -11356, -10799, -4853, -5152, -11945, -9064, -8865, -6628, -6083, -9284, -8304, -9022, -7774, -7019, -7912, -8903, -12319, -6745, -8790, -7708, -10442, -13365, -6256, -17034, -8683, -9106, -9149, -6885, -9753, -10799, -6899, -8165, -8247, -7752, -13738, -5942, -8060, -7213, -8582, -17034, -6246, -8615, -5853, -13365, -28777, -8454, -9936, -6204, -14195, -17034, -13365, -12534, -8982, -11356, -13738, -8683, -10613, -11945, -9064, -12534, -8247, -8865, -9193, -7484, -12776, -10613, -9531, -9936, -7247, -17034, -14195, -11004, -14195, -8060, -13365, -11232, -8423, -9695, -9149, -10210, -11488, -7353, -7644, -9238, -9064, -13049, -7583, -7484, -8220, -9106, -11945, -8304, -7408, -6988, -9695, -10284, -8754, -6113, -6615, -9639, -9238, -8865, -4929, -7408, -9639, -8363, -8903, -4307, -9284, -9639, -8276, -8754, -4495, -10362, -8827, -9064, -8615, -5888, -9022, -8393, -10362, -9064, -8754, -7665, -8582, -11781, -9936, -8582, -6828, -8903, -14195, -10442, -6528, -6615, -9193, -12123, -10210, -5888, -6973, -9429, -8982, -10001, -6540, -7562, -9753, -7888, -10001, -9022, -7730, -10613, -8220, -10362, -17034, -7730, -12319, -10362, -11488, -15615, -8582, -12534, -28777, -13049, -15615, -11004, -9429, -14195, -12776, -9380, -13365, -7865, -12776, -11945, -7146, -10799, -8009, -14784, -11945, -6411, -8754, -10001, -12534, -12534, -6828, -8423, -12534, -10899, -11945, -8192, -9812, -10899, -10138, -10526, -9585, -12776, -10799, -10362, -9585, -9695, -13365, -12776, -11356, -9936, -9429, -10442, -13049, -10799, -11945, -6602, -9331, -17034, -6692, -7960, -7113, -8754, -11781, -6745, -6504, -8165, -9331, -13365, -7196, -5988, -11115, -10899, -14195, -7066, -5444, -9585, -9585, -10001, -6343, -4743, -6958, -7603, -9873, -6235, -4168, -6376, -6666, -12123, -7281, -4006, -7230, -6553, -13738, -10526, -4361, -9380, -7230, -11488, -15615, -5306, -12534, -8754, -8615, -9531, -6480, -9585, -8903, -6842, -7752, -6958, -6745, -7196, -6590, -7408, -6759, -6064, -6434, -8086, -8393, -6577, -7353, -6602, -13365, -10210, -6504, -10526, -6376, -12123, -11945, -6732, -12534, -5387, -8790, -15615, -6565, -9106, -5942, -9479, -7687, -5576, -4923, -10362, -7752, -3535, -3840, -1920, -2664, -2432, -788, -1616, -269, 35, -115, 743, 13, 29, 912, 614, 1152, 624, -1164, 438, 96, 421, 120, -4541, -1426, -1563, -1617, -1613, -12123, -5279, -4215, -5183, -4644, -8649, -28777, -7179, -6800, -7842, -8649, -11629, -9106, -6719, -7730, -6856, -11115, -9238, -7842, -6540, -5121, -9639, -7353, -9064, -6615, -4303, -8718, -6083, -9585, -7264, -4713, -8718, -6343, -9238, -7019, -6376, -9873, -8393, -9149, -6943, -7426, -13049, -10210, -10210, -8060, -7213, -28777, -7426, -14784, -11356, -8718, -14195, -6153, -11488, -14195, -12534, -15615, -6143, -8112, -11004, -7389, -17034, -6988, -7050, -10613, -5380, -10001, -8549, -7335, -12123, -5097, -7936, -11004, -8582, -12319, -6615, -7130, -15615, -9429, -9064, -14195, -7281, -15615, -8009, -8276, -8485, -8517, -11115, -6064, -9429, -6422, -11945, -9585, -5422, -11488, -6628, -15615, -8982, -6469, -12123, -7623, -10613, -8982, -11004, -11629, -7960, -9585, -9022, -9106, -9331, -7819, -9429, -8549, -6516, -8165, -8138, -9022, -7281, -6163, -8903, -9479, -8138, -6411, -6899, -11781, -10799, -7484, -6310, -8333, -10362, -10362, -7523, -6856, -9639, -7644, -10442, -8423, -7299, -9022, -6343, -12123, -10210, -7019, -8517, -5924, -14784, -12123, -6914, -9873, -6434, -28777, -13365, -7644, -15615, -8009, -13365, -12534, -9380, -14784, -10001, -9531, -10899, -11781, -12534, -10526, -8112, -10799, -13049, -10001, -10613, -7842, -13049, -11945, -8865, -9022, -7936, -28777, -11356, -10138, -7888, -8165, -10442, -12319, -14784, -7687, -8903, -8865, -17034, -12776, -8034, -11232, -8009, -12123, -17034, -7796, -15615, -6973, -9429, -11629, -7196, -9753, -6745, -8485, -8517, -7281, -8485, -7730, -8549, -8393, -8060, -8865, -9380, -9331, -9812, -9331, -10001, -9639, -10799, -10613, -10138, -12319, -10210, -13365, -10138, -10613, -15615, -11629, -17034, -10210, -11488, -11781, -10704, -15615, -10613, -12776, -10526, -10526, -11356, -11356, -28777, -11488, -12123, -9639, -11781, -12319, -28777, -14195, -9064, -11115, -9873, -10069, -15615, -9531, -11004, -10138, -7687, -15615, -10899, -12776, -11945, -7317, -11232, -13049, -28777, -12776, -8363, -9429, -12123, -11945, -12534, -11232, -8865, -10526, -9812, -11945, -14195, -9022, -9429, -9695, -11004, -14784, -10442, -9238, -11004, -11629, -10069, -4104, -8333, -5801, -9149, -9429, -4447, -14784, -5554, -9106, -8060, -4654, -13365, -5871, -6399, -6299, -4985, -10613, -6745, -5472, -5253, -5326, -10069, -8086, -5678, -5026, -5234, -10526, -10613, -6434, -5422, -4625, -9531, -13365, -7408, -6143, -3937, -6628, -8982, -8423, -7019, -3507, -5312, -7019, -9284, -8247, -3546, -5073, -5951, -9936, -10526, -4127, -5353, -5584, -11488, -14784, -4728, -5743, -6026, -11781, -15615, -4447, -6565, -7146, -9936, -10613, -4180, -8754, -8009, -9284, -8790, -5234, -12123, -8009, -9639, -8827, -8517, -8865, -8220, -11488, -8549, -9812, -6093, -6679, -11629, -5061, -5670, -3237, -3656, -4826, -2012, -1978, -693, -1030, -1746, -188, -34, 920, 530, -283, 484, 425, 1414, 892, -63, 72, -546, 703, -42, -1096, -1479, -3375, -1434, -2578, -3738, -4234, -11781, -4774, -8060, -10069, -7179, -8333, -5279, -15615, -8060, -7665, -8009, -6183, -17034, -6365, -7665, -9753, -9873, -11004, -5906, -8165, -8549, -8247, -8942, -5339, -10138, -5988, -7213, -8192, -4800, -13738, -5014, -8942, -7353, -4863, -9193, -5360, -14195, -6773, -5524, -8454, -6640, -7960, -6943, -6267, -10613, -8276, -6143, -7708, -6457, -12776, -8942, -5915, -8304, -6732, -7774, -8615, -6745, -9106, -7644, -6007, -8549, -8247, -10899, -8903, -6016, -9695, -9022, -13049, -9873, -7865, -12319, -8903, -12123, -12776, -11629, -10069, -9064, -9331, -12123, -9695, -7912, -8942, -7050, -8754, -9022, -7196, -7960, -5801, -8220, -9479, -7912, -7281, -5554, -10001, -9106, -10704, -7389, -6288, -17034, -8333, -28777, -8649, -7819, -10526, -7936, -28777, -12319, -8982, -8454, -7408, -13049, -15615, -9193, -8165, -6422, -8423, -10899, -10704, -8982, -5623, -7196, -10799, -14784, -10442, -5286, -8138, -14784, -9331, -12123, -5266, -10799, -15615, -7583, -12319, -5516, -7603, -10362, -7464, -10613, -6445, -5247, -9639, -7687, -9695, -8615, -4336, -10613, -7687, -10526, -12776, -4295, -13365, -8034, -17034, -28777, -4733, -12123, -9022, -10362, -15615, -5286, -9812, -10799, -7842, -11488, -5768, -8683, -14784, -7353, -9873, -6045, -8333, -14195, -8582, -8683, -6332, -8615, -9479, -13049, -7774, -7230, -9639, -7752, -17034, -7247, -8683, -12534, -7299, -12776, -7445, -8009, -17034, -7503, -11356, -8393, -6814, -11004, -8060, -9695, -10284, -6590, -9812, -9380, -8754, -13365, -7179, -10210, -11945, -8165, -14784, -8582, -11232, -13738, -8363, -12776, -11232, -10613, -15615, -9753, -10704, -28777, -10442, -15615, -11781, -9531, -11781, -10704, -11115, -10210, -8615, -9429, -9064, -9284, -8903, -7912, -9193, -7503, -8683, -8582, -7819, -9753, -6504, -9193, -8942, -8582, -9873, -6064, -10704, -9873, -10284, -9873, -6235, -13049, -11781, -14784, -11232, -7097, -13049, -14195, -14784, -13365, -8982, -11781, -17034, -10362, -11356, -13738, -11945, -10899, -8827, -9380, -15615, -13049, -8827, -8333, -8393, -12319, -13365, -8549, -8363, -8304, -14784, -13738, -9585, 8691, 10305, 10541, 8363, 6601, 7910, 9849, 9903, 7804, 6059, 5271, 8450, 7889, 6106, 4381, 2415, 6066, 4679, 3269, 1449, 3746, 3056, 3635, -135, -1732, 2977, 1488, 2915, -2326, -3242, 1084, 2377, 314, -3227, -10362, 1812, 3353, -1552, -1758, -9, 2880, 3452, -1317, 255, 2692, 2860, 2480, -2229, 1058, 3712, 1121, -330, -3824, 1567, 3828, -1906, -2217, -5784, 3306, 3465, -906, 2508, -5367, 4815, 2717, -2032, 4277, -3779, 5221, 1198, -297, 4506, -3801, 4428, -1244, 1773, 3323, -4874, 2258, 699, 1762, 222, -3574, -1859, 2634, -210, -3474, -1026, -4230, 2955, -6786, -395, 729, -3103, 1975, -3235, 766, 1489, -3182, 25, -913, 1107, 1108, -3036, -3247, -458, 987, -859, -2470, -3695, -1216, 718, -5214, -1939, 724, -3490, 430, -3417, -674, 1651, -3034, -301, -1909, 543, 121, -1499, -2123, -570, 478, -8220, -2148, -6422, 845, -1650, -2236, -1663, -7665, 1426, -28777, -1095, -287, -3016, 1119, -2076, -1716, -1664, -1746, 342, -150, -677, -8517, -2730, -131, 258, 982, -354, -7408, -391, -114, 1613, 886, -5109, -628, -244, 676, 383, -4412, -501, 496, -4067, -910, -6565, -777, 1177, -1882, -2829, -4412, -2807, 1366, 1056, -7960, -3401, -15615, 993, 1442, -4541, -2871, -2735, 13, 377, -1948, -930, -955, -888, -2300, -1862, -33, -836, -284, -10069, -3493, -756, -1612, 337, -5853, -4831, -1978, -2877, 10, -4500, -3692, -220, -4089, -1151, -4089, -2716, 1032, -5346, -2460, -2605, -2490, 888, -5646, -3606, -1341, -3621, -652, -3147, -5879, -839, -8112, -3903, -1432, -14195, -1252, -7445, -8165, -824, -8865, -2881, -4112, -13365, -1057, -7484, -5670, -3704, -5055, -1760, -6321, -6773, -4728, -2445, -2448, -4021, -9695, -5576, -1677, -2988, -2416, -8790, -4100, -1923, -3375, -1634, -4597, -3187, -2762, -2935, -1601, -3062, -3674, -4010, -2057, -2430, -2516, -5240, -5333, -1733, -4290, -2943, -6899, -5164, -2188, -6376, -4420, -13365, -4274, -3094, -5735, -6422, -6278, -4176, -3808, -4901, -8485, -3586, -5079, -4262, -4640, -11945, -3557, -6856, -4635, -4357, -7464, -6173, -8454, -4800, -3951, -5546, -13049, -7865, -4968, -3686, -5253, -6183, -6214, -5214, -3683, -5793, -5759, -5458, -5049, -3978, -6692, -8683, -6103, -4336, -4482, -7623, -10210, -8304, -3840, -4997, -8086, -5569, -11356, -4250, -5888, -7371, -4378, -9695, -5487, -7484, -6332, -4442, -7081, -6516, -9022, -6113, -5367, -6480, -6388, -9753, -6885, -7034, -7230, -6173, -9531, -9284, -9429, -7912, -6899, -8718, -14195, -28777, -8138, -10442, -8649, -10362, -7936, -8683, -11781, -11781, -10613, -5401, -8615, -8683, -8247, -9873, -4708, -7213, -8615, -5170, -7936, -5164, -6143, -9106, -4382, -6988, -6445, -5906, -9022, -4940, -5465, -8363, -6365, -8649, -6540, -4089, -5646, 5776, 7356, 3662, -4733, -891, 4819, 6828, 3205, -2859, 332, 1246, 5321, 1950, -203, -938, 82, 3287, -24, 509, -5103, 1880, 1533, -2011, -545, -3311, 673, -508, -1247, -2386, -1726, 81, -8517, -1443, -5299, -1130, 1969, 499, -263, -3964, -234, 2762, 3183, 1844, -1575, 614, 2807, 4262, 2043, -974, 942, 2151, 4793, -92, 1499, 666, 24, 4919, 621, 3218, 66, -5031, 4265, 3095, 3609, -451, 562, 2416, 3298, 3098, -804, 2856, -732, 1155, 2234, -976, 3584, -1030, -11945, 1723, -486, 3028, 96, 444, 1906, 586, 914, 578, 1841, 1995, 1404, -2605, 808, 1760, 1269, 1355, -1232, 521, 1411, -642, -42, -377, -578, 1605, -4723, -3383, -871, -1250, 2108, -9531, -3824, -2795, -475, 2321, -4559, -3168, -3526, -563, 1969, -3714, -4250, -1292, -2276, 950, -3316, -5380, -1071, -5266, -620, -2173, -6343, -3067, -3698, -2121, -1644, -5615, -7708, -1516, -2692, -2690, -6719, -3741, -222, -2179, -5960, -8982, -1137, 155, -1559, -5097, -3615, 536, -715, -1587, -3769, -1940, 1480, -4086, -1873, -4478, -1514, 1701, -7066, -1580, -7004, -1689, 1130, -2935, -1197, -12534, -2581, -372, -3468, -1499, -10526, -5319, -3175, -6256, -2664, -4550, -3748, -11004, -2422, -4049, -1393, -977, -6074, -513, -4215, -142, -642, -3843, -126, -2155, -431, -2592, -4149, -813, 157, -2058, -7179, -8247, -2589, 1296, -3417, -4123, -5145, -6183, 1086, -3378, -3968, -1775, -7371, -866, -4258, -3215, -509, -3985, -7984, -6388, -1246, -78, -2958, -3523, -9193, -662, -246, -3490, -1799, -11004, -1445, -1325, -5353, -2192, -11629, -3367, -3906, -4486, -3496, -12534, -5844, -6026, -2701, -4831, -12776, -7796, -4693, -2236, -5662, -10613, -6553, -5183, -2350, -6225, -9106, -5853, -6388, -2388, -6899, -9284, -7213, -6235, -2458, -8363, -8454, -9429, -5759, -2839, -11004, -6773, -9193, -4569, -3689, -7146, -6365, -11629, -3529, -4826, -5494, -7179, -12534, -3365, -5516, -6445, -8718, -7984, -3876, -4649, -11781, -9380, -5584, -4654, -3117, -7730, -11356, -4097, -5286, -2355, -5888, -15615, -3521, -5897, -2443, -5710, -8423, -3860, -7317, -2999, -5853, -6899, -5292, -9753, -3383, -5768, -7113, -8393, -11232, -2979, -5437, -8517, -11488, -14784, -2084, -4957, -10799, -7819, -9812, -1522, -4559, -11781, -6480, -7081, -1630, -4478, -8517, -6399, -6540, -2505, -4795, -6516, -7130, -7389, -4230, -5306, -5897, -7644, -9238, -6143, -5827, -6388, -7146, -10899, -5380, -6870, -7603, -6666, -9936, -4219, -9479, -8086, -6759, -8009, -3785, -12123, -7583, -7464, -6457, -3710, -8304, -7542, -8790, -5630, -3701, -7936, -8649, -8903, -5360, -3910, -10899, -13049, -6214, -5494, -4679, -11004, -11232, -4795, -5862, -6321, -7562, -7484, -4478, -6288, -9331, -7130, -6492, -4901, -6113, -12776, -8549, -6457, -2505, -4842, 2010, 3905, 962, 931, -1150, 2331, 2455, 4825, 2939, 1276, 2948, -12123, 6643, 3103, 2313, 3325, 1971, 6810, 1326, 2360, 3195, 3111, 5724, -1206, 1605, 2525, 1581, 3512, 149, 81, 1509, 532, 1417, -60, -2447, 528, 2746, 835, 1160, -4805, -479, 2964, 1023, 3140, -3042, -3788, 1231, 2606, 3882, 269, -2610, 1012, 3180, 3560, 2815, 1979, 2340, 1817, 2254, 3991, 3427, 1267, 245, -174, 3757, 3255, -3526, 2637, -1163, 1815, 1866, 974, 3641, 347, -1141, 667, 2125, 4254, 427, 760, 598, 835, 5135, -1214, 1375, -187, -3487, 5450, -4168, 602, -1979, -7687, 4788, -1616, -490, -3554, -4153, 3180, 491, -645, -4274, -3927, 1757, 1151, -23, -3232, -5933, 2244, 860, 300, -1203, -9429, 2633, 495, -227, 95, -3069, 1981, 450, -1686, 478, -1450, -36, -83, -3830, -208, -1324, -4644, -1547, -6045, -2422, -1701, -6310, -3964, -8485, -6590, -855, -2226, -7019, -6628, -3571, 705, -1452, -7542, -4184, -1956, 1596, -3042, -5915, -3420, -1749, 1607, -5576, -4592, -3827, -2578, 742, -2460, -3203, -4611, -4810, -1168, -1341, -1930, -4361, -12123, -6214, -2116, -1302, -3853, -5768, -4307, -7130, -1501, -4191, -2182, -743, -4416, -1949, -4455, 17, 415, -2943, -2045, -3103, 1169, 582, -6267, -2578, -2211, 1153, 183, -2608, -3025, -2472, -375, -695, -344, -2277, -4089, -3014, -1815, -394, -2603, -10899, -1472, -1127, -2189, -5253, -4425, -875, 327, -5145, -15615, -1682, -2442, 743, -4708, -11629, -1515, -5615, 166, -3540, -11115, -3971, -4340, -688, -2787, -9639, -10799, -4184, -1343, -2785, -13365, -3744, -7389, -2690, -4093, -6246, -2950, -7523, -5509, -7066, -4303, -3600, -3161, -7562, -6814, -4348, -4451, -1787, -8060, -5827, -5776, -4601, -1865, -7623, -5897, -7464, -4495, -3365, -4907, -5339, -6928, -4946, -7583, -3817, -3808, -5844, -5793, -9585, -3692, -2564, -5380, -5273, -6516, -3425, -2257, -5524, -4104, -7730, -3001, -2971, -6194, -3457, -10613, -3433, -4161, -6928, -3342, -6773, -5718, -4373, -7113, -3763, -5970, -8363, -3889, -6786, -5152, -6988, -4635, -3830, -6590, -8865, -8982, -3482, -4683, -7004, -12534, -10210, -3656, -6376, -8718, -8165, -10284, -4399, -6354, -11488, -7230, -8112, -5085, -5189, -7562, -7247, -6083, -5836, -5133, -5415, -8034, -5494, -6615, -6173, -4842, -9936, -6343, -6745, -7819, -5472, -12123, -7281, -6074, -8827, -6943, -11945, -5751, -5472, -8363, -8247, -10284, -4564, -5710, -7281, -8034, -8865, -4207, -7130, -6343, -7247, -8112, -4348, -8942, -5844, -7081, -7665, -4382, -8517, -5599, -7708, -7130, -3873, -8220, -5451, -9380, -6692, -3071, -8982, -6204, -14784, -6759, -2517, -9429, -9429, -11945, -7113, -2597, -7842, -14195, -8517, -7603, -3624, -7034, -10799, -7936, -8220, -6054, -7644, -13365, -10284, -7196, -9106, -9193, -3674, -8086, -7445, -9812, -10799, -4541, -5997, -6153, -8086, -7426, -7623, -5020, -4504, -6814, -5451, -7299, -4573, -3501, -6759, -4779, -4473, -4266, -3306, -7542, -5306, -3920, -4046, -3766, -8454, -7097, -4940, -4142, -4635, -8683, -10138, -7687, -4907, -5451, -8549, -10210, -10526, -6540, -6434, -7984, -8192, -7936, -6640, -8549, -7213, -7230, -7281, -4929, -11004, -7066, -7623, -8718, -4323, -7888, -8615, -9812, -9331, -5073, -5970, -11945, -15615, -6577, -7796, -5037, -8615, -13738, -5437, -28777, -4611, -7230, -12776, -5623, -8192, -4513, -6745, -12534, -6973, -6492, -5273, -6173, -11232, -10284, -6235, -7484, -4963, -9695, -12123, -7179, -8790, -3853, -9193, -7097, -11115, -7984, -3701, -9873, -5319, -11004, -10001, -4805, -12319, -5115, -8112, -15615, -7230, -12319, -6267, -8009, -8683, -9531, -10526, -9022, -8485, -7213, -9812, -8827, -14784, -9380, -7130, -10899, -7426, -28777, -14784, -7888, -11781, -6759, -12534, -9479, -9238, -12123, -6692, -10138, -6267, -11356, -10526, -7146, -8517, -5061, -13365, -8903, -8549, -7583, -4853, -12319, -9331, -12123, -7389, -5444, -9936, -10899, -12776, -8060, -7004, -8754, -9064, -9193, -9639, -7562, -9695, -7842, -8393, -11232, -6064, -13049, -7819, -8423, -11356, -5615, -9331, -8247, -8615, -10613, -6469, -6719, -9193, -10069, -9331, -7353, -5208, -10442, -10362, -8304, -6602, -4620, -9812, -8393, -7819, -5879, -4985, -7708, -8304, -8034, -5686, -6256, -6267, -9695, -9022, -5638, -8485, -5960, -10613, -11781, -5654, -10613, -6773, -9531, -17034, -5743, -8549, -8683, -8454, -11004, -5592, -6615, -10526, -9106, -10138, -4874, -5924, -8942, -13365, -10799, -4112, -6246, -7730, -10704, -10899, -3893, -7426, -7623, -8423, -9695, -4433, -8192, -8454, -8086, -9193, -5862, -7774, -10704, -8138, -9639, -7708, -8086, -13049, -8060, -10613, -7730, -10704, -10001, -8220, -10613, -7162, -13365, -8683, -8942, -9479, -7484, -9429, -9193, -10138, -8718, -8247, -8582, -11488, -11004, -8718, -8649, -8827, -11945, -10704, -8615, -8549, -9193, -11115, -10069, -8754, -8220, -10284, -11629, -9479, -10210, -7426, -14784, -12319, -8942, -11945, -6628, -11629, -12776, -8615, -10442, -6434, -7708, -17034, -8517, -10442, -7213, -6480, -17034, -8393, -14195, -9695, -6504, -12534, -8192, -14195, -13365, -7281, -13738, -7687, -10069, -9639, -8333, -28777, -7230, -9380, -8517, -9479, -10210, -7113, -9695, -9064, -11232, -8192, -7299, -10526, -9284, -12319, -7960, -7426, -12534, -7984, -11004, -9193, -7819, -28777, -7730, -9695, -11488, -8903, -14195, -8718, -9585, -14784, -11356, -14784, -10138, -10704, -13365, -15615, -12319, -12534, -13049, -10362, -28777, -9936, -28777, -12534, -9238, -28777, -9479, -10799, -11004, -9238, -17034, -10001, -9585, -11004, -9812, -14195, -10704, -10799, -11945, -11629, -12776, -11781, -28777, -10799, -14784, -12534, -13738, -17034, -8982, -14195, -14784, -15615, -11629, -8192, -13049, -17034, -17034, -5554, -5502, -11115, -10284, -6759, -6153, -5472, -9531, -8790, -7371, -6973, -6492, -8220, -8138, -7562, -8112, -8718, -7562, -7936, -7050, -9022, -9873, -7819, -8086, -7542, -9284, -8423, -8683, -8790, -9022, -9064, -6958, -9479, -9753, -9380, -8942, -6074, -10138, -10001, -8790, -8220, -5997, -11629, -9479, -8485, -7353, -6540, -9429, -9106, -8517, -7752, -7371, -6786, -7912, -9585, -10704, -8582, -5862, -6577, -11232, -15615, -12123, -6492, -6163, -12534, -10704, -12319, -9380, -6615, -12776, -10704, -8942, -28777, -7371, -12776, -11232, -8086, -9812, -7687, -11945, -10526, -6914, -7888, -8138, -10799, -10442, -5879, -6928, -9639, -11781, -8827, -5853, -6332, -10362, -13365, -6870, -6602, -5970, -8333, -8790, -5988, -7984, -5818, -7583, -7523, -6016, -11115, -5942, -8718, -7865, -6653, -9380, -6692, -12534, -8363, -7426, -7445, -9429, -13049, -7523, -7665, -8034, -12776, -13049, -6469, -7665, -9585, -7865, -17034, -5979, -8192, -8060, -7335, -14784, -6434, -9479, -7665, -9149, -11629, -7408, -10613, -9193, -15615, -10069, -7081, -10210, -12776, -15615, -8942, -6653, -9531, -14195, -11356, -8276, -7281, -9064, -17034, -8423, -7730, -8165, -8683, -12776, -6928, -6943, -7888, -8138, -9380, -6973, -6422, -7562, -7542, -8615, -9064, -6516, -8220, -7484, -10001, -13049, -7146, -9936, -8165, -13738, -10526, -8086, -9695, -9149, -11945, -11115, -8790, -7865, -9479, -9531, -12776, -8903, -7130, -8485, -7503, -9753, -8517, -7774, -7644, -6376, -7865, -7888, -10069, -7888, -6204, -6719, -7371, -28777, -9936, -6958, -6615, -7583, -10069, -11488, -8582, -7912, -8827, -8034, -8086, -11232, -10284, -11629, -7912, -6842, -28777, -10284, -28777, -9531, -6914, -10704, -9936, -17034, -9585, -8112, -7960, -10362, -14195, -7912, -10799, -7819, -10442, -12776, -7888, -13738, -10210, -9149, -12776, -9873, -9106, -15615, -8363, -12776, -12776, -7353, -11232, -9284, -12123, -10899, -7389, -10526, -14784, -10799, -9149, -8485, -10799, -12319, -9639, -8192, -7464, -13365, -9238, -9531, -7774, -6422, -12776, -8615, -11004, -7960, -6828, -9585, -8615, -14784, -8865, -8517, -9585, -8827, -17034, -10526, -10362, -12123, -9639, -12123, -9873, -10138, -17034, -11629, -9331, -7796, -9149, -12776, -13365, -8086, -6705, -9429, -11488, -11629, -8060, -6705, -11232, -11115, -11004, -9022, -8165, -15615, -11232, -11115, -10526, -13049, -28777, -13738, -11781, -12534, -11488, -28777, -28777, -11629, -28777, -9531, -13738, -11115, -10799, -12319, -9873, -12123, -9639, -9639, -9531, -10210, -11945, -10001, -9064, -8982, -9531, -11232, -11115, -9106, -10069, -8363, -8982, -9812, -9331, -12776, -7865, -7503, -7984, -9238, -17034, -8485, -6899, -7113, -9695, -14195, -10362, -7081, -7019, -11488, -11115, -11232, -7819, -7542, -15615, -9936, -10210, -8982, -8683, -17034, -9753, -9585, -10799, -10704, -17034, -10210, -9106, -15615, -13365, -17034, -10899, -8790, -12776, -13365, -14784, -11356, -9022, -9429, -13365, -13049, -12534, -9531, -9331, -9695, -11629, -10362, -11945, -10001, -13738, -14195, -12776, -11004, -7034, -14784, -14195, -9106, -12776, -5960, -10069, -9873, -7353, -28777, -6035, -8649, -6828, -6332, -9753, -5970, -9238, -5531, -5759, -7426, -5726, -14784, -5109, -5897, -6745, -6492, -9531, -5299, -6745, -7081, -8982, -6553, -5702, -7623, -8649, -11945, -5654, -6113, -7503, -9753, -11945, -5888, -7034, -6045, -7687, -11115, -7317, -9284, -4901, -6457, -8276, -11356, -11488, -4759, -6026, -7019, -12123, -9531, -5630, -6045, -7004, -8009, -8827, -7464, -6365, -7644, -6842, -9106, -10210, -6492, -8582, -7213, -9695, -15615, -5988, -9812, -7708, -9639, -13365, -5480, -9695, -6256, -7730, -8582, -5085, -7623, -5472, -6225, -6640, -4693, -6958, -6354, -6113, -6204, -4464, -8304, -8454, -7960, -6828, -4460, -14195, -8333, -10899, -8086, -4759, -11781, -8393, -8718, -9284, -5569, -9064, -8903, -9479, -9639, -7019, -7796, -7066, -15615, -8754, -8942, -6653, -5933, -10799, -8034, -11356, -5879, -6026, -8649, -7353, -28777, -6064, -6786, -7353, -7034, -9585, -7583, -7247, -6759, -7912, -6528, -9639, -6800, -7130, -11356, -5516, -9429, -6225, -8165, -12534, -5853, -10069, -6204, -8827, -10613, -6842, -11781, -6870, -8649, -14784, -7665, -13365, -7960, -8393, -10613, -9149, -14784, -8220, -8683, -6914, -10069, -11781, -8009, -9479, -5678, -8060, -10138, -9193, -8549, -5726, -7752, -10613, -11356, -6828, -6870, -9639, -13365, -9753, -6007, -8615, -9873, -28777, -9238, -6299, -8649, -8393, -12319, -8485, -7730, -8423, -9429, -9284, -6745, -9873, -9429, -13049, -7445, -5718, -11488, -11115, -11232, -6388, -5561, -12776, -13738, -10138, -6083, -6026, -12319, -12319, -10442, -6267, -6692, -10799, -9429, -8903, -6565, -6732, -10284, -9149, -7264, -6928, -5951, -10284, -11004, -6615, -7936, -4885, -10069, -15615, -6745, -9936, -4180, -10899, -11004, -7247, -12776, -4250, -17034, -9531, -7644, -15615, -5286, -11232, -9812, -7984, -11781, -7213, -8683, -11781, -8790, -9695, -8112, -8754, -17034, -9106, -8982, -7912, -11629, -12534, -8754, -8485, -8683, -14195, -10799, -9238, -7984, -10704, -11629, -9873, -9531, -7936, -12319, -12776, -9106, -9479, -7912, -12534, -14784, -9022, -11945, -7984, -14784, -12534, -9639, -15615, -8363, -28777, -10138, -9639, -9936, -9064, -12776, -8304, -9479, -8549, -8517, -11356, -7299, -10210, -8034, -7623, -11004, -7179, -11115, -7523, -7842, -10001, -7796, -10613, -7408, -9695, -9380, -9531, -10526, -7912, -14195, -9812, -13738, -11356, -10001, -28777, -11781, -17034, -13738, -28777, -28777, -14195, -11945, -28777, -9429, -13365, -12123, -10138, -14784, -7708, -12534, -10001, -9106, -12776, -7936, -17034, -9022, -8790, -11356, -9479, -14195, -9022, -9380, -10704, -11629, -10613, -10001, -10613, -10526, -11115, -10362, -12123, -10799, -10284, -9531, -11629, -13738, -10138, -10284, -8827, -15615, -11629, -10704, -10704, -9284, -17034, -11004, -12319, -11629, -10613, -12123, -12534, -12319, -11488, -12534, -7912, 8129, 8421, 4616, -91, -5208, 7667, 8075, 5018, 389, -3412, 6217, 7030, 5460, 639, -1710, 3433, 5274, 5332, 427, 1114, -2217, 2927, 4709, 850, 3155, -662, 578, 3903, 1078, 3852, 970, -1786, 2948, -412, 2963, 594, -8393, 1261, -3701, -587, -1247, -2245, -2217, 919, -951, -2749, 439, -2153, 2934, 1518, -1398, 1739, -17, 3694, 1447, 72, 2577, 49, 3955, 134, 1663, 2943, -1025, 3872, -1774, 2634, 2519, -565, 3053, -2194, 2594, 766, 973, 632, -985, 1323, -4518, 1671, -1203, -1142, -2094, -979, 1525, 2144, -2555, -5183, 1761, 946, 3236, -3748, -1343, 2641, 1113, 2723, -8549, -981, 2386, 2234, 930, -3067, -1508, 953, 3135, -57, 413, -727, -2273, 3407, -346, 1639, -181, -8192, 3019, -5061, 1671, -1185, -7113, 1992, -1153, 673, -3436, -10799, 44, 2113, -1646, -1458, -4278, -4527, 3050, -5444, 107, -2885, -2182, 2826, -4064, 295, -3540, 293, 1696, -1480, -95, -2478, 637, -295, -243, -21, -812, 326, -1317, -374, 306, -1037, 1164, 100, -1299, 74, -4901, 2180, 1009, -1759, -752, -3763, 2296, 1240, -832, -1872, -349, 1388, 1079, 676, -3339, 2, -304, 441, 1219, -6064, -1645, -1207, -1156, 393, -7230, -5531, -861, -4640, -1244, -2071, -3543, -1275, -7603, -1078, 108, -2222, -3080, -4097, -773, 777, -2339, -5979, -2231, -2156, 148, -2924, -7004, -1341, -6958, -2383, -3947, -5458, -1268, -7583, -11232, -4195, -3471, -1645, -5026, -3344, -2294, -2049, -2220, -4123, -2877, -1233, -1253, -2783, -2232, -5472, -1025, -1301, -2756, -872, -10284, -589, -2064, -2294, -487, -8247, 466, -3187, -1788, -1037, -6958, 1229, -5480, -1302, -2305, -3225, 1182, -5139, -1156, -3566, -1562, 155, -1846, -1830, -5008, -1327, -2032, -539, -3886, -6679, -2234, -5487, -243, -6235, -4784, -4157, -5176, -421, -4669, -3641, -6528, -3220, -884, -4442, -3751, -8112, -2661, -1820, -5592, -5014, -8718, -3404, -3316, -6800, -7936, -8754, -5214, -3518, -7865, -7984, -10210, -6054, -2198, -10899, -8086, -14195, -5554, -1443, -11004, -14195, -9936, -4455, -1409, -6553, -6705, -8982, -2877, -1998, -3798, -5247, -10001, -1698, -3056, -1842, -6103, -11232, -1157, -3830, -744, -9429, -13738, -1310, -3612, -526, -13365, -9873, -2330, -3121, -1324, -7426, -5654, -4307, -2992, -3422, -4821, -3701, -4790, -3306, -6267, -3704, -2889, -3360, -3883, -5879, -3971, -3089, -2819, -4323, -6113, -5451, -4532, -3201, -4373, -7583, -6422, -7984, -4278, -4331, -7687, -6054, -13049, -5844, -4664, -6885, -5299, -13738, -6074, -6045, -5768, -4315, -8865, -4649, -10210, -4764, -3937, -6640, -4089, -11232, -4869, -4303, -6256, -4286, -7445, -6800, -5247, -6759, -4327, -6256, -15615, -6679, -8276, -4145, -5055, -7081, -8276, -12319, -4509, -4286, -5031, 5810, 2751, -3003, 7114, -1794, 5418, 2238, 3725, 6585, 1614, 4093, 685, 5400, 4857, 2891, 1271, 812, 4932, 2564, 1994, -6143, 2495, 2201, 3529, -1765, -4078, 2793, 446, 4063, -5646, -2043, 1563, 3779, 2944, -1987, -73, -741, 4886, 951, -3641, 1109, 535, 4795, 682, -9380, 1309, 2366, 3656, -273, -2364, 977, 3028, 1304, -5924, -327, 785, 2696, 784, -983, 822, 1122, 2017, 3220, 1278, 1077, 1885, 2691, 4575, 1727, 180, 2938, 3463, 4949, 1296, -1754, 3983, 2996, 4442, 255, -2783, 4638, 729, 2959, -985, -1745, 4593, -3589, 119, -174, -1396, 3498, -1326, -3201, 2031, -2305, 626, -854, -706, 3390, -4017, -1043, -2162, 473, 3675, -6786, 1434, -4863, -47, 3198, -6914, 1734, -11488, -1307, 2907, -2245, 728, -2637, 106, 2779, -1092, -103, -201, 1108, 1615, -884, 94, 218, 542, -373, 777, 109, -1231, -1205, 134, 1873, 98, -2015, -1610, 41, 1161, 808, 797, -1238, -2432, -2831, 1786, 2177, -2685, -10526, -3615, 2351, 2540, -3112, -6504, -1518, 2203, 2385, -201, -5480, -4352, 1230, 1832, 710, -5776, -4679, -322, 609, -284, -9238, -2265, -1097, -1628, -4564, -10442, -2677, -516, -4230, -4460, -6814, -1613, 538, -4810, -1797, -7503, -42, 1397, -6064, -2071, -10001, 538, 1530, -11356, -3814, -2455, 176, 566, -5465, -5109, 413, -1173, -2320, -3175, -3957, 1652, -3060, -13738, -3301, -2560, 1715, -3896, -3933, -4759, -1663, 636, -4262, -3641, -3449, -1377, -1990, -4336, -5121, -2095, -1987, -7299, -4064, -6225, -2019, -3763, -4795, -3479, -5437, -3154, -4115, -3618, -2863, -4123, -6016, -2204, -3776, -3058, -3656, -8615, -1599, -4089, -3873, -4307, -7019, -2412, -4195, -3529, -6565, -7687, -5014, -4713, -2694, -12123, -8903, -9936, -6653, -2657, -4795, -8754, -5444, -11629, -3347, -2709, -9531, -3751, -8304, -4478, -2605, -9812, -3237, -7004, -5494, -4078, -5458, -3286, -7019, -5702, -4688, -3609, -4161, -7019, -5401, -3010, -3449, -6958, -6628, -5516, -1701, -4473, -8982, -5970, -6399, -549, -6299, -8393, -5509, -7623, 134, -8086, -8363, -5662, -7523, 20, -8549, -3560, -6064, -6310, -985, -7708, -2178, -5853, -5638, -2893, -5451, -3085, -6411, -5743, -5615, -4527, -5472, -9936, -6133, -9106, -5827, -2956, -11945, -5970, -13365, -12319, -1656, -6885, -5273, -13738, -9585, -1994, -4319, -4951, -10442, -7730, -3644, -2833, -5710, -7247, -6299, -6842, -2720, -6565, -5380, -5306, -28777, -4315, -5546, -4644, -5702, -8423, -9149, -5279, -4659, -7796, -6133, -6842, -6885, -4698, -7842, -5662, -5444, -11781, -4161, -5654, -6602, -6988, -9531, -3465, -5164, -6705, -10210, -7623, -3324, -6016, -4810, -6615, -7034, -4180, -7752, -4060, -5408, -6885, -6183, -8754, -4683, -5576, -7066, -8982, -7730, -6540, -6577, -7426, 7775, 3486, -3409, 6394, 8147, 7302, 2951, -449, 6089, 7915, 5722, 1586, 1184, 5311, 7244, 2010, 796, 1186, 4451, 6152, -1259, 1258, -143, 3733, 4391, 3176, 1783, -1680, 2617, 2593, 4027, 2024, -818, 940, 4178, 3651, 1508, 642, 1854, 4899, 3008, -50, 1485, 2837, 3291, 2594, -1202, 1176, 2496, -949, 1762, -714, -1098, 1766, 3303, -217, -906, -9193, 1214, 4537, -4536, -1948, -20, 431, 4869, -3051, -3428, 2048, 862, 5421, 9, -5654, 2373, 1696, 5574, 1413, -4912, 1299, 1275, 5145, 1772, -1607, -880, -945, 4881, 977, 366, -679, -4644, 4832, -1743, 1576, 555, -2873, 4192, -3360, 2583, 878, -1392, 2959, 293, 3527, 613, -306, 2757, 1714, 4104, 309, -101, 3943, 2141, 4010, 797, -980, 4874, 1935, 3045, 1596, -2488, 4965, 1063, 1165, 1614, -3301, 3808, -674, -618, 227, -2893, 170, -3163, -1216, -4382, -2688, -1249, -2943, -2112, -4060, -3407, 1858, -1005, -1935, -613, -2294, 1852, 326, -1055, 170, 94, 143, 1129, -904, -427, 1297, -2583, 1531, -1292, -2635, 1298, -3665, 1668, -2020, -7730, -15, -2960, 1607, -2366, -12123, -3208, -2994, 1257, -2372, -7196, -4491, -4108, 349, -1875, -2801, -2228, -5312, -1377, -277, -804, -1556, -4754, -2490, 165, 258, -1644, -2973, -1534, -1685, 980, -2268, -1210, -632, -6666, 1193, -3923, -272, -311, -1448, 502, -7960, -698, -1348, -619, -1335, -4357, -3680, -5836, -1920, -3479, -2168, -7230, -5801, -3846, -3417, -2079, -2309, -3396, -3523, -3808, -3776, -2241, -4226, -3738, -4601, -7335, -4912, -6235, -3606, -4254, -8363, -3158, -6278, -2698, -4723, -6278, -739, -4569, -3433, -7230, -3644, -133, -3792, -7503, -9936, -2613, -839, -4555, -5988, -9106, -3357, -2545, -6504, -4654, -7984, -6103, -3208, -4764, -6225, -6365, -5401, -2424, -2701, -6899, -6800, -3316, -2280, -2060, -6628, -13365, -2724, -2745, -2776, -6745, -7583, -2871, -3360, -5444, -3735, -4985, -3254, -4211, -14784, -2288, -4219, -3078, -6214, -6310, -2404, -4010, -2121, -10362, -5049, -3913, -3957, -1096, -9193, -5273, -7097, -3840, -438, -9936, -6399, -12319, -3326, -169, -11232, -8615, -11945, -2688, -95, -10001, -10210, -11488, -2409, -150, -14195, -8138, -11115, -2670, -566, -5924, -7523, -10613, -3354, -1602, -3430, -7774, -10001, -3940, -3354, -2922, -7408, -10284, -3947, -5662, -3589, -6113, -9429, -4112, -8517, -4064, -5109, -6988, -5067, -13738, -4089, -4907, -5879, -6628, -12319, -5394, -5718, -6540, -7408, -10799, -8138, -8009, -9429, -7317, -10284, -5546, -14784, -7179, -8304, -7888, -4064, -8754, -4606, -10210, -6885, -4100, -6163, -3665, -7146, -7687, -5319, -5292, -3837, -5444, -11781, -8454, -5444, -4997, -5444, -10284, -13365, -6528, -6411, -6679, -6928, -8423, -8865, -7113, -7960, -5827, -8034, -8393, -8903, -5516, -4659, -4713, -8982, -7464, -6492, -6480, -5422, -11232, -8363, -6856, -7426, -6842, -6666, -11488, -6745, -5494, -8485, -4438, -28777, -7196, -4718, -8827, -3766, -12123, -8827, -5170, -7888, -3856, -8615, -10613, -6814, -7034, -4024, -6457, -10284, -10138, -7004, -4145, -5127, -8754, -13365, -7484, -4901, -4826, -7426, -11488, -6958, -7066, -6035, -7335, -10704, -5694, -12776, -10442, -7445, -9695, -5091, -13365, -9479, -6640, -8517, -5158, -9695, -6457, -6035, -7542, -5844, -7335, -5592, -6225, -6958, -7408, -6173, -5678, -7796, -6602, -9193, -6745, -6411, -11781, -6786, -11629, -10362, -6666, -6163, -7960, -8790, -4869, -4536, -2833, -6422, -3989, -2273, -2716, -1138, -3641, -1965, -1694, -2068, -603, -2534, -1450, -2610, -2617, -1166, -2945, -2211, -4416, -4311, -2994, -4963, -4455, -5133, -5818, -6692, -9238, -8582, -5592, -5339, -10362, -13049, -10704, -7335, -5465, -8718, -11781, -11115, -9585, -6928, -9380, -10284, -14195, -9064, -8165, -11115, -10442, -17034, -8423, -6640, -10799, -13365, -13738, -8827, -5401, -9331, -11781, -13365, -8754, -5353, -8220, -9193, -15615, -8034, -6800, -7984, -8138, -13049, -8276, -9331, -8363, -7960, -12534, -9873, -9753, -7066, -8192, -14195, -12319, -10138, -5888, -8009, -14784, -12776, -10362, -6074, -8615, -13049, -9479, -7819, -7665, -12319, -15615, -7162, -6759, -10526, -11004, -17034, -6194, -7464, -12776, -8903, -14784, -6183, -9331, -10210, -10442, -28777, -6288, -9479, -8454, -15615, -10001, -6143, -8393, -8582, -14784, -7665, -6083, -7523, -10526, -17034, -7752, -6653, -6615, -17034, -10526, -10799, -8790, -5960, -12123, -9149, -11232, -12534, -6183, -8333, -9479, -7503, -8034, -7774, -6516, -9873, -6343, -6719, -11781, -5554, -10799, -6045, -6828, -8517, -5121, -14784, -6204, -7796, -6411, -5103, -14195, -6388, -9695, -6246, -5662, -11945, -6422, -10284, -7603, -7034, -11945, -6828, -8086, -10613, -9022, -11115, -8485, -6973, -13738, -10284, -9873, -14195, -7034, -28777, -11356, -9238, -11488, -7687, -12319, -13049, -8942, -8423, -8138, -9479, -11781, -8982, -7842, -8333, -9193, -9193, -9531, -8423, -9022, -10613, -8192, -10526, -9695, -9812, -11945, -8304, -11356, -8982, -9695, -10362, -8982, -10613, -7888, -9238, -9380, -8942, -9193, -8276, -9193, -8827, -8363, -8086, -11356, -10138, -8247, -7865, -8009, -17034, -12776, -8060, -7912, -9380, -11945, -14195, -9022, -8827, -13365, -13738, -12319, -11945, -10069, -15615, -17034, -12319, -28777, -9695, -13738, -10899, -11629, -15615, -8982, -15615, -10284, -9812, -15615, -9479, -17034, -12123, -8615, -12776, -10526, -14195, -17034, -8304, -11356, -11115, -10799, -28777, -9149, -11356, -12319, -8982, -15615, -11232, -11356, -15615, -8276, -12534, -13049, -11115, -17034, -8903, -12123, -14784, -11356, -13365, -11356, -13738, -15615, -13738, -10284, -28777, -28777, -14195, -17034, -8683, -12534, -17034, -11488, -12776, -8485, -11004, -13365, -10899, -11004, -9429, -10613, -11781, -10069, -6553, -8903, -8865, -7353, -9284, -6332, -9812, -14784, -7281, -7708, -7842, -8942, -8982, -9064, -6343, -11115, -8517, -7281, -8393, -5933, -7819, -8903, -7644, -4901, -6786, -6615, -8942, -10210, -3833, -9022, -7353, -8485, -13365, -4469, -11488, -9531, -8649, -9429, -6856, -9479, -12123, -9695, -8582, -8423, -6628, -10284, -9936, -9531, -6365, -4985, -8009, -9238, -12319, -5810, -4319, -6973, -9193, -17034, -6457, -4238, -7196, -9531, -15615, -8192, -4327, -8790, -8276, -10442, -14195, -4327, -12123, -7004, -7464, -9695, -4395, -14784, -6411, -6354, -6434, -5133, -10799, -5437, -6321, -5607, -8220, -5888, -3589, -5888, -6828, -8649, -2902, -1778, -3641, -8276, -3989, -1348, -695, -2039, -4082, -2509, -972, -555, -1717, -2545, -2517, -1735, -1415, -2737, -2841, -3707, -3804, -3373, -4555, -4826, -5888, -7644, -6469, -4527, -8517, -8138, -17034, -10442, -4203, -13365, -10442, -12534, -12319, -5085, -9531, -11781, -8865, -11781, -7162, -7426, -9022, -7130, -10362, -10799, -7542, -7196, -6246, -8827, -28777, -9531, -6504, -6457, -8247, -28777, -14784, -6842, -8276, -9380, -11004, -14784, -7912, -13049, -17034, -7230, -11115, -8865, -11356, -10001, -5630, -10001, -9479, -9695, -7665, -5584, -9936, -9022, -9639, -7583, -6914, -10069, -7335, -9429, -9022, -8942, -7819, -6153, -8865, -9936, -9639, -6035, -6143, -8942, -9022, -9753, -5502, -7774, -9429, -8649, -8060, -5997, -12776, -10069, -8333, -6973, -7264, -11488, -10613, -7562, -7162, -8718, -9812, -10001, -6988, -8454, -10069, -10362, -9380, -7034, -10613, -11945, -11232, -8304, -7888, -14195, -10899, -11488, -6856, -9753, -14784, -9380, -11629, -6235, -11356, -11004, -9639, -12319, -6814, -9284, -9284, -10704, -14784, -9331, -7230, -8718, -10442, -28777, -15615, -6103, -8423, -11356, -12776, -8903, -5970, -8165, -17034, -12534, -7389, -7019, -8304, -13738, -14784, -7752, -9531, -8790, -11115, -12123, -8790, -9585, -8865, -10442, -10138, -8517, -8086, -8549, -9936, -9149, -8220, -7888, -8363, -8865, -7960, -8423, -8247, -8827, -7796, -7179, -8060, -8615, -10526, -7503, -6800, -7264, -9106, -14784, -8517, -6679, -7162, -9873, -13738, -12123, -6719, -8009, -10138, -11488, -14195, -6958, -9753, -9531, -11004, -9429, -7583, -11004, -8982, -11232, -8754, -9193, -10210, -8393, -11945, -9639, -13365, -10362, -7819, -12319, -10442, -13049, -12319, -8112, -13738, -10704, -9936, -28777, -9753, -14784, -12123, -9479, -17034, -14784, -12776, -13738, -10069, -14784, -14195, -11356, -11781, -11488, -14195, -12123, -10210, -9022, -14195, -11356, -12534, -9193, -7445, -11232, -8982, -13365, -8718, -7130, -8393, -7842, -11945, -9022, -8060, -7644, -7936, -10704, -9873, -9812, -8454, -9585, -9531, -9238, -11232, -10899, -13738, -8942, -8165, -12534, -14195, -28777, -9064, -7865, -13738, -11488, -15615, -9585, -8363, -15615, -9479, -15615, -9753, -9753, -15615, -8982, -17034, -10613, -11781, -13049, -10001, -15615, -12534, -12776, -12776, -13049, -8138, -7865, -5554, -10001, -8649, -9193, -7842, -5818, -9429, -6653, -9936, -7888, -6679, -7426, -6628, -10526, -7162, -8517, -6640, -7523, -8060, -5615, -11629, -6299, -7335, -7912, -4336, -12776, -5615, -8276, -10442, -3923, -11232, -4274, -28777, -8220, -4611, -9284, -3137, -7464, -6235, -6870, -8165, -2801, -5539, -5751, -11232, -7842, -3311, -5592, -5933, -11781, -7097, -4532, -7034, -6235, -10069, -6540, -6163, -9936, -6194, -7066, -7445, -7865, -13365, -5862, -5387, -10526, -8649, -13049, -5678, -5055, -11232, -8454, -11945, -5818, -5897, -8517, -8615, -10526, -6773, -7317, -6411, -8220, -7335, -7796, -6007, -4149, -5584, -3982, -4616, -3930, -2168, -3281, -2036, -2698, -2823, -1128, -1967, -1420, -2253, -2741, -1185, -1613, -2040, -2889, -3920, -2462, -2334, -3971, -4336, -6365, -5234, -4386, -7562, -6267, -6278, -10138, -7623, -14784, -7503, -5599, -9479, -6773, -13738, -6074, -6856, -7281, -5924, -11004, -4880, -10362, -5451, -6565, -9531, -4664, -28777, -4299, -8423, -8790, -5380, -17034, -4075, -9873, -8549, -7066, -28777, -4946, -9936, -8304, -9531, -28777, -7196, -10442, -8363, -8903, -15615, -11945, -8363, -8903, -6973, -14195, -14195, -6365, -10210, -6143, -14195, -9193, -5576, -10526, -6083, -12776, -7130, -5662, -9531, -6365, -9695, -6310, -6577, -9284, -6628, -7730, -6504, -7708, -9331, -7019, -6856, -7562, -7445, -8683, -8060, -6800, -8790, -7389, -8112, -10138, -7066, -8138, -8086, -8112, -12123, -7179, -7066, -8086, -8220, -11115, -7426, -6492, -8865, -7936, -9380, -7888, -6310, -14784, -7081, -8423, -8582, -6653, -10442, -6422, -8138, -9873, -7562, -8009, -6434, -8276, -8790, -8517, -7687, -7213, -8086, -6899, -9479, -8138, -8247, -7371, -6469, -11488, -8393, -8683, -6343, -7687, -28777, -7984, -9022, -5429, -11488, -13365, -7730, -9531, -4957, -11004, -10799, -7865, -9639, -5061, -9238, -9531, -8220, -9873, -5853, -9531, -8754, -8582, -11945, -7603, -10799, -9193, -9284, -14195, -10284, -9695, -11356, -10799, -10362, -11115, -8454, -12319, -12319, -9064, -9238, -8582, -11004, -11781, -8649, -8034, -10442, -12319, -10613, -8517, -7464, -13049, -14784, -9639, -8363, -7665, -11629, -11629, -9149, -8454, -9331, -10442, -10001, -9149, -8754, -28777, -9106, -9531, -9531, -8718, -9238, -8423, -10526, -11232, -8247, -7247, -8517, -14195, -15615, -8192, -7774, -9106, -10704, -11945, -8865, -11232, -10442, -8363, -10442, -10704, -11945, -14195, -7960, -11115, -13049, -10138, -28777, -8649, -13049, -12123, -11781, -14784, -10442, -17034, -12776, -14195, -15615, -12534, -28777, -28777, -12123, -15615, -11232, -15615, -12319, -12319, -13365, -10210, -13738, -9936, -13365, -10899, -10362, -11488, -9479, -13365, -9380, -11629, -10526, -10210, -12776, -8982, -13365, -11356, -11488, -11781, -9753, -15615, -12123, -13365, -11232, -12319, -28777, -11781, -17034, -11945, -17034, -17034, -10799, -28777, -14195, -12123, -12123, -9639, -28777, -28777, -10526, -10001, -10284, 4117, -1741, 9439, 9312, 2929, 4284, 3780, 9089, 8741, 3537, 3546, 5573, 8139, 6969, 2777, 77, 5538, 6789, 3793, -832, 507, 4484, 5032, -1375, 2805, 1841, 4026, 2905, -4071, 3685, -490, 4578, 1425, -2758, 2398, 458, 4783, 2331, -3201, 1941, 2624, 4456, 3865, -749, 2661, 2622, 3622, 4037, 2250, 1839, 2018, 2369, 2478, 3507, 644, 2440, 1644, -681, 3310, 3949, 3087, 2569, -214, 2662, 6229, 3034, 3999, 1167, 3524, 7221, 2032, 4742, 2237, 4177, 7205, 1220, 4302, 3191, 3378, 6255, 1632, 2944, 3826, 324, 4266, 755, 3572, 3941, -5662, 652, -3412, 4796, 3351, -770, -8165, -3357, 4906, 1831, 557, -985, 358, 4203, -1154, 1485, 947, 3721, 3249, -5266, 2252, 1828, 5710, 2217, -2133, 3012, 2522, 6438, 254, -589, 3494, 3352, 6161, -3589, -192, 3259, 3915, 5106, 963, -496, 2047, 3842, 3530, 3031, -504, -223, 2924, 1435, 3332, -164, -1337, 954, -1360, 2077, -599, -29, -2297, -866, -1878, -2659, 1208, -4373, -668, -883, -9531, 2301, -707, -6504, 1977, -3968, 3284, 981, -403, 2637, -1710, 3956, 1025, 2695, 1865, -885, 4103, 302, 3660, -1123, -897, 3684, 222, 3544, -3586, -1897, 2782, 35, 2671, 818, -4331, 1276, -1210, 1024, 1553, -6773, -1669, -2617, -1780, 71, -4527, -4478, -2152, -2730, -5670, -3860, -1207, -1155, -566, -2241, -4123, -442, -263, 373, -511, -3007, -1201, 340, 491, -918, -1462, -3367, 250, 208, -2363, -759, -6759, -1057, -143, -3065, -858, -4795, -4550, -870, -2470, -1504, -2823, -9873, -2795, -2651, -2312, -1758, -7936, -5374, -4215, -3254, -1158, -6299, -2873, -5085, -4923, -1030, -3927, -1384, -3594, -8304, -1410, -3342, -940, -2659, -8827, -1766, -3583, -1076, -1906, -6705, -1193, -4049, -1614, -1075, -5726, -683, -5221, -2495, -660, -4795, -1190, -6553, -3583, -1224, -4262, -3252, -6163, -4679, -3641, -4429, -10001, -5960, -5306, -9193, -4564, -4134, -5836, -4295, -5085, -4270, -1272, -5234, -3135, -5458, -4386, -361, -4718, -2859, -9812, -4630, -674, -4664, -3744, -6745, -2861, -1711, -5472, -5312, -5109, -1241, -2348, -8304, -4991, -4425, -891, -1728, -5818, -4738, -4278, -1773, -806, -3342, -5221, -6214, -3968, -556, -2918, -3989, -10138, -7542, -1268, -3856, -2881, -4826, -11232, -3067, -4974, -3175, -3760, -8865, -6153, -4713, -5465, -4473, -5531, -8942, -3720, -12776, -6388, -3662, -7464, -3069, -5726, -8517, -2941, -5014, -3378, -3650, -8827, -3294, -3076, -5061, -3274, -8192, -4123, -1979, -8086, -4683, -8086, -3937, -1515, -8683, -9936, -9064, -3546, -1564, -5818, -4616, -8982, -3523, -1957, -3741, -1935, -7484, -3319, -2576, -2992, -1060, -6814, -3227, -3629, -3638, -1564, -6365, -3404, -3479, -6615, -3879, -6235, -3566, -2186, -9531, 6803, 9364, -4743, 4275, 9806, 6092, 8981, -377, 4063, 9215, 3944, 7910, 1949, 3178, 7333, 886, 6396, 2910, 2059, 3891, 539, 4752, 3404, 2191, 1230, 2443, 3137, 3821, 2050, 2253, 2887, 2212, 3979, 886, 2908, 935, 2848, 3917, -157, 2637, -1532, 3687, 3734, -219, 1128, 1752, 3753, 3302, -985, -1205, 2359, 2832, 2821, -2288, -2016, 1916, 716, 2936, 264, -266, 2262, -3396, 3667, 1652, 1017, 2916, -293, 4315, 1773, 1691, 3217, 2884, 4483, 1961, 2831, 3601, 4208, 4235, 2651, 3658, 4113, 4035, 3815, 3109, 3289, 4379, 1922, 3346, 2946, 1350, 4232, -4258, 2606, 1940, -2472, 3801, 545, 1129, 540, -4968, 3411, 1727, -1748, 1032, -6235, 2953, 1598, -4698, 1944, -4693, 2074, 634, -4513, 1989, -2300, 757, -121, -4486, 2266, 700, -1212, 2880, -918, 3610, 2747, -1140, 4536, 460, 4539, 3819, 1327, 4779, 542, 4573, 4236, 2028, 4032, 1154, 4013, 4197, 881, 2632, 1796, 3564, 3842, -3010, 736, 1195, 3340, 3341, -3692, -1967, -945, 2819, 2825, -1001, -7335, -3729, 2154, 2324, -172, -9585, -3404, 2086, 1895, 379, -9753, -2977, 2253, 1590, 868, -7464, -4184, 1805, 1304, 925, -4382, -4230, 159, 876, 240, -5067, -2104, -4336, 667, -1389, -4810, -1882, -2749, 1094, -3201, -1576, -3606, -125, 1286, -2071, -437, -4654, 30, 482, -1386, -1085, -2873, -1636, -1678, -2569, -4455, -2055, -2859, -5014, -7050, -6914, -1747, -1120, -6016, -5630, -2958, -1727, -1106, -7299, -2686, -3668, -2101, -3342, -9284, -1620, -8192, -2082, -5494, -7066, -1754, -1736, -1399, -3515, -6870, -3149, 466, -749, -3449, -5751, -6800, 1016, -236, -4826, -3662, -8276, 385, -15, -5374, -2675, -3147, -1336, -179, -3339, -2437, -1522, -3808, -489, -2068, -2378, -1380, -5326, -975, -2128, -2409, -2273, -4991, -2112, -3903, -2815, -3785, -4184, -4625, -8220, -3748, -5115, -4142, -11004, -7097, -3893, -5176, -6143, -4764, -6653, -2510, -4403, -9479, -2203, -7730, -1546, -3833, -4708, -1125, -5429, -1141, -4049, -3766, -1216, -2813, -684, -4703, -4733, -2958, -1710, -160, -4299, -5020, -9106, -2054, -124, -3512, -3401, -6113, -3741, -712, -3560, -2661, -5367, -6083, -1682, -4433, -2673, -9284, -7464, -2952, -5202, -3040, -9873, -7603, -5253, -5139, -3779, -6943, -5960, -7484, -4764, -5115, -6628, -3606, -5451, -3951, -8165, -5253, -1947, -4847, -3412, -7603, -3154, -1143, -5502, -3744, -4089, -1949, -1174, -7264, -5049, -2926, -1984, -2088, -7583, -6973, -2964, -2871, -3101, -5260, -7317, -3529, -3383, -2129, -4504, -6814, -3937, -4153, -1065, -5451, -7665, -4086, -6828, -1231, -7912, -8393, -4946, -5208, -2937, -12776, -6988, -6973, -3714, -4191, -7146, -6434, -5422, -5097, -2644, -4238, -7464, -3490, -13738, -2661, -4157, 5486, 3550, 4844, 8175, 8460, 5170, 3253, 3870, 7568, 8093, 4392, 2279, 1352, 5729, 7079, 3654, 309, 2109, 3368, 5881, 3139, -3668, 2386, 2603, 5308, 2364, -8718, 25, 1314, 5027, 954, -4592, -1019, -1668, 4008, -1091, -5694, -124, -885, 1579, -2493, -5401, -2617, 1393, 2270, -812, -468, -3650, 2522, 4231, 1549, 1044, -4078, 2252, 4803, 3187, 1508, -2751, -310, 5157, 3896, 2408, 242, -2160, 5623, 3491, 2656, -224, 2457, 5488, 1534, 1314, -926, 3846, 4459, -2553, 733, 1956, 3667, 2790, -1379, 1855, 2803, 2220, 1933, -639, 1429, 1960, 41, 2406, -1353, 895, 35, -1813, 2323, -2060, 2131, -1625, -13049, 1137, -1410, 2833, -2186, -281, -752, 498, 2583, -1550, 2102, -2289, 2368, 1526, -1194, 2105, -1291, 3310, -269, -1906, -200, 423, 2948, -2686, -3580, -5988, 1673, 944, -6035, -5227, 44, 2718, -748, -8549, -4336, 1949, 3219, 624, -3420, -2696, 2753, 3215, 240, -1534, -1060, 2976, 3404, -2350, -1011, 456, 2636, 3995, -3354, -1177, 1455, 1662, 4339, -1947, -1081, 1825, 307, 4072, -2610, -688, 1728, -275, 3103, -5097, -1049, 1468, -274, 1509, -4145, -2833, 1249, -1048, -3, -1979, -5694, 910, -2216, -152, -1130, -4127, 189, -751, -208, -1515, -2531, -918, 877, -835, -4262, -2002, -1690, 1630, -395, -4395, -1661, -840, 1837, 461, -897, -621, 139, 1759, 545, -180, 34, 72, 1428, 226, -1002, -608, -1502, 841, 222, -1966, -2914, -4847, 164, 579, -1713, -4451, -3612, -274, 639, -1577, -4319, -2460, -340, -86, -1999, -7865, -3054, -164, -1470, -2859, -8009, -4127, 94, -2163, -4433, -4303, -2969, 286, -2071, -7097, -2997, -1438, 197, -2385, -8086, -2427, -750, -224, -3085, -6411, -2945, -831, -647, -3757, -5615, -5630, -1552, -668, -4290, -5897, -6628, -3189, -624, -4963, -7984, -2752, -7034, -1196, -5531, -7162, -2084, -11488, -2897, -3860, -3399, -3433, -7687, -5429, -1557, -1965, -3365, -4795, -4644, -287, -2211, -1878, -2088, -3354, 54, -4664, -2297, -765, -3352, -291, -11488, -4963, -507, -5768, -1282, -3707, -4399, -1078, -6577, -3203, -2057, -1956, -2407, -2091, -3992, -1900, -1040, -4769, -717, -1906, -2507, -1232, -8790, -824, -740, -2735, -2528, -6163, -2170, -543, -2407, -4234, -5546, -5638, -1051, -2666, -4108, -8790, -7426, -2071, -3853, -4153, -5502, -2971, -2943, -5576, -5576, -2823, -1522, -2783, -6653, -5888, -2222, -1382, -2201, -6332, -4447, -2897, -2361, -1945, -5615, -4172, -4142, -4901, -2239, -5743, -4635, -4262, -8790, -3237, -7603, -4348, -3978, -5554, -4997, -8754, -3632, -3261, -4130, -6666, -4447, -2597, -1600, -3535, -6288, -2571, -1420, -776, -3560, -4869, -2213, -1073, -1289, -5326, -2952, -3149, -2082, -3218, -8247, -1549, -6719, -5997, -3763, -2377, -3992, -3662, -4254, -4985, -5202, -2762, -2493, -2635, -11356, -6113, -3760, -2419, -1961, -4907, -3076, -4659, -2787, -2257, -2323, -2555, -1855, -2967, -3487, -2100, -3266, -850, -2670, -5897, -3856, -5061, -1705, -2414, -9585, -5408, -10138, -4842, -2644, -7865, -2825, -6133, -9639, -3757, -6457, -1792, -3449, -10362, -6321, -6814, -1902, -2835, -7752, -8112, -10362, -2628, -3436, -3653, -4491, -8165, -3930, -5061, -2342, -2330, -4238, -6411, -7146, -2232, -1533, -2910, -5623, -7247, -2560, -2306, -3184, -3027, -6828, -2813, -6278, -5319, -2311, -6469, -2641, -4743, -7503, -3465, -4469, -1841, -1353, -3704, -4968, -1794, -867, -386, -1854, -2222, 59, -291, -631, -1258, -1011, 840, -452, -1650, -1797, -1335, 566, -1607, -3069, -3883, -2512, -619, -4211, -4764, -9380, -3641, -2355, -7774, -6376, -9695, -5818, -4282, -5718, -6225, -8827, -11629, -4968, -4816, -5429, -10362, -4064, -3165, -5853, -4559, -6354, -2305, -1973, -10362, -3665, -3916, -2135, -1928, -6705, -3289, -3261, -2754, -3036, -3388, -4042, -3903, -3566, -4104, -2140, -7113, -4559, -4270, -3621, -2326, -10704, -4460, -4352, -3893, -3886, -5408, -5678, -3714, -5569, -7066, -4003, -11945, -3683, -4863, -11356, -3723, -8363, -5043, -3441, -7730, -4130, -6388, -8549, -3626, -7335, -5374, -5686, -6504, -5247, -8060, -8220, -4460, -4112, -7583, -4311, -17034, -3650, -3194, -8192, -2510, -6786, -3543, -3007, -7371, -2286, -3975, -3766, -3276, -7960, -3087, -2610, -3947, -3824, -8192, -3999, -2271, -4408, -4500, -4769, -5127, -2739, -5472, -5152, -3126, -9238, -3779, -6692, -5367, -2837, -8423, -4748, -6528, -4764, -3476, -5394, -4795, -6246, -4357, -4769, -5784, -4733, -6914, -4974, -6204, -8865, -5630, -7708, -6653, -6310, -11115, -8086, -7213, -7523, -5592, -9695, -11232, -5836, -6267, -5592, -9022, -8649, -4703, -4336, -6814, -6445, -6885, -4238, -3144, -6943, -3886, -6256, -4112, -3362, -4348, -2540, -6870, -4112, -5451, -2793, -2488, -7317, -4918, -5408, -2306, -3732, -5176, -7503, -3056, -2690, -6278, -3638, -9380, -2420, -4049, -10138, -2859, -7004, -2865, -6026, -8517, -2594, -7335, -3741, -5827, -5638, -2885, -12776, -4282, -5326, -5152, -3923, -8034, -4195, -5988, -6504, -5879, -5710, -4164, -6732, -7299, -9479, -6103, -4997, -7213, -6143, -12123, -8138, -7130, -8333, -6026, -9585, -9064, -8903, -9479, -6719, -10362, -11115, -10210, -8363, -7066, -17034, -12534, -12534, -6504, -6214, -11232, -8754, -7371, -5292, -4896, -7936, -8086, -5988, -5020, -4108, -5906, -7644, -6007, -5759, -4207, -4869, -6759, -6204, -7796, -5260, -4923, -6016, -5654, -9022, -7230, -6434, -5183, -4759, -7464, -8034, -10704, -4460, -4270, -7264, -6705, -6590, -4352, -4625, -8192, -6310, -3913, -4863, -5933, -8827, -7445, -2891, -5915, -7912, -8304, -12319, -2992, -7484, -7960, -7213, -10138, -9380, -3198, -4853, -4295, -8247, -5208, -4573, -3269, -5286, -4901, -2557, -9106, -3225, -4863, -2065, -1252, -7542, -3662, -5561, -1290, -945, -4390, -4583, -6928, -994, -1398, -3222, -6928, -6800, -747, -2217, -2823, -28777, -4683, -983, -3344, -2512, -6540, -3242, -1728, -6354, -2286, -4420, -3471, -2276, -8827, -2631, -4104, -6016, -2254, -3543, -3827, -4416, -8615, -2257, -1908, -5702, -4145, -6842, -2597, -1442, -7426, -3846, -8827, -3412, -1750, -6163, -4089, -28777, -5227, -2910, -4433, -4412, -9331, -9873, -4880, -3913, -4583, -5401, -5654, -6445, -5127, -5234, -3870, -2733, -8942, -7644, -7097, -4357, -1243, -7960, -2900, -4940, -3049, -371, -2897, -697, -2018, -369, 88, -1191, -128, -795, 869, 184, -1080, -729, -956, 933, -136, -2139, -2060, -2672, 54, -1031, -3735, -3042, -7774, -1542, -2696, -4482, -3367, -7264, -3399, -5374, -4478, -3820, -4935, -5360, -9380, -4369, -4504, -5888, -8060, -14784, -4142, -5429, -8393, -9639, -15615, -3324, -5638, -5202, -10284, -28777, -2351, -4003, -3266, -8363, -12123, -2019, -2683, -2657, -6153, -8827, -2455, -2333, -3352, -5862, -8247, -2631, -2492, -6278, -5871, -5801, -1885, -2223, -8683, -4115, -3683, -1462, -1820, -4935, -2724, -3309, -1690, -2053, -4024, -2566, -4513, -2232, -3080, -4064, -4024, -5253, -2517, -4451, -4286, -8086, -3714, -2739, -4784, -4728, -4625, -2716, -4060, -3951, -6267, -2622, -2462, -8485, -3254, -13365, -2336, -2751, -8165, -3003, -5465, -2941, -3521, -6732, -2766, -2605, -3754, -4743, -8942, -2455, -1535, -4157, -6528, -17034, -2562, -1482, -4336, -7503, -11232, -3239, -2075, -4620, -5726, -7583, -3754, -3128, -4541, -4089, -4460, -3940, -4429, -4616, -3271, -2875, -4759, -5346, -6256, -3352, -2730, -6814, -5109, -8903, -4460, -3782, -10138, -4606, -5801, -7146, -4597, -13738, -4997, -4759, -17034, -4145, -12319, -5043, -5061, -8754, -4164, -10362, -3515, -5988, -7034, -4810, -11004, -2789, -7687, -7034, -4985, -12534, -3391, -8423, -6246, -4649, -12534, -5584, -7562, -4464, -4478, -9936, -11945, -7484, -3653, -3732, -6615, -8112, -6988, -3896, -2578, -5374, -5374, -6719, -4708, -2130, -5853, -4683, -7888, -5546, -2867, -8333, -5801, -10284, -6958, -5408, -15615, -11232, -8827, -8683, -10442, -12123, -7687, -7912, -6399, -7603, -9479, -5801, -8790, -4907, -7562, -6885, -6773, -8827, -4901, -9479, -5437, -10442, -6310, -6299, -11004, -5401, -8615, -5061, -9284, -9531, -7066, -7464, -5127, -13049, -7936, -12319, -6943, -6615, -13049, -7796, -11115, -5234, -10138, -11488, -9106, -7230, -3992, -8865, -11356, -11356, -5031, -3686, -7097, -11781, -11356, -3804, -4093, -7130, -11232, -8304, -3741, -4713, -8582, -9193, -6123, -5195, -4754, -12534, -7960, -4842, -9479, -4006, -13049, -8304, -4311, -8903, -3191, -9873, -11356, -4504, -7213, -3025, -8982, -10069, -5862, -8333, -3863, -8718, -6870, -5247, -4654, -6411, -3069, -1035, -7730, -4555, -7819, -1087, -1342, -5793, -2967, -4473, -272, -2170, -2918, -2353, -2538, 8, -3001, -1487, -1935, -1790, -342, -3540, -1089, -1391, -1646, -1800, -4266, -1343, -995, -1936, -3040, -5735, -1846, -942, -2416, -1246, -7445, -2502, -1150, -2128, -392, -7081, -4060, -1581, -1503, -831, -7317, -6445, -2747, -1493, -2198, -8304, -4067, -5879, -2066, -3692, -7213, -2385, -13738, -2741, -4382, -5451, -1823, -8454, -3304, -4693, -4078, -1647, -7842, -3961, -5026, -3906, -1611, -7503, -4184, -5494, -4469, -2280, -8865, -3814, -5253, -3334, -5014, -10526, -5686, -4821, -2962, -4963, -4779, -5793, -6143, -5509, -1939, -1962, -893, -5339, -5801, -1399, -953, 636, -2308, -2420, -2447, -1412, 543, -889, -1892, -3827, -3210, -730, -471, -3133, -3080, -5793, -2355, -653, -6577, -2703, -7562, -2999, -1036, -7644, -4017, -8865, -3334, -1310, -4923, -6399, -10210, -3788, -1838, -4703, -4748, -9812, -3717, -3144, -6988, -3916, -9936, -3266, -4583, -8393, -3689, -8247, -3201, -3957, -5793, -3252, -6504, -3441, -3128, -7389, -3158, -5768, -3457, -3119, -6914, -3281, -5759, -2950, -4093, -3047, -3242, -6590, -2303, -6692, -2143, -2924, -9284, -2162, -11356, -3069, -1932, -12534, -2743, -6093, -5735, -1068, -6759, -3751, -4234, -8192, -985, -4597, -4664, -3444, -6457, -1686, -3314, -5227, -2646, -5299, -2897, -2437, -5253, -2032, -4718, -4559, -1932, -4559, -2176, -4142, -7445, -1959, -3367, -3051, -3378, -28777, -2960, -2257, -3840, -2677, -6988, -5888, -1494, -3889, -2366, -4262, -7371, -1097, -3279, -2641, -2988, -4968, -1021, -2743, -3249, -2762, -5326, -1308, -3184, -3428, -3409, -7034, -2049, -5437, -3087, -3850, -7264, -3208, -15615, -2939, -3321, -8034, -4207, -6745, -3698, -3244, -11004, -4157, -4597, -6083, -4203, -12776, -4119, -3529, -9238, -5844, -11945, -5292, -2458, -11232, -6692, -6988, -9812, -1581, -11115, -5615, -4679, -8363, -1255, -6856, -4013, -4203, -4985, -1556, -7752, -3065, -5524, -4219, -2495, -11356, -2926, -9695, -4923, -3961, -5127, -3347, -12534, -7299, -5221, -3580, -3779, -13738, -11115, -5394, -3704, -3735, -8790, -6457, -5487, -5346, -3485, -5879, -3493, -5751, -11004, -3311, -4800, -2051, -5401, -7523, -3276, -4097, -1771, -4399, -5008, -3493, -3249, -2398, -3569, -4569, -4164, -2488, -3490, -3474, -4654, -5176, -2023, -4336, -4482, -4357, -5951, -2102, -4784, -7389, -4049, -5979, -2962, -5401, -9238, -4115, -5776, -4382, -7213, -6354, -4064, -6267, -5759, -12319, -5897, -3798, -7936, -8485, -12534, -6943, -3933, -9639, -11945, -8982, -8582, -4478, -10284, -6828, -6870, -8363, -4754, -11629, -6074, -6183, -7503, -4863, -10442, -6914, -7019, -7146, -5516, -7730, -8333, -8276, -7004, -5818, -6278, -8790, -7130, -6204, -5109, -6214, -7960, -6445, -5067, -5214, -7213, -7050, -7113, -4564, -6653, 8198, 5825, 565, 6157, -726, 8211, 6039, 937, 5454, -1500, 7961, 5718, 1930, 2821, -1419, 6996, 3610, 3491, -2125, 778, 5105, -701, 4384, 2225, 1888, 2860, 2874, 3799, 2570, 1659, 1944, 3990, 757, 6, 290, 2955, 3960, -313, -4550, 736, 4407, 3787, 2482, -13, 2463, 4907, 3661, 2428, 1038, 3412, 4593, 3283, 160, 2893, 3943, 4378, 2556, -6653, 4867, 4183, 4084, 3063, -2468, 5775, 4065, 2255, 4607, -936, 5456, 3534, -2251, 5324, -1104, 3646, 2312, 637, 5050, -2286, 152, -54, 1147, 4049, -2288, 1191, -2440, -34, 2488, -1036, 2116, -2567, -18, -227, -804, 1244, -4290, 1057, -7113, -1859, -1124, -6516, 1512, -4416, -3569, -5055, -2477, 1477, -1324, -3920, -6054, -589, 1325, 33, -2380, -4064, -160, 762, -497, 55, -1526, -1123, -42, -3455, 1225, 705, -3501, 694, -2492, 1104, 1705, -2016, 1467, -1420, 769, 1596, 43, 1437, -4223, 1187, 339, 402, 1444, -1094, 918, -3930, -1041, 1311, 1932, -814, -2984, -3964, -87, 2749, -571, 483, -760, -4067, 1963, 1360, 691, 598, -11781, -884, 1887, -1220, -117, -9193, -5292, 1071, -1963, -2268, -7081, -2286, -1614, -180, -1212, -3618, -2590, -10210, 186, -399, -1580, -3367, -1739, -271, -1497, 119, -1307, -209, -666, -2229, 1094, 208, -312, -470, -27, 1304, 583, -1302, -130, 1320, 1171, -440, -1944, -270, 1714, 1237, -3624, -1451, -1228, 1456, 1535, -2159, -400, -2783, 980, 1626, -77, 549, -3580, 757, 1075, 81, 654, -3140, 555, -480, -854, -543, -2197, -50, -3856, -1857, -3220, -1787, -894, -11115, -1628, -2835, -2587, -1603, -4311, -553, -1333, -3695, -2292, -3056, 260, -1349, -2020, -2916, -2982, 472, -2470, -460, -3080, -3140, 130, -3557, 129, -3126, -2797, -666, -2879, -131, -4100, -2022, -2007, -1925, -1522, -7984, -1648, -4473, -1732, -5862, -9022, -1961, -9331, -2541, -5516, -6163, -2875, -7004, -4693, -1872, -7034, -4203, -5888, -9873, -937, -7484, -6354, -6577, -6628, -914, -6422, -8192, -6256, -3523, -1178, -6399, -4853, -4587, -2443, -1405, -6885, -3543, -3603, -2986, -1479, -7888, -3985, -3574, -6035, -1498, -7912, -6054, -4254, -8138, -1556, -5686, -7984, -5189, -5043, -1677, -4254, -5630, -6321, -5810, -2093, -3827, -3701, -7562, -11115, -3005, -4464, -2432, -7389, -8060, -4625, -6153, -1654, -6828, -7019, -7819, -6679, -1536, -8247, -8393, -17034, -5360, -2342, -9695, -7389, -7984, -5103, -4203, -5638, -6194, -7353, -6679, -5279, -4918, -7299, -8718, -14784, -5164, -6732, -11781, -8718, -8034, -6388, -12776, -7389, -9106, -6528, -8827, -13365, -5686, -17034, -7865, -14784, -13365, -5793, -9873, -17034, -8865, -9531, -6828, -8549, -8454, -5942, -8333, -7796, -9331, -5183, -5387, -8903, -7503, -9380, -3754, 1488, 4732, 5435, 3299, 860, 2075, 3934, 4830, 2558, 1286, 2330, 1112, 2417, 1071, 1434, 1165, -8363, -3886, 2056, 1478, -1660, -4616, 2254, 3008, 2384, -1958, -10362, 2932, 2279, 2697, -718, -3479, 629, -65, 1658, -270, -1728, 11, 1675, 800, 77, -2100, 3171, 3169, 2379, -347, -1384, 4349, 2465, 3936, -3521, 511, 5009, 619, 5251, -852, 2031, 5436, 3324, 6009, 2604, 3193, 5140, 4662, 5949, 3812, 3872, 3587, 3984, 5094, 3644, 3951, -497, 399, 3731, 2084, 3418, -3961, 651, 2635, -1610, 2150, -303, 3766, 2558, -978, -292, -478, 4689, 2681, 720, -2050, 274, 4780, 1965, 118, -1257, 2008, 4519, -164, -2843, -2743, 2550, 4088, -4184, -7004, -3179, 1817, 3563, -3798, -3860, -1303, 299, 3029, -3076, -3940, -2207, 505, 2487, -4115, -6469, -6235, 1721, 1771, -5214, -7213, -5394, 1936, 830, -4606, -2642, -6800, 615, -7, -4042, -706, -3289, -4299, -335, -1880, 224, -629, -1722, -274, 326, 795, 420, 779, -327, 1319, 1012, 995, 639, -702, 1040, 654, 1419, -1532, -1244, -445, -207, 1283, -1665, -1869, -2528, -804, -170, -231, -2112, -2962, -937, -5401, -1052, -2047, -1992, -1880, -2900, -3944, -2583, -605, -2653, -581, -2295, -3704, 611, -1237, -618, -710, -4451, 1218, -912, -1821, -88, -3085, 1122, -2241, -2902, 337, -823, 645, -5091, -1728, 559, 342, 452, -7081, -194, 312, 296, 440, -3393, 847, -706, -910, -13, -696, 1511, -3036, -3067, -868, 661, 1809, -6565, -4089, -1280, 971, 1570, -4532, -3222, -1412, 392, 500, -3698, -2879, -2223, -1051, -1976, -3689, -3707, -3554, -3563, -8220, -2958, -5662, -4545, -7708, -6153, -2225, -5686, -5055, -8165, -5031, -2030, -4863, -4816, -8582, -6870, -2188, -5480, -4764, -17034, -15615, -2677, -7034, -5387, -7299, -10526, -3618, -8683, -6225, -6653, -13365, -4784, -7960, -7464, -9238, -8549, -5735, -6828, -8718, -6299, -4693, -6083, -7081, -6745, -3569, -3329, -5997, -6628, -5554, -2073, -3242, -6343, -5726, -6692, -1243, -4089, -8138, -5260, -9936, -1058, -5686, -11629, -4064, -5630, -1614, -6988, -9639, -2895, -3863, -3023, -7097, -10899, -2377, -3425, -5827, -7264, -6914, -2443, -3754, -9695, -7665, -3184, -2885, -4532, -5326, -7281, -1505, -3407, -5240, -3668, -6288, -1109, -3896, -5810, -3779, -5531, -1808, -4569, -5801, -5836, -5319, -3409, -5164, -5170, -8363, -5879, -4564, -5380, -4923, -4968, -7264, -4195, -5810, -4991, -3940, -8423, -4108, -6492, -5020, -4649, -7562, -4779, -6705, -5189, -7066, -5933, -5561, -6083, -5853, -10799, -5214, -5472, -5531, -7019, -8333, -5569, -5176, -5623, -8454, -6225, -6705, -5646, -6504, -9429, -5292, -8333, -7019, -8192, -10001, -5326, -12123, -8790, -10526, -9479, -5997, -12534, -9479, -11115, -7299, 6416, 2356, 4664, 4031, -5299, 5458, 1289, 4241, 3522, 3198, 1889, 1076, 3307, 2987, 5682, -4035, 3271, 3179, 3621, 6467, 59, 4035, 3779, 3662, 5954, 1569, 3567, 3884, 2134, 4082, 2618, 1938, 3351, 1349, 1174, 1829, -1816, 2461, 3482, -75, 696, -2000, 1162, 3919, 2162, 3512, 195, -3866, 2144, 3865, 5329, -174, 928, 1771, 3107, 5968, 2492, 4503, 4015, -511, 5618, 4771, 5457, 3596, 3888, 4171, 5142, 4513, -1174, 5022, 1539, 3408, 845, 2442, 3508, 593, -4985, 461, 4277, 1141, 911, 1157, 2545, 3506, 3875, -508, 2441, 2172, 332, 4892, -2675, 1350, 582, -8615, 4703, -1820, -1203, -755, -6321, 3747, -788, -3971, -398, -7464, 2446, -422, -4918, 387, -3692, 1952, -274, -5394, 804, -1739, 1899, 15, -7984, 865, -494, 1162, -218, -28777, 590, -50, -82, -1703, -8827, -114, -985, -533, -4795, -6163, -1497, -4119, -419, -5710, -4226, -4134, -1442, -325, -5319, -3792, -13049, 877, -304, -5444, -4688, -5360, 1446, -1034, -1832, -3843, -2853, 881, -1636, 495, -1986, -2173, -539, -513, 1571, -1239, -2722, -2480, -15, 1774, -952, -3996, -5026, -761, 1241, -701, -5346, -8060, -1784, -104, -1099, -7179, -4266, -891, -2424, -2472, -4176, -2655, -268, -4307, -3557, -1370, -2465, -664, -2546, -2875, -335, -2845, -877, -605, -1921, -770, -3067, -707, 113, -1986, -2306, -2276, -1312, -1001, -2125, -2260, -961, -2552, -6800, 205, -1553, -26, -3680, -3230, 1694, -2138, 262, -6411, -1366, 1734, -2295, 14, -6759, -2095, 468, -1256, -340, -2545, -4219, -1418, -1221, -522, -1363, -7050, -2198, -2366, -1086, -1909, -10362, -3119, -3306, -2743, -4258, -6856, -5451, -2386, -6214, -8276, -6692, -7299, -1541, -8942, -7936, -12534, -6321, -1470, -6163, -8517, -7019, -4968, -2194, -4172, -11232, -4134, -4386, -3769, -3465, -11781, -3409, -5437, -6602, -3923, -6194, -3735, -7097, -11488, -4307, -4403, -4447, -3782, -12534, -3487, -4295, -5091, -1998, -10899, -3058, -5121, -5924, -1595, -6422, -4053, -5951, -7888, -2160, -4968, -8247, -6235, -12123, -3532, -5458, -6692, -6679, -8517, -5458, -7984, -3465, -8454, -6590, -7665, -13365, -2592, -9106, -6064, -10001, -15615, -2795, -7019, -6814, -6035, -12776, -3577, -6225, -9873, -3856, -8454, -4555, -5202, -8754, -3294, -7687, -5415, -3827, -6194, -3951, -8754, -5888, -3140, -5836, -5531, -8276, -5516, -3276, -6628, -6194, -7708, -4774, -3910, -7623, -5195, -10442, -4683, -4698, -7752, -4482, -10210, -5759, -5906, -7888, -4219, -6590, -8393, -8165, -9936, -4319, -5988, -9585, -15615, -28777, -4929, -6759, -6973, -9149, -9585, -6553, -7034, -5924, -6828, -7888, -11004, -5793, -6759, -6083, -6007, -9106, -4790, -11945, -5615, -4527, -6434, -4620, -8034, -5480, -4238, -6214, -5273, -5480, -6343, -6343, -9238, -6773, -8009, -3386, -8683, -7960, -7113, -7213, -3776, -8009, -7162, -10362, -7708, -4536, -5339, -7665, -11356, -10069, -5031, -4195, -9873, -7819, -11629, -4997, -4199, -12319, -8034, -9936, -5208, -4382, -10526, -10284, -9106, -6123, -4035, -8982, -12776, -9479, -7665, -4180, -7960, -14195, -13049, -7796, -5546, -7865, -10613, -10069, -6388, -8304, -8754, -7464, -6565, -5465, -11781, -9429, -5879, -5546, -4896, -13049, -10069, -5970, -6214, -5014, -8549, -7687, -7097, -8649, -5924, -9936, -6288, -7281, -13738, -6480, -8790, -5031, -6988, -8220, -5458, -10284, -6492, -9284, -12776, -9936, -304, -622, 154, -394, 27, 3828, 3713, 4003, 3698, 4086, 5846, 5794, 5951, 5755, 6050, 6437, 6405, 6546, 6426, 6623, 5763, 5698, 5893, 5839, 5941, 3711, 3461, 3829, 3848, 3851, -232, -1519, -371, -255, -389, -8865, -5630, -10362, -11115, -14784, -11232, -3671, -7113, -7426, -6973, -15615, -5458, -12123, -10284, -11488, -11781, -7484, -10442, -7774, -12123, -8034, -7708, -7081, -8086, -10284, -7408, -8009, -5312, -9639, -8790, -8718, -10442, -5115, -14784, -8649, -9479, -13738, -6133, -11004, -9064, -7408, -11781, -8393, -8247, -9585, -6310, -12776, -10704, -7542, -9639, -6958, -8683, -10210, -7888, -9479, -9639, -6256, -11356, -8790, -10210, -17034, -5202, -17034, -8683, -13365, -14784, -5031, -15615, -7842, -28777, -13049, -5360, -10613, -7708, -17034, -12123, -6183, -8247, -8790, -14784, -12319, -7583, -8304, -11488, -10799, -14784, -9380, -11629, -11781, -8165, -15615, -10899, -14195, -10704, -7264, -11232, -11004, -10001, -11945, -7687, -8649, -9479, -9429, -13365, -9284, -7113, -8423, -9812, -9149, -10899, -6445, -8423, -10704, -7408, -10362, -6786, -9284, -11356, -6899, -9331, -8423, -9149, -9531, -7247, -8718, -11945, -8423, -7665, -8683, -8363, -11356, -8165, -6679, -11232, -8247, -9064, -7984, -6814, -10704, -8304, -8454, -8086, -8454, -10069, -8827, -9331, -8582, -10362, -9873, -9193, -11629, -9284, -8754, -9479, -8517, -11629, -9936, -8517, -9531, -8138, -10284, -11232, -10069, -10704, -8790, -10138, -15615, -13738, -13049, -10138, -9531, -13049, -15615, -14784, -10362, -8112, -10799, -15615, -12776, -9639, -7281, -10362, -15615, -11232, -9753, -7542, -8903, -13365, -10138, -11488, -8454, -7984, -12534, -9812, -28777, -8790, -8485, -14784, -10069, -14195, -9531, -10210, -28777, -10001, -11115, -12319, -11356, -12776, -9479, -9936, -17034, -11356, -11232, -8942, -9873, -14784, -11488, -11004, -8754, -11004, -14784, -11945, -11488, -9238, -15615, -11781, -11781, -11781, -11356, -13365, -10613, -12319, -12776, -28777, -10799, -10899, -13365, -13049, -13049, -11356, -11629, -13738, -11356, -11781, -15615, -10704, -14195, -10704, -13049, -28777, -9873, -13365, -10899, -14784, -28777, -10210, -11004, -12123, -14195, -14784, -11781, -10613, -15615, -13365, -14195, -14195, -11115, -14784, -13049, -17034, -13049, -11945, -12123, -11356, -28777, -12319, -11781, -11004, -9753, -14195, -6365, -9753, -9238, -7113, -5810, -6492, -8903, -8615, -5115, -5751, -6745, -8276, -8009, -4541, -7842, -6153, -7623, -8363, -4858, -12319, -5599, -6332, -10613, -5836, -7196, -6321, -5079, -12776, -7708, -5702, -8718, -4569, -10442, -10704, -5422, -10069, -4831, -8790, -11945, -5531, -11356, -5630, -8138, -13365, -5818, -12123, -6480, -7936, -7796, -6640, -10284, -7019, -7687, -5079, -8247, -11356, -7247, -7445, -4021, -8903, -12319, -8942, -8615, -4157, -6943, -9695, -12776, -10613, -5055, -5776, -11356, -10001, -8112, -6973, -7665, -8393, -7066, -5599, -7644, -8304, -17034, -7842, -10362, -10704, -10899, -463, -258, -579, -346, -735, 3740, 3829, 3777, 3803, 3715, 5796, 5856, 5835, 5855, 5858, 6417, 6453, 6427, 6491, 6529, 5751, 5747, 5709, 5866, 5905, 3657, 3566, 3521, 3875, 3843, -577, -903, -882, 30, -296, -28777, -15615, -8982, -7130, -7081, -7004, -6943, -8615, -10284, -7623, -9479, -5662, -11488, -11004, -7230, -11945, -5266, -9429, -10799, -6343, -10799, -6332, -9238, -15615, -8718, -10210, -8112, -8582, -10138, -11356, -11232, -11945, -8423, -9753, -11488, -12123, -17034, -7335, -11232, -11945, -12776, -10899, -6615, -17034, -13365, -17034, -8718, -6928, -28777, -12123, -13738, -8009, -8009, -28777, -7503, -9149, -8454, -8009, -13738, -5487, -7842, -9695, -6786, -10899, -4784, -8165, -10613, -6553, -10613, -5158, -10001, -10210, -7730, -11232, -6590, -10704, -9639, -9585, -10526, -9193, -9331, -8615, -9812, -9585, -12319, -8982, -8220, -9429, -9936, -14195, -8865, -9531, -9429, -12534, -17034, -8086, -13049, -10799, -28777, -13738, -8086, -10284, -13049, -14784, -10613, -8790, -9753, -10362, -17034, -7984, -7888, -12534, -8790, -13049, -6745, -7113, -14784, -7796, -11629, -6828, -7523, -12123, -7019, -11356, -8192, -8827, -11115, -6759, -11115, -10526, -10899, -10138, -7264, -10138, -11356, -11232, -9639, -8649, -9284, -9936, -11004, -10704, -10799, -9695, -9106, -11945, -12776, -13365, -11945, -9149, -10704, -11945, -17034, -28777, -9873, -8683, -10069, -17034, -13738, -10899, -8485, -9331, -12776, -12776, -11629, -9695, -9936, -11004, -14195, -11945, -11781, -12534, -10442, -28777, -12534, -13738, -14195, -10613, -17034, -12319, -14784, -10799, -11781, -12534, -10526, -14784, -8982, -14784, -11004, -9064, -13738, -8086, -12319, -10442, -8903, -13365, -8333, -10442, -10362, -10069, -13365, -10001, -10704, -10613, -13049, -14784, -14784, -12319, -11629, -28777, -17034, -13365, -12123, -14195, -14784, -17034, -11232, -11004, -28777, -13049, -13738, -11488, -11356, -17034, -11781, -12776, -13738, -13049, -17034, -11629, -11488, -17034, -12776, -17034, -12534, -10284, -15615, -11945, -17034, -14195, -9639, -15615, -12319, -28777, -14195, -9873, -28777, -13365, -15615, -12534, -11115, -28777, -14195, -12319, -12534, -13365, -14195, -14195, -11488, -13365, -15615, -13365, -14195, -12123, -14784, -15615, -15615, -13365, -14784, -15615, -14784, -17034, -11629, -28777, -17034, -13365, -28777, -10799, -17034, -15615, -5253, -8454, -6615, -5133, -8982, -7865, -28777, -7865, -6054, -28777, -9639, -10442, -8333, -8138, -10001, -8865, -13738, -8615, -9812, -7912, -9380, -10210, -8718, -9284, -7445, -8485, -7752, -8165, -9531, -8865, -8060, -8363, -6732, -12534, -12534, -9380, -9812, -5726, -13365, -8247, -8649, -9429, -5694, -9331, -6885, -7247, -8827, -6103, -7665, -6943, -7796, -8827, -6973, -6914, -7426, -9873, -9479, -8754, -7730, -8517, -10704, -8718, -9238, -14195, -10442, -9753, -6332, -7230, -10284, -8865, -11488, -6288, -6679, -10613, -10613, -8485, -6914, -6899, -7019, -7484, -9531, -6870, -6773, -6204, -8517, -466, -145, -95, -355, -422, 3651, 3885, 3750, 3753, 3830, 5698, 5914, 5730, 5808, 5899, 6308, 6529, 6341, 6438, 6532, 5592, 5882, 5697, 5793, 5904, 3327, 3857, 3651, 3756, 3930, -1577, -60, -461, -267, 173, -7796, -8649, -11629, -10001, -5951, -6899, -9695, -8060, -11232, -6870, -13049, -11488, -10001, -9193, -6786, -9284, -9238, -8393, -7213, -6745, -9531, -8333, -8942, -8615, -6602, -8086, -7665, -10799, -11781, -6103, -7097, -7113, -12534, -9380, -6278, -6615, -7066, -13049, -7936, -6814, -6705, -8276, -11945, -8718, -7353, -7264, -9812, -12534, -13049, -7865, -9331, -9284, -28777, -11945, -8754, -28777, -8790, -11004, -8827, -11781, -11004, -8982, -9106, -7912, -15615, -9284, -9753, -8683, -7888, -9585, -9106, -10526, -8454, -8982, -8333, -9585, -10210, -8247, -12319, -8903, -11488, -8718, -8517, -14784, -10362, -10799, -7665, -9695, -10210, -9106, -7960, -7730, -10069, -8423, -7819, -6732, -8790, -8754, -7687, -8009, -6745, -10001, -7842, -7984, -9873, -7819, -9639, -7503, -9585, -13365, -10362, -8454, -7603, -13365, -13049, -17034, -7542, -8060, -13738, -12776, -17034, -7050, -8865, -11945, -17034, -12776, -6732, -9812, -11781, -15615, -9639, -6540, -10526, -12319, -11356, -8754, -6773, -10442, -12776, -10210, -10362, -7408, -9639, -13049, -10210, -10799, -8247, -9284, -13738, -10526, -8333, -8903, -9695, -13049, -11629, -7426, -9106, -10899, -11781, -15615, -7523, -8982, -11781, -10526, -28777, -8333, -9064, -11115, -10284, -17034, -9639, -9753, -11004, -11004, -28777, -11004, -11356, -12319, -10704, -17034, -11115, -11945, -17034, -9695, -12123, -10613, -10704, -17034, -9753, -11356, -11004, -10001, -13738, -11004, -13049, -11629, -9639, -12319, -14784, -14784, -10799, -9812, -12319, -28777, -13738, -10069, -9812, -14195, -11945, -12319, -11004, -9106, -17034, -9812, -11781, -14195, -8790, -14195, -9106, -12534, -12776, -9695, -14784, -9753, -13365, -12534, -12123, -17034, -12319, -12319, -13738, -28777, -11945, -28777, -11356, -12123, -28777, -10613, -28777, -12319, -11488, -28777, -11115, -14784, -12123, -13049, -15615, -12776, -11115, -9639, -28777, -17034, -14195, -10613, -8582, -28777, -28777, -13049, -11629, -8247, -28777, -14195, -11004, -12319, -7912, -28777, -10899, -10799, -11781, -8009, -17034, -9936, -11781, -12123, -8649, -13738, -10284, -12534, -13365, -9585, 13663, 14366, 4813, 9113, 11708, 13034, 13853, 4611, 8494, 11025, 10985, 12278, 4030, 6553, 8801, 6567, 9566, 4556, 3159, 4258, 23, 5985, 5758, 1153, -1510, 4596, 3621, 5802, 1683, -3940, 4343, 4039, 4320, 489, -3597, 2011, 4334, 2002, -489, -2114, 583, 3693, 2781, 2757, 2647, 3150, 2999, 3816, 4459, 4923, 3320, 3110, 4217, 5034, 5775, 1425, 3950, 4379, 4757, 6105, -2950, 4772, 4336, 3451, 6336, -4779, 5028, 3919, 436, 6201, -1146, 4583, 3020, 206, 5210, 888, 3344, 2187, 2548, 2965, 1294, 1055, 2540, 2995, 508, 1023, -2831, 3195, 2080, 1107, 250, -3920, 3249, 899, 1211, -3422, -2881, 2700, 2154, 958, 1131, -3707, 1843, 3627, 1307, 4062, -4060, 550, 4293, 1474, 4927, -2178, -2010, 4267, 970, 4235, -928, -2791, 3646, 26, 1260, -346, -392, 2637, -1267, -3707, -201, 601, 1883, -1302, 1531, -1050, 632, 1692, 3, 1726, -1791, -271, 1323, -476, -535, 412, -2737, 283, -2330, -4810, 1448, -5227, -1626, 131, -5718, 1085, -2871, -4307, 1252, -4536, 95, -3425, -8454, 590, -364, -333, -2939, -7960, -143, 2446, -253, 306, -3792, 1164, 3844, -286, 1537, -2555, 1973, 3894, -777, 1300, -1574, 1533, 2500, -2628, -71, -1296, -489, -1166, -3121, -2726, -3433, -5670, -3792, -128, -8582, -8485, -6235, -58, 854, -7687, -2871, -6143, 1347, 377, -7730, -2181, -5759, 1924, -1303, -6183, -2034, -3184, 1734, -4352, -4901, -1175, -1961, 690, -6123, -6163, -380, -1114, -1276, -4134, -6434, -104, -255, -4373, -3757, -3147, -476, 242, -4180, -3269, -1111, -1338, 104, -2061, -2219, 166, -2512, -538, -1373, -1912, 685, -4003, -1385, -1579, -1990, 342, -4191, -2155, -2162, -1939, -832, -3269, -3213, -2741, -2222, -2703, -2967, -5960, -2692, -3177, -4837, -3360, -10138, -2100, -4946, -7464, -4119, -7264, -1641, -7960, -17034, -5208, -7912, -1717, -6457, -6163, -7603, -10526, -3117, -3422, -4688, -10362, -11629, -9873, -2331, -5694, -4713, -12123, -4805, -3354, -8220, -2881, -14195, -2801, -9380, -10442, -2935, -28777, -3447, -5569, -8423, -4078, -9149, -6445, -4630, -5853, -5031, -3927, -10362, -5208, -4369, -5818, -1274, -6123, -4115, -2705, -9238, -275, -4299, -4246, -1044, -6786, -542, -2567, -5085, -193, -2811, -1527, -2231, -4769, -594, -1943, -2416, -3638, -4795, -2257, -2841, -3760, -5607, -6354, -3386, -5115, -7445, -4826, -12123, -2664, -8982, -11945, -3455, -8485, -2128, -9873, -8304, -2768, -6814, -2460, -6786, -9531, -2829, -8790, -4532, -7034, -10210, -3428, -9873, -9639, -10613, -6480, -4238, -8112, -11232, -11115, -5623, -4386, -10799, -7408, -12123, -5319, -3916, -9106, -2730, -8034, -5103, -4319, -8393, -1135, -5539, -6332, -6093, -9936, -994, -4447, -7019, -10362, -8393, -1819, -4451, -8220, 8822, 6405, 7399, 8736, 8940, 8108, 6463, 6945, 8230, 8444, 6300, 5574, 5860, 6894, 6892, 4971, 1103, 5156, 5220, 4105, 3752, 1794, 5631, 3523, 308, 941, 4355, 6534, 2315, -1042, -1475, 3609, 7092, 1064, -262, 2831, 2053, 7104, -2149, 141, 5010, 3075, 6424, -2136, 967, 5572, 3899, 4428, -3080, 2160, 5193, 4063, -1720, -3971, 2729, 4869, 3813, 3597, 729, 2838, 5201, 3285, 5870, 2287, 2616, 5477, 3139, 6462, 2691, 1934, 5416, 3392, 6174, 2617, 1037, 5274, 2939, 5375, 2343, 409, 5104, 835, 4338, 1477, 20, 4546, -6434, 3082, -1333, -794, 3018, -3301, 1368, -551, -3161, -1070, -3110, 82, 2614, -7752, -1746, -8485, 427, 3135, -2280, 2055, -6928, 76, 1302, -39, 2952, -4674, -1500, -1419, 786, 2431, -367, -2659, 1626, 321, 516, 1682, -2716, 2762, -2399, -3096, 2207, -1478, 3437, -4842, -5170, 1807, 292, 3899, -40, -6480, 826, 1054, 3570, 669, -6422, -1270, 853, 2182, -1006, -2841, -10001, -349, -527, -1803, -1647, -1090, -4195, -5524, -187, -1622, 1487, -3321, -7752, -444, -1934, 2397, 37, -5576, -772, -613, 2402, 782, -4991, -122, 1514, 1893, 341, -4315, -382, 2946, 1275, -874, -2813, -1966, 3649, 905, -2939, -385, -2994, 3805, 447, -6705, 1507, -1546, 3452, -891, -8086, 2821, -1213, 2358, -2705, -4234, 3670, -2559, -119, -2245, -2073, 3915, -4115, -7179, -2847, -282, 3381, -3521, -2299, -6732, 646, 1818, -2195, -74, -2236, 308, -1558, -804, 581, -606, -1475, -5584, -561, 125, -1294, -3961, -1442, -2034, -1497, -2772, -3249, -499, -8138, -2528, -1841, -2152, -958, -3546, -1837, -1595, -2038, -2450, -634, -2030, -2883, -2504, -4258, 264, -2891, -5208, -2893, -4266, 104, -3498, -6786, -3304, -3571, -714, -4049, -6299, -5195, -3726, -1544, -3975, -5020, -8683, -3971, -2061, -3776, -3471, -3027, -2982, -3042, -4810, -2534, -1400, -2198, -5152, -5524, -3170, -1548, -2393, -8683, -4234, -6870, -3309, -3577, -7623, -2933, -6343, -6093, -5079, -5115, -1865, -4447, -4500, -5260, -4442, -1204, -4518, -4625, -3944, -4769, -918, -4215, -8649, -3393, -5333, -1063, -4234, -5020, -4038, -5759, -2000, -5871, -4500, -4659, -6267, -4108, -7865, -6173, -4491, -6814, -6870, -6204, -2407, -4386, -6679, -9429, -6256, -920, -5037, -6133, -7562, -5408, -1164, -3735, -5387, -4805, -4369, -2677, -2198, -5646, -4299, -4089, -5085, -2396, -6434, -5097, -3843, -6026, -4592, -5502, -6504, -4464, -5221, -6194, -5067, -6899, -7050, -5906, -3182, -5951, -5879, -14195, -10069, -2356, -7130, -5509, -5339, -7796, -3476, -8423, -5333, -2999, -3944, -5494, -15615, -5710, -2583, -1894, -5465, -9331, -8165, -3291, -989, -7665, -9149, -6540, -3370, -1182, -7730, -10526, -7353, -3507, -2797, -5933, -9238, 7163, 3687, 5260, 8213, 6927, 7099, 2930, 4980, 7774, 6104, 6680, 494, 4202, 6396, 3805, 5330, -2238, 3077, 4062, 3177, 2075, -2030, 1648, 2540, 3088, 1958, 913, -385, 3181, 857, 3995, 2958, -693, 3621, 2641, 4066, 3034, 1153, 3868, 3757, 3306, 881, 1696, 3399, 2009, 2354, -2000, 1067, 1075, -7335, 972, 1108, -542, -2813, 1110, -754, 2354, -2477, -681, 1451, -1726, 2622, 1049, -1597, 1460, -3038, 2053, 3143, 894, 2779, -4559, 424, 3398, 2886, 2453, 1076, -2425, 1810, 3045, 1969, 3164, -1512, -599, 1551, 4105, 3482, 703, 1603, -2733, 5065, 2147, 1542, 2633, -4086, 4530, -3331, 2566, 2539, -2406, 2913, 76, 3736, 2075, -5286, 2058, 3235, 4006, 1889, -3621, 2842, 4099, 3106, 2235, -1203, 3599, 3643, 834, 2223, -1038, 3658, 1940, -3701, 1122, -2016, 2423, -1124, -4357, -1084, -3574, 113, -4071, -4378, -1717, -5031, 1767, -2879, -5158, -511, -2135, 3054, -760, -1125, 505, 548, 3064, 974, -66, 1112, 2247, 2563, 2056, -524, 927, 3215, 1915, 2428, -1174, -555, 3404, 1122, 2253, -1849, -4064, 2614, 788, 1757, -2546, -4997, 329, 1078, 931, -3546, -2900, -5401, 1319, -44, -6422, -567, -2659, 1296, -811, -2208, 732, -833, 861, -1465, -1203, 497, -430, -227, -904, -3296, -324, -495, -1476, 583, -10899, 290, -957, -1272, 1293, -2485, 515, -2176, -1158, 596, -350, -718, -4438, -2345, -1813, 460, -2560, -5408, -2924, -2211, 262, -3230, -5487, -956, -522, -364, -4053, -4805, 120, -213, -522, -2793, -2733, -241, -1401, -573, -1804, -2594, -2897, -5387, -1062, -2271, -5020, -4640, -6856, -2235, -3257, -12319, -1258, -4460, -4509, -3215, -9479, -1044, -5214, -7247, -2801, -3944, -2756, -4038, -11629, -2226, -1211, -4754, -1913, -7583, -1734, -355, -4923, -1044, -4352, -2238, -647, -4640, -1345, -4640, -4728, -1616, -3396, -2811, -9380, -8304, -2655, -3490, -5516, -5638, -5862, -2514, -7146, -9106, -3215, -7230, -1398, -6163, -12534, -2817, -7281, -679, -3126, -9238, -3399, -4795, -641, -3618, -7034, -4010, -3577, -981, -8192, -6885, -4935, -2589, -1117, -7523, -9585, -7865, -2090, -989, -5818, -10613, -6577, -2225, -910, -7842, -7665, -5127, -2641, -1227, -10284, -7179, -5702, -2793, -2450, -7445, -7179, -6469, -3020, -5718, -5871, -6103, -6516, -3729, -10069, -4664, -5599, -6204, -4693, -6083, -3964, -6332, -5710, -5615, -6016, -3906, -7213, -5933, -6354, -6899, -4601, -6457, -6434, -7066, -7503, -6958, -5183, -6653, -8363, -10613, -11629, -4821, -7213, -8517, -7912, -5827, -5127, -9331, -7888, -5333, -5008, -3782, -10001, -6133, -5516, -5871, -3242, -8485, -4664, -7912, -6692, -5353, -11115, -4464, -9873, -7317, -28777, -8517, -4246, -5997, -9639, -9284, -7130, -3971, -4805, -11629, -9106, -5623, -3029, -4323, -5451, -6204, -4112, -4089, -4035, -3659, -5299, -4191, -5743, -5346, -4130, -4447, -7603, -7523, -8138, -5801, -3479, -8683, -7066, -8454, -7317, -3252, -6343, -5247, -6093, -13049, -4307, -8220, -3760, -5319, -7247, -6133, -8363, -3580, -5121, -4980, -6590, -10526, -5480, -4266, -5630, -6422, -11629, -8582, -5189, -6183, -8903, -6173, -4274, -10442, -5576, -5458, -3391, -2406, -4491, -5346, -6083, -9238, -5906, -4536, -6615, -3594, -4527, -5844, -2210, -2393, -5073, -4974, -5444, -4425, -7708, 1869, 1882, 1049, 1145, 1714, -6035, -8192, -4104, -7984, -7066, 8644, 8718, 8778, 8646, 8552, 12957, 12975, 12939, 12875, 12866, 15047, 15028, 14991, 14946, 14945, 15688, 15638, 15619, 15581, 15573, 15034, 14952, 14964, 14925, 14906, 12932, 12802, 12877, 12820, 12782, 8632, 8327, 8645, 8488, 8397, -6528, -2889, -3769, -8903, -5915, 1222, 2427, 1013, 1494, 1667, -7408, -2831, -4042, -6828, -5509, -3170, -7426, -2312, -3641, -2776, -10899, -6388, -4901, -11488, -7603, -7426, -2621, -4278, -6204, -4858, -10138, -3518, -6103, -10704, -6679, -5394, -5073, -7865, -8718, -13049, -8363, -4369, -7623, -5326, -12534, -7034, -3306, -4896, -3689, -10799, -7912, -4187, -6016, -4373, -9753, -14195, -6480, -8754, -4743, -4874, -10001, -8718, -9695, -5266, -4748, -9429, -9022, -11232, -6666, -8582, -10069, -8086, -12123, -7583, -9936, -11488, -9531, -10799, -10442, -6278, -9380, -10799, -8683, -9873, -5247, -7484, -8549, -9585, -10704, -5374, -6163, -6973, -8138, -13365, -7066, -5933, -6045, -6354, -12776, -9531, -6759, -5768, -6153, -11945, -10799, -10001, -5662, -7752, -11781, -6235, -9873, -4997, -8582, -9531, -4157, -7888, -5539, -8485, -7130, -4559, -9531, -8454, -9380, -5458, -6719, -11629, -10899, -6590, -4795, -7004, -7066, -8582, -4821, -5026, -6602, -5933, -8112, -4587, -6026, -7730, -6914, -8060, -5924, -8165, -9753, -8034, -8165, -9238, -11488, -10362, -6988, -8582, -11945, -9479, -10799, -8034, -8517, -10526, -9812, -12776, -15615, -9238, -9064, -17034, -13738, -10526, -10001, -9873, -11781, -9022, -9284, -9284, -13738, -10704, -7162, -8942, -10799, -17034, -11488, -6480, -6914, -28777, -12776, -10362, -6856, -6504, -10284, -11232, -9585, -9429, -8304, -7842, -28777, -9585, -14784, -9812, -6786, -10442, -10799, -8333, -12319, -6786, -9695, -11945, -8192, -14784, -7623, -8060, -8485, -10442, -11004, -9639, -6590, -7842, -11115, -11629, -13365, -6973, -9331, -10362, -13738, -12319, -8423, -11115, -8790, -10613, -12534, -10138, -8942, -6628, -7464, -10799, -10799, -7687, -5546, -8247, -7484, -11945, -9064, -6173, -17034, -5195, -28777, -13738, -9149, -11115, -4486, -17034, -10284, -17034, -11781, -5055, -11781, -8138, -15615, -14784, -5933, -10284, -7819, -11232, -10899, -6354, -11781, -9284, -8827, -8790, -6773, -15615, -12776, -8009, -7665, -7623, -14195, -28777, -8903, -7730, -9331, -12123, -28777, -10210, -11004, -4307, -6577, -6590, -7389, -5776, -4923, -13365, -6256, -8582, -6885, -6445, -11488, -6321, -11488, -11781, -7730, -9380, -7644, -6235, -6870, -6640, -11781, -6653, -5702, -4858, -8423, -6516, -6842, -6153, -3349, -8086, -4713, -15615, -5997, -2956, -5960, -4282, -10138, -5346, -3586, -6516, -4774, -8582, -3975, -3493, -5942, -5195, -5176, -4142, -2552, -9695, -2924, -3354, -8649, -2383, -11781, -1787, -2612, -5979, -8060, -4683, -5195, -4583, -9331, -4504, -1870, -3425, -3391, -3012, -7408, -8903, -9639, -4847, -7371, 1023, 1298, 733, 1225, 1518, -6235, -6732, -4935, -3870, -8649, 8697, 8728, 8774, 8757, 8620, 12889, 12938, 12926, 12920, 12889, 14951, 14991, 14962, 14962, 14956, 15584, 15612, 15572, 15578, 15579, 14929, 14946, 14892, 14903, 14907, 12833, 12834, 12757, 12777, 12785, 8538, 8507, 8347, 8410, 8461, -6553, -9585, -5158, -7752, -12534, 1497, 1372, 1741, 1370, 603, -4625, -8790, -6422, -5970, -8423, -7484, -2807, -3339, -2589, -2065, -5539, -7484, -9064, -6064, -3811, -3071, -8718, -5480, -7335, -2463, -5678, -8276, -7665, -10001, -4130, -6692, -4299, -11629, -7408, -6093, -6007, -5273, -13738, -9639, -7912, -3529, -7264, -13738, -5273, -9022, -3474, -6914, -6958, -5897, -8060, -4357, -5319, -4748, -7299, -7752, -4805, -5546, -5726, -6732, -11232, -4518, -7888, -9812, -7687, -9812, -4698, -10210, -10069, -9331, -7247, -6093, -9639, -9695, -6679, -7408, -7464, -11115, -9639, -6310, -7623, -8549, -12319, -7708, -8827, -7464, -8718, -8304, -7034, -14784, -8718, -8942, -7623, -8333, -12319, -10899, -8304, -6732, -10138, -8363, -9380, -8393, -5678, -10001, -8333, -10613, -8683, -5592, -7445, -10001, -15615, -8615, -7247, -7050, -10613, -11629, -9022, -13049, -8138, -8982, -7426, -8393, -12319, -8649, -6914, -6054, -7562, -8827, -8192, -5554, -5678, -7842, -7113, -8615, -5158, -6445, -10069, -6565, -8865, -5458, -8754, -14195, -7389, -7819, -5623, -8304, -14784, -8982, -7960, -5158, -7865, -14195, -9284, -9022, -4620, -8060, -13738, -10001, -9284, -4674, -7623, -11629, -9531, -8942, -5516, -7389, -10001, -8865, -8485, -6899, -8827, -11629, -9380, -8485, -7162, -10704, -8582, -7796, -7842, -6267, -8754, -6828, -6856, -7752, -6225, -9022, -7708, -7445, -9284, -7281, -9812, -10526, -7523, -10362, -7503, -9022, -11629, -7019, -10899, -6399, -10138, -10210, -7247, -14784, -6093, -28777, -10138, -8034, -10799, -7299, -9585, -11488, -10210, -9639, -10799, -7583, -10284, -13738, -9531, -14195, -7130, -7687, -9936, -9936, -9531, -6422, -5871, -10069, -10284, -7583, -6123, -5942, -28777, -10613, -8220, -7408, -7819, -10210, -11004, -12534, -8454, -8718, -8649, -10899, -12534, -7912, -7865, -9193, -10069, -11232, -8683, -8009, -11629, -9149, -11629, -10069, -9193, -17034, -9380, -11781, -10899, -11781, -9753, -9873, -11115, -10799, -14195, -8615, -10138, -9331, -9936, -14195, -8582, -9064, -8903, -9284, -11004, -6615, -4323, -5546, -7464, -7984, -6074, -4408, -7146, -8304, -6870, -6553, -3798, -6528, -7484, -7842, -8865, -3689, -7796, -5286, -10210, -6870, -4134, -8034, -4578, -10138, -6343, -4031, -4831, -2960, -7730, -9639, -2918, -3964, -1644, -6064, -6705, -2709, -4523, -2032, -6235, -4805, -3641, -5531, -3804, -7066, -4006, -3498, -5915, -3133, -8363, -3563, -3031, -13049, -2590, -4573, -3496, -2594, -6553, -2954, -6246, -14195, -4545, -6469, -8903, -3121, -3375, -4616, -2267, -3985, -4708, -3900, -3314, -5546, -5055, 1399, 1967, 2093, 896, 1351, -7623, -6928, -8549, -3824, -5743, 8664, 8640, 8637, 8910, 8824, 12887, 12912, 12897, 12993, 12948, 14942, 14968, 14952, 14998, 14964, 15560, 15579, 15567, 15588, 15559, 14886, 14896, 14890, 14893, 14870, 12760, 12763, 12765, 12748, 12730, 8405, 8412, 8417, 8354, 8329, -5924, -13365, -9022, -7562, -6103, 1189, 779, 1209, 1178, 1529, -7113, -4442, -7542, -12319, -7162, -2817, -1299, -3996, -2751, -3422, -7819, -5569, -12123, -9429, -9380, -5743, -7542, -4748, -6504, -5836, -14195, -6064, -10899, -14784, -9193, -6640, -5266, -6354, -6480, -6504, -7960, -5933, -9022, -7819, -8790, -7912, -5546, -10138, -13738, -10799, -7888, -7097, -8485, -9753, -12776, -10442, -13738, -6842, -6653, -9429, -9812, -12534, -6093, -7984, -9193, -6988, -8363, -7281, -10362, -9149, -6540, -7523, -8276, -7353, -7865, -7445, -7162, -7335, -6321, -6343, -7819, -8549, -8034, -6310, -5654, -6786, -17034, -8247, -7299, -5710, -7130, -10442, -6988, -8112, -5784, -10210, -10799, -7464, -7230, -5924, -13738, -10210, -7912, -7389, -6163, -8165, -7583, -8903, -11488, -5933, -5380, -5592, -10799, -10362, -5576, -4769, -5494, -8549, -9193, -7335, -5312, -6445, -5933, -8517, -8220, -5599, -6679, -4997, -8333, -6540, -5380, -5862, -4901, -9429, -7081, -5960, -5853, -5437, -10362, -8582, -7819, -7464, -7004, -9873, -9873, -9380, -9531, -8649, -11356, -9479, -7984, -8304, -8086, -13738, -7583, -6469, -7066, -8034, -8827, -8009, -6457, -7281, -10001, -9193, -14195, -7774, -7752, -10704, -9531, -7050, -8549, -6153, -10899, -8649, -6399, -9238, -4940, -8982, -9695, -9284, -11781, -5247, -6615, -7984, -17034, -9479, -7130, -6365, -5569, -10069, -8517, -9193, -8086, -5014, -9284, -8982, -8790, -10526, -6310, -10362, -8790, -7644, -10704, -10526, -11781, -7603, -7066, -14195, -10442, -9639, -6958, -7317, -17034, -8393, -7426, -7179, -8454, -14784, -8485, -6800, -7464, -10001, -13049, -8454, -7353, -7179, -10138, -12776, -8485, -8276, -6973, -9149, -12123, -9812, -9479, -7752, -9695, -9106, -12319, -14195, -10138, -10799, -7281, -12123, -10613, -13738, -7842, -6800, -11945, -8304, -14195, -6321, -7960, -14784, -9639, -13365, -6288, -10799, -14784, -15615, -13738, -7623, -13738, -13049, -28777, -14195, -10526, -15615, -12776, -17034, -14784, -12776, -14784, -17034, -15615, -13738, -11232, -11356, -14195, -28777, 12983, 8466, 12344, 11392, 6461, 12380, 8703, 11634, 10869, 5922, 10364, 8737, 9285, 9233, 4385, 5508, 8522, 4691, 6360, 3469, 3990, 8762, 3806, 2616, 4362, 6738, 8873, 3098, 927, 4760, 6552, 8370, 1133, 3740, 4637, 4825, 7566, 1153, 4516, 4528, 505, 6857, 585, 2372, 4276, 326, 6123, 1571, -416, 3811, 3583, 5147, 2412, 4610, 3586, 4122, 3992, 2286, 5935, 3851, 2898, 3285, 1987, 5780, 4498, -1384, 3170, 2228, 4459, 5196, -2026, 2326, 2240, 2699, 5702, 1171, 506, 1386, 3207, 5755, 1764, 2206, 904, 3826, 4887, 2222, 3757, 1995, 3129, 2468, 3180, 3870, 2658, 942, 52, 3634, 2839, 2456, 320, 976, 3623, 1191, 1604, 2480, -885, 4603, 1822, -525, 3460, -782, 5581, 2952, -7583, 3661, 1818, 5375, 2516, 1379, 3371, 1904, 3979, 1095, 3413, 2724, 295, 2803, 2173, 3843, 2163, -2385, 2485, 2834, 3487, 1736, -2409, 713, 1200, 2875, 930, -201, -2075, -2698, 2360, -206, 1030, -335, 1973, 2030, -1165, 1748, -562, 3507, 1755, -2140, 2111, -2956, 3447, 1208, -3479, 1329, -7774, 2264, -274, -2064, -2785, -4100, 446, -5810, -735, -425, 42, -35, -2204, -666, 2481, 1366, 911, 852, -333, 2815, 934, 1890, 1563, 554, 1385, -1336, 2567, 1102, 550, -1894, -6376, 2435, -70, -911, -2829, -2457, 958, -1321, -3425, -1625, 208, -495, -1875, -1609, -1192, 1831, 1443, -1879, 491, -833, 2715, 2199, -1954, 1279, -1153, 2768, 1427, -1787, 1024, -2191, 1800, -707, -1361, 429, -1825, -546, -3438, -1469, 132, -506, -3306, -3067, -2342, -434, 361, -1826, -2148, -2438, -1419, 693, -1060, -2789, -1291, -2326, 540, -1398, -5646, -281, -3230, 120, -2630, -11488, 255, -4086, -627, -5260, -6332, 89, -3741, -1594, -15615, -3076, -947, -2797, -1242, -8009, -1610, -2895, -2657, -440, -8192, -1745, -5759, -3449, -303, -10613, -3589, -10442, -3436, -614, -3603, -5997, -10613, -2567, -1078, -1281, -4863, -10138, -2612, -1569, -520, -4495, -7408, -3833, -1657, -926, -3920, -4923, -6388, -1532, -2597, -2969, -3811, -7523, -2140, -5735, -2642, -2462, -5569, -3792, -8903, -2857, -1095, -3814, -4282, -7081, -3203, -232, -2463, -3808, -4550, -3029, 77, -2125, -5353, -3463, -2450, -288, -2714, -5827, -3230, -2220, -1383, -3518, -3274, -3360, -2747, -3014, -3735, -2954, -3860, -4664, -4266, -3515, -4620, -5145, -10138, -4303, -3276, -8549, -7408, -11232, -4743, -3592, -13049, -7523, -7371, -5367, -4664, -12534, -4142, -4679, -4075, -4683, -7819, -1976, -3738, -2964, -3396, -6064, -914, -4863, -3261, -3286, -4100, -790, -9873, -5026, -4779, -2705, -1613, -4451, -5115, -7912, -2533, -3729, -2303, -3540, -8982, -3714, -8485, -2100, -3257, -5897, -6267, -6828, -3168, -4416, -3299, -5208, 6641, -9022, 10014, 6932, -1285, 6421, -1480, 9436, 7458, 1188, 5645, 2610, 7535, 8047, 2195, 4735, 4517, 3383, 7927, 1683, 5629, 4916, 677, 7040, 793, 6675, 4017, 3672, 5761, 24, 6487, 2575, 4180, 5137, 538, 5092, 2426, 3491, 5309, 924, 3984, 2299, 1425, 5228, -717, 3747, 2723, -1441, 4428, 616, 1867, 4179, 1667, 2892, 3293, 1701, 4930, 3607, 1086, 4534, 4106, 4823, 3888, 466, 5018, 4366, 4170, 2549, 1764, 4844, 2309, 3279, 1656, 3391, 3867, -3065, 2441, 3906, 4277, 2018, 2846, 1991, 5039, 4113, -508, 4320, 1427, 4954, 2669, -2954, 4298, -544, 3932, -1070, -4532, 3797, -1827, 2483, -3689, -4800, 3753, 796, 1513, 252, -2135, 4138, 1456, 1353, 1074, -456, 4171, 898, 1583, 871, -337, 3238, 175, 1024, 1179, -1526, 566, 287, -1177, 2338, -1895, -3903, 874, -4447, 3044, -501, -182, 686, -5702, 3154, 282, 680, -897, -3301, 3143, 548, 350, -3985, -1326, 3063, 734, 651, -5208, -1914, 2360, 1041, 1284, -2238, -6615, 387, 1321, 1603, -596, -3417, -4340, 1313, 2419, -419, -267, -6343, 929, 3345, -1096, 1233, -4509, 503, 3560, -2006, 1986, -4578, 421, 2957, -3375, 2159, -3137, 481, 1964, -2125, 1832, -2116, 563, 1390, 388, 1080, -2204, 597, 1090, 1687, -76, -3194, 23, 254, 1963, -1079, -834, -1623, -2399, 1268, -702, 1592, -3647, -6113, -443, 252, 2691, -4482, -453, -2270, 784, 2846, -3208, 1029, -1537, 470, 2426, -989, 1175, -343, -1194, 1835, -405, 404, 38, -5933, 1317, -1371, -1761, -562, -5784, 731, -2118, -4500, -1603, -3154, -261, -1164, -1740, -1446, -2731, -1899, -1024, -816, -1005, -2999, -3609, -1717, -1398, -1076, -3817, -3087, -2260, -3447, -1105, -5458, -1917, -2435, -7050, -742, -9429, -1559, -2653, -2837, -443, -5487, -2207, -2908, -1002, -616, -2232, -4184, -3210, -769, -1488, -1135, -9380, -3577, -1431, -3196, -1630, -5793, -4157, -2182, -4172, -4311, -2885, -4743, -2132, -2201, -11629, -1680, -4784, -1212, -723, -4270, -814, -4708, -487, -185, -3133, 428, -5784, -565, -483, -3220, 1544, -14784, -1568, -1605, -3515, 1989, -5524, -3415, -3294, -3600, 1609, -3452, -5997, -4774, -2975, 283, -4138, -9106, -4412, -1765, -2497, -3996, -12123, -1937, -904, -10799, -1660, -12776, -887, -837, -5429, -947, -9022, -1666, -1611, -4250, -1784, -8086, -3455, -3007, -5897, -3900, -6299, -2897, -3947, -17034, -6590, -4089, -2849, -3896, -5091, -9022, -3326, -4532, -4754, -3110, -5524, -3833, -6842, -11629, -3213, -3038, -3996, -8393, -4017, -5152, -1874, -2465, -9753, -476, -8138, -1381, -1210, -7523, 1019, -7389, -1357, -724, -4049, 1292, -5152, -1799, -1083, -1897, 459, -2644, -2716, -2390, -1028, -1522, -1132, -3989, 8639, 8433, -1228, 8965, 4876, 8228, 7718, 4726, 8594, 5063, 7076, 5210, 6354, 7458, 4833, 5526, -2424, 5894, 5453, 3010, 4164, 1836, 3901, 2248, -1123, 3075, 2791, 3507, -4997, 3103, 1547, 1485, 4525, -1727, 4722, -669, -1895, 4015, 660, 4281, -1112, -9812, 1797, 682, 357, 551, -7081, 203, -1030, 1809, 2363, -4805, 1729, -2295, 5573, 3098, 957, 1841, -1607, 6763, 2731, 3022, 246, -4138, 7010, 2067, 3062, -430, -1722, 6901, 1854, 751, 1400, 1568, 6515, 1354, -1704, 1351, 2000, 5632, 229, 1042, -1413, -132, 4024, -1084, 157, -2303, -5333, 1880, -3399, -11115, 231, -2480, 2450, -6615, 1257, 103, -8112, 4125, -1409, 3194, -1411, 408, 4623, 513, 3307, -3373, 2865, 3766, 1561, 2018, -3659, 3266, 886, 2293, -1206, -615, 2429, -1319, 2346, -2475, 1007, 750, 1659, 1237, -173, 1398, -1381, 1832, -1701, -92, 1144, -2637, -613, -9873, -1564, 975, -3933, -1284, -11356, -4097, 1184, -2793, 2481, -5079, -4620, 1234, 1121, 3869, -593, -2943, 907, 2930, 4064, 1427, -2205, 494, 3505, 3465, 2313, -2933, 318, 3319, 2384, 2448, -4587, 446, 2791, 1361, 1854, -2659, 610, 2286, 1592, 246, -1155, 575, 1779, 3000, -2831, -1207, 415, 890, 4033, -2644, -2430, 240, 52, 4175, -656, -4991, 246, 1121, 3334, 146, -8903, 865, 2385, 1424, 232, -1411, 1617, 2712, -1662, -424, 975, 1771, 2113, -4935, -1887, 1733, 1068, 756, -4042, -3817, 1432, -459, -953, -1926, -4336, 443, -1721, -2394, -605, -3133, -275, -1533, -3187, -620, -2311, -118, -1638, -3644, -2713, -2172, -356, -2204, -5109, -4733, -2364, -2047, -1807, -6553, -1473, -2793, -4447, -1011, -3526, -836, -3814, -2730, -825, -1912, -1361, -4713, -2764, -1393, -1556, -1480, -4195, -6719, -2564, -2201, -1628, -3999, -5686, -3843, -3430, -2891, -3732, -3144, -4946, -3047, -6321, -3289, -4071, -5079, -1706, -7004, -3824, -11004, -3433, -897, -2590, -3853, -6093, -2707, -684, -628, -2450, -4021, -3788, -1165, 208, -2008, -3951, -7819, -2500, 203, -2997, -4278, -6480, -4340, -338, -5020, -3850, -3388, -5776, -845, -4230, -2887, -1583, -8754, -1543, -2960, -2257, -490, -8942, -3168, -2522, -2334, -160, -4664, -3656, -1959, -3130, -648, -2910, -2090, -1419, -4211, -2229, -2087, -1033, -1469, -4664, -5906, -2068, -348, -2148, -4654, -7752, -3187, -275, -3163, -5662, -6103, -6332, -1275, -4010, -8363, -9753, -7523, -4038, -3732, -4738, -7796, -5539, -7960, -2495, -2902, -4361, -5793, -4640, -1578, -2839, -3396, -6856, -2698, -1377, -3396, -3108, -9193, -1689, -1841, -3557, -3357, -8247, -1904, -2670, -4491, -4130, -2811, -3618, -3729, -9284, -4108, -436, -3801, -5286, -6914, -3671, 602, -1820, -6457, -3964, -4149, 782, -1314, -4429, -4278, -7583, -1988, -2573, -3798, -3401, -6153, -1867, -1335, -4478, -2322, -4093, -2514, -1215, -7081, -1609, -4550, -2581, -2153, -6143, -1119, -10362, -2172, -4089, -3417, -1093, -5127, -2505, -5158, -2906, -1857, -2259, -3479, -3964, -4416, -3257, -1897, -4089, -2550, -8276, -3396, -3482, -3662, -1197, -6093, -2956, -5561, -3005, -405, -5516, -3860, -2622, -3133, -451, -5776, -8086, -1141, -4541, -1394, -3543, -6958, -915, -7936, -2776, -2172, -3319, -1323, -10799, -2906, -1923, -2242, -1740, -6235, -2445, -2545, -2337, -2102, -4226, -2470, -4149, -3449, -3112, -3321, -2437, -7484, -5662, -5592, -3479, -2050, -4509, -5176, -4929, -4679, -1811, -1759, -3147, -2711, -4853, -2040, -792, -2628, -2217, -4046, -3154, -1075, -3624, -2964, -4518, -5862, -1859, -6411, -4743, -4620, -6705, -1925, -9753, -6899, -3031, -4573, -1916, -7984, -7179, -2091, -4262, -2578, -6958, -7542, -2058, -5109, -3923, -6653, -8276, -2975, -5592, -5353, -6365, -6899, -5008, -4478, -5844, -5718, -6399, -5367, -3396, -5988, -5702, -5776, -3695, -2863, -6007, -5942, -4262, -3360, -2791, -6411, -5133, -3843, -3930, -3191, -7603, -3916, -5444, -4451, -4199, -7445, -3154, -9695, -5240, -6640, -7865, -3415, -5942, -7299, -14195, -15615, -4896, -5227, -6786, -4635, -6653, -6123, -6225, -4759, -2279, -3999, -5836, -5554, -4319, -1663, -3329, -7371, -4874, -4935, -2594, -4010, -8517, -5670, -5951, -6083, -5801, -3951, -7130, -6399, -7179, -5871, -2030, -6958, -5097, -3883, -4307, -1505, -5853, -3540, -3460, -3886, -2225, -4438, -2613, -4869, -4784, -4611, -3316, -1983, -8718, -7335, -12319, -3144, -1329, -6800, -14784, -8112, -4172, -971, -4532, -9149, -6492, -6469, -1242, -3954, -7842, -5569, -5897, -2128, -4469, -8276, -4669, -4473, -3286, -5592, -8582, -4674, -4282, -4500, -6246, -7888, -5480, -4460, -6278, -6113, -6870, -6143, -4382, -9331, -5374, -5970, -5429, -4365, -10526, -4759, -5793, -3773, -4518, -6705, -4486, -6692, -2902, -4215, -4569, -4021, -7819, -3098, -3537, -3760, -3609, -6899, -3717, -3225, -3930, -3754, -6745, -4149, -3748, -4451, -4282, -8247, -4386, -5759, -4573, -4800, -7960, -4495, -10210, -4420, -5458, -7230, -4901, -8454, -4482, -6943, -8718, -6214, -9479, -5516, -10899, -10899, -8304, -11781, -9064, -11004, -11356, -6914, -8034, -8790, -6759, -11781, -6074, -8112, -5793, -5339, -5997, -7523, -10704, -4896, -4991, -3452, -10284, -13738, -4644, -5353, -2605, -8790, -12319, -4664, -6183, -3156, -7503, -11232, -5073, -7623, -5394, -6354, -11232, -6246, -9873, -11232, -5346, -12776, -6692, -11356, -10442, -5079, -10613, -4951, -8549, -8718, -6026, -8393, -3886, -6445, -8485, -7389, -7389, -3985, -5394, -8304, -6516, -6842, -5227, -5253, -8363, -6123, -5960, -7752, -6434, -8192, -7371, -4769, -9695, -10613, -7299, -11232, -4234, -7865, -8304, -7213, -12534, -4940, -6719, -5607, -4097, -1277, -4093, -629, -5152, -4299, -2417, -3748, -1023, -6214, -3029, -3933, -2964, -2319, -8790, -1610, -4625, -3218, -4769, -6163, -842, -4211, -3641, -7162, -2624, -879, -4157, -3047, -5055, -1195, -1696, -5061, -2690, -3820, -1165, -3476, -5784, -3326, -3686, -2430, -7230, -4698, -3989, -4086, -5133, -7230, -3367, -3259, -4420, -7796, -4545, -2624, -2795, -4555, -7774, -3674, -2399, -3130, -5202, -6679, -3373, -2347, -4024, -6958, -4086, -3360, -2149, -5266, -7484, -2455, -3788, -1884, -7050, -4968, -1965, -4340, -1810, -11781, -3393, -2325, -4688, -2060, -9873, -2950, -3067, -5599, -2166, -6914, -4203, -4438, -9380, -1485, -6064, -8649, -8903, -8718, -856, -5133, -3589, -5623, -5127, -1114, -4282, -1720, -3334, -3430, -2282, -3889, -1959, -3244, -1872, -2597, -3540, -4395, -3609, -1138, -1833, -2787, -15615, -3391, -1660, -1713, -1877, -4708, -2941, -4013, -1927, -1303, -3518, -2364, -28777, -1980, -1443, -4504, -2414, -4625, -2305, -2499, -7687, -3689, -2969, -2867, -3586, -6321, -6194, -3415, -3187, -2863, -4134, -8982, -6064, -3201, -2422, -4180, -12776, -8683, -2528, -3274, -7603, -13049, -4532, -1939, -4779, -7708, -10362, -3103, -2490, -3571, -3927, -8942, -3031, -4858, -1898, -3621, -8060, -4286, -10799, -1147, -5630, -6480, -9331, -28777, -1127, -11004, -4779, -6528, -8393, -1725, -5103, -4134, -3005, -4352, -3071, -2831, -4821, -1917, -2809, -5970, -1917, -7484, -2166, -2728, -12123, -1922, -7426, -3656, -3866, -8060, -2875, -4038, -6153, -6173, -7644, -4527, -2514, -7583, -8827, -6007, -5380, -2143, -7484, -10069, -4006, -5623, -2831, -5638, -9149, -3117, -6899, -4482, -4319, -7389, -3045, -8304, -6445, -4161, -7196, -3741, -7542, -9873, -3916, -8485, -5827, -6445, -5915, -2758, -10526, -14195, -5516, -2969, -1825, -8220, -7113, -5158, -2289, -1682, -4974, -5133, -5374, -3386, -2433, -3357, -4784, -6035, -6214, -4230, -2986, -4748, -5247, -6343, -6814, -3656, -4587, -3036, -5422, -7130, -5127, -4606, -1727, -6113, -6054, -6434, -5380, -1586, -7665, -5387, -5524, -7213, -2316, -8304, -4974, -4282, -8086, -2943, -7081, -4874, -3903, -7335, -2924, -5915, -5480, -4644, -7445, -3566, -5127, -6565, -6988, -7004, -5759, -4500, -6705, -9585, -5615, -7299, -4075, -5970, -6679, -4378, -6411, -4299, -5002, -4869, -3804, -7936, -5933, -4669, -3870, -4412, -10138, -11781, -5879, -3612, -7484, -6113, -8683, -11232, -4191, -10613, -4795, -6828, -6640, -5253, -5844, -5109, -7888, -4153, -6411, -5472, -6973, -11232, -3594, -7665, -6445, -11356, -7583, -4108, -9193, -6814, -13049, -4545, -5176, -13738, -7317, -7445, -2939, -6332, -13365, -9022, -5646, -2470, -8138, -10442, -9106, -5654, -3089, -13738, -11232, -7066, -6943, -4805, -8615, -11488, -5844, -7842, -7583, -6411, -8333, -5623, -7179, -7984, -6692, -6745, -6173, -6628, -6343, -7888, -6376, -6800, -6973, -6194, -5630, -3504, -5152, 304, -2356, -5279, -3930, -4513, -717, -5924, -6469, -4290, -3215, -2268, -7562, -9873, -4769, -2571, -3833, -3468, -7066, -6267, -2463, -3785, -2490, -4738, -10442, -2478, -3476, -2926, -3785, -11356, -2457, -4357, -4550, -3247, -8615, -2642, -5546, -5444, -2900, -8790, -3309, -3996, -2730, -2979, -7936, -4573, -2752, -1042, -4138, -5576, -6492, -2429, -863, -8718, -4038, -8754, -2630, -2257, -5055, -3108, -5888, -3218, -5353, -2028, -2580, -2947, -4315, -5008, -1020, -2605, -1484, -5353, -3776, -923, -3729, -1239, -4693, -3609, -1018, -7484, -2447, -3463, -3259, -800, -8942, -6928, -2709, -2299, -601, -4611, -6045, -2361, -1372, -976, -3546, -3096, -2396, -920, -1943, -3896, -3189, -3007, -1016, -2869, -5718, -5306, -4790, -1264, -3337, -11781, -5630, -9812, -1020, -3889, -7247, -3873, -7130, -521, -4408, -4500, -3751, -4513, -359, -4319, -3632, -4985, -3668, -828, -3896, -3501, -6958, -3677, -2409, -3968, -3444, -8790, -4469, -7842, -5539, -3501, -7623, -5630, -4869, -13738, -3409, -6045, -6074, -1869, -5784, -2553, -4890, -5103, -1226, -3563, -1982, -3463, -3498, -1678, -3349, -2756, -2799, -2789, -2799, -4071, -6666, -3571, -3168, -4303, -4246, -5979, -6973, -3853, -5988, -3732, -2285, -9585, -4500, -7408, -3896, -1483, -4997, -6653, -6828, -4946, -2378, -3606, -11356, -4723, -6054, -5776, -2871, -6093, -3701, -5862, -9639, -2545, -3999, -4056, -4968, -4774, -2677, -2916, -5189, -4390, -4130, -3078, -2567, -5569, -4357, -4674, -3085, -2967, -6899, -4703, -5408, -3117, -4527, -9238, -4688, -6246, -4149, -11488, -4064, -4842, -7730, -5380, -5049, -1793, -6278, -9695, -3441, -2143, -734, -4654, -10613, -1937, -1323, -417, -1908, -6299, -1546, -1647, -674, -812, -4127, -2146, -2541, -1348, -1010, -3763, -3951, -3149, -2207, -2024, -5139, -4654, -3404, -2999, -2639, -9284, -2200, -3563, -3515, -2386, -14195, -1123, -3378, -3615, -2391, -11629, -1485, -2977, -3254, -3027, -11488, -3365, -2929, -2933, -4723, -8754, -7213, -3886, -2855, -9753, -7081, -8718, -6692, -2745, -7774, -5915, -7960, -6590, -2543, -4509, -4698, -8790, -4230, -2776, -3795, -3650, -9812, -3589, -4230, -4630, -2952, -9064, -3968, -7542, -5997, -2698, -7281, -4946, -5670, -5202, -2922, -5836, -6064, -4010, -4842, -3665, -5367, -7542, -3866, -5152, -4738, -6153, -10613, -4569, -4006, -5924, -7752, -9149, -6093, -2958, -6988, -6856, -6828, -8363, -3124, -7623, -5615, -6153, -6653, -4625, -8304, -5509, -6540, -4527, -6899, -7445, -6376, -8276, -3735, -7562, -5145, -8220, -13738, -3776, -8649, -3937, -8982, -11488, -4246, -12534, -3975, -7865, -8220, -5360, -12534, -5073, -7019, -6814, -7583, -11115, -7034, -6590, -6278, -6399, -11356, -9479, -6540, -6504, -4266, -28777, -14784, -7081, -7353, -3386, -11945, -10138, -7665, -7004, -3512, -9873, -6480, -8165, -5429, -4578, 6593, 3030, 1538, 6735, -3388, 6250, 2597, 1701, 6297, -1212, 5305, 1149, 1623, 5029, 852, 4075, -2288, 823, 3180, 2145, 3078, -7796, 216, 1115, 2889, 2249, -2043, 993, -2197, 2992, 943, -1459, 1852, -5133, 2263, 410, -1761, 2430, -72, 800, 819, -179, 2860, 1829, 553, -1209, 1652, 2740, 2877, 2116, 1362, 3020, 1299, 3377, 3701, 4582, 4225, -37, 3143, 5044, 5643, 5346, 2696, 1786, 5895, 5377, 6168, 3704, -242, 6002, 4448, 6394, 2690, 929, 5225, 3888, 5742, -526, 1833, 3773, 3467, 3792, 1936, 1358, 2873, 2329, -393, 3745, 94, 2228, 1512, 75, 3814, -1690, -93, 2392, 1020, 2661, -3612, -1816, 2772, -695, 969, -287, -583, 1903, -561, 232, 1779, -974, -475, 969, -1284, 2667, 1299, -5494, -222, -8393, 2952, 2553, -6988, -11115, 945, 2854, 1571, -5109, 688, 3075, 2353, -2945, -3071, 2798, 3446, 1365, 1195, -7, 3496, 2658, -465, 3161, 1703, 3593, 1298, -4625, 3128, 2164, 3229, 325, -1254, 1624, 1362, 2432, -48, 1774, -1066, -1865, 1408, 750, 3080, -3012, -3893, 411, 1726, 3408, -5312, 961, -517, 1730, 3047, -6332, 2111, -1748, 678, 2222, -3487, 1821, -2429, -403, 1194, -3814, 564, -382, -424, 331, -4842, -989, 817, -1142, -140, -2101, -939, 432, -2326, -365, -87, 378, -1663, -1107, -599, 1056, 1447, -3629, -744, -1047, 1613, 1991, -3142, -2698, -1760, 1621, 2080, -5380, -2630, -2714, 1089, 1814, -7162, -266, -3795, 104, 1204, -3391, -181, -3860, -1191, 177, -3213, -2232, -2369, -2751, -1324, -3893, -6590, -1126, -4578, -3365, -2383, -6640, -771, -4821, -5793, -834, -10362, -1288, -4021, -4378, 73, -7644, -2118, -4211, -2409, 533, -4386, -2004, -5615, -1627, 432, -3156, -1762, -6565, -1683, -450, -2336, -2546, -5531, -2115, -2312, -1854, -4180, -5079, -2083, -3860, -2130, -3751, -5145, -1793, -2752, -3883, -2356, -4748, -2251, -1627, -9193, -1781, -4053, -4464, -1368, -7665, -1781, -3798, -5360, -2297, -9106, -1923, -4728, -1756, -5031, -7264, -1875, -8165, -585, -11115, -3117, -1738, -8086, -1181, -7264, -2344, -1690, -5487, -3840, -5879, -3910, -1807, -4659, -17034, -5380, -8549, -2040, -4258, -6705, -5139, -3933, -2396, -4790, -5678, -5333, -2265, -3034, -7213, -5853, -5906, -2168, -4327, -7912, -5451, -6411, -3010, -6615, -5494, -4145, -6759, -4352, -7623, -5451, -2871, -8086, -4912, -6705, -8060, -2115, -17034, -4495, -7317, -11781, -2000, -8517, -4754, -10138, -7752, -2409, -6113, -5970, -12534, -9022, -3239, -6093, -7299, -8982, -7984, -4738, -7603, -7097, -6074, -4482, -8112, -9531, -5793, -4348, -3401, -8865, -9585, -4991, -3744, -3757, -5458, -7865, -5353, -4311, -4968, -4923, -5970, -7317, -6343, -6153, -6856, -4597, -9873, -10899, -6204, 1100, 6058, 1262, 2909, -8304, 2480, 5532, 2293, 2255, 1405, 3401, 3810, 3401, -217, 3985, 2749, 476, 3689, -7819, 4990, 398, -847, 3265, -284, 5012, 553, 668, 2244, 1759, 4306, 3124, 1150, 286, 2546, 2994, 4618, 1022, -4974, 2675, 810, 5369, 61, -3067, 2254, -2435, 5451, 1225, -1758, 1528, -3618, 5105, 4067, -62, 1110, -161, 5514, 5608, 3900, 1295, 2631, 6450, 5978, 5828, 1423, 3820, 6658, 5414, 6206, 1258, 3695, 5953, 4252, 5103, 2447, 2361, 4714, 2964, 1905, 4220, -153, 3574, 1759, -1407, 5231, -3373, 2705, -175, 986, 5531, -4713, 1455, -6083, 310, 5342, -4071, -1755, -483, -3218, 4798, -4821, -7842, 874, -10442, 3995, -4874, -3170, -946, -8649, 3129, -3744, -2666, -1948, -4769, 2334, -4713, -280, 1915, -440, 1301, -3311, 1086, 3469, 1578, -460, -1780, 1468, 3979, 2469, -1979, -2764, 1497, 3816, 2633, 65, -4086, 1528, 3136, 2198, 1650, -1067, 1651, 2419, 1097, 1922, -8, 1788, 2395, -647, 826, -665, 1778, 2654, -1939, -2472, -3354, 1547, 2531, -1566, -7603, -4442, 1264, 1722, -675, -1455, -575, 1309, -370, -272, -99, 1310, 1612, -1725, -852, -430, 2251, 1652, 1252, -2540, -1670, 2593, 1005, 2489, -4620, 217, 2450, -641, 2245, -4536, 2304, 1829, -3729, 548, -2219, 3283, 760, -5546, -3334, -639, 3546, -400, -2587, -14784, -60, 3408, -842, -471, -4991, -119, 3013, -117, 982, -638, -645, 2390, 931, 1808, 1517, -1510, 1431, 1485, 1993, 2218, -2069, -135, 1363, 1547, 1881, -2363, -1277, 650, 499, 1021, -3237, -583, -364, -1250, 259, -4795, -439, -978, -4145, -734, -6054, -1390, -930, -4270, -2990, -5888, -3014, -990, -2590, -7936, -5073, -4664, -1563, -3137, -10210, -4555, -5061, -2414, -7445, -6035, -4985, -4357, -3042, -7247, -2813, -6256, -3309, -3225, -4601, -1790, -5286, -2068, -3580, -5678, -2762, -3563, -1158, -5061, -6914, -7484, -3078, -849, -8454, -3704, -6928, -3913, -1121, -7317, -2083, -4319, -6246, -1507, -6504, -1624, -5073, -8903, -1521, -6666, -2095, -8942, -6988, -1499, -4963, -3490, -8903, -5121, -1668, -3441, -5810, -5437, -4311, -1918, -2900, -6773, -3971, -4640, -2062, -3650, -4826, -3476, -5584, -1869, -6321, -3237, -3893, -5630, -1827, -10138, -2213, -5109, -5273, -2617, -10704, -1868, -6492, -5569, -4630, -11232, -2455, -6565, -6183, -6943, -5221, -4447, -6123, -7230, -5415, -3386, -8790, -5836, -9873, -4089, -3184, -8615, -5539, -9753, -3840, -4369, -6705, -5380, -8517, -4935, -6528, -5524, -5408, -9873, -9479, -6133, -4951, -5751, -11232, -6267, -5979, -5266, -6628, -10799, -3321, -8393, -6246, -7888, -12319, -2666, -7819, -6973, -8363, -11232, -3422, -5933, -7050, -6204, -9936, -5509, -6565, -6679, -4447, -9639, -9064, -8454, -7865, 6384, 8433, 6336, -1661, 2254, 6190, 7798, 6460, 4567, 4610, 5623, 6069, 6709, 6674, 5012, 4822, 4554, 6703, 6995, 3751, 3834, 3798, 5914, 5827, 458, 2226, 1892, 3772, 2775, -1699, 919, -2082, 1070, 361, -1205, 1609, -7162, 1990, 1068, -4578, 1643, -3184, 1957, 2505, -3412, 715, -877, 2185, 5062, 1287, 500, -36, 3480, 6450, 3364, 1762, 233, 3873, 6837, 4204, 2522, 91, 2879, 6135, 3929, 2207, -1136, -383, 3287, 2281, 788, -5319, -6602, 1016, -1621, -2222, -1546, -911, 5163, -1417, -6399, 602, -1000, 6003, 314, -1749, 715, -2538, 5599, -180, -1145, -336, -3284, 5076, -2475, -3656, -1872, -3535, 4641, -7230, -3957, -3306, -1466, 3675, -14195, -678, -3571, -320, 2228, -8009, -95, -3269, -952, 907, -4451, -1287, -3529, -3311, 22, -3375, -4880, -2945, -5751, -427, -4100, -8276, -1433, -5458, -1026, -8009, -7034, -302, -5008, -1895, -6225, -5646, 172, -4403, -1174, -2648, -2351, 92, -4035, -23, -1707, -1615, -535, -3751, 230, -2340, -2964, -1887, -3140, -276, -3632, -5710, -3680, -2605, -1382, -2845, -4416, -4071, -3436, -4184, -1916, -2918, -2391, -6411, -5306, -1193, -2234, -422, -1541, -1468, 25, -2686, 676, 819, -617, 708, -4583, 616, 1322, -1187, 154, -4693, -595, 305, -2733, -2350, -2639, -810, -2528, -5346, -5109, -1642, 636, -12534, -2644, -2534, -1726, 1346, -3811, -352, -3600, -1944, 1705, -1487, 634, -2813, -585, 1998, -1370, 995, 746, 581, 1725, -3485, 1000, 1936, 794, 496, -12534, 578, 1525, 184, -1491, -6553, -574, -590, -981, -1893, -5387, -2650, -6434, -2317, -783, -4718, -5049, -5374, -3316, -217, -4361, -7708, -3763, -3677, -430, -4708, -14195, -5227, -3618, -1553, -4896, -7644, -8649, -3482, -3992, -4779, -6376, -5247, -3632, -7113, -4912, -6565, -3886, -4473, -5516, -5085, -5942, -4211, -6492, -4929, -5422, -4759, -5776, -9812, -5615, -6705, -4234, -7687, -8165, -6480, -8982, -4013, -7888, -5776, -7196, -7912, -3412, -7665, -4420, -9753, -6434, -2589, -7665, -3766, -15615, -5494, -2086, -6786, -3589, -8485, -4270, -2326, -5970, -3930, -7408, -3189, -3763, -6045, -5279, -8247, -2781, -7936, -6214, -9936, -9479, -3244, -8549, -6153, -7865, -9753, -4587, -4278, -6679, -4282, -9331, -6640, -2747, -7888, -3347, -8942, -7960, -2222, -8754, -4031, -8363, -8165, -2447, -7912, -6214, -5360, -8615, -3269, -6376, -6943, -4082, -8718, -4180, -5260, -5576, -4597, -8138, -4234, -4880, -4640, -6093, -8086, -3460, -5576, -4127, -6679, -9022, -2662, -7542, -4311, -7960, -11781, -2289, -7353, -5458, -9639, -13738, -2447, -7408, -7936, -7730, -8790, -3232, -11356, -10899, -7162, -7623, -4863, -5346, -8192, -8423, -8454, -7004, -3388, -6653, -14784, -10704, -7230, -3404, -6332, -11115, -10442, -7281, -8009, -3903, -7687, -12776, -5387, -5189, -3686, -6422, -9429, -4991, -4555, -3686, -6183, -7623, -5915, -4935, -3710, -6256, -6469, -8549, -5694, -3808, -5862, -6457, -7389, -7426, -4611, -5380, -7464, -6123, -8276, -6759, -5702, -6504, -6786, -5759, -11488, -7066, -4957, -7623, -4282, -13738, -9429, -4541, -7389, -3571, -10284, -11781, -5133, -7162, -3269, -8790, -11004, -6054, -6133, -3242, -8549, -8423, -6288, -5152, -3546, -8549, -7281, -6492, -4929, -4344, -7687, -6828, -7603, -5260, -6016, -7730, -6516, -8942, -5623, -10210, -8903, -6786, -8423, -5630, -11232, -8454, -7774, -8363, -5524, -7583, -7730, -9064, -9284, -5801, -7179, -6504, -9149, -11945, -6899, -8649, -5109, -6899, -10362, -8827, -11629, -4640, -5353, -6759, -8649, -11629, -5279, -5055, -5247, -7464, -9331, -7004, -5630, -4810, -7603, -6899, -8112, -5942, -5133, -9284, -5539, -6653, -5592, -6026, -12534, -5429, -5801, -6016, -6914, -11356, -6590, -5623, -8454, -7004, -9695, -8683, -5561, -11115, -6943, -8304, -10362, -5312, -7888, -7865, -6885, -9331, -5020, -7264, -10001, -5630, -7281, -4935, -8138, -9695, -4968, -6343, -5415, -10799, -7097, -5292, -6565, -6705, -28777, -5662, -6814, -7353, -7484, -9429, -5401, -8517, -7912, -6540, -7503, -6045, -7644, -8333, -6214, -7445, -7130, -7113, -8138, -6899, -8454, -7752, -7796, -7623, -8192, -9873, -7335, -8649, -7230, -9585, -10613, -6732, -7774, -7299, -10704, -9873, -6692, -5988, -8165, -10899, -8060, -7113, -4805, -9284, -10210, -7371, -7445, -4644, -8865, -9284, -8220, -7426, -5836, -8718, -7819, -11781, -6602, -9149, -8333, -6958, -14195, -5670, -9479, -7542, -7299, -10362, -5599, -7196, -7796, -8982, -8982, -6422, -6705, -10210, -9753, -7665, -8112, -6640, -17034, -8827, -6422, -10704, -6376, -9531, -9193, -5836, -10442, -6399, -8485, -11629, -6007, -8549, -7081, -9531, -13049, -6856, -8060, -8517, -13049, -11232, -7819, -9149, -10362, -28777, -10284, -8060, -13738, -10613, -14195, -8683, -8333, -11232, -9429, -11356, -7912, -9585, -8086, -8086, -8942, -8615, -13738, -7066, -7774, -7484, -12319, -28777, -7247, -8903, -7408, -14195, -12123, -8363, -13365, -9380, -9753, -12776, -10526, -12776, -13738, -8982, -12319, -12776, -11004, -7936, -9284, -8393, -13738, -13049, -6288, -9238, -6434, -13365, -10069, -6445, -8485, -5718, -11945, -7523, -8333, -8112, -5951, -10613, -6504, -12123, -8423, -7213, -10526, -6321, -9022, -9238, -9639, -10284, -7081, -7644, -9873, -12319, -9238, -9193, -8423, -10138, -12123, -9149, -12123, -11004, -10284, -14195, -10442, -12534, -10069, -10210, -28777, -12123, -10210, -9284, -10069, -12123, -12319, -8304, -11356, -11356, -10442, -10138, -7687, -14784, -28777, -9873, -8827, -7936, -10613, -13365, -9531, -8790, -8865, -9106, -11004, -8790, -10284, -10526, -9193, -10526, -8112, -13738, -14195, -10138, -10899, -7730, -28777, -28777, -10138, -11945, -7865, -17034, -13365, -10210, -10138, -8485, -15615, -12123, -6246, -4003, -9331, -11945, -9284, -5569, -5002, -9531, -9284, -13049, -4728, -7426, -10526, -7081, -9873, -4238, -8393, -11945, -5793, -7464, -4504, -7426, -11488, -5401, -6602, -5759, -6422, -9479, -5801, -5121, -7960, -5561, -8333, -6692, -4031, -10284, -5599, -7960, -7562, -4064, -12776, -6800, -8060, -8582, -5451, -11232, -8165, -8485, -8790, -9064, -8615, -8276, -8485, -6870, -11945, -7503, -7819, -6814, -6026, -8649, -7213, -7335, -5360, -6928, -8034, -7113, -7464, -5139, -10704, -8903, -6666, -8683, -5988, -11356, -12123, -5951, -11232, -5960, -7687, -12776, -5458, -13365, -5189, -6422, -9331, -5360, -10526, -5710, -6204, -8423, -5546, -9331, -7819, -6786, -8942, -5710, -8718, -8112, -8393, -9753, -5638, -6590, -7583, -10799, -8454, -5607, -4713, -10001, -9585, -7299, -5678, -4097, -11356, -8138, -6914, -5638, -4779, -5979, -7842, -7408, -5853, -6842, -4491, -7865, -8903, -6885, -10613, -4759, -7130, -10001, -7542, -28777, -6516, -6143, -9238, -5906, -12319, -8454, -5607, -7912, -4764, -9695, -8086, -5615, -6388, -4874, -9238, -8582, -5888, -5472, -6299, -9936, -9936, -6267, -5465, -10362, -11488, -8942, -6666, -6679, -12534, -14784, -8009, -7335, -10210, -8549, -11629, -8112, -9064, -11781, -8086, -9331, -8138, -11945, -7819, -8333, -9284, -7644, -12534, -6899, -8517, -10284, -6842, -28777, -7264, -9936, -9936, -6133, -9149, -8276, -10526, -9585, -6553, -6469, -9238, -7912, -8982, -9695, -5408, -10069, -6411, -7146, -11629, -5202, -11356, -5960, -6204, -7936, -5988, -13365, -6321, -6246, -7774, -7888, -11945, -7708, -6732, -8086, -7960, -10138, -9753, -7050, -7371, -6828, -9429, -9479, -6870, -6602, -6469, -9284, -8247, -6553, -6194, -6732, -9149, -8220, -6577, -6267, -7644, -9331, -8903, -7299, -7213, -9106, -10138, -9812, -8582, -9585, -10526, -13738, -10526, -8754, -13049, -12534, -14195, -11115, -8304, -10899, -28777, -9284, -11781, -8718, -9429, -11629, -7936, -12123, -10284, -8982, -10069, -8165, -12776, -13049, -9193, -11356, -9753, -14195, -28777, -10899, -17034, -10613, -13365, -13049, -12123, -17034, -8615, -9429, -11232, -8754, -13738, -7179, -7796, -11781, -7213, -9331, -6719, -7752, -14195, -7050, -7196, -7081, -8827, -11488, -7774, -6842, -8333, -10069, -9106, -8485, -8165, -10799, -10362, -9064, -8034, -12319, -28777, -10613, -11781, -7113, -28777, -12534, -12123, -11629, -6943, -13049, -10001, -14195, -8903, -8363, -11115, -9331, -12534, -8615, -12319, -10138, -9380, -10210, -9695, -13049, -10899, -9238, -8790, -10704, -12319, -11781, -9585, -7912, -9873, -11945, -10899, -10704, -7353, -8827, -9639, -10526, -9479, -7426, -7888, -8942, -11004, -7960, -8517, -7299, -10138, -12123, -7542, -10526, -7562, -14195, -12319, -8060, -10069, -9064, -12776, -11115, -9331, -9193, -12534, -10210, -11356, -10799, -10138, -17034, -9873, -12534, -11629, -14784, -15615, -10704, -11115, -12123, -13738, -14784, -11004, -9812, -11629, -10442, -12123, -10362, -10138, -10362, -4863, -7264, -8363, -10001, -8582, -7353, -10138, -7842, -11004, -7146, -7335, -12776, -8615, -12534, -5702, -5915, -10613, -10284, -28777, -6299, -5997, -11232, -12534, -11629, -9531, -8393, -13738, -12319, -10138, -8615, -10799, -9812, -11004, -13365, -6615, -6732, -7281, -11945, -13738, -6885, -5346, -5759, -28777, -9429, -9284, -5429, -4968, -15615, -8138, -13365, -7299, -4923, -12319, -7213, -8982, -11945, -5286, -10613, -7034, -7774, -8754, -5524, -9429, -8276, -7960, -7503, -5472, -9531, -12319, -8718, -7097, -5768, -13049, -10284, -9695, -6615, -7408, -10526, -7484, -10799, -6814, -11945, -7317, -6434, -9064, -8754, -17034, -6214, -6267, -7230, -10284, -12534, -5195, -6786, -6516, -7542, -7842, -3989, -8192, -6719, -7113, -6399, -3422, -11115, -7819, -8454, -6914, -3930, -11004, -8549, -9193, -8220, -5380, -8485, -7371, -8304, -8423, -6457, -7281, -6288, -8615, -8582, -6745, -6492, -5915, -9429, -9812, -7464, -5906, -6214, -8827, -11488, -9753, -5630, -6828, -7583, -10899, -14784, -5784, -6988, -6123, -11004, -7842, -6143, -6256, -4847, -9479, -6225, -6288, -5374, -4161, -7162, -6093, -6480, -4974, -4075, -6074, -6504, -6773, -5158, -4523, -5879, -6870, -7179, -5853, -5561, -6163, -7004, -8549, -7213, -7583, -6705, -7247, -12319, -9238, -9695, -6973, -8363, -11232, -9936, -8517, -6885, -11781, -8485, -8649, -8582, -7752, -13738, -7730, -7426, -11004, -11232, -10138, -7819, -7034, -13738, -14195, -10138, -7960, -7389, -13049, -10613, -12319, -7960, -7819, -13738, -9022, -12319, -8333, -8423, -13365, -7264, -11781, -9639, -9812, -17034, -6745, -14195, -11945, -10799, -12319, -7264, -14784, -12123, -12123, -8112, -8086, -9531, -10704, -11629, -6628, -8423, -6914, -10899, -8649, -6332, -8615, -5592, -11781, -7426, -6666, -9064, -5360, -13738, -6899, -7317, -9753, -6214, -17034, -6928, -8549, -10210, -8942, -10799, -7730, -10526, -10899, -28777, -8165, -9531, -10899, -12776, -9695, -7097, -12319, -10799, -11781, -8754, -7050, -28777, -13738, -9238, -10442, -7484, -12123, -14195, -8903, -13738, -7796, -8683, -11629, -11356, -10362, -7842, -7034, -12123, -15615, -9380, -8034, -6246, -11945, -9380, -10442, -8517, -6628, -10210, -8582, -13365, -9149, -8790, -9812, -9695, -13365, -9380, -13738, -10001, -11004, -11629, -9479, -13365, -9238, -10799, -10442, -10526, -10526, -8060, -11232, -10799, -13049, -7960, -7247, -12319, -12319, -14195, -6653, -6928, -12319, -15615, -13365, -6299, -7113, -12123, -28777, -12776, -6666, -7842, -11629, -28777, -10284, -7865, -9479, -12319, -28777, -8827, -10613, -13049, -14784, -28777, -8903, -17034, -28777, -17034, -14784, -10284, -13365, -13365, -12123, -11629, -12319, -14195, -12123, -11356, -9936, -13365, -28777, -11629, -11945, -9695, -11629, -14195, -11488, -12319, -10799, -10138, -13365, -11781, -10799, -13365, -9873, -14195, -11945, -10284, -12534, -11781, -14784, -12319, -11356, -11232, -28777, -13365, -11488, -17034, -11629, -11115, -10138, -9812, -13738, -13049, -9585, -8790, }; \ No newline at end of file diff --git a/sw/applications/trans_versasense/tokenPosEmbeddingC.c b/sw/applications/trans_versasense/tokenPosEmbeddingC.c new file mode 100644 index 00000000..39a63e40 --- /dev/null +++ b/sw/applications/trans_versasense/tokenPosEmbeddingC.c @@ -0,0 +1,33 @@ +// +// Created by alireza on 10/6/23. +// + +#include "tokenPosEmbeddingC.h" + + +void createTokenPosEmbedding(TokenPosEmbedding* tokenPosEmbedding, quant_bit_width* pos_matrix, quant_bit_width* cls_token_vector, size_t seq_len, size_t input_dim, size_t pos_matrix_dim) { + tokenPosEmbedding->cls_token_vector_ = cls_token_vector; + tokenPosEmbedding->pos_matrix_ = pos_matrix; + tokenPosEmbedding->seq_len_ = seq_len; + tokenPosEmbedding->input_dim_ = input_dim; +} + +void clsConcatenate(TokenPosEmbedding* tpe, quant_bit_width* input, quant_bit_width* concatenated_input) { + // Copy cls_token_ into the concatenated array column-wise at the beginning + for (size_t i = 0; i < tpe->input_dim_; ++i) { + concatenated_input[i] = tpe->cls_token_vector_[i]; + } + // Copy the input array into the concatenated array + for (size_t i = 0; i < tpe->seq_len_ * tpe->input_dim_; ++i) { + concatenated_input[i + tpe->input_dim_] = input[i]; + } +} + +void posEmbedding(TokenPosEmbedding* tpe, quant_bit_width* input) { + for (size_t i = 0; i < (tpe->seq_len_ + 1); ++i) { + for (size_t j = 0; j < tpe->input_dim_; ++j) { + input[i * tpe->input_dim_+ j] += tpe->pos_matrix_[i * tpe->input_dim_ + j]; + } + } +} + diff --git a/sw/applications/trans_versasense/tokenPosEmbeddingC.h b/sw/applications/trans_versasense/tokenPosEmbeddingC.h new file mode 100644 index 00000000..9357a153 --- /dev/null +++ b/sw/applications/trans_versasense/tokenPosEmbeddingC.h @@ -0,0 +1,24 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_TOKENPOSEMBEDDINGC_H +#define FVLLMONTITRANSFORMER_TOKENPOSEMBEDDINGC_H + +#include "param.h" +#include "stdlib.h" + +typedef struct{ + quant_bit_width* cls_token_vector_; + quant_bit_width* pos_matrix_; + size_t seq_len_; + size_t input_dim_; +} TokenPosEmbedding; + + +void createTokenPosEmbedding(TokenPosEmbedding*, quant_bit_width* pos_matrix, quant_bit_width* cls_token_vector, size_t seq_len, size_t input_dim, size_t pos_matrix_dim); +void clsConcatenate(TokenPosEmbedding* tpe, quant_bit_width* input, quant_bit_width* concatenated_input); +void posEmbedding(TokenPosEmbedding* tpe, quant_bit_width* input); + + +#endif //FVLLMONTITRANSFORMER_TOKENPOSEMBEDDINGC_H diff --git a/sw/applications/trans_versasense/transformerBlockC.c b/sw/applications/trans_versasense/transformerBlockC.c new file mode 100644 index 00000000..111a36af --- /dev/null +++ b/sw/applications/trans_versasense/transformerBlockC.c @@ -0,0 +1,116 @@ +// +// Created by alireza on 10/6/23. +// + +#include +#include "transformerBlockC.h" +#include "multiply_cgra.h" + +SingleHeadSelfAttn global_selfatten [NUM_LAYERS * NUM_HEAD]; +Dense global_query_layer[NUM_LAYERS * NUM_HEAD]; +Dense global_key_layer[NUM_LAYERS * NUM_HEAD]; +Dense global_value_layer[NUM_LAYERS * NUM_HEAD]; + +Dense global_condense[NUM_LAYERS]; +Dense global_patch; +Dense global_FF[NUM_LAYERS * 2]; +Dense global_mlp; + +TransformerBlock global_transformer_block; +TokenPosEmbedding global_token_embedding; + +TransformerBlock* createTransformerBlock(size_t pre_seq_len, size_t input_dim, size_t head_hidden_size, size_t num_heads, size_t ff_size, int32_t** weightVector, int32_t** biasVector, int32_t* clsTokenVector, int32_t* posMatrix) { + TransformerBlock* transformerBlock = &global_transformer_block; + transformerBlock->num_heads_ = num_heads; + transformerBlock->head_hidden_size_ = head_hidden_size; + transformerBlock->input_dim_ = input_dim; + transformerBlock->ff_size_ = ff_size; + + transformerBlock->addNorm = createAddNormalize(pre_seq_len, D_EMBEDDING, weightVector[0], biasVector[0]); + transformerBlock->patchEmbedding = &global_patch; + createDense(transformerBlock->patchEmbedding, D_EMBEDDING, D_MODEL, weightVector[1], biasVector[1]); + transformerBlock->addNorm2 = createAddNormalize(pre_seq_len, D_MODEL, weightVector[2], biasVector[2]); + transformerBlock->token = &global_token_embedding; + createTokenPosEmbedding(transformerBlock->token, posMatrix, clsTokenVector, pre_seq_len, input_dim, D_SEQ + 1); + + for (int l = 0; l < 4; l++) { + transformerBlock->transformer_layer_0_addNorm[l] = createAddNormalize((pre_seq_len + 1), D_MODEL, weightVector[l * 17 + 3], biasVector[l * 17 + 3]); + + for (int n = 0; n < num_heads; n++) { + transformerBlock->selfatten[l * num_heads + n] = &global_selfatten[l * num_heads + n]; + transformerBlock->selfatten[l * num_heads + n]->query_layer = &global_query_layer[l * num_heads + n]; + transformerBlock->selfatten[l * num_heads + n]->key_layer = &global_key_layer[l * num_heads + n]; + transformerBlock->selfatten[l * num_heads + n]->value_layer = &global_value_layer[l * num_heads + n]; + + create_SingleHeadSelfAttn(transformerBlock->selfatten[l * num_heads + n], (pre_seq_len + 1), input_dim, head_hidden_size, weightVector + l * 17 + 4 + n * 3); + } + + transformerBlock->condense[l] = &global_condense[l]; + createDense(transformerBlock->condense[l], num_heads * head_hidden_size, input_dim, weightVector[l * 17 + num_heads * 3 + 4], biasVector[l * 17 + num_heads * 3 + 4]); + + transformerBlock->transformer_layer_1_addNorm[l] = createAddNormalize((pre_seq_len + 1), input_dim, weightVector[l * 17 + num_heads * 3 + 5], biasVector[l * 17 + num_heads * 3 + 5]); + + transformerBlock->feedForward0[l] = &global_FF[2*l]; + createDense(transformerBlock->feedForward0[l], input_dim, ff_size, weightVector[l * 17 + num_heads * 3 + 6], biasVector[l * 17 + num_heads * 3 + 6]); + + transformerBlock->feedForward1[l] = &global_FF[2*l + 1]; + createDense(transformerBlock->feedForward1[l], ff_size, input_dim, weightVector[l * 17 + num_heads * 3 + 7], biasVector[l * 17 + num_heads * 3 + 7]); + } + + transformerBlock->mlp_head_norm = createAddNormalize(1, D_MODEL, weightVector[(NUM_LAYERS - 1) * 17 + NUM_HEAD * 3 + 8], biasVector[(NUM_LAYERS - 1) * 17 + NUM_HEAD * 3 + 8]); + + transformerBlock->mlp_head_linear = &global_mlp; + createDense(transformerBlock->mlp_head_linear, D_MODEL, D_MODEL, weightVector[(NUM_LAYERS - 1) * 17 + NUM_HEAD * 3 + 9], biasVector[(NUM_LAYERS - 1) * 17 + NUM_HEAD * 3 + 9]); + + return transformerBlock; +} + + +void destroyTransformerBlock(TransformerBlock* transformerBlock) { + // Free dynamically allocated memory + + free(transformerBlock); +} + +void computeFixedPoint(TransformerBlock* transformerBlock, size_t seq_len, quant_bit_width * input, + quant_bit_width * input_normalized, quant_bit_width * output, + quant_bit_width* intermediate, quant_bit_width* qkv, quant_bit_width * aux_padding, void * kperf) { + + //printf("\rStep 1\n"); + normalize(&transformerBlock->addNorm, input, input); // 12x400 + computeDense(transformerBlock->patchEmbedding, seq_len, input, output); // 12x400x16 -> OK + normalize(&transformerBlock->addNorm2, output, output); // 12x16 + + clsConcatenate(transformerBlock->token, output, input); // 13x16 + seq_len++; + posEmbedding(transformerBlock->token, input); // 13x16 + + //printf("\rStep 2\n"); + for (int l = 0; l < 4; l++) { + normalize(&transformerBlock->transformer_layer_0_addNorm[l], input, input_normalized); // 13x16 + for (int n = 0; n < NUM_HEAD; n++) { + // printf("\rl%d: Step 3\n", l); + compute_SingleHeadSelfAttn(transformerBlock->selfatten[l * NUM_HEAD + n], input_normalized, + output + n * (seq_len * transformerBlock->head_hidden_size_), qkv, intermediate, aux_padding); +// destroy_SingleHeadSelfAttn(transformerBlock->selfatten[l * NUM_HEAD + n]); + } + //printf("\rl%d: Step 4\n", l); + multihead_transpose(output, intermediate, seq_len, transformerBlock->head_hidden_size_, transformerBlock->num_heads_); + + int padding = 3; + computeDense(transformerBlock->condense[l], seq_len + padding, intermediate, output); // 13x16x16 + + add(input, output, seq_len, transformerBlock->input_dim_ ); // 13x16 + + normalize(&transformerBlock->transformer_layer_1_addNorm[l], input, input_normalized); // 13x16 + computeDense(transformerBlock->feedForward0[l], seq_len + padding, input_normalized, intermediate); // 13x16x4 + activation(transformerBlock->feedForward0[l], seq_len * transformerBlock->ff_size_, intermediate, intermediate); // 13x4 + + computeDense(transformerBlock->feedForward1[l], seq_len + padding, intermediate, output); // 13x4x16 + add(input, output, seq_len, transformerBlock->input_dim_ ); // 13x16 + } + //printf("\rStep 5\n"); + normalize(&transformerBlock->mlp_head_norm, input, input_normalized); // 13x16 + computeDenseOneRow(transformerBlock->mlp_head_linear, 1, input_normalized, output); // 1x16x16 +} + diff --git a/sw/applications/trans_versasense/transformerBlockC.h b/sw/applications/trans_versasense/transformerBlockC.h new file mode 100644 index 00000000..f783d2a7 --- /dev/null +++ b/sw/applications/trans_versasense/transformerBlockC.h @@ -0,0 +1,48 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_TRANSFORMERBLOCK_H +#define FVLLMONTITRANSFORMER_TRANSFORMERBLOCK_H + +#include +#include +#include "selfattentionC.h" +#include "addNormC.h" +#include "dense_layerC.h" +#include "tokenPosEmbeddingC.h" +#include "param.h" +#include "transposeC.h" +#include "cgra.h" + +typedef struct { + size_t num_heads_; + size_t head_hidden_size_; + size_t input_dim_; + size_t ff_size_; + SingleHeadSelfAttn* selfatten[NUM_LAYERS*NUM_HEAD]; + int32_t* multihead_out; + int32_t* condense_out; + int32_t* intermediateFF; + int32_t* intermediateFFBlockWise; + AddNormalize addNorm; + AddNormalize addNorm2; + AddNormalize transformer_layer_0_addNorm[NUM_LAYERS]; + AddNormalize transformer_layer_1_addNorm[NUM_LAYERS]; + AddNormalize mlp_head_norm; + TokenPosEmbedding* token; + Dense* condense[NUM_LAYERS]; + Dense* feedForward0[NUM_LAYERS]; + Dense* feedForward1[NUM_LAYERS]; + Dense* patchEmbedding; + Dense* mlp_head_linear; + #ifndef REARRANGE + int32_t* multihead_out_reshape; + #endif +} TransformerBlock; + +TransformerBlock* createTransformerBlock(size_t pre_seq_len, size_t input_dim, size_t head_hidden_size, size_t num_heads, size_t ff_size, int32_t** weightVector, int32_t** biasVector, int32_t* clsTokenVector, int32_t* posMatrix); +void destroyTransformerBlock(TransformerBlock* transformerBlock); +void computeFixedPoint(TransformerBlock* transformerBlock, size_t seq_len, int32_t* input, int32_t* input_normalized, int32_t* output, int32_t* intermediate, int32_t* aux_padding, int32_t* qkv, void * kperf); + +#endif //FVLLMONTITRANSFORMER_TRANSFORMERBLOCK_H diff --git a/sw/applications/trans_versasense/transposeC.c b/sw/applications/trans_versasense/transposeC.c new file mode 100644 index 00000000..2c27aa52 --- /dev/null +++ b/sw/applications/trans_versasense/transposeC.c @@ -0,0 +1,31 @@ +// +// Created by alireza on 10/6/23. +// + +#include "softmaxC.h" + + +void multihead_transpose(const quant_bit_width * input, quant_bit_width* output, size_t seq_len, + size_t head_hidden_size, size_t num_head) { + const quant_bit_width * initial_input = input; + for (int i=0; i < seq_len; i++){ + for (int n=0; n< num_head; n++){ + input = initial_input + i*head_hidden_size + n*seq_len*head_hidden_size; + for (int j=0; j < head_hidden_size; j++){ + *output++ = *input++; + } + } + } +} + + +void transpose_quant(const quant_bit_width * input, quant_bit_width* output, + size_t width, size_t height) { + for (size_t i = 0; i < height; i++) { + for (size_t j = 0; j < width; j++) { + output[i * width + j] = input[j * height + i]; + } + } +} + + diff --git a/sw/applications/trans_versasense/transposeC.h b/sw/applications/trans_versasense/transposeC.h new file mode 100644 index 00000000..500c100e --- /dev/null +++ b/sw/applications/trans_versasense/transposeC.h @@ -0,0 +1,22 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_TRANSPOSEC_H +#define FVLLMONTITRANSFORMER_TRANSPOSEC_H + + + +#include +#include "param.h" + +// Replace class with struct +typedef struct { + // struct members +} Transpose; + +// Function prototypes +void transpose_quant(const quant_bit_width* input, quant_bit_width* output, size_t width, size_t height); +void multihead_transpose(const quant_bit_width * input, quant_bit_width* output, size_t seq_len, size_t head_hidden_size, size_t num_head); + +#endif //FVLLMONTITRANSFORMER_TRANSPOSEC_H diff --git a/sw/applications/trans_versasense/weightsAndBiasesC.c b/sw/applications/trans_versasense/weightsAndBiasesC.c new file mode 100644 index 00000000..2fd600f0 --- /dev/null +++ b/sw/applications/trans_versasense/weightsAndBiasesC.c @@ -0,0 +1,181 @@ +// +// Created by alireza on 10/6/23. +// +#include "weightsAndBiasesC.h" +#include +#include +#include "data_cpp/data.cpp" + +void getWeights(quant_bit_width * weightVec[]){ + + int weightVectorIndex = 0; + weightVec[weightVectorIndex++] = to_patch_embedding_layer_norm1_weight; + weightVec[weightVectorIndex++] = to_patch_embedding_linear_weight; + weightVec[weightVectorIndex++] = to_patch_embedding_layer_norm2_weight; + + + /* *************************** Layer 1 ***************************** */ + weightVec[weightVectorIndex++] = transformer_layers_0_0_norm_weight; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_Q_H0; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_K_H0; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_V_H0; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_Q_H1; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_K_H1; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_V_H1; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_Q_H2; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_K_H2; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_V_H2; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_Q_H3; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_K_H3; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_V_H3; + + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_projection_weight; + + weightVec[weightVectorIndex++] = transformer_layers_0_1_norm_weight; + + weightVec[weightVectorIndex++] = transformer_layers_0_1_fn_ff1_weight; + weightVec[weightVectorIndex++] = transformer_layers_0_1_fn_ff2_weight; + + /* *************************** Layer 2 ***************************** */ + weightVec[weightVectorIndex++] = transformer_layers_1_0_norm_weight; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_Q_H0; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_K_H0; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_V_H0; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_Q_H1; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_K_H1; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_V_H1; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_Q_H2; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_K_H2; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_V_H2; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_Q_H3; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_K_H3; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_V_H3; + + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_projection_weight; + + weightVec[weightVectorIndex++] = transformer_layers_1_1_norm_weight; + + weightVec[weightVectorIndex++] = transformer_layers_1_1_fn_ff1_weight; + weightVec[weightVectorIndex++] = transformer_layers_1_1_fn_ff2_weight; + + /* *************************** Layer 3 ***************************** */ + weightVec[weightVectorIndex++] = transformer_layers_2_0_norm_weight; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_Q_H0; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_K_H0; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_V_H0; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_Q_H1; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_K_H1; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_V_H1; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_Q_H2; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_K_H2; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_V_H2; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_Q_H3; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_K_H3; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_V_H3; + + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_projection_weight; + + weightVec[weightVectorIndex++] = transformer_layers_2_1_norm_weight; + + weightVec[weightVectorIndex++] = transformer_layers_2_1_fn_ff1_weight; + weightVec[weightVectorIndex++] = transformer_layers_2_1_fn_ff2_weight; + + /* *************************** Layer 4 ***************************** */ + weightVec[weightVectorIndex++] = transformer_layers_3_0_norm_weight; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_Q_H0; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_K_H0; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_V_H0; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_Q_H1; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_K_H1; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_V_H1; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_Q_H2; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_K_H2; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_V_H2; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_Q_H3; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_K_H3; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_V_H3; + + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_projection_weight; + + weightVec[weightVectorIndex++] = transformer_layers_3_1_norm_weight; + + weightVec[weightVectorIndex++] = transformer_layers_3_1_fn_ff1_weight; + weightVec[weightVectorIndex++] = transformer_layers_3_1_fn_ff2_weight; + + /* *************************** MLP HEAD ***************************** */ + weightVec[weightVectorIndex++] = mlp_head_layer_norm_weight; + weightVec[weightVectorIndex++] = mlp_head_linear_weight; + +} + +void getBiases(quant_bit_width * biasVec[]){ + int biasVectorIndex = 0; + biasVec[biasVectorIndex++] = to_patch_embedding_layer_norm1_bias; + biasVec[biasVectorIndex++] = to_patch_embedding_linear_bias; + biasVec[biasVectorIndex++] = to_patch_embedding_layer_norm2_bias; + + /* *************************** Layer 1 ***************************** */ + biasVec[biasVectorIndex++] = transformer_layers_0_0_norm_bias; + for (int i=0; i<3*4; i++) + biasVec[biasVectorIndex++] = (quant_bit_width *) NULL; + + biasVec[biasVectorIndex++] = transformer_layers_0_0_fn_projection_bias; + biasVec[biasVectorIndex++] = transformer_layers_0_1_norm_bias; + + biasVec[biasVectorIndex++] = transformer_layers_0_1_fn_ff1_bias; + biasVec[biasVectorIndex++] = transformer_layers_0_1_fn_ff2_bias; + + /* *************************** Layer 2 ***************************** */ + biasVec[biasVectorIndex++] = transformer_layers_1_0_norm_bias; + + for (int i=0; i<3*4; i++) + biasVec[biasVectorIndex++] = (quant_bit_width *) NULL; + + biasVec[biasVectorIndex++] = transformer_layers_1_0_fn_projection_bias; + biasVec[biasVectorIndex++] = transformer_layers_1_1_norm_bias; + + biasVec[biasVectorIndex++] = transformer_layers_1_1_fn_ff1_bias; + biasVec[biasVectorIndex++] = transformer_layers_1_1_fn_ff2_bias; + + /* *************************** Layer 3 ***************************** */ + biasVec[biasVectorIndex++] = transformer_layers_2_0_norm_bias; + + for (int i=0; i<3*4; i++) + biasVec[biasVectorIndex++] = (quant_bit_width *) NULL; + + biasVec[biasVectorIndex++] = transformer_layers_2_0_fn_projection_bias; + biasVec[biasVectorIndex++] = transformer_layers_2_1_norm_bias; + + biasVec[biasVectorIndex++] = transformer_layers_2_1_fn_ff1_bias; + biasVec[biasVectorIndex++] = transformer_layers_2_1_fn_ff2_bias; + + /* *************************** Layer 4 ***************************** */ + biasVec[biasVectorIndex++] = transformer_layers_3_0_norm_bias; + + for (int i=0; i<3*4; i++) + biasVec[biasVectorIndex++] = (quant_bit_width *) NULL; + + biasVec[biasVectorIndex++] = transformer_layers_3_0_fn_projection_bias; + biasVec[biasVectorIndex++] = transformer_layers_3_1_norm_bias; + + biasVec[biasVectorIndex++] = transformer_layers_3_1_fn_ff1_bias; + biasVec[biasVectorIndex++] = transformer_layers_3_1_fn_ff2_bias; + + /* *************************** MLP HEAD ***************************** */ + biasVec[biasVectorIndex++] = mlp_head_layer_norm_bias; + biasVec[biasVectorIndex++] = mlp_head_linear_bias; +} + +quant_bit_width * getPosEmbedding(){ + quant_bit_width * posMatrix; + posMatrix = pos_embedding; + return posMatrix; +} + +quant_bit_width * getClassToken(){ + quant_bit_width * clsTokenVector; + clsTokenVector = cls_token; + return clsTokenVector; +} + + diff --git a/sw/applications/trans_versasense/weightsAndBiasesC.h b/sw/applications/trans_versasense/weightsAndBiasesC.h new file mode 100644 index 00000000..b16d6468 --- /dev/null +++ b/sw/applications/trans_versasense/weightsAndBiasesC.h @@ -0,0 +1,15 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_WEIGHTSANDBIASESC_H +#define FVLLMONTITRANSFORMER_WEIGHTSANDBIASESC_H + +#include "param.h" + +void getWeights(quant_bit_width * weightVec[]); +void getBiases(quant_bit_width * biasVec[]); +quant_bit_width * getPosEmbedding(); +quant_bit_width * getClassToken(); + +#endif //FVLLMONTITRANSFORMER_WEIGHTSANDBIASESC_H diff --git a/sw/applications/transformer/SYLT-FFT/LICENSE b/sw/applications/transformer/SYLT-FFT/LICENSE new file mode 100644 index 00000000..f1c15f58 --- /dev/null +++ b/sw/applications/transformer/SYLT-FFT/LICENSE @@ -0,0 +1,48 @@ +MHG (MORAL HIGH GROUND) LICENSE + +This software is released under the UNLICENSE license under the single +condition that good moral standards are maintained in its use. + +The term "moral standards" is chosen because it is impossible to define +legally as it varies with cultural and individual values, principles and +ideas. Hence, the following may or may not apply. + +If you find this software useful - use it in any way you like, but +consider dropping the author a "thank you" message. + +If you want to use this software to earn money - please do, but +consider mentioning the authors name or making a donation. + +If you use this software - consider letting the author know. Simply +knowing it is being put to good use is often rewarding. + +You should consider maintaining open source licensing for software +that uses or is derived from this software. + + +UNLICENSE + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to \ No newline at end of file diff --git a/sw/applications/transformer/SYLT-FFT/README.md b/sw/applications/transformer/SYLT-FFT/README.md new file mode 100644 index 00000000..530a2f31 --- /dev/null +++ b/sw/applications/transformer/SYLT-FFT/README.md @@ -0,0 +1,59 @@ +SYLT-FFT +======== +DEVSOUND (I)FFT(R) LIBRARY +------------------------------------- +And some other funky fixed-point maths like gray-coding and pow(2, f) + +**Optimized (C-level) for Keil C Compiler and GCC on Cortex-M4.** + +**Authors:** +* D. Taylor 2014 (gmail: senseitg) + +**License:** +* MHG (GPL compatible) - see LICENSE + +**Features:** +* FFT (Fast Fourier Transform) and IFFT (Inverse FFT) +* Fixed-point 32-bit, Radix-2 +* Complex or real (with slight conversion overhead) data +* No plan construction required before (I)FFT +* No reliance on other libraries (including libm if using precomputed tables) + +**Options (config.h):** +* DIT (decimation-in-time) or DIF (decimation-in-frequency) +* Rounding on divide (-speed, +accuracy) +* Saturating math (-speed, +stability) +* Table size vs. max. FFT length + +**Resource requirements:** +* Minimal memory requirements (in-place) +* Minimal stack use (non-recursive) +* Minimal twiddle tables (512 bytes for max N=512 FFT) + +**Notes:** +* Designed for optimal performance, not optimal accuracy + +**Caveats:** +* Care must be taken with input data to ensure no overflows +* Requires C99 (-std=c99 for GCC) + +**Performance:** +* Comparing against: CMSIS DSP arm_cortexM4I_math.lib(1.4.2) +* Platform: Freescale Kinetis K20 (Cortex-M4/ARMv7E-M) +* KEIL = Keil C Compiler 5.01 -O3 +* GCC = GNU Tools for ARM Embedded Processors 4.8.4 -O3 + +``` +Comparisons are of speed, +N% = faster than CMSIS, -N% = slower. +Please verify and do additional tests to add to the list. + + CMSIS-DSP SYLT-FFT N KEIL GCC +* arm_cfft_radix2_q31 fft_inverse 256 +25.6% +15.1% +``` + +**Thanks to:** +* [Wikipedia](http://www.wikipedia.org/) - for existing and taking donations +* [KATJA](http://www.katjaas.nl/) - for intelligible merge/split spectra algorithm +* [XCORE](https://github.com/xcore/) - for intelligible (I)FFT algorithm +* [CMLAB](http://www.cmlab.csie.ntu.edu.tw/cml/dsp/training/coding/transform/fft.html) - for intelligible FFT algorithm breakdown +* [BEVAN](http://web.ece.ucdavis.edu/~bbaas/281/slides/Handout.fft2.pdf) - for intelligible DIT vs. DIF, radix-2 vs. 4 overview diff --git a/sw/applications/transformer/SYLT-FFT/config.h b/sw/applications/transformer/SYLT-FFT/config.h new file mode 100644 index 00000000..a55673dd --- /dev/null +++ b/sw/applications/transformer/SYLT-FFT/config.h @@ -0,0 +1,88 @@ +// CONFIGURATION FILE +// D. TAYLOR 2014 + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +#include "stdint.h" +#include "stdbool.h" + +#ifndef __INLINE +#if defined(__GNUC__) +#define __INLINE __attribute__((always_inline)) inline +#else +#define __INLINE __inline +#endif +#endif + + +/* == MATH CONFIGURE =============================================== */ + +#define FPOW2_FBITS 27 // Number of fractional bits (1...28) +#define FPOW2_LIMIT 8 // Limit accuracy to n fractional bits (1...FPOW2_FBITS-1) + +#define SINE_BITS 7 // Sine quality (2..14) vs. memory tradeoff +#define SINE_USE_TABLE 1 // Use pre-computed ROM table (vs. generate in RAM) +#define SINE_PRINTOUT 0 // Write sine table to screen (PC only) + +/* == FFT CONFIGURE =============================================== */ + +// Maximum FFT size: 4 << SINE_BITS (complex data points) +// Memory used by sine table: 4 << SINE_BITS (bytes) +// FFT is faster when SINE_USE_TABLE is 0 (located in RAM) + +#define FFT_DIT // Operation mode, FFT_DIT or FFT_DIF (slower) +#define FFT_ROUNDING 0 // Perform rounding when dividing (slower) +#define FFT_SATURATE 0 // Use saturating math where possible (slower) + +/* == WAVETABLE CONFIGURE ========================================== */ + +/* == GLOBAL DATA CONFIGURE ======================================== */ + +// PI +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +// LUT for sine wave, first quadrant only +#if SINE_USE_TABLE +// == PLACE GENERATED SINE TABLE HERE ======================== // +// ROM +#if SINE_BITS != 7 +#error "sinetable[] size does not match SINE_BITS" +#endif +const int32_t sinetable[] = { + 0x00000000, 0x01921d1f, 0x03242abe, 0x04b6195d, 0x0647d97c, 0x07d95b9e, 0x096a9049, 0x0afb6805, + 0x0c8bd35e, 0x0e1bc2e3, 0x0fab272b, 0x1139f0ce, 0x12c8106e, 0x145576b1, 0x15e21444, 0x176dd9de, + 0x18f8b83c, 0x1a82a025, 0x1c0b826a, 0x1d934fe5, 0x1f19f97b, 0x209f701c, 0x2223a4c5, 0x23a6887e, + 0x25280c5d, 0x26a82185, 0x2826b928, 0x29a3c484, 0x2b1f34eb, 0x2c98fbba, 0x2e110a61, 0x2f875262, + 0x30fbc54d, 0x326e54c7, 0x33def287, 0x354d9056, 0x36ba2013, 0x382493b0, 0x398cdd32, 0x3af2eeb7, + 0x3c56ba70, 0x3db832a5, 0x3f1749b7, 0x4073f21d, 0x41ce1e64, 0x4325c135, 0x447acd50, 0x45cd358f, + 0x471cece6, 0x4869e664, 0x49b41533, 0x4afb6c97, 0x4c3fdff3, 0x4d8162c4, 0x4ebfe8a4, 0x4ffb654d, + 0x5133cc94, 0x5269126e, 0x539b2aef, 0x54ca0a4a, 0x55f5a4d2, 0x571deef9, 0x5842dd54, 0x59646497, + 0x5a827999, 0x5b9d1153, 0x5cb420df, 0x5dc79d7c, 0x5ed77c89, 0x5fe3b38d, 0x60ec382f, 0x61f1003e, + 0x62f201ac, 0x63ef328f, 0x64e88926, 0x65ddfbd3, 0x66cf811f, 0x67bd0fbc, 0x68a69e81, 0x698c246c, + 0x6a6d98a4, 0x6b4af278, 0x6c242960, 0x6cf934fb, 0x6dca0d14, 0x6e96a99c, 0x6f5f02b1, 0x70231099, + 0x70e2cbc6, 0x719e2cd2, 0x72552c84, 0x7307c3cf, 0x73b5ebd0, 0x745f9dd0, 0x7504d345, 0x75a585cf, + 0x7641af3c, 0x76d94988, 0x776c4edb, 0x77fab988, 0x78848413, 0x7909a92c, 0x798a23b1, 0x7a05eead, + 0x7a7d055b, 0x7aef6323, 0x7b5d039d, 0x7bc5e28f, 0x7c29fbee, 0x7c894bdd, 0x7ce3ceb1, 0x7d3980ec, + 0x7d8a5f3f, 0x7dd6668e, 0x7e1d93e9, 0x7e5fe493, 0x7e9d55fc, 0x7ed5e5c6, 0x7f0991c3, 0x7f3857f5, + 0x7f62368f, 0x7f872bf2, 0x7fa736b4, 0x7fc25596, 0x7fd8878d, 0x7fe9cbbf, 0x7ff62182, 0x7ffd885a, + 0x7fffffff, // <= space potato! +}; // <= sad monkey? +// == END OF GENERATED SINE TABLE ============================ // +#else +// RAM +int32_t sinetable[(1 << SINE_BITS) + 1]; +#endif + +// LUT for pow(2, fixedpoint) +// Only need to define up to FPOW2_LIMIT +const int32_t fpow2table[] = { + 0x6a09e668, 0x306fe0a3, 0x172b83c8, 0x0b5586d0, 0x059b0d31, 0x02c9a3e7, 0x0163daa0, 0x00b1afa6, +/*0x0058c86e, 0x002c605e, 0x00162f39, 0x000b175f, 0x00058ba0, 0x0002c5cc, 0x000162e5, 0x0000b172, + 0x000058b9, 0x00002c5d, 0x0000162e, 0x00000b17, 0x0000058c, 0x000002c6, 0x00000163, 0x000000b1, + 0x00000059, 0x0000002c, 0x00000016, 0x0000000b, 0x00000006, 0x00000003, 0x00000001, 0x00000001,*/ +}; + +#endif diff --git a/sw/applications/transformer/SYLT-FFT/fft.h b/sw/applications/transformer/SYLT-FFT/fft.h new file mode 100644 index 00000000..d6fb3ba7 --- /dev/null +++ b/sw/applications/transformer/SYLT-FFT/fft.h @@ -0,0 +1,423 @@ +// (I)FFT(R) +// D. TAYLOR 2014 + +#ifndef __FFT_H__ +#define __FFT_H__ + +#include "config.h" +#include "intrinsics.h" +#include "fpmath.h" + +/* == DECLARATIONS ================================================ */ + +// Fixed-point data type +typedef int32_t fft_t; + +// Complex number type +typedef struct { + fft_t r, i; +} fft_complex_t; + +// Readability macros +#define FFT_QCOS(K, SH) sinetable[(1 << SINE_BITS) - (K << SH)] +#define FFT_QSIN(K, SH) sinetable[K << SH] + +#if !((defined FFT_DIT) | (defined FFT_DIF)) +#error "Must define FFT_DIT or FFT_DIF" +#endif + + +/* == CODING STYLE DEFINITIONS ==================================== */ + +// GCC/ARMCC require different coding styles for optimal performance. +// These defines unify the different styles into one syntax. + +// # Optimal performance on ARMCC (Keil) # +#if defined(__ARMCC_VERSION) +// Declare complex, assign complex +#define FFT_DECLC(VAR, ASG) fft_complex_t VAR = ASG; +// Declare complex, assign real, imaginary +#define FFT_DECLR(VAR, R, I) fft_complex_t VAR = (fft_complex_t){ .r = R, .i = I }; +// Assign real, imaginary +#define FFT_ASSGN(VAR, R, I) VAR = (fft_complex_t){ .r = R, .i = I }; +// Access real, imaginary +#define FFT(VAR, SUB) VAR.SUB +#endif + +// # Optimal performance on GCC # +#if defined(__GNUC__) +// Declare complex, assign complex +#define FFT_DECLC(VAR, ASG) fft_t VAR##r = ASG.r, VAR##i = ASG.i; +// Declare complex, assign real, imaginary +#define FFT_DECLR(VAR, R, I) fft_t VAR##r = R, VAR##i = I; +// Assign real, imaginary +#define FFT_ASSGN(VAR, R, I) VAR.r = R; VAR.i = I; +// Access real, imaginary +#define FFT(VAR, SUB) VAR##SUB +#endif + +#if FFT_SATURATE +#define FFT_A(A,B) qadd(A, B) // A + B (saturating) +#define FFT_S(A,B) qsub(A, B) // A - B (saturating) +#define FFT_M2(W) qadd(W, W) // W * 2 (saturating) +#else +#define FFT_A(A,B) ((A) + (B)) // A + B +#define FFT_S(A,B) ((A) - (B)) // A - B +#define FFT_M2(W) ((W) << 1) // W * 2 +#endif +#define FFT_M(A,B) smmulr(A, B) // A * B +#define FFT_MA(A,B,C) smmlar(A, B, C) // C + (A * B) +#define FFT_MS(A,B,C) smmlsr(A, B, C) // C - (A * B) +#if FFT_ROUNDING +#define FFT_D2(W) (((W) + 1) >> 1) // W / 2 (rounded) +#else +#define FFT_D2(W) ((W) >> 1) // W / 2 +#endif + +/* == FORWARD AND INVERSE FFT ===================================== */ + +// Forward FFT transform +// Permutation must be performed prior to (DIT)/after (DIF) call +void fft_forward(fft_complex_t data[], unsigned bits) { + unsigned size = 1 << bits; +#ifdef FFT_DIT + unsigned shift = SINE_BITS + 1; + for(unsigned stride = 2 ; stride <= size; stride <<= 1, shift--) { +#else//FFT_DIF + unsigned shift = SINE_BITS - (bits - 2); + for(unsigned stride = size; stride >= 2; stride >>= 1, shift++) { +#endif + // Twiddle and combine for k = 0, having trivial (0 and 1) twiddle factors + for(unsigned a = 0; a < size; a += stride) { + unsigned b = a + (stride >> 1); +/* + FFT_DECLC(A, data[a]); FFT_DECLC(B, data[b]); + // # Radix-2 DIT/DIF trivial butterfly # + FFT_ASSGN(data[a], FFT_D2(FFT_ADD(FFT(A,r), FFT(B,r))), FFT_D2(FFT_ADD(FFT(A,i), FFT(B,i)))); + FFT_ASSGN(data[b], FFT_D2(FFT_SUB(FFT(A,r), FFT(B,r))), FFT_D2(FFT_SUB(FFT(A,i), FFT(B,i)))); +*/ + // Special case: GCC optimizes ARMCC style better here + fft_complex_t A = data[a], B = data[b]; + // # Radix-2 DIT/DIF trivial butterfly # + data[a] = (fft_complex_t){ .r = FFT_D2(FFT_A(A.r, B.r)), .i = FFT_D2(FFT_A(A.i, B.i)) }; + data[b] = (fft_complex_t){ .r = FFT_D2(FFT_S(A.r, B.r)), .i = FFT_D2(FFT_S(A.i, B.i)) }; + } + if(!(stride & 2)) { + for(unsigned a = (stride >> 2); a < (stride >> 2) + size; a += stride) { + unsigned b = a + (stride >> 1); + FFT_DECLC(A, data[a]); FFT_DECLC(B, data[b]); +#ifdef FFT_DIT + // # Radix-2 DIT trivial butterfly # + FFT_ASSGN(data[a], FFT_D2(FFT_A(FFT(A,r), FFT(B,i))), FFT_D2(FFT_S(FFT(A,i), FFT(B,r)))); + FFT_ASSGN(data[b], FFT_D2(FFT_S(FFT(A,r), FFT(B,i))), FFT_D2(FFT_A(FFT(A,i), FFT(B,r)))); +#else//FFT_DIF + // # Radix-2 DIF trivial butterfly # + FFT_ASSGN(data[a], FFT_D2(FFT_A(FFT(A,r), FFT(B,r))), FFT_D2(FFT_A(FFT(A,i), FFT(B,i)))); + FFT_ASSGN(data[b], FFT_D2(FFT_S(FFT(A,i), FFT(B,i))), FFT_D2(FFT_S(FFT(B,r), FFT(A,r)))); +#endif + } + } + // Twiddle and combine + for(unsigned k = 1; k < (stride >> 2); k++) { + FFT_DECLR(W, FFT_QCOS(k, shift), FFT_QSIN(k, shift)); + for(unsigned a = k, b; a < size; a += (stride >> 2) + (stride >> 1)) { + b = a + (stride >> 1); + { // These two blocks prevent the compiler from confusing... + FFT_DECLC(A, data[a]); FFT_DECLC(B, data[b]); +#ifdef FFT_DIT + // # Radix-2 DIT butterfly # + FFT_DECLR(BW, FFT_MA(FFT(B,i), FFT(W,i), FFT_M(FFT(B,r), FFT(W,r))), + FFT_MS(FFT(B,r), FFT(W,i), FFT_M(FFT(B,i), FFT(W,r)))); + FFT_ASSGN(data[a], FFT_A(FFT_D2(FFT(A,r)), FFT(BW,r)), FFT_A(FFT_D2(FFT(A,i)), FFT(BW,i))); + FFT_ASSGN(data[b], FFT_S(FFT_D2(FFT(A,r)), FFT(BW,r)), FFT_S(FFT_D2(FFT(A,i)), FFT(BW,i))); +#else//FFT_DIF + // # Radix-2 DIF butterfly # + FFT_ASSGN(data[a], FFT_D2(FFT_A(FFT(A,r), FFT(B,r))), FFT_D2(FFT_A(FFT(A,i), FFT(B,i)))); + FFT_DECLR(D, FFT_S(FFT(A,r), FFT(B,r)), FFT_S(FFT(A,i), FFT(B,i))); + FFT_ASSGN(data[b], FFT_MA(FFT(D,r), FFT(W,r), FFT_M(FFT(D,i), FFT(W,i))), + FFT_MS(FFT(D,r), FFT(W,i), FFT_M(FFT(D,i), FFT(W,r)))); +#endif + } + a += (stride >> 2); b += (stride >> 2); + { // ...register use resulting in more efficient code + FFT_DECLC(A, data[a]); FFT_DECLC(B, data[b]); +#ifdef FFT_DIT + // # Radix-2 DIT butterfly # + FFT_DECLR(BW, FFT_MS(FFT(B,r), FFT(W,i), FFT_M(FFT(B,i), FFT(W,r))), + FFT_MA(FFT(B,i), FFT(W,i), FFT_M(FFT(B,r), FFT(W,r)))); + FFT_ASSGN(data[a], FFT_A(FFT_D2(FFT(A,r)), FFT(BW,r)), FFT_S(FFT_D2(FFT(A,i)), FFT(BW,i))); + FFT_ASSGN(data[b], FFT_S(FFT_D2(FFT(A,r)), FFT(BW,r)), FFT_A(FFT_D2(FFT(A,i)), FFT(BW,i))); +#else//FFT_DIF + // # Radix-2 DIF butterfly # + FFT_ASSGN(data[a], FFT_D2(FFT_A(FFT(A,r), FFT(B,r))), FFT_D2(FFT_A(FFT(A,i), FFT(B,i)))); + FFT_DECLR(D, FFT_S(FFT(B,r), FFT(A,r)), FFT_S(FFT(B,i), FFT(A,i))); + FFT_ASSGN(data[b], FFT_MS(FFT(D,i), FFT(W,r), FFT_M(FFT(D,r), FFT(W,i))), + FFT_MA(FFT(D,i), FFT(W,i), FFT_M(FFT(D,r), FFT(W,r)))); +#endif + } + } + } + } +} + +// Inverse FFT transform +// Permutation must be performed prior to (DIT)/after (DIF) call +void fft_inverse(fft_complex_t data[], unsigned bits) { + unsigned size = 1 << bits; +#ifdef FFT_DIT + unsigned shift = SINE_BITS + 1; + for(unsigned stride = 2 ; stride <= size; stride <<= 1, shift--) { +#else//FFT_DIF + unsigned shift = SINE_BITS - (bits - 2); + for(unsigned stride = size; stride >= 2; stride >>= 1, shift++) { +#endif + // Twiddle and combine for k = 0, having trivial (0 and 1) twiddle factors + for(unsigned a = 0; a < size; a += stride) { + unsigned b = a + (stride >> 1); +/* + FFT_DECLC(A, data[a]); FFT_DECLC(B, data[b]); + // # Radix-2 DIT/DIF trivial butterfly # + FFT_ASSGN(data[a], FFT_A(FFT(A,r), FFT(B,r)), FFT_A(FFT(A,i), FFT(B,i))); + FFT_ASSGN(data[b], FFT_S(FFT(A,r), FFT(B,r)), FFT_S(FFT(A,i), FFT(B,i))); +*/ + // Special case: GCC optimizes ARMCC style better here + fft_complex_t A = data[a], B = data[b]; + // # Radix-2 DIT/DIF trivial butterfly # + data[a] = (fft_complex_t){ .r = FFT_A(A.r, B.r), .i = FFT_A(A.i, B.i) }; + data[b] = (fft_complex_t){ .r = FFT_S(A.r, B.r), .i = FFT_S(A.i, B.i) }; + } + if(!(stride & 2)) { + for(unsigned a = (stride >> 2); a < size; a += stride) { + unsigned b = a + (stride >> 1); + FFT_DECLC(A, data[a]); FFT_DECLC(B, data[b]); +#ifdef FFT_DIT + // # Radix-2 DIT trivial butterfly # + FFT_ASSGN(data[a], FFT_S(FFT(A,r), FFT(B,i)), FFT_A(FFT(A,i), FFT(B,r))); + FFT_ASSGN(data[b], FFT_A(FFT(A,r), FFT(B,i)), FFT_S(FFT(A,i), FFT(B,r))); +#else//FFT_DIF + // # Radix-2 DIF trivial butterfly # + FFT_ASSGN(data[a], FFT_A(FFT(A,r), FFT(B,r)), FFT_A(FFT(A,i), FFT(B,i))); + FFT_ASSGN(data[b], FFT_S(FFT(B,i), FFT(A,i)), FFT_S(FFT(A,r), FFT(B,r))); +#endif + } + } + // Twiddle and combine + for(unsigned k = 1; k < (stride >> 2); k++) { + FFT_DECLR(W, FFT_QCOS(k, shift), FFT_QSIN(k, shift)); + for(unsigned a = k, b; a < size; a += (stride >> 2) + (stride >> 1)) { + b = a + (stride >> 1); + { // These two blocks prevent the compiler from confusing... + FFT_DECLC(A, data[a]); FFT_DECLC(B, data[b]); +#ifdef FFT_DIT + // # Radix-2 DIT butterfly # + FFT_DECLR(BW, FFT_MS(FFT(B,r), FFT(W,r), FFT_M(FFT(B,i), FFT(W,i))), + FFT_MA(FFT(B,i), FFT(W,r), FFT_M(FFT(B,r), FFT(W,i)))); + FFT_ASSGN(data[a], FFT_S(FFT(A,r), FFT_M2(FFT(BW,r))), FFT_A(FFT(A,i), FFT_M2(FFT(BW,i)))); + FFT_ASSGN(data[b], FFT_A(FFT(A,r), FFT_M2(FFT(BW,r))), FFT_S(FFT(A,i), FFT_M2(FFT(BW,i)))); +#else//FFT_DIF + // # Radix-2 DIF butterfly # + FFT_ASSGN(data[a], FFT_A(FFT(A,r), FFT(B,r)), FFT_A(FFT(A,i), FFT(B,i))); + FFT_DECLR(D, FFT_S(FFT(A,r), FFT(B,r)), FFT_S(FFT(A,i), FFT(B,i))); + FFT_ASSGN(data[b], FFT_M2(FFT_MS(FFT(D,i), FFT(W,i), FFT_M(FFT(D,r), FFT(W,r)))), + FFT_M2(FFT_MA(FFT(D,i), FFT(W,r), FFT_M(FFT(D,r), FFT(W,i))))); +#endif + } + a += (stride >> 2); b += (stride >> 2); + { // ...register use resulting in more efficient code + FFT_DECLC(A, data[a]); FFT_DECLC(B, data[b]); +#ifdef FFT_DIT + // # Radix-2 DIT butterfly # + FFT_DECLR(BW, FFT_MA(FFT(B,i), FFT(W,r), FFT_M(FFT(B,r), FFT(W,i))), + FFT_MS(FFT(B,r), FFT(W,r), FFT_M(FFT(B,i), FFT(W,i)))); + FFT_ASSGN(data[a], FFT_S(FFT(A,r), FFT_M2(FFT(BW,r))), FFT_S(FFT(A,i), FFT_M2(FFT(BW,i)))); + FFT_ASSGN(data[b], FFT_A(FFT(A,r), FFT_M2(FFT(BW,r))), FFT_A(FFT(A,i), FFT_M2(FFT(BW,i)))); +#else//FFT_DIF + // # Radix-2 DIF butterfly # + FFT_ASSGN(data[a], FFT_A(FFT(A,r), FFT(B,r)), FFT_A(FFT(A,i), FFT(B,i))); + FFT_DECLR(D, FFT_S(FFT(A,r), FFT(B,r)), FFT_S(FFT(B,i), FFT(A,i))); + FFT_ASSGN(data[b], FFT_M2(FFT_MS(FFT(D,r), FFT(W,i), FFT_M(FFT(D,i), FFT(W,r)))), + FFT_M2(FFT_MA(FFT(D,i), FFT(W,i), FFT_M(FFT(D,r), FFT(W,r))))); +#endif + } + } + } + } +} + + +/* == DATA SET PROCESSING AND MANIPULATION ======================== */ + +// Process complex data to produce real-only output +// This allows us to output N*2 point of real data using a N point complex (I)FFT +// Even/odd real data will be found in the real/imaginary parts of every output bin upon completion +void fft_convert(fft_complex_t data[], unsigned bits, bool permutated, bool invert) { + unsigned size = 1 << --bits; + unsigned shift = SINE_BITS - bits++; + unsigned n, z, nc, zc; + fft_t rsum, rdif, isum, idif; + fft_t itwiddled, rtwiddled; + for(nc = zc = size; nc; nc--, zc++) { + if(permutated) { + n = RBITS(nc, bits); z = RBITS(zc, bits); + } else { + n = nc; z = zc; + } + rsum = data[n].r + data[z].r; isum = data[n].i + data[z].i; + rdif = data[n].r - data[z].r; idif = data[n].i - data[z].i; + fft_t r = FFT_QCOS(nc, shift); fft_t i = -FFT_QSIN(nc, shift); + if(invert) r = -r; + rtwiddled = FFT_MA(r, isum, FFT_M(i, rdif)) << 1; + itwiddled = FFT_MS(r, rdif, FFT_M(i, isum)) << 1; + data[n].r = rsum + rtwiddled; data[n].i = itwiddled + idif; + data[z].r = rsum - rtwiddled; data[z].i = itwiddled - idif; + } + fft_t data_0_tr = data[0].r; + data[0].r = (data[0].r + data[0].i); data[0].i = (data_0_tr - data[0].i); + if(!invert) { data[0].r <<= 1; data[0].i <<= 1; } +} + +// Perform bit-reversal permutation on data set +// (Reverses address bits for all data points) +void fft_permutate(fft_complex_t data[], unsigned bits) { + unsigned size = 1 << bits; + unsigned shift = 32 - bits; + for(unsigned i = 1; i < size - 1; i++) { + unsigned z = rbit(i) >> shift; + if(z > i) { + fft_t + t = data[i].r; data[i].r = data[z].r; data[z].r = t; + t = data[i].i; data[i].i = data[z].i; data[z].i = t; + } + } +} + + +/* == "HIGH"-LEVEL FUNCTIONS ====================================== */ + +// Perform forward FFT (including permutation) +__INLINE +void fft_fft(fft_complex_t *complex, unsigned bits) { +#ifdef FFT_DIT + fft_permutate(complex, bits); +#endif + fft_forward(complex, bits); +#ifdef FFT_DIF + fft_permutate(complex, bits); +#endif +} + +// Perform inverse FFT (including permutation) +__INLINE +void fft_ifft(fft_complex_t *complex, unsigned bits) { +#ifdef FFT_DIT + fft_permutate(complex, bits); +#endif + fft_inverse(complex, bits); +#ifdef FFT_DIF + fft_permutate(complex, bits); +#endif +} + +// Perform forward FFT (including permutation, real output conversion) +__INLINE +void fft_fftr(fft_complex_t *complex, unsigned bits) { + fft_fft(complex, bits); + fft_convert(complex, bits, false, false); +} + +// Perform inverse FFT (including permutation, real input conversion) +__INLINE +void fft_ifftr(fft_complex_t *complex, unsigned bits) { + fft_convert(complex, bits, false, true); + fft_ifft(complex, bits); +} + + +/* == DATA SET CONSTRUCTION ======================================= */ + +// Magnitude and phase => complex FFT bin [index] +// A data set built with this method does not require fft_permutate before DIT IFFT +__INLINE +void fft_phase_magnitude(fft_complex_t complex[], unsigned bits, unsigned index, int32_t mag, uint32_t pha) { +#ifdef FFT_DIT + unsigned n = RBITS(index, bits); +#else//FFT_DIF + unsigned n = index; +#endif + complex[n].r = FFT_M(mag, sine(pha)); + complex[n].i = FFT_M(mag, cosine(pha)); +} + +// Magnitude, phase:0 => complex FFT bin [index] +// A data set built with this method does not require fft_permutate before DIT IFFT +__INLINE +void fft_magnitude(fft_complex_t complex[], unsigned bits, unsigned index, int32_t mag) { +#ifdef FFT_DIT + unsigned n = RBITS(index, bits); +#else//FFT_DIF + unsigned n = index; +#endif + complex[n].r = 0; complex[n].i = mag; +} + +// REAL Symmetric DC offset => complex FFT bin [0] (DC) +// A data set built with this method does not require fft_permutate before DIT IFFT +// A data set built with this method does not require fft_convert before IFFT +__INLINE +void fft_real_dc(fft_complex_t data[], fft_t r, fft_t i) { + data[0].r = r + i; + data[0].i = r - i; +} + +// REAL Symmetric magnitude and phase => complex FFT bins [index], [size-index] +// A data set built with this method does not require fft_permutate before DIT IFFT +// A data set built with this method does not require fft_convert before IFFT +void fft_real_phase_magnitude(fft_complex_t complex[], unsigned bits, unsigned index, int32_t mag_lo, int32_t pha_lo, int32_t mag_hi, int32_t pha_hi) { + unsigned size = 1 << bits; + unsigned shift = SINE_BITS - (bits - 1); +#ifdef FFT_DIT + unsigned n = RBITS(index, bits); + unsigned z = RBITS(size - index, bits); +#else//FFT_DIF + unsigned n = index; + unsigned z = size - index; +#endif + fft_t rsum, rdif, isum, idif, r, i; + fft_t itwiddled, rtwiddled; + r = FFT_M(mag_lo, sine(pha_lo)); + i = FFT_M(mag_hi, sine(pha_hi)); + rsum = r + i; rdif = r - i; + r = FFT_M(mag_lo, cosine(pha_lo)); + i = FFT_M(mag_hi, cosine(pha_hi)); + isum = r + i; idif = r - i; + r = -FFT_QCOS(index, shift); i = -FFT_QSIN(index, shift); + rtwiddled = FFT_MA(r, isum, FFT_M(i, rdif)) << 1; + itwiddled = FFT_MS(r, rdif, FFT_M(i, isum)) << 1; + complex[n].r = rsum + rtwiddled; complex[n].i = itwiddled + idif; + complex[z].r = rsum - rtwiddled; complex[z].i = itwiddled - idif; +} + +// REAL Symmetric magnitude, phase:0 => complex FFT bins [index], [size-index] +// This method works with permutated (bit-reversed) addressing +// A data set built with this method does not require fft_permutate before DIT IFFT +// A data set built with this method does not require fft_convert before IFFT +void fft_real_magnitude(fft_complex_t complex[], unsigned bits, unsigned index, int32_t mag_lo, int32_t mag_hi) { + unsigned shift = SINE_BITS - bits + 1; +#ifdef FFT_DIT + unsigned n = RBITS(index, bits); + unsigned z = RBITS((1 << bits) - index, bits); +#else//FFT_DIF + unsigned n = index; + unsigned z = (1 << bits) - index; +#endif + fft_t isum, idif, r, i; + fft_t itwiddled, rtwiddled; + isum = (mag_lo + mag_hi); idif = mag_lo - mag_hi; + r = FFT_QCOS(index, shift); i = FFT_QSIN(index, shift); + rtwiddled = FFT_M(r, isum) << 1; + itwiddled = FFT_M(i, isum) << 1; + complex[n].r = -rtwiddled; complex[n].i = (idif - itwiddled); + complex[z].r = rtwiddled; complex[z].i = -(idif + itwiddled); +} + +#endif diff --git a/sw/applications/transformer/SYLT-FFT/fpmath.h b/sw/applications/transformer/SYLT-FFT/fpmath.h new file mode 100644 index 00000000..9385d3c0 --- /dev/null +++ b/sw/applications/transformer/SYLT-FFT/fpmath.h @@ -0,0 +1,139 @@ +// FIXED POINT MATHS +// D. TAYLOR 2014 + +#ifndef __FPMATH_H__ +#define __FPMATH_H__ + +#include "config.h" +#include "intrinsics.h" +#include "fpmath.h" + +#define SINE_SIZE (1 << SINE_BITS) // Sine table size +#define SINE_FBITS (32 - 2 - SINE_BITS) // Fractional bits +#define SINE_FMASK ((1 << SINE_FBITS) - 1) // Fraction mask + +// Linear/box interpolation (30 bit precision) +// y1 is first point, y2 second +// mu is interpolation point 00000000-FFFFFFFF +// floating-point equivalent return y2 - y1 * mu + y1; +__INLINE +int32_t linear(int32_t y1, int32_t y2, uint32_t mu) { + return smmlar((y2 >> 1) - (y1 >> 1), mu >> 1, y1 >> 2) << 2; +} + +// Cubic interpolation +// y0...y3 need to be externally limited in range to prevent overflow +// y0...y3 are control points, interpolation is performed between y1 and y2 +// mu is interpolation point 00000000-FFFFFFFF +// floating-point equivalent return y1+mu/2*(y2-y0+mu*(2*y0-5*y1+4*y2-y3+mu*(3*(y1-y2)+y3-y0))) +__INLINE +int32_t cubic(int32_t y0, int32_t y1, int32_t y2, int32_t y3, uint32_t mu) { + mu >>= 1; + int32_t a = (3 * (y1 - y2) - y0 + y3); + int32_t b = 2 * y2 + y0 - (5 * y1 + y3) / 2; + int32_t c = (y2 - y0) / 2; + return smmlar(smmlar(smmlar(a, mu, b) << 1, mu, c) << 1, mu, y1); +} + +// Generate first quadrant (0 to PI/2) of sine wave +// Output table is in Q31 format, with 1 limited to 0x7FFFFFFF +void sine_init() { +#if !SINE_USE_TABLE + unsigned int n; +#if SINE_PRINTOUT + printf("// ROM\n"); + printf("#if SINE_BITS != 7\n"); + printf("#error \"sinetable[] size does not match SINE_BITS\"\n"); + printf("#endif\n"); + printf("const int32_t sinetable[] = {"); +#endif + for(n = 0; n <= SINE_SIZE; n++) { + uint64_t v = (sin(((double)n * M_PI) / (double)(SINE_SIZE * 2)) * 2147483648.0); + sinetable[n] = v > 2147483647 ? 2147483647 : v; +#if SINE_PRINTOUT + // Print table + if((n & 7) == 0) printf("\n "); + printf("0x%08x, ", sinetable[n]); +#endif + } +#if SINE_PRINTOUT + printf("// <= space potato!\n}; // <= sad monkey?\n"); +#endif +#endif +} + +// Sin by table lookup with interpolation +// pos = 00000000 to FFFFFFFF, corresponding to 0-2PI(less one) +int32_t sine(uint32_t pos) { + uint32_t fraction = (pos & SINE_FMASK) << (2 + SINE_BITS); + uint32_t index = (pos & 0x40000000) ? (0x40000000 + SINE_FMASK - (pos & 0x3FFFFFFF)) : (pos & 0x3FFFFFFF); + uint32_t indexa = index >> SINE_FBITS; + uint32_t indexb = pos & 0x40000000 ? indexa - 1 : indexa + 1; + int32_t sample = linear(sinetable[indexa], sinetable[indexb], fraction); + return pos & 0x80000000 ? -sample : sample; +} + +// Cos by table lookup with interpolation +// See sine +__INLINE +int32_t cosine(uint32_t pos) { + return sine(pos + 0x40000000); +} + +// Fast sin by table lookup +// Same as sine, but no interpolation +__INLINE +int32_t fastsin(uint32_t pos) { + uint32_t index = (pos & 0x40000000) ? 0x40000000 - (pos & 0x3fffffff) : (pos & 0x3fffffff); + int32_t sample = sinetable[index >> SINE_FBITS]; + return (pos & 0x80000000 ? -sample : sample); +} + +// Fast cos by table lookup +// See fastsin +__INLINE +int32_t fastcos(uint32_t pos) { + return fastsin(pos + 0x40000000); +} + +// Fixed point pow(2, e) +uint64_t fpow2(uint32_t e) { + uint32_t ipart = e >> FPOW2_FBITS; +#ifdef FPOW2_LIMIT + uint32_t fpart = (e >> (FPOW2_FBITS - FPOW2_LIMIT)) << (32 - FPOW2_LIMIT); +#else + uint32_t fpart = e << (32 - FPOW2_FBITS); +#endif + uint64_t final = 0x100000000; + if(fpart) { + uint32_t bit = clz(fpart); + uint32_t fcalc = fpow2table[bit++] >> 1; + fpart <<= bit; + while(fpart) { + uint32_t lzc = clz(fpart); + bit += lzc++; + int32_t fmul = fpow2table[bit++]; + fcalc += smmlar(fcalc, fmul, fmul >> 1); + fpart <<= lzc; + } + final += (uint64_t)fcalc << 1; + } + return final << ipart; +} + +// Convert binary to gray-code +unsigned bin2gray(unsigned bits) { + return (bits >> 1) ^ bits; +} + +// Convert gray-code to binary +unsigned gray2bin(unsigned bits) { + bits ^= bits >> 16; + bits ^= bits >> 8; + bits ^= bits >> 4; + bits ^= bits >> 2; + bits ^= bits >> 1; + return bits; +} + +#endif diff --git a/sw/applications/transformer/SYLT-FFT/intrinsics.h b/sw/applications/transformer/SYLT-FFT/intrinsics.h new file mode 100644 index 00000000..e2614bae --- /dev/null +++ b/sw/applications/transformer/SYLT-FFT/intrinsics.h @@ -0,0 +1,153 @@ +// INTRINSICS +// D. TAYLOR 2014 + +#ifndef __INTRINSICS_H__ +#define __INTRINSICS_H__ +#include "config.h" + +// issue warnings when not using full hardware acceleration + +#if defined(__ARMCC_VERSION) || (defined(__GNUC__) && defined(__arm__)) +#if (__CORTEX_M < 0x03) +#warning "Cortex-M core < M3 detected; hardware acceleration for math operations not supported" +#elif (__CORTEX_M < 0x04) +#warning "Cortex-M core < M4 detected; partial hardware acceleration for math operations supported" +#endif +#endif + +// reverse bits (ARM: RBIT) +__INLINE +uint32_t rbit(uint32_t x) { + uint32_t result; +#if defined(__ARMCC_VERSION) && ((__CORTEX_M >= 0x03) || (__CORTEX_SC >= 300)) + __asm{ rbit result, x } +#elif defined(__GNUC__) && defined(__arm__) && ((__CORTEX_M >= 0x03) || (__CORTEX_SC >= 300)) + __asm("rbit %0, %1":"=r"(result):"r"(x)); +#else + x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); + x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); + x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); + x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); + result = (x >> 16) | (x << 16); +#endif + return result; +} + +#define RBITS(W, BITS) (rbit(W) >> (32 - (BITS))) + +// count leading zeroes (ARM: CLZ) +__INLINE +uint32_t clz(uint32_t x) { + uint32_t result; +#if defined(__ARMCC_VERSION) && ((__CORTEX_M >= 0x03) || (__CORTEX_SC >= 300)) + __asm{ clz result, x } +#elif defined(__GNUC__) && defined(__arm__) && ((__CORTEX_M >= 0x03) || (__CORTEX_SC >= 300)) + __asm("clz %0, %1":"=r"(result):"r"(x)); +#else + x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; + x -= 0x55555555 & (x >> 1); + x = (0x33333333 & x) + (0x33333333 & (x >> 2)); + result = 32 - ((0x01010101 * (0x0F0F0F0F & (x + (x >> 4)))) >> 24); +#endif + return result; +} + +// 32-bit signed multiply -> 32-bit result, add 32-bit (ARM: SMMLAR) +// floating point equivalent: return c + a * b +__INLINE +int32_t smmlar(int32_t a, int32_t b, int32_t c) { + int32_t result; +#if defined(__ARMCC_VERSION) && (__CORTEX_M >= 0x04U) + __asm{ smmlar result, a, b, c } +#elif defined(__GNUC__) && defined(__arm__) && (__CORTEX_M >= 0x04U) + __asm("smmlar %0, %1, %2, %3":"=r"(result):"r"(a),"r"(b),"r"(c)); +#else + result = c + ((((int64_t)a * b) + 0x80000000) >> 32); +#endif + return result; +} + +// 32-bit signed multiply -> 32-bit result, subtract 32-bit (ARM: SMMLSR) +// floating point equivalent: return c - a * b +__INLINE +int32_t smmlsr(int32_t a, int32_t b, int32_t c) { + int32_t result; +#if defined(__ARMCC_VERSION) && (__CORTEX_M >= 0x04U) + __asm{ smmlsr result, a, b, c } +#elif defined(__GNUC__) && defined(__arm__) && (__CORTEX_M >= 0x04U) + __asm("smmlsr %0, %1, %2, %3":"=r"(result):"r"(a),"r"(b),"r"(c)); +#else + result = c - ((((int64_t)a * b) + 0x80000000) >> 32); +#endif + return result; +} + +// 32-bit signed multiply -> 32-bit result (ARM: SMMULR) +// floating point equivalent: return a * b +__INLINE +int32_t smmulr(int32_t a, int32_t b) { + int32_t result; +#if defined(__ARMCC_VERSION) && (__CORTEX_M >= 0x04U) + __asm{ smmulr result, a, b } +#elif defined(__GNUC__) && defined(__arm__) && (__CORTEX_M >= 0x04U) + __asm("smmulr %0, %1, %2":"=r"(result):"r"(a),"r"(b)); +#else + result = ((((int64_t)a * b) + 0x80000000) >> 32); +#endif + return result; +} + +// saturating add (ARM: qadd) +// floating point equivalent: return max(min(a + b, 1), -1) +__INLINE +int32_t qadd(int32_t a, int32_t b) { + uint32_t result; +#if defined(__ARMCC_VERSION) + __asm{ qadd result, a, b } +#elif defined(__GNUC__) + __asm("qadd %0, %1, %2":"=r"(result):"r"(a),"r"(b)); +#else + int64_t c = (int64_t)a + b; + if(c > 2147483647) c = 2147483647; + if(c < -2147483648) c = -2147483648; + result = c; +#endif + return result; +} + +// saturating subtract (ARM: qsub) +// floating point equivalent: return max(min(a - b, 1), -1) +__INLINE +int32_t qsub(int32_t a, int32_t b) { + uint32_t result; +#if defined(__ARMCC_VERSION) + __asm{ qsub result, a, b } +#elif defined(__GNUC__) && defined(__arm__) + __asm("qsub %0, %1, %2":"=r"(result):"r"(a),"r"(b)); +#else + int64_t c = (int64_t)a - b; + if(c > 2147483647) c = 2147483647; + if(c < -2147483648) c = -2147483648; + result = c; +#endif + return result; +} + +// 32-bit arithmetic shift right with rounding (ARM: ASRS + ADC) +// floating point equivalent: return v / pow(2, s) +__INLINE +int32_t asrr(int32_t v, int32_t s) { + int32_t result; +#if defined(__ARMCC_VERSION) + __asm{ asrs result, v, s }; + __asm{ adc result, result }; +#elif defined(__GNUC__) && defined(__arm__) + __asm("asrs %0, %1, %2":"=r"(result):"r"(v),"r"(s):"cc"); + __asm("adc %0, %1, #0":"=r"(result):"r"(result)); +#else + result = (v + (1 << (s - 1))) >> s; +#endif + return result; +} + +#endif diff --git a/sw/applications/transformer/SYLT-FFT/main.c b/sw/applications/transformer/SYLT-FFT/main.c new file mode 100644 index 00000000..cf59fcad --- /dev/null +++ b/sw/applications/transformer/SYLT-FFT/main.c @@ -0,0 +1,74 @@ +// BENCHMARKING FOR FRDM-K20D50M +// D. TAYLOR 2014 + +// * Do not build with operating system +// * Uses FTM0 as core clock cycle counter +// * Requires C99 standard + +#define BENCH_RUNS 100 // Not really necessary without OS + +#include + +#include +#include + +#include "config.h" +#include "intrinsics.h" +#include "fpmath.h" +#include "fft.h" + +static volatile unsigned count_hi; // FTM0 high counter +static volatile unsigned count; // Performance counter + +// FFT data structure +fft_complex_t complex[256]; + +// This function contains code to benchmark +static void benchmark(void) { + fft_inverse(complex, 8); +} + +// Initialize FTM0 +static void bench_init(void) { + SIM->SCGC6 |= SIM_SCGC6_FTM0_MASK; + FTM0->MOD = 0xFFFF; + NVIC_EnableIRQ(FTM0_IRQn); +} + +// Resets cycle counts, begins benchmarking +__INLINE +static void bench_begin(void) { + FTM0->SC = 0; + count_hi = 0; + FTM0->CNT = 0; + FTM0->SC = FTM_SC_CLKS(1) | FTM_SC_TOIE_MASK; +} + +// Ends benchmarking, returns cycle count +__INLINE +static unsigned bench_end(void) { + FTM0->SC = 0; + return (FTM0->CNT | (count_hi << 16)) - 2; +} + +// FTM0 overflow counter +void FTM0_IRQHandler(void) { + FTM0->SC &= ~FTM_SC_TOF_MASK; + count_hi++; +} + +int main() { + bench_init(); + while(1) { + // Perform benchmark + unsigned ack = 0; + for(unsigned n = 0; n < BENCH_RUNS; n++) { + bench_begin(); + benchmark(); + ack += bench_end(); + } + count = ack / BENCH_RUNS; + // Count is reported here - use a breakpoint or add communication code + count = count; + } +} diff --git a/sw/applications/transformer/addNormC.c b/sw/applications/transformer/addNormC.c new file mode 100644 index 00000000..31828e28 --- /dev/null +++ b/sw/applications/transformer/addNormC.c @@ -0,0 +1,71 @@ +// +// Created by alireza on 10/6/23. +// + +#include "addNormC.h" + + + +// Function implementations +AddNormalize createAddNormalize(int seq_len, int input_dim, quant_bit_width *weight, quant_bit_width *bias) { + AddNormalize addNorm; + addNorm.seq_len_ = seq_len; + addNorm.input_dim_ = input_dim; + addNorm.weight_ = weight; + addNorm.bias_ = bias; + // Initialize other fields as needed + return addNorm; +} + + + + +void normalize(AddNormalize *addNorm, quant_bit_width *input, quant_bit_width *input_normalized) { + for (int i = 0; i < addNorm->seq_len_; i++) { + quant_bit_width *input_ptr = input + i * (addNorm->input_dim_); + quant_bit_width *input_normalized_ptr = input_normalized + i * (addNorm->input_dim_); + + int sum = 0; + for (int j = 0; j < addNorm->input_dim_; j++) { + sum += *input_ptr; + input_ptr++; + } + + input_ptr = input + i * (addNorm->input_dim_); + quant_bit_width mean = (quant_bit_width)((float)sum / (float)addNorm->input_dim_); + + int64_t variance = 0; + for (int j = 0; j < addNorm->input_dim_; j++) { + variance += MUL_HQ((*input_ptr - mean), (*input_ptr - mean)); + input_ptr++; + } + + variance = SHIFT(variance); + float variance_float = (float)variance / (float)(addNorm->input_dim_); + variance_float = variance_float / (float)(1 << NUM_FRACTION_BITS); + float sd = sqrtf(variance_float); + float sd_inv = (float)(1 / (sd + 0.00001)); // prevent zero divide! + quant_bit_width sd_inv_int = (quant_bit_width)(sd_inv * (1 << NUM_FRACTION_BITS)); + + input_ptr = input + i * (addNorm->input_dim_); + input_normalized_ptr = input_normalized + i * (addNorm->input_dim_); + + for (int j = 0; j < addNorm->input_dim_; j++) { + *input_normalized_ptr = (quant_bit_width)MUL((*input_ptr - mean), sd_inv_int); + *input_normalized_ptr = (quant_bit_width)(MUL((*input_normalized_ptr), addNorm->weight_[j]) + addNorm->bias_[j]); + input_ptr++; + input_normalized_ptr++; + } + } +} + +void add(quant_bit_width *input, quant_bit_width *to_be_added, int seq_len, int input_dim) { + int32_t sum; + for (int i = 0; i < seq_len * input_dim; i++) { + sum = input[i] + to_be_added[i]; + if ((quant_bit_width)sum != sum) // In case of overflow in 16 bits + input[i] = (sum > 0) ? INT16_MAX : INT16_MIN; + else + input[i] = (quant_bit_width)sum; + } +} diff --git a/sw/applications/transformer/addNormC.h b/sw/applications/transformer/addNormC.h new file mode 100644 index 00000000..c2132867 --- /dev/null +++ b/sw/applications/transformer/addNormC.h @@ -0,0 +1,26 @@ +// +// Created by alireza on 10/5/23. +// + +#ifndef FVLLMONTITRANSFORMER_ADDNORMC_H +#define FVLLMONTITRANSFORMER_ADDNORMC_H + + +#include +#include +#include "math.h" +#include "param.h" + +typedef struct { + int seq_len_; + int input_dim_; + quant_bit_width *weight_; + quant_bit_width *bias_; +} AddNormalize; + + +AddNormalize createAddNormalize(int seq_len, int input_dim, quant_bit_width *weight, quant_bit_width *bias); +void normalize(AddNormalize *addNorm, quant_bit_width *input, quant_bit_width *input_normalized); +void add(quant_bit_width *input, quant_bit_width *to_be_added, int seq_len, int input_dim); + +#endif //FVLLMONTITRANSFORMER_ADDNORMC_H diff --git a/sw/applications/transformer/cgra_bitstream.h b/sw/applications/transformer/cgra_bitstream.h new file mode 100644 index 00000000..014ee6b8 --- /dev/null +++ b/sw/applications/transformer/cgra_bitstream.h @@ -0,0 +1,12 @@ +#ifndef _CGRA_BITSTREAM_H_ +#define _CGRA_BITSTREAM_H_ + +#include + +#include "cgra.h" + + +static uint32_t cgra_kmem_bitstream[CGRA_KMEM_SIZE] = { 0x0, 0xf01c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; +const uint32_t cgra_imem_bitstream[CGRA_IMEM_SIZE] = { 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x850d0000, 0x0, 0xa4081ff4, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0x850d0000, 0x0, 0x0, 0xc80000, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa5081ffc, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0x0, 0x0, 0x850d0000, 0x0, 0xab0000, 0xd0000, 0x8780001c, 0x0, 0xf0000, 0x0, 0x0, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x0, 0x0, 0xa5081ffc, 0x91c00000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8a0d0001, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xab0000, 0xd0000, 0xd0000, 0x87800018, 0xf0000, 0x0, 0x0, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x7a180010, 0x0, 0x0, 0x0, 0xa5081ffc, 0x91c00000, 0x7a180004, 0x0, 0x5a080010, 0x8a0d0001, 0x7a181ff0, 0x1a181ffd, 0xd0000, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x820d0000, 0x0, 0xa4080004, 0x0, 0x91c00000, 0x0, 0x5080000, 0x0, 0x820d0000, 0x0, 0x820d0000, 0x2080000, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x2080000, 0x0, 0x0, 0x0, 0x5080000, 0x820d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa5081ffc, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x820d0000, 0x0, 0x3080000, 0x0, 0x820d0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa5081ffc, 0x0, 0x91c00000, 0x0, 0x43180000, 0x0, 0x830d0000, 0x0, 0x830d0000, 0x4080000, 0x840d0000, 0x0, 0xab0000, 0xd0000, 0x0, 0x0, 0xf0000, 0x87800010, 0x8a0d0001, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x0, 0x0, 0xa4080004, 0x91c00000, 0x7a181ffc, 0x0, 0x0, 0xd0000, 0x7a180010, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x850d0000, 0x0, 0xa4080004, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x830d0000, 0x0, 0x2080000, 0x0, 0x830d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x0, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x3a080010, 0x0, 0x0, 0x0, 0x4080000, 0x830d0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x4090000, 0x0, 0x0, 0x2080000, 0x0, 0x61180000, 0x910f0000, 0x0, 0x800005, 0x8080000, 0x8a0d0010, 0x8a081ff0, 0x91c00000, 0x0, 0x0, 0x0, 0x800003, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x8b90000, 0x0, 0x0, 0x0, 0x0, 0x2080000, 0x61180000, 0x910f0000, 0x8a0d0004, 0x0, 0x0, 0xa508000c, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0x840d0000, 0x0, 0x800002, 0x0, 0xab0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x5090000, 0x0, 0x0, 0x3080000, 0x0, 0x61180000, 0x910f0000, 0x7a180010, 0x0, 0x0, 0x0, 0xa4080004, 0x91c00000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xad0000, 0x0, 0x0, 0x0, 0xf0000, 0x0, 0x0, 0x0, 0x5090000, 0x8b80000, 0x0, 0x0, 0x61180000, 0x910f0000, 0x0, 0x820d0000, 0x0, 0xa4080004, 0x0, 0x91c00000, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0x0, 0x0, 0x840d0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + +#endif // _CGRA_BITSTREAM_H_ diff --git a/sw/applications/transformer/data_cpp/data.cpp b/sw/applications/transformer/data_cpp/data.cpp new file mode 100644 index 00000000..4e7efc7a --- /dev/null +++ b/sw/applications/transformer/data_cpp/data.cpp @@ -0,0 +1,104 @@ +#include "stdint-gcc.h" + +int32_t pos_embedding[1936] = {-1383, 964, -5839, -3654, -5069, 4064, -1907, -3855, -3658, -8857, 316, -1245, -3385, 1368, -2997, 13377, 7049, -1252, 2205, -219, -1524, -1316, 4386, 3600, 244, 6103, 1171, 2736, -222, -10278, 728, -1065, 297, 490, 2032, 4887, 4769, -2205, -2950, 3033, 1045, -84, -924, -9504, 871, 6262, -6855, -7938, 3453, -1851, 2541, 741, 10731, 1307, 2100, -4055, -1536, 5267, -2867, -2898, 1939, 25, 3560, 3399, -2064, 139, -1077, 4781, -8273, -6488, 403, 439, 1265, 8417, -106, -211, -4182, 3988, 6307, 104, 3200, -2645, 2750, 1677, 5047, 1988, -368, 784, 2920, 1074, -3975, 322, 2831, -2976, -1221, 4132, -8774, -3231, -3688, -1704, 6092, 4813, -2799, -686, 6206, 460, 10634, 6885, -3182, 5878, 920, -1219, 461, 2684, -2039, -7031, -5283, -6447, 5388, 490, 692, -1467, 28, -72, -766, 6259, 2560, 9225, -6087, -4768, -285, 933, -5913, 6449, 840, -2466, 1073, 2144, 2515, -2408, -7375, 7211, -1006, 1794, -9011, -5, 2908, 3234, 891, -2127, 2135, 1420, -1477, -820, 486, 2927, 2929, -6034, -4795, 6535, 981, 1943, -2114, 112, 1866, 3449, 114, 4353, -3075, 722, 8027, -2035, -2310, 1004, -1842, 766, -193, -4143, -468, -10321, -641, -4879, -58, -4413, -6004, 1211, 2336, -7301, -2585, -2329, -2014, -9458, -2424, -2518, -2531, -1006, -11344, -79, 579, -2929, -3784, -115, 1487, 338, -6021, 6798, -3510, -1279, -584, 4754, 4306, 6089, 5313, -7733, -5283, -1086, -4182, -10, 1619, 7458, 4068, 3304, -3974, -2321, -3290, 1892, 4567, 3601, 3791, 6113, -2470, -1036, 3080, 2368, -84, -365, -3006, 2347, -2591, -3977, -5959, 1168, 475, -7409, 4234, -3694, -3462, -2384, -1386, 6249, 2631, -3582, -2584, -3016, -4120, -3507, 6681, 9170, -512, 2289, 437, -7173, -4825, -7726, -3024, 3, -152, 2356, -125, -793, 1257, 11753, 841, 689, -5175, 525, -30, 2126, 399, 4477, -6030, -8924, 6246, 2527, 4445, 3728, 3477, -4071, -2582, 265, 2704, 4541, 4935, -4722, -661, 2167, -1137, 4947, 484, -7557, 2390, -604, 5174, -1680, -7771, 5151, -2544, 4752, -5385, -5953, 6899, 1995, -3538, -1964, -2005, -2899, -3806, -2889, -875, -6668, 2421, 7852, -4135, 3480, -2472, 1312, -372, -1592, -4654, 2972, 6772, -1416, 1550, 956, 858, -2759, 3268, -2765, -4870, -2471, -794, 679, -6719, -659, -159, -987, -247, -3032, -1714, 232, -1652, -3874, -919, -7050, -1827, -5084, -771, -4296, 3897, -3539, 3699, 7776, -7566, 1318, -3243, -2937, -3200, 4591, 5992, -2227, -1440, 112, 4378, 5404, -8718, 279, -1468, -10044, 2330, -4613, -4171, 344, 3440, 8488, -3674, 51, 1177, 2204, -716, -1666, -1899, -2359, 4873, -2739, 1130, 1508, 492, -4401, 7262, -369, -4263, -383, -833, 4751, -292, 2986, -3862, 5871, 1335, 280, 2117, -4211, -2144, -2733, 1554, 2206, -3493, -6634, 491, 3879, 2548, 1455, 4467, 1138, 2686, 3161, 16872, -5, 1346, -7243, -3078, 757, 76, 647, 3155, -7469, 5539, -4297, 2788, -2706, -824, 9735, 227, -164, 1836, -2907, -902, 3414, 9070, 448, -365, 3590, 1785, 3155, -4327, 1762, -192, 5660, -4526, -2613, -5665, 4197, -7165, 6556, -575, -2809, 9670, -1455, 3162, 5698, -2530, 6970, -1283, 2194, 3080, 5368, -2841, 1661, -3814, 734, 2233, 1298, -2275, 2558, -663, 337, -1486, 5124, -4945, -705, 2226, 3647, 3922, -1636, -3246, -1121, 5034, 6748, 1672, -7449, 4429, 7100, -2473, 7379, -947, 96, 883, -571, 5956, 2154, -4363, -5640, 483, 4663, 4230, -1531, 4186, 8916, 2290, 2685, -3635, -2636, -10375, -359, -763, 3008, 1932, -3181, 4049, -2683, -1566, 218, 1499, -4272, 8315, -5687, -3909, -10107, -2763, 49, 4835, -3659, 5096, 2762, 1572, -1215, -1102, 1778, -304, -3823, -7065, -3514, 842, 1533, 3766, 7351, 2417, -4943, 3180, -1947, 1386, -76, 3659, -998, -3692, 1470, -4130, -4735, -920, -3834, -142, -1852, 1681, 1398, -1615, -395, -5920, 1152, 2867, -8946, -1574, -4741, 2136, 2927, -3393, 1605, 1767, 624, -161, -9984, -9672, -1855, -1974, 2349, -7959, 8138, 405, 3118, -5967, -400, -2649, 1157, 5872, 3428, 3737, -1628, 1432, 319, -1607, 1023, -2374, 3938, 1798, -3673, 1438, 3258, -753, -1809, 5015, 4319, -5591, 8596, 1887, -4751, -4368, 2422, -1443, -134, -788, -21, -2064, 1963, -10361, -3825, -3084, 10016, 2496, 7829, -1263, 10488, -6681, -2736, -3243, -2854, -5366, 4789, 3023, 5010, -1605, 818, 3508, 4327, 1620, 5211, 1638, -1602, -6396, -1011, -4742, -2177, -769, -7017, -5381, 6374, -434, 5859, -1740, -3273, -1150, -272, -4498, -1411, 3119, -2595, -3171, 2275, 4851, -2317, 9149, -5869, -470, -6065, -5685, -3181, -3491, 2468, 1930, -3545, -4076, 4313, -2524, -3857, -800, -2219, 3414, 477, -968, -2669, -3937, 7518, -421, -2605, -230, -2500, 1462, -3009, 1442, 3465, -1343, -4661, 9064, -1488, 2426, 4510, 5118, -6978, -8568, -3232, -803, 1624, -3680, -2136, -3299, -5547, -4491, -6242, 1845, 5622, -710, 3020, 5498, -3608, 1922, 1233, -851, 623, 1153, 2165, -5331, 5668, -4262, 6967, 5474, -86, 3346, -2149, 1429, 1485, 4000, 2078, 1875, 5851, -3715, 4393, 1652, 1144, 5240, 728, 1415, -864, 3615, 1811, 3974, -92, 4902, -8521, -4400, -627, 675, -3433, -3801, -2291, 3850, -6717, 0, -3766, -5335, -5421, -3057, 3809, -5880, 1665, 378, 4789, 3382, -5372, 4777, -1177, 329, -4118, -724, -6930, -1720, -1816, 436, 7447, -533, 4725, -2361, -1161, -3119, 4255, 8766, -1131, 22, 1182, 3252, 4970, -3812, -5076, 971, 7043, -2200, -4456, 3164, 707, -6497, -5324, -218, 9741, -6039, -8101, 6605, 6995, 2298, -10900, -9604, 14083, -2495, 1095, 6337, 1553, 636, 2874, -2222, -2863, 3775, 4896, 8593, -1049, -760, 1582, -720, 54, -1277, -493, -2055, -4673, 2164, -5176, -8766, 3986, 538, 1980, 3639, -5559, 2434, -6174, -2313, -933, 2087, 5489, 1018, -3362, 2350, 8964, 3414, -2611, 5676, -6438, -441, 4548, -3126, 454, 4305, -6046, -1526, 8867, -2809, -3597, 4805, 2720, 5284, -3439, -4167, -1973, -6302, -2436, 693, 2798, -3159, -3125, -1843, -9666, -2709, 6212, -2448, -2614, 9744, 7912, -2084, 6710, -519, -3216, -2973, 339, -1878, 5720, 1510, 3180, 2514, -516, -6191, 8129, -1176, 2473, -1280, -5885, 1885, 2574, 3670, -3595, 5584, 2165, -6515, 5554, -23, 9021, -1911, -881, 465, -2769, -1336, 4516, 781, 1487, 826, -239, 3450, -4089, 312, 4057, -1917, -4253, 2178, 3868, 2352, -96, 3171, 1883, -4054, 7586, -11703, -329, 4425, -6981, 5046, 3208, -4103, -112, -1376, 4341, -2181, -2487, -892, -589, 271, 3055, -346, -137, 741, 2066, 6128, 2551, -4083, -6775, -1311, -4114, 1237, 3796, -616, 3564, 352, -4720, -765, -1952, -3557, 4101, -1777, 4274, 887, 295, 951, -3343, -646, 5854, 4607, -1567, -3609, -4403, 6565, -7334, 109, 1943, 2694, -3486, 2950, -515, 2109, -4209, -3735, -7865, 324, -7742, 8839, 2293, -3205, -2644, 295, 1396, 861, -2310, -6156, -1106, 802, 3566, 486, -1692, 5686, 1646, -1695, 769, 2990, 5526, -2497, -3342, -533, -3074, -5231, 5510, 936, 4001, -324, 4587, 10056, 4353, 1130, -421, 674, -6294, 1722, 2558, 4, -2187, 6847, 2125, -6077, 2690, -719, 2561, 4669, -2845, 5001, 2939, -7002, 2354, 742, 2684, -799, -4004, -5759, 2889, -4625, -6648, 1569, 735, -553, 6963, 2696, 2508, -8183, 5055, -1470, 4075, -5437, -7301, 1969, 2904, 134, -4279, 6075, -1524, 355, -3125, 10803, 1276, -1346, 3689, 794, 742, 1634, 3327, 2022, -3683, 3090, 7283, 1861, -4229, 7780, 3606, -238, -4646, 5503, -2117, -1909, 1908, 6075, -6532, -1732, 5579, 3041, -3126, 4348, 4055, 692, -753, -4153, -1657, 2367, 6320, -235, -9175, -3784, -615, 2829, 2843, -2256, -1470, -5818, -6843, -196, -151, 1301, 2017, -4884, -203, 9959, -4350, 462, 3320, 4236, 1534, -4264, 699, 1578, 3318, 4140, 4835, 1014, -440, 8480, 1889, -706, -1703, 7888, -4966, 2139, 283, -2559, -1652, -1207, 999, 5663, 3620, -9024, 1337, -331, 4966, 1586, -5856, 6659, 4837, -3025, 1162, 204, -2217, -2655, -3015, 3457, -415, -10613, 4144, 4124, -2337, 4753, -2210, 6730, 5633, -4650, 6065, 1790, 4687, 1802, 5954, 3767, 1889, 3277, 1196, -3345, -50, -582, -976, 1391, 4427, -2472, 10868, 1423, -4134, 1687, 616, -5144, 3766, 7614, -3716, -2228, 8223, -4436, -49, 4142, 6244, 2533, 1008, 3650, 3387, 2705, 228, -1405, 1866, -2994, 6573, 6639, 2522, 892, -6028, -7974, -1034, -2814, -5937, -1890, -5217, -7161, -11827, 1492, -355, 5499, -1280, 6, -5161, -3852, 2855, -353, -2529, 999, -5875, 540, 690, 2957, 2639, -5606, 3065, -912, -8014, -2138, 11664, -2999, 3785, -3479, -443, 5357, 3674, 6408, 7416, -2708, -3874, 1420, -8040, 123, -5179, -1861, -68, 2909, 2095, 398, 3777, 2569, 10516, -3511, -10, -4321, -4616, 1167, -8103, 3211, -8598, -1242, -3099, 521, 3416, -4465, 1157, -5550, -219, -164, 3618, 795, -2932, -2417, -3135, 3185, -4072, -229, -5254, -9385, -2973, 7064, 1924, 6405, -2424, 2374, 3312, 1684, 46, 2385, 788, 6867, 1158, 1092, -1723, -3498, 1711, 106, -958, -2024, -2930, 8257, 7091, -1887, -2165, -1379, -4090, 3170, -1518, -1696, -461, -95, -1146, -3041, -486, -1225, 2840, 2454, -535, 4306, 4365, 1027, -7522, 6268, -3390, 1507, -4160, 3606, 4296, 844, 6481, 5322, 845, 1058, -2461, -770, 5714, -1310, 2248, -2115, 8250, -729, -3421, 4037, -2574, -1750, 5356, -6683, -4439, -2797, -5302, -5110, 398, -3725, -2597, 2897, -2513, 1987, -416, -2444, 6916, 349, -1110, -4154, -4623, 53, 3865, -993, -8210, -651, 1280, -4261, -4337, -7605, 2074, -413, -2321, 837, -2882, -3536, 8512, -3100, -751, -1466, -1352, -3046, 833, -538, -378, -5832, -2967, 3981, -608, -274, 39, 1911, -811, 6059, 1289, 6744, -3978, -2821, 2813, 3185, 1641, 4621, -5059, 5139, -4251, 7102, 2009, 4088, 13455, 3158, 2023, 845, -2790, -6827, -7613, 2793, 362, -2562, 7864, -4174, 2552, 30, -2629, -8870, 6764, 478, -2226, 1224, 1911, 2986, -6839, 750, -4442, 43, -4298, 2500, 1377, 4444, -1386, -903, 5267, 3429, 3397, -128, -314, -1175, 557, -1281, 3879, -6261, -2378, -4673, -4546, -9533, -434, -1251, 4867, -478, 6570, 1638, -6200, 2489, 1825, -3280, 2302, 529, 808, -1079, -932, -7550, 308, 5501, -2490, -1262, -503, 2525, 5519, -1882, -1477, -86, -9414, -1875, 3709, 9345, 696, -580, -4114, 3784, -1469, -2308, -7687, 7726, -5358, 2180, 198, -4601, 6568, -846, -743, 602, 3768, -8464, -2305, 1505, 3102, -1882, 1882, 2084, -5905, 10953, 1874, 4433, -4212, 9862, 845, -1182, 2011, -3850, -3034, 1874, 4546, 4268, 481, 5882, 2178, -797, 636, 195, -2742, -6500, -172, 6924, -2807, 1402, 1809, 4814, -6196, -4112, -489, 4513, -788, -1141, -1066, 6471, -366, 3895, -7083, -2192, -936, -4171, -3834, -2427, 60, -2176, 1471, -7225, 1075, -4612, 2404, 923, -6865, 3175, -2994, 3791, 3837, 4112, -2837, -2407, -1790, -135, -2982, 756, 2905, -3754, 3142, 4695, -4753, 3775, -3668, 2878, 58, 1401, -6116, -3778, -835, -1237, 4451, -486, -5649, -2662, -1359, 2480, 764, 6716, 1520, -3423, 3565, 6528, -5598, -2577, -5838, 3809, 4273, -5191, -6151, 856, -3401, 1877, 181, -3391, 6397, 521, 2696, -729, 2447, -2357, 71, 393, -4286, -3678, -3804, 202, 2483, -1495, -567, -351, -5601, 4345, 727, 2205, -446, -1712, 4245, -555, 2319, -1229, -4391, 1198, 3343, 6352, -3041, 3530, 2555, -2491, 3267, 5197, 7241, -5418, -196, -6974, 4126, -6772, -1952, -1254, 4365, -856, -7301, 2039, -3488, -1819, -5129, -8144, 1046, 9050, -2252, 3089, 1116, -3244, 3722, -6500, -2682, 6899, 999, -6970, 4962, 1942, -155, 205, 1988, 2059, -7244, 8643, -2080, -11003, -3558, 6445, 4859, 5428, 2292, 67, -996, 6220, 3174, -276, -9762, -1324, 1566, 3728, -677, 3279, -2624, 2045, 2832, -6470, 1538, -1687, -3169, -2649, -7823, -1285, 4916, 1915, 8069, -955, 3076, 5247, 6909, -1496, 6131, -4841, 8632, 495, -755, -1478, -1746, -5553, 6564, -2779, -3504, 639, -5842, 1703, 1079, 2635, 2315, 1960, -9291, 531, -1071, -1838, -2918, -399, 2394, -8068, -720, 31, -1530, -1179, 65, -4719, 5641, -1551, 5440, -2457, 6268, -5913, 3913, -6646, 188, -6885, 2757, -3601, 3880, -3979, -1443, 1375, -2572, -1632, 2321, 5070, -2172, 731, 481, 1710, -5181, 8850, -931, -3332, 3141, -1414, -2568, -3533, 728, -1683, 206, 907, 5058, 2523, -158, -1465, 1969, -5960, -1139, -7207, 991, 2704, -8160, -2148, -4477, 4621, -5992, 2561, -2189, 5366, 2138, 2017, -2125, -844, -6806, 3850, 3987, 2856, 2990, -6767, -2315, -721, -205, -672, -2231, -617, 4268, 4988, -1234, -2918, 5121, 4651, -2067, 629, 655, 2305, 490, 990, 598, 4562, 3404, 3903, -5174, 7998, -8369, -7167, -1066, 5288, -2154, 5324, -1541, -620, -3439, -4516, 6180, -8012, -1858, 1175, -2675, -2835, -3610, -7460, 10522, 3595, -4464, 1727, 2719, -2989, -2425, 2312, 1535, -2001, -4046, 3982, -3749, -1536, 2144, -68, 284, 1545, -2459, -6920, -2683, 3627, -1356, -188, 2040, 3459, 33, 6605, -1418, 5162, 2430, -1030, 3098, }; +int32_t cls_token[16] = {1579, -8312, -1543, 5366, -5637, -2872, -787, 5773, -2441, 5560, -195, -1606, -1795, -6080, 1247, 219, }; +int32_t to_patch_embedding_layer_norm1_weight[400] = {4133, 4145, 3757, 3886, 3959, 4157, 3936, 3941, 4085, 3902, 4116, 4193, 4064, 4147, 4075, 4082, 4012, 4029, 4116, 3960, 4010, 3944, 4027, 4086, 3719, 3979, 4088, 4002, 4053, 3642, 3885, 3881, 4070, 3980, 3861, 4118, 3899, 4082, 4035, 3967, 3992, 3993, 3975, 3960, 4044, 4026, 3964, 4104, 4141, 4203, 4335, 3950, 4260, 4394, 4250, 4142, 4046, 4265, 4355, 4162, 4026, 3882, 4271, 4276, 4216, 3970, 3983, 3922, 4114, 3907, 4105, 3924, 3986, 4032, 4059, 4209, 3959, 4090, 4356, 3975, 4122, 3986, 4208, 4332, 3799, 4094, 4119, 4180, 3884, 4095, 4133, 4137, 3932, 4225, 4114, 4111, 4032, 3875, 4169, 4247, 4040, 4016, 3875, 4170, 3953, 4202, 3919, 4007, 4077, 4003, 4305, 3842, 4027, 4056, 4142, 4325, 4154, 4097, 3973, 4237, 4355, 4214, 3867, 4227, 3953, 4371, 4289, 3955, 4040, 4009, 4349, 4107, 4081, 3992, 4066, 4087, 4143, 3998, 4267, 4175, 4172, 4379, 4104, 3944, 4301, 4158, 4079, 4004, 4215, 3903, 3995, 4349, 4114, 4170, 4144, 3863, 4146, 4371, 4222, 4055, 3768, 4143, 4415, 4017, 3835, 3989, 4230, 4134, 3999, 4111, 4047, 4056, 4048, 3949, 4234, 3900, 4057, 3988, 4199, 4106, 4042, 3996, 4172, 3837, 4434, 3947, 4334, 4126, 3984, 4289, 4126, 4312, 4083, 4108, 4197, 4109, 4378, 4341, 4190, 4026, 4163, 4292, 4392, 4021, 4034, 4101, 4160, 4278, 4369, 3999, 3936, 4324, 4048, 4162, 4044, 3925, 4438, 3960, 4227, 3866, 4002, 4304, 4042, 4232, 4019, 4004, 4256, 4206, 4115, 4146, 4098, 4208, 4202, 4077, 4139, 3819, 4197, 4112, 4082, 4096, 4123, 4186, 4242, 3938, 3958, 3854, 4033, 3863, 4125, 3973, 4049, 4200, 4256, 4168, 3976, 4109, 3891, 4326, 3963, 4095, 3989, 4003, 3975, 4060, 3839, 4141, 4158, 3988, 4027, 3942, 4172, 3919, 3789, 4114, 3849, 4044, 4072, 4189, 4027, 3988, 4126, 4168, 4252, 3919, 4101, 4337, 4444, 4213, 4265, 4097, 4241, 4310, 4159, 3999, 3960, 4176, 4212, 4061, 4151, 4209, 3865, 4062, 4143, 4250, 4240, 3844, 3949, 4000, 4163, 3924, 4031, 4240, 3901, 4130, 4081, 3980, 4027, 4228, 4179, 4012, 4004, 4040, 4259, 3998, 4100, 4036, 4036, 4179, 3997, 4013, 3999, 4269, 3892, 4237, 3970, 4001, 4144, 3987, 4286, 4028, 3876, 4163, 4167, 4266, 4089, 3886, 3843, 4096, 4022, 4139, 3774, 3958, 4185, 3968, 3734, 3858, 3944, 3847, 3897, 4437, 3900, 4063, 4092, 4064, 4184, 4036, 3915, 4042, 4022, 4221, 4130, 3789, 4108, 4215, 4273, 3804, 3838, 3820, 4098, 4179, 3893, 4165, 3959, 4077, 4066, 3950, 4334, 4204, 3915, 3767, 4120, 4262, 4153, 3926, 4022, 3947, 4106, 4003, 3883, 3666, }; +int32_t to_patch_embedding_layer_norm1_bias[400] = {-181, -150, -345, -240, -156, -149, -228, -310, -125, -193, -139, -95, -144, -184, -125, -137, -225, -204, -98, -170, -13, -175, -169, -127, -341, -168, -8, -182, -261, -380, -104, -230, -161, -206, -269, -152, -96, -4, -246, -37, -138, -182, -33, -64, 9, -50, -201, 66, 108, 50, 51, -30, 117, 88, 32, 40, 5, 73, 92, 7, -126, -116, 87, 86, 78, -51, -135, 5, 48, -15, -3, -54, -132, 77, -78, 44, -12, -133, -116, -105, 60, -27, -108, -166, -119, -68, -6, -132, -102, -68, 29, 94, -23, 58, -51, -35, -61, -28, 4, -114, -232, 9, -89, 23, -29, 46, -44, -122, 78, -82, 53, -36, 47, 62, -86, 50, 35, 90, 5, -70, 69, 105, 3, 113, -38, 42, -69, 2, 131, -44, 53, -59, -18, -111, -97, -18, -91, 9, -97, -53, -121, -103, -6, 42, -30, -55, -39, -11, 121, 8, -32, -27, 20, -58, 54, -76, -13, -34, -80, 83, -37, -57, -59, -4, 42, 97, -90, -39, 19, -59, 44, -68, 115, 80, -65, 13, 54, -46, 109, -21, -47, 11, -23, 136, 56, -34, -30, -40, -29, 47, -71, -89, -16, 112, -95, -71, -114, -57, 79, -70, -81, -76, -106, -18, -53, -66, -53, -52, -116, -127, -50, -104, -70, -36, 41, -56, -110, 104, -62, 132, -40, -73, -54, -24, -21, 37, -40, -59, -3, -65, -28, -87, -69, -37, 83, 40, -38, -35, -61, 59, -59, -72, -92, 118, -4, 36, 29, 133, -64, 135, 9, -33, 69, -76, 74, -28, 52, 68, 108, 95, -77, 156, 191, 69, 130, -58, 88, 141, -12, 89, -39, 256, 158, -6, 61, -118, 75, -15, -21, 99, -115, 205, -21, 50, 121, -88, 110, -40, -19, -30, -57, 110, 140, 152, -37, -56, 123, 128, 151, 87, 53, 95, -35, 89, 98, 91, 154, 25, 83, 6, 145, 102, 99, 186, -14, 51, 39, 103, 124, 140, 114, 130, 81, 120, 157, 129, 160, 152, 169, 144, 111, 104, 51, 11, 43, 156, 74, 234, 13, 193, 130, -45, 159, -14, 102, 205, 125, 137, 43, 169, 306, 142, 87, 182, 136, 216, 166, 198, 142, 88, 233, 165, 195, 49, 192, 104, 37, 200, 17, 189, 36, 134, 192, 224, 76, 272, 170, 180, 146, 85, 130, 69, 189, 142, 163, 142, 111, 130, 251, 186, -30, 128, 149, 264, 144, 72, 200, 147, 131, 210, }; +int32_t to_patch_embedding_linear_weight[6400] = {-173, 179, -273, -237, 19, 323, 124, -8, -4, -42, 39, -70, -3, -226, 215, -34, -120, 218, -189, -275, 21, -86, 42, 92, 209, -149, 196, 180, 164, -87, 49, 54, -54, 66, -83, 102, 32, 118, 140, -60, -96, -33, -165, -97, -141, -163, 34, 208, -214, 108, 22, -126, 151, -120, -195, 88, 21, 35, 157, -22, -12, -191, 82, 89, 183, 252, 17, -22, 206, -29, 22, 57, 40, -82, -285, 98, 46, 52, -16, 165, -125, 181, -157, -105, -129, 329, -88, 193, 218, -133, -27, 85, 294, -133, -127, -40, 114, 68, 18, -162, -98, 166, -117, -18, 74, 59, 92, -40, 56, -200, 122, -163, 199, -62, -49, 106, -136, 184, 136, -64, 52, -164, -255, 115, -58, 162, 245, -40, 34, -19, -127, -342, -173, 220, -44, 171, 124, -198, -144, -127, 27, 219, 7, -176, 314, -18, -43, 69, 75, 138, -23, 118, 163, -35, 69, 100, 208, 65, 126, 149, 100, 210, -48, -106, 9, 41, 43, -3, 43, -297, -324, -96, -51, 47, 126, 5, 116, 360, -299, -36, -50, 148, -155, 242, 64, -130, 69, -48, 210, -165, 54, 142, -59, 101, -64, -264, 80, -13, -111, 223, -145, -159, 47, -87, 141, 196, 57, -183, -11, 300, -304, -50, -157, 122, 34, -19, -83, -170, 70, -41, 12, -44, -60, -122, -85, 69, 38, -107, -205, -58, -122, 100, 155, -300, -175, -11, 326, 120, 131, -174, 152, 104, -46, -72, 122, -19, -161, 138, 61, -76, -343, -88, 176, -103, 148, -188, -129, 282, 65, -34, -61, 91, 111, 38, 114, -19, 95, 50, 206, -33, -113, 81, 323, -45, -34, -164, -122, 253, 186, 102, -5, -244, 88, 181, -58, 195, -30, -18, 155, 107, -108, -267, 72, -23, 125, 65, -204, -254, -238, 96, 159, 228, 71, 13, 223, 3, -192, -176, -65, -151, -115, 213, 122, 8, -130, 66, 144, 208, 63, -140, 193, -90, 104, -189, -59, -146, -39, -185, 172, 138, -264, -217, -88, 39, 39, 42, -61, 194, 123, -57, 156, 0, -172, -132, -221, -197, -165, 80, 110, -95, 50, 52, 244, 41, -58, -107, 145, 203, 212, 204, 112, -91, 45, -22, -26, -51, 34, -152, -205, 239, -88, -122, 203, -85, -69, -43, -190, -202, -248, 7, 189, 103, 137, 133, -63, 42, -115, 68, 129, 184, -192, 176, -118, 86, -1, 90, 210, 37, -40, 135, -45, -164, -175, 70, 283, 232, -219, -81, 66, -85, -171, 40, -67, 310, 164, -66, 32, -64, -64, -52, 172, -128, -229, -156, -273, 208, -107, -196, -176, 355, 43, -19, 48, 155, 74, -145, -28, -83, -128, 15, -101, -37, -54, 103, 278, 194, 154, -161, -342, 8, -187, -34, -149, 175, -73, -153, -1, -303, -197, -180, -29, -75, 9, -157, -75, 157, -66, -130, 112, -68, -26, 10, 117, 138, -104, -189, -81, 38, 138, 149, -52, -30, 110, -93, 153, -62, -116, 189, -67, -67, -94, -94, 17, 45, 122, -158, 177, 166, 101, 105, 52, 140, -115, -7, -184, -85, -249, 98, 19, 233, -100, 198, -165, 6, -73, -183, -133, 196, -146, 231, 42, -266, 70, -104, 50, -80, 281, -171, -331, -9, 168, -98, 177, 201, -234, -103, 79, -96, 112, -38, 170, 36, -86, 201, -132, 137, -9, 34, 105, 75, -234, -69, -34, -193, 78, -236, 205, -169, 96, -48, -191, 55, -261, -52, -100, -15, -261, 24, -68, -304, -137, -296, 240, -164, 185, -182, -111, -93, 149, -194, 264, -46, -231, -16, 168, 36, -202, -47, -68, -22, 69, -129, -157, -118, 251, 40, 0, 89, -44, 117, -149, -10, -241, 89, -199, -124, -32, 146, -178, 157, 64, -285, 11, 38, -75, -46, -83, -75, 159, 32, -141, 42, 196, -159, 43, -164, -143, -6, 23, -149, -263, -75, -223, -44, 15, -220, 94, 86, -157, 104, -62, 74, -249, -46, -210, 4, -253, 126, 104, 32, 60, 64, 266, -67, -87, 149, -87, 222, 24, 66, -40, 215, -20, 143, -77, 1, -33, 165, -16, -109, 49, -142, -4, -9, 154, 163, 9, -198, -177, 40, -27, 102, 171, -158, 128, 122, 203, -8, -163, -18, -20, -102, 190, 137, 37, -143, -97, 71, 0, 49, -174, -31, -124, -165, 106, 93, 123, -117, 44, -250, -306, 72, -93, 193, -33, -62, -94, 208, 88, 271, -74, -127, 237, -187, -189, -22, 68, 219, -145, 54, 153, 185, -118, -157, 52, -40, -169, 107, -163, 117, 10, 109, -303, -33, 179, 35, 63, 2, 41, -167, -6, 46, -175, -94, 144, 195, 60, -2, -157, 185, -250, -49, -170, -204, -103, -32, -46, 163, -96, -232, -64, 206, 273, -166, -227, -127, -12, -14, -248, -98, -145, 440, -51, 48, 212, -426, 140, 275, 314, -190, -270, -342, -139, 95, -110, 298, -114, -93, 16, 253, 150, -110, 390, 282, 180, -162, 121, 90, -170, 72, -83, 150, -353, -119, -5, 341, -89, 100, 61, 58, 1, 58, -203, -85, -28, 174, -126, -44, -31, -18, 12, 170, -88, -354, 326, 19, -1, -223, -124, -175, -270, 43, -54, 73, -345, 90, 19, 171, -40, -251, 332, 245, 259, -14, -85, -418, -299, 125, -324, 123, -124, 475, 153, 349, 205, -154, 290, 37, 45, -230, -81, -178, -215, 335, 40, 230, -357, 310, -126, 269, 58, -334, 131, 101, 254, -141, -235, 7, -240, 30, 35, -22, -147, 183, -16, 22, -100, -138, 154, -4, -158, 46, 154, -301, -147, -85, 155, -97, -275, 68, 84, 160, 151, -319, 105, 230, -179, -41, -105, -23, -445, 463, -29, -24, -255, 53, -256, 349, -126, -481, 341, 224, 239, -322, -302, -98, -143, 170, -279, 78, -369, 124, 106, 379, -65, -202, 393, 148, -31, 25, -257, -260, -217, 80, 35, 119, 1, 191, -242, 87, 342, 19, -120, -80, 241, -29, -76, -314, 1, -125, -219, 76, -167, 65, 3, 281, 24, -17, 22, -131, 295, -81, 80, -116, -56, -51, 148, -231, 80, 232, 28, 74, -219, -231, 383, 165, 165, -122, -124, 66, -237, 357, 1, 318, -54, 391, -175, 353, -331, -405, 247, 40, -27, -38, 86, -286, -118, 306, -253, 235, -210, 153, -77, 158, -217, -229, 177, 345, 145, 66, 29, -100, 30, 78, -155, 115, -13, 193, -136, 250, -6, -98, -10, -90, 112, 25, -141, -107, 71, -27, -156, 101, -137, 5, 65, 45, 23, -100, -15, -24, 151, 161, 80, -155, 250, -107, 40, -82, 127, 201, -110, 26, -257, 22, 154, -109, -13, -108, 95, -81, 14, -46, -278, 45, -130, 132, 94, 205, -57, -65, -42, 120, 273, 174, -8, -103, -170, 201, -323, 24, -205, 274, 49, 151, 39, -38, 43, 139, -92, -239, -203, 160, -41, -99, -9, -33, 89, 311, 125, 136, 31, -311, 64, 44, 168, -124, -45, 97, 155, 131, 33, 90, 211, 229, 155, 51, -27, 61, -229, -16, -166, 13, 256, -85, -69, -208, -125, 31, -174, 134, 266, 51, -182, 87, 98, -266, -75, 140, -39, -21, -70, 52, -230, -159, -113, -47, -17, -114, -101, -52, 216, -70, 88, -134, -306, -153, -56, 27, -294, 195, -114, -30, 17, 167, -14, 154, -62, -187, -246, 256, -154, 116, 76, 62, -133, -302, 237, 212, -25, 55, -65, -402, -140, 271, -144, -256, -117, -135, -160, 174, -27, -30, 193, 6, -118, 217, -177, -111, -148, 80, -6, 259, 249, -190, 226, -5, -133, -272, 180, 218, -133, -196, 200, 226, -8, -30, -163, 76, 271, 195, 28, -218, 44, 77, 153, 74, 48, -100, -69, 501, -408, -465, 15, 212, -400, 14, 196, -245, -36, 65, 7, 236, 267, -91, 228, 215, -49, -24, -133, 233, -121, -180, 13, -63, -266, -171, 79, -208, 52, 177, -430, -222, 51, 204, -65, -151, -83, -96, -124, -120, -276, 54, 20, -160, 204, 288, -350, -181, 14, 63, 4, 167, 200, -82, -104, 226, 167, 58, -47, 82, 47, -166, -114, 227, -217, -307, -342, 222, 88, 57, -26, -61, -30, -53, -52, -155, -46, -169, -263, 489, -78, -174, -117, 383, -120, 50, 350, -197, 5, -40, 220, 18, 138, -250, 479, 66, 91, 121, 70, -38, -25, -30, -128, -78, 73, -39, 63, -19, 154, -88, -254, -90, 150, 1, 76, 259, -271, -83, -86, -10, -77, 83, 26, -49, 158, 224, 26, -21, 24, 17, 192, 107, 280, -337, 91, 375, -147, -155, -224, -165, -25, -18, -204, 212, -191, -97, -198, 85, 42, 76, 17, -292, -19, -2, 200, -220, -81, -147, -412, -87, -45, -146, -28, 143, -206, -67, -32, -85, 79, -225, -57, 76, -78, -115, 60, 154, -159, 163, 197, 167, 25, -344, 67, -24, -36, 85, -298, 166, -209, 124, 37, -245, 222, 171, 153, 54, -143, -48, -53, -84, -41, 16, -193, 74, 24, 219, -78, -13, 146, -6, 208, -32, 214, -190, 217, 162, -32, -131, -246, -68, -163, 222, -219, 165, 113, 174, -198, -126, -21, -27, 59, 124, -165, -183, 62, -260, 93, -123, -66, -362, 349, 167, -79, -255, -165, 16, -249, 33, 64, 43, -281, 10, -295, -2, 114, 271, -300, 76, 156, 292, -146, 162, 49, -186, -123, -62, 163, 73, 95, 59, 235, -148, 48, -140, 236, 97, -293, -12, 213, -230, -266, 156, 192, 276, 206, 31, -149, 29, -84, -82, -16, 49, 87, 135, 290, -181, -121, 63, 111, -260, -131, 101, 26, 74, 57, 72, -166, -134, 33, 39, -144, 0, 29, -231, -93, 87, 282, -4, -401, 100, 293, 217, 146, -40, -168, -61, -19, 226, 46, -57, 102, 333, -213, 181, -159, 239, -167, -189, 68, 373, -270, 205, 287, -244, 29, -164, 117, -246, 236, -212, 191, 133, -31, -190, -13, 239, -67, 220, 9, -57, -230, 85, 21, 102, 158, 50, 21, 90, 140, 147, 179, 182, -65, -162, 18, 153, -103, 49, 35, -204, -94, 168, -32, -55, -69, 91, 159, -65, 94, -53, 120, -176, 102, -170, -28, 133, 1, 56, -181, -32, 260, -114, 138, -22, -412, 55, -106, -82, -166, -37, -256, 34, -222, 168, -79, -8, -54, -122, 176, 189, -242, -8, 38, 64, -132, 33, 120, -83, -122, 99, -103, -323, 256, 184, 90, -276, 51, -46, -42, 340, -145, -1, -42, -80, 58, 125, -53, 105, 32, 89, 142, -101, 132, 125, 208, 193, 137, 56, -238, -12, -205, 13, -169, -97, -30, 51, -269, 97, -141, -90, 231, -266, 191, -113, 86, -21, -72, -97, 99, -110, 180, -232, 98, 177, -208, -84, -86, -46, -61, 148, -49, 320, -32, 227, -334, 98, 88, 35, 38, 46, -360, -176, 73, -91, -121, -146, 9, 22, 75, 256, -42, -285, 346, 241, 81, -69, -89, -5, -386, 219, 218, -77, -171, 98, -226, 204, 97, -33, -112, 152, 152, 34, 66, 119, -155, -199, 43, 130, -137, -44, -96, 82, -288, -136, 180, 67, 58, 240, -51, -101, 89, 76, -165, -18, 136, 163, 147, 207, -95, -269, 174, 176, -33, 7, -154, 34, 31, 75, -125, -131, 170, 93, -5, 4, -255, -115, 28, -94, -301, 115, -40, 222, 64, -253, 17, -361, 297, -179, 34, -122, -332, -498, 281, 146, 81, -278, -275, -391, -361, 191, 223, -101, -58, 252, -214, 112, 303, -63, 104, 77, 83, -6, 261, 69, -349, 239, 101, 17, -165, -216, -167, -42, 214, -158, 43, -76, 196, -192, -289, -128, -184, 198, -114, 185, -211, 175, 193, -2, 42, 261, -80, -165, 59, -100, -91, -102, -10, 96, -207, -315, -50, 122, 73, 68, 25, 283, 43, 53, -269, 315, -203, 78, 271, -252, 254, -237, 276, -168, -30, -139, 91, -524, 353, 229, 57, -60, -142, -120, -139, 219, -241, 245, -152, 68, 18, 123, -110, -320, 281, 100, 94, -293, 137, 79, -199, 243, -207, 369, -253, 46, -218, -91, -102, -115, -243, -60, 208, 198, -75, 57, 190, 198, -45, -201, -9, -41, 151, 98, -128, -259, 201, -44, 148, -109, 113, -111, 66, 174, -262, 215, -231, 232, -61, 174, -299, 182, -137, -75, 8, 164, 17, 133, -65, -230, -86, -109, 27, -206, 6, 41, 46, -317, 478, 341, 236, -222, 232, -178, -364, 430, -294, 250, -320, -201, -10, 23, 124, 308, 72, -229, -361, 21, 459, 86, -109, -87, 81, 121, -40, -47, -2, -456, 50, 43, -181, 18, 150, -103, -124, 83, -96, 62, 188, -96, 53, -207, -160, -115, -81, -9, 272, -59, -43, 28, -176, 19, 103, 20, -150, -92, -52, 106, -100, 250, 2, -92, -80, -190, -220, -14, 237, -166, -25, -163, 175, -183, 239, -42, -23, 4, 439, -583, 218, 202, 110, -80, 443, -129, -302, 113, 154, -186, -221, -109, 8, -34, 41, 227, -91, -144, -77, 59, 159, 269, -36, 78, 290, -352, 152, -351, -88, -82, 261, -65, -69, 73, -90, 173, 403, 191, 157, -55, -106, -167, -20, -267, 102, -97, -53, 276, -127, -53, -155, 159, -99, -71, 90, -168, 150, -247, -75, 80, -235, -60, -57, 24, 17, -178, 96, 71, 187, 101, -97, 66, 192, -313, 211, -257, -349, -104, 251, 110, 38, 214, 378, -169, 154, 88, 233, 114, 34, -13, 48, -105, -173, -229, 30, 70, -119, -12, -167, 240, 139, -86, 214, -45, 185, -14, 325, -8, 240, -272, 183, 148, -4, 8, -260, -30, 75, -113, 3, -142, 35, -289, 2, -163, -137, 0, -361, 155, 6, -194, -268, 359, 145, -108, 299, -257, 134, -44, 273, -23, -218, -84, 36, 385, -189, -269, -151, -45, 27, 114, 125, 148, 136, -150, 91, -251, -310, 188, -184, 115, -332, -88, -139, 89, 200, 274, 301, 15, 14, -16, 122, 6, -111, -399, -73, 356, -280, -103, -216, 119, -56, 158, 364, -175, 40, -239, 365, -225, 284, -136, 81, 12, 67, 9, 22, 157, -28, 240, 102, 167, -27, -290, 261, -138, 166, -265, -110, 114, 7, 252, -175, -84, 137, -44, -19, 41, -277, 21, 82, 209, 21, -140, -231, 378, -54, -203, -112, 365, 29, 221, 160, -320, 52, 3, 364, 115, -10, -74, -104, 274, -264, -235, -243, 104, -48, 357, 191, -34, -95, 98, -56, -223, -225, -131, -64, 69, -95, -44, -1, -155, -94, 0, 318, -249, -150, -84, -4, 4, -182, 109, -28, 162, 27, 105, -15, -50, -9, 50, 83, -335, 142, -197, 150, 11, -19, -5, 65, -415, 220, 342, 294, -116, 23, -71, -63, 87, -228, -17, 80, -44, -340, 242, 32, 191, 211, 127, -160, -160, 37, -133, 135, 88, 79, -59, -25, -39, -188, -78, -119, 0, 16, -201, -128, -22, 51, 205, 203, -251, 55, -68, 139, -213, 57, -194, 89, 143, -474, -147, -11, 215, -80, 10, 483, -289, -150, -102, 402, -64, 199, 92, 89, 74, -32, -19, -82, -39, 30, 315, 160, -190, 46, -287, -29, -401, -124, -363, 145, 379, -251, -80, -198, 123, 64, 200, 139, -314, 131, -168, 274, -175, -17, -56, 74, -237, 399, -4, 77, -194, -69, -225, -175, 220, 88, -68, -72, 189, -183, 57, -90, 104, 45, 77, 23, -30, 34, 245, 32, -195, -78, 9, -6, 126, -20, -48, 129, -4, -185, -77, -126, 106, 235, 104, 426, 31, 20, -284, -41, 172, -66, -98, 84, 373, -314, -14, -207, 90, -31, 359, 299, -430, -48, -280, 430, -229, 122, -257, 16, 360, -122, -226, -7, 332, 2, -61, 393, -208, 48, -257, -4, 70, -135, -152, 30, -188, -33, 162, 90, 24, 89, -147, 123, 221, -219, 105, -231, 67, -141, 68, -151, -95, 78, 152, -117, 5, 78, -312, 72, -86, 77, 102, 46, -7, 93, 209, -19, 123, -276, 218, 63, 184, -116, 13, 302, -95, -30, -169, 141, 71, -137, -58, 291, 356, -220, -165, -56, 144, 298, 156, 262, -250, -88, 33, 444, -421, 74, -504, 153, 59, -3, -20, -179, 58, -266, -160, 256, -217, -209, 60, -26, 64, 190, 11, -116, -36, 5, 18, 100, -111, -164, -197, 136, -5, 32, 19, -13, 28, -95, 201, -166, -177, -132, 273, 45, 60, 41, -72, -60, 64, -261, 165, 44, 86, 152, 205, 64, 371, -359, 1, 235, 109, 66, 54, 102, -121, 97, 71, 202, 22, -268, -198, 94, 123, -164, -106, -264, 18, 307, -108, -5, -209, 149, 279, -20, -235, 312, -34, -47, -77, 0, -136, -78, -73, 262, 133, 90, -191, 18, 17, 210, 84, 227, 0, -135, 138, -106, -124, -26, -125, 0, 123, 135, 60, 185, -230, 295, -524, -214, -158, -99, -137, 201, 84, -204, -170, 151, -142, -41, 94, -43, 135, -121, 274, -3, -114, 36, -194, -89, 140, 161, 3, 147, 38, 239, -238, -30, 91, 114, -197, 126, -186, -83, -100, 128, 198, 10, -154, 57, 48, -232, 155, -210, 348, 37, -83, -130, -85, 3, 15, -13, -307, -138, -28, 48, -28, 58, -26, 26, 177, -27, 61, -100, 91, -81, 434, -211, -47, -101, 42, -92, -68, -6, -324, 270, -162, 296, -227, -208, -115, 26, -97, 159, -142, -114, 60, 108, 189, 158, 109, -63, -39, -165, -80, -222, -97, -22, -105, 108, 83, 76, -43, 116, -48, 177, 195, 237, -73, -95, -361, 154, -186, 185, 38, -54, -88, 10, -34, 191, 225, 53, 14, -63, 183, 41, -166, -26, -154, 45, -300, 267, 65, 196, -13, -244, -54, 60, 221, 162, 1, -144, 358, 5, 242, -241, -56, 207, -172, 68, 226, -44, 24, -149, -174, 293, -346, 218, -298, -73, 68, 197, -24, -127, -47, -77, 65, 35, -150, 139, -218, -55, -267, -30, -107, 182, 166, 103, 121, -172, 160, -121, 90, 19, -86, 153, 210, -88, -188, 51, -277, -198, -20, 107, 23, -304, -154, -166, -35, -32, 35, 266, -42, -243, -176, 223, -282, -49, -382, 12, -90, 60, 228, 25, -65, 61, 113, -115, 55, -10, 54, -67, -20, -88, 110, 46, -367, 416, 400, -84, -2, 160, -258, -325, 301, -10, -93, -286, 42, -435, 8, -1, -31, 6, 241, 89, -97, 122, 81, 21, -3, -101, -77, -297, -110, 68, -92, -46, 317, -59, -308, -152, 72, 253, 332, 231, -370, 15, 13, 413, -143, -71, -169, -17, 15, -217, 82, -70, -75, 277, -13, -59, 68, 165, -80, 260, -12, 172, -332, -350, 72, -90, -24, -114, 169, 108, 121, 190, 57, -26, -83, 4, 24, -317, -132, -5, -94, 456, 278, 57, -108, 35, -43, -176, 158, 372, -98, -339, -270, -190, -220, 220, 290, -266, -206, -64, -41, -141, -117, -18, -327, 96, -117, 106, -8, 17, 100, -139, 105, -455, -354, -210, 78, 110, 56, 276, -312, 151, -78, 387, -14, -96, -422, -140, 133, -50, 140, -109, -171, -22, 50, 131, 101, -48, 310, -29, 42, 45, -193, -239, -20, 274, -98, 229, 16, 142, -100, 43, 119, 165, 73, -83, 11, -413, 54, 63, 211, -158, 59, -197, 63, 243, 88, -8, -228, 401, -273, 69, -212, -14, -167, 128, 104, -152, -365, -98, 67, -117, 348, 124, -12, -7, -115, 193, -123, 6, -279, -49, 371, -328, -340, -126, -28, 241, 98, 101, -317, 155, -108, 176, -166, 36, -494, 69, 296, -345, -282, 43, 121, 113, 189, 402, -338, -142, -49, 193, -279, 156, -75, -254, -118, 218, 151, 28, -95, 72, -197, -206, 52, 172, 363, -26, -153, 25, -257, 82, 293, -72, 128, -227, -135, 87, 50, -101, -80, 328, -90, 131, 54, 92, -325, 197, 148, -329, -25, 24, -202, 37, 94, 128, -156, -284, 189, 109, -138, -28, -158, 195, 389, -373, -160, -15, 81, 223, 308, 210, -183, 184, 31, 121, -50, -15, -287, 40, 178, -461, -201, -28, 359, 280, 143, 228, -155, -85, 10, 138, -297, 140, -414, 76, 121, 100, 132, -226, 53, 187, 41, -145, -142, 149, 124, 178, -328, -72, -207, 254, 117, -233, -1, -44, -131, 0, 91, 139, -113, 82, -35, 239, -93, 22, -172, 317, 107, 120, 29, -158, -129, -363, 110, 238, 111, 86, -159, 13, -36, 112, 67, 137, 271, -191, -127, -218, -76, 131, -7, 28, -30, -10, 143, -40, -217, -167, -362, -212, -35, -280, -203, 9, 221, 117, -52, 348, -83, -29, -257, 110, -330, 154, -171, -99, 372, -146, -231, -457, 200, 320, 151, 235, -105, 369, 82, 301, -280, 91, -390, -142, 178, 65, -95, 5, 228, 101, 162, 45, 51, 64, -12, 202, 1, -138, -181, 271, -188, -175, 102, 25, 92, -81, 132, -26, -217, 108, -95, 96, -115, -100, -88, -336, 221, -319, -213, -399, 80, 195, 165, 154, 110, 179, 17, 312, -418, -147, -353, 73, 104, -59, -130, -276, 197, 170, -42, 151, 65, 319, 122, 107, -27, 244, -101, -101, 165, -72, -248, -237, -230, 185, 263, 225, -225, 107, 175, 122, 234, -21, -6, -112, -116, 186, 66, -152, -70, -73, 59, -40, 77, -26, -228, -141, 197, -200, 22, 41, -17, -158, 162, -35, 75, 268, 198, 96, 15, 10, 19, 77, -156, 0, -277, -40, 486, -302, -359, -201, 349, 285, 301, 149, -104, 132, -256, 260, -178, -151, -475, -6, 14, -81, 39, -108, -159, 175, -164, 180, 242, -90, -30, 51, -215, 146, 225, 136, 305, -45, -111, -49, 18, 297, 122, 156, -326, -197, -3, 9, 112, 153, -334, 221, -196, -97, 19, -54, -199, -92, 28, -179, -105, -139, 230, -6, 115, -143, -102, -91, 214, -42, 27, -321, -40, 145, 39, -141, 114, -57, -287, 173, 67, -16, -158, -106, 130, -286, -393, -191, 211, 196, 80, 368, -338, -79, -141, 334, 200, 79, -316, -64, 140, -64, 39, -114, 115, 17, -46, 186, -127, 37, 16, -3, -230, 5, 38, 384, 210, -360, -255, 155, 28, 149, 289, 69, -72, -25, -139, 53, -119, 69, -83, 180, 164, -118, -107, -100, -55, 27, 150, 260, 75, 29, -262, -100, -193, -31, 12, 25, 5, 179, 100, 23, -3, 35, 160, 25, 192, 102, -65, -182, -234, 50, -113, 131, -24, -270, -163, 4, 88, 155, 223, 160, -171, 95, -280, 391, -28, -301, -172, -64, 275, -202, -35, -20, 356, -15, -35, 167, -57, 112, -197, 280, -325, -75, -119, 196, 110, -320, -116, 93, 130, -43, 67, 171, -38, 84, 61, 99, 22, 56, -33, -264, 362, -250, -96, 32, 139, -72, 209, 81, -76, 176, -76, 43, -213, -136, -201, -173, 126, -21, -62, -246, -105, 381, 339, 94, -111, 243, 153, 13, -227, -181, 159, 253, 200, -48, 0, -202, -34, 181, 196, 92, -296, 161, -256, 269, -277, 171, -192, 23, 301, -61, -135, -137, 291, 358, 303, 67, -183, 118, -82, 50, -280, -6, -223, 40, 206, -160, -160, -159, 85, 233, -9, 155, -173, 96, 165, 57, -149, 117, -173, 107, -33, 202, 202, 223, 95, 338, 73, -246, 264, 113, -75, -230, -321, -208, 168, 94, 74, -58, 105, -49, 220, 209, -154, 124, 15, 184, 50, -29, 0, -85, -54, -192, -93, -369, -252, -199, 30, 15, 9, -55, -229, 88, 334, 188, -104, 101, 53, 39, 215, -312, -153, -124, 8, 216, 67, 72, -13, 113, -342, 285, -68, 150, -222, -1, 209, 0, -58, -194, 187, 81, -62, 269, -203, 161, -5, 150, 77, 127, -46, 268, 90, -54, -4, -31, -275, 253, 69, -284, 149, -111, 81, -262, -212, -277, -111, 57, 242, -188, 55, -217, -20, 432, 154, 21, 69, 207, 94, 166, 78, -71, -181, 45, 64, -198, -40, -179, 71, 71, 28, 56, -262, 158, 358, -158, -103, 87, -199, -118, 284, -308, -174, 178, 155, 165, 13, 157, -88, 150, -139, 121, -132, 50, -151, -59, 4, 151, -14, -199, -174, 185, 94, -71, 24, 29, 117, 56, 354, -244, -10, 229, -70, -94, -13, 351, 202, -13, -128, 57, -77, -121, 6, 21, -139, 142, -159, 111, 73, 24, -14, -54, 78, 95, -85, 4, -64, -97, 97, -202, 87, 123, 190, -37, -172, 18, 51, -176, -335, 147, 66, 130, -1, 227, 143, -11, -2, 101, -187, 146, -114, 87, 39, -118, -8, 209, -37, 90, 231, 82, 73, -115, -153, 63, -179, -111, 83, -130, -356, 146, 181, 22, 119, 142, -15, 169, -225, -42, 233, 59, -204, 183, 59, -15, 36, 162, -141, 55, -29, -260, 33, -13, 144, -190, -27, -21, 120, 287, -74, 152, -86, 78, -42, 76, 138, -22, 8, 153, 300, -6, -67, 126, -88, 98, 312, -59, -312, -30, 25, 233, -18, 79, -263, -144, -15, 154, 203, 75, -291, 202, -62, 48, 117, 19, -274, 174, -188, -268, 298, 277, 209, -63, -146, -319, -5, -188, 126, -221, -115, 158, -140, 43, 85, -32, -154, 3, 213, 105, 308, 256, -119, 171, -236, -139, -171, 117, -19, -34, -168, 2, -23, -100, -250, -166, 41, -158, -119, -101, 82, -64, -256, -25, -53, 151, 224, -231, -47, 26, 66, 188, 58, 129, 122, -23, 91, -25, -150, -230, 208, 141, -34, 28, -50, 8, 117, 139, -77, 205, -213, 199, -122, 142, 344, -213, -477, 44, -117, -107, 351, 311, 112, -84, 274, -355, 80, 112, -149, -61, -85, 1, -15, -141, 38, 292, -82, -4, 155, 88, 132, -10, -35, -31, -260, 206, 62, 186, -90, 25, 79, -196, 204, -62, 173, -12, 208, -158, -21, -172, 49, 3, -109, -85, 230, -51, 28, 245, -202, 70, -349, 122, -185, -26, -309, -254, -66, -133, 221, 29, -225, -109, -199, 101, 93, 145, 26, -64, -161, -135, 181, -16, -49, 286, 177, 106, -210, 40, -241, 8, 169, -32, 25, -150, -5, 46, -62, 271, -250, 130, 143, 204, 43, 81, -49, -102, -63, -26, 247, -58, 200, 0, -27, 46, 30, 202, 169, -111, -164, 57, -53, -227, -117, -74, -93, -78, 77, 50, 201, -191, 68, -183, -165, -48, 124, 98, 306, 16, -177, 89, -181, -102, -204, 290, -186, -46, -93, 176, 314, 167, -110, -32, -194, 89, 145, 314, -154, -78, 292, -96, 93, -127, -128, 133, -108, -139, -44, 238, 53, -127, 126, 329, 116, 112, -173, -233, -124, 133, -1, -199, -60, 204, -55, 170, 168, -62, -45, 149, 129, 229, -75, -126, -154, 233, -119, 41, 44, 183, -121, 195, 149, 30, 61, -137, -69, 6, -264, 129, -98, 207, 172, -14, -390, -341, 199, 155, -71, -174, -121, 149, -37, 189, -1, -42, -122, -18, -104, 89, 103, -142, -89, 173, 146, -169, 136, -102, -165, 30, -106, -49, -108, -216, -81, 109, 6, -142, 203, 285, -38, -31, -183, 133, -3, -155, -158, -21, -24, 143, -108, -291, -209, -15, 87, 261, 215, 86, -236, -149, -38, -169, 1, -142, -216, 184, -155, -94, -141, 49, 77, 136, 66, 84, 159, -90, 176, -48, 0, -5, -87, 5, 104, -71, -335, -131, -157, -118, -98, 228, -164, 207, -202, -3, -5, 72, -256, -40, 22, 99, -172, -9, -471, 278, -10, -7, 19, 138, -242, -47, -152, -217, -51, -124, 422, -351, -51, -336, 146, 16, -11, 21, -222, 19, -233, -8, -186, 57, -116, 224, 16, -151, -174, -6, 155, -101, 320, 73, -71, -186, 145, 213, -120, 186, -234, 31, -97, -10, 225, -79, -265, 166, -133, -207, -18, -20, 122, -18, -246, 138, 90, 38, -4, -256, 27, -292, -134, -31, 45, 209, -245, 132, -374, 254, -310, -108, -247, 48, -23, 143, 116, -200, -177, 352, 144, 1, 262, 166, 50, -192, -14, -309, 47, -68, 289, -185, -5, -199, 240, 175, 231, 73, -280, 101, -464, 322, -410, 190, -127, 28, -21, 9, -92, 8, 117, -134, -10, 72, -263, -322, 74, -177, -134, 80, -199, 59, -81, 112, 49, 34, -46, -68, -201, -39, 337, -11, -98, -237, -155, 69, 89, -333, 338, 88, -36, -408, -90, -64, 91, 263, -41, 193, -123, -31, -338, -70, -49, 33, -535, 211, 351, 102, -468, 46, -232, -58, 603, 355, 330, -287, 270, -402, 232, 174, 223, -348, 66, 52, 5, 361, 139, 85, -128, 197, -240, -9, -195, 0, -370, 352, 178, -91, 6, 290, 156, -213, 184, 445, -149, -508, -32, 142, -21, -9, -368, 46, 240, 89, -16, -96, 169, -51, 242, -148, -153, 149, 49, 97, -294, 101, 18, -200, 216, -23, 155, -278, -197, 75, 155, -115, -147, 199, 143, 138, -185, 154, -178, 64, -236, 351, 223, -163, -474, 286, 61, -160, 161, -24, 413, -508, -102, -111, 255, -81, -263, 122, 266, -42, -109, 147, -176, -156, 309, -23, 41, -10, 118, -188, -95, 160, -249, -205, -155, 148, -239, -47, 169, 143, 114, -217, 144, -132, 6, 101, 105, 104, 90, 51, -93, 30, -100, -111, -83, 223, -182, 112, 26, -18, -151, -174, -44, -168, 214, 59, 35, -195, -253, 186, 13, 13, 8, 452, 348, 23, -141, -89, -192, -102, -455, 283, -57, -122, -35, -16, -157, -178, 15, -39, 224, -405, 78, -185, 215, 258, -256, -224, -13, 28, 123, 41, 25, 81, 139, 139, -1, -148, -34, 141, 211, 276, -139, 20, 78, 126, 46, -196, -120, 39, -114, -157, 46, -228, 355, 35, 148, 162, -305, 13, 362, -86, -141, 23, 23, -188, 286, -84, 209, -302, 171, -331, 135, -128, 81, 99, 146, -104, -97, 35, 108, 91, -62, 118, 133, 108, -69, 107, -57, 144, -371, 115, 132, -3, 19, 211, -46, -164, -57, -56, 9, 73, 97, -138, -29, 61, 169, -32, -116, -29, 106, 96, -12, 111, -295, -52, 102, 106, 110, -3, -126, -163, -326, 365, 11, -57, -93, 141, -364, -193, 297, -18, 1, -147, 23, -113, 142, 58, -274, 343, 86, 115, -225, 6, -86, -73, 158, 129, 8, -191, 179, -54, 316, -83, -168, -165, -108, -90, -24, 2, 212, -131, -37, 183, -117, 140, 89, 241, 143, 98, -50, 34, 215, -61, -267, 317, -118, -151, -110, -68, 201, -60, -254, 94, -87, -113, 126, -12, 113, -126, -55, -44, 79, 175, 92, 205, 193, 215, 22, 92, -128, -326, -261, 297, 293, -21, 78, -36, -259, -81, 53, 205, 1, 41, -102, -152, 44, -119, 85, -68, 0, 56, 144, -16, -35, 154, -25, 207, -124, -20, -170, 40, -56, -114, 139, 221, -108, 123, -230, -131, 125, -33, 142, 55, 314, -130, -70, 192, 31, 254, -414, 223, -26, 169, -202, 98, 168, -21, 216, 96, 191, -22, -98, 98, 117, 182, 105, 197, -9, -38, -157, 97, 193, 85, -125, -227, 55, -21, 109, 6, -56, -223, -219, 291, 246, -140, -205, 43, -24, -255, 85, -136, 141, -36, -17, 14, 294, -236, 179, -27, 46, 48, 115, 170, 106, -17, -186, 259, -150, 18, -157, 64, 121, -190, -60, -182, 80, -66, -73, -67, -171, 196, -168, 119, 297, -150, 168, 323, -29, 127, -139, 114, 19, -65, -288, 233, 7, -25, 161, 126, 27, 101, -57, -101, 11, 257, -331, 220, 163, 101, -9, 157, -14, -317, 189, 48, 43, -189, -128, 145, -172, -141, -59, 278, 296, -82, 135, -62, -137, 104, 300, -95, 145, -32, 32, -271, 134, -59, 9, -23, -151, 186, 0, -11, -156, 103, 174, 81, 87, -188, -14, -304, 155, 135, 50, -32, 254, -160, -256, -228, -248, 128, 147, 117, 105, -16, 100, -105, 119, 57, -171, 158, 0, 30, -189, 110, 40, -201, 171, -39, -65, -9, 184, 245, 35, -114, -273, 398, 211, 29, -41, 37, -116, -156, 137, 31, 121, -376, -98, -137, 123, -87, -168, 41, -41, 7, -76, -25, 45, -136, -184, -139, -3, -18, 127, 179, 152, 116, -164, 76, -46, 150, -120, 123, -192, -195, 67, 97, -211, -8, -72, -251, 188, -24, -163, -98, 136, 153, 95, 54, -181, -162, 303, -117, 277, -89, -84, 129, 147, 25, -116, 262, -29, -118, -235, 177, -107, -59, 51, 296, 122, -5, 81, 81, 119, -15, -168, 267, 344, 30, -162, -61, -303, -192, 225, -135, 173, -13, 220, -257, 239, 53, -12, -110, -89, 82, 27, -382, -33, -183, 10, -72, -272, -146, -26, 55, 188, -172, -230, 12, -136, 65, -32, -61, -276, -140, 243, 102, -5, -94, 88, -92, 31, 102, -77, -81, 267, -31, -29, 40, -300, -150, 3, 136, 74, -181, 66, -192, -61, 110, -323, 293, 262, -129, -224, 226, -302, -135, 263, 103, -115, -44, 297, 166, -109, -54, 82, -80, 129, 6, 34, 23, -4, 32, -25, -180, 18, 43, 213, -139, -41, -18, 26, -208, -216, -66, 206, -457, 169, 131, -224, -110, -229, 268, 12, 14, -281, -3, 93, 13, -8, -136, -119, 245, 106, -42, 152, 293, -42, 100, 44, -127, 133, 256, -130, 22, 55, -56, -70, -225, -196, -108, 23, -37, 90, -191, 71, -51, -27, -99, -164, 311, 313, -217, 154, 109, -142, -82, 0, 142, 188, -134, -126, 167, 82, 192, -110, -25, 1, -134, 25, 0, -218, -273, -49, 49, 375, -155, -103, 144, 222, 109, 84, -100, -521, -101, 41, -353, 472, 73, -210, -83, -350, 379, -96, 40, -206, 165, -145, 163, -129, 7, -116, 47, -244, -5, 125, -155, 49, 69, 92, -129, 83, -60, 13, -43, 194, 138, -143, -3, 4, -58, -195, 3, -59, -104, 166, -1, -119, -207, 62, -146, 129, -85, 127, 5, 136, 228, -143, 102, -154, 151, -237, 213, -213, 6, -349, 112, 279, 183, -199, 87, -13, 65, -22, 88, -14, -188, 23, -356, 185, -154, 357, -301, -398, -191, 45, -155, 38, 5, -377, 3, -139, 119, 59, -26, -162, -40, -92, 157, 59, 9, -106, 50, -42, -24, 113, 388, 113, -179, 10, -89, 193, -42, -78, 20, 226, 220, 45, 199, 104, 105, -42, -89, 292, 20, 78, -98, 37, -227, 100, 49, 131, -95, 197, 85, -21, -108, -68, -127, 128, -67, 78, 41, -44, 72, -176, 22, 368, 15, -280, 57, -113, -61, 254, 76, 222, 41, 212, 10, 68, -194, 57, -214, -27, -135, -49, -200, -65, 46, 2, -172, 219, -65, 116, 167, 24, -94, 39, 210, 310, -162, 19, 56, -79, 51, 305, 113, -152, -46, 76, -327, 171, -15, -46, 82, -153, 17, 10, 80, -164, -159, -18, -126, -4, 80, 94, 12, 197, -179, -54, 135, -147, -187, -108, -63, 136, -173, 116, 102, 219, 94, 159, 49, 89, -115, -140, 208, 324, 230, 9, 146, 3, -244, 84, 131, 114, -328, 122, 84, 96, -206, -253, -60, 26, 104, 124, 98, -142, 74, 83, -63, 160, -123, 21, 93, -93, -41, -29, 132, 61, 153, -47, -147, 9, 58, 35, 165, 112, 69, -13, -231, 171, -47, 90, 158, -25, 47, -132, 36, 214, -164, -224, -17, 9, 83, -82, 134, -153, -116, -48, 76, -173, -219, -106, -15, -77, -198, 21, -202, 161, -132, 28, -68, 137, -54, -76, 74, 63, 240, 1, -232, -229, 46, 226, -103, -190, -117, -85, 130, -71, -143, -89, 196, 99, 18, -169, -147, -114, -145, -85, -50, 48, -43, 115, 130, 48, -224, -402, 535, 529, 2, -64, 181, -160, -73, 488, 17, -69, -461, 52, -249, 389, -365, -89, 46, -233, -242, -119, -119, 199, -88, 16, 85, 0, -130, -156, -154, -198, -172, -192, 100, 13, 98, 149, -306, -18, -6, 197, 80, 105, 64, -71, 58, -1, -141, 8, -73, 111, 130, -260, 21, -95, -257, 161, 118, 9, -278, -96, 149, 148, 37, 87, 102, -225, 181, 13, -120, -272, 147, -90, -223, 290, 213, 258, -42, -4, 180, -434, 122, 56, 199, -340, -58, -184, -117, 145, 129, 42, -313, 220, -62, 89, -362, 1, -235, 26, -152, -19, -27, -207, 202, 11, 90, 130, 295, -18, -263, -320, 28, 97, -4, -97, -154, 169, -342, -102, -168, -75, 78, -8, 32, 181, -210, 26, -95, -149, 149, 240, 83, 76, 33, -212, -67, -9, 26, 2, -124, 151, 39, 231, -144, 104, 136, -110, 71, 145, -64, 86, 83, -177, 2, 152, 119, 226, 153, 113, 358, -183, 111, 366, 330, -70, -143, -87, -283, 245, -266, -142, -89, 270, -201, 357, -286, 219, 114, -164, -76, 210, -91, -1, 240, 105, 382, -164, -102, -142, -92, -171, -18, 79, -131, 66, -240, 55, -118, 24, 22, 85, 13, 64, 134, -64, -27, -85, 41, -102, 164, 114, 130, 24, 120, -212, -153, 29, -131, 0, -147, 42, -42, 269, 32, -288, -40, 239, 234, -172, 256, 22, -191, -103, -272, 230, -210, 377, 125, 340, 32, -193, 383, 220, 383, -47, -200, -121, -132, 269, -59, -42, -282, -3, 140, 217, 101, 70, 28, -168, -28, 45, 104, 83, -190, 69, -68, -58, 18, -4, 109, -61, -174, -80, 144, 12, 36, 69, 22, 155, 4, -63, 275, -151, 209, -6, -63, -72, -142, 49, -85, -34, 117, -82, -184, -134, -93, 7, -6, 159, -255, 73, 94, 138, 104, -87, 240, 193, 259, -108, 117, 111, -240, 193, -37, 105, -15, 172, 116, -98, 63, -296, 33, 21, 286, -122, -292, -353, -195, 323, -38, 170, -138, 95, 68, -39, -74, 185, 129, 133, 11, 70, -13, 180, -64, -74, -108, 173, -53, -11, 281, 77, -145, -39, 230, 270, 99, -44, -225, -166, -155, 334, 215, 120, -202, -159, -320, 77, -340, -148, 170, -1, -161, -125, -8, -56, -105, -90, 144, 73, -59, -259, 215, -76, -250, -212, 17, -117, 73, -63, -80, -167, -98, 101, 145, -73, -107, 294, -173, 111, -11, -271, 106, 206, 173, -130, -192, -95, -1, 85, -111, 123, -25, 12, 37, 105, -149, -89, 103, -43, 26, -252, 171, 31, -24, 21, -21, -111, -40, -39, -136, -68, 140, -260, 452, 305, 218, -366, -42, -236, -70, 404, 140, -51, -349, 21, -287, 334, -301, -308, 336, 227, -222, -231, -62, -208, -135, 153, 62, 34, -271, 17, 52, 163, -284, -154, -44, -182, -24, 245, 120, 64, -8, -98, -49, 307, -77, 233, -102, -102, -33, -42, -96, -12, -127, -108, 13, -66, -23, -55, 36, -298, -155, -13, -103, 3, 151, 107, -72, -44, -68, 177, 312, 197, 227, -248, 108, 86, 244, -299, -21, -300, 47, -414, 427, 291, 123, -82, 148, -185, -44, 114, 27, 141, -307, 73, -324, 200, -144, -72, 348, 10, -47, -80, 222, 154, -297, 54, 119, 40, -6, 54, -90, -16, -72, 83, 177, -138, 81, 0, 123, -277, 137, -185, 72, 167, -36, 153, 30, 23, 248, 249, 67, 48, 253, 189, -88, -143, 193, 52, -154, -143, -12, 122, 90, -152, -109, 83, -86, -94, -180, -31, 124, 146, -48, -123, 27, 123, -147, -128, -78, -139, -60, -236, 201, 30, -122, -84, -61, 79, -128, 194, 0, -6, -196, 0, -211, 360, -179, -128, 70, 44, -158, -109, -128, -10, -144, 176, -87, 132, 0, -49, 117, -225, -240, 117, -44, -5, 145, -8, -38, -158, 99, 57, 73, 32, 112, 70, 19, -186, 16, -107, 124, -48, 2, -143, -70, 5, 105, -94, -124, 99, 129, -76, -179, -88, }; +int32_t to_patch_embedding_linear_bias[16] = {227, -68, -2, -126, -99, -174, -84, 74, -6, 99, -139, 80, -62, -140, 83, -7, }; +int32_t to_patch_embedding_layer_norm2_weight[16] = {3971, 4588, 4419, 4328, 3995, 4153, 4080, 3987, 4099, 4443, 4075, 3864, 4214, 4134, 4104, 4276, }; +int32_t to_patch_embedding_layer_norm2_bias[16] = {132, -148, 57, 34, 72, -70, -116, -26, -76, 79, -190, 10, -46, 57, -30, 204, }; +int32_t transformer_layers_0_0_norm_weight[16] = {4052, 4657, 4613, 4245, 4042, 4415, 4086, 4275, 4240, 4498, 4285, 4081, 4387, 4184, 4302, 4580, }; +int32_t transformer_layers_0_0_norm_bias[16] = {80, -54, 40, 214, -203, -129, -101, 57, -177, 57, -56, -281, -36, 219, -182, 92, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_Q_H0[64] = {-568, -962, 189, -868, -562, 692, 858, 407, -818, -814, 262, -471, 1273, 623, -384, 338, -321, -114, -723, 913, -697, 294, -35, -123, -264, -331, 509, 129, 184, 595, 16, -677, -348, 313, -401, 679, -798, 378, -145, 190, 618, -246, 776, 801, 974, 570, 842, -29, -685, 721, 640, 87, -612, -939, 890, -225, 522, 70, -514, 927, 990, 825, 114, -893, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_Q_H1[64] = {640, 166, -336, 542, 491, -1105, -458, -497, 20, -292, 989, -578, -438, 699, -855, 724, 901, 119, -824, 607, 1135, 1478, -883, -673, -923, -897, 445, 395, -782, 260, 591, 327, 970, -1386, 631, 281, -121, -721, 109, 203, 74, 106, 593, 1065, 857, -728, 761, -620, -558, 765, -514, 587, -489, -144, 839, -142, -270, 415, -757, 288, 305, 1302, -249, 247, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_Q_H2[64] = {-1419, 962, -640, 252, -124, -585, -573, 363, 218, 537, 461, 201, -502, 636, 804, -1101, 434, 91, -595, -67, -209, -257, 132, 782, -55, -268, -36, -205, -1225, 1346, 648, -933, 360, 693, -726, -675, 1319, 324, -601, -707, 234, 687, 630, 769, 323, -334, -855, 135, -410, 330, -330, 739, -812, -33, -356, -471, 689, -841, 242, -763, -1304, 937, 743, -440, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_Q_H3[64] = {-1060, 1048, 444, 53, 299, -1202, -112, -899, 1136, 226, 103, -466, 653, 104, 151, -131, -910, 333, 104, -1167, -337, -744, -291, 445, -339, -916, 64, -170, -569, 334, -1016, 803, -782, -18, 583, -961, 304, -358, 725, 244, -567, -128, -370, 950, 536, -757, 290, -506, -365, -1083, 685, -1292, 555, -640, -304, 840, 919, -707, 665, -777, 781, 909, 869, 882, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_K_H0[64] = {339, 84, 743, 513, 937, -490, 499, -304, 1092, 299, 522, -95, -850, -672, -565, 107, -47, -401, 196, 1062, -158, -507, 736, -381, -249, 768, -185, -849, -107, 483, 520, -997, -234, -945, 1008, -44, 674, -34, -388, -817, 289, 988, -652, -446, -603, 226, 427, 582, -422, 37, 474, -103, 561, 198, 113, 520, 150, 37, -857, 1162, -361, -122, -909, 596, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_K_H1[64] = {587, -190, 215, -264, -1101, -633, 784, 643, 562, 794, -31, 134, -75, 572, -551, 233, -162, -1081, 780, -472, -588, 170, 1040, -1217, 805, 505, -961, -23, 457, 730, -77, 117, 771, -422, -811, -611, 622, 678, 554, -690, 435, 403, -904, 91, -350, -398, -563, -750, 352, -406, -22, 667, 468, -1362, 395, -764, 132, -553, -612, 61, -284, -933, -340, -561, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_K_H2[64] = {399, -840, -111, -768, -787, 925, 1041, 579, -842, 1107, -195, -454, -1018, -673, 330, -1015, 554, 339, 389, 461, 579, -387, -826, 465, -1171, 274, -94, 518, 899, -878, -986, 258, -406, 199, -487, -577, -1264, 1126, -283, -1205, -1311, -101, 970, 79, 183, -108, -499, 980, 122, 110, -163, -25, 767, -718, -836, -838, 839, 120, -734, 789, -324, 119, -159, -411, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_K_H3[64] = {585, 567, -262, -561, -166, 469, 155, -56, -512, 839, -519, 859, -225, 693, -983, -707, 395, -196, -574, 63, 3, -162, -1000, -962, 248, 335, 1235, -284, 994, 727, -475, -891, -428, -817, -598, -1159, 526, 715, -232, -742, -191, -21, 65, 1479, 84, 389, 658, 385, 674, 729, 169, 221, 7, -27, 811, 841, -1080, 645, 14, -1033, -1146, -472, -74, 265, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_V_H0[64] = {356, -364, 862, -1113, -938, 408, 1437, 968, 987, 664, -411, -881, 756, 768, -795, 77, 326, 481, -714, 196, -110, -215, 106, 621, -812, 542, 213, 1043, -188, -725, -266, -114, 785, -690, 427, 627, 1001, 796, -752, -410, -760, -304, 129, 1112, 62, 805, -1030, 382, -1195, -1002, 855, 1261, 1026, -281, 57, -850, 763, 77, 738, -135, 1189, 65, -1168, 617, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_V_H1[64] = {536, 374, 293, 992, -103, -576, -463, -1069, -605, 1261, 597, -599, 643, -622, 268, 603, 712, 373, -455, 8, 760, -1245, -460, 201, 1035, 731, 955, 626, -131, -759, 43, -722, -817, -398, 168, 999, 474, 150, 639, -148, -359, -493, -551, 339, -737, 825, -827, -86, -681, 474, 757, -1097, -858, -351, 372, -792, -44, -609, -879, 540, 286, 701, 875, 406, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_V_H2[64] = {764, 345, -422, -624, 1231, 99, -640, -1501, -301, -900, 283, 1233, -1172, 202, 1417, -498, 544, 858, 106, 761, 381, -695, -1310, 63, 651, -635, 946, 848, 999, 198, 84, -923, 1050, 851, -766, -870, -854, -29, 999, 47, -538, -926, -208, 448, 898, 61, -418, 1075, 429, -731, -414, -264, -538, 892, 876, 667, 311, -928, -294, 449, -854, 53, 670, -212, }; +int32_t transformer_layers_0_0_fn_to_qkv_weight_V_H3[64] = {-944, 62, 621, 124, -535, -149, 709, 95, 1129, 832, -644, 656, 547, 233, -187, 737, -793, 821, 16, -558, 129, -235, -896, 491, 753, 42, 343, 894, -531, -820, 518, -426, -787, 3, -398, -1120, 1170, 1063, -813, -105, -78, -135, 248, -263, -351, -172, 224, -430, -1072, -956, 331, -6, -221, -602, -34, 0, 913, -859, -110, -512, 1154, 657, -630, 8, }; +int32_t transformer_layers_0_0_fn_projection_weight[256] = {-402, -1077, -244, -103, 318, -176, 766, -1187, -866, 337, 1127, 451, -280, -1007, -185, -704, 654, 854, 369, -532, 565, -666, 1063, 433, 312, 232, 211, 846, 273, 115, -969, 847, -514, 236, -588, 549, -298, 759, -253, 1035, 6, -854, -445, -1030, -204, -85, -398, -307, 785, 142, -1233, -991, 496, 512, -675, -12, 172, 11, -1111, -633, 573, 502, -201, 322, -391, 248, -499, -56, -559, -305, -527, 629, 315, 130, -98, -248, 172, 148, 36, -337, 494, 353, 696, 517, 187, -1141, 985, -1041, -1095, 86, -29, 626, -1129, 678, -357, 67, 557, 291, -223, 493, -797, -561, 1218, -793, -542, 266, 275, 229, -637, -993, 965, 673, -884, 707, -19, -635, -663, -730, 87, 528, -179, 1047, -677, 1117, -854, -716, -700, 234, -970, 807, -180, -116, 1006, -13, -1029, -40, 182, 390, -1164, -858, 584, -453, 202, -765, 821, 362, -337, -572, 40, 20, -963, 525, -390, -743, 990, -432, 156, -54, 629, 666, -252, 461, 486, -5, 762, -728, 3, -742, -741, 1112, 1431, 1199, -676, -393, 403, -522, -474, -760, 508, -904, -265, 203, 78, -1096, -852, 587, 113, -680, 171, -308, -231, -484, -210, -463, 635, -561, -1093, 140, 509, -767, -329, 120, 518, 396, 280, -194, -414, 772, -697, -104, 218, 260, -105, 210, 1339, -369, -991, 856, 977, -735, 664, 306, 405, -156, -290, -772, -732, 594, -101, 930, -1060, 1133, 977, -515, -736, -390, 1010, 118, -351, -652, 74, -553, 216, -609, 289, -209, 1004, 930, 462, 171, 755, -914, -686, -185, -616, -648, }; +int32_t transformer_layers_0_0_fn_projection_bias[16] = {-840, -92, -107, 118, 323, -361, 278, -5, 135, 300, -784, 540, -15, 380, 771, 648, }; +int32_t transformer_layers_0_1_norm_weight[16] = {3913, 4457, 4086, 4198, 3935, 4065, 4044, 3934, 3956, 3983, 4205, 3852, 4319, 4076, 4119, 3967, }; +int32_t transformer_layers_0_1_norm_bias[16] = {-176, -178, -255, 86, 151, -163, -161, -8, 155, -133, -118, 180, -206, 30, -113, -222, }; +int32_t transformer_layers_0_1_fn_ff1_weight[64] = {-269, 879, 417, 125, -1042, 562, 825, 151, -22, 941, 340, 837, -99, -941, -81, -34, 779, -802, -170, 98, -331, -642, 898, 694, -266, 574, -677, 748, -770, -37, 501, -738, 539, -756, 846, -539, 380, 724, -628, 795, 1144, 372, 525, 499, -257, -2, -298, -356, -821, -8, 829, 852, 205, 290, -229, 201, -910, -991, -340, 841, -610, 961, 227, 151, }; +int32_t transformer_layers_0_1_fn_ff1_bias[4] = {-143, -827, -308, 129, }; +int32_t transformer_layers_0_1_fn_ff2_weight[64] = {305, -252, 1555, 1351, -1680, 1389, 1229, -741, -1475, 285, -203, -1095, -1407, -1403, -1965, 1256, -273, -533, -1, -1734, -417, 176, -253, 1055, -326, -525, -1, 343, -413, 309, -1034, -1608, -1219, -547, -472, -663, -1628, -1026, -56, -1330, 673, 451, -900, -1720, 2030, 607, 1103, -1915, 1853, 911, -939, 398, 21, 15, 1670, -409, 378, -1568, 1405, 1371, 933, -759, 545, -2014, }; +int32_t transformer_layers_0_1_fn_ff2_bias[16] = {837, -1010, 736, 2060, 1857, -1132, 728, -1052, 947, 1603, 1612, 1908, 1519, 508, -1745, -1202, }; +int32_t transformer_layers_1_0_norm_weight[16] = {3943, 4401, 4285, 4286, 4112, 4059, 4094, 4023, 4156, 4435, 4079, 4136, 4219, 4111, 4081, 4076, }; +int32_t transformer_layers_1_0_norm_bias[16] = {-44, -53, 85, 19, -34, -44, 71, -39, 40, 66, -63, 14, 27, -106, -87, -76, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_Q_H0[64] = {495, 600, -127, -357, 489, 355, 41, 97, 758, -317, 99, -403, 730, 452, -27, 354, -495, 997, 387, -732, -742, 475, 67, -193, 464, 305, -691, 995, 902, 1007, -985, -300, -608, 939, -555, 527, 454, -789, 77, 203, 550, 130, 912, 756, 104, 733, -477, -462, -25, 816, -253, -828, -407, 607, -1024, 458, -159, -75, -422, -327, 772, -845, 661, 673, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_Q_H1[64] = {-780, -895, 1016, -316, 1036, -767, 839, -289, -582, -1437, 46, -283, -830, 69, 661, 720, 925, -302, -908, -185, -771, 486, 460, -953, 327, -491, -209, -21, 210, -935, -445, 117, 541, -967, 810, -458, -985, -328, -38, 647, 456, 982, -64, -586, -155, 738, -358, 85, -536, 5, -210, 168, -628, 278, -280, 13, -793, 687, 18, -27, -340, 178, 258, -977, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_Q_H2[64] = {-397, -371, 571, 275, -30, 516, 642, 475, 831, 781, -398, -383, -510, 210, -543, 47, -637, 293, 625, -645, 40, -892, -734, 402, -172, -431, 7, -150, -549, 512, -208, 249, -527, -433, 922, 769, -788, -851, 328, 370, -51, 214, -971, -639, -809, 119, 54, 694, 746, -331, -515, 64, -894, 340, -713, -372, 540, -418, 924, 572, 1071, 882, 877, -633, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_Q_H3[64] = {476, -152, -876, 172, -361, -748, -636, -123, 162, -616, -504, 793, 661, 27, 626, 102, -518, 900, 891, -508, -848, -553, 519, 101, 122, -683, -204, 986, 44, 263, 421, -1069, 811, -302, 909, 942, 864, 478, -225, -1105, -470, 4, 387, 537, 133, 434, -6, -780, 301, 739, 1092, -834, -1072, 173, 106, 480, 981, -1, -672, 1039, -32, -769, -809, -673, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_K_H0[64] = {-536, -105, 457, -372, -36, -789, 776, -669, 705, -386, -480, -493, -216, 652, -161, -285, 385, 1026, -222, 268, -761, -564, 815, 991, -417, -308, 967, -141, 950, -843, -774, 222, -9, -387, 466, 539, -385, 108, 569, 873, 607, 184, -627, -371, 92, 143, 355, 885, 141, 339, 397, 598, -574, 500, 226, 716, 449, 328, 820, -210, 614, -841, -650, -881, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_K_H1[64] = {487, 12, -424, -75, 464, 210, 601, -479, 874, -114, 421, 630, 621, 563, 671, -886, 856, -783, 351, 676, 1263, -231, 1, -862, 609, 307, -259, -737, 649, -552, 811, -851, 764, -42, -780, -1011, -595, 521, -447, -604, -581, 286, -718, 184, -32, 81, -644, 927, -789, -145, 864, 638, -400, 675, -935, -786, 1144, -920, -702, 755, -341, -782, -596, 566, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_K_H2[64] = {339, 539, 363, -56, -218, 918, 616, -856, -651, 992, -167, 175, 652, -456, -927, 539, -234, -846, -502, 924, 457, -677, -48, 41, -224, 685, -994, -17, -373, 766, 1014, -845, 509, -554, -878, 187, 824, 437, 871, 410, 1037, 18, 459, -666, 496, 360, -294, 407, 245, 266, -455, -167, -1086, -133, -739, 1113, 462, -910, 764, 1087, 238, -358, -725, -713, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_K_H3[64] = {-909, -289, 660, -80, -802, 331, 600, 430, -889, 182, 205, -1121, 799, 211, 337, -537, 1094, -867, 396, 415, 806, 787, 683, 530, 240, -442, 73, -203, 433, 326, 802, 184, 1048, 362, 49, -755, 903, 970, 491, -289, -807, -123, -625, -826, -348, -711, 943, -872, 369, 459, -610, -780, -902, 865, -479, 952, 251, 723, 10, 137, 110, 432, 545, 827, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_V_H0[64] = {-904, -972, 395, -281, 1346, 1215, 17, -994, -340, 936, -382, -125, -644, -779, -546, 815, 142, 820, 98, 552, -377, 959, 1113, 123, -221, -107, -964, -219, 206, 648, 834, -596, -35, 431, 658, 398, -1069, -140, -465, -39, 455, 824, -75, 420, -270, -55, 619, -394, -685, 548, 194, -23, 38, 815, -786, 474, 684, 318, -763, 593, -655, -618, -263, 251, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_V_H1[64] = {550, 404, -867, -355, 1129, -344, -759, 403, 203, 811, 891, 674, 433, 812, 428, 68, -321, 344, -725, 560, 425, 801, 653, -328, 60, 269, 427, -15, -159, 367, 235, -599, 8, -1167, -239, -594, -544, 871, 675, 78, 607, 621, -244, -492, 415, 668, 1004, -170, 961, -1137, -717, 1007, 228, -242, 508, 511, -703, 429, 800, 807, 826, -723, 855, 790, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_V_H2[64] = {137, -567, -524, -1077, -226, -320, -619, -639, -215, 351, 297, -193, 280, -282, 92, 700, 987, -271, 103, -408, 138, -763, -252, -592, 890, 463, 961, -740, -487, 323, 233, -639, -752, -186, 124, -984, -70, 996, 194, 663, 72, 109, 382, -590, 948, 98, -885, -1018, -411, -896, 847, 478, 16, 0, -861, 876, -875, -176, -784, 30, -797, -803, -906, 896, }; +int32_t transformer_layers_1_0_fn_to_qkv_weight_V_H3[64] = {523, -54, 650, 319, 905, -162, 443, -845, -509, 320, -1008, -984, -99, 709, -64, -938, 175, -357, -351, 40, 777, 340, 1157, -867, -689, 733, 553, -237, 721, -1006, -476, -684, -446, -31, -974, 214, 469, -240, -1137, -233, 285, 528, 266, -798, 538, 786, 438, -717, 586, -872, -901, 1040, 137, -19, 215, -995, -446, -870, 675, 139, 103, -691, -115, -573, }; +int32_t transformer_layers_1_0_fn_projection_weight[256] = {-961, -497, -218, -462, -752, 764, 182, -416, 43, -295, -1317, -752, 990, 758, 595, 383, -297, 299, -272, -565, -953, -338, -303, 1186, 1256, 504, -455, 329, 353, -416, 202, 446, -869, 19, -776, -409, 959, 382, -5, 278, 503, 440, 209, 407, 410, 406, -331, 877, 463, 721, 65, -135, 293, -336, 674, -687, -1054, -331, -225, -675, -963, 710, 728, 790, -392, 108, -834, 300, -154, 767, 401, 421, -820, 246, -236, -957, 669, 358, 483, 60, 249, 66, 1149, -828, -539, 332, 57, -1235, 282, 268, 978, 216, -830, -553, -541, 279, -214, -340, 977, -249, 205, 70, -401, -502, 17, 1231, 634, 390, -937, 15, -798, -473, 50, -277, -825, 504, 79, 163, -647, -875, -860, 161, -256, -936, 594, -491, -403, -47, 643, 316, -778, 1075, -1066, -1276, -590, -713, 888, 114, 749, -78, -257, 103, -363, 247, -128, 40, 1004, 152, 639, 171, -485, -1083, 70, 342, 903, 569, -606, 472, -894, -585, -682, 488, -726, 169, 16, -905, -906, -734, 796, 697, -527, 807, -1091, -911, -320, -791, 718, 622, 475, -343, 853, 769, 884, 564, -1171, -59, 180, 14, 288, -1012, 1087, -518, -549, 777, 576, 765, -356, 945, 640, -174, 238, 281, -341, -889, 1007, 311, 40, -45, 633, -584, 1091, -101, -801, -483, -527, 411, 164, 457, 365, 19, 209, -542, 114, 352, -625, 590, 666, -706, 1037, -388, -993, -373, 240, -343, -914, 856, 956, 617, 982, -140, 371, -455, 208, 973, 133, 652, -646, 344, 297, -880, -97, 271, -380, -219, 827, 596, }; +int32_t transformer_layers_1_0_fn_projection_bias[16] = {-736, 309, -43, -180, -220, -446, 37, 54, 389, -788, 1114, -969, -17, 10, 286, 852, }; +int32_t transformer_layers_1_1_norm_weight[16] = {4083, 4051, 4008, 4127, 3974, 3860, 4095, 4052, 3996, 4005, 4114, 4195, 3983, 4097, 4071, 4004, }; +int32_t transformer_layers_1_1_norm_bias[16] = {137, -2, 135, 87, 127, -139, -134, -96, 67, 14, -108, -63, -78, 31, 15, 53, }; +int32_t transformer_layers_1_1_fn_ff1_weight[64] = {-127, -843, -176, -862, -255, -382, -561, 758, -943, -676, -585, -721, -737, -526, -519, -110, 481, 81, -122, -888, 358, 455, 170, 527, 336, 86, 266, 133, 896, 362, 806, -114, -894, -490, -7, 55, -544, 938, 456, -382, 987, -919, 127, 210, 427, -677, 788, -316, 776, -675, 152, 89, -813, -174, -14, 274, 317, -26, 399, -560, -367, -255, 649, -1004, }; +int32_t transformer_layers_1_1_fn_ff1_bias[4] = {90, -953, 421, -933, }; +int32_t transformer_layers_1_1_fn_ff2_weight[64] = {-1042, -1584, 1737, 504, -1780, 1348, 536, -1647, -1350, 839, -1377, 663, 455, -1985, -1640, 1642, 1730, -960, -1286, -54, -1541, 714, 971, 579, -69, 1795, -831, -1040, 1600, -382, -1386, 245, 1170, 1367, -210, 904, 1794, -1331, -524, -1304, 84, 743, 593, -621, -1397, -1482, 1047, -849, -1283, -1557, 911, 218, -1263, -1694, 1757, 1760, 812, 762, 1568, 1882, -1391, 1405, -244, 478, }; +int32_t transformer_layers_1_1_fn_ff2_bias[16] = {-1109, -350, -895, 2006, 686, -472, 1124, 1903, 1174, -405, -1500, -440, -422, -142, 1269, -836, }; +int32_t transformer_layers_2_0_norm_weight[16] = {4135, 4645, 4316, 4215, 4243, 4415, 4186, 4002, 4224, 4214, 4305, 4162, 4319, 4117, 4437, 4432, }; +int32_t transformer_layers_2_0_norm_bias[16] = {-10, -219, 118, -51, 66, -61, 16, 57, 4, 67, 27, 112, 24, -177, -70, 114, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_Q_H0[64] = {750, 642, 712, 102, -275, -314, 514, -1305, 48, 907, 72, -639, -859, -1227, -96, 131, -174, 771, 585, -694, 1109, -192, -60, -1356, 95, -133, -539, -295, -1002, 421, -649, 590, 403, 1025, -703, 311, 867, 275, -77, -759, 624, -841, -753, -297, -807, 129, 827, -804, -772, 63, 894, -59, -512, -206, 425, 657, 431, -1100, -646, 1259, -1036, -1045, 252, 1058, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_Q_H1[64] = {-101, 525, -497, -703, 267, -890, -574, 202, 304, -567, 1090, -181, -37, -245, -262, 545, -260, 686, -634, -882, 1059, -247, -562, -1061, -944, -143, 1018, -218, -608, -752, -127, 623, 467, -1114, -92, -355, -635, 947, 626, 710, -41, -864, -216, 275, -567, 834, -282, -558, -925, 848, 565, -826, 129, -724, 323, -1025, 681, 725, -81, -38, -463, -653, 1066, -210, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_Q_H2[64] = {-1000, -805, 417, -430, -467, 482, -643, 174, 646, -165, -599, 93, 65, -1101, 230, 546, -172, -758, -61, -837, 974, 408, -104, -727, -296, -456, -186, -148, -786, 216, -490, -825, 362, 932, -340, 816, 142, 20, -125, -1072, 390, -69, -839, 806, 830, -740, -407, -804, 1087, 182, 602, -206, -283, -331, -868, 454, 758, -753, -277, 266, -147, 297, -885, -669, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_Q_H3[64] = {890, -862, -125, -582, -1112, -1234, 52, -854, -742, -485, 26, -1324, 767, -304, 274, 490, 285, -878, -741, -904, -46, 536, -1020, -689, 33, 434, 481, -13, 67, -67, -28, 798, 162, 915, -629, 766, -1016, -907, 705, -1195, 1089, 399, -878, -55, -212, -838, -19, -777, 207, -357, -446, 28, 210, -1012, 500, 196, -409, 121, 470, 957, 885, -742, -227, 284, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_K_H0[64] = {196, -857, -988, -250, 851, 1125, 256, 246, -13, -115, 43, 444, -62, 5, 196, 922, 603, 803, 7, -895, 225, 886, -688, 262, -355, -427, 167, 47, -220, -688, 373, -63, 36, 672, 524, -170, 675, 562, -1017, 662, -648, -36, -1136, 523, -305, 50, 303, 147, 246, -676, -142, 524, 327, 584, -688, -1043, 1089, -277, 414, -934, 798, 883, 1051, -572, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_K_H1[64] = {893, 528, -509, -849, 255, -684, -717, 423, 113, -646, -210, -702, -66, 1028, -1014, -219, -40, -803, -291, 773, -187, 46, 954, 809, -872, 516, 833, -855, -848, 835, -481, 54, -295, 326, 904, 732, 338, 604, 78, -733, 129, 699, 498, 835, -949, 376, -955, -820, -618, 1033, 981, -643, 906, -534, -1152, 65, -322, 66, -274, 926, -558, -402, -926, -78, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_K_H2[64] = {1036, 778, -513, 648, 42, 482, -147, 968, 12, -521, -380, 241, 982, 639, -959, -558, -511, 941, 56, -425, -745, 546, -937, 670, 819, -652, 739, -106, -552, -691, 445, -287, 30, -36, -715, -196, 884, -637, 0, 586, -230, 692, -169, -1036, 9, 548, 426, 797, 300, -356, -648, -432, 1287, -533, -110, -604, 835, 396, 466, -484, -443, 443, 421, -29, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_K_H3[64] = {-1028, -82, 553, 856, -861, -129, 600, -637, 300, -239, 141, -296, 443, 358, 949, 498, -736, 977, 339, 225, -1016, -994, 330, -1120, 1007, 178, -78, 1380, -459, -932, 620, -454, -671, -885, -617, -1051, 1021, -378, 542, 1186, 512, 608, -809, 418, 153, -173, -46, -342, -1247, -413, 461, -858, 482, -234, 593, 168, -638, -919, -2, -734, -703, -717, 275, 1043, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_V_H0[64] = {-569, -735, 276, 102, -180, 537, -520, 1212, 789, -363, 25, -565, 952, 177, 147, -941, -448, -1023, 433, -198, 197, 686, 450, 217, 498, 850, 455, -791, 992, 707, 544, -393, 914, 631, -407, -221, 131, 614, 619, 430, 710, -753, -270, 347, 115, 834, 648, -138, -386, -1090, -122, 758, 753, 488, -639, 843, 35, 193, -708, 1173, -499, -677, -894, -551, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_V_H1[64] = {189, 384, -576, 584, 707, -516, -1085, 81, -652, 809, 849, 929, -834, 725, 256, -568, -77, 932, 4, 445, -174, -238, -718, -991, 539, -472, -577, -951, -1016, 229, 73, 838, 980, -710, -18, 111, -583, 916, 1046, -814, 551, 95, 777, -46, 975, 27, 252, 362, -772, -863, -803, 496, 855, 100, -481, 357, 577, 945, 630, 44, 712, -157, -147, 1142, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_V_H2[64] = {668, -279, 884, 126, -1152, -408, 994, -84, 549, -356, -363, -365, 596, -513, 305, -212, 175, 181, -1146, -1, 588, 511, 147, 231, -751, -28, 129, 877, 385, 904, -362, -628, -290, -366, -1028, -102, 909, -942, 1006, 653, 454, -908, 1069, -462, 1201, -227, -847, -775, -1091, 75, -924, 178, 87, 519, 431, 287, -411, 100, 605, -926, 593, -438, -588, 618, }; +int32_t transformer_layers_2_0_fn_to_qkv_weight_V_H3[64] = {496, 644, 748, 90, 519, 492, 816, -402, -44, -1013, -886, -581, 880, 744, -302, 821, -992, 729, -44, -493, -1191, -137, 352, 950, 342, -211, 347, -1036, 125, -31, 912, 313, -1230, 354, 356, -195, 220, -693, -1152, 538, 1248, -1006, 152, -822, -541, -813, 12, -269, -863, -739, -438, -650, -250, 770, 240, 195, -813, 411, 597, 1034, -114, -202, 777, -162, }; +int32_t transformer_layers_2_0_fn_projection_weight[256] = {-250, -616, -353, -787, 606, 329, 1043, 644, 827, -65, 841, 68, -804, -131, 515, 298, 594, 611, 284, -40, -72, -695, 564, -25, -141, -9, -936, 100, 318, 1101, -899, -442, 755, -919, -439, 111, -58, -1232, 34, 191, -666, 651, -416, -578, -160, -1101, 927, 786, -1151, 834, -830, 143, -180, 381, -887, 812, 755, -287, -1322, 98, 629, 499, 917, 957, 261, 509, -1001, -522, -102, -106, -48, -816, -161, -516, 345, 373, -881, 1022, -493, 648, 1124, -152, -542, -293, -708, -46, 779, -106, -1112, 1022, -634, 145, 401, -1117, -374, 775, -378, -672, 956, -497, 798, -1060, 359, -1384, -853, 802, 1090, -431, -391, -659, -931, 348, 565, 363, 395, -576, -696, 206, 157, 741, 253, -57, 848, -844, -828, -758, 621, -122, -565, 1162, 834, -754, -840, -883, 464, -1167, -816, 670, 613, 272, -459, -529, -585, -854, -559, 925, 240, 1169, -413, -69, -1001, 513, 571, -426, 359, 319, 612, -510, -580, -707, 391, 896, 354, -1138, 922, 943, 115, -252, 36, 225, -326, 598, -232, 828, -678, 621, 582, 930, -1020, 375, -504, -157, -669, -629, 577, -491, 312, 701, -909, -779, -159, 95, -738, 806, 1109, 64, -398, -15, 1345, -1061, -833, 827, 756, -223, 460, -359, -417, -114, 719, -1035, -180, -515, 124, 428, -975, 993, 533, -1178, 966, -308, 575, -908, -113, -656, -439, -547, -542, -343, 1116, -219, -704, 32, -184, -1065, -794, 784, 247, -762, -59, 35, -98, 387, 100, 593, 748, 564, 413, 453, -306, -254, 7, -255, -889, 814, -766, -481, }; +int32_t transformer_layers_2_0_fn_projection_bias[16] = {194, 93, 543, 448, -911, -445, 195, -40, 634, 876, 754, -1012, 50, 857, -446, -108, }; +int32_t transformer_layers_2_1_norm_weight[16] = {4070, 4054, 4113, 4250, 4054, 4081, 4083, 4181, 3917, 4167, 4225, 4116, 4074, 4125, 4118, 4086, }; +int32_t transformer_layers_2_1_norm_bias[16] = {42, 64, -32, 110, 137, -170, 140, 80, -43, -16, 168, -178, 100, 6, 44, -66, }; +int32_t transformer_layers_2_1_fn_ff1_weight[64] = {-874, -1079, -163, 736, -294, -562, -500, 987, 108, 568, -363, -934, -409, -573, -1048, -366, 277, -902, 259, 602, -45, 983, 366, 811, -394, -751, -662, -964, -400, -240, -967, -749, 166, 599, -648, -608, 618, 609, -928, -602, 56, -852, -818, -343, -398, 671, 187, 523, 906, -568, 602, 1123, 788, 123, 297, 817, -692, -732, -585, 704, 1029, 787, -902, 971, }; +int32_t transformer_layers_2_1_fn_ff1_bias[4] = {267, 470, -574, -399, }; +int32_t transformer_layers_2_1_fn_ff2_weight[64] = {1877, 1625, -992, -1629, -1178, -1784, 4, -1248, 905, 507, 1721, -4, 1659, 420, -527, 1624, -482, 1213, -223, 1858, -200, -1466, -160, 330, 1406, 396, -1566, 1945, -1635, 733, -1490, -1626, 404, -1409, -268, 1645, 1503, 1635, -1849, 1682, -1379, 1453, -465, 666, 593, -578, 1630, -747, -1665, -1625, 436, -1834, -1397, 1706, -1779, 42, -96, -1266, -1052, 1321, -1843, 128, -1722, 1636, }; +int32_t transformer_layers_2_1_fn_ff2_bias[16] = {-473, -1167, 1703, 46, 113, 609, -1347, 396, -303, -1647, -449, -372, 176, -1396, 1388, -966, }; +int32_t transformer_layers_3_0_norm_weight[16] = {4331, 4371, 4459, 4169, 4329, 4301, 4145, 4299, 4294, 4423, 4268, 4098, 4104, 4173, 4155, 3944, }; +int32_t transformer_layers_3_0_norm_bias[16] = {-9, -50, -35, -36, 149, -24, -70, 75, 0, 43, 35, -47, -72, 36, 13, 91, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_Q_H0[64] = {812, -991, -1033, 164, -795, 579, -348, 766, 1070, 162, 149, -447, 298, -560, 489, -455, -458, 1003, 28, 1178, -74, 572, 1063, -531, 288, -656, 52, -852, 268, -340, 554, 363, -261, 534, -24, -513, -736, 186, -265, -656, -131, -1131, 917, -628, -624, -829, 190, 508, -405, 31, 991, -533, 728, 1148, 761, -174, -792, -169, 356, 52, 950, 90, -723, 659, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_Q_H1[64] = {417, 44, -833, 344, 124, 505, 217, 114, -753, -223, 59, 506, 404, 796, 326, -824, 45, -937, -647, -1044, 367, 197, -42, 101, 914, -45, 768, 244, 988, 114, 388, 165, 502, -169, 880, 852, -46, -1099, -445, 420, 903, 508, 945, -334, 729, -605, 8, -69, 950, 0, 277, 227, -321, -251, 636, 393, 441, 75, 269, -270, -713, 662, -916, -227, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_Q_H2[64] = {-625, -372, 134, 911, -887, 1167, -760, 713, -72, 576, 108, -1107, -353, -550, 605, -319, -229, 136, 335, 688, 221, -610, 366, 98, -380, -125, -61, -205, -432, 389, 110, 286, 1046, 550, -314, -243, 626, -699, -397, -950, 806, 553, -298, -1018, 713, 74, 860, 746, 348, -952, -293, 440, 797, -396, -340, -810, 182, 1001, 47, 626, 734, 45, -284, -563, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_Q_H3[64] = {1082, 533, -719, 574, 747, -378, 72, -655, 244, -372, -790, -465, -449, -305, 970, 536, 218, -626, 396, -1083, -413, -840, 679, -186, -650, 865, 721, -883, 882, -1084, 614, -783, -846, 623, 94, 490, 1052, -340, -1226, -483, -16, -382, 717, 491, -780, -723, -848, -613, 345, 648, -319, -34, -72, -347, 989, -457, 377, -805, -29, 734, 973, 791, 861, -764, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_K_H0[64] = {-521, 858, 454, -495, 916, 442, -168, 604, 411, -89, 999, 1, -96, 421, 95, 197, -129, -822, 103, 866, -480, 714, -342, 656, -813, -974, 231, -1000, 783, -582, -154, -1051, -942, -760, 788, -81, -396, -102, 270, 72, 1116, -755, -832, 101, 1, -476, 195, 308, -144, -1003, -811, 813, -853, 1089, -738, -198, -100, 252, 935, 526, 115, 513, 18, 735, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_K_H1[64] = {-918, -29, 832, 896, -778, 564, -148, 730, -237, 85, 834, 823, -836, 820, 575, 638, 661, 140, -132, 629, -1014, 82, -486, -571, 994, -457, 1027, 346, 445, -634, -202, 487, 587, 25, 580, 854, -154, -265, -46, 733, 728, 507, -780, -448, -367, -229, 937, 305, 293, -1028, 445, -37, -608, -867, 512, 240, 230, -243, -412, -676, 930, 645, -19, -602, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_K_H2[64] = {-77, -1040, 122, 316, -714, 687, -1048, -1038, 982, -600, -161, 541, -937, -978, 541, 656, 134, -443, -314, -18, 239, 44, 138, -596, -403, 588, 715, 958, 812, -651, -300, 441, -765, 319, -127, -1081, 385, -228, -45, -405, 134, -655, 949, -141, -850, 513, -829, 466, -601, -76, 280, 217, 155, -150, 1085, 409, -572, 165, 818, 548, -504, -663, -25, -151, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_K_H3[64] = {-822, -987, 500, 498, -380, 118, 296, -875, -428, 525, 721, -948, -96, -220, 952, -534, -1220, -182, -802, -290, 53, 825, -687, -910, 930, -42, -265, -297, 1184, -688, -121, -414, 524, -856, -476, 496, 631, 134, 1193, -132, 486, -166, 691, 1058, 274, -1097, -921, 388, 993, -9, -933, 525, -20, -405, -604, -828, 207, -280, -1049, 406, 872, -153, 134, -7, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_V_H0[64] = {883, 284, 1094, -584, -1043, 1291, -1017, 538, 1181, -826, 537, -743, 1056, -1051, 1065, -347, 947, -152, -36, -529, -394, -532, 143, -447, 819, 768, 375, -626, 107, 1032, -154, 691, 845, 1047, -224, 931, 1173, -396, -983, -455, 16, -1076, -83, 121, -988, 816, -291, 72, -1167, -783, 823, -605, 196, -86, -857, 738, -495, 625, -374, -571, 128, -985, 844, 796, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_V_H1[64] = {-121, -695, 45, -12, 29, 145, 226, 781, -515, 970, 780, 1133, -311, -960, 447, 445, 896, -274, 519, -1066, -274, -909, 923, 193, 246, 733, -661, 1113, -95, -1037, -874, -375, 807, -375, 333, -1144, 290, -112, -464, 1003, -578, -207, 751, 1000, 582, -342, 641, 775, -672, 604, -283, 834, 8, -312, -856, -454, 326, -226, -11, -959, 70, 1098, -225, -777, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_V_H2[64] = {800, -780, 659, 436, 608, 983, -692, -810, 1055, 209, -284, 989, 203, -579, -376, 84, -312, -39, 309, 272, -631, -387, 500, -413, 866, 99, 322, -723, -751, 811, 635, 257, -571, 521, 454, -915, 239, -332, 381, -897, 1141, 265, 813, 83, 105, 243, -431, -597, -886, -987, -1014, -252, -271, -94, -218, -324, -948, 846, 376, -282, -851, 724, -920, 601, }; +int32_t transformer_layers_3_0_fn_to_qkv_weight_V_H3[64] = {-539, 136, 319, -1137, 523, -281, -164, 890, -243, -237, -195, 331, 203, 862, -165, 188, 480, -509, 632, -963, 98, -30, -1019, 1024, -732, -486, -843, -480, -458, -729, 528, 728, -402, -495, -697, 1208, 689, -417, 308, -1250, 809, -878, 772, -534, 648, -420, -677, -614, 230, 167, -953, 828, -357, 801, 752, 1045, -868, 305, 622, 1084, -482, 809, 990, 825, }; +int32_t transformer_layers_3_0_fn_projection_weight[256] = {342, 5, -248, -706, 551, -1138, -335, -803, -1059, -259, 550, -227, -212, -948, 336, -347, 724, 0, -258, -610, 104, 853, -1145, 801, 45, -122, -296, -960, 979, -164, 227, -633, 291, -29, 331, -570, -899, 539, 166, -885, 666, -86, 227, -209, 44, -1134, 439, 556, 428, -932, 165, 517, 13, 135, -735, 917, 412, 6, -317, -426, 450, 310, 11, 70, -476, -749, -107, 792, -254, 818, -650, 707, -400, 687, 222, 431, -284, -826, 120, 150, -819, -614, -974, -859, 345, 367, -32, -770, -762, 372, 1068, 352, -201, 500, 166, -592, 665, -217, 231, 366, 564, 47, -268, -925, 1011, -851, 371, 688, -1137, 740, 918, -1041, 971, 42, 914, -1073, -248, 73, 271, -1088, 335, 392, -633, 626, 233, 825, 398, -790, 157, 1155, 441, -655, 356, -920, 699, -145, -525, 955, 180, -23, 97, 817, -420, -964, 1096, -19, -195, -12, 843, 359, -504, 273, 655, -269, 438, 373, -546, -25, 663, -717, -136, -276, 938, 78, -921, -687, 740, -459, -1038, -826, 965, -535, 352, 804, 894, 293, -451, 707, 613, 768, -1007, -1111, 410, -671, -224, 418, 773, 388, -242, -517, 908, 3, -794, 179, -520, 518, -565, -638, -300, 55, 888, 790, 754, -689, -561, 358, 723, -21, -528, 557, 1065, -476, -312, -544, -658, 803, -328, -464, -309, -778, -558, 298, 299, 445, -143, 526, 1111, -49, -762, -721, -224, -158, 529, 1242, -545, -287, -974, -391, 603, 743, -589, -1132, 55, 661, 757, 273, -1212, 1374, 396, -276, -975, -866, -192, -78, 168, -164, }; +int32_t transformer_layers_3_0_fn_projection_bias[16] = {-513, 807, 27, 109, 381, 633, 651, -345, -188, -948, -40, -1119, 69, -344, 610, -562, }; +int32_t transformer_layers_3_1_norm_weight[16] = {4014, 4033, 3946, 3968, 4029, 3985, 4117, 4068, 4052, 4005, 4190, 4268, 4082, 4047, 4155, 3996, }; +int32_t transformer_layers_3_1_norm_bias[16] = {114, -8, 39, -134, -76, -28, -5, -45, -16, 95, 69, -148, 162, 32, 143, -74, }; +int32_t transformer_layers_3_1_fn_ff1_weight[64] = {45, -294, -338, -514, 405, -861, -371, 974, 831, 195, -815, 159, -8, -783, 753, 635, -125, 722, 314, 472, -678, 633, 911, -906, 948, -593, -502, 602, 482, 1182, 18, -479, -804, 954, 458, 242, -300, 779, -731, 989, 108, -1102, -456, -82, 914, -716, 923, 673, -451, 517, -480, -898, -279, 521, -213, 1045, -1039, 728, -1044, -504, 824, -374, -136, 480, }; +int32_t transformer_layers_3_1_fn_ff1_bias[4] = {420, -528, 708, 556, }; +int32_t transformer_layers_3_1_fn_ff2_weight[64] = {-1264, -245, -243, -1258, -1099, -1898, -832, -1786, -91, -535, 338, 531, 99, 47, 1132, -293, 1776, -1641, 1705, -1170, 1156, 1020, -187, -1538, -652, 147, -962, -721, 748, -398, -1670, -84, 1373, 389, -1031, -329, 520, -615, -769, 1458, 1650, 1183, 1178, -137, -775, -271, -1281, -1755, 1191, -1755, -561, -1893, -104, 833, 1300, 1269, 1925, 1248, -225, 316, 1618, -1789, 479, -958, }; +int32_t transformer_layers_3_1_fn_ff2_bias[16] = {170, -517, 322, 1989, -502, 37, -357, 766, 1958, -45, 1673, -1260, 1175, -1481, -1355, 818, }; +int32_t mlp_head_layer_norm_weight[16] = {4039, 4009, 3972, 4135, 3957, 4168, 4133, 4187, 4009, 4196, 4210, 4267, 4051, 4053, 4018, 3976, }; +int32_t mlp_head_layer_norm_bias[16] = {-17, 24, 34, 16, -13, -23, -17, 16, 1, -62, 29, -4, 6, 46, 47, -28, }; +int32_t mlp_head_linear_weight[256] = {-400, 764, -464, -564, 75, -317, 351, -609, -341, -736, 55, 467, -747, 464, -536, 11, -341, 380, 479, -292, 53, 351, -332, 245, 155, -579, 630, 827, 727, 483, -86, 108, 213, 752, -431, 437, 649, -37, 685, 776, 793, -899, 934, 175, 432, -808, -868, 652, 337, 186, -967, -417, 839, -193, -764, 361, -577, 497, 103, 29, 709, 472, 390, -606, -656, -616, -69, -770, 191, -494, 187, 355, 687, -821, -806, 283, 407, -555, -704, -244, 293, -970, -991, 380, 67, 390, 291, 35, 677, 337, -688, -817, 332, 688, 115, -779, 759, 534, 1055, 544, -116, -636, -247, -774, -784, -208, -659, 704, 557, 19, -829, 373, -758, -1026, -1167, 763, 885, -721, -593, -330, 864, 108, -561, 49, 217, -543, 154, -191, 121, -393, 365, 39, 803, 558, -218, 55, 207, 304, -657, -35, -421, 416, 483, 446, 703, 943, 692, -200, -8, 13, 895, -533, 740, -906, -911, -388, 582, -75, -1053, 767, 540, -323, 452, -414, -781, 723, 942, 1029, -920, 937, 884, 1034, 698, 554, -1068, 265, 816, 549, -8, -511, -490, -485, 385, 399, 523, -225, -770, 248, -263, 463, -796, 920, 392, -447, 302, -81, 528, -831, 62, 885, 86, -591, -37, -233, -211, -441, 837, 72, -598, 370, 45, -481, 671, 651, 781, -823, -731, 754, -199, -540, -639, -364, -318, 723, 485, 423, -650, -648, -909, 197, -795, 824, 336, 546, 837, 201, -398, -653, 219, -537, 809, -402, -652, -289, -437, 160, 122, -485, -203, -50, 731, -353, 805, -87, 878, -517, }; +int32_t mlp_head_linear_bias[16] = {-54, 918, 756, -770, 1018, -2, -846, 44, 784, -104, -384, -203, 212, -628, -94, -97, }; + +// Total 14512 parameters \ No newline at end of file diff --git a/sw/applications/transformer/data_cpp/signal.cpp b/sw/applications/transformer/data_cpp/signal.cpp new file mode 100644 index 00000000..0f18a419 --- /dev/null +++ b/sw/applications/transformer/data_cpp/signal.cpp @@ -0,0 +1,5 @@ +#include "stdint-gcc.h" +//int32_t STFT_out[48000] ={15022, 16390, 15545, 7388, 9791, 14435, 15910, 14934, 8889, 9029, 12589, 14368, 13003, 9548, 6344, 9857, 11479, 9461, 8476, -1914, 9560, 7842, 5972, 6077, 3300, 9683, 6443, 5918, 4306, 3938, 8512, 3724, 5741, 5023, 2931, 7275, 3649, 5604, 5232, 3039, 7640, 5448, 5155, 3191, 4248, 7282, 5707, 3886, -1395, 4874, 5392, 5566, 307, 3140, 5102, 5513, 5713, 2597, 3891, 5867, 6802, 5914, 4893, 3388, 6861, 6592, 6289, 5121, 3314, 7333, 4961, 6907, 3998, 3581, 7119, 1288, 7340, 1455, 3347, 6134, -4195, 7221, -649, 2575, 4133, 1906, 6413, 1158, 1360, 639, 3608, 4810, 1664, -862, -2161, 4537, 2477, 1308, -3721, -2389, 5307, 903, -4, -555, -6878, 5826, 1113, -906, 1167, -1543, 5776, 1199, 1884, 1762, 149, 4966, 11, 3047, 1390, -386, 3716, -5616, 2671, -203, 74, 2832, -1861, 1678, -2604, 1596, 1292, 161, 1333, -2384, 1575, -3881, 818, 667, -1833, -390, -1812, 1707, -740, -1805, -3086, -694, 1426, -453, -1980, -790, -124, -648, 361, -3457, 42, 1155, -1014, 791, -13091, -656, 812, 379, 1297, -3332, -2853, -1853, -235, 1618, -420, -3919, -2006, -4401, 1689, 1044, -2273, 275, -565, 1635, 1800, -2376, 792, 2138, 1102, 1969, -2561, 237, 2818, -543, 1624, -310, -1249, 2136, -4400, 904, 920, -3606, 71, -6615, -81, 501, -2837, -1532, -4246, -1490, -2411, -879, -159, -3977, -4394, -7388, -319, -37, -4141, -10580, -1874, -1163, -1711, -3155, -3770, -1572, -3881, -5011, -826, -3183, -2875, -10316, -4701, 956, -4547, -3369, -6280, -4795, 1932, -4555, -2151, -4832, -7088, 2278, -4062, -1050, -4362, -9139, 2188, -5250, -628, -4430, -6307, 1816, -7122, -665, -4281, -3722, 1238, -4499, -856, -3217, -2790, 465, -2960, -1433, -2147, -3077, -434, -3195, -2783, -1981, -2941, -1212, -5049, -5353, -3217, -1690, -1498, -5065, -11050, -3855, -942, -1402, -2999, -6061, -1383, -1013, -1582, -2083, -3332, -275, -1903, -2508, -2036, -2211, -841, -4324, -4298, -2542, -2304, -3922, -6944, -6426, -3393, -3771, -7282, -2375, -9088, -4619, -7090, -2152, -895, -13285, -6205, -9679, -953, -1090, -7111, -6943, -7333, -1160, -2657, -5178, -6399, -4361, -2748, -5439, -4401, -5331, -2684, -7849, -7725, -4121, -4253, -2323, -6348, -6897, -3765, -3744, -2985, -4222, -5344, -3340, -3952, -4292, -6316, -3943, -3635, -5099, -5501, -6581, -3258, -5395, -8104, -6121, -2890, -3694, -8349, -8938, -7267, -2405, -5253, -6570, -6183, -8317, -3901, -6728, -6160, -6023, -6129, -6730, -5623, -7081, -8065, -5117, -7618, -3654, -5993, -12612, -5517, -6372, -2633, -5248, -9541, -6669, -4810, -2844, -6076, -6778, -7488, -5029, -4130, -6289, -5302, -5846, -9132, -5152, -5290, -5980, -4321, -6877, -5027, -5471, -8488, -3290, 10948, 5340, 9881, -583, -1529, 10281, 3184, 9400, 6255, -1363, 7983, 1790, 7839, 8319, -1213, 2985, 5766, 4578, 8716, -1201, 5806, 5972, -7468, 8093, 239, 7278, 3992, 2631, 6914, 2658, 7007, 3013, 4259, 6183, 4335, 5657, 4920, 4879, 6103, 5026, 5172, 5662, 5285, 5893, 4883, 5509, 5524, 5613, 5378, 4402, 4184, 4538, 5872, 4553, 4309, 3084, 2519, 6053, 4412, 4533, 5541, 2182, 5884, 5410, 4304, 6269, 3345, 4957, 5653, 3045, 5565, 3276, 3046, 4418, 1028, 4272, 2407, 595, 1213, 734, 3636, 1612, -1021, -9, 1479, 3416, 1031, -324, 1364, 1998, 3255, 94, 588, 973, 1467, 3470, -317, 408, -256, -1566, 3966, 176, -148, -1555, -5910, 4403, -381, 149, -3399, -1218, 4406, -3162, 1043, -3706, -2034, 3699, -6969, 1255, 13, -2967, 2095, -928, 675, 2541, -309, -742, 1059, -55, 3772, 276, -5152, 1483, -1167, 3918, -918, -2310, 600, -2456, 3234, -4253, -629, -1699, -803, 2143, -8360, -748, -4480, 187, 920, -4510, -2796, -5722, -657, -732, -2852, -6555, -8562, -5101, -1617, -1578, -3238, -2751, -2692, -76, -473, -1770, -1006, 672, 1164, 146, -1307, -1054, 1972, 1728, -76, -1108, -747, 2401, 1777, -1105, -617, 737, 2292, 1237, -496, 491, 1494, 1811, -216, 1202, 1623, 1157, 1162, -1153, 1656, 2217, -332, 552, 898, 776, 2074, -3098, -150, 2083, -258, 1096, -4664, -1276, 2076, 269, -817, -3732, -2660, 1252, 403, -3595, -2332, -3627, 139, -804, -5568, -652, -4610, -491, -4906, -5112, 12, -5653, -40, -5243, -4091, -766, -6220, 444, -1562, -3606, -3645, -7870, -40, -1055, -4503, -10695, -8347, -1875, -1973, -6634, -7025, -5321, -3534, -3721, -6422, -10405, -3470, -2072, -5833, -8296, -6307, -2409, -1348, -8634, -8763, -3250, -1734, -1712, -13134, -3935, -2113, -1132, -2943, -10088, -2782, -1927, -552, -3587, -7851, -3207, -2420, -210, -2134, -5907, -4824, -3031, -288, -1175, -4432, -6584, -2800, -678, -1292, -3739, -5705, -2132, -1039, -2508, -3901, -3854, -1624, -1437, -5728, -4955, -2528, -1266, -2274, -7524, -5831, -2232, -1272, -3370, -2624, -5012, -3195, -2200, -3783, -947, -4277, -4836, -4802, -3420, -488, -3943, -4317, -5543, -2886, -691, -4040, -4122, -3597, -2892, -1142, -4925, -6452, -3758, -4002, -1519, -5252, -10060, -5054, -4808, -1904, -3326, -4930, -4535, -2874, -2275, -1642, -3491, -3392, -1585, -2128, -765, -3125, -2599, -1366, -1867, -687, -3101, -1848, -2227, -2471, -1521, -3092, -1584, -4873, -5110, -4002, -3221, -2450, -8948, -5746, -11796, -3989, -5450, -4673, -2300, -3014, -6275, -6993, -3629, -1265, -1233, -13060, -3994, -3325, -1129, -1401, -6473, -2795, -2634, -856, -3122, -4984, -1852, -2143, -668, -4531, -4954, -1543, -2277, -1158, -4444, 8135, 6088, 8626, -4024, 9938, 7329, 6317, 8147, 3034, 9253, 4904, 6099, 7090, 5534, 7062, 4788, 5168, 5821, 5756, 2868, 6323, 4576, 3219, 3312, 1833, 6494, 3735, 3133, -3194, 4473, 5760, 1781, 5247, 3503, 5033, 4322, 154, 5491, 4139, 2895, 2112, -1883, 5106, 3344, 1160, 567, -8604, 5398, 2834, 5248, 2441, -1097, 6168, 3530, 5936, 4900, 904, 6690, 4608, 5104, 6129, 2446, 6590, 5040, 5192, 6005, 3385, 5551, 4266, 6075, 4500, 3096, 3111, 1873, 6379, 1400, 1015, -337, -2432, 6535, -3148, -6312, 1153, -3379, 6387, -4178, -2431, 1960, -3097, 5323, -2846, -282, 1735, -1790, 2714, -1477, 1123, 1114, 483, -5178, -288, 2408, 349, 2279, -962, 828, 2867, -310, 3205, 602, 1651, 2089, 248, 3324, 1195, 1919, -836, 1723, 2724, 2721, 1435, -8160, 2498, 1506, 3795, -83, -1480, 2126, 141, 3702, -2304, -1676, 632, -186, 2139, -1688, -2840, -452, 758, 749, -1085, -1050, 84, 1955, 2587, -1448, -667, 47, 2776, 3314, -1334, -1973, -584, 3074, 2871, -1128, -4037, -927, 2914, 2029, -1831, -4223, -893, 2430, 1750, -3735, -1903, -725, 1721, 2124, -4438, 91, -814, 695, 2326, -1846, 1159, -718, -1112, 1779, -605, 1229, 953, -4285, 161, -1077, 226, 2278, -2549, -3196, -1597, -1233, 2448, -61, -10037, 1326, -207, 1631, 1238, -5459, 2800, 1173, 597, 1719, -2662, 2475, 1064, 234, 1395, -1008, 22, -931, 85, 225, -520, -10125, -1692, -101, -2013, -1056, -3239, -169, -365, -5623, -1918, -2721, -886, -713, -4148, -1070, -4144, -4883, -992, -3366, -504, -5371, -7334, -1451, -4299, -1722, -5860, -5572, -2058, -2407, -3307, -5420, -9669, -1902, -626, -800, -3278, -4000, -1470, -465, 514, -2492, -1965, -1758, -2323, 435, -3628, -1768, -2921, -5922, -956, -9229, -2309, -4942, -927, -4084, -4407, -2502, -9038, 836, -8231, -2095, -2284, -5389, 1066, -5365, -1906, -1985, -2756, 264, -3891, -3017, -2226, -2262, -1447, -4557, -4960, -3502, -3466, -3976, -11280, -5981, -3511, -5119, -4299, -3848, -5230, -2657, -3228, -2919, -1482, -4701, -3847, -1903, -2750, -1004, -4962, -9136, -1535, -4156, -1487, -5918, -5496, -1578, -9790, -2332, -7666, -4300, -1746, -6635, -2932, -11718, -5430, -1928, -3956, -3045, -13570, -7603, -2016, -3785, -2822, -9656, -7021, -2159, -4384, -2470, -5004, -4553, -2859, -3625, -2045, -2525, -3046, -5049, -2807, -1748, -1425, -2589, -10651, -3267, -2273, -1223, -2394, -5327, -4768, -4832, -1712, -1883, -4089, -3759, -6611, -2592, -1631, -4451, -2098, -3778, -2317, -1688, -4707, -1511, -4370, -1104, -1674, -5347, -1880, -7616, -511, -1990, -8962, -3392, -5659, -637, -3117, -7329, -6851, -5500, -1134, -4374, -4297, -12628, -9453, -1507, -3914, -3602, -7923, -7498, -4224, -5554, -4353, -4133, -2129, -3878, -7270, -2473, -2452, -1737, -3507, -7586, -2008, -2512, -2831, -2846, -5254, -3025, -3418, -5986, -2821, -3714, -5611, -3744, -7985, -2808, -3010, -13840, -2935, -6763, -2277, -2991, -6283, -2459, -7017, -2183, -3789, -3468, -3366, -5831, -3055, -6182, -2980, -5755, -4109, -5251, -13347, -4226, -3284, -3689, -9905, -6728, -7062, -1040, -4341, -6515, -5290, -10547, -88, -4173, -4287, -5037, -9538, 15, -3219, -3665, -4580, -5533, -670, -3366, -3725, -4293, -3755, -2433, -5426, -3616, -4979, -3342, -5897, -10483, -3418, -6809, -4226, -5644, -6907, -3888, -7436, -6950, -4348, -6768, -4698, -5425, -7290, -5661, -11547, -4637, -4024, -4705, -7820, -7789, -5294, -3717, -3606, -4001, -4241, -7811, -4602, -2791, -2423, -2364, -6255, -6510, -1775, -2276, -1164, -5607, -6340, -1017, -3077, -580, -7866, -4238, -901, -4310, -652, -11726, -3115, -1541, -5083, -1309, -10766, -3063, -2977, -5072, -2160, -5334, -3219, -5153, -4673, -2549, -2761, -2681, -5813, -4537, -2539, -1887, -2418, -4519, -5214, -2776, -1955, -2947, -4445, -6446, -3623, -2344, -4213, -5961, -6591, -5118, -2949, -6336, -7215, -6457, -7136, -4560, -9194, -6317, -7439, -9810, -7339, -9647, -7399, -9089, -8084, -5084, -8196, -10603, -8142, -4773, -4006, -6529, -5264, -6082, -3144, -4962, -5245, -3482, -4467, -2991, -7160, -4667, -3534, -3485, -4536, -5624, -4729, -5032, -3222, -8808, -4191, -5173, -6219, -3555, -16024, -4330, -5943, -5030, -4186, -8660, -6684, -6669, -4314, -4229, -3671, -7971, -6376, -4176, -3187, -1670, -3458, -5898, -4030, -2731, -1236, -1895, -5622, -3478, -3836, -1952, -1883, -5111, -2565, -7553, -3555, -3115, -4399, -1740, -7056, -5274, -5062, -4108, -1482, -5186, -5586, -5718, -5093, -2065, -5623, -4664, -4970, -9301, -3493, -7925, -3350, -3927, -8207, -4928, -13647, -2286, -3205, -5647, -5288, -11389, -1695, -3351, -5048, -5436, -10277, -1476, -4273, -3759, -5299, -11084, -1462, -3966, -2469, -4478, -12156, -1510, -2701, -2149, -3377, -9283, -1412, -2234, -3086, -2832, -6406, -1068, -2636, -6186, -3387, -5200, -747, -3812, -10087, -5553, -4196, -911, -5894, -5260, -12137, -2698, -2137, -8129, -4371, -9214, -1973, -5654, -7221, -4905, -7118, -2635, -11761, -6359, -5793, -7149, -5285, -7383, -5904, -6008, -8398, -8178, -8107, -5657, -6536, -9448, -5544, -5874, -6363, -8914, -8639, -5672, -4566, -8413, -10223, -8665, -9040, -4611, -8140, -6790, -7995, -9845, -5443, -6600, -5701, -5196, -5562, -6064, -6901, -5391, -3432, -4047, -5589, -10634, -4751, -2899, -3579, -5435, -9912, -4255, -3442, -3902, -5816, -6228, -4453, -4620, -5031, -6518, -5566, -5374, -5341, -6901, -8805, -6416, -7360, -5643, -8714, -17696, -8138, -11290, -6006, -9255, -12064, -8799, -7964, -6673, -10575, -9542, -7865, -5755, -8615, -10922, -5114, -7102, -4998, -11781, -6158, -3484, -4628, -2421, -3126, -2497, -6789, -5250, -4794, -4449, -4410, -7477, -9881, -6436, -5064, -3607, -3449, -4608, -4046, -5613, -2139, -2217, -2871, -2510, -6822, -1828, -2235, -3843, -2185, -5537, -2152, -3064, -6329, -3289, -4432, -2550, -4718, -4122, -6236, -4556, -2730, -8599, -3320, -6537, -4686, -2432, -7789, -4202, -4618, -4608, -2175, -3777, -6026, -3566, -6205, -2668, -2263, -7801, -2576, -13093, -4308, -2029, -9251, -1785, -4928, -7375, -3049, -8052, -1709, -2944, -9674, -6259, -5386, -2760, -2434, -9137, -6066, -4239, -5655, -2581, -6472, -3521, -4001, -10908, -3366, -5255, -3280, -3305, -4920, -6014, -6907, -4092, -2406, -3021, -9081, -10022, -4709, -2289, -2635, -3189, -5011, -4448, -3296, -3604, -1475, -4570, -4321, -5646, -6025, -1196, -5631, -5608, -5570, -5345, -1726, -3948, -8925, -3247, -3919, -2528, -2846, -4629, -2085, -3725, -3203, -2884, -1340, -1892, -3501, -3959, -2956, 213, -2570, -3436, -5344, -3247, 385, -3672, -4179, -7922, -4596, -782, -4517, -4623, -10663, -5247, -3613, -5710, -4269, -7357, -3805, -8204, -7537, -4200, -4774, -3261, -3386, -9210, -3521, -3260, -4029, -1266, -10245, -2801, -2777, -6779, -618, -8283, -3242, -3408, -5810, -806, -5770, -5696, -4816, -2843, -1404, -3474, -12002, -4835, -2324, -2230, -1947, -5336, -3635, -4445, -3446, -1253, -3757, -2754, -9328, -5841, -1357, -3536, -2539, -2725, -13317, -2351, -3881, -3123, -1220, -7147, -4485, -4898, -4220, -1221, -5824, -7862, -8392, -5317, -2285, -6768, -11502, -7970, -6846, -4558, -7862, -6879, -3544, -8386, -8920, -5639, -3193, -1802, -5582, -16426, -4403, -1478, -1162, -3322, -11213, -4289, -1030, -1320, -2236, -7203, -4753, -1637, -2259, -2066, -5910, -5082, -3287, -4154, -2592, -7050, -4526, -5607, -7379, -3425, -5504, -4246, -5552, -9774, -4065, -2373, -5163, -4380, -8617, -4242, -1009, -7160, -3989, -7901, -3963, -876, -8081, -4222, -6692, -3726, -1778, -6391, -4630, -5593, -4172, -3764, -4734, -4670, -5500, -5797, -7407, -4288, -4354, -7442, -8769, -8786, -5317, -4301, -11498, -6984, -5990, -8221, -4744, -5009, -4564, -5757, -9903, -4512, -3263, -3106, -7633, -8076, -3552, -3447, -2234, -11771, -6541, -3325, -5117, -1930, -12667, -4415, -4296, -5804, -2117, -11981, -2877, -7575, -5708, -2684, -12463, -2311, -10012, -7172, -3786, -17520, -2856, -5074, -5329, -5509, -11698, -4665, -4276, -3556, -6559, -7320, -4445, -5423, -3139, -6032, -4982, -2432, -6815, -3515, -5233, -3675, -1834, -5983, -4451, -4885, -3100, -2452, -6053, -5609, -4813, -3412, -3794, -7398, -6187, -4484, -5126, -5070, -8555, -5637, -4332, -8942, -6059, -7890, -4903, -4780, -8156, -5664, -6966, -5044, -5826, -7445, -4759, -6094, -6121, -7366, -8944, -5258, -4845, -7107, -8586, -12286, -7313, -4354, -6859, -8099, -16158, -6273, -5653, -6242, -7236, -8803, -5182, -11020, -6046, -6956, -5479, -6656, -1536, -2950, -4414, -6079, -3604, -1428, -2411, -7541, -5139, -1848, -1324, -2361, -9913, -4836, -1486, -1298, -2802, -4591, -3959, -2406, -1573, -3744, -2758, -1712, -4194, -2495, -5418, -2422, -42, -5054, -4591, -9189, -3442, 459, -3980, -9195, -8925, -4492, -230, -2899, -11097, -5822, -3678, -2121, -2792, -12465, -5374, -3936, -5487, -3382, -10965, -6491, -4860, -13201, -3897, -6980, -8176, -4223, -4575, -4537, -5943, -7331, -4482, -2722, -5484, -5427, -5826, -5564, -2821, -5674, -5105, -4386, -3766, -4394, -4608, -5164, -2664, -1603, -5443, -3593, -4710, -1555, -639, -4933, -2796, -3042, -1221, -1098, -6719, -1430, -1246, -1225, -3395, -11421, -447, -162, -1211, -8133, -7246, -627, 167, -1171, -4891, -10083, -2175, -139, -1219, -3020, -7058, -4571, -1084, -1635, -2768, -4466, -3412, -2470, -2518, -4109, -4079, -1188, -3285, -3544, -6015, -4011, 137, -3802, -3376, -4381, -3608, 518, -4965, -1353, -3572, -3037, -126, -7139, 168, -4533, -3447, -1934, -13471, 690, -7204, -6408, -3553, -5680, 417, -9220, -8269, -2607, -3936, -222, -8050, -5319, -2079, -4119, -761, -4771, -4550, -1746, -4482, -1413, -3437, -3790, -1023, -3611, -2864, -3832, -3177, -620, -2645, -4979, -5815, -2643, -652, -2136, -4731, -10493, -2648, -695, -2344, -4163, -10081, -3430, -880, -3418, -4701, -6001, -2792, -1648, -5340, -4910, -4263, -1434, -2959, -6768, -3486, -3360, -1291, -4215, -5259, -2557, -2870, -2715, -5327, -4127, -2717, -2591, -6908, -7188, -3928, -3565, -2566, -9345, -9250, -4424, -3837, -3153, -6026, -6089, -5596, -3329, -4823, -4115, -4029, -5332, -3093, -7403, -2244, -3228, -3730, -3423, -6394, -1321, -3169, -3120, -4030, -4822, -1391, -3856, -3352, -4019, -4452, -2389, -6223, -4162, -3507, -5531, -3885, -11595, -5537, -3763, -9584, -4454, -7117, -6049, -5539, -11492, -4732, -8537, -4404, -6531, -8904, -4400, -6582, -2673, -5208, -8826, -2727, -2659, -1747, -5819, -5655, -2061, -1277, -1705, -9453, -4239, -3059, -1187, -2241, -10353, -4868, -6682, -1802, -3158, -5447, -8286, -8509, -2649, -4713, -3619, -12757, -5460, -3539, -4764, -3014, -12636, -4901, -4068, -3348, -2840, -8742, -5394, -4270, -3392, -2768, -4667, -6856, -5074, -5305, -2984, -3324, -7579, -6296, -6783, -3459, -3532, -4949, -5979, -5328, -4029, -5532, -2721, -5319, -5970, -4667, -14849, -1369, -6133, -10401, -5585, -6837, -790, -12638, -8761, -7334, -5777, -937, -6287, -6741, -9955, -8368, -1808, -3420, -7326, -12278, -8497, -3363, -2912, -8770, -16695, -5559, -4951, -4095, -8610, -13416, -4846, -5025, -7435, -7926, -11937, -3580, -4428, -9001, -6381, -11803, -2464, -4303, -6744, -4580, -13182, -2617, -4979, -6343, -3508, -14602, -4359, -6610, -6657, -3260, -15423, -8127, -8838, -6860, -3720, -14890, -7968, -8299, -6477, -4389, -9173, -6467, -6679, -6249, -4327, -7138, -6132, -6455, -6392, 992, 7886, 7836, 5707, 2952, 5763, 7674, 7512, 5744, 3131, 7257, 7047, 6697, 5594, 2840, 6944, 6137, 5861, 5029, 1656, 6387, 5254, 5171, 4191, 1669, 6716, 4499, 4157, 3252, 2364, 6445, 3756, 2809, 2540, 1949, 4670, 3162, 2233, 3092, 910, 3710, 3344, 2679, 4147, 410, 5517, 4146, 3327, 4671, 452, 6178, 4380, 3727, 4620, 2149, 6053, 3711, 3627, 3805, 4693, 5401, 2486, 3007, 1193, 6237, 3584, 1501, 2138, -2809, 6624, -1377, 1312, 1430, 1631, 5874, -740, 1336, 1335, 2278, 3788, 1232, 544, 1760, 1376, -797, 984, -1787, 1610, 858, -4456, -16, -4421, 402, 1445, -841, -510, -1344, -1367, 1905, -616, -34, -459, -2302, 2253, -1120, 504, -1942, -2912, 2376, -1730, 720, -3838, -5891, 1875, -2627, 388, -695, -5800, 806, -4711, -673, 741, -1852, 50, -11015, -2310, 1308, -789, -233, -8245, -3429, 1893, -426, -743, -6045, -3855, 2501, -212, -1327, -3983, -5484, 2535, -521, -2006, -2393, -6745, 1562, -1584, -3385, -1364, -4140, -858, -3071, -6674, -598, -3454, -2410, -4007, -10510, -171, -4255, -203, -4907, -4974, -243, -6219, 582, -5832, -3180, -1018, -8783, -28, -4707, -1608, -2965, -5414, -2510, -3392, -581, -7330, -3019, -3582, -2700, -677, -6955, -1847, 35, -2277, -1773, -3219, -1611, 1252, -2376, -2733, -1083, -2530, 694, -4002, -2387, -716, -5145, -2053, -9433, -1461, -2429, -5676, -2719, -10283, -1021, -1831, -3878, -761, -5449, -1362, 475, -3664, -1287, -2617, -1862, 915, -3556, -2383, -2085, -1446, 149, -2817, -670, -4159, -375, -472, -2112, 394, -5643, 323, -35, -1757, 248, -2140, 192, 320, -1983, -1029, -1086, -983, -22, -2932, -3865, -1238, -3894, -1474, -4558, -9183, -1959, -7920, -3368, -5977, -7833, -2767, -2841, -1495, -4291, -6174, -3929, -1107, -176, -2147, -2464, -4110, -851, -181, -1039, -299, -2417, -2003, -1071, -1016, 578, -2123, -5311, -1919, -1861, 617, -3951, -4696, -2089, -1896, 235, -9294, -2333, -2652, -733, -288, -6439, -1996, -4479, -339, -1155, -4501, -2973, -7503, -1126, -2682, -2749, -3114, -5895, -3277, -4758, -822, -1788, -4046, -8511, -7487, 437, -1922, -3277, -7813, -5958, 551, -5066, -3319, -4848, -2147, -756, -6046, -3552, -4780, 106, -3455, -2730, -2710, -5057, 1332, -4293, -3013, -1523, -5034, 1646, -4528, -6230, -887, -6935, 891, -6414, -9181, -812, -4640, -1659, -7119, -6210, -1117, -2365, -14029, -5370, -6259, -1621, -1609, -3314, -5115, -7142, -1958, -1108, -2256, -7398, -7089, -1758, -994, -2106, -4836, -5489, -1371, -1982, -2098, -2545, -3927, -1402, -4561, -3066, -2233, -3486, -2416, -7078, -4875, -3155, -4911, -5524, -4643, -4758, -5020, -7861, -12217, -3992, -3582, -9911, -4628, -6038, -4259, -2813, -6597, -3333, -5671, 4431, 6956, 4647, 3404, 3214, 3330, 6394, 4445, 4636, 4919, -2018, 4626, 3869, 5670, 6749, 174, 1203, 3186, 5540, 7498, 1979, -3313, 3158, 4216, 7309, 89, 504, 3878, 1072, 6525, -7332, 2160, 4371, 83, 5384, -1885, 2720, 4121, 2851, 3793, -2387, 2886, 3245, 3140, 2596, -131, 3575, 2615, 2064, 2369, 2750, 4385, 2649, 2541, 1643, 4474, 4335, 2717, 3876, 2216, 5069, 3125, 2641, 4261, 3761, 4424, 1483, 2251, 3750, 4483, 2485, 1454, 1283, 2464, 4432, 1067, 1443, 85, 569, 3826, 2180, 401, 47, -1340, 3066, 2822, -1339, 182, -2231, 2563, 2587, -1558, -920, -2301, 1920, 1218, 336, -3313, -1700, 683, -1842, 1950, -4908, -599, -386, -1289, 2887, -5087, -836, 463, 149, 3227, -887, -4338, 1261, -594, 3167, 1502, -1816, 1038, -2955, 2939, 2548, 680, 327, -2472, 2629, 2745, 1043, 51, -1627, 2053, 2212, 948, -302, -2321, 933, 785, 1074, -1594, -3706, -838, -1956, 601, -3409, -3084, -3032, -6554, -656, -3464, -1611, -4914, -7763, -1656, -4244, -1174, -4880, -6737, -1234, -2011, -1233, -4355, -3618, -340, 526, 47, -5364, -1510, -318, 1544, 1463, -7198, -750, -1860, 1727, 1828, -5679, -1416, -7268, 1307, 931, -6528, -3862, -4626, 11, -1518, -4014, -6626, -1510, -2411, -4306, -437, -6696, -397, -3961, -3760, 1004, -6606, -513, -3297, -2746, 1013, -5990, -1930, -2778, -663, -172, -11236, -2111, -3063, 473, -2169, -4851, -144, -4907, 464, -3009, -1982, 781, -8275, -439, -1982, -1424, 776, -9936, -1390, -912, -1763, 71, -6078, -531, -87, -1362, -1265, -4817, 709, 402, -298, -2933, -7191, 1147, 411, 464, -3762, -5416, 641, -36, 858, -3242, -3244, -878, -725, 974, -2772, -4068, -3062, -1369, 786, -3532, -4200, -3880, -2030, 165, -5898, -1956, -3455, -3426, -1106, -5290, -1439, -3346, -6797, -3430, -3721, -2194, -3895, -5475, -7296, -2447, -2540, -5088, -2472, -7216, -1279, -1260, -6922, -1288, -5455, -683, -66, -6827, -1382, -4648, -376, 376, -4007, -2543, -4856, -190, 93, -2386, -3378, -5880, -477, -515, -2070, -2682, -4918, -1273, -1178, -3491, -2129, -3087, -1615, -2334, -12014, -1948, -2105, -1411, -4243, -2991, -1997, -1792, -1734, -8766, -470, -2496, -1876, -2784, -5016, 104, -3838, -1877, -4591, -1105, -731, -6301, -1746, -9082, 199, -3223, -8534, -2817, -6844, -58, -8548, -7309, -10561, -3983, -1936, -10120, -5995, -3376, -3673, -4603, -20985, -4612, -1454, -2665, -1776, -7189, -3343, -2512, -930, -299, -4932, -3211, -7404, -583, -305, -4692, -4774, -3010, -1973, -1335, -5472, -5595, -369, -4883, -2031, -6404, -3584, 783, -3635, -1048, -6310, -2819, 852, -2206, -154, -5323, -1834, -93, -1718, 30, -4480, -626, -1947, -1728, -541, 4174, 4649, 8112, 4717, 10466, 5280, 6423, 7948, 6862, 10222, 6501, 8002, 7664, 8295, 9563, 6769, 8408, 7456, 8429, 8561, 6127, 7730, 6905, 7644, 7034, 5048, 5903, 5514, 5941, 4594, 4185, 2543, 3305, 2660, 982, 3149, -888, 1426, -2564, -1865, 1011, 1471, 735, 1166, -1159, -5527, 2616, -306, 1632, 314, -106, 3024, -43, -844, 734, 2930, 3341, 2467, -2478, 2614, 3788, 3719, 3345, 2597, 4789, 2812, 3667, 2827, 4269, 5884, -511, 3317, 2219, 4869, 6290, 1704, 3473, 2860, 4963, 6365, 3274, 3591, 3308, 4690, 6044, 2644, 2936, 2953, 4056, 5092, -557, 1584, 1968, 2995, 3317, -4360, 179, 891, 1167, 815, 452, -215, 513, -2135, 86, 1319, 299, 907, -1288, 765, 870, 155, 1373, 1199, 403, 686, -2036, 1276, 2295, -1164, 1208, -6659, 115, 2607, -2310, 701, -1110, -2708, 2307, -1258, -1150, -328, -2530, 1467, -1410, -736, -1907, -296, 883, -2029, -52, -5263, 495, 1564, 553, -1306, -5543, 797, 2156, 1991, -3684, -3848, 1128, 1951, 1912, -3782, -1034, 1249, 1359, 895, -5389, 388, 952, 1349, 218, -6377, 657, 576, 1456, 759, -2880, 335, 729, 494, 1309, -1657, 478, 1458, -2099, 866, -473, 1422, 2292, -1460, -620, -50, 1993, 2768, -94, -1113, -2239, 1399, 2583, -751, -410, -4992, -1336, 1481, -2172, -510, -476, -3462, -839, -1211, -841, -618, -17, -2638, -555, 273, -3499, 496, -876, -1009, 1572, -1315, -297, 196, -2170, 2027, -228, -1264, 454, -3745, 1439, -1464, -2322, 81, -4717, -381, -5409, -4077, -907, -4231, -3575, -11310, -5445, -2337, -2910, -8052, -6921, -5310, -4192, -1845, -13976, -4606, -4917, -4348, -2024, -8954, -3415, -5146, -1546, -3490, -8070, -3267, -5532, -149, -4645, -5821, -3369, -4589, 86, -4673, -3846, -4033, -4557, -413, -2522, -2014, -7275, -7793, -1331, -262, -1161, -6355, -4242, -2505, 707, -1661, -2821, -1515, -4093, 563, -3620, -1675, -1146, -6469, -473, -6858, -1510, -2831, -7219, -1769, -5947, -1635, -7801, -5863, -2385, -4331, -2407, -5390, -5883, -3613, -4909, -5852, -2773, -7221, -9159, -8695, -6468, -1251, -7432, -3003, -8598, -3055, -955, -3342, -265, -7250, -2386, -2007, -710, 612, -7422, -1428, -3766, 347, 364, -4521, -496, -3947, -144, -697, -1507, -547, -3434, -2881, -2096, 292, -1598, -3256, -5414, -2594, 965, -3239, -3247, -2169, -2317, 652, -4359, -2603, -1742, -3337, -557, -4459, -1171, -2509, -10715, -2786, -4692, -227, -3927, -3425, -7108, -6957, -226, -4770, -818, -4731, -6172, -1041, -2897, -248, -2449, -1775, -2384, -1771, -697, -2684, -90, -5076, -1110, -1802, -6855, 99, -9796, -337, -4902, -5453, -1061, -2976, -36, -5415, -2246, -3853, -1317, -549, -918, -1705, -3747, -2112, -4001, -3034, -4635, -4213, -1260, -3727, -2473, -2438, -6982, -367, -3185, -1593, -982, -4534, 264, -2079, -1182, -222, -2747, 483, -2456, -1750, 35, -2512, 388, -5304, -3164, -88, -2206, 140, -4527, -3982, -532, -1428, -144, -2873, -3008, -1346, -1345, -365, -3984, -1784, -2639, -2397, -697, -6265, -1517, -3277, -2307, -1651, -4134, -2354, -1553, -288, -3640, -3791, -3550, 65, 652, -3861, -4141, -3568, 950, 228, -2067, -2900, -2781, 1302, -1954, -1289, -2053, -2108, 1342, -6273, -1345, -1988, -2096, 1204, -4779, -1906, -1653, -3694, 637, -5027, -1988, 82, -10105, -1492, -629, -486, 2110, -1648, -3002, 1882, 1459, 3378, 657, 1358, 2660, 2603, 3623, 1185, 2820, 2130, 2627, 2740, 637, 2565, 365, 1434, 560, -235, 841, -2650, -1067, -3141, -370, -1308, -5821, -3575, -5607, 47, -1692, -6442, -2726, -5532, -168, -2738, -4904, -1480, -7712, -1903, -4340, -3564, -672, -11754, -6389, -3800, -3243, -417, -5924, -5494, -2953, -3758, -816, -4087, -4188, -2255, -4726, -1998, -3790, -4542, -1674, -5694, -3952, -5810, -5381, -1442, -6169, -5589, -7299, -5101, -1910, -5950, -4971, -2468, -4109, -3935, -6223, -3510, -1109, -4084, -12610, -7526, -2798, -1748, -4875, -2691, -6655, -3009, -5180, -3571, -299, -4560, -3222, -5909, -1531, 345, -3402, -2278, -3277, -663, -382, -2929, -1166, -3916, -1028, -2305, -2012, -494, -7351, -2594, -3089, -610, -250, -8475, -5069, -3070, -48, -487, -5563, -7464, -4932, -943, -1479, -3054, -7030, -5903, -3367, -3876, -1946, -5475, -4377, -2021, -7366, -2306, -4082, -4492, -563, -4662, -4219, -2805, -3707, -1053, -3735, -9693, -2621, -1912, -4055, -3845, -8011, -3894, -912, -8948, -3433, -5298, -6418, -661, -3656, -2446, -5489, -10928, -1071, -2590, -1764, -7680, -8049, -2208, -2121, -1662, -6862, -3920, -4199, -1926, -2121, -4885, -2611, -7311, -2486, -3145, -4183, -2502, -6901, -3554, -5151, -3631, -2937, -4649, -4186, -7162, -2699, -4051, -3461, -4742, -5468, -2078, -6172, -2738, -5050, -5448, -2188, -5573, -2471, -5332, -7820, -3023, -4144, -2849, -8141, -9531, -4575, -4189, -3847, -6521, -7025, -4941, -5784, -4681, -3328, -4626, -2908, -10587, -4944, -2513, -3434, -1903, -8857, -6083, -3079, -3631, -2184, -6619, -7385, -4605, -4939, -3503, -7520, -4832, -5781, -5437, -4992, -16740, -3000, -5635, -4065, -5684, -7742, -2005, -6065, -2885, -6214, -5278, -1464, -7700, -2155, -7036, -4340, -1287, -9068, -1918, -8916, -4106, -1409, -10187, -2433, -8882, -4859, -1646, -9359, -4090, -7672, -7479, -1849, -6429, -6578, -10293, -11893, -2146, -5860, -5821, -9577, -9527, -2889, -7698, -5002, -5400, -10978, -4290, -10471, -5225, -4621, -9688, -5863, -8450, -5468, -6029, -7785, -7006, -10558, -5211, -9458, -7926, -8354, -10826, -5036, -5769, -9321, -8951, -3863, -401, -4910, -2323, -2099, -3046, -1484, -5082, -3636, -4300, -1990, -3768, -3293, -6039, -2892, -1020, -3385, -4360, -10286, -1381, -255, -1195, -8361, -4200, -844, 278, 114, -2769, -1775, -811, 435, 634, -894, -1206, -1477, -8, 381, -142, -2189, -3598, -1427, -717, 335, -4704, -8123, -5223, -2835, 417, -4946, -7597, -6079, -6358, -351, -3272, -5801, -2029, -7051, -2202, -2890, -3212, -1142, -3754, -3082, -3662, -1664, -2077, -2099, -2011, -3470, -1050, -5634, -1766, -1891, -1794, -940, -8934, -2247, -2760, -858, -1262, -3438, -2825, -4027, -444, -2366, -964, -2952, -3780, -62, -4754, 1092, -744, -1225, 785, -3777, 2671, 1289, 547, 1815, -1385, 3401, 2002, 1037, 2102, -919, 3093, 1419, 302, 1159, -2604, 1611, -615, -1667, -1151, -6590, -1305, -4651, -4417, -2579, -2497, -5931, -3787, -3795, -2262, -1112, -6328, -1578, -2133, -2192, -1282, -5249, -492, -1608, -1433, -1872, -5463, 56, -2829, -1033, -1877, -6735, 108, -8921, -1287, -2722, -7527, -461, -2687, -1650, -8005, -5833, -1891, -802, -2093, -3565, -4344, -4628, -1311, -2714, -996, -3912, -7108, -4596, -2647, -767, -3612, -5606, -7922, -2412, -2013, -1807, -5153, -3394, -3264, -3955, -187, -5528, -2571, -5326, -4593, 284, -4498, -2853, -4618, -4179, -632, -2208, -3530, -2875, -3441, -3109, -724, -4099, -2419, -2947, -2721, -181, -4229, -3471, -2999, -1022, -361, -3709, -7384, -3834, -599, -967, -3015, -8685, -5134, -711, -1899, -2887, -5903, -3554, -765, -3358, -3166, -5754, -1923, -714, -3785, -2993, -5364, -1627, -914, -2953, -2677, -4464, -2332, -1681, -3383, -2699, -3035, -3388, -3309, -3892, -3248, -1738, -3700, -6108, -2633, -5378, -1179, -2604, -4500, -2448, -6191, -1404, -1393, -2437, -4005, -3079, -2358, -977, -2288, -5299, -2310, -4056, -1572, -3908, -3726, -3124, -5777, -3196, -5321, -2909, -5437, -4515, -4846, -3710, -2791, -11497, -2689, -5536, -3021, -3005, -9364, -1774, -7165, -3170, -3541, -5741, -2088, -5895, -4048, -4716, -2782, -4370, -4907, -6604, -7144, -759, -6454, -7052, -7518, -8122, 162, -3555, -4903, -4158, -5895, 171, -3090, -2152, -3245, -5270, -458, -3873, -1626, -3560, -5052, -1399, -4831, -2721, -3192, -3680, -2242, -6011, -5172, -1962, -2520, -2037, -8181, -5573, -1320, -2241, -1316, -8217, -4278, -1378, -2414, -1338, -6014, -3858, -2009, -2515, -2295, -5196, -4232, -3320, -2881, -3690, -5759, -4847, -5692, -3846, -4289, -8306, -4073, -8223, -5282, -3679, -16164, -3100, -6849, -6858, -3166, -9936, -3173, -6371, -6714, -3424, -8925, -4364, -5933, -6648, -3920, -7339, -6037, -4464, -9019, -3779, -6133, -6647, -3996, -10396, -3640, -6068, -6735, -5136, -8205, -3995, -6796, -7047, -8061, -8816, -4599, -6902, -7482, -10407, -11258, -4973, -5821, -7887, -7805, -11952, -5019, -5191, -8094, -3997, -1225, -1726, 455, -2235, -1923, -1850, -2943, 550, -3777, -1445, -2087, -3342, -100, -5814, -1953, -2336, -3153, -1103, -4142, -2632, -4684, -3320, -1695, -2613, -2901, -8141, -4337, -1264, -1490, -2999, -2810, -6058, -562, -465, -3671, -2464, -7398, -133, 2, -5802, -5233, -7651, 29, -553, -6365, -4151, -6733, -20, -2718, -6204, -1790, -5319, -477, -5304, -14004, -1346, -5160, -1726, -2391, -5560, -1932, -7949, -4745, -808, -3556, -3041, -3434, -9599, -338, -2007, -3100, -831, -3094, -916, -500, -1744, -360, -1619, -2268, -816, -956, -1394, -1788, -2899, -8095, -2464, -3479, -2063, -2920, -96, -6021, -2134, -158, -528, 2698, 497, 628, 1616, 1838, 3059, 2030, 1896, 2141, 2847, 1232, 1605, 1912, 1225, 2745, -8986, -425, 926, -1296, 1901, -483, -2512, -753, -2453, 956, 843, -1462, -2673, -1688, 9, 95, -537, -4408, -2272, -2437, -1608, -347, -5766, -2994, -5430, -3559, -711, -6027, -2730, -1048, -6876, -1160, -5132, -2448, -191, -9054, -1174, -3723, -2641, -1234, -7680, -999, -2339, -3458, -3787, -4533, -1345, -1551, -4958, -4962, -1365, -2678, -1656, -4757, -4839, -255, -4576, -3032, -2895, -6716, -603, -5046, -6251, -2278, -6261, -1986, -4877, -5405, -3344, -5445, -3752, -4363, -3169, -7274, -8626, -5077, -4816, -2093, -8234, -4423, -6048, -8315, -1521, -5655, -2150, -7367, -4908, -1421, -4987, -2215, -8890, -2915, -1900, -3782, -4512, -8844, -3645, -2610, -2110, -11768, -7070, -6387, -2648, -642, -5088, -5925, -2978, -2638, 160, -3597, -6593, -1333, -4099, 112, -3402, -10426, -1467, -8395, -890, -3571, -6303, -2852, -3149, -3120, -4245, -3113, -4508, -964, -7471, -4544, -1674, -5138, -434, -8217, -3670, -1793, -6248, -1070, -7179, -3860, -3207, -11460, -2975, -7530, -5558, -2942, -8060, -6450, -4451, -7461, -2403, -5962, -4914, -1935, -10274, -3799, -6274, -3149, -605, -5873, -6762, -4510, -3147, -166, -3850, -6233, -2935, -4624, -373, -4159, -5653, -2806, -7555, -1092, -5467, -7347, -3662, -11322, -2169, -5232, -6273, -4987, -12250, -1931, -6186, -3310, -6732, -12012, -704, -11559, -2685, -8575, -6899, -460, -3157, -3793, -10286, -3554, -1608, -737, -6339, -9748, -1825, -4462, -94, -7832, -6802, -1348, -6603, -749, -7260, -7043, -2270, -5405, -2259, -6798, -13103, -5551, -4543, -3056, -6387, -5503, -8667, -4196, -3570, -6220, -3738, -5031, -5614, -4747, -6335, -4764, -4838, -14754, -2743, -6782, -10976, -6079, -6492, -839, -8010, -3814, -6350, -4274, -270, -10839, -1667, -4784, -3521, -885, -8579, -1418, -3388, -3149, -2850, -6281, -2455, -2546, -3133, -7300, -6330, -4263, -2585, -3700, -11042, -7839, -5477, -3646, -4679, -6705, -5640, -5430, -5216, -5187, -4908, -3996, -4950, -5622, -5062, -3597, -3962, -5171, -5520, -5080, -3056, -5109, -6746, -6170, -4909, -3343, 12256, 8004, 12464, 10904, 8416, 11661, 8838, 11745, 10292, 7837, 9829, 9223, 9416, 8226, 5859, 6696, 8767, 5290, 3434, 1111, 2977, 8757, 4969, 1397, -464, 2108, 8772, 5794, 2522, 410, 3623, 7901, 5356, 2679, -1019, 5245, 5907, 2704, 4437, 2837, 6340, 1941, -1646, 4585, 4770, 6369, -1679, 2483, 2553, 5902, 5187, 2214, 1437, -1825, 6887, 4304, 3741, 84, 2872, 7698, 4748, 5084, 4322, 4584, 8097, 3880, 6081, 5659, 4890, 7818, 404, 6185, 5249, 4249, 6527, -7291, 5006, 2951, 2881, 3497, -5240, 2206, -4488, 1561, -9294, -62, 927, -185, 1006, 283, 2058, 2088, 1229, 656, 1421, 2252, 1775, 1014, 258, 2453, 1699, 199, 430, -287, 3213, 2191, -2181, -57, -1054, 2911, 3325, -3151, -687, -1903, 1542, 3738, -1571, -2331, -1605, -940, 3089, 510, -6440, -368, -8987, 1177, 1854, -1607, -59, -1887, -1725, 2033, 1828, -1407, 592, -2381, 864, 3501, -5873, 1064, -2537, -1580, 3845, -3362, 542, -1505, -2445, 2886, -229, -405, 220, -2483, 444, 1400, -1286, 1392, -3217, -2656, 2135, -1229, 2661, -1199, -1080, 1981, -101, 3840, 256, 738, 747, 983, 4422, 182, 1386, -1648, 1393, 4214, -1355, 859, -838, 572, 3078, -2979, -575, 1179, -2779, 1287, -2136, -2727, 2186, -603, 978, -480, -6706, 2734, 2007, 1252, 808, -2298, 2885, 2142, 482, 891, -647, 2223, -222, -882, 48, -1264, 701, -928, -1442, -453, -2690, 1267, 2068, -781, -1361, -3028, 2620, 2817, -385, -2744, -5865, 2610, 2421, -936, -733, -3840, 1366, 1544, -2087, 10, -1101, -272, 683, -2789, -693, -877, -801, 163, -3096, -1309, -2391, -582, 299, -3274, -1850, -6029, 58, 616, -2384, -4761, -7028, 879, 179, -883, -6516, -4411, 1277, -1468, 34, -2535, -2780, 952, -4018, -129, -857, -2165, 261, -4386, -1751, 839, -3254, 107, -2568, -3835, 2081, -8946, 80, -1732, -2107, 2452, -4218, -605, -3095, -1867, 1838, -2078, -1614, -6924, -5828, -12, -2580, -2200, -2167, -3131, -2820, -2926, -3767, -1126, 719, -1176, 479, -6279, -2542, 2094, 49, 2495, -2044, -5879, 2347, -592, 3243, -1135, -5126, 1748, -3047, 3057, -3205, -4156, 138, -1356, 2208, -7246, -1605, -2387, 720, 1134, -3015, 104, -1286, 1267, 413, -3284, 616, 176, 843, 110, -6889, 398, 697, -193, -436, -11669, -33, 829, -1605, -2037, -10863, -448, 101, -2500, -5866, -5674, -1045, -2758, -2960, -12132, -2950, -1885, -5134, -5512, -10490, -2075, -2092, -2006, -4752, -10492, -2218, -1038, -1937, -3669, -4559, -1907, 129, -3237, -4189, -2470, -812, 589, -2988, -1045, -2067, -276, -42, -1464, 325, -2838, 109, -2212, -1060, 380, -3663, 1003, -7791, -1896, 621, -2976, 1814, -2913, -403, -258, 8045, 9550, 7186, 501, 120, 7325, 8675, 6888, 1718, -160, 4903, 5702, 5722, 2833, -1728, 3467, 5928, 3912, 3925, -1514, 5284, 7940, 4257, 4699, 1072, 4933, 8041, 4843, 5014, 3906, 1122, 6909, 4358, 5019, 5623, 1005, 5540, 3590, 4792, 6091, 4076, 4906, 3947, 3907, 5549, 3769, 3762, 4786, 890, 4882, 741, 1371, 5631, -291, 4994, 728, 1159, 6304, 4450, 4886, 3321, 2554, 6345, 5797, 3780, 3904, 2829, 5709, 5579, 1185, 3568, 1699, 4629, 4263, -2447, 2989, -2181, 3142, 3186, 129, 2449, -5138, 1168, 3525, 1168, 1787, -1819, 195, 3274, 742, 1218, -663, 1042, 1324, -866, 1954, 1364, 1572, 1662, -4443, 3379, 2084, 1684, 4019, -8671, 4064, 1194, 1955, 4407, -4026, 3688, 230, 2287, 3023, -2688, 2463, 1878, 2236, 1119, -1896, 1342, 2899, 2547, 2351, -1459, 192, 2690, 3911, 2889, -558, -3703, 1611, 4897, 2077, 1155, -4453, 1426, 4812, 253, 2535, -1286, 2192, 3359, -1729, 3156, -1705, 2219, -457, -1692, 2994, -4273, 1368, -6251, -398, 2085, -4517, -325, -1626, 744, 1019, -1348, -3731, -2295, 1545, 1093, 732, -3623, -5882, 1875, 1617, 2194, -270, -4617, 1827, 2031, 3166, 506, -916, 1703, 1981, 3615, -387, 1276, 1579, 173, 3603, -2179, 2473, 1186, -3435, 3314, -2054, 2724, 140, 1652, 3011, 491, 2149, 1076, 2844, 2872, 2244, 1128, 3283, 1936, 2805, 2588, 349, 3957, -821, 2510, 1202, -190, 2950, -1257, 1734, -4619, -1319, 204, -250, 544, -1348, -2007, 294, -875, -352, 1091, -997, 1688, -2024, -425, 1248, -1371, 1668, -855, -262, 382, -5691, 956, 510, -302, -817, -2914, 1049, 907, -595, -1920, 502, 1943, 448, -821, -2724, 1601, 2352, -661, -746, -3330, 1475, 2140, -2026, -671, -4629, 392, 1396, -2031, -648, -7270, -1545, -146, -264, -553, -5524, -5040, -3276, 1055, -589, -3499, -9133, -5950, 1530, -979, -2698, -4207, -2716, 1158, -1913, -2031, -4130, -1612, -210, -3641, -1409, -6419, -2059, -2883, -5326, -565, -1954, -4178, -5976, -4314, 748, 198, -8769, -5558, -2953, 1516, 195, -7740, -4682, -1797, 1192, -2740, -4010, -3483, -331, -413, -5649, -2104, -2098, 1117, -2120, -1314, -1318, -954, 2108, -357, -1250, -1381, -306, 2503, 958, -537, -1893, -644, 2144, 961, 741, -1843, -2192, 590, -137, 519, -1748, -1145, -2490, -1252, -1332, -2488, 606, -797, -2951, -2477, -3125, 1038, 190, -3824, -112, -2300, 779, -1038, 313, 1460, -1318, 19, -3384, 1074, 2146, -964, -1678, -3315, -616, 2249, -1141, -4332, 867, -1709, 1865, -1088, -9021, 3321, 629, 1195, -654, -782, 4100, 1998, 1048, -939, 2199, 3533, 2857, 1285, -2908, 3349, 1691, 3051, 932, 8460, 8764, 11352, 9229, 2753, 7994, 8949, 10816, 8749, 4209, 6432, 8797, 9288, 7514, 4087, 3028, 7763, 7221, 6280, 2883, 4307, 6429, 6286, 6063, 5151, 7170, 5960, 7057, 6742, 5915, 7885, 5807, 7424, 7641, 5033, 6634, 4701, 7023, 8459, 3040, 2317, 292, 6300, 8670, 1377, 4805, 1482, 5279, 7906, 2178, 6627, 4124, 3261, 6187, 1619, 6761, 5003, 2385, 4000, -1840, 6090, 5749, 4444, 149, 435, 4690, 5625, 4623, 68, 1056, 2124, 4213, 2140, 3875, -22, -3026, 2354, -1857, 4641, 1532, -8310, 1683, 2757, 4313, 3311, -7519, 872, 3382, 3707, 4183, -6729, -44, 2501, 2651, 4306, -3805, -1024, 1050, 4, 4095, -3055, -2232, 319, -2462, 4125, -2696, -1606, 834, 1370, 4268, -2410, -1369, 1480, 2791, 4182, -2101, -3471, 1399, 2977, 3828, -1520, -10223, 1, 2121, 3192, -775, -2869, -4311, -529, 2125, -186, -1618, -5470, -6680, 279, -352, -75, -2436, 917, -2823, -2656, 1519, -1145, 3016, -804, -4637, 1827, 182, 3785, 2504, 898, 1495, 964, 3725, 4232, 2812, 2149, 1390, 2948, 4710, 3434, 2418, 1520, 1436, 4089, 3316, 1374, 1283, -1088, 2899, 2824, 1657, 994, -7632, 2226, 2433, 2951, -5, -3054, 1144, 2270, 2699, -55, 100, -2935, 1379, 725, 3089, 1043, -1725, -2073, -2755, 4658, 399, 1008, -1394, -4091, 4839, -2461, 1439, 629, -1411, 3963, -2723, 695, -1442, -2145, 2462, 299, -1740, -1715, -2818, 1113, 1355, -2852, 2143, 2129, 732, 1797, 736, 2904, 3268, 1169, 2289, 1744, 1974, 1867, 1005, 2571, 1211, -754, -5190, -349, 2287, -231, -8360, 810, -1871, 1834, -1632, -3091, 2122, -1322, 2495, -2923, -1269, 1075, -755, 3536, -2198, -695, -2012, -865, 3776, -238, -991, -3860, -1450, 2933, 160, -2163, -644, -2220, 1230, -1354, -3734, 1575, -2364, 379, -5293, -4967, 2724, -1855, 144, -3369, -5844, 2915, -1599, -1240, -2022, -5521, 2148, -1625, -2487, -1109, -3257, 70, -1427, -1644, 471, -1981, -5198, -595, -705, 1684, -2131, -6811, 346, -443, 2197, -3951, -6458, 798, -2139, 1940, -8099, -3504, 634, -5089, 805, -6176, 47, 469, 671, -1372, -7883, 1266, 1254, 2689, -5451, -5118, 975, 2109, 3192, -9195, -643, -664, 2208, 2548, -3472, 822, -3077, 1423, 640, -719, 902, -5188, 621, -3357, 1233, 509, -7465, 1372, -8998, 2263, 412, -1372, 1921, -3528, 2170, 457, 1163, 1371, -1897, 689, 419, 2608, 199, -990, -2223, 406, 3461, -518, -285, -1417, 524, 3722, -721, -471, -59, 846, 3468, -3, -2518, -219, 1216, 2950, 769, -6634, -1664, 1267, 2254, 1212, -4126, -3522, 954, 1146, 1796, -4887, -2688, 562, -252, 2150, -5063, -1078, 15, -607, 1798, -1354, 64, -2422, 1217, -1222, 2356, -549, -826, 1359, 46, 2528, 77, 703, 1093, 540, 2047, 385, 1584, 810, 575, 906, 905, 1793, 607, -30, -280, 928, 1335, 127, -2231, -579, 524, 372, -1104, -3372, -1242, 594, -759, -2885, -1276, -2669, 1271, -2051, -1787, -2151, 731, 1607, -3941, -142, -2902, 2755, 1031, -2410, 257, 526, 3356, 338, 368, -416, 1648, 3127, 1169, 1554, -883, 1187, 2447, 1919, 1349, 35, -355, 1505, 2010, -49, 491, -1493, 290, 1885, -1012, -189, -706, -1402, 1835, -653, -1342, 414, -4049, 1445, -1380, -835, 1399, -2753, -656, -1061, 407, 2389, 328, -5594, 1578, 1699, 3256, 1557, 1803, 3104, 2721, 3595, 1262, 3600, 3538, 2988, 3157, -425, 3530, 3049, 2241, 2007, -2748, 1807, 1702, 292, 913, -2749, -1753, -271, -1737, 416, -410, -2780, -2211, -796, -825, 738, -3053, -3166, 224, -4159, 388, -6781, -1350, 778, -7538, -684, -6021, 40, 794, -8075, -1196, -2613, 194, 186, -5381, -1710, -796, -846, -876, -3076, -2264, 450, -3535, -2173, -2795, -2610, 1111, -3248, -2985, -3229, -2763, 942, -1127, -3091, -2968, -2029, -564, -957, -3445, -2602, -2077, -4367, -1931, -2600, -3586, -4953, -599, -2966, -1270, -6257, -3913, 1906, -3599, -1194, -3077, -125, 2630, -4263, -2647, -1461, 1024, 1879, -4804, -1485, -2161, 636, -401, -5464, 880, -7517, -1091, -1523, -7686, 1802, -3875, -3391, -522, -10960, 1715, -893, -3458, 65, -4600, 963, 83, -1659, 494, -638, -385, 426, -37, 215, 1234, -2347, 531, 777, -961, 1538, -3032, 550, 806, -2996, 382, -1489, 670, 104, -6353, -2430, -72, 764, -1070, -7499, -7218, 711, 512, -2166, -6543, -16015, 894, -116, -4145, -8256, -4972, 799, -1035, -9862, -3472, -1895, 662, -2096, -2376, -442, -683, 312, -2580, -257, 980, -586, -284, -2829, 219, 1468, -997, -665, -3893, -358, 1381, -1313, -924, -5072, -1739, 1043, -1979, -2041, -4316, -4271, 900, -3999, -5376, -3714, -10667, 1246, -9268, -12061, -4294, -2703, 1723, -5847, -6724, -5843, -451, 1670, -3115, -8155, -5466, -5, 553, -2213, -8196, -3675, -928, -2179, -2481, -5031, -2801, -2871, -5236, -2656, -4252, -2905, -3313, -4565, -1879, -5726, -3708, -2167, -4952, -1631, -9692, -4346, -1480, -4648, -2599, -3388, -4863, -1423, -3280, -5618, -1103, -6256, -2118, -2033, -7619, -369, -4822, -3878, -1391, -3919, -476, -2701, -7312, -1380, -2864, -804, -2024, -5814, -1760, -2468, -1219, -2327, -3750, -2191, -2058, -2263, -2831, -3560, -2300, -2160, -4133, -2731, -4973, -1943, -3298, -4746, -2163, -8332, -1633, -5245, -3793, -1897, -9267, -2145, -4547, -3877, -2678, -7678, -4342, -3610, -5656, -5583, -6145, -6009, -4297, -9752, -11844, -3874, -3231, -9564, 3317, -1712, 2495, -249, -4231, 2333, -4860, 1441, -2319, 472, 214, -2134, 332, -6326, 2920, -5387, -2290, -772, -1964, 3892, -958, -9231, -1652, 802, 3680, 1596, -2025, -1339, 1828, 2542, 1900, 188, -1396, 1656, 1022, 311, 218, -2450, 361, -494, -5238, -143, -2696, -2148, -2685, -3968, 428, -2002, -5779, -3974, -1723, 596, -1375, -7355, -2275, -1966, -382, -1209, -4313, -1981, -1460, -2295, -2147, -1661, -4310, -181, -3322, -3900, 111, -7570, -182, -3673, -3565, 1099, -2872, -1643, -4352, -1997, 1367, -1554, -2401, -4965, -514, 875, -433, -1869, -6022, 566, -330, 1229, -3502, -2602, 1703, -1157, 2667, -3167, -378, 2998, -711, 3240, 137, 101, 3765, -609, 2728, 1359, -902, 3624, -1976, 1083, 1316, -2345, 2389, -8600, -1322, 389, -1026, -309, -758, -3238, -266, 437, -6312, 2126, -4703, 816, 1101, -3475, 3235, -5948, 1770, 967, -999, 3122, -5564, 1828, -395, -227, 1573, -3359, 1194, -5735, 255, -3600, -2273, 303, -2483, 1032, -1824, -2752, -632, 326, 1326, 840, -5005, -1329, 466, 820, 941, -4284, -1794, -1498, -222, -125, -1421, -2664, -5865, -1489, -924, 146, -2813, -1618, -2149, -70, 669, -2351, 367, -1519, 961, -46, -1477, 1177, -1038, 1226, -1699, 628, 1361, -486, 532, -76, 2150, 963, 527, -1000, 1627, 2592, 101, 1346, -1927, 2020, 1908, -700, 1647, -1514, 1653, -332, -1236, 1406, -1411, 1325, -10068, -989, 667, -924, 1690, -1303, 515, -409, -10, 2410, 1293, 1728, -1478, -109, 2706, 2163, 2160, -2210, -2149, 2184, 1921, 1908, -2428, -9430, 658, 573, 1130, -1598, -8966, -2020, -2038, -112, -240, -6766, -3364, -3674, -1602, 690, -1499, -2217, -1771, -1832, 920, 140, -2417, -677, -1264, 421, -87, -4587, -576, -1291, -567, -1831, -8048, -1305, -1898, -875, -4965, -3671, -2780, -2956, 215, -9928, -2334, -4840, -3151, 960, -8429, -2557, -4926, -2364, 391, -4029, -3040, -2353, -2119, -1905, -2826, -2297, -703, -1551, -2284, -3370, -806, -431, -283, -701, -2411, 257, -1976, 712, -781, -110, 523, -5822, 1049, -1996, 1024, 18, -2396, 621, -3525, 1091, -1011, -1452, -564, -4353, 241, -1537, -3027, -1276, -3894, -1498, -1273, -1980, -230, -3036, -4200, -1669, 593, 335, -2142, -8792, -3426, 1475, -195, -1508, -9505, -5679, 1171, -1675, -1465, -6397, -4053, 5, -4040, -2016, -6187, -2771, -1603, -8102, -3353, -6786, -2667, -2941, -7881, -5242, -6067, -3708, -3427, -6175, -3917, -4149, -5051, -3540, -5787, -2668, -2366, -3368, -4009, -4915, -2502, -1633, -1766, -4810, -3513, -2509, -2258, -1212, -5520, -2392, -2325, -4518, -1430, -6411, -2023, -2446, -5615, -2144, -7517, -2545, -2686, -4291, -2848, -6527, -3844, -1880, -4841, -1145, -145, 628, 475, 457, -2957, -10, -1570, 1391, -133, -4206, 52, -6385, 1664, -1805, -3079, 145, -4327, 1253, -3114, -1486, -819, -975, 374, -2454, -1235, -5610, 467, -293, -1797, -3162, -3606, 815, -758, -304, -3796, -1578, 354, -1073, 797, -583, -2625, -499, -771, 551, 92, -2287, -1511, -778, -390, -1734, -786, -2860, -1886, 191, -5805, -598, -3619, -3831, 690, -130, -1444, -1214, -2643, 209, 1606, -3083, 1408, -614, -1114, 2381, -4094, 2906, 633, -6743, 2871, -2164, 3295, 1471, -1532, 2341, -551, 2600, 1803, 1710, -254, -1350, 670, 852, 2520, 1150, -2959, -1344, -3412, 1716, 3180, 1734, 1280, -675, -265, 2878, 3379, 3075, 1577, 593, 564, 3251, 3563, 1385, 2170, 651, 1874, 3033, -583, 2850, 2123, 884, 1686, -4414, 3101, 1837, 1719, -398, -9515, 2822, 99, 2401, -3167, -4597, 1589, -2826, 2676, -4771, -1401, -138, -5814, 2910, -6350, -610, -104, -6063, 3013, -8985, -1488, -619, -3875, 2957, -8283, -2294, -2217, -1501, 3230, -2237, -1782, -1127, 361, 3596, 688, -1570, -753, 1476, 3297, 1530, -1263, -1992, 1754, 1762, 584, -332, -3281, 1156, -2419, -2802, 614, -2246, -349, -3108, -5652, 727, -1032, -2545, -441, -2741, -363, -1151, -3433, -692, -2244, -2517, -3094, -2801, -2605, -2152, -2148, -5145, -2558, -3874, -1905, -258, -4390, -2293, -3149, -1464, 888, -6111, -1497, -3126, -774, 1634, -5495, -650, -2098, -295, 1935, -2774, -379, 67, -790, 1403, -1358, -1010, 1457, -3443, -11, -51, -2306, 1889, -3109, -284, 1057, -4607, 1583, 263, 789, 1584, -6906, 976, 1375, 1056, 1371, -1678, 582, 1247, 544, 460, -635, 136, 304, -188, -774, -1331, -1029, -952, -1160, -2151, -918, -1051, -1310, -2378, -3368, 140, 174, -419, -310, -2190, 673, -106, 227, 1558, -1586, 1039, -2416, -134, 2027, -2991, 893, -6580, -1703, 1269, -6484, -115, -5723, -4105, -856, -2971, -2238, -3554, -6704, -5229, -939, -6743, -2910, -7597, -3618, -429, -10337, -4056, -6796, -1566, -1561, -6673, -4428, -12669, -1216, -7896, -6061, -3668, -2993, -1485, -2882, -5866, -4362, -584, -1137, -280, -6184, -5742, -232, -590, 311, -7151, -6190, -1667, -693, 372, -10047, -5120, -7048, -1029, 73, -10798, -3369, -4997, -1002, -1285, -5770, -2927, -2547, -1148, -2374, -4233, -4789, -2791, -1988, -447, -4173, -8613, -4557, -3999, 457, -4995, -3105, -6255, -7731, -100, -6188, -1730, -7142, -5266, -2370, -6593, -2111, -11767, -3767, -5091, -5145, -3803, -7493, -3824, -2533, -4008, -6733, -4307, -4295, -1719, -4287, -10252, -3294, -4072, -2339, -5571, -8014, -3507, -3417, -3899, -3474, -6660, -4456, -2442, -6205, -1628, -7007, -4803, -1214, -10809, -1319, -8609, -4288, -465, -10738, 11098, 5212, 12300, 10731, -13274, 10442, 6685, 11667, 10185, -5310, 8302, 7186, 9625, 8459, -3020, 3785, 5776, 5462, 5253, -2244, 1023, 3996, -1424, 287, -1736, 2976, 4149, 407, -1784, -605, 3079, 3114, -722, 661, 89, 2958, 784, -5, 1303, 325, 3135, 1756, -86, -672, 1340, 3989, 2726, 137, -26, 2416, 4821, 2709, 1082, 3029, 3017, 4752, 3030, 538, 4385, 3491, 3277, 4047, -3489, 4673, 3810, -348, 4441, -1135, 3980, 3758, 216, 3628, 293, 2357, 3336, 1802, 1749, -2091, 829, 2509, 1505, 768, -891, 395, 811, 631, 636, 1899, 109, -4455, 226, -296, 2648, 168, -1596, -540, -1523, 2391, 272, 1368, -1774, -3220, 1437, 265, 1752, -1880, -5949, -332, 528, 741, -1641, -3799, -3154, 1030, -656, -1690, -2449, -3611, 1340, -1832, -1245, -2534, -2997, 1490, -4817, -374, -2040, -4587, 1682, -2789, -169, -908, -9040, 1674, -187, -1274, -1075, -8328, 1255, 257, -3880, -3698, -4611, 584, -873, -5979, -5615, -2235, 163, -3707, -9433, -1926, -1347, 160, -9210, -7969, -1200, -1870, 103, -12453, -4893, -2052, -4712, -220, -7170, -5432, -4455, -7397, -715, -3549, -7741, -7953, -2554, -1232, -1773, -5242, -5832, -1528, -1503, -1547, -2831, -3492, -2060, -1501, -3042, -1437, -1902, -3381, -1917, -4839, -896, -1487, -4409, -3751, -2231, -1335, -2925, -5361, -9173, -752, -2493, -11578, -7925, -5094, -347, -2519, -3585, -18176, -3398, -604, -1625, -1877, -10374, -3873, -1355, -1285, -2854, -12016, -6563, -2503, -1518, -6327, -12043, -7376, -3559, -2105, -3820, -7938, -4767, -3599, -2760, -2402, -6678, -4353, -3201, -3089, -2845, -6013, -5385, -3098, -2942, -4488, -4418, -8138, -3288, -2847, -6622, -2408, -14394, -3652, -3416, -8079, -1161, -5638, -4190, -4624, -8116, -831, -2668, -4954, -5222, -6976, -1189, -1206, -5770, -5339, -5479, -1860, -828, -5995, -6444, -4132, -2620, -1298, -5463, -7908, -3071, -3510, -2244, -4449, -6470, -2511, -4811, -3266, -3517, -4756, -2817, -6980, -3990, -3400, -4214, -4423, -6924, -3501, -4595, -5061, -7353, -5594, -2586, -6687, -5601, -7305, -5826, -2433, -5014, -4189, -6156, -7004, -3291, -3297, -3931, -4989, -7679, -4740, -2520, -5206, -4326, -7732, -5585, -2025, -5975, -4052, -6323, -7057, -1360, -4578, -2613, -4732, -12016, -683, -3435, -1212, -4410, -7504, -294, -2585, -828, -5621, -6556, -375, -2187, -1415, -5592, -8070, -1032, -2424, -2718, -3489, -9643, -1973, -3028, -4759, -3094, -7536, -2619, -3475, -9114, -5000, -4308, -3469, -3501, -6100, -6687, -2197, -4270, -3029, -3362, -3660, -1111, -3131, -3031, -2650, -3297, -786, -2407, -4677, -3325, -5145, -1064, -3122, -10750, -5078, -6277, -1863, -5590, -9095, -6716, -4257, -3437, -10057, -8470, -7109, -3506, -7310, -10609, -11511, -6290, -2969, -8178, -5305, 1585, 3305, 8481, 3947, -7373, 857, 2438, 7871, 4483, -5163, -1996, -93, 5893, 4989, -1325, -1659, 841, 2403, 4908, 1273, 2099, 2461, 2031, 4779, 2616, 3751, 2638, 2640, 5051, 3061, 4361, 2355, 1685, 5346, 2837, 4441, 2016, 406, 5189, 2082, 4328, 247, 1849, 4410, 1080, 4039, -3195, 3468, 3163, -336, 4027, 2040, 4662, 1497, -3365, 4988, 3859, 5658, -982, 38, 5693, 4172, 5994, -1242, 3006, 5278, 3567, 5174, -822, 4260, 3458, 2747, 2548, -2184, 4354, 706, 2516, 58, -2813, 3520, 445, 2291, 2562, -2896, 2005, 192, 1550, 2941, -4081, 194, -869, 734, 1859, -4434, -1360, -785, 930, 155, -3206, -2027, 300, 1899, -530, -2885, -1699, 1254, 2444, 93, -5182, -1408, 1767, 2207, 423, -10119, -1961, 1778, 1408, -459, -6219, -2644, 1226, 771, -1880, -1894, -2940, 111, 722, -634, 805, -3221, -589, 873, 577, 1830, -1550, 239, 766, 783, 1632, -334, 995, 95, 209, 354, -388, 892, -717, -877, -2339, -1423, -500, -449, -1883, -4972, -3426, -5195, -1, -1938, -2367, -8461, -3421, -187, -1485, -1279, -4852, -866, -240, -1510, -1196, -1826, -1293, 206, -2200, -1447, -684, -4666, -29, -3118, -1524, -475, -6737, -1703, -3556, -973, -677, -4775, -4770, -3481, -59, -841, -4117, -4457, -3387, 502, -1063, -2478, -3343, -3405, 513, -1847, -1872, -2763, -3513, 216, -3158, -1954, -3293, -3491, 6, -1841, -2078, -6307, -3108, -39, -34, -2676, -4200, -3202, -70, 295, -4143, -1613, -4699, 133, -1057, -5056, -933, -8726, 735, -5222, -4775, -1032, -7064, 1143, -6540, -5723, -1051, -4089, 856, -4798, -7549, -1215, -2400, -195, -7213, -5635, -2425, -1542, -1435, -6176, -4819, -4529, -1232, -2289, -3326, -6213, -3064, -863, -4036, -3085, -8323, -2295, -451, -4993, -4715, -5061, -4020, -749, -2752, -3877, -3576, -6565, -1875, -2479, -2051, -3764, -3560, -2217, -3992, -1880, -5381, -3341, -1708, -5812, -3022, -4445, -4321, -1992, -6653, -5129, -2650, -3498, -3241, -5129, -7028, -2528, -2897, -4728, -3051, -5802, -4167, -3519, -5969, -2871, -4319, -7325, -4670, -9996, -4331, -3595, -4791, -4604, -7482, -4786, -3318, -3351, -3509, -5488, -4479, -3763, -3662, -3008, -6282, -6129, -6270, -5514, -3122, -7904, -5156, -9061, -7791, -2629, -5439, -3320, -3932, -5454, -1852, -3039, -2650, -2778, -3742, -1820, -1611, -1754, -3548, -3505, -2607, -1143, -1164, -7063, -4740, -3944, -1745, -1874, -6602, -7379, -5275, -3118, -4641, -2947, -5731, -4220, -3162, -4582, -1783, -3739, -2276, -2644, -2088, -1782, -3252, -1601, -3260, -1424, -2322, -3649, -2494, -4660, -1975, -3063, -4196, -5663, -5993, -3845, -3228, -4619, -8550, -9567, -6095, -2124, -4831, -5158, -8780, -3685, -1638, -4736, -3700, -5019, -2600, -2706, 3707, 2638, 6935, 2367, -409, 2736, 2365, 6486, 3751, 2168, 1377, 1343, 5470, 4876, 3115, 3163, -681, 4488, 4624, 1773, 4089, -697, 2993, 2655, -2576, 3762, 1709, 329, -2962, -906, 2292, 2976, 233, -1112, 746, -870, 3029, 587, -145, 458, -5764, 1947, 2, -1787, -2017, -2262, -4, 430, -2562, -3108, -14, -1930, 1231, -1716, 1821, 1788, -2410, 1649, -1517, 3826, 2804, -1236, 1710, -143, 4544, 3057, -441, 1395, 1775, 4359, 2635, 418, 578, 2847, 3582, 1434, 1425, -1172, 2693, 2857, -1028, 1644, -3601, 1070, 2653, -6563, 865, -687, -76, 2631, -10669, -513, 830, 1328, 2475, -6428, -1739, 525, 1282, 2073, -2958, -2828, -1301, -1020, 1441, -2750, -4133, -3430, -16441, 646, -4168, -2603, -3920, -2047, 242, -486, -225, -4235, -270, 624, 1024, 1000, -3784, 359, 546, 493, 1237, -3623, 640, -679, -2010, 381, -3130, 969, -2732, -3305, -2278, -1646, 1447, -3567, -2123, -7752, -834, 1559, -1510, -2701, -3584, -997, 908, 148, -4190, -2956, -1853, -521, 587, -4177, -3973, -2802, -2053, 103, -3373, -5826, -3259, -2014, -1133, -3022, -7751, -3502, -801, -3851, -2864, -7128, -4058, 12, -6858, -2197, -5368, -4733, -156, -2515, -1500, -4914, -3531, -1289, -1601, -2129, -5401, -1761, -934, -3359, -5833, -5855, -929, 961, -7624, -2855, -4490, -885, 1960, -1611, -733, -2348, -960, 2037, 345, -1164, -1348, -729, 1452, 1044, -3845, -1594, -613, 382, 974, -4552, -3003, -778, -1558, 95, -3389, -5396, -859, -5068, -1692, -3932, -3957, -712, -2859, -2906, -4352, -1844, -920, -1314, -2445, -3971, -1383, -2114, -710, -2151, -3884, -2316, -5126, 123, -1625, -4171, -3896, -7733, 660, -1102, -4685, -3933, -2734, 588, -702, -5475, -3649, -655, 67, -528, -6936, -4077, -101, -1149, -1218, -10007, -4253, -984, -4323, -3259, -7527, -2958, -3909, -5933, -3525, -3866, -1383, -6203, -2006, -1102, -2139, -615, -2993, -907, 107, -2018, -870, -1857, -1267, 143, -3948, -1987, -1685, -2792, -1038, -8334, -3092, -2154, -4408, -3392, -4299, -3602, -3363, -4114, -3630, -3513, -4155, -6059, -3263, -2461, -5321, -4200, -9254, -2273, -2403, -14087, -3900, -5744, -1227, -3193, -4042, -4117, -5267, -476, -3996, -1661, -4803, -7994, -240, -3732, -892, -5842, -10145, -634, -3205, -1265, -7545, -5716, -1846, -2950, -2523, -9839, -4877, -4653, -3034, -3705, -7522, -4084, -5418, -3877, -4613, -4659, -3178, -2218, -5807, -7387, -3785, -3515, -1403, -8260, -11497, -4984, -6182, -2172, -9360, -6346, -6504, -6892, -4239, -7743, -4428, -4122, -4123, -6879, -7008, -3190, -3511, -4579, -10967, -6432, -2575, -3400, -5683, -7842, -4646, -2471, -1945, -3157, -3757, -4293, -2553, -1025, -2473, -2903, -5273, -2585, -1288, -3610, -4283, -4097, -9523, -5943, -2164, -5581, -2444, -7776, -7923, -2002, -6584, -1324, -6893, -10160, -3126, -8249, -1242, -5853, -5730, -6185, -7069, -1318, -4999, -4494, -11606, -4761, -1033, -4625, -4512, -9209, -2764, -895, -4675, -5093, -5432, -2392, -906, -5316, -6753, -2629, -4217, -506, -7343, -12258, -1117, -18640, -111, -9723, -7977, -691, -4660, -501, -6642, -6882, -1346, -3457, -2156, -5205, -9530, -3231, -4659, -6435, -3930, -12152, -6519, -8626, -5634, -3154, -7490, -9589, -6737, -2102, -3723, -7020, -9157, -4072, -731, -5013, -8657, -9415, -2941, -398, -4607, -10880, -9679, -2876, -754, -5311, -14843, -9054, -4567, -1638, -14356, -6364, -8733, -13294, -3056, -4994, -2996, -4463, -5328, -4725, -2286, -1904, -2246, -4056, -4127, -1121, -2429, -1557, -5177, -2582, -734, -4504, -1938, -7300, -2004, -1035, -7966, -3344, -7584, -2366, -1927, -7388, -7014, -5819, -3508, -3280, -5943, -7778, -3259, -5056, -4883, -5403, -3711, -1761, -6577, -5724, -3812, -2815, -1334, -10214, -6432, -2134, -3513, -1800, -7198, -8335, -1299, -5112, -3064, -4323, -6722, -1216, -6206, -5131, -3659, -5068, -1666, -8050, -8021, -4004, -4996, -2605, -8072, -11208, -4015, -6186, -4652, -4438, -10588, -3273, -8792, -9297, -3155, -7707, -2889, -9015, -5467, -3343, -5270, -3625, -6067, -3545, -4613, -3311, -6748, -5065, -2944, -6260, -2057, -9865, -6187, -2925, -7114, -1475, -5008, -6917, -3686, -7323, -1268, -4218, -3167, -5852, -7615, -1271, -4439, -1312, -6944, -8678, -1771, -3908, -680, -4782, -8846, -3161, -3446, -825, -4036, -8856, -5418, -4445, -1466, -4437, -10779, -6813, -5622, -2382, -5802, -4930, -7126, -3128, -3724, -7505, -1874, -8631, -1671, -6449, -8103, -453, -13228, -1267, -9744, -7564, -269, -10195, -1356, -6865, -6983, -1270, -7884, -1598, -7550, -8264, -3377, -6582, -1809, -13209, -10664, -5900, -4933, -2029, -6603, -7333, -6637, -3141, -2649, -4805, -5579, -4607, -2065, -3786, -4159, -4530, -3556, -1958, -4434, -4021, -3946, -3579, -2653, -4115, -5443, -4218, -3204, -3892, -4038, -9143, -6128, -2134, -4915, -5295, -4613, -13797, -1494, -3796, -8152, -2934, -8834, -1618, -2501, -3860, -2776, -7296, -2660, -1837, -2081, -3349, -6771, -4973, -1725, -2184, -4176, -7035, -10012, -2470, -3850, -4867, -10270, -8530, -4484, -7644, -4945, -11567, -5452, -7947, -13246, -4593, -7648, -4465, -13331, -8972, -4690, -7031, -4486, -11865, -9795, -5755, -7391, -4672, -9503, -9418, -6950, -7780, -4682, -16058, -7030, -6089, -6621, -4720, -7791, -5977, -5453, -5265, -4802, -5117, -5921, -6064, -4721, -5110, -5085, -8222, -8408, -4431, -5728, -7469, -7815, -12098, -3763, -6161, -10741, -3895, -8584, -3051, -5790, -8524, -2729, -7566, -2674, -5077, -9058, -3014, -8564, -2654, -4944, -7027, -4310, -8408, -2854, -6054, -5405, -6337, -6067, -3169, -7725, -5604, -8646, -5427, -3730, -6045, -7173, -9349, -5644, -2745, -4435, -3255, -5100, -10319, -2409, -5707, -5709, -3217, -4289, -2904, -8567, -10219, -1759, -1428, -4532, -10403, -10345, -2067, -360, -8814, -11601, -8343, -3550, -360, -6021, -10113, -5433, -2952, -1047, -2621, -6476, -3020, -2146, -2014, -1286, -3590, -1799, -3138, -3347, -1293, -2157, -2028, -4382, -6207, -2485, -2222, -3986, -3157, -6363, -4376, -3953, -6302, -2993, -3178, -4933, -8381, -5066, -4482, -2127, -4846, -12400, -4240, -7919, -2555, -6214, -8454, -3503, -7013, -4322, -5684, -6272, -2668, -4389, -4535, -3199, -3959, -1933, -3414, -2477, -2617, -2243, -1718, -3123, -1327, -3827, -1305, -2294, -2093, -1066, -7001, -1076, -3850, -801, -1632, -8388, -1685, -6329, -498, -2998, -7507, -3648, -5368, -1515, -4982, -7466, -7383, -3325, -2655, -7653, -7390, -5273, -2413, -1555, -14324, -6261, -3707, -2532, -1035, -9651, -4787, -3281, -3732, -1629, -5854, -4420, -3728, -5714, -2317, -4014, -5483, -5742, -5663, -2378, -3529, -7319, -8604, -4638, -3085, -4334, -6198, -5104, -4462, -5674, -6502, -5078, -3689, -4555, -14132, -11050, -5171, -3450, -4259, -13545, -9341, -5933, -3294, -3862, -8457, -5184, -6151, -2572, -4167, -4497, -3611, -5143, -1653, -5473, -3356, -3468, -3974, -1278, -6098, -3895, -4212, -3747, -2331, -4030, -5500, -5145, -5045, -7589, -2336, -6391, -5749, -7203, -4400, -1870, -5463, -6348, -6143, -2208, -2193, -4082, -7322, -4906, -2997, -1735, -2751, -4971, -3830, -7372, -806, -1731, -2704, -3698, -7334, -695, -1307, -1781, -5715, -4778, -1785, -1633, -1760, -9078, -4864, -4826, -2603, -2323, -4936, -5444, -10881, -3398, -3460, -4051, -6080, -4726, -3330, -5913, -4514, -9708, -2940, -3278, -9419, -5049, -7931, -2193, -3486, -4353, -4575, -4653, -2333, -3719, -1933, -3317, -4288, -3790, -4057, -585, -2619, -6018, -6452, -4951, -5, -3009, -13340, -4646, -7322, -224, -4531, -8298, -3373, -11910, -1415, -6536, -5687, -3711, -8413, -4246, -7867, -4259, -5131, -4938, -8504, -10451, -3386, -6804, -2993, -4161, -10671, -3469, -9349, -2556, -2815, -8378, -5085, -9094, -3620, -2359, -9030, -9748, -5670, -6663, -1707, -10671, -5964, -4925, -6982, -1238, -6904, -4084, -6098, -4870, -1593, -4780, -4367, -8449, -4262, -3044, -3837, -7028, -7802, -3321, -5930, -3460, -13684, -7987, -2254, -10288, -3088, -6700, -13398, -1980, -7907, -2537, -5443, -5852, -2529, -5309, -2281, -5477, -3144, -3454, -3354, -2779, -6270, -2284, -3982, -2010, -4131, -8456, -2577, -3993, -1443, -5248, -14405, -3869, -3884, -1780, -5301, -7072, -6484, -3667, -3182, -6687, -4773, -11855, -3411, -6299, -13380, -4030, -9727, -3625, -13249, -6993, -4150, -8273, -5127, -5833, -5646, -4561, -7768, -9798, -3523, -7344, -4823, -7563, -9133, -2409, -13634, -5072, -8797, -8460, -2152, -6157, -5646, -14285, -14051, -2812, -4474, -6838, -10685, -8765, -4529, -4371, -9026, -8921, -7190, -2538, -2793, -5336, -3947, -3232, -2447, -6203, -5527, -1346, -4646, -2657, -11648, -5577, -289, -7774, -3120, -5916, -4942, -409, -4535, -2327, -3789, -3437, -1664, -3652, -1306, -2676, -2158, -4312, -5043, -1433, -2688, -1550, -4704, -12021, -2924, -4046, -1718, -2938, -6369, -5811, -5486, -2140, -2456, -4418, -9238, -4771, -1672, -2623, -5173, -7536, -5012, -1027, -2916, -7563, -5388, -6455, -1047, -3534, -5747, -3857, -6470, -1762, -6188, -4386, -2362, -5764, -3270, -7302, -3486, -1317, -5339, -5938, -2043, -2596, -977, -5002, -5752, -567, -2031, -1364, -5686, -4356, -871, -1595, -2485, -9444, -4559, -3048, -1263, -4310, -9670, -4284, -9537, -1203, -5912, -6224, -3258, -4981, -1598, -5220, -6752, -3456, -3016, -2725, -4270, -13093, -3992, -2290, -3813, -4408, -7856, -1929, -1810, -2808, -6610, -6766, -300, -1490, -1837, -12281, -9620, 182, -1437, -1396, -4540, -5758, -268, -1434, -1067, -2260, -3563, -1245, -1335, -1237, -1190, -3551, -1476, -1500, -2333, -991, -4916, -812, -2049, -2009, -1888, -4600, -483, -2455, -390, -4537, -3079, -788, -2471, -38, -8360, -2618, -1859, -2379, -449, -5758, -2959, -4411, -2219, -90, -6016, -3160, -7765, -2225, 307, -9508, -2980, -4024, -2636, -255, -5505, -3532, -2875, -3524, -1276, -2591, -5988, -3067, -5231, -1555, -1350, -8221, -4186, -8034, -1763, -1154, -3675, -7696, -8156, -2892, -1762, -1783, -8195, -7268, -4659, -2969, -1119, -3649, -6626, -3255, -4262, -1365, -2163, -6289, -1846, -4546, -1670, -1498, -6156, -1979, -4453, -425, -943, -4181, -3783, -5071, 723, -488, -2102, -7526, -5890, 759, -454, -991, -7736, -5490, -412, -1108, -886, -9249, -5507, -2500, -2611, -1753, -11330, -8110, -3541, -4951, -3085, -6498, -11560, -2818, -6163, -3838, -5476, -7744, -1613, -4473, -4503, -4895, -10538, -787, -3815, -4152, -4471, -9289, -772, -5325, -2438, -4617, -7042, -1681, -12156, -1011, -4078, -11124, -3652, -4463, -221, -3429, -6484, -6516, -2117, -224, -4362, -3413, -8298, -1303, -1142, -8465, -2652, -10619, -1620, -3147, -4694, -2958, -9320, -3078, -5244, -2625, -3493, -7538, -4728, -4215, -2782, -3538, -7417, -5557, -4010, -5181, -3169, -3829, -6440, -6266, -8421, -2777, -1878, -4202, -11497, -4542, -2452, -1751, -2812, -4234, -3385, -2148, -2715, -2843, -2160, -3604, -1954, -2837, -3958, -1415, -4855, -2031, -2412, -5695, -1431, -6987, -2535, -2219, -6285, -1866, -8006, -3450, -1908, -5988, -2553, -5303, -4148, -2209, -7158, -3775, -2744, -4606, -3348, -12623, -6204, -1360, -6610, -3959, -7071, -11644, -1069, -13710, -4590, -5496, -9894, -1583, -5968, -8329, -6387, -6163, -2172, -4522, -6894, -9424, -4457, -2212, -4798, -3904, -7938, -4179, -2202, -6264, -3431, -5745, -5168, -2666, -9482, -4409, -5407, -7155, -4061, -10419, -6791, -6801, -8847, -7855, -5501, -8849, -10972, -7787, -7849, 11195, 15123, 10025, 6099, 8571, 11019, 14694, 9644, 5733, 7741, 10391, 13372, 8577, 4369, 4786, 9563, 11038, 6931, 1192, -2344, 9374, 7356, 4436, -3542, 1962, 9099, 3349, 1630, -2046, 1944, 7586, 6115, 2811, -531, 935, 5291, 7372, 2914, 1121, 1036, 6408, 7321, 1143, 1454, 2072, 7296, 6291, 1497, 1177, 3087, 6928, 5468, 3598, 1443, 4050, 5664, 5714, 4290, 2105, 4939, 3856, 6142, 3746, 2319, 5591, 727, 6849, 1885, 1557, 5915, -7395, 7137, -2519, -389, 5801, -1126, 6483, -4415, -2680, 5201, -1921, 4721, -769, -2403, 4188, -739, 1647, -162, -594, 2599, 794, 821, -656, 91, -466, 1178, 2644, -1822, -1098, -11217, 1390, 3262, -1618, -5779, -4820, 1147, 2935, 896, -7053, -5800, -464, 1555, 2522, -6062, -6045, -5268, -1479, 3020, -9656, -3864, -1743, 964, 2638, -5107, -3853, -203, 3374, 1760, -4036, -6396, -1279, 3921, 776, -4029, -16551, -3809, 2968, -236, -3220, -8143, -3589, 368, -1465, -2442, -7889, -10233, -2711, -3780, -2795, -5569, -709, -936, -8300, -5686, -3273, 2446, 737, -3423, -7181, -2279, 3543, 1442, -1155, -2180, -1762, 3392, 861, 137, -815, -746, 2232, -1795, 961, -896, 52, 239, -5979, 1433, -1863, -189, -2099, -897, 1622, -3121, -1718, -3985, 551, 1557, -3537, -2905, -5520, 686, 1261, -2232, -1677, -7394, 27, 715, -885, -1237, -8488, -1059, -213, -377, -2039, -4980, -2121, -1747, -830, -4073, -2595, -3249, -4097, -2325, -6630, -1691, -4229, -7405, -4772, -5486, -2005, -3586, -7187, -7279, -4017, -3260, -3248, -4533, -7752, -3357, -5022, -4191, -3047, -4702, -3228, -5988, -5489, -2174, -3104, -3376, -4316, -6122, -1603, -2904, -3414, -2785, -8958, -1317, -3641, -3062, -2009, -8828, -1351, -4858, -2576, -1824, -4507, -1595, -6319, -2447, -2153, -3322, -1869, -7238, -2943, -2892, -4009, -2192, -6063, -3927, -4048, -7471, -2810, -5060, -5006, -6336, -7996, -4013, -5153, -6513, -12027, -5008, -6226, -6290, -9703, -6730, -4456, -10684, -7420, -12876, -5063, -4618, -8828, -6957, -13355, -4465, -4695, -6007, -6580, -10569, -3031, -4757, -4748, -6951, -6650, -1852, -5345, -4392, -8115, -5484, -1897, -6110, -5073, -11001, -5880, -3632, -5574, -7318, -9674, -5604, -9235, -5218, -9011, -7118, -4163, -8010, -6298, -7697, -7118, -3950, -7467, -7900, -8856, -9572, -5670, -9525, -7093, -9777, -8870, -11966, -4224, -6722, -7543, -6720, -9695, -2019, -7078, -7268, -6368, -8813, -1415, -6884, -7908, -6644, -10736, -2124, -5611, -8390, -6536, -9810, -4488, -4537, -9472, -6533, -7881, -9121, -4070, -12403, -7430, -6232, -5549, -3898, -14521, -8280, -5120, -4089, -3925, -8328, -6393, -5058, -4425, -4379, -6126, -4521, -6278, -5827, -5537, -5533, -3452, -9027, -5927, -8372, -6073, -3144, -11883, -5083, -12795, -7374, -3693, -10706, 7471, 1317, 4615, -14033, 6451, 6761, -946, 3861, 2250, 6218, 4361, 2064, 1361, 3975, 5565, 1245, 4653, -2752, 3802, 4901, 3821, 4949, -1612, 2915, 4689, 5122, 3530, -928, 2833, 4410, 5379, 619, -784, 3273, 3654, 5126, 1850, -228, 3372, 2809, 4595, 4245, 1260, 3195, 2679, 3317, 5555, 3236, 3066, 3585, 2570, 6007, 4835, 3199, 5060, 5802, 5615, 5821, 3574, 6185, 7650, 4281, 6151, 3833, 6600, 8050, 1836, 5719, 3310, 6301, 7191, -1342, 4359, 947, 5430, 4988, -2155, 1953, -4581, 4275, 1230, -1996, -855, 1888, 3139, -1090, -3080, -2669, 3627, 1920, -848, -2718, -4740, 3998, -120, -600, -370, -6840, 3703, -4798, 942, 482, -5468, 3139, -1418, 2099, 270, -1744, 2580, 254, 2134, 83, 206, 1939, -599, 1174, 971, 901, 592, -4386, -109, 2158, 709, -1687, -3201, -668, 2771, -56, -1057, -2015, -653, 2568, -1020, 370, -4131, -1203, 1562, -1873, 813, -8413, -3746, 260, -2548, 481, -4924, -3734, 66, -3146, -998, -6771, -975, 696, -3602, -5177, -5184, -1115, 1081, -3284, -2797, -2198, -5771, 1062, -1997, 6, -1363, -1954, 769, -720, 941, -1541, 928, 396, -202, 718, -2197, 1581, 51, -822, -701, -3020, 1164, -226, -3019, -3831, -3029, 261, -275, -7997, -4819, -2221, -863, -369, -19659, -2074, -2177, -2305, -1211, -8690, -561, -3244, -3692, -3153, -4836, 423, -3537, -3659, -4844, -3733, 1030, -1982, -2668, -3175, -3808, 1179, -958, -1967, -1121, -3089, 819, -892, -1758, -304, -2016, 0, -1850, -1648, -1034, -1839, -1084, -3559, -1352, -3952, -2599, -2187, -4248, -1182, -6726, -3883, -3331, -3728, -1352, -4597, -5022, -4866, -3655, -1972, -5668, -6061, -5979, -4598, -3524, -7075, -7941, -4363, -6821, -7352, -4790, -10153, -3141, -8647, -7694, -4560, -8181, -3059, -8163, -5139, -5967, -6999, -3522, -7499, -4662, -4430, -7789, -3323, -7236, -5095, -2678, -13015, -2370, -8770, -6402, -2326, -8020, -1428, -15172, -5738, -2779, -5912, -718, -6714, -3872, -3293, -6246, -269, -4852, -3756, -3844, -8584, -248, -5726, -6181, -5197, -8974, -895, -9090, -9187, -7961, -7599, -2222, -3604, -4499, -7550, -8094, -3415, -1637, -3358, -5196, -9103, -3766, -1415, -3280, -4638, -8634, -4531, -2375, -3022, -6155, -8514, -6723, -3882, -2388, -12957, -8294, -10702, -4611, -2183, -6208, -6294, -8596, -4624, -3030, -4294, -4482, -6502, -4505, -5533, -4369, -3588, -5140, -4437, -9778, -5678, -3492, -4094, -5129, -8125, -5901, -3924, -3454, -7825, -6824, -5268, -4546, -3504, -13669, -6096, -6415, -5086, -4449, -6758, -6129, -8657, -5754, -5507, -5122, -6649, -5868, -7418, -4495, -4525, -6668, -4849, -10128, -3423, -4501, -6654, -5680, -9210, -3299, -5553, -7664, -8110, -9114, -4008, -9971, -8777, -8515, -9887, -5323, -8213, 2153, 1795, 3912, 3587, 5834, -1016, 1537, 4466, 5109, 5613, 2066, 1108, 5719, 6749, 5662, 4755, 1217, 6345, 7241, 5840, 4602, 781, 5804, 6512, 5032, 2445, -1165, 4060, 4580, 2896, 1283, -330, 1412, 1818, 314, 2223, 989, -1502, -594, 801, 1915, 805, -2466, -1993, 3264, 2110, 52, 1217, -2491, 4804, 3837, -370, 3461, 1191, 5229, 5129, 1590, 4442, 3359, 5230, 5439, 3535, 4021, 3458, 5420, 4640, 4053, 1234, 1504, 5143, 2771, 2996, -656, -252, 3689, 1434, 58, 2848, 505, 725, 1598, -723, 3135, -993, -1702, 1350, 456, 1419, -4105, -508, 626, 15, -3113, -8520, -826, -156, -918, -6508, -1488, -4348, -47, -1237, -2357, 1393, -258, 649, -1318, -869, 2277, 2002, 1054, -1786, 235, 2361, 2321, 970, -2298, 985, 2258, 1436, 338, -2189, 1162, 1883, 110, -861, -1995, 521, 926, -600, -2784, -1977, -1188, -663, -1187, -5786, -2009, -2750, -2117, -1153, -5734, -2331, -1468, -1559, -424, -3789, -3391, -846, -124, -271, -2616, -5094, -1425, 568, -635, -1514, -7855, -2307, 193, -1079, -957, -6199, -1955, -1183, -242, -1688, -1225, -674, -3158, 874, -4361, 557, 144, -2714, 775, -2997, 622, 45, -932, -462, -885, -746, -456, -966, -1615, -916, -3384, 16, -3805, -3124, -3523, -8639, 1030, -4263, -9598, -4733, -6012, 1482, -1416, -4817, -1442, -2525, 1284, -727, -3537, -1493, -2039, 938, -420, -4252, -4997, -2887, 726, -354, -6085, -5058, -2260, 126, -945, -11731, -2710, -1154, -1202, -1769, -7325, -3777, -1094, -2891, -2222, -4635, -9826, -1999, -3706, -3273, -3883, -7014, -3719, -3379, -6908, -5244, -4869, -5933, -2992, -7082, -10324, -5168, -7420, -3277, -4263, -5530, -7436, -7158, -4667, -4579, -4126, -15350, -6271, -7759, -7094, -4505, -11147, -6313, -8923, -7329, -4495, -10853, -8293, -6150, -3947, -3008, -9408, -7699, -4367, -1877, -2408, -9026, -4849, -2898, -1183, -3101, -12385, -3941, -1949, -1875, -4788, -11231, -4544, -1903, -3954, -6879, -9517, -6720, -3039, -5178, -8548, -9850, -8467, -5021, -4193, -7323, -13018, -5354, -5141, -3844, -6560, -9112, -2811, -4752, -4008, -7486, -4419, -1606, -4762, -4680, -7503, -2441, -1777, -4502, -5971, -6081, -1754, -3403, -4646, -6904, -7030, -1869, -5849, -5379, -6375, -17535, -2471, -5899, -5749, -5793, -5734, -3495, -5789, -5025, -5445, -3960, -5428, -6367, -4398, -4889, -4138, -9359, -7064, -5009, -4619, -5597, -7328, -7851, -7654, -5160, -7970, -5438, -9383, -9530, -6483, -9446, -5387, -12105, -8456, -7893, -9236, -6564, -11607, -10606, -7852, -10832, -7544, -11498, -9134, -6662, -15210, -6070, -8433, -6344, -5589, -10395, -4950, -6170, -5338, -4885, -8898, -5055, -5460, -5829, -4232, -8021, -6466, -5481, -9062, -3557, -8159, -9262, -5154, -10191, -3290, -10077, -5350, -5843, -8811, -5320, -9128, -7464, -3738, -10143, -7960, -8100, -9496, -3235, -12739, -9271, -7889, -5974, -4061, -12627, -9218, -7999, -4389, -6014, -9309, -7709, -7663, -4306, -6351, -8323, -6228, -6876, -6256, -4848, -8023, -5981, -6369, -22941, -3874, -7185, -6829, -7207, -7048, -3467, -7086, -8196, -10378, -6642, -3479, -9258, -9857, -7156, -11084, -3651, -9220, -14935, -5104, -7677, -3819, -5829, -12594, -4775, -5058, -4090, -4704, -10755, -5069, -4478, -4545, -4855, -12465, -4925, -4561, -5231, -5501, -8389, -4510, -4559, -6212, -5288, -5943, -4715, -4564, -6756, -4783, -5362, -6670, -5045, -5267, -4956, -6155, -12391, -5872, -3268, -5009, -7774, -4679, -6195, -2051, -4210, -7952, -2658, -5427, -1662, -3561, -6643, -2372, -4257, -1872, -3409, -5854, -3374, -3473, -2318, -3894, -6110, -5644, -3255, -2620, -5374, -7144, -8270, -3633, -2712, -6792, -7214, -7604, -4796, -2792, -5905, -6319, -6949, -7097, -2972, -6274, -5927, -6965, -8726, -3185, -10383, -6426, -6650, -7111, -3338, -7288, -8155, -5905, -6216, -3604, -4812, -10773, -5450, -6311, -4407, -4748, -8935, -5538, -7599, -6173, -6452, -7096, -5857, -10204, -9091, -10233, -5895, -5855, -9265, -11213, -18393, -4744, -5604, -7013, -10177, -15188, -3829, -5427, -5872, -8567, -13044, -3467, -5386, -5846, -7906, -14226, -3806, -5568, -7225, -8231, -15640, -4867, -6064, -7962, -8570, -15315, -6491, -6603, -5666, -8093, -12325, -8361, -6551, -4535, -7626, -8564, -10203, -5893, -4544, -7566, -6681, -10950, -5123, -5408, -7591, -5847, -10538, -4421, -7186, -7343, -5592, -11590, -3902, -11545, -6836, -5673, -13925, -3799, -10239, -6406, -6118, -7636, -4267, -5771, -6545, -7258, -5346, -5225, -3950, -7375, -9963, -4827, -6336, -3422, -8649, -19154, -5777, -7520, -3945, -11323, -9199, -8682, -8992, -5413, -13915, -6826, -13591, -9162, -7564, -8499, -5978, -9332, -7473, -9923, -7084, -6291, -8315, -6112, -12872, -7505, -7801, -8927, -5640, -20680, -9918, -9336, -11811, -6077, -12715, -18131, -8541, -12484, -7082, -9311, -15387, -8505, -8095, -7985, -7318, -16632, -10172, -6551, -8789, -6129, -15036, -11625, -6071, -10040, -5623, -14149, -10038, -5712, -12652, -5786, -8795, -8596, -5150, -17093, -6398, -6442, -7428, -4844, -10921, -6799, -6098, -6908, -5106, -9167, -6896, -7377, -7247, -5934, -9277, -6995, -10019, -8436, -7206, -11837, -6677, -11714, -9005, -8900, -14474, -6423, -10326, -7606, -10715, -8786, -7193, -9644, -7153, -10266, -6949, -9861, -9951, -8611, -9436, -6413, -15358, -10963, -12247, -10379, -6633, -11458, -15410, -11217, -13295, -7154, -11108, -12643, -12588, -9742, -7396, -11499, -9731, -11903, -7479, -7161, -11064, -10301, -8998, -6598, -6914, -11898, -16542, -9630, -6623, -7180, -13601, -11254, -10157, -7547, -8109, -9983, -8363, -6865, -9548, -8945, -8289, -6601, -5682, -12160, -8646, -8391, -5706, -5913, -11865, -8276, -10447, -5925, -6935, -9121, -8354, -7604, -6798, -9462, -6838, -4716, -6822, -6549, -8462, -7693, -4000, -6594, -7895, -6769, -7586, -4973, -6013, -8419, -5617, -7780, -7360, -5270, -5937, -5635, -9492, -7264, -4908, -4523, -7270, -15655, -6850, -5062, -4234, -9884, -13528, -8888, -5614, -4852, -7523, -10928, -7270, -6215, -5311, -6747, -7114, -4923, -6566, -4600, -7739, -4724, -4564, -7040, -4242, -8549, -3727, -5943, -8435, -4850, -7798, -3812, -9394, -9503, -6331, -8229, -4845, -8458, -8618, -8332, -10959, -6702, -8161, -9438, -10704, -9777, -8455, -12745, -8288, -18293, -7542, -8917, -6757, -5409, -10329, -7475, -8013, -4059, -4109, -6316, -7180, -5499, -2730, -3871, -4034, -4328, -3872, -1852, -4352, -2859, -2390, -3590, -1313, -5337, -2758, -1733, -4776, -1285, -6561, -3900, -2343, -8214, -2047, -8071, -6182, -4479, -13300, -4172, -9847, -5768, -6314, -8925, -10777, -7609, -4552, -4439, -8330, -7203, -5519, -4559, -3779, -8590, -5127, -4699, -4959, -4239, -9071, -5260, -4944, -4503, -5149, -10096, -6423, -6439, -3922, -5556, -12913, -7777, -9690, -4341, -5107, -11462, -9815, -12056, -6622, -4521, -7703, -10977, -13298, -11830, -4439, -5979, -7696, -10712, -5605, -5086, -5555, -6830, -6915, -3485, -6244, -6340, -8277, -5108, -2779, -6934, -8530, -14756, -4508, -3014, -6373, -12795, -8122, -4962, -3946, -5447, -20497, -5840, -6385, -5337, -5108, -16593, -5327, -8387, -7255, -5739, -11819, -6191, -10161, -7649, -7019, -10547, -9152, -10066, -5847, -6470, -14486, -10060, -8501, -5217, -5286, -9341, -5770, -7874, -5880, -5256, -5970, -3900, -8430, -7759, -6395, -5144, -3241, -9640, -11092, -7933, -6040, -3405, -10804, -14053, -8638, -9004, -4054, -13237, -11551, -9299, -12484, -5009, -14033, -10711, -9999, -8460, -6175, -9999, -11959, -10288, -7217, -6379, -8146, -14966, -9243, -7447, -6123, -7424, -10787, -8123, -8228, -7030, -7654, -9525, -8109, -7544, -8848, -8383, -10883, -8998, -5887, -8280, -8208, -19806, -10114, -4968, -7492, -8023, -12012, -11740, -5422, -7524, -9341, -8940, -12506, -8279, -6865, -13448, -6894, -7999, -13915, -5800, -15544, -6065, -5780, -8611, -5322, -10285, -6815, -5080, -9507, -5177, -8316, -10562, -5325, -9006, -5229, -8222, -10018, -6044, -6886, -5836, -10249, -6882, -7736, -7052, -6820, -14958, -6880, -13252, -7863, -7128, -11928, -9877, -7676, -7032, -6802, -11699, -13657, -5602, -7377, -6714, -12093, -8943, -5430, -10822, -6575, -10612, -8469, -6471, -9368, -5754, -10230, -9748, -8396, -7060, -5243, -10757, -16112, -9310, -7211, -5730, -10197, -11386, -7731, -8958, -7499, -9370, -9610, -6667, -10252, -10601, -8998, -11204, -6622, -9982, -9833, -8612, -10396, -7354, -10764, -8613, -8016, -8505, -7972, -13083, -8838, -7443, -9133, -7421, -22329, -9933, -7356, -13400, -6717, -12747, -10748, -8053, -11388, -6577, -9403, -10115, -9711, -8863, -6951, -8050, -9368, -13137, -8426, -7709, -8026, -9329, -16157, -9241, -8961, -9285, -10204, -10665, -4364, -6294, -3836, -7219, -9365, -3929, -6002, -5580, -4914, -8936, -4243, -7687, -8215, -4495, -10010, -5284, -8697, -7519, -5838, -12775, -6430, -8266, -7565, -10654, -11040, -7006, -10283, -10751, -9930, -10448, -7897, -13324, -7606, -7022, -9663, -9744, -8958, -4818, -6295, -6927, -10911, -7584, -3691, -5889, -5940, -10517, -7192, -3582, -5363, -7219, -9895, -7168, -4360, -5180, -9619, -8691, -7961, -5198, -5803, -5978, -7237, -10391, -4804, -7380, -4833, -6109, -10396, -4192, -9450, -5547, -5263, -9089, -3209, -10289, -6763, -4585, -6318, -1948, -8639, -6093, -4576, -4159, -1231, -6172, -5231, -5832, -3620, -1236, -4528, -3804, -6468, -4263, -1849, -3621, -2225, -4256, -4723, -2965, -2791, -1475, -3322, -4411, -4578, -1826, -1700, -3905, -4468, -6272, -1273, -2831, -6034, -4816, -5906, -1430, -4717, -8818, -4714, -4902, -2262, -6920, -8330, -4036, -4736, -3635, -8333, -7975, -3348, -5249, -4955, -8431, -7728, -2994, -6889, -5195, -8476, -6570, -3102, -13434, -5928, -9587, -5214, -3852, -6093, -7567, -11295, -4506, -5399, -3752, -5774, -9771, -4808, -6523, -3233, -4852, -8863, -5962, -6095, -3654, -5989, -8809, -6196, -6473, -4103, -7589, -9073, -5738, -7981, -4108, -5257, -8939, -6148, -8299, -4780, -3803, -6527, -6477, -6990, -7861, -3288, -4499, -6232, -6105, -10866, -3259, -3479, -6646, -5314, -6065, -3503, -3374, -7567, -4174, -5087, -3853, -4226, -8037, -3362, -5254, -4256, -6220, -8814, -3278, -6154, -5008, -9116, -10928, -3834, -7891, -6764, -9195, -9869, -4800, -10372, -11778, -8982, -7745, -6119, -11778, -10249, -10527, -7539, -7762, -9666, -7519, -11275, -9557, -9285, -7147, -7933, -10382, -14017, -13071, -6178, -12286, -10424, -9186, -10255, -7514, -11687, -8993, -7492, -6503, -9128, -10698, -7872, -7326, -5508, -4999, -16246, -7830, -8372, -6157, -3467, -8183, -8341, -9524, -8154, -3266, -6474, -8933, -10035, -9500, -3579, -6851, -9384, -10592, -9732, -3931, -8966, -10573, -9352, -10725, -4621, -8411, -12677, -8166, -8141, -5573, -6177, -10671, -6396, -7005, -5019, -5664, -8539, -4903, -7998, -4353, -6129, -7154, -4439, -8108, -5015, -6479, -6239, -4922, -6675, -6239, -7302, -5595, -5903, -7161, -5943, -9650, -5466, -6010, -10543, -6084, -7520, -6087, -5225, -15220, -7054, -5292, -6691, -4902, -11189, -6657, -4647, -6504, -5288, -11743, -5961, -5358, -6616, -6282, -13219, -6286, -7658, -6664, -7806, -14203, -7961, -9002, -6051, -8918, -12693, -12553, -6606, -6071, -8136, -9552, -11452, -5097, -7414, -7769, -7945, -8942, -4260, -9978, -9190, -7114, -9340, -4201, -10764, -13846, -5954, -15349, -5477, -9096, -10039, -4706, -9028, -10172, -7495, -8385, -4112, -5674, -7674, -6897, -8848, -4367, -4294, -4688, -7419, -10627, -5427, -3950, -3679, -8725, -9351, -7109, -4392, -3577, -9706, -6925, -9179, -5632, -4123, -9339, -5498, -11658, -7746, -5061, -8542, -4782, -13051, -8615, -5995, 10207, 11289, 9083, 11137, 8447, 9430, 10944, 8381, 10592, 8026, 7216, 9886, 6198, 8985, 6673, 6633, 8129, 4138, 6584, 4431, 7475, 6153, 5042, 4490, 3804, 6993, 5102, 5109, 3740, 4357, 5154, 4561, 3913, 3153, 3361, 3044, 3469, 1068, 2251, 46, 5734, 1797, -3758, 2245, -1866, 7030, 564, 1773, 1725, 1478, 6789, 625, 3127, -1614, 3713, 6222, 488, 3036, -562, 5623, 5979, 1255, 3515, 3295, 6951, 4547, 3822, 4257, 4597, 7390, -822, 4900, 3891, 4550, 6732, 826, 4401, 2104, 3719, 4627, 2534, 2473, -938, 2962, -219, 1731, -34, -1834, 2546, -1652, 296, -325, -1352, 2012, -161, 110, -52, -1516, 1491, -1138, 1025, -483, -1726, 1399, -1913, 1741, -1410, -987, 1403, -1115, 1689, -1125, -40, 831, -211, 353, 543, -80, -702, -268, -1854, 1470, -1423, -4196, -1443, 1014, 1393, -2236, -3751, -2075, 2777, 588, -92, 156, -1659, 3229, -489, 1328, 1353, -2081, 2877, -1334, 1669, 744, -1109, 1810, -1551, 1024, -2013, 743, 890, -1334, -573, -3908, 1664, 2001, -1130, -2663, -2071, 1890, 2865, -872, -2943, -3700, 1837, 2831, -270, -1210, -6507, 1574, 2720, -90, 239, -577, 784, 2899, -1803, 1098, 983, -818, 2646, -5786, 1519, 789, -3360, 1812, -615, 1551, -667, -9003, 940, 404, 1184, -1470, -3667, 193, -742, 497, -1471, -710, -601, -2693, -262, -4084, 478, -929, -1549, -687, -2203, 1135, -674, -381, -561, 895, 1537, -720, -271, -731, 1593, 1380, -1903, -1418, -2215, 596, 488, -5180, -3958, -6036, -2502, -1253, -8537, -4943, -11206, -5160, -4763, -5640, -3247, -5166, -1946, -7933, -5692, -1330, -1766, -398, -2854, -7819, -79, -219, 665, -1759, -10432, 51, -41, 1234, -2617, -5774, -1231, -1204, 1088, -5262, -3406, -5013, -4180, 88, -4682, -2510, -7221, -6368, -1986, -2630, -2390, -4973, -4483, -5984, -1756, -2469, -4899, -4610, -6454, -1856, -2687, -3228, -6005, -3629, -3222, -3783, -2565, -6734, -2752, -7600, -6444, -3639, -5262, -2601, -7169, -2645, -4663, -2591, -2349, -4601, -60, -3248, -847, -1804, -5712, 1000, -2539, -362, -1421, -7959, 1097, -3055, -943, -1731, -5327, 408, -4410, -1942, -2930, -5813, -1139, -4321, -2170, -3867, -7668, -4112, -3678, -1571, -3272, -4025, -6533, -4260, -973, -2701, -2626, -3591, -6282, -1033, -2514, -2780, -2551, -9603, -1826, -2444, -3987, -2360, -8058, -2500, -2464, -5667, -2311, -6635, -2500, -3015, -6611, -2884, -7232, -2174, -4393, -6850, -3689, -11287, -1442, -5914, -7380, -1876, -8607, -1157, -5547, -5864, -537, -7727, -2009, -4643, -3494, -603, -8298, -4132, -4745, -2530, -1954, -3908, -5005, -6482, -3294, -4320, -2201, -3564, -8216, -7161, -5690, -2257, -2733, -6127, -9394, -4781, -2998, -2583, -3481, -7349, 5426, 7847, 9313, 7297, 4636, 5085, 7058, 8906, 6891, 6119, 4043, 4658, 7771, 5909, 7459, 2156, 2417, 6234, 5217, 7788, -1435, 1624, 5049, 5095, 7408, -7233, -3838, 4569, 4327, 6644, -901, -94, 3901, 1247, 5628, 546, 2292, 3526, -2961, 4485, 1089, 2669, 4078, 1769, 4119, 257, 2406, 3876, 672, 4579, -46, 2191, 2664, 96, 5252, 4383, 2794, 2833, 4355, 5809, 6437, 3970, 3823, 5731, 5659, 6971, 4748, 3719, 5315, 4453, 6348, 4851, 2532, 2791, 2260, 4618, 4379, 1086, -8967, 813, 1747, 3504, 474, 1170, 1665, 656, 2502, -629, 2487, 2435, 1586, 1424, -1338, 2665, 2198, 903, -639, 1323, 2723, 670, -3224, -1740, 2583, 2562, -3183, -2303, 757, 2232, 1425, -3889, 1318, 1349, 528, -629, -666, 2355, 216, -310, 590, -34, 2543, -2223, 1015, 1222, -286, 2181, -3519, 1729, -234, -448, 874, -4004, 1344, -1421, -769, -2573, -5363, -1150, -254, -1731, -6367, -5754, -2257, -787, -1895, -884, -4020, 1781, -3247, -481, 896, -1826, 2605, -3712, -117, 1559, -668, 1196, -2059, -1999, 1519, -1375, -2616, -1751, -10551, 1487, -6260, -456, -2258, -1066, 1966, -3019, 589, -2636, 819, 2356, -1004, 39, -3487, 1438, 2445, -993, -1235, -4447, 1845, 2441, -462, -2703, -3742, 2280, 2201, 496, -1995, -2080, 2322, 1166, 981, -201, 444, 1756, -1499, 868, 431, 1756, 806, -3667, -112, -238, 1637, -78, -1968, -1412, -2136, 109, -646, -3260, -733, -5007, -2825, -1485, -9342, 109, -10058, -5639, -4041, -4338, 254, -9527, -5977, -12869, -2969, 285, -5502, -5068, -4607, -1379, 469, -3507, -3972, -3367, -219, 405, -2348, -2465, -3265, -347, -173, -1863, -1051, -3589, -1807, -931, -1612, -414, -4401, -4781, -861, -1242, -673, -5615, -13421, -194, -944, -1880, -6549, -7062, 327, -1004, -4253, -7672, -4454, 748, -1496, -5510, -13924, -3132, 923, -2578, -3646, -7889, -2116, 404, -5211, -3170, -5116, -1094, -1253, -7590, -3962, -4729, -190, -4422, -3925, -4724, -5366, 176, -4380, -3646, -4135, -5588, -196, -2938, -6095, -2935, -4876, -1312, -2734, -8116, -2162, -4472, -3171, -3102, -10162, -2307, -5976, -5890, -3760, -5903, -3491, -9974, -7713, -4368, -1577, -6112, -5954, -5608, -3784, 30, -7232, -4160, -3885, -2656, 375, -4147, -1974, -3448, -2591, -104, -2696, -669, -4437, -3507, -1342, -2292, -787, -6889, -3156, -3878, -2933, -2172, -8951, -2564, -14786, -4893, -3482, -6806, -3435, -5097, -4805, -2796, -4327, -5656, -3335, -3204, -1890, -3247, -6490, -4428, -3529, -1462, -2997, -4216, -10286, -6461, -1467, -2295, -3052, -2273, -15047, -1709, -1113, -4487, -3, -7242, -1887, -336, -7340, 491, -3356, -2034, -380, -1820, -228, -857, -2469, -1405, -209, -1899, 295, -2879, 9652, 7124, -6527, 7067, 8584, 9372, 7627, 4321, 7288, 8635, 8507, 8128, 6618, 7542, 8691, 6993, 7912, 7318, 7372, 8450, 5156, 7030, 7061, 6655, 7534, 4824, 5754, 6076, 5354, 5562, 5020, 4152, 4597, 3849, 2168, 3748, 1157, 3080, 3905, -862, -888, -4556, 1962, 4386, 440, 1776, 1834, -482, 3628, 2068, 4814, 2591, -2346, 2446, 1044, 6083, 3325, 3300, 3420, -8072, 6245, 4934, 4483, 3509, 1315, 5062, 5033, 2977, 2414, 1922, 1231, 2650, -7803, 3735, 4001, -994, -396, 3097, 4750, 6221, 2117, 3058, 4447, 4182, 6836, 1332, 3289, 3808, 2267, 6175, -2967, 1953, 2041, -705, 4531, -3984, 268, 555, -6472, 2323, -252, -245, 1111, -3071, 1547, 589, 90, 2149, 168, 2513, -158, -521, 2545, 1469, 3099, -3443, -3551, 2239, 1852, 3305, -5347, -5659, 1439, 1681, 3407, -1643, -2718, 664, 1044, 3140, -836, -3775, 451, -421, 1750, -909, -8705, 356, -2317, -2939, -1755, -3895, 55, 313, -1306, -2954, -3244, 290, 2307, 1473, -2253, -2582, 1121, 2993, 1894, -1241, -812, 1586, 2776, 1418, -694, -196, 1431, 1897, 301, -354, -91, 871, 447, -2935, -300, 497, 132, -1759, -1713, -692, 664, -1077, -5634, 1413, -1322, -130, -2534, -9987, 2011, -1774, -1518, 21, -4793, 692, -783, -4924, 2058, -2960, -3722, 1082, -4365, 2653, -2402, -2916, 1796, -616, 2184, -3321, -672, 892, -837, 1125, -5352, -197, -2158, -4373, -104, -2044, -116, -4696, -799, -1885, 108, -455, -3788, 609, -3943, 912, -1172, -5821, -365, -3853, 922, -1494, -10726, -3632, -4144, 351, -1992, -13746, -7281, -6012, -870, -4088, -7003, -8955, -9928, -2215, -10930, -4801, -4130, -9607, -1677, -6667, -4013, -2026, -7841, -1256, -4379, -3478, -2305, -7516, -2244, -2726, -3069, -5169, -7457, -3927, -1566, -3072, -5952, -8071, -4662, -1407, -3683, -3284, -12012, -6466, -2627, -5559, -2466, -8503, -8260, -7049, -12068, -1939, -6263, -5644, -5535, -5532, -1498, -8145, -3326, -1547, -2922, -1460, -8897, -1785, -83, -2035, -1681, -3586, -1615, 262, -2335, -1801, -1720, -3506, 34, -3925, -1776, -1105, -7138, -351, -7320, -2071, -1136, -2049, -1030, -13759, -3510, -1246, -409, -2428, -11366, -7703, -1434, -345, -3435, -6548, -4630, -2223, -1301, -2075, -4725, -2506, -3777, -3015, -810, -3991, -2467, -5095, -5961, -163, -3725, -3751, -5199, -6350, -106, -4025, -4216, -6003, -3078, -822, -4461, -2049, -9318, -1990, -2599, -3994, -206, -8426, -2517, -5395, -3002, 684, -5990, -5066, -4987, -2271, 701, -4272, -9414, -2754, -1898, 125, -2779, -4829, -1562, -1654, -710, -2591, -4261, -1492, -1627, -1909, -3583, -5441, -2417, -2053, -3650, -2863, -2625, -3523, -2894, -4334, -1597, -473, -3340, -4067, -3633, -1699, 232, -2580, -4067, -2308, -3084, -1180, -6092, -4239, -1293, -4354, -36, -2800, -3728, -1102, -5333, 72, -1672, -1911, -1753, -4297, -556, -1852, -986, -3200, -4189, -1704, -2067, -1346, -5424, -6356, -3116, -1528, -2690, -6495, -5987, -3808, -981, -3077, -4233, -4180, -3316, -640, -2510, -2383, -6287, -2277, -429, -2864, -1384, -5192, -1512, -475, -3355, -1349, -966, -1403, -881, -2271, -2630, 389, -1847, -1543, -1237, -4508, 338, -2645, -1930, -979, -2698, -646, -3822, -1645, -1614, -1494, -1975, -5789, -1433, -3747, -1685, -2633, -8070, -1757, -8432, -3345, -3061, -5691, -1998, -3004, -8269, -4698, -4254, -1247, -599, -4812, -2980, -4254, -336, 249, -2421, -411, -4544, -81, -145, -2301, 396, -4487, -860, -1777, -4124, -241, -4998, -3200, -3160, -8355, -2338, -5146, -7469, -2295, -9141, -5032, -3662, -5895, -1874, -5905, -5154, -2514, -5081, -2382, -4328, -6181, -2148, -4711, -4073, -4849, -8862, -2655, -3913, -8250, -4878, -8104, -4369, -3010, -6854, -3375, -5052, -6610, -2190, -4762, -2965, -3345, -5969, -1668, -5101, -3189, -3193, -5337, -1630, -7802, -3245, -4524, -4370, -2125, -8453, -3168, -6898, -3635, -3126, -6650, -3888, -6152, -4153, -4874, -7013, -7049, -4643, -6797, -8176, -7959, -7043, -4792, -14044, -4507, -7943, -3770, -7443, -6466, -1643, -7323, -3277, -7378, -5406, -580, -7269, -4736, -4354, -6025, -960, -8876, -6648, -4096, -7668, -2995, -12681, -3646, -6702, -9556, -6765, -12470, -1753, -6742, -7613, -4703, -9559, -975, -2850, -4852, -3019, -7457, -1062, -1342, -2897, -2641, -6713, -1993, -831, -1659, -2941, -6644, -3833, -972, -1070, -3118, -6411, -6991, -1778, -1119, -3081, -6290, -8705, -2943, -1677, -3203, -7092, -5220, -2945, -2155, -3704, -7188, -3990, -2399, -2346, -4409, -5589, -4399, -2796, -3158, -4166, -5033, -6164, -4740, -5073, -3487, -5275, -8020, -9252, -5519, -3013, -5280, -7049, -6241, -4112, -2602, -5002, -4342, -4485, -3499, -2209, -5353, -2726, -3989, -3586, -1779, -7542, -2447, -3624, -4131, -1538, -10178, -3316, -3414, -4716, -1680, -6510, -4780, -3717, -4943, -1959, -5807, -5592, -4417, -5193, -2187, -6896, -5312, -4970, -5971, -2826, -9528, -4553, -5374, -7619, -4631, -11720, -4032, -6466, -10981, -9776, -9626, -3596, -7883, -7643, -7926, -9450, -3189, -6556, -4514, -5081, -10063, -3555, -5838, -3001, -4330, -5326, -5705, -6934, -2437, -4379, -3222, -13828, -8629, -2534, -4638, -3081, -6308, -7829, -3122, -4884, -4988, -4575, -8347, -4172, -5425, -12266, -3980, -12652, -5641, -6592, -8644, -3517, -9681, -6087, -8262, -6792, -3360, -7437, -5156, -9033, -6179, -3928, -7239, -4846, -7804, -6242, -5451, -7585, -5468, -6124, -7393, -7578, -6948, -6962, -4992, -10180, -8464, -5689, -10150, -5007, -9271, -9298, -5037, -12223, -7211, -6436, -12225, -5674, -6543, -12220, -5783, -11803, -8592, -4992, -5941, -3157, -170, -3957, 419, -2841, -3929, -1142, -4620, -314, -3270, -2281, -2919, -3992, -1859, -5558, -532, -5426, -4294, -4450, -10597, 248, -5391, -4548, -9407, -3583, -35, -3340, -3159, -7880, -1402, -1515, -2693, -2726, -6853, -692, -4796, -3774, -3899, -7827, -1072, -6084, -8339, -5251, -6331, -2497, -3400, -7077, -4072, -4268, -4882, -2502, -4276, -3589, -3245, -7636, -2608, -3600, -4090, -3282, -9546, -3455, -3308, -4841, -4708, -8275, -4656, -2979, -5731, -9120, -5274, -5088, -2714, -6845, -9933, -3065, -4837, -2564, -7328, -5654, -1960, -4820, -2365, -6734, -3859, -2256, -5088, -1539, -5890, -4024, -4679, -4334, -322, -4506, -10133, -2871, -2397, 300, -2445, -3656, -186, -1113, -244, -1247, -620, 543, -552, -2311, -1136, 177, -4, -276, -3337, -1706, -466, -1231, -500, -2301, -2313, -2774, -2075, -2132, -3227, -2650, -6498, -2054, -7939, -3448, -2781, -5073, -1721, -3973, -1305, -3086, -6035, -1765, -1945, -533, -4356, -16899, -2541, -1818, -706, -6369, -5265, -4491, -2578, -1216, -4346, -3699, -10344, -3971, -1983, -3044, -4514, -7241, -6979, -2824, -3433, -10366, -5372, -9833, -3742, -6117, -5688, -5513, -3639, -6728, -9176, -3372, -5632, -1562, -6172, -3954, -3871, -4747, -992, -3247, -2446, -7278, -3462, -1548, -3282, -1876, -5573, -2696, -2417, -4861, -1604, -2894, -2699, -1627, -3137, -1879, -1806, -3529, -636, -1494, -2835, -1315, -5640, -629, -1268, -3994, -1102, -7340, -1609, -2153, -4626, -1179, -3667, -3165, -4117, -4095, -1683, -1811, -4122, -7872, -3229, -2724, -1385, -3690, -10671, -2923, -4360, -2363, -2690, -6183, -3171, -6327, -5682, -2145, -4540, -3834, -6881, -12452, -2398, -4211, -4850, -5589, -7662, -2900, -5063, -5796, -4179, -7179, -2366, -6936, -5940, -3622, -3547, -1541, -6389, -6049, -4282, -2157, -1368, -4364, -7178, -6198, -2702, -2154, -3233, -9029, -6981, -5334, -4461, -2787, -7655, -3614, -9777, -7026, -2835, -5070, -1319, -8361, -4223, -3253, -3094, -448, -9863, -3240, -3538, -2131, -806, -18134, -3532, -2913, -2198, -1992, -9332, -4367, -2200, -3003, -2578, -7431, -5050, -2440, -3693, -2335, -6507, -5188, -4258, -3720, -2648, -5348, -4864, -6207, -3824, -3727, -4056, -4372, -4311, -4385, -5038, -3425, -3762, -4365, -5165, -6263, -3861, -2949, -5523, -5803, -7267, -5535, -2440, -3450, -6491, -6583, -7471, -2905, -2155, -7149, -5838, -7255, -5139, -2232, -6117, -5664, -7448, -9986, -3195, -5670, -6103, -9060, -5480, -4686, -7828, -7515, -11807, -4176, -6412, -10395, -8694, -8353, -4366, -7673, -6264, -7269, -4235, -5007, -7954, -5487, -5539, -2070, -5206, -7984, -5717, -4639, -1338, -5335, -9191, -5433, -4683, -1827, -6415, -13691, -4209, -5045, -3519, -8156, -12743, -3118, -4772, -6756, -6671, -9288, -2765, -4329, -8963, -6039, -8329, -3145, -4475, -6576, -7427, -8702, -3934, -5309, -6314, -5477, -3410, -3167, -66, -2262, -5855, -3498, -5408, -1286, -2858, -5521, -3041, -5328, -4032, -4533, -6361, -2287, -3867, -20243, -4777, -10200, -2155, -2661, -5044, -3543, -9783, -3018, -1798, -4161, -3724, -4886, -4616, -1429, -7303, -5895, -2396, -4869, -1700, -6545, -6492, -949, -3431, -2717, -2493, -2300, -565, -2311, -4681, -1593, -456, -1694, -1798, -8494, -2401, -264, -6883, -1563, -11681, -4056, -1761, -3721, -1230, -5505, -3650, -5053, -947, -821, -2387, -3506, -3741, -358, -624, -405, -3536, -2328, -642, -790, 472, -970, -2018, -1064, -1438, 77, 912, -1657, -583, -2990, -2015, 1734, -664, 340, -4616, -3717, 1779, 565, 722, -2975, -1722, 1200, 1446, 669, -2045, -1682, 17, 1739, 477, -2367, -3931, -1958, 1421, -69, -3265, -7861, -5522, 510, -1234, -3364, -5265, -17262, -914, -2866, -2765, -4489, -7162, -2282, -3834, -2555, -3742, -5362, -3331, -3263, -2447, -3105, -3817, -6616, -3147, -1883, -3630, -2625, -6406, -4667, -1269, -5446, -2050, -2187, -9455, -626, -7359, -1879, -1076, -5427, 148, -6831, -1534, -1283, -2948, 483, -4340, -944, -2099, -2338, -155, -3232, -947, -2821, -3413, -2428, -3920, -2179, -3242, -7184, -12341, -7016, -4100, -3160, -5233, -3558, -14145, -3318, -2490, -3249, -1710, -7597, -2832, -2170, -3325, -1787, -6355, -3936, -2602, -4810, -2898, -5908, -5624, -3795, -8726, -3745, -5841, -3629, -5146, -8145, -4212, -6266, -1858, -3569, -3990, -6194, -5008, -1244, -2718, -2468, -10348, -2920, -1426, -4559, -2215, -7165, -2210, -2518, -10184, -2919, -6182, -3111, -6181, -2783, -4790, -6442, -3864, -3545, -859, -16235, -6619, -1850, -595, -2, -3783, -5489, -641, 56, 310, -930, -3593, -440, -895, -13, -139, -2242, -907, -3589, -963, -691, -2010, -1697, -8947, -1732, -1890, -2865, -1927, -12190, -1474, -2324, -3764, -1104, -6571, -1214, -2128, -3762, -508, -5101, -1675, -1924, -4087, -850, -5613, -2976, -2142, -5175, -2255, -4302, -4548, -3586, -6211, -4518, -3139, -4060, -8390, -5934, -6325, -4610, -2357, -7488, -5683, -6163, -7341, -1213, -4894, -4927, -6371, -2692, -1206, -5002, -3591, -9952, -1444, -3129, -5790, -2942, -8019, -1823, -13260, -5479, -3063, -4223, -3022, -3420, -5042, -3514, -3078, -3803, -1685, -5575, -3754, -3408, -4172, -1592, -8212, -3633, -5294, -4751, -2493, -10080, -3281, -8064, -4468, -4490, -5562, -2984, -6170, -3963, -7899, -4475, -3326, -5320, -4466, -5433, -4894, -5054, -5898, -6387, -3080, -5548, -10698, -6944, -9742, -2464, -5787, -7323, -7028, -11875, -3031, -6788, -4895, -6152, -15868, -3168, -8866, -4532, -5277, -7629, -2080, -10652, -5437, -4903, -5330, -1388, -10577, -7358, -5212, -4795, -1010, -9603, -9015, -6117, -5454, -606, -8182, -9363, -6617, -7009, -517, -6436, -9368, -6261, -6469, -1053, -6020, -8244, -6454, -4848, -2195, 6928, 7161, 7582, 9663, 3009, 6574, 6930, 7288, 8942, 2336, 5736, 5959, 6643, 6362, 551, 4880, 4033, 6077, -2389, 1134, 4115, 3344, 5678, 3457, 2681, 3483, 3649, 5306, 3935, 2660, 2102, 2126, 4541, 2237, 516, -2154, -289, 2802, 3058, -1716, 3671, 2723, 322, 4541, 2205, 5567, 3995, -57, 4703, 3907, 5418, 4148, -1085, 3697, 5001, 3807, 4239, -3546, 1478, 6029, 1668, 4889, 818, -144, 6718, 1282, 5574, 2393, 1204, 6736, 1982, 5516, 2036, 1773, 5835, 1456, 4272, -5, 1474, 3807, -453, 1723, -367, 723, 1272, 1176, 589, 1470, -87, -532, 1951, 1410, 2149, -182, -2145, 820, 1516, 1956, 714, 1835, 1723, 1139, 1227, 1601, 3241, 4201, 697, 407, 1961, 2985, 5495, 625, 86, 1831, 1753, 5665, 644, 258, 1375, 101, 4633, 408, 428, 591, 101, 1964, 73, 586, -1114, 1791, -3599, 341, 1153, -5101, 2327, -3064, 1556, 1648, -5711, 1436, -3218, 2393, 1225, -6239, -1028, -2614, 2159, -112, -3314, -6108, -490, 634, -104, -935, -7254, 1131, -2714, 266, -725, -2490, 2436, -5403, -995, -1625, 141, 3343, -2207, -1860, -1732, 1613, 3657, -1396, -380, -920, 2091, 3269, -2605, -115, -694, 1471, 2147, -8207, -1260, -1161, -634, 487, -5559, -2514, -1353, -5645, -720, -3252, -1475, -1312, -5870, -873, -3397, -1416, -2092, -3917, -921, -4442, -3653, -3683, -3276, -1468, -2817, -6368, -4562, -2547, -2602, -945, -5453, -3824, -2102, -3643, -496, -10197, -3446, -2567, -3957, -1277, -5898, -4932, -4097, -3617, -2940, -3369, -12484, -5700, -3037, -4624, -2317, -5191, -6881, -2797, -4694, -1040, -3485, -9315, -3042, -3857, -200, -3721, -8256, -3425, -3250, -339, -3769, -6949, -3035, -2842, -1585, -1973, -5703, -2145, -2747, -3759, -602, -4099, -1649, -3167, -5274, -249, -3214, -1890, -4350, -6286, -1009, -3009, -3173, -7507, -6186, -3358, -3037, -6044, -9712, -3886, -9717, -2858, -4379, -4317, -3178, -6481, -2575, -1477, -2575, -4203, -5782, -2697, -165, -2142, -5758, -7880, -3698, -55, -2516, -4626, -9078, -6360, -1198, -3214, -4071, -7936, -8296, -3909, -3814, -5051, -7098, -4863, -6324, -4723, -6959, -5957, -3596, -5381, -6863, -5569, -4869, -3771, -5398, -9812, -3639, -3449, -5759, -6330, -7022, -2587, -2509, -9998, -7825, -5322, -2124, -2606, -5872, -7187, -4567, -1959, -3973, -4872, -7178, -4412, -1840, -7693, -6145, -8514, -5065, -1816, -10338, -9791, -6354, -6935, -2090, -5574, -7507, -5249, -10146, -2684, -4477, -6408, -5846, -8380, -3063, -4549, -7633, -7512, -6250, -2611, -4874, -9968, -9417, -5461, -2196, -5033, -10329, -9230, -5494, -2565, -5050, -7495, -7770, -5990, -3404, -4994, -5494, -7295, -6686, -3496, -5244, -5669, -7175, -7101, -3513, -5959, -9259, -6859, -6415, -4417, -6444, -6359, -1981, 7876, 7695, 8495, 8237, -2844, 7481, 7270, 7862, 7545, 1019, 6019, 5665, 6034, 5202, 3039, 2185, 2306, 5340, -953, 3467, -1751, 3379, 6516, -117, 3658, 2522, 4529, 6607, 2003, 4490, 2914, 3987, 5438, 1648, 5270, 2903, 3379, 3369, -873, 5512, 2931, 3175, 1822, -2892, 5008, 2496, 1168, 220, -3019, 3421, 1830, -4198, -2965, -1917, 2406, 1767, 2827, 1174, 509, 4688, 2281, 4282, 2522, -37, 5930, 2738, 4040, 2101, -5544, 6003, 2823, 2793, 766, -3529, 5412, 2160, 1395, -503, -2334, 4763, 194, 657, -1395, -5836, 4156, -4541, -263, -2714, -6537, 2816, -3596, -1707, -728, -2451, -1709, -784, 231, 1996, -855, -251, 214, 1987, 2531, 152, 3082, 342, 2359, 300, 813, 3486, 164, 1775, -2561, 1035, 2136, 271, 621, 2147, 408, -696, 702, -1360, 3150, -1099, -2018, 944, -8521, 3171, 847, -1162, 473, -2446, 3282, 2751, 143, -1128, 31, 3279, 2878, 1415, -2750, 35, 2765, 1139, 2366, 390, -2352, 1736, -3317, 2803, 2860, -7559, 611, -4770, 2225, 4179, -3502, -87, -5472, -484, 4644, -5787, -1006, -3457, -4922, 4405, -4343, -2748, -1305, 943, 3514, -212, -2991, -843, 2521, 2064, 748, -836, -1403, 3056, 516, 233, 886, -1366, 2921, -400, -794, 2005, -3, 1891, -1284, -1647, 2547, 456, -449, -3947, -3161, 2391, -251, -4949, -10357, -2631, 1181, -1484, -7207, -6178, -821, -2308, -2560, -5659, -11313, -580, -5646, -2848, -3473, -2267, -1680, -967, -2630, -2106, 56, -3239, -401, -3008, -2384, 407, -4374, -1663, -3304, -4877, -627, -4487, -4751, -4659, -9247, -2585, -2020, -9640, -8211, -5383, -3012, -327, -11648, -2926, -5704, -2565, 378, -6753, -1507, -7532, -3347, 483, -4807, -2080, -3945, -4303, 264, -4548, -4391, -2012, -3684, -187, -4851, -6521, -1326, -3289, -980, -4349, -5678, -1515, -2131, -2063, -3427, -6038, -2768, -864, -2668, -2829, -7045, -6107, -792, -2995, -2743, -6596, -12351, -2175, -3964, -3177, -5050, -7948, -4977, -3998, -3949, -3822, -7796, -6941, -3381, -4913, -3246, -4481, -7580, -4051, -6255, -3220, -2724, -7102, -5431, -6488, -3589, -2407, -5400, -5885, -4847, -4463, -2929, -4341, -6888, -4257, -6679, -3643, -3892, -5181, -5014, -18357, -3975, -4023, -3273, -6397, -5969, -4322, -4631, -3067, -6547, -3801, -5631, -4851, -4139, -5174, -3317, -8692, -4473, -5120, -3951, -3770, -9338, -4609, -5421, -3673, -4699, -8021, -5558, -6945, -4439, -5838, -9140, -6951, -8590, -6337, -7444, -14789, -8155, -6678, -9408, -9408, -12676, -8249, -5398, -12206, -9098, -11849, -6063, -4893, -14348, -8102, -14796, -3920, -5688, -8043, -8041, -11395, -3023, -9351, -5778, -8808, -9526, -3716, -11085, -4731, -10442, -9287, -7182, -8530, -3985, -15913, -9585, -9185, -10307, -3460, -10567, 6844, 8184, 3420, 5950, 6590, 5716, 7520, 2915, 5650, 5578, 1323, 5655, 1526, 4481, 1420, 2109, 4602, 938, 2294, 15, 4468, 5518, 3231, 2469, 3187, 5793, 5964, 4592, 3694, 3339, 6224, 5655, 4528, 4454, 2352, 5057, 4221, 3430, 5324, 971, 1833, -301, 2190, 5579, 373, 2644, 850, 1098, 4721, 980, 4056, 3616, -1585, 2925, 537, 4012, 4156, -3087, 1117, -3988, 3210, 4093, 1451, -2670, -2487, 1519, 3634, 2380, -613, -810, -2387, 2590, 568, 2761, -6471, -488, 1010, -5312, 3534, 340, 1823, -1565, 1888, 3010, 3257, 1775, -3382, 3422, 2002, 4252, -685, -951, 3397, 1173, 4308, -3154, 168, 2609, -479, 3921, 1052, 588, 1830, -3238, 3553, 2378, 610, 1794, -208, 3373, 2364, 113, 2254, 1288, 3176, 1322, -1241, 2383, 1270, 2722, -950, -4485, 1628, 102, 1826, -5666, -8227, -513, -1899, 410, -4133, -3782, -6552, -905, -1388, -2513, -747, -3604, 1420, -3010, -3860, 972, -216, 2714, -628, -2463, 1139, 963, 3132, 1691, 105, 357, 731, 2731, 2376, 650, 659, -968, 1401, 1577, -86, 1151, -5024, -280, -273, -1284, 615, -7242, 329, -1523, -2322, -285, -1319, 1239, -3131, -4030, -1557, 1273, 1204, -2623, -4930, -4765, 2533, 382, 31, -3846, -2702, 2810, -1149, 1031, -2436, -2306, 2244, -3404, 1046, 817, -8994, 1047, -4395, 638, 2113, -1506, 182, -2293, 232, 1249, 408, 245, -443, 303, -2615, -457, 2, 388, 1146, -1225, -3270, -964, 114, 1823, 69, -1130, -1849, -1146, 1661, -1202, -555, -1365, -2727, 687, -4664, -2784, -860, -4224, -719, -8293, -6623, -1237, -5927, -2521, -5505, -3504, -1674, -4074, -4433, -3443, -3662, -1029, -1584, -4872, -3436, -5480, -604, 87, -4061, -6831, -6373, -954, 895, -2930, -4665, -5970, -1481, 869, -3005, -1678, -6194, -1725, 102, -4007, -1213, -7330, -2515, -1336, -4220, -2492, -4365, -4748, -3634, -3468, -6231, -2036, -8618, -7015, -2416, -10932, -1345, -8476, -5322, -2055, -7350, -2131, -10709, -3277, -3007, -7164, -4938, -10398, -2347, -5087, -6032, -11826, -6451, -1985, -5375, -5476, -6386, -5870, -1782, -5321, -6190, -5095, -7148, -1297, -6906, -7337, -4828, -9918, -793, -7903, -6343, -5432, -7696, -862, -6090, -4809, -7046, -5531, -1731, -4551, -4415, -5858, -5221, -3339, -4088, -5435, -4033, -6463, -4688, -4882, -8282, -4049, -8560, -3891, -6749, -9165, -6707, -8658, -2887, -8564, -7138, -10402, -6502, -2670, -9858, -6370, -4903, -4838, -3343, -10015, -6338, -3947, -4444, -5240, -7141, -7775, -4739, -5188, -6116, -4346, -12681, -6528, -6728, -3824, -2500, -6372, -8095, -9228, -2730, -1680, -4190, -7241, -11071, -2502, -1914, -3767, -4542, -8579, -2851, -3341, -4537, -3365, -7100, -4257, -5807, -6160, -3938, -6677, -8386, -5363, -6487, -5417, -4831, -5399, -3595, -6606, -5220, -4098, -3955, -2996, -6791, -5518, -4339, -2958, -3813, -5029, -4855, -6573, -2456, -5830, -3627, -3990, -10242, -2583, -6572, -3503, -3955, -5694, -3498, -5733, -4531, -4720, -4080, -4973, -6642, -6336, -5565, -3660, -5397, -11244, -7572, -5403, -3796, -4399, -9624, -6943, -4976, -4501, -3341, -7751, -6284, -4998, -6524, -2623, -7953, -6400, -5125, -13720, -2499, -7962, -6581, -4922, -9675, -3201, -6947, -6428, -4554, -8044, -5125, -5239, -7512, -4496, -6154, -8552, -3600, -12902, -5097, -3938, -6733, -2506, -12785, -7219, -2296, -6245, -2448, -8098, -6875, -793, -7453, -4342, -2270, -1398, 579, -2516, -2953, 237, 929, 1489, 27, 266, 986, 1584, 1656, 936, 1345, 322, 829, 893, 681, 786, -1675, -1400, -934, -484, -1650, -4605, -5233, -3661, -2148, -8273, -7098, -7983, -5542, -3463, -6495, -9317, -6325, -6176, -3798, -6445, -10349, -4891, -7107, -3570, -7094, -11108, -4375, -7870, -3322, -4857, -10823, -4363, -8390, -3422, -3691, -7608, -4723, -10417, -4252, -3535, -5257, -5565, -11499, -5773, -3891, -4566, -6740, -9103, -6320, -4558, -5707, -7907, -7989, -6022, -5807, -10570, -8858, -6677, -6372, -7130, -8773, -8440, -6381, -6672, -7034, -6078, -8636, -9076, -6136, -7177, -5651, -8736, -9553, -5450, -7590, -6840, -7336, -5381, -5011, -6630, -14294, -7488, -4801, -4871, -5848, -6136, -10098, -6286, -5008, -6046, -3235, -11529, -8986, -5317, -6412, -2186, -7462, -8587, -5614, -5608, -2127, -5546, -5993, -5602, -4895, -2768, -4953, -3879, -5369, -5200, -4091, -5580, -3164, -5477, -6772, -6470, -7886, -3903, -6183, -9649, -11308, -9200, -6437, -7719, -8945, -10678, -6182, -9302, -11853, -7614, -9572, -5189, -7009, -10482, -7855, -10849, -5754, -6670, -7654, -7960, -10133, -8021, -8450, -7492, -6982, -9424, -10234, -15495, -8411, -6733, -10228, -7509, -11577, -8767, -7567, -9477, -6263, -9487, -9857, -8789, -7763, -6036, -8615, -16894, -9219, -6594, -6453, -7945, -10252, -9583, -5649, -7061, -7302, -7813, -10419, -4963, -7236, -6595, -7004, -10903, -4924, -7947, -6179, -6655, -10453, -5878, -10923, -6142, -6372, -9527, -7202, -14480, -6401, -6149, -9032, -6310, -9481, -6657, -5984, -9602, -5378, -7495, -6427, -5769, -9697, -5650, -6850, -6403, -5592, -7339, -7131, -7150, -7731, -5749, -5664, -8298, -6849, -11449, -6429, -4910, -7086, -6298, -10534, -7720, -4908, -6514, -6999, -10839, -9769, -5924, -6860, -9561, -13612, -11400, -9204, -6920, -14357, -8162, -11150, -11068, -6493, -12766, -6878, -13047, -6942, -6884, -9274, -7453, -15660, -5989, -8558, -7535, -9432, -9547, -6401, -9898, -7434, -14187, -7718, -7893, -9707, -8867, -13166, -7538, -10498, -11141, -10755, -9815, -8900, -12875, -16967, -9262, -9781, -12291, -11937, -15404, -8060, -13327, -13354, -9920, -12630, -7888, -12745, -11948, -8216, -10002, -7989, -8788, -11573, -7404, -9210, -6686, -15004, -3289, -6328, -7919, -10176, -10887, -3489, -4414, -6566, -8259, -9697, -4196, -4142, -5503, -5290, -11864, -5981, -5954, -4598, -5677, -11430, -11060, -14555, -3737, -8789, -6780, -7117, -8086, -3108, -8413, -5414, -4226, -8755, -3056, -6295, -5370, -2921, -10658, -3642, -5938, -5817, -2362, -5959, -4464, -6230, -6351, -2305, -4802, -5318, -5661, -7355, -2605, -4648, -6030, -4788, -8877, -3153, -4318, -5904, -4916, -9187, -3968, -3807, -6158, -6283, -7416, -4581, -3478, -7312, -8938, -5776, -4128, -3614, -8987, -8870, -4994, -3576, -4325, -11480, -8343, -4380, -3152, -4685, -5002, -9948, -2766, -2348, -3502, -1091, -2435, -586, -914, -1095, 924, 162, 874, 420, 766, 1496, 868, 1184, 908, 1411, 666, 95, 131, 390, 762, -1920, -2085, -2922, -845, -1280, -7756, -4454, -16110, -1966, -4698, -6715, -3873, -5983, -2930, -5724, -6404, -2975, -5321, -4831, -4148, -8149, -2771, -6242, -8405, -2985, -11642, -3082, -7557, -10505, -2280, -10096, -3383, -5472, -15643, -2315, -5910, -3512, -4542, -9302, -3544, -4161, -4119, -5871, -6931, -7014, -3807, -6345, -9365, -7016, -10307, -4311, -9961, -7929, -7821, -5691, -5163, -6055, -8191, -8082, -4467, -6171, -4793, -9507, -9009, -4679, -7184, -4796, -7642, -11541, -6390, -7723, -5518, -7267, -10546, -7902, -8212, -6977, -8316, -7941, -5667, -8984, -8527, -8988, -6911, -4411, -8643, -6370, -8980, -7105, -3989, -8007, -4233, -8228, -7891, -4022, -8794, -3315, -6300, -7934, -4546, -11341, -3481, -5193, -7635, -5755, -12427, -4738, -5205, -8025, -8019, -10792, -7259, -5891, -8796, -13258, -7564, -11530, -6159, -9580, -11920, -5757, -17389, -5882, -11718, -8114, -5523, -15594, -6008, -10143, -6180, -6780, -17090, -6855, -7510, -5038, -8817, -11814, -7704, -6483, -4638, -7888, -8637, -7401, -6001, -5064, -6890, -6993, -7147, -5609, -6385, -7082, -6207, -7481, -5691, -7961, -8353, -5988, -7837, -6738, -7876, -11189, -5943, -7604, -9331, -7787, -19199, -5825, -7175, -12307, -8505, -11676, -5962, -6404, -9173, -8273, -9909, -6757, -5111, -8220, -8439, -9529, -8310, -4397, -8781, -9601, -10027, -9518, -4853, -9488, -6396, -11585, -8235, -6822, -10060, -4537, -9577, -6889, -10416, -8115, -4244, -7183, -6916, -8712, -5559, -5065, -6404, -7819, -6786, -4732, -6745, -6723, -6229, -6014, -5754, -8068, -7727, -4706, -6080, -9574, -6889, -9382, -4416, -6628, -7227, -5957, -10909, -4928, -6618, -5124, -6000, -10310, -5733, -5841, -5155, -6098, -9824, -6774, -5344, -7076, -5466, -9382, -8830, -5583, -13008, -5116, -9364, -14598, -6627, -10457, -5703, -10925, -13134, -7897, -9338, -7078, -17766, -11047, -8228, -10926, -7312, -12329, -10043, -8854, -14096, -6377, -9246, -8903, -12360, -12308, -6179, -7824, -7904, -11876, -9138, -6918, -7406, -6685, -7622, -7962, -8100, -8250, -5658, -6581, -8677, -8669, -11653, -5213, -7600, -11726, -9502, -6275, -7459, -7000, -6470, -3903, -4611, -8854, -5266, -3553, -3567, -3870, -4951, -3609, -2416, -4242, -4366, -4804, -3320, -2270, -5967, -6275, -6972, -4166, -3256, -8507, -10171, -12115, -5676, -6261, -8439, -11299, -12043, -7006, -8492, -5927, -10517, -10697, -7794, -4872, -3723, -11855, -6608, -8993, -3744, -2358, -13710, -4703, -11678, -3516, -1921, -10297, -4260, -14057, -3549, -2336, -7447, -5051, -12593, -3527, -3366, -6283, -7371, -9834, -3390, -4634, -6581, -9859, -7409, -3297, -5936, -8880, -6768, -5974, -3285, -6690, -13443, -5505, -5455, -2978, -6634, -11797, -7806, -6402, -2254, -6693, -7806, -5050, -6959, -1229, -6141, -2174, -264, -2380, 89, -2592, 260, 1781, 74, 1016, -20, 921, 2414, 1007, 941, 1072, 9, 1957, 705, -553, 924, -2636, 564, -799, -4597, -202, -5387, -1546, -3587, -7025, -1771, -6066, -3644, -7205, -3911, -3331, -9450, -4568, -8048, -3349, -4854, -7175, -5245, -7936, -3646, -6327, -6008, -6570, -8861, -4621, -11767, -7183, -7459, -9946, -5893, -6739, -11369, -7622, -9559, -5931, -3608, -13936, -8468, -8911, -4742, -2750, -10183, -10097, -8682, -4374, -2987, -9181, -8548, -8794, -5678, -3069, -8990, -5410, -10167, -9059, -2481, -10011, -3681, -11519, -7713, -2240, -12961, -3158, -7402, -7225, -2629, -14315, -3664, -4975, -8061, -3591, -8715, -5158, -3513, -6182, -5211, -6693, -7881, -2674, -4835, -7763, -6634, -13779, -2476, -4538, -10107, -9065, -12637, -3083, -4685, -6531, -13953, -9700, -4730, -4943, -4833, -7463, -8389, -7154, -5426, -5212, -5979, -7985, -7362, -6888, -8907, -5809, -8836, -7039, -10232, -9569, -6110, -10164, -7723, -6606, -5848, -6181, -8551, -9132, -4796, -5085, -5711, -7127, -12411, -5076, -5321, -5106, -7060, -8607, -7079, -7071, -4767, -8634, -5752, -7579, -8468, -4796, -9544, -5016, -6526, -4435, -5263, -7770, -5677, -6851, -2722, -6394, -7830, -5973, -6828, -2351, -7826, -8200, -4993, -5965, -2867, -7129, -6373, -4708, -5973, -3666, -6375, -5292, -5314, -6838, -3734, -7316, -5384, -6269, -7531, -3386, -10330, -6284, -7143, -7886, -3446, -9316, -7264, -8282, -7969, -3961, -8354, -7454, -9326, -7048, -4575, -9967, -6846, -9308, -6015, -5682, -12094, -6182, -9574, -5562, -8455, -10098, -6251, -8823, -5788, -7933, -10115, -7438, -7179, -5798, -6256, -12729, -9670, -6641, -4424, -6670, -16869, -11702, -7349, -3136, -8626, -11379, -12571, -8894, -2706, -10776, -9858, -12632, -10360, -3202, -9852, -9656, -14351, -11892, -4516, -8120, -10112, -9196, -14718, -6029, -7326, -11073, -6167, -20010, -7015, -7571, -13288, -4933, -16628, -8164, -8158, -15866, -4808, -13887, -8859, -8671, -13006, -5320, -12181, -7866, -10275, -11071, -5975, -11702, -6915, -13457, -9700, -6806, -12271, -6528, -11149, -8831, -8396, -13721, -6934, -8250, -8454, -9442, -13972, -9042, -6740, -8719, -7705, -11615, -17335, -6696, -9993, -6648, -9134, -8087, -7929, 11499, 9653, 11787, 11865, 10918, 10750, 9748, 11068, 11240, 10364, 8109, 9531, 8698, 9336, 8658, -392, 8420, 3495, 6224, 6048, 4468, 6188, -2829, 2992, 4944, 4836, 2886, -1034, 852, 4834, 3423, -314, 929, -354, 3400, 2873, -1496, 1653, 65, -323, 689, -2183, 2935, 767, -6658, -226, -1673, 3889, 816, -6654, 5189, 544, 3523, 1694, 727, 7001, 1280, 3374, 3183, 4394, 7543, 2819, 4609, 4414, 6201, 7338, 5335, 5343, 5008, 6784, 6524, 6594, 5248, 4727, 6186, 4964, 6532, 4685, 3373, 4034, 2635, 5338, 4042, 439, -1698, 1519, 3675, 3143, -3463, -868, 1737, 2813, 1237, 612, 987, 1363, 2305, -3363, 2166, 1556, 1643, 2080, -5536, 2433, 1979, 2425, 2309, -3356, 2424, 956, 2375, 2323, -5877, 2676, -9137, 1643, 1847, -2948, 2781, 1636, 1445, 565, -278, 2290, 4161, 1827, -51, 118, 1184, 4603, 2057, 2119, -766, 999, 3517, 1918, 3192, -1961, 1741, 351, 1084, 2772, -5075, 1823, -9009, -3, 1315, -3513, 1715, -3156, 754, 666, -1, 2060, -6758, 1223, 3, 894, 2448, -4417, -629, -2904, 789, 2644, -1501, -4193, -1362, 779, 2463, -342, 741, -280, 657, 1614, 444, 1940, -2432, -386, 302, 300, 1661, -5600, -2648, -116, -1426, 728, -517, -5816, 42, -8691, -478, 1020, -5590, -492, -2680, -2624, 1193, -3778, -1788, 222, -9612, 248, -3523, -2310, 1328, -4828, -1791, -4731, -1546, 1500, -3774, -4803, -6916, -1462, 950, -6641, -4848, -8218, -1770, 222, -7771, -1963, -6686, -921, 557, -3923, -756, -4622, 123, 1229, -2846, -872, -3909, 554, 1169, -2433, -1846, -5745, 413, 243, -2080, -2755, -6614, -278, -1394, -1921, -2331, -1802, -1389, -2957, -2013, -1209, -272, -2419, -2893, -1213, -627, -236, -2201, -2356, -14, -707, -987, -752, -2093, 439, -940, -1989, 234, -1770, 82, -885, -3121, 317, -1690, -747, -680, -4513, -297, -2330, -1287, -546, -7327, -631, -3621, -1505, -658, -4254, -147, -4817, -2767, -1298, -1704, 213, -5047, -6312, -2616, -1171, 99, -4591, -4520, -3856, -2233, -602, -4570, -3047, -4603, -5501, -2062, -4365, -3248, -5468, -13943, -3893, -2743, -3891, -4549, -8014, -5236, -1218, -3439, -4507, -10182, -5271, -339, -2017, -6499, -6396, -3095, 51, -1278, -5234, -4433, -1926, 180, -1582, -4112, -5251, -1997, 117, -3012, -4723, -5486, -2358, -140, -6067, -5077, -2875, -2262, -540, -4332, -4377, -2761, -2777, -1175, -1347, -4245, -6137, -3431, -2252, 198, -5646, -2423, -1844, -3110, 896, -10059, 0, -490, -2063, 662, -7959, 293, -39, -1037, -1028, -5465, -943, -84, -1061, -5569, -3676, -3524, -278, -2353, -4143, -3071, -6214, -1188, -5856, -2726, -4220, -11237, -4123, -9832, -3171, -6078, -4947, -2949, -10897, 1986, 7534, 7994, 8395, 5655, 1586, 6803, 7469, 7696, 4993, 986, 4683, 6042, 5302, 3663, 1176, 4020, 4165, -290, 3540, 1354, 5071, 1972, 1624, 3711, 1165, 4944, -498, 2650, 3436, 1305, 3929, -780, 2245, 3125, 2022, 2784, 1021, 1914, 2896, 2842, 2606, 2544, 1909, 2503, 3458, 2577, 3509, 1162, 2278, 4319, 2777, 4320, -1679, 3341, 5631, 4337, 5485, 591, 4894, 6571, 5188, 6487, 2665, 5846, 6695, 4848, 6546, 2448, 6016, 6031, 3962, 5257, 374, 5518, 4941, 3891, 1946, -1263, 4519, 4092, 3892, -9767, -732, 3047, 3742, 2274, -3403, 28, 1256, 3246, -4496, -6805, 1456, 9, 2179, -172, -5004, 2240, -1027, 1634, -109, -3777, 2227, -2661, 1529, -2955, -4061, 1781, -4333, -54, 227, -4123, 1286, -2738, -3606, 548, -7285, 702, 202, -2746, -36, -1668, -116, 2048, -502, 1178, -760, 320, 3206, 1792, 1855, -4693, 1439, 3944, 3000, 1660, -2152, 1418, 4259, 3060, 927, -29, -23, 4053, 2125, -517, -1139, -1610, 3269, 301, -1313, -3676, -661, 1878, -2420, 858, -3865, 454, -397, -6488, 1913, -3258, 1317, -4907, -6205, 1205, -992, 1933, -2414, -2780, -2487, 70, 2028, 163, -680, -3970, 142, 1003, 843, 334, -195, -40, -3085, 301, 112, -43, -188, -1548, -1011, -1459, -1898, -666, 1611, -2204, -1343, -6526, -1699, 2298, -2599, 591, -7144, -2901, 1715, -1844, 1237, -4046, -3598, 179, -140, 759, -2406, -3075, -2445, 1180, -335, -1952, -1899, -5612, 1415, -1094, -2214, -1360, -1893, 203, -1459, -1069, -1757, 481, -3330, -2097, 752, -2767, 1624, -7473, -1792, 1782, -2900, 1889, -7712, -101, 1912, -2068, 1430, -5585, 1149, 1283, -1498, 397, -866, 1524, 568, -963, -1106, 495, 954, 497, -188, -3461, -19, -412, 139, 324, -10632, -2949, -900, -1303, -35, -4678, -7384, -163, -3549, -1866, -2417, -2039, -90, -4801, -7138, -2238, -767, -899, -3789, -5957, -2726, -570, -2445, -1632, -2991, -2995, -898, -4903, -717, -1806, -1742, -1512, -8493, -1379, -1798, 585, -1549, -5539, -3625, -3504, 1770, -763, -3517, -3105, -8456, 1591, -119, -3114, -1345, -7055, 92, -21, -4398, -782, -9520, -2433, -808, -6538, -902, -6864, -4298, -3229, -2854, -1191, -3592, -3995, -7376, -1294, -667, -3069, -3510, -3439, -1592, -26, -2002, -4369, -1857, -2227, -397, -443, -3309, -1476, -1091, -2056, 221, -1094, -2369, -668, -4218, -5, -716, -6260, -1626, -3114, -970, -2628, -5218, -2561, -1129, -2134, -2523, -2555, -2529, 148, -2205, 324, -2183, -3484, 433, -2391, 994, -2104, -4388, -687, -4433, -147, -1845, -2974, -4487, -13025, -4452, -1215, -1607, -5702, -5079, -4621, -8, -769, -2473, -2682, -1284, 552, -657, -1852, -1952, -775, -338, 3403, 4132, 7641, 778, 5289, 2552, 4145, 7421, 2383, 6068, 4670, 4212, 7130, 4931, 6997, 6328, 4373, 6985, 5898, 7176, 6003, 4155, 6359, 5214, 6490, 3584, 2785, 4682, 2921, 4968, -3986, -778, 1301, -742, 3260, -539, -3989, -6344, -2274, 2502, -875, -1955, -2882, -434, 1798, -3591, -1851, -1994, 1043, 958, 3027, -70, 38, 2360, 1125, 5424, 2700, 1757, 2968, 1329, 6100, 4469, 1807, 2654, 1037, 5305, 4858, -175, 2820, 2749, 2728, 3599, 755, 3658, 4815, -3318, 76, 2620, 3579, 5670, -6116, 599, 2350, 2258, 5308, -2952, 1593, -76, 344, 3740, -1295, 197, -7631, -293, 1431, -414, -2083, -4705, -32, 454, 1193, -1037, -2916, 140, -87, 2307, -23, -1998, -320, -18, 2491, 240, -1222, -2065, 924, 1975, -38, -567, -6414, 1177, 977, -812, -86, -2158, 1569, -272, -2074, 62, 217, 2576, -712, -3867, -198, 1022, 2926, -117, -3578, -924, 905, 2160, -125, -1289, -2054, 12, 982, -1563, -215, -2503, -1765, 993, -6099, -47, -1659, -4728, 1308, -6373, -203, -670, -5335, 1637, -2661, -739, 229, -3261, 1850, -1322, -2303, 947, -1527, 1748, -928, -5554, 1239, 616, 2135, -1827, -11079, 834, 2152, 2999, -5832, -6189, -473, 2630, 3320, -3403, -2728, -1400, 2094, 2477, -572, -1483, -13, 1139, -474, 25, -1786, 1043, 931, -2991, -845, -3318, 1407, 776, 1042, -2630, -4489, 1405, -256, 2424, -987, -2810, 1333, -2287, 2747, 512, -1553, 1549, -5824, 2282, 279, -2049, 1871, -3869, 900, -1724, -5113, 1702, -1201, -1600, -2784, -3388, 568, -172, -2220, -895, -1663, -2290, 292, -362, -418, -2568, -9930, 580, 503, -1227, -7070, -2603, 429, 437, -2729, -5947, -436, -295, -560, -2611, -3597, 571, -1311, -2955, -1634, -2500, 779, -2367, -6798, -1580, -1228, 83, -3626, -2730, -1961, -159, -1607, -4533, -689, -1789, 222, -2814, -4019, 358, -1588, -452, -1013, -4088, 995, -2319, -2726, 767, -6820, 974, -4507, -8398, 1631, -11130, -303, -2578, -6953, 1518, -6724, -3262, -327, -6716, 421, -8780, -1524, 193, -8230, -1594, -5833, 225, -690, -4076, -3241, -2524, 550, -3379, -1911, -2869, -975, 320, -6486, -1262, -3444, -392, -71, -2338, -1737, -7273, -902, -761, -805, -3112, -5322, -3132, -1739, -753, -4756, -3052, -3407, -2524, -1795, -7989, -2173, -957, -2388, -3114, -6050, -1001, -97, -1763, -3563, -1277, -227, -19, -1780, -4053, 280, -333, -629, -3246, -5652, -96, -1690, -2562, -4260, -11515, -3068, -6057, -6844, -1570, -6403, -7864, -5955, -5304, -902, -3614, -3309, -3410, -4326, -2882, -2501, -2023, -1490, -3336, -7164, -1740, -36, 312, -1321, -2026, -1151, 996, 668, -883, -890, -1372, 643, -586, -3064, -910, -3402, -4482, -2190, -1270, -4262, -3070, -4590, -2040, -2520, -946, -3274, -9669, -4249, -9697, -56, -3661, -5978, -4859, -3848, -493, -3439, -3542, -2771, -1509, -504, -3120, -3970, -2516, -560, 163, -2938, -6862, -2398, -958, 411, -2723, -11590, -1025, -3975, 1108, -3014, -6531, 310, -5335, 1975, -3553, -4511, 957, -1340, 1873, -3638, -4597, 887, -704, 258, -5787, -7724, 248, -1979, -4020, -5723, -4889, -576, -6030, -5557, -1752, -1896, -1048, -5583, -3021, -961, -879, -994, -2977, -1828, -2324, -1161, -756, -2567, -894, -8329, -3006, -890, -3048, -336, -2419, -12398, -1434, -2230, 342, 771, -2734, -174, 527, 1344, 2390, -223, 1634, 2317, 2073, 3055, 210, 2246, 2721, 1891, 2870, -912, 1627, 1673, 245, 1928, -3573, -115, -1050, -3564, 507, -6432, -3262, -4038, -2351, -1054, -6372, -8754, -4753, -938, -2769, -7193, -2761, -4473, -1032, -3845, -10328, -1095, -2632, -1692, -3653, -2631, -1126, -2259, -2446, -3893, -256, -2771, -3310, -2791, -4961, 361, -8126, -5707, -2611, -5749, -245, -7360, -6102, -2940, -5490, -1830, -6736, -4501, -4546, -5568, -4055, -6866, -4259, -6523, -5735, -6537, -2456, -3944, -4694, -5152, -6281, -791, -2729, -3326, -5147, -4384, -636, -1952, -3614, -6397, -3150, -1511, -1616, -7073, -4951, -2081, -2980, -1332, -7338, -2755, -1670, -4406, -1259, -3640, -1452, -2662, -5710, -1451, -3615, -261, -5548, -7769, -1585, -5654, 706, -3476, -12844, -1737, -4974, 1109, -1569, -10018, -2414, -4155, 931, -1372, -8834, -4007, -7511, 348, -2417, -19835, -6770, -5193, -391, -4759, -5253, -7132, -1173, -1144, -7689, -1769, -4823, 228, -1928, -6624, -170, -3580, 522, -2723, -5276, 133, -3197, 312, -3832, -5133, -786, -3275, 86, -6741, -5275, -2979, -3246, -15, -9085, -3240, -6076, -2781, -346, -4076, -2116, -6898, -1822, -1476, -2444, -2481, -5099, -863, -3556, -1673, -3676, -3843, -402, -3266, -1569, -4468, -2131, -551, -2215, -3039, -4968, -340, -1284, -2389, -8551, -5841, 652, -2084, -3633, -3304, -6153, 803, -1768, -9006, -1361, -4735, 202, -833, -4478, -1044, -3627, -1151, -16, -1493, -1415, -3147, -3442, 294, -1194, -2076, -3305, -6063, -281, -2926, -2664, -4702, -3915, -1898, -6565, -2405, -6927, -2282, -3991, -4178, -1692, -5166, -2072, -5567, -3102, -1571, -4346, -2848, -8095, -4080, -2244, -5297, -3728, -11771, -6981, -3029, -8705, -3791, -10247, -6713, -3057, -9979, -3672, -6229, -4608, -3131, -5419, -4169, -4738, -3996, -4066, -3853, -5631, -5869, -5689, -6247, -3266, -7684, -20323, -11907, -7206, -2894, -8001, -5255, -3943, -5052, -2472, -5833, -3593, -2379, -3961, -2063, -4117, -4113, -2539, -3763, -1759, -4145, -4780, -3799, -3579, -1678, -7482, -3796, -5995, -3003, -2008, -6027, -3836, -9554, -3075, -3017, -2896, -5702, -14625, -1504, -2360, -3044, -1487, -4265, -3225, -3986, -9075, -3210, -4127, -2464, -6521, -5388, -6423, -916, -408, -6156, -3486, -9355, -571, 552, -4207, -4319, -8203, -1147, 569, -2249, -4905, -6750, -937, -72, -543, -2242, -4041, -863, -1216, 432, 114, -2699, -2014, -3629, 418, 1352, -3433, -2727, -10814, -681, 1366, -6282, -1958, -2590, -2952, -6, -3716, -2224, -513, -6937, -3433, -2625, -4043, -163, -7808, -13572, -3488, -9508, -1117, -3808, -5312, -4816, -6499, -2760, -1250, -3357, -2952, -2767, -2385, 163, -1731, -865, -1248, -1202, 216, -691, -552, -359, -1048, -1285, -1002, -3070, 1192, -999, -682, -3304, -1531, 2877, 478, 1448, -1240, 1840, 3908, 1324, 1752, 1094, 2880, 4142, 771, 68, 1497, 2483, 3577, -1142, -4927, 401, 872, 2279, -3574, -4789, -1818, -1422, 578, -4474, -4161, -2381, -2721, -792, -3274, -4035, -1915, -2841, -1498, -1655, -3202, -2845, -1530, -2122, -731, -4220, -4852, -346, -3911, -488, -8410, -3948, 17, -11601, -1054, -6930, -2428, -223, -4265, -3181, -5540, -1608, -827, -2590, -7168, -6787, -955, -1883, -2828, -1763, -8574, -293, -4050, -3295, 197, -4504, 297, -6437, -3468, 640, -2015, 398, -3753, -4356, 188, -1034, -732, -2281, -6113, -672, -1381, -4975, -1556, -7557, -1508, -2985, -3857, -829, -5404, -2414, -5159, -1358, 231, -3005, -3667, -5494, -1721, 1210, -1657, -2840, -4258, -4395, 1572, -946, -1003, -4242, -6830, 1068, -494, -228, -7851, -4250, -530, -338, -381, -6428, -3621, -3439, -768, -1361, -3066, -4154, -4575, -2020, -3706, -2565, -5873, -4091, -3450, -8764, -3454, -11360, -3994, -2473, -2757, -5121, -9430, -2536, -1171, -226, -6409, -6764, -1856, -666, 1078, -4370, -4805, -2973, -793, 1676, -2813, -3727, -5223, -1648, 1649, -2899, -4746, -2938, -3744, 960, -4358, -6558, -1958, -7719, -587, -4615, -3112, -2844, -8827, -3886, -3787, -1491, -5185, -4575, -6683, -4287, -1159, -6972, -1822, -2712, -6079, -1790, -7969, -556, -1786, -7156, -3885, -6150, -504, -1647, -6708, -10546, -3778, -1648, -662, -6693, -4053, -3151, -2948, 216, -6619, -2100, -4161, -2211, 7, -6241, -2150, -7819, -1901, -1619, -5625, -4201, -9236, -2125, -5359, -4772, -20035, -6203, -1695, -8961, -3936, -4620, -8137, -1423, -7771, -3168, -2625, -7866, -1884, -10407, -2637, -2134, -3678, -2511, -4562, -2875, -2186, -2574, -2759, -1385, -4470, -2603, -2829, -2964, -151, -5713, -3902, -4024, -2960, -285, -4488, -7391, -6273, -2378, -1600, -5924, -6123, -8840, -1575, -4013, -10024, -3258, -8351, -1241, -8567, -3585, -2348, -6904, -2097, -7621, -2694, -2456, -5419, -5432, -2881, -4705, -3130, -4781, -9225, -949, -11217, -3993, -5228, -5395, -421, -3792, -4698, -6520, -6366, -1110, -2417, -5091, -7604, -8282, -3182, -2698, -5569, -7999, -6149, -3058, -1149, -2782, -5494, -1655, -5423, -4878, -2823, -425, -4758, -4616, -5470, -3528, 1229, -4878, -3694, -2318, -7757, 1559, -807, -1796, -428, -3529, 926, 319, -670, 610, -1132, -507, -59, -806, 775, -582, -1285, -1894, -1604, -11, -1141, -280, -4756, -2209, -1942, -1683, 395, -4392, -3263, -5611, -859, 232, -5596, -6205, -10941, 8, -890, -9871, -9277, -6377, 262, -3581, -4485, -3242, -3582, -180, -7947, -3244, -492, -2391, -1929, -2648, -2125, 1089, -2467, -7535, -184, -1467, 1949, -3488, -1853, 927, -1118, 2048, -5434, -232, 1105, 12, 1109, -8568, -1789, 588, 134, -54, -1893, -2458, 90, -2350, 1154, 1134, 1625, 861, -2206, 1874, 2340, 2891, 1827, 813, 1064, 2174, 2645, 2115, 1368, -1399, 752, 1734, 1801, 465, -4924, -1875, 1555, 987, -998, -3232, -5678, 1800, -332, -737, -1065, -4665, 1480, -1490, 7, -36, -2542, 608, -1714, -508, 265, -2403, -86, -2104, -2181, 70, -4109, 53, -2358, -179, -995, -5926, 423, -1358, 1566, -3229, -3574, 424, -385, 1563, -2794, -2277, -289, 57, 211, -1662, -1919, -2226, 214, -608, -2548, -1864, -5770, 128, -489, -5510, -1845, -4538, -522, -1573, -2361, -2327, -3159, -2097, -2126, -19, -3712, -2801, -5200, -529, 895, -4192, -3067, -14878, 331, 844, -2237, -4676, -5338, 164, -106, -889, -10372, -2762, -871, -1700, -574, -4661, -1659, -1252, -2037, -1288, -1745, -1741, -415, -1122, -1881, -221, -2879, -431, -795, -27, 586, -2664, -1936, -1383, 1453, 760, -877, -5747, -3279, 1713, 230, 48, -9848, -6121, 743, -1223, 33, -6267, -4083, -1491, -4338, -683, -3873, -3319, -3890, -10951, -1470, -2171, -4353, -4587, -6234, -1877, -1456, -6665, -4400, -6122, -2562, -1490, -9262, -2215, -8824, -2936, -2028, -5486, -970, -12518, -1587, -2449, -3870, -1006, -5513, -81, -1884, -5070, -1852, -2270, 846, -1583, -9725, -2673, -446, 1035, -2785, -3642, -3626, 299, 384, -4071, -1697, -5615, 0, -845, -1718, -1073, -7410, -1367, -1028, -814, -935, -6894, -3471, -398, -1648, -916, -3548, -6133, -728, -4499, -965, -830, -6958, -2693, -7097, -1111, 409, -3086, -6713, -4160, -1165, 298, -1895, -3881, -2976, -907, -1067, -2241, -1851, -2797, -502, -2215, -3381, -910, -3517, -345, -1448, -4587, -507, -4985, -745, -742, -5417, -460, -4953, -1722, -290, -5442, -719, -2865, -2546, -433, -6672, -1408, -930, -2768, -1687, -15512, -2698, 113, -3871, -4079, -5756, -4240, 71, -8233, -6080, -4337, -4508, -951, -6482, -6111, -5045, -3690, -1837, -3879, -3679, -6100, -3119, -1430, -3633, -2205, -5399, -3187, -1123, -4720, -2134, -4594, -3773, -1525, -7034, -3457, -4808, -4327, -2954, -13724, -6477, -6667, -4058, -6774, -6851, -6498, -11831, -3388, -5873, 4533, 15493, 7130, 11099, 10872, 8971, 15079, 7409, 10372, 10215, 10477, 13792, 7275, 7939, 8110, 10115, 11471, 5974, 2071, 4093, 8807, 7904, 3893, -401, 596, 7640, 6406, 2632, 291, 246, 6353, 7830, 1705, 498, -2133, 5933, 8178, -99, 1669, -1466, 7015, 7495, -3209, 1380, 906, 6642, 5809, -2085, 420, 2649, 3011, 3101, 467, 890, 4060, 2610, 1239, 3134, 2438, 5095, 6134, 4168, 4923, 3666, 5672, 6390, 6574, 5504, 4339, 5666, 5175, 7432, 4771, 4364, 4716, 3611, 6811, 2487, 3671, 2068, 2734, 4441, 897, 2214, -1551, 1422, -1480, 1980, 145, 404, -1713, -829, 1479, -1429, -400, -2830, -620, -980, -1508, -4595, -937, -4509, -5950, -843, -3942, -436, -956, -3109, -86, -2002, -692, 253, -1534, 309, -1370, -1942, -1167, -2427, 197, -874, -4390, -7899, -2739, -461, -450, -4445, -2005, 564, -1706, -673, -4643, 937, 1953, -3334, -2247, -9197, 2447, 1896, -3203, -7384, -2865, 3140, 702, -1405, -4796, -1206, 3044, -1300, -192, -2152, -1597, 2136, -2908, 125, -1193, -3364, 442, -2540, -592, -655, -6300, -1686, -1452, -2733, -319, -2385, -3504, -1146, -6747, -114, 418, -6151, -1916, -7425, -50, 1525, -8056, -3061, -8010, -273, 1413, -4908, -3606, -8036, -740, 45, -4499, -3707, -9333, -1100, -3493, -4605, -2349, -7706, -1075, -5940, -4116, -1488, -4490, -1074, -2420, -4716, -2222, -4322, -1688, -1937, -7574, -5472, -7708, -3210, -2954, -9068, -8547, -8071, -5093, -4749, -6216, -4839, -4324, -4994, -4740, -5370, -4755, -3714, -4619, -3586, -5709, -6445, -4542, -5527, -3203, -6705, -7296, -6022, -7614, -3491, -7190, -5463, -5318, -7737, -3294, -6641, -3769, -3574, -6598, -2733, -6292, -2699, -2511, -6223, -3322, -7125, -2528, -1985, -6367, -6489, -9032, -3192, -1758, -6932, -10492, -10363, -3831, -1862, -7547, -5582, -7436, -3718, -2684, -7591, -4955, -4703, -3850, -5169, -7156, -5282, -3324, -4932, -15759, -6365, -5603, -2636, -7772, -5235, -5242, -5591, -2536, -7604, -3910, -4440, -5019, -3328, -4982, -4552, -4531, -4227, -5154, -4938, -6666, -5498, -4315, -7384, -6805, -10403, -6424, -6270, -8430, -6066, -14886, -5957, -8237, -9381, -4709, -7991, -4773, -6516, -15946, -5086, -4770, -4046, -7510, -8213, -7473, -3115, -3811, -5936, -6036, -13292, -2612, -3598, -3212, -6093, -7140, -2970, -3330, -2197, -7069, -5339, -3798, -3249, -2596, -7484, -4894, -4503, -3658, -4898, -7717, -5436, -4681, -5182, -7703, -9217, -6569, -4421, -10267, -4587, -15266, -5999, -3847, -8154, -4051, -14168, -5103, -3525, -4809, -5255, -9670, -5175, -3853, -3862, -7668, -5919, -5897, -4642, -4121, -8586, -4629, -7287, -5715, -5258, -7177, -5460, -9161, -7852, -7043, -6614, -7702, -10597, -16619, -8897, -6982, -6417, -13152, -8491, -8037, -7590, -5676, -7926, -5771, -7079, 8378, 264, 6883, 11011, 8143, 7556, 1695, 6137, 10467, 7604, 4780, 3511, 3566, 8760, 5905, -1905, 4481, 1645, 5576, 3317, -5876, 4662, 3831, 483, 3090, -657, 4234, 4030, 917, 3836, 2385, 3349, 2513, 2198, 3803, 3375, 2196, -346, 2695, 3488, 3584, 819, -176, 2702, 3452, 2746, 335, -412, 2651, 3857, 1787, 2832, 1422, 3444, 4373, 5252, 4678, 5194, 4458, 4573, 7185, 5288, 6970, 4627, 4164, 7558, 4889, 7263, 3451, 2960, 6666, 3846, 6129, 1351, 758, 4646, 2817, 2960, 2364, -3368, 1865, 2292, -15868, 3155, -5752, -564, 1822, -116, 2577, -2844, -2178, 610, -161, 1399, -2842, -3605, -1454, -690, 520, -2531, -955, -1400, -539, -353, -1441, 1152, -124, -2240, -2051, -868, 1843, 464, -11447, -4585, -824, 1495, 678, -1738, -5301, -1185, 281, 745, -280, -5586, -1797, -1825, 459, -992, -6544, -2607, -5670, -649, -4226, -6437, -4093, -9434, -2416, -5874, -4257, -7643, -4370, -1347, -2625, -2606, -5330, -3094, 283, -2130, -1978, -2963, -3396, 824, -3189, -1573, -2398, -5621, 448, -5830, -798, -2397, -12478, -642, -10395, -161, -1970, -5002, -2176, -11549, -242, -785, -3316, -4916, -7381, -1520, 502, -2597, -9442, -4302, -5125, 1082, -1579, -3107, -2656, -2112, 665, -1043, -2269, -1962, 1021, -494, -1698, -4389, -2045, 2453, -1441, -4094, -4653, -3063, 2833, -2423, -13200, -2195, -5171, 2263, -4770, -6279, -2685, -4206, 699, -11234, -4126, -5226, -2200, -889, -6141, -3336, -2471, -1746, -560, -3305, -3339, -1170, -2899, -506, -3067, -4504, -2083, -7249, -1161, -4422, -7364, -6452, -7606, -1149, -5031, -7721, -5413, -4786, -466, -5029, -5662, -2999, -6071, -230, -5115, -4645, -3330, -11883, -811, -4326, -4105, -5245, -6769, -2428, -3992, -4199, -6936, -6518, -5211, -4770, -5177, -5351, -9277, -5506, -7365, -5638, -2906, -9850, -3555, -18071, -4137, -2140, -6688, -2506, -11084, -3154, -3833, -4152, -2146, -9314, -3232, -7623, -2662, -2270, -6701, -4756, -2688, -2446, -2726, -5357, -10055, -1806, -3670, -3392, -5184, -7186, -3235, -6329, -4180, -5034, -5349, -8245, -7533, -4973, -4501, -5329, -6564, -8702, -5175, -4938, -4572, -3817, -13587, -3909, -6498, -3654, -2700, -8833, -2464, -4797, -3378, -2376, -7217, -1812, -3428, -3628, -2944, -6491, -2063, -3960, -3761, -4608, -6658, -3034, -6518, -2849, -6431, -8580, -3801, -7431, -2009, -6121, -16045, -3344, -5560, -2096, -5897, -10675, -2850, -5160, -3323, -6165, -8817, -3093, -5969, -6089, -6663, -8860, -4081, -8848, -13227, -7866, -10554, -5060, -9306, -10594, -9882, -12794, -4854, -5107, -7765, -7546, -9109, -4704, -3508, -6253, -4799, -6608, -5836, -3334, -5350, -3322, -5327, -9282, -4326, -4660, -2846, -5363, -7109, -5836, -3927, -3251, -7120, -4339, -5865, -3254, -4504, -9555, -3564, -5144, 1256, 8194, 9051, 8438, 6129, 650, 7937, 8480, 7806, 6110, 593, 6913, 6782, 5746, 5680, 1396, 4326, 4193, 1459, 4087, 699, -3885, 2269, -3077, 178, -1300, 2669, 2316, -3257, 1229, -395, 4207, 1878, -348, 2806, -745, 3878, -490, 2326, 2043, -6821, 2190, -9079, 2726, -404, 2215, 355, -1577, 2680, 1752, 5378, 1813, 1864, 4276, 4284, 6994, 4431, 3807, 5208, 5306, 7530, 5770, 4359, 4429, 4896, 6988, 5456, 3166, 388, 2751, 5161, 2708, -623, -360, 3728, 1734, -3842, 1396, 2724, 6103, -350, 2628, 2636, 1996, 6816, -647, 3185, 1600, -2459, 6482, -3023, 2185, -1368, -3164, 5709, -7149, 372, -6559, -756, 4888, -5411, -2287, -12196, -1359, 3713, -2871, -4511, -9419, -3677, 1748, -2653, -5209, -5848, -5567, -924, -4604, -8946, -3825, -3525, -2421, -15332, -4285, -2637, -2461, -1599, -5356, -2543, -1760, -1539, -2080, -2989, -3332, -1242, -553, -7473, -2254, -4298, -1333, 51, -966, -2558, -1966, -1802, 158, 1360, -3677, -1343, -2179, -240, 1463, -4227, -2395, -2938, -1199, -487, -3520, -3483, -4805, -2796, -7193, -2827, -3956, -7252, -5226, -2860, -2057, -5333, -12403, -8461, -1370, -1333, -4898, -4867, -4416, -1209, -1339, -4761, -1651, -1420, -763, -2458, -3962, -610, 30, -99, -4593, -2531, -997, 341, -220, -6698, -3370, -2282, -267, -1783, -5861, -10912, -1765, -1616, -2858, -4350, -3667, -232, -3596, -457, -4035, -2491, -17, -4169, 839, -4041, -4380, -1642, -2772, 1037, -3197, -3931, -6408, -1924, 423, -1948, -1864, -4142, -621, -571, -1301, -2064, -2997, 731, -961, -1589, -4497, -4267, 1250, -926, -2992, -8958, -8864, 917, -1474, -7457, -6750, -7896, 44, -2788, -5957, -6933, -5080, -899, -4510, -2528, -7146, -4167, -1538, -5667, -2113, -6172, -3159, -2182, -5590, -3646, -5813, -2198, -3796, -5537, -7502, -5014, -1999, -8334, -5487, -8382, -4255, -2704, -10080, -4584, -7250, -4315, -4114, -7922, -3508, -7169, -4759, -5307, -12536, -2807, -5831, -4859, -4921, -8245, -2569, -4107, -4743, -4018, -5103, -3040, -3088, -5043, -3730, -3963, -4918, -2810, -6461, -4368, -3629, -10136, -2912, -10574, -6007, -3890, -5810, -3042, -11332, -8360, -4947, -3876, -3399, -7554, -10480, -6989, -3516, -4362, -5965, -12544, -6735, -3533, -5859, -5315, -14505, -4827, -3209, -7345, -5893, -14616, -4171, -3017, -9808, -8271, -13590, -4636, -3677, -14120, -9644, -9215, -6100, -5605, -12666, -8331, -6548, -8048, -7381, -10863, -10016, -5139, -7709, -5938, -6204, -15211, -4551, -6454, -4807, -4875, -8887, -4491, -6128, -3721, -5659, -7500, -4682, -6747, -2556, -7675, -6139, -4864, -7890, -1964, -6667, -4402, -5188, -8256, -2320, -4996, -3710, -6703, -7762, -3806, -4001, -4335, -11670, -7648, -6396, -3930, -6030, -5334, -8387, -8283, -5021, -7927, -3020, -9673, -7495, -8041, -6548, -6351, -4577, -6923, -7329, -8284, -6631, -4061, -7063, -5307, -8390, -6378, -4222, -7515, -4424, -7435, -5524, -5190, -6242, -5340, -6891, -6092, -6443, -4482, -9412, -6512, -8504, -7151, -3780, -6509, -6541, -7944, -7748, -4030, -3881, -7323, -6572, -8041, -5028, -3184, -8845, -7005, -7553, -6481, -3803, -8940, -8206, -6558, -7744, -6040, -6500, -8761, -6037, -7925, -10519, -5080, -9533, -6506, -7240, -9368, -4760, -9287, -8232, -7063, -10010, -4792, -7236, -12589, -7486, -9919, -5057, -5658, -8648, -7374, -7534, -6010, -4564, -5838, -5932, -5664, -6665, -3232, -6002, -4453, -3240, -4373, -1650, -13290, -3202, -865, -1386, -185, -2610, -1208, 688, 185, 948, 143, 530, 1179, 389, 1454, 963, 1243, 482, -607, 1088, 355, 836, -1785, -2522, -295, -1720, -758, -8318, -4503, -2747, -4915, -3800, -5798, -5229, -5997, -5149, -7227, -3822, -5190, -8891, -5027, -5935, -4036, -5501, -11012, -5751, -5296, -5407, -5933, -14699, -6245, -5838, -7147, -5933, -7333, -6323, -7869, -6831, -5364, -5247, -6471, -12393, -6155, -4895, -4878, -6556, -8509, -6499, -4992, -5571, -6484, -6755, -7576, -5429, -6747, -6782, -6913, -8912, -5640, -6000, -7704, -8167, -8864, -5128, -4469, -8921, -8017, -6624, -4493, -4273, -9640, -7406, -5049, -4473, -5991, -9343, -7561, -4418, -5066, -13268, -8643, -6815, -4450, -5720, -8838, -8074, -5190, -4799, -5812, -7425, -8578, -3930, -4919, -5457, -8368, -10504, -3413, -4635, -5151, -10434, -8473, -3847, -4677, -5001, -14928, -6745, -5601, -5846, -4794, -13557, -6224, -9763, -9292, -4507, -10355, -6021, -7168, -9656, -4467, -9557, -6503, -4641, -8241, -5059, -8694, -8687, -3764, -11422, -6437, -8146, -8778, -3950, -7103, -7453, -9133, -6146, -5314, -4463, -7307, -13477, -5448, -8279, -4093, -8118, -10718, -6447, -8181, -5475, -10931, -8180, -10001, -7192, -8322, -15204, -7878, -10771, -9099, -7508, -16281, -8573, -8246, -11432, -6265, -15411, -7892, -8576, -7119, -6237, -10841, -6883, -9984, -5696, -6866, -8892, -7123, -7987, -5549, -7763, -7957, -8032, -6305, -6345, -8954, -7489, -7324, -5799, -7600, -10486, -7290, -6169, -5854, -7392, -9232, -7372, -5691, -6019, -6508, -7284, -7752, -5822, -6340, -6327, -6590, -8314, -6392, -7067, -6831, -6989, -8911, -6713, -8579, -7890, -7869, -9445, -6372, -10999, -9800, -7776, -9341, -6414, -10052, -11851, -7401, -8415, -7597, -8164, -10261, -8170, -7870, -9737, -7401, -10459, -10877, -8278, -9718, -7889, -16067, -13568, -9071, -9638, -9811, -10978, -12213, -8858, -12121, -9877, -8305, -12370, -8594, -13135, -9242, -7339, -8537, -8928, -9409, -11784, -6960, -6211, -9573, -8126, -11065, -7114, -5472, -10652, -8225, -8324, -8287, -5949, -10635, -9908, -8492, -11586, -7270, -8860, -15514, -11024, -18718, -8410, -7806, -11134, -12072, -14639, -8466, -7747, -8489, -10385, -18810, -8197, -8742, -7493, -9563, -13499, -2908, -6699, -7247, -4378, -5073, -3327, -10845, -5664, -6704, -5999, -5316, -12007, -4681, -6668, -8456, -11358, -7040, -4423, -5286, -14984, -5540, -5199, -5265, -5211, -8728, -3696, -4677, -7107, -6611, -6682, -3638, -5055, -7761, -13025, -6529, -4707, -5934, -7805, -8128, -7618, -5980, -6600, -9058, -5764, -8213, -6226, -6227, -8087, -6096, -7454, -6407, -5201, -6920, -7532, -7107, -6511, -4581, -7163, -6288, -7064, -6532, -4870, -6736, -5605, -7004, -7435, -6602, -5552, -6552, -6745, -7886, -12200, -5388, -7769, -6227, -6979, -6980, -5654, -7796, -5688, -6463, -4928, -6064, -6473, -4840, -4803, -5437, -11898, -3453, -2951, -2292, -4249, -3831, -573, -738, -575, -1265, -669, 1261, 600, -18, -52, 336, 1930, 743, -753, -352, -12, 1425, -450, -3087, -2171, -1392, -310, -3143, -7103, -6068, -3344, -3185, -5780, -7571, -8065, -5057, -5027, -6312, -6455, -6798, -6420, -4856, -6105, -4670, -7252, -9081, -4674, -4671, -4106, -7864, -13386, -4465, -4086, -5220, -8621, -10281, -4309, -4242, -8559, -9005, -10797, -4498, -4461, -7752, -8497, -7325, -5414, -4277, -5370, -7797, -5059, -7937, -3897, -4982, -6640, -4296, -11752, -3836, -6238, -6072, -4338, -6354, -4438, -6660, -6407, -4700, -4666, -5675, -4453, -7390, -5256, -4511, -6533, -3547, -8897, -6522, -4832, -6306, -4020, -11184, -10382, -4960, -6389, -5959, -13516, -10335, -6209, -7820, -11066, -12590, -6437, -14322, -12986, -10320, -10129, -5207, -6874, -10885, -6944, -7587, -4943, -4813, -8883, -5362, -5973, -5279, -5283, -7056, -4170, -5508, -6155, -8576, -4767, -3337, -6284, -7542, -11029, -3905, -3103, -7915, -10062, -6884, -4627, -3659, -6884, -16473, -5993, -7170, -5101, -5139, -8567, -5852, -10715, -7398, -4371, -6536, -5670, -11270, -10348, -4382, -5992, -5626, -18778, -9143, -5134, -5752, -6121, -9399, -6596, -6755, -5309, -7402, -6917, -5445, -8929, -5428, -9935, -6312, -5132, -10054, -7106, -10118, -6658, -5255, -9667, -13075, -7099, -6394, -5653, -7872, -8792, -5678, -5288, -6438, -6763, -7146, -5493, -4663, -7384, -6729, -7684, -6347, -4530, -7160, -7379, -9507, -7291, -4559, -6680, -8148, -11206, -6599, -4802, -7142, -8712, -10361, -5839, -5422, -8417, -9661, -8222, -5888, -6181, -9920, -13604, -6597, -6609, -6751, -11337, -11829, -5824, -7493, -7258, -12042, -7840, -5990, -8131, -7717, -10880, -6602, -7278, -8949, -8032, -9651, -6747, -10059, -10509, -8548, -9624, -8103, -13261, -12531, -9616, -10733, -10395, -12730, -10939, -9319, -11676, -10460, -12527, -9983, -8093, -10785, -9309, -12955, -10411, -7973, -9245, -8938, -13295, -9574, -8281, -8789, -9000, -9805, -9090, -8248, -9757, -9125, -7776, -10044, -8898, -9633, -9117, -7390, -9505, -10617, -8342, -8800, -8461, -8786, -12609, -8822, -8115, -10808, -10312, -19216, -11882, -7526, -10971, -18444, -11727, -11604, -7828, -9439, -10460, -9691, -10746, -10399, -8907, -8269, -10319, -6878, -9851, -2641, -8407, -6705, -6866, -10729, -3982, -6529, -7147, -5880, -8550, -8117, -5432, -9053, -5592, -6433, -7111, -4552, -9303, -5849, -4964, -5221, -3781, -6290, -6387, -3769, -5732, -3360, -4621, -6109, -2878, -8342, -3383, -4350, -4191, -2694, -9240, -3989, -5223, -3001, -3438, -6009, -5375, -6996, -3143, -5046, -4195, -6291, -10745, -4699, -6768, -3080, -5204, -10279, -7260, -7703, -2416, -4464, -6950, -7035, -7753, -2151, -4372, -6527, -6596, -7208, -2333, -4532, -8309, -8248, -6634, -3117, -4632, -15361, -9623, -5373, -4999, -4484, -9217, -6905, -4820, -12682, -4436, -6508, -6933, -4762, -5006, -3898, -3783, -3713, -1910, -1481, -1738, -1064, -643, 227, 177, -122, 543, 585, 909, 595, 257, 852, 386, 309, -314, -640, -275, -1112, -1534, -3212, -2963, -3566, -3883, -4501, -7127, -6597, -9483, -7485, -7128, -4571, -7375, -4444, -11865, -7870, -5313, -7155, -3428, -11077, -7770, -9125, -8310, -3381, -7399, -6912, -8765, -11503, -3966, -6346, -6521, -7168, -11360, -5531, -7257, -7706, -7116, -7068, -7660, -12054, -10682, -8340, -5558, -7006, -8854, -9587, -9526, -6069, -6389, -7118, -9337, -5638, -9274, -6453, -8845, -12604, -3441, -10968, -6227, -14733, -10009, -2529, -10137, -5697, -8539, -7247, -2413, -12264, -5425, -8522, -6545, -2854, -6333, -5646, -12419, -7328, -3787, -4279, -6259, -8824, -9771, -4800, -3838, -6481, -7261, -8563, -4664, -4541, -6203, -7890, -6232, -4045, -6420, -6541, -6816, -5547, -3955, -9842, -7972, -5009, -5959, -4435, -10213, -10475, -4682, -6963, -5504, -7886, -11744, -5499, -7792, -7511, -7102, -11514, -5834, -7854, -9814, -7475, -13256, -4957, -7573, -8841, -7927, -13400, -4683, -7644, -7727, -7390, -9887, -5684, -8306, -7013, -6861, -7521, -8562, -10015, -6961, -6447, -5779, -15776, -10543, -8142, -6028, -4576, -14903, -7085, -10275, -5988, -4022, -9449, -6034, -10182, -6406, -4355, -7039, -7576, -10481, -6594, -5971, -6042, -10735, -12139, -6102, -10077, -5147, -6540, -9336, -5684, -13039, -4449, -5644, -7173, -5861, -10946, -4710, -6404, -6152, -6929, -12656, -6287, -6600, -5901, -9247, -8756, -9140, -5629, -6384, -11170, -6098, -9513, -5078, -7412, -10098, -4956, -7975, -4866, -7864, -9491, -4904, -7755, -4930, -7681, -8716, -5856, -9063, -5549, -8024, -7235, -7838, -10883, -6812, -8157, -5775, -11198, -10213, -8346, -7342, -5226, -16470, -8954, -9620, -7158, -5899, -10835, -8071, -10983, -8544, -7222, -10022, -7876, -13422, -12045, -7091, -14439, -8548, -15395, -10606, -6787, -10761, -10332, -12884, -8817, -7185, -8085, -10652, -10287, -8365, -7504, -8403, -8478, -8341, -8698, -7538, -8349, -7415, -7562, -8799, -7687, -6477, -7272, -7897, -8144, -8004, -5823, -7833, -8661, -8029, -8453, -6541, -9320, -8159, -8876, -9742, -9087, -11904, -7116, -10415, -10815, -14632, -10865, -6658, -11041, -7507, -8806, -9105, -6804, -9543, -5818, -7707, 10155, 12746, 13112, 9384, 6364, 9425, 12279, 12488, 8807, 5785, 6856, 10838, 10468, 7169, 4021, -1794, 8320, 6370, 5113, 1089, 3338, 4773, 2049, 3570, -2031, 4578, 1878, 3081, 2124, -3039, 4190, 2224, 1344, 426, -4825, 2790, 3118, -1476, -3958, -4895, 1593, 3326, -3336, -3215, -40, 1441, 2672, -2582, -63, 2254, -2078, 622, -2736, 1020, 3521, -1089, -6869, -1708, 2853, 4154, 1811, 1747, 62, 4384, 4192, 1339, 4130, -49, 4952, 3521, 776, 4507, -2725, 4560, 2308, 2035, 3068, -3883, 3154, 2592, 2099, -2045, -1190, 368, 3919, 780, -955, -1675, -4758, 4235, -493, 1643, -5914, -2613, 3299, -102, 2175, -3555, -576, 1433, 323, 1824, -2409, 554, -344, 524, 616, -3957, 1226, -3936, 628, -124, -3020, 1340, -3346, 361, 1304, -944, 997, 114, -405, 2360, 69, 317, 418, -1152, 2405, 535, -1268, -1198, -1069, 1531, 603, -5980, -5265, -577, -49, 269, -6258, -4021, -918, -1856, -616, -3713, -1023, -2786, -3457, -2425, -4304, 609, -1514, -5701, -4607, -6379, 1493, 253, -5339, -5188, -10266, 1581, 28, -1870, -4916, -5895, 550, -2190, -734, -3085, -3294, -2146, -4314, -1378, -3039, -1655, -2526, -1846, -3501, -6895, -253, -421, -642, -5841, -5964, 766, 65, -417, -6885, -2925, 1104, -557, -677, -3422, -2869, 680, -2226, -977, -1882, -4846, -307, -5870, -1316, -2482, -7492, -1746, -5986, -1963, -3896, -4590, -4094, -2960, -2495, -1718, -4834, -5027, -2262, -2106, -268, -14176, -4192, -2772, -1617, -161, -4262, -5206, -3131, -1845, -1199, -2457, -5959, -2018, -2950, -3579, -2876, -5138, -300, -4511, -8852, -4098, -5770, 1085, -5111, -8511, -4172, -8071, 1678, -4856, -3797, -3774, -9588, 1229, -5366, -1471, -3627, -6087, -643, -7686, -479, -3710, -3453, -3701, -5377, -581, -3755, -2312, -1745, -2660, -1705, -3430, -2398, -620, -1427, -4016, -2901, -3232, -1016, -1039, -7903, -2776, -4205, -2516, -1344, -7185, -3750, -5736, -4869, -2431, -5456, -6694, -7873, -7378, -4341, -5246, -10595, -12277, -6725, -5936, -6069, -6533, -6152, -4723, -5557, -6075, -3954, -2296, -3849, -4801, -4137, -2590, -1009, -4258, -4566, -2724, -2469, -1338, -5936, -5982, -2265, -3786, -3074, -8221, -11402, -2912, -6822, -5872, -8258, -4370, -5367, -4966, -7581, -7360, -2243, -6281, -3751, -6287, -7066, -1808, -2884, -5122, -5047, -6901, -2359, -1531, -9857, -5059, -5925, -3686, -1311, -7128, -6167, -4822, -6161, -1804, -6896, -5863, -4475, -6151, -2600, -9974, -4072, -5347, -3663, -2725, -15938, -3560, -8575, -2717, -1770, -10213, -4551, -7879, -2768, -787, -9373, -4406, -4310, -3255, -205, -9962, -2890, -2963, -3422, 1, -6661, -3392, -2844, -3029, -170, -4916, -8209, -3539, -3108, -942, -4675, -3966, -3962, -3867, -2982, -4586, -1818, -3373, -4092, 7465, 10363, 10751, 7892, -896, 6569, 9725, 10121, 7108, 489, 3261, 7811, 8164, 4473, -38, 1488, 4891, 4774, -1000, -2812, 3807, 1945, 981, -1314, -4478, 3427, -937, 259, -2409, -518, 2267, -4716, 342, -3855, 954, 2702, -1194, -894, -4800, 1416, 3355, 2541, -24, -4117, 1331, 3433, 3956, 950, -5606, 1135, 2957, 4417, -231, -2425, 1451, 1445, 4334, -740, -4, 1960, -2938, 3566, 1676, -36, 2061, -443, 1518, 2270, -1102, 1814, 2329, -4486, 1457, -1257, 1751, 3119, -2316, 873, -678, 2230, 2757, -404, 1232, 550, 2768, 1250, -906, 1095, 1159, 2764, -1686, -2178, 629, 491, 1950, -1012, -2263, 502, -1620, 151, 803, -1032, 320, -5347, -2789, 1188, -332, -302, -9984, -2968, 1024, -469, -936, -8802, -1426, 921, -1322, -874, -4464, -1272, 774, -3355, -300, -1727, -1962, 407, -4289, 192, -290, -2721, -63, -741, 414, -45, -2883, -413, 1133, 417, -1107, -2659, -597, 1776, 49, -3274, -3075, -661, 1373, -1110, -2215, -5329, -642, -89, -3609, -769, -10998, -851, -2524, -9132, -735, -5260, -666, -4873, -5634, -1800, -3680, 670, -5591, -1939, -3299, -4235, 1397, -7483, -350, -4024, -6442, 682, -10761, 74, -5944, -1923, -2142, -4543, 208, -6266, 39, -12373, -2914, 956, -2055, -71, -3681, -2241, 2248, -784, -2158, -2380, -1894, 3287, -867, -2712, -2920, -1889, 3491, -1740, -699, -3844, -2384, 2524, -3659, -485, -2494, -3500, 9, -4356, -2160, -1864, -3123, -1755, -2585, -8293, -2174, -1722, -256, -2470, -4448, -2638, -1516, -185, -4057, -2350, -3833, -3287, -1331, -7535, -2298, -6043, -7242, -2531, -11586, -3140, -4751, -2519, -1968, -9226, -3707, -3978, -1185, -1044, -6128, -3021, -5076, -1576, -888, -4336, -2184, -6571, -3061, -1757, -3834, -2065, -5168, -5343, -3763, -4201, -2827, -3367, -9239, -5769, -4884, -4592, -2241, -8583, -5319, -6652, -7865, -1871, -5208, -5235, -6257, -10939, -1962, -4412, -6054, -2774, -7764, -2222, -5460, -5720, -1289, -4814, -2796, -6417, -5008, -886, -3633, -4235, -4891, -5366, -1022, -4116, -7967, -4810, -6575, -1521, -4923, -11224, -7129, -7925, -2409, -3956, -6990, -17269, -8064, -3622, -3433, -5957, -8662, -6873, -4986, -3865, -5455, -5338, -6159, -7519, -4616, -5257, -3224, -7325, -9523, -4790, -5156, -2448, -9371, -3567, -4489, -5697, -2821, -5314, -1640, -4708, -8441, -3770, -3707, -1381, -6199, -8236, -3921, -3471, -2251, -8708, -4559, -3491, -3836, -3328, -8789, -3216, -3637, -4449, -3813, -9644, -3129, -4424, -5738, -4748, -7124, -3965, -4513, -6723, -5711, -4060, -5275, -3835, -4397, -3995, -2311, -5990, -4048, -3026, -2356, -1567, -5673, -5713, -2770, -1660, -1904, -5196, -10226, -2655, -1716, -3442, -3897, -6594, -1813, -2358, -5478, -2519, -3534, -912, -3236, 2816, 10853, 11130, 7971, 5305, 2639, 10384, 10551, 7334, 5102, 1951, 8983, 8721, 5502, 4500, 472, 6733, 5317, 2994, 3652, -2632, 4136, 846, -685, 2731, -942, 2498, 250, -2235, 1608, 1547, 2032, -817, 2360, 1113, 2142, 1255, -1477, 3248, 2007, 2181, -258, -1515, 2199, 2816, 2574, -934, -2617, -551, 3123, 3037, -17, -2686, 1598, 2910, 3264, 1765, 319, 3044, 1515, 3095, 3165, 1646, 2554, -4918, 2191, 3454, 1129, 531, 1550, 591, 2469, -2124, -1176, 4667, 243, 798, -3351, -1221, 6207, 202, 977, -39, -1104, 6777, -1813, 1461, 366, -318, 6336, -1875, 1209, -607, -15, 4776, 1149, 936, -2417, -791, 2440, 2332, 1056, -3948, -2974, 1560, 2195, 1417, -3292, -8100, 1569, 929, 1661, -1614, -3619, 997, -930, 1448, -901, -1155, -156, -1963, 846, -2205, -348, -1919, -2811, 257, -8398, -214, -3453, -4946, -206, -1537, -170, -7124, -10364, -164, 402, 115, -4540, -12621, 588, 652, 896, -1195, -16424, 900, 60, 1597, -1237, -7107, 278, -1201, 1633, -3867, -3272, -858, -4112, 939, -2844, -900, -1321, -10210, -263, -1175, 454, -1039, -4481, -2017, -716, 561, -736, -6075, -5001, -71, -1380, -522, -4911, -1851, 211, -5301, -51, -100, 645, -415, -538, 199, 1670, 1488, -1398, 29, -730, 1896, 1173, -1821, -2739, -3889, 487, -216, -2279, -6894, -6878, -3666, -2184, -3296, -2486, -6489, -1177, -1264, -4863, -3892, -11466, 696, 258, -4590, -6984, -3988, 744, 570, -2274, -3033, -2936, -16, -459, -1090, -1224, -4081, -1101, -2535, -1339, 120, -7075, -3108, -1752, -3254, 546, -14394, -7204, -355, -3727, -306, -8928, -4062, 58, -1666, -2335, -5461, -2334, 28, -982, -2879, -4177, -2322, -84, -990, -2306, -3866, -3444, -366, -908, -3226, -3878, -5506, -1203, -564, -6448, -4126, -11451, -2910, -152, -8746, -4208, -6954, -3861, 100, -5412, -3887, -4327, -2458, 36, -4128, -4020, -4759, -1580, -462, -3551, -4817, -5465, -1384, -1518, -3568, -5537, -2972, -1548, -2904, -4034, -5937, -1743, -2046, -3334, -4066, -7162, -1717, -2720, -2923, -3738, -10740, -2582, -2337, -2918, -4108, -10690, -4479, -1383, -3176, -5674, -9109, -8246, -1332, -2751, -8263, -9485, -10896, -2741, -2023, -8803, -4645, -7508, -5089, -2009, -7045, -2053, -5038, -2886, -2801, -4004, -1291, -3449, -1253, -3022, -2556, -2207, -3232, -859, -2392, -2889, -4765, -5100, -1269, -2410, -4490, -4375, -12314, -2208, -3197, -4435, -3202, -5109, -3341, -4380, -3450, -3109, -3996, -4346, -6059, -1620, -2968, -4817, -5390, -7471, 117, -2499, -5740, -6338, -5152, 752, -2173, -6120, -6169, -4065, 257, -2365, -8440, -4260, -4972, -1232, -3283, -8427, -2650, -7703, -3235, -5008, -4629, -2540, -7609, -4511, -5536, -3071, -5195, -7715, -2229, -7725, -3696, -1743, -3123, -402, -3041, -2461, -2227, -3511, 82, -1098, -1439, -2126, -3625, -604, -1073, -1291, -1826, -3226, -2174, -2719, -2504, -1520, -3114, -3895, -6905, -3542, -946, -4190, -5272, -7702, -2073, -304, -9118, -7403, -5800, -2159, -127, -4725, -6445, -6421, -5627, -774, -2103, -3377, -9635, -5046, -2299, -1817, -1608, -11314, -1802, -3645, -3641, -607, -7169, -1155, -3617, -5895, -97, -5934, -1594, -3750, -2787, -76, -5338, -2697, -4602, -1917, -767, -3873, -3565, -4736, -2394, -2683, -2203, -2411, -3080, -3139, -8290, -1188, -1566, -2246, -3717, -6051, -1043, -2144, -2269, -4135, -3166, -1736, -4665, -1541, -3420, -2445, -2807, -5714, -428, -1720, -2671, -3901, -3742, -133, -304, -3534, -6730, -4461, -635, 196, -4999, -9280, -10084, -1368, -461, -6250, -3601, -7678, -1850, -2531, -4963, -1718, -6610, -2500, -5824, -3788, -911, -10839, -4332, -5219, -3619, -707, -7788, -9632, -2921, -4230, -945, -5913, -8131, -1636, -5498, -1431, -6064, -7834, -1339, -7316, -1910, -6401, -7193, -1225, -7706, -2012, -5833, -4882, -998, -6730, -1463, -4220, -3883, -1552, -7327, -1007, -3446, -3715, -3291, -9721, -1335, -4379, -4961, -4267, -8177, -2680, -8030, -7886, -4251, -8146, -4898, -11524, -5527, -6364, -9818, -4962, -9179, -4559, -12750, -7549, -3475, -7716, -5543, -10002, -6633, -2922, -5897, -8312, -16142, -5658, -3029, -4932, -15307, -9516, -4894, -3818, -4216, -12433, -8084, -5217, -6432, -3736, -10402, -5130, -4942, -11180, -3459, -8452, -2451, -4563, -6610, -3042, -5685, -1321, -6302, -7019, -2659, -3931, -1369, -14280, -10820, -2711, -3088, -2285, -9053, -9099, -3352, -2633, -3749, -11980, -9436, -4253, -2509, -5009, -8102, -13941, -4320, -3419, -4522, -5168, -12003, -4059, -7399, -3655, -4747, -14360, -4608, -6510, -3954, -5312, -8539, -5475, -3113, -6467, -5601, -6161, -5400, -2508, -12457, -6038, -5294, -5312, -3169, -5293, -7629, -4882, -5578, -4175, -3787, -8540, -4697, -6554, -3984, -4043, -7789, -5165, -8141, -2751, -6578, -7592, -7204, -6154, -2242, -11739, -5629, -15877, -4579, -3361, -5185, -3711, -7014, -3568, -8555, -3553, -2900, -4905, -2461, -5455, -2903, -3147, -4420, -1824, -2925, -2480, -4606, -4717, -2029, -2581, -2166, -8433, -5083, -3066, -3064, -2108, -11378, -5143, -4636, -3586, -2551, -7590, -5327, -5433, -4131, -3709, -8176, -6163, -4356, -4980, -5464, -13694, -8437, -3324, -5727, -7051, -11130, -12397, -3008, -6211, -8993, -9184, -8892, -3231, -7306, -7476, -9969, -7742, -3573, -10203, -4634, -12684, -7927, -3684, -16659, -3624, -17243, -8584, -3813, -9568, -3837, -13002, -8983, -4193, -7514, -4636, -10462, -8864, -4036, -5969, -5485, -8704, -8689, -3081, -4683, -6535, -7310, -7888, -2436, -3996, -7866, -6560, -7437, -2539, -3992, -9937, -6985, -9075, -3531, -4695, -11614, -9521, -14498, -5769, -6377, -8750, -6250, -2388, -2382, -792, -3844, -5568, -4195, -2097, -1896, -4692, -3336, -7965, -2214, -4281, -6960, -2085, -4817, -2960, -4738, -14538, -2011, -4251, -4964, -4203, -9271, -2839, -6000, -9238, -3609, -8753, -4399, -4727, -9798, -2251, -8970, -7127, -2190, -7635, -1894, -5336, -4922, -1187, -6424, -3022, -3667, -2114, -1209, -5803, -5445, -3153, -1059, -1714, -5782, -6155, -2981, -1207, -1976, -6663, -6096, -2844, -2311, -2135, -7195, -8362, -2705, -4110, -3132, -3972, -14535, -2467, -5510, -5792, -1921, -7078, -2310, -4635, -4818, -1135, -5387, -2569, -3822, -2402, -1269, -4121, -3458, -4663, -1609, -2134, -2080, -5044, -10175, -1910, -3693, -420, -7921, -5837, -3250, -6267, 390, -11087, -2919, -5527, -11392, 354, -4261, -2479, -5466, -12193, -474, -1930, -3810, -4357, -7850, -1864, -1383, -4977, -4058, -6027, -2994, -2375, -3743, -3166, -5115, -2870, -4993, -4345, -2099, -4091, -1980, -7257, -8726, -2171, -3207, -1416, -4962, -7049, -4404, -3282, -1581, -2328, -4625, -11970, -4971, -2512, -957, -4192, -3732, -8884, -3966, -954, -4571, -2315, -4916, -3980, -2717, -4787, -2467, -2751, -2466, -10008, -4276, -3237, -1999, -1585, -3612, -3781, -3062, -2151, -1621, -1599, -3895, -2077, -3195, -2708, -1552, -4783, -1739, -5405, -5519, -2732, -5996, -2242, -6747, -8327, -4793, -6178, -3120, -5205, -4868, -6877, -5084, -3574, -4568, -3278, -8116, -4178, -3346, -3155, -2751, -9489, -3357, -2974, -1424, -3687, -8878, -2607, -3122, -724, -7232, -7028, -2531, -4177, -1287, -8077, -4775, -3380, -6154, -3483, -8296, -2786, -5279, -7446, -9742, -7717, -2005, -6688, -8091, -7778, -4203, -2509, -3835, -9854, -6041, -3579, -3402, -2103, -5315, -6127, -4537, -3127, -1887, -2927, -7252, -5946, -3274, -3282, -2280, -8381, -6652, -4967, -7575, -3073, -6001, -7409, -8732, -10256, -5786, -4500, -10375, -14838, -7218, -12124, -4221, -8848, -10338, -7181, -5745, -4837, -5972, -6104, -7131, -3726, -6107, -5315, -4291, -6432, -3057, -7145, -5953, -4118, -5286, -3563, -7131, -7803, -4913, -4846, -5573, -7630, -12685, -4135, -5862, -5860, -8251, -10917, -2629, -9106, -3478, -5686, -7278, -1934, -6210, -2447, -3660, -6232, -1807, -4019, -2351, -2685, -6934, -1713, -3831, -2811, -2361, -10394, -1327, -5543, -3893, -2399, -11271, -924, -12006, -6556, -2697, -8086, -980, -6260, -8052, -3147, -7675, -1867, -3905, -4646, -3523, -8270, -4120, -3468, -3723, -3978, -8272, -9603, -4622, -4360, -5092, -6699, -5698, -8289, -6575, -7691, -4966, -3395, -7250, -13723, -9388, -3800, -2684, -5014, -8438, -5655, -3298, -2890, -4606, -5398, -3834, -3409, -3617, -4354, -4354, -3106, -3951, -4212, -3430, -4542, -3071, -4575, -4677, -2538, -5841, -3489, -4923, -5681, -2124, -8023, -4274, -4900, -7264, -2333, -8982, -5708, -4813, -8796, -3313, -8289, -8689, -5138, -7854, -5175, -8156, -10859, -6117, -5752, -5528, -4471, -2652, -6196, -11727, -8669, -4997, -2925, -1220, -9177, -4889, -4601, -3001, 373, -6932, -2599, -2013, -2167, 571, -6367, -2479, -1175, -1324, -277, -4778, -3825, -2284, -1048, -2049, -2983, -3926, -5524, -1465, -4418, -2204, -2113, -3979, -2658, -6428, -2456, -1106, -2602, -4177, -8465, -3291, -1040, -2746, -4047, -10954, -3643, -1595, -3662, -3529, -5062, -3396, -2253, -5660, -4050, -2701, -3635, -3181, -7993, -5894, -1968, -5269, -5613, -4906, -11586, -2387, -6787, -19755, -3199, -7378, -3991, -3393, -7052, -2632, -4643, -7713, -1496, -6389, -2867, -3961, -5292, -933, -8342, -3994, -3450, -2399, -1669, -13083, -6695, -1822, -1225, -4265, -6013, -7647, -205, -1037, -6638, -3330, -5317, 707, -1597, -4335, -2858, -4621, 846, -2926, -4878, -4668, -4337, 262, -4596, -10910, -8174, -5034, -934, -3779, -6660, -4125, -9053, -2616, -2219, -4445, -2773, -8275, -4516, -1280, -4806, -2834, -5603, -5921, -916, -7097, -3696, -5307, -7555, -1364, -9936, -4798, -5744, -9207, -3079, -8646, -5690, -7252, -5003, -6585, -8770, -6410, -10935, -3488, -5610, -8659, -6744, -9245, -4543, -3736, -6559, -7362, -6667, -9999, -3573, -4302, -8965, -5489, -3734, -5494, -2963, -5703, -5456, -1880, -11408, -2594, -2907, -6858, -1770, -4699, -2890, -1549, -6535, -2640, -2857, -3453, -1154, -4094, -4328, -2189, -4074, -1541, -3391, -7130, -2055, -4605, -2792, -4375, -8446, -2633, -4459, -5634, -6677, -6922, -3739, -4190, -16075, -7423, -5863, -3600, -4931, -5658, -5893, -4679, -3076, -6630, -3613, -3718, -3507, -3927, -7514, -2568, -2615, -2837, -7290, -8002, -1719, -2934, -2845, -6953, -8216, -1143, -4435, -3538, -4074, -8730, -1125, -4456, -5120, -3464, -9807, -1668, -3324, -8996, -4488, -7542, -2334, -3513, -9803, -7113, -5666, -2808, -5626, -6177, -5883, -4286, -3672, -12648, -5514, -4407, -3453, -5572, -8244, -5411, -5150, -3455, -8737, -7283, -4425, -10922, -4379, -13654, -5561, -3741, -5647, -6222, -14264, -3558, -4234, -2762, -6842, -13732, -2974, -6441, -1961, -4929, -7858, -3630, -11656, -2401, -3825, -4479, -4823, -8689, -3994, -3620, -2891, -5125, -7594, -6922, -3746, -2095, -4262, -6938, -10203, -3831, -1822, -3487, -5721, -7810, -4420, -2297, -3764, -5273, -5157, -6377, -3705, -5866, -5856, -3896, -8346, -5827, -11724, -7327, -3817, -6118, -6657, -5614, -9996, -4462, -5188, -5069, -3567, -23608, -5227, -5446, -3785, -2982, -9908, -6383, -6470, -3373, -2828, -7664, -9051, -7122, -3856, -2319, -7283, -14350, -6048, -5148, -1901, -7891, -10559, -5218, -6995, -2190, -8009, -8803, -5223, -9427, -3309, -6301, -8108, -5472, -11170, -5393, -4919, -7391, -5316, -14433, -7828, -4693, -6097, -5145, -7918, -5216, -5792, -4923, -5350, -4639, -3623, -8660, -4158, -5483, -3482, -3677, -8145, -3554, -4932, -3589, -5313, -5483, -2925, -4456, -4440, -9515, -4467, -2589, -4890, 3118, 146, 1330, 6913, -8593, 2225, -2169, 4462, 6442, -5307, 12, -2240, 6211, 5121, -3754, 1312, 1078, 6366, 3616, -3143, 2963, 2155, 5076, 3021, -2276, 3466, 3005, 1414, 2465, -1894, 3025, 3214, -157, 740, -4887, 1293, 2110, 3189, -4219, -2132, -4556, -1005, 3860, -2021, 2117, -988, -6969, 3108, 306, 3776, 2001, -3941, 546, -137, 4468, 2875, -3603, -7925, -958, 4940, 2381, -2086, -131, 1799, 5298, -257, -19, 1104, 3233, 5130, -1436, 755, 202, 3141, 3946, 2103, -996, -1421, 1700, 660, 2879, -1924, -391, -73, -827, 1894, 2690, 319, 1207, 2394, -865, 4090, 511, 2256, 2674, -2225, 3748, 735, 2067, 1310, -805, 1920, 526, 1172, -336, 316, 162, -206, 561, -4199, 1989, 568, -1159, 654, 72, 3204, 150, -3201, 1390, 3714, 3505, -472, -9209, 1725, 4733, 2879, -171, -1469, 729, 4091, 1390, -691, 396, -2601, 1674, -810, -2626, 295, -7749, -4042, -3765, -4460, -1820, -3734, -3146, -8464, -6383, -8245, -1372, -2356, -3271, -5291, -2978, 733, -1947, -1560, -1302, -1978, 1491, -432, -2768, 154, -3479, 940, 126, -7540, 9, -7941, -284, -776, -2313, -1679, -4676, -294, -3182, -1244, -3582, -2537, -44, -2447, -1635, -2579, -1208, -961, -777, -1382, -3078, -74, -3733, -602, -943, -3659, 674, -12982, -1533, -1950, -926, 812, -5139, -3127, -3137, 55, 385, -4789, -4648, -987, -234, 565, -5526, -5624, -483, -47, 1504, -2684, -7560, -1628, 61, 1754, -738, -8574, -1004, -1997, 1217, 92, -2497, 756, -4957, 887, 251, -78, 1558, -1276, 1105, -37, 864, 1478, -1042, 1072, -963, 840, 515, -1753, 612, -3097, 141, -1088, -1256, -163, -5478, -1065, -2240, -1733, -901, -2319, -3035, -2699, -4870, -1569, -198, -5528, -3643, -3113, -3722, 748, -2815, -6049, -748, -8112, 813, -1249, -10768, -477, -1404, 223, -1639, -9965, -1843, 436, -587, -4400, -7743, -5307, 600, -1048, -9887, -4784, -6827, -371, -1397, -3433, -2408, -4764, -1549, -3179, -1722, -763, -4034, -1054, -5471, -2083, 41, -3624, 844, -613, -5535, -199, -3123, 2355, 787, -6442, -1793, -3035, 2846, 197, -1717, -5117, -4639, 2196, -2325, 310, -4472, -17536, 255, -7013, 1172, -1994, -3928, -3289, -9853, 1038, -379, -1702, -10583, -4825, 59, 694, -786, -4575, -2715, -1504, 1229, -290, -574, -2738, -2659, 1129, -455, 1086, -4577, -2561, 147, -1698, 1292, -6912, -2028, -2223, -3573, 147, -4034, -1176, -6949, -4009, -2647, -2021, -691, -7117, -1952, -4681, -1034, -173, -5394, 544, -2675, -487, 966, -1670, 2086, -1898, -583, 1526, 1029, 2718, -1984, -2698, 884, 2329, 2530, -2503, -3246, -933, 2231, 1490, -2589, 810, -2167, 188, -256, -1535, 1951, -1852, 4277, 8809, 8073, 8894, 6117, 3705, 8169, 7263, 8200, 5739, 2140, 6120, 4511, 5897, 4409, 220, 2412, -1604, 1340, 1445, 146, 481, -1372, 1083, -3380, 1598, 78, -303, 1172, -534, 1779, 437, 2339, -180, 102, -96, 3588, 3941, 1896, -338, -7107, 5326, 4951, 4069, -568, -1001, 5674, 5616, 4464, 116, 533, 4623, 5794, 2535, 2085, -90, 2337, 5337, -650, 3534, -2172, 3173, 4030, 3689, 3828, -2848, 4564, 1813, 4696, 3088, -83, 4455, 1995, 3875, 1675, 2758, 3043, 3189, 1410, 215, 4450, 479, 2920, -1555, -385, 4934, -2987, 1382, 245, 524, 4125, -3666, -1159, 1789, 2241, 2386, -582, -2739, 2611, 3599, 3106, 367, 503, 3170, 3851, 4087, -163, 2224, 3834, 2505, 3466, -1465, 2628, 4288, -600, 1277, -2497, 2187, 3945, 1691, 460, -1772, 1456, 2627, 3462, 1714, 507, 977, 1390, 4027, 1833, 2274, 325, 1221, 3987, 747, 3308, -1273, 328, 3319, -1813, 3771, -4158, -1971, 1860, -2041, 3738, -8238, -6137, 140, 549, 3185, -8916, -8056, -245, 1533, 1988, -3807, -2856, 8, 1112, 86, -2567, -1311, 257, -1158, -625, -4053, -884, 724, -8202, 204, -5880, -549, 1493, -3115, -338, -1423, -598, 2289, -2715, -2811, 211, -2133, 2723, -5070, -3071, 611, -8399, 2597, -3161, -2561, 692, -3892, 1767, -1189, -3756, 1144, -1831, -48, -728, -3358, 1838, -1321, -3653, -891, -2556, 2279, -818, -5325, -1002, -2309, 2273, -755, -1921, -970, -3974, 1745, -2182, -462, -1343, -6567, 595, -4975, -109, -2688, -712, 98, -2412, -786, -4322, 515, 930, -1467, -2608, -3287, -363, 881, -3112, -5276, -1939, -1794, -198, -6744, -6453, -1216, -868, -1136, -1844, -4225, -1144, -463, -2293, -40, -2040, -1808, -1214, -5789, 735, -1162, -4271, -3008, -8304, 1061, -1156, -6402, -4590, -6784, 835, -1738, -1396, -3877, -4845, -72, -3918, -375, -3647, -2302, -1608, -8159, -1533, -3457, -957, -3636, -2085, -3981, -2984, -393, -6563, -454, -4316, -2912, -391, -7770, -154, -8634, -3245, -852, -4968, -428, -2861, -3898, -1510, -4373, -1559, 310, -5401, -2226, -5840, -5442, 1388, -5982, -3498, -12001, -6296, 1478, -2471, -6107, -5912, -2775, 1040, -626, -5956, -2526, -2580, 37, -222, -3260, -729, -3968, -2029, -982, -2254, 52, -7660, -4143, -1877, -1721, 0, -9829, -3081, -1249, -993, -278, -7732, -3697, -1019, -611, -13, -9038, -9054, -2074, -485, 538, -3289, -6787, -3741, -897, 1122, -1718, -5178, -3493, -3183, 1177, -2659, -4875, -1197, -3555, -370, -7024, -2896, 359, -1109, -10480, -3403, -1167, 750, -742, -682, -1152, -273, 631, -359, 1694, -417, -631, 967, 650, 2436, -396, -3188, 1408, 1224, 2455, -890, -4362, 1385, 1311, 1974, -2045, 6241, 8127, 8154, 3329, 3450, 5414, 7353, 7504, 4539, 2359, 2893, 4853, 5406, 5810, 1415, -1407, 256, 1137, 6393, 2869, -4026, -1018, -3143, 6315, 2155, 1049, 1256, -932, 5055, -2328, 1888, 2348, -688, 522, 392, 1371, 1929, -161, 1861, -383, 1944, 436, 605, 4813, 1599, 2704, -665, 78, 5335, 4973, 2879, 316, -4132, 4860, 5703, 2508, 552, -2180, 3700, 5143, 1233, -840, 1420, 1344, 4776, -241, -3382, 2340, -973, 4692, 1402, -6939, 1903, 1856, 4098, 2648, -7534, 271, 2871, 3474, 2561, -2175, -3392, 2245, 3982, 1263, 431, -5024, -271, 5016, -803, 2239, -404, -4052, 5332, -1549, 3452, 1413, 285, 4676, -1912, 4399, 2200, 1950, 4041, -4243, 5284, 2722, 2343, 5254, -7932, 5851, 3446, 2058, 6540, -3096, 5792, 3984, 1509, 7012, -79, 5012, 3853, 851, 6625, 1757, 3676, 2829, -245, 5303, 2223, 2010, 665, -2602, 2883, 1032, -577, -3711, -5186, -375, -2619, -5703, -5238, -928, -593, -1219, -2876, -1840, 1076, 1431, 735, -2153, -756, 1646, 2671, 1002, -3381, -237, 951, 2829, 384, -4943, 284, -1173, 1765, -810, -2245, 794, -1385, -1118, -718, -879, 1043, 812, -1580, 712, -1844, 617, 1873, 391, 1316, -2229, -997, 2264, -60, 984, 724, -1524, 2405, -3089, 20, 2026, 1053, 2434, -4403, -739, 2167, 2422, 2259, -839, -659, 1578, 2632, 1650, 247, -828, 419, 1795, 319, -694, -1902, -798, -256, -1868, -4354, -3589, -864, -1973, -3668, -3444, -3657, -939, -447, -4164, -3165, -2500, -2023, 36, -5331, -7651, -2047, -2187, -969, -5920, -3386, -2484, -1053, -2807, -5063, -1625, -3744, -1227, -2107, -4562, -1828, -5324, -3535, -728, -5042, -2414, -4339, -4821, -435, -5803, -1451, -1994, -2642, -1112, -3598, 21, -334, -3353, -2078, -1599, 842, 223, -10118, -2764, -810, 845, -733, -5822, -4143, -1101, -5, -3691, -6578, -4775, -1730, -1606, -2260, -4415, -2597, -1198, -2413, -567, -414, -1047, -116, -1646, -993, 475, -162, 1059, -1526, -3779, -725, 354, 1978, -2684, -12033, -4345, 581, 2077, -5734, -6570, -7242, 245, 967, -9861, -2620, -13415, -1008, -2056, -3860, -341, -4412, -3183, -16484, -1046, 515, -1713, -3196, -5242, 290, 709, -847, -1213, -3672, 196, 859, -581, 130, -2007, -1415, 1056, -926, 842, -1128, -1339, 832, -1558, 1039, -1686, 429, -331, -120, 936, -4188, 662, -2454, 1262, 705, -4660, -622, -3390, 1469, -124, -3031, -3537, -1024, 687, -2587, -4361, -8373, 1268, -716, -3647, -8348, -7906, 2426, -1858, -1745, -2939, -3338, 2563, -1919, -2562, -1240, -1319, 1873, -1528, -8172, -740, -557, 537, -905, -5316, -928, -343, -1343, -382, -3196, -2312, -285, -3772, -710, -2727, -4046, -461, -2665, -536, -163, 1395, -2433, 1451, 700, 744, 289, -3430, 3049, 1103, 669, 769, -1953, 3410, 273, -1166, 1312, 104, 3125, -2569, -3797, 1211, 1460, 2553, -9160, 187, 970, 1832, 1920, -2243, 1512, 854, 1220, 1268, -1188, 946, 536, 262, 486, -2287, -1878, -373, -200, -702, -7091, -6246, -1769, -1183, -2357, -3416, -2110, -2397, -3818, -3072, -1011, -1305, -1881, -3042, -1255, -866, -1461, -1339, -1058, 828, -1576, -1817, -975, -769, 1895, -384, -1716, -768, -1761, 1759, 840, -483, -1031, -4489, 255, 635, 564, -2962, -4338, -2924, -1584, 561, -6641, -1145, -3653, -8057, -1020, -37, -382, -2246, -1516, -6472, 2152, -2088, -1904, 192, -4472, 2868, -3651, -1567, -85, -2669, 2764, 450, -990, -2113, -2535, 2310, 1626, -728, -874, -1695, 1779, 891, -1428, 971, -1296, 972, -2200, -4166, 1114, -1924, -589, -5780, -7825, 221, -2285, -3323, -1691, -3487, -433, -1145, -6073, -230, -2525, 154, -513, -7508, 585, -2832, 982, -1242, -6886, 1164, -3535, 1293, -3821, -2967, 1527, -2951, 1074, -3743, -1304, 1347, -1822, 720, -957, -1811, 494, -1426, 611, -92, -6989, -125, -2038, 500, -931, -3428, -303, -4554, -223, -4165, -768, -1666, -8290, -1602, -9042, -497, -5360, -2436, -1486, -5364, -1441, -9835, -372, -324, -4806, -3517, -7210, 429, -68, -4413, -9929, -2532, 63, -987, -4720, -4172, -1231, -2332, -2607, -7687, -1449, -1587, -10531, -2300, -6691, -997, -1616, -2487, -1538, -2714, -1635, -947, -2399, -1748, -1546, -1794, -870, -4803, -2651, -1760, -1825, -737, -1535, -4039, -2533, -1711, 154, -150, -5934, -2753, -484, 1019, -933, -7073, -2866, 5, 1070, -3637, -5680, -4080, -1145, -109, -2894, -3903, -7681, -5198, -2927, -1149, -3309, -13945, -4640, -7076, -712, -4112, -8977, -2381, -8465, -1063, -5929, -6661, -2103, -10346, -2170, -6951, -5306, -1922, -8416, -3844, -6126, -3923, -918, -6938, -3284, -5098, -1641, 232, -4789, -1976, -5542, -320, 584, -2403, -1930, -9068, -89, -478, -1271, -3167, -8062, -453, -3539, -1173, -4139, -5769, -675, -2442, -1128, -3323, -5757, -424, -655, -992, -3463, -5377, -141, -554, -1804, -4584, -4849, -221, -1415, -3947, -3942, -5664, -758, -2821, -5311, -2857, -7407, -1807, -4706, -4203, -2952, -7839, -3364, -7523, -2643, -4658, -7175, -4285, -10408, -1974, -8684, -5055, -3850, -10031, -3020, -4467, -3341, -3543, -10283, -8030, -2506, -2501, -3456, -9502, -4641, -2462, -2508, -3156, -8393, -1826, -4311, -3506, -2583, -6880, -1017, -10471, -5698, -1943, -5264, -1200, -6114, -8872, -1308, -3958, -2024, -3779, -9555, -714, -3006, -3196, -2756, -7642, -318, -2665, -4451, -2181, -7800, -232, -3248, -5932, -1995, -9862, -387, -5214, -7985, -2473, -5118, -634, -10596, -6671, -590, 828, 1140, 897, -4455, 836, -453, 1020, -805, -8201, 1240, -3314, 1013, -1857, -4285, 878, -10100, 575, -1714, -2248, -534, -4527, -1053, -2108, -1398, -3738, -3428, -5782, -2540, -1106, -8967, -1979, -7322, -2507, -1225, -4764, -375, -5824, -3301, -1909, -188, 210, -5874, -5913, -2966, 2004, 13, -2887, -11871, -3077, 2628, -182, -2256, -7499, -2382, 1941, -20, -2963, -6365, -2134, -214, 85, -3343, -6950, -2664, -5440, -97, -2891, -9609, -4111, -6051, -512, -1859, -6414, -4387, -2835, -991, -1289, -3253, -1811, -2261, -1819, -1961, -2581, -154, -3716, -3708, -4248, -2866, 428, -5957, -4586, -5717, -1388, 250, -1362, -2812, -4076, -46, -232, 202, -2495, -3994, 145, -473, -293, -2952, -5457, -607, -394, -2999, -2029, -5329, -1868, -402, -1902, -730, -2852, -2581, -860, 88, 94, -1471, -1763, -1976, 154, 599, -1287, -409, -3449, -1277, 655, -2383, 311, -2279, -4613, -296, -5104, -67, -199, -7294, -3867, -8220, -1944, 800, -3967, -4647, -7273, -3447, 759, -2999, -810, -6999, -836, -375, -3924, 91, -6887, 602, -3578, -9585, 263, -6229, 989, -4598, -5303, 443, -5622, 594, -814, -1778, 190, -5693, -602, 161, -20, -1138, -6369, -3280, -345, 693, -4110, -7452, -10517, -2039, 522, -6520, -10090, -1877, -3949, -111, -3046, -10215, 153, -3469, -1228, -858, -4303, 197, -3005, -4583, 20, -1881, -1980, -3873, -6635, -204, -969, -12129, -6634, -2248, -1165, -1067, -3411, -14424, -1216, -2162, -1806, -3472, -10512, -1015, -3433, -2713, -8785, -8797, -1523, -4765, -3220, -6674, -6629, -2753, -1521, -3010, -5032, -4341, -2046, 556, -2567, -5564, -2743, -961, 1157, -2728, -4715, -2157, -1369, 577, -3680, -2853, -2554, -3246, -935, -4763, -1830, -3949, -5571, -2846, -4939, -2357, -7216, -5189, -5632, -5028, -5879, -6176, -3218, -5355, -6656, -7252, -2515, -2071, -1519, -8773, -3268, -1159, -1901, 43, -6697, -2751, -1582, -2470, 251, -5832, -3593, -4347, -3784, -472, -4930, -4996, -2333, -5359, -1016, -3163, -5633, 387, -3609, -360, -1554, -4434, 1352, -1620, 357, -653, -2786, 1356, -955, 589, -304, -1947, 814, -1709, 232, -331, -2133, -95, -4579, -960, -981, -3216, -1523, -9511, -3151, -2752, -5009, -4028, -4287, -3325, -6326, -7580, -8835, -2825, -1915, -12577, -9888, -6154, -2438, -1518, -16095, -8728, -4523, -2806, -1754, -12740, -4331, -4205, -4441, -2262, -10771, -1767, -4063, -7782, -2945, -5524, -579, -3885, -4925, -3475, -2923, -415, -3872, -3641, -3227, -1621, -1265, -3880, -3911, -2963, -1030, -3607, -3291, -2867, -3751, -882, -10713, -2529, -1312, -6123, -944, -7948, -2416, -1050, -9084, -1181, -7284, -3032, -2472, -8240, -1961, -10394, -3808, -7257, -8586, -3656, -7317, -4037, -6884, -10044, -5869, -5150, -3836, -5947, -2580, -1817, -63, -1113, -9139, -3509, -732, 2203, -2243, -7660, -666, -399, 3078, -3463, -3819, 709, -1157, 2992, -3260, -3360, 978, -3220, 2087, -1007, -5895, 413, -6009, 198, 468, -7010, -938, -5300, -2032, 601, -3241, -3022, -4062, -1096, -266, -2400, -3961, -3889, -541, -976, -2954, -2619, -4510, -1088, -1482, -3296, -1694, -3411, -1747, -2278, -2002, -1510, -1566, -1565, -2514, -1351, -1842, -731, -667, -2777, -2532, -1939, -895, -195, -2897, -6893, -1062, -1717, -852, -4150, -2542, -28, -2440, -3422, -5473, -890, 332, -3761, -6847, -2396, -1703, -569, -8831, -1617, -2322, -6028, -4802, -1462, 155, -5542, -3449, -3114, 1202, 196, -3242, -1460, 157, 2223, -1741, -982, -1798, 999, 2258, -4027, -504, -2424, 1102, 1597, -309, -858, -1269, 835, 568, 1041, -1503, -573, 96, -538, 860, -2239, -1024, -476, -2009, -584, -3420, -2146, -1219, -4215, -3154, -5719, -2372, -4291, -5754, -5190, -10646, -2435, -8020, -6840, -4674, -10945, -3730, -3218, -7367, -2206, -6945, -6626, -2250, -5292, -295, -4357, -7260, -2140, -4918, 608, -2141, -4577, -3272, -6137, 700, -806, -4059, -8068, -7767, 67, -862, -2626, -6891, -9693, -1233, -2828, -190, -4005, -13823, -3004, -7741, 1078, -2999, -7404, -4510, -6447, 1406, -1940, -6131, -1874, -7410, 1286, -1144, -5664, 323, -9777, 931, -869, -4100, 1027, -5152, 3, -929, -3232, 550, -2988, -2172, -960, -3351, -688, -2065, -5764, -756, -3666, -2056, -1780, -2930, -674, -3646, -3854, -1655, -605, -1363, -3738, -5948, -1755, 749, -3931, -4082, -4189, -2218, 1260, -7893, -3659, -2275, -2730, 775, -2651, -2921, -1098, -2917, -955, -1833, -3719, -945, -3060, -4225, -3916, -10150, -1887, -3949, -4420, -7190, -3920, -2446, -6648, -3020, -2013, -1590, -1372, -9080, -3407, -786, -1784, -739, -6573, -5994, -1196, -4625, -954, -5556, -5302, -2991, -6013, -1596, -3238, -2435, -6571, -2527, -1443, -1401, -1446, -12956, -1688, -623, -692, -1449, -9256, -1925, -434, -936, -2392, -6646, -2804, -1317, -1929, -6513, -7742, -4992, -3521, -3534, -4806, -5703, -11473, -7166, -5587, -1267, -2751, -6370, -6135, -5950, -694, -2614, -5122, -3782, -4633, -1739, -4493, -4723, -2648, -3777, -4008, -2574, -3483, -2485, -3100, -5203, -825, -2691, -3275, -2515, -3061, -688, -2771, -4995, -2296, -1519, -1502, -3411, -4819, -2533, -989, -1955, -4571, -3057, -3199, -1354, -1337, -6963, -2599, -4289, -2705, -1162, -9032, -3603, -5197, -5798, -2242, -8257, -6241, -4827, -14563, -5396, -9561, -8319, -4668, -6812, -10119, -13471, -6541, -5009, -7422, -5365, -9996, -4516, -3651, -8204, -3802, -6835, -2656, -2308, -3295, -3198, -5994, -1602, -2187, -1432, -3289, -6904, -1313, -3172, -1048, -4012, -7904, -1301, -4601, -1706, -5041, -7724, -1318, -5221, 9893, 6950, 9734, 7998, -3265, 9282, 6868, 9246, 7306, -879, 7376, 6226, 7886, 5027, 487, 4021, 4447, 6120, 1103, 1111, 198, 1432, 4432, 1914, 1731, -41, 270, 2231, 2670, 2032, 765, 1266, -1073, 2285, 1999, 57, 2064, -1174, 1420, 1713, -4, 2528, 18, 208, 1011, 2531, 2550, -774, -987, 247, 4302, 2273, -1992, -512, 1069, 5292, 2765, 601, 259, 2656, 5511, 3997, 1922, 615, 3785, 4756, 4676, 1487, 1453, 4497, 2866, 4353, -1937, 1953, 5063, 1640, 2681, -406, 1008, 5555, 2238, -1792, 3028, -2156, 5709, 1660, -707, 4037, -1697, 5139, 1333, 1563, 3710, 144, 3461, 2740, 1301, 2213, 216, 279, 3573, -1012, -915, -575, -2572, 4101, -6155, -5955, -974, 776, 4613, -6417, -2489, -160, 3507, 4596, -3033, -2042, 376, 4807, 3740, -543, -3313, -291, 4973, 2331, 90, -4669, -1893, 4219, 1493, -1212, -3760, -962, 2868, 1060, -4321, -2394, 350, 1828, 136, -1545, -2829, 486, 1568, -150, 91, -6332, -233, 1223, 791, 955, -972, -1221, 404, 1432, 1927, 1262, -538, -576, 1452, 2499, 1585, 1448, -604, 990, 2197, 668, 2686, -106, 401, 527, -548, 2888, -561, 375, -5179, -647, 2015, -2836, 934, -1038, -715, -143, -6899, 1233, 1224, -2034, -4156, -4439, 707, 970, -5586, -6884, -3377, -790, -1534, -10400, -6638, -2846, -2670, -2224, -4720, -4488, -2764, -3121, -458, -2227, -2505, -3033, -2467, -895, -1393, -2155, -2927, -2708, -2651, -2073, -2826, -2188, -5623, -2440, -4684, -3015, -1380, -7691, -1396, -8090, -3008, -1330, -2732, -1107, -4133, -4632, -2552, -1529, -1286, -2098, -8551, -5014, -1830, -1746, -1218, -6037, -4872, -2835, -2461, -1528, -5820, -4374, -3178, -3227, -2825, -7996, -6427, -3596, -3601, -3179, -7516, -5452, -5289, -4098, -2506, -5674, -2494, -6585, -5832, -2239, -5129, -1965, -6739, -7895, -2245, -6075, -3593, -12704, -6431, -2473, -5989, -8011, -5722, -6393, -2616, -3421, -7615, -2983, -6584, -2418, -2383, -7676, -2490, -4175, -2544, -2873, -5523, -3387, -2302, -3566, -4987, -4964, -5383, -1518, -5393, -9860, -6669, -8023, -1758, -6861, -8351, -5303, -8833, -3061, -5485, -5551, -3952, -6464, -5607, -3324, -4449, -4393, -4230, -9981, -2401, -4229, -6714, -2955, -12310, -2517, -4169, -5225, -2739, -8967, -3045, -3946, -2176, -3315, -6666, -3395, -4325, -1027, -3142, -4725, -3617, -6432, -1090, -1997, -3373, -3991, -8417, -1858, -1347, -2983, -4736, -5653, -2642, -1435, -3830, -5918, -4329, -3166, -2324, -6439, -7517, -2801, -3681, -4403, -7189, -8238, -1590, -3374, -9389, -3213, -5115, -866, -2799, -9122, -880, -2473, -394, -3240, -5616, 298, -980, -554, -4377, -4575, 393, -443, -1834, -4171, -5295, -725, -757, -4530, -2532, -10057, -2845, -1725, -8647, -698, 3683, 4463, 1825, -124, 2917, 3531, 4227, 4240, 35, 2671, 2782, 3483, 5662, 524, 2710, 504, 2319, 5436, 1115, 3175, -3508, 963, 3424, 1254, 3130, 543, -871, -2756, 521, 2540, 1362, -2417, 1540, 422, 1314, 82, -1317, 3275, 2037, -1669, -2950, 414, 3145, 2608, -6893, -6719, 2433, 1962, 1679, -5415, -244, 4197, -253, -665, -1236, 3013, 5400, -2164, -3883, 1545, 4445, 5907, -791, -4302, 2164, 4659, 5654, -2012, -1539, 953, 4030, 4641, -1671, 1948, -2540, 3135, 2907, 2284, 4142, -1780, 2362, 508, 3697, 5003, -104, 1246, -2934, 3750, 4673, -57, -356, -7216, 2959, 2988, 324, -1990, -788, 1999, -1190, 1584, -6384, 1481, 1711, -875, 2793, -3376, 1938, 1773, 816, 3392, -910, 903, 1359, -1253, 2831, -1619, 1642, -188, -731, 255, -5239, 3956, -4493, 2828, -8619, -2533, 4856, -4998, 3833, -1001, -1084, 4393, -3073, 3923, 618, -1142, 2651, -4611, 4240, 1265, -881, 210, -5301, 4501, 1122, -499, 193, -4510, 3983, 262, -1048, 1801, -4984, 2540, -291, -2398, 2929, -4414, 757, 537, -2886, 3307, -4481, 103, 1723, -996, 2971, -4340, -56, 2378, 779, 1931, -1460, -617, 2165, 1457, 356, 324, -1165, 1014, 957, -219, 749, -1223, -80, -772, 268, -53, -1566, 7, -3643, 100, -2097, -3244, -380, -5296, -443, -5329, -3409, -1484, -4828, -764, -7308, -397, -2607, -4755, -1428, -5650, 1043, -4558, -3782, -2276, -4608, 1365, -4631, -3248, -2331, -4564, 937, -3603, -4689, -1848, -5570, -114, -4942, -6652, -1041, -8989, -1444, -4558, -4670, -768, -8841, -1623, -2698, -3964, -1574, -4905, -1545, -2709, -3772, -1889, -3496, -2481, -4800, -3080, -487, -3199, -2491, -6607, -2057, -99, -3860, -956, -4339, -1413, -1421, -5906, -119, -5179, -1661, -4126, -6756, -18, -9412, -2886, -3466, -4567, -490, -4385, -3190, -3539, -4647, -1720, -3269, -2601, -6575, -8530, -4143, -4104, -3705, -7531, -6789, -4666, -5399, -6984, -4920, -3645, -2381, -3745, -4689, -3534, -2175, -1047, -1526, -3752, -2596, -1387, -478, -439, -5222, -2893, -1772, -690, -638, -9504, -5060, -3742, -1752, -2606, -5450, -5338, -4699, -3223, -8253, -2526, -2665, -3154, -3203, -3882, -1171, -1418, -2852, -1799, -2719, -769, -956, -3830, -592, -3001, -893, -876, -6593, -122, -2411, -1366, -712, -6676, -453, -1599, -2241, -174, -5179, -1158, -1393, -3593, 190, -8457, -1606, -1738, -5732, -191, -5409, -1791, -2832, -8734, -1571, -1648, -1687, -4201, -8852, -4170, -527, -1602, -4051, -5823, -9139, -730, -1987, -3716, -3907, -11209, -1602, -2843, -3955, -3356, -8787, -2174, -3993, -4651, -3786, -10514, -2840, -4097, -4885, -5179, -7967, -4623, -2429, -3972, -9638, -4419, -2540, -1185, -3861, -8437, -2446, -244, -882, -5374, 2071, 5274, 358, 3097, 2901, 3087, 5290, 179, 2440, 4240, 4286, 5227, 2071, 2279, 5543, 4640, 4868, 3722, 3871, 5615, 4256, 4036, 3915, 4598, 4038, 3599, 2603, 2792, 4107, -820, 2694, 333, 669, 2386, 1352, 545, -2228, -1132, -297, 2616, -4617, 66, -478, 928, 1899, -3609, 2059, 1131, 3144, 3561, -2802, 2953, 1802, 4341, 5646, 176, 3275, 1193, 4703, 6660, 1689, 3389, -406, 4168, 6646, 1494, 3245, -202, 2362, 5312, 546, 2550, 672, -1315, 1314, 539, 1039, 99, -305, -1380, 537, -1736, -2001, 1107, 2170, -629, -4142, -3126, 824, 2788, -3120, -323, -1983, -1179, 3342, -5279, 1431, -1203, -15504, 3500, -8644, 1589, -289, -1264, 2896, -1443, 1085, 870, 683, 1977, 1646, 1753, 1766, 762, 1584, 2523, 2441, 2014, -410, 1828, 1733, 2143, 1665, -2458, 1779, -580, 1122, 1333, -2289, 443, -2330, -694, 1141, -851, -5301, -1406, -4307, 201, -240, -704, -1220, -1759, -349, -231, 1902, -3224, -1091, 1012, -494, 2122, -3760, -3942, 1430, -685, 606, -911, -2434, 572, -741, -1792, -827, 187, -959, -812, -1344, -3080, 1182, -2765, -1219, -396, -2854, 1454, -6097, -2278, 349, -346, 984, -5858, -1832, 586, 208, 185, -3048, -159, 35, -1482, 5, -482, 323, -1365, -9304, -245, 965, -492, -2805, -809, -578, 1008, -2378, -2286, 462, 348, 162, -3310, -1562, -1082, 1163, 61, -1521, -886, -10256, 1089, 201, -321, -304, -1749, 651, -802, -186, -472, -786, 487, -3197, -700, -1998, -2250, 30, -5741, -1330, -5332, -5894, -1304, -5224, -2301, -5321, -7508, -3500, -4848, -4435, -5400, -4138, -5353, -5387, -4648, -5943, -2636, -4929, -5749, -2260, -5960, -2548, -4522, -5910, -1570, -11322, -3391, -4287, -4582, -2262, -5475, -4224, -5056, -2469, -3304, -3208, -5285, -15497, -1671, -2481, -3233, -7761, -3302, -2240, -1290, -4304, -7305, -748, -3313, -959, -4685, -8587, -138, -2873, -1691, -5040, -9775, -750, -2175, -3745, -8771, -4605, -2461, -1900, -7811, -6671, -3613, -5205, -1659, -16669, -3382, -4566, -5873, -1742, -7431, -2962, -7979, -4609, -2757, -3770, -4067, -8369, -3708, -5023, -1628, -5470, -4799, -3005, -7284, -787, -4821, -3364, -3245, -8660, -1205, -3282, -2386, -5394, -21635, -2749, -3176, -1431, -9820, -6374, -4620, -5153, -994, -7799, -3404, -5608, -4621, -1549, -4089, -1986, -5269, -2318, -3083, -733, -1068, -3624, -1497, -3572, 905, -463, -2247, -1346, -2685, 1208, -663, -1894, -1327, -2314, 308, -1739, -2844, -1368, -2315, -1855, -2198, -5478, -1863, -2681, -4685, -2098, -9135, -3094, -4042, -6115, -3475, -7313, -4275, -7120, -11604, -4665, -5881, -3958, -4008, -5829, -2099, -5042, -3526, -1499, -3020, -955, -4614, -3889, -628, -2335, -978, -5090, -5198, -6693, -2397, -2436, -6940, 413, -3124, -1150, -1766, -4277, 569, -1716, -1089, -821, -3726, -133, -1335, -2118, -574, -4771, -1118, -1788, -4533, -1089, -6483, -1203, -3295, -7803, -1687, -7666, -782, -7035, -5120, -1532, -8367, -640, -8173, -3809, -1042, -5039, -758, -4992, -2834, -766, -2795, -1257, -4148, -1562, -1042, -1781, -2915, -3268, -924, -2126, -1678, -6465, -2094, -1358, -3889, -2569, -2978, -1369, -2705, -4702, -4670, -1376, -1192, -2399, -4298, -3541, -1823, -1405, -688, -4292, -1129, -4441, -1744, 165, -4909, -83, -8700, -2234, 64, -6111, -44, -5034, -3463, -1129, -8544, -933, -3916, -5216, -4297, -9496, -3055, -4060, -5058, -6889, -5530, -6880, -5043, -5511, -3563, -3947, -5509, -4620, -9826, -3077, -3703, -4110, -2473, -9109, -3073, -4321, -4340, -1237, -6172, -2252, -4721, -5560, -1206, -4919, -1714, -3427, -5315, -2540, -3081, -2010, -2043, -3547, -5688, -1806, -3034, -1653, -2336, -6185, -1448, -4324, -2606, -1612, -4627, -1750, -5049, -5608, -1617, -4301, -2017, -4837, -10434, -3121, -3926, -1761, -4320, -6408, -8827, -3809, -1742, -3933, -5517, -7753, -4951, -2753, -3445, -5975, -8179, -10358, -5800, -2992, -6739, -8190, -6338, -11959, -2968, -4780, -3609, -3461, -5121, -3250, -2908, -2881, -3423, -3601, -3812, -2465, -4197, -6068, -3341, -5352, -3239, -7876, -8982, -3038, -5348, -4535, -9111, -5954, -1789, -3284, -4922, -5043, -5908, -801, -2898, -4112, -2754, -6412, -731, -4210, -3444, -1365, -6418, -1557, -7601, -3078, -1010, -6761, -2828, -12376, -2903, -2004, -8207, -3801, -7601, -3812, -5223, -8936, -4466, -7246, -7516, -7407, -6897, -5080, -11590, -5389, -3402, -4261, -6361, -6756, -2689, -1936, -2229, -7673, -4149, -1919, -1751, -1495, -5312, -3567, -2082, -2883, -2053, -4058, -3840, -2715, -6105, -3758, -4086, -4213, -3681, -9655, -7278, -5025, -4966, -5049, -5135, -8523, -6913, -6019, -5251, -3028, -3299, -7882, -4942, -4176, -1766, -1731, -6423, -4198, -3960, -1243, -1617, -6221, -5419, -4669, -1382, -2249, -7777, -9966, -5818, -2018, -2800, -11253, -7221, -7299, -2961, -2481, -11771, -6067, -8673, -4298, -1633, -8038, -7159, -8733, -5798, -1147, -5952, -6394, -8592, -4579, -1465, -5627, -4546, -7981, -3215, -2877, -6026, -3884, -7634, -3317, -6058, -4868, -4166, -8562, -4982, -14775, -3836, -5090, -10727, -6290, -6773, -4127, -5961, -10665, -4646, -4232, -6169, -5847, -7353, -4010, -3031, -13470, -5311, -4702, -4576, -2828, -9168, -5029, -3332, -5408, -3340, -7328, -5208, -3058, -5153, -4181, -7644, -6256, -3696, -5304, -5532, -8713, -9250, -4765, -7600, -6878, -7966, -7504, -4952, -13402, -4994, -6511, -4579, -4783, -7267, -3893, -6276, -3691, -5962, -6824, -4245, -7964, -4287, -11713, -9145, -5564, -10924, -6544, -7722, -13292, -6756, -7277, -10999, -4536, -12303, -6903, -6011, -8762, -3384, -8783, -7266, -5094, -1758, 539, -1365, -4791, -4721, -2575, 280, -2241, -2165, -6321, -5738, -745, -3091, -1159, -8461, -5071, -2328, -3748, -1559, -5463, -2303, -4316, -4237, -2643, -4484, -1084, -7260, -4257, -2386, -5808, -502, -9351, -3275, -2278, -5282, -685, -5953, -2327, -4449, -2162, -2211, -4664, -2235, -11079, -874, -6058, -3890, -3257, -3600, -1054, -5523, -3336, -5205, -2252, -3012, -4600, -3611, -4839, -2429, -12304, -6370, -4213, -3251, -3541, -3974, -8535, -3213, -2980, -5442, -2141, -8424, -1759, -4405, -5868, -2593, -9943, -955, -5322, -4002, -5310, -10303, -894, -3296, -3313, -9276, -8628, -1514, -3113, -4392, -6355, -6785, -2784, -5316, -8109, -6109, -6047, -4949, -6070, -7465, -6936, -5086, -6889, -2832, -7369, -6030, -3774, -4208, -1253, -8404, -3820, -3682, -2389, -679, -3868, -2504, -5052, -2034, -1099, -1895, -2037, -4638, -3185, -3038, -868, -2173, -2866, -6430, -9804, -424, -2733, -2356, -7989, -5663, -811, -3507, -2854, -5952, -4975, -1880, -4178, -3808, -6414, -5351, -2707, -4521, -4528, -8718, -2235, -4135, -4597, -4677, -8254, -804, -6268, -4446, -3836, -9373, -640, -2699, -4008, -2669, -9369, -1061, -1315, -3832, -2167, -3958, -1699, -1593, -4476, -2625, -2028, -2486, -3115, -4525, -4117, -1429, -3197, -5245, -3167, -6147, -1533, -3729, -5266, -2557, -5763, -2090, -4646, -4320, -2833, -3939, -3538, -6731, -4405, -3527, -2938, -8177, -7466, -5799, -4107, -3175, -6661, -4212, -7763, -3838, -5107, -3701, -2595, -6778, -3437, -9132, -3471, -2411, -6444, -3854, -5967, -4620, -3650, -7721, -4753, -4224, -4841, -6932, -4576, -5572, -3361, -3391, -7439, -2177, -7651, -2442, -2727, -4821, -1431, -15264, -1812, -3167, -3935, -2009, -9428, -2125, -4544, -3858, -4016, -8822, -3363, -6455, -4417, -8595, -10716, -3291, -9719, -6556, -7831, -9129, -2689, -14961, -11897, -5334, -6140, -4082, -10302, -5638, -4772, -4843, -9858, -6458, -4837, -4478, -4410, -4187, -4183, -5874, -3020, -4188, -2493, -3906, -4757, -1700, -4013, -2692, -5375, -4042, -1573, -4192, -4489, -7997, -4416, -3228, -4402, -8039, -8710, -3564, -6046, -3384, -5108, -7259, -3197, -3036, -2377, -2994, -7188, -4405, -1827, -2444, -2195, -9858, -5077, -1842, -3757, -2257, -9107, -4206, -2181, -6015, -3182, -8494, -4305, -2950, -6589, -4508, -13431, -5429, -4654, -6104, -3609, -6191, -7352, -4738, -6426, -2113, -4235, -6788, -3346, -7461, -1490, -4282, -4553, -3139, -9259, -1646, -5598, -2930, -3924, -11458, -2406, -7733, -2064, -5018, -10187, -3546, -10919, -2177, -5494, -8587, -4725, -11695, -3399, -5475, -7729, -5695, -6528, -5951, -5992, -7138, -6525, -4372, -11951, -6613, -5776, -6964, -4011, -9602, -4965, -4208, -6534, -5737, -7235, -3685, -3411, -5973, -14497, -7473, -3750, -3294, -5934, -5699, -9083, -5165, -3318, -6469, -4112, -8797, -8091, -3206, -7289, -4758, -7385, -13164, -983, -2618, -1430, -6237, -6901, -2444, -3226, -1698, -4829, -7651, -3930, -3933, -2127, -4045, -9454, -3907, -4364, -3061, -5928, -9154, -4016, -4725, -3306, -10267, -6507, -4147, -6880, -2790, -3706, -5966, -4041, -8154, -2811, -1877, -6466, -3886, -4459, -2223, -1488, -7046, -3697, -2987, -1109, -2058, -7563, -3708, -2432, -971, -3695, -8193, -2804, -2787, -2060, -8280, -9323, -1595, -4177, -3683, -6437, -12501, -1280, -6059, -3919, -2800, -11453, -1949, -6527, -3085, -1425, -9891, -3501, -3659, -2804, -1343, -11028, -5985, -1959, -4378, -2792, -6076, -9615, -1845, -9014, -5251, -3560, -11352, -3228, -4238, -3017, -2309, -8728, -5041, -3193, -1803, -1228, -6368, -2893, -4937, -2003, -375, -5447, -749, -9557, -3031, -201, -5586, 505, -3438, -4368, -737, -5887, 1022, -1503, -5542, -1723, -6895, 933, -961, -7023, -2900, -11516, 625, -1297, -12475, -4248, -9750, 605, -2522, -7218, -5872, -6866, 534, -4454, -4463, -8378, -6013, -297, -4135, -4382, -14230, -4859, -2286, -2914, -7407, -9845, -3623, -4097, -2763, -5304, -9005, -3696, -2495, -3462, -2115, -8544, -5963, -1348, -3882, -987, -4457, -7470, -1439, -3310, -899, -2184, -5336, -2739, -3180, -1397, -1390, -5633, -3845, -4027, -2116, -1766, -6484, -3335, -5731, -2782, -2970, -5438, -3612, -7501, -3358, -3969, -4071, -5267, -6485, -3966, -4561, -2938, -8219, -4049, -4750, -6253, -2217, -9780, -2429, -5805, -7919, -1982, -7617, -1792, -7054, -5938, -2146, -6167, -1846, -8343, -5433, -2438, -5843, -1846, -9650, -6905, -2410, -7158, -1193, -9534, -10417, -2000, -12900, -399, -6743, -7047, -1744, -7605, -143, -4190, -4915, -2287, -4745, -836, -2500, -4223, -4594, -3315, -2877, -1744, -4608, -11793, -2157, -6722, -1960, -6021, -5013, -913, -6898, -3122, -7735, -3919, -49, -4869, -4548, -7977, -4797, 55, -4032, -4615, -6303, -6967, -623, -4596, -4538, -4574, -7977, -1834, -6415, -4690, -4360, -7051, -2900, -7709, -3442, -6105, -5977, -3239, -7452, -2039, -4954, -4467, -3367, -4470, -1369, -2568, -3856, -3578, -2824, -1408, -2082, -5095, -3258, -2876, -2106, -3241, -9538, -3047, -4457, -3370, -6342, -6241, -4427, -7243, -4289, -10023, -5125, -7772, -8947, -3484, -8418, -7120, -5262, -7066, -2664, -8736, -10187, -4987, -4961, -2399, -13039, -5705, -7055, -3659, -2047, -8617, -4646, -5492, -3211, -1724, -6067, -4670, -3438, -3741, -2229, -5475, -3997, -2771, -5357, -4129, -5380, -3021, -3085, -7386, -7047, -5142, -2896, -3938, -7699, -6699, -4483, -3973, -5248, -8577, -6873, -3673, -6820, -8722, -9155, -7596, -3153, -15415, -11084, -7236, -7217, -2845, -10475, -6924, -7289, -7188, -2861, -10334, -6502, -11166, -7858, -3324, -9201, -5974, -8784, -9039, -3723, -6916, -4568, -5916, -8996, -3705, -6047, -3705, -5480, -8428, -3879, -6029, -3437, -5810, -8973, -4596, -5666, -3464, -5546, -8858, -5801, -5238, 15165, 2220, 10293, 9886, 8359, 14767, 5638, 9599, 9189, 10163, 13535, 6920, 7288, 6853, 10144, 11358, 6285, 2129, 1303, 9299, 8385, 4271, 475, 1013, 8251, 7587, 1764, 688, 1984, 6512, 8553, 128, -249, -611, 3759, 8828, -867, 256, -6937, 5346, 8283, -328, -509, -264, 6056, 6842, 1506, 1386, 1412, 4279, 4689, 3435, 3697, 2469, -3939, 3292, 4896, 4869, 3037, 1643, 3547, 5663, 5200, 3137, 1847, 4912, 5548, 4834, 2720, -1288, 5655, 4299, 3914, 1229, -7067, 4971, 1763, 2803, -2426, -3092, 2336, 631, 1807, -2942, -2819, -836, 1185, 836, -1536, -5055, 1715, 493, 50, -1759, -1808, 2202, -1063, -527, -2432, -664, 1002, -2089, -1745, -6010, -296, -2271, -1179, -4133, -3901, 1201, -5958, -318, -3961, -898, 2363, -3331, -739, -3644, -745, 2815, -2835, -2475, -6246, -1696, 2777, -3418, -2199, -6704, -874, 2129, -6288, -653, -4689, -13, 121, -6716, -278, -5560, -415, -8130, -1474, -1032, -5326, -1839, -1879, 429, -3153, -3739, -3077, -201, 1026, -7811, -3606, -2202, -740, 728, -17050, -3349, -857, -1628, -260, -9764, -3061, -223, -1872, -1284, -5219, -3867, -554, -3348, -1211, -3364, -4911, -2136, -5185, -949, -3196, -6153, -3803, -4069, -1546, -4273, -11220, -2293, -5814, -3211, -5874, -9225, -1543, -7654, -4453, -6492, -8702, -2022, -3445, -3538, -5984, -11835, -3137, -2778, -3033, -5314, -7909, -4071, -3630, -3184, -5341, -5343, -5856, -4960, -3531, -6565, -3590, -10830, -5853, -3938, -7846, -2905, -4797, -4374, -4549, -6669, -3654, -3344, -2147, -5170, -6659, -4874, -3849, -841, -5242, -9633, -3131, -5622, -363, -4773, -11108, -1937, -7477, -427, -4271, -6912, -1979, -7271, -877, -4149, -5375, -2753, -6536, -2024, -4627, -4488, -3442, -6879, -4657, -5827, -4222, -3640, -8266, -9185, -7401, -4772, -4017, -8267, -7768, -7331, -6096, -5318, -6145, -7204, -6757, -7470, -8929, -4211, -6455, -7478, -7380, -8746, -2915, -6007, -11402, -6159, -5388, -2385, -5302, -10046, -4972, -4620, -2669, -4366, -5827, -4223, -5372, -3708, -4377, -4049, -3955, -7320, -5222, -5567, -3183, -4157, -10406, -6307, -7145, -2926, -4542, -15272, -5720, -7004, -3214, -4562, -9529, -5296, -6641, -4069, -4579, -8847, -6434, -8733, -5309, -5471, -11759, -9022, -9436, -6037, -8163, -10258, -7918, -3794, -5935, -12911, -7705, -6644, -1835, -5753, -8442, -7612, -6550, -1397, -5687, -7383, -8925, -7595, -2077, -5466, -7698, -9273, -9340, -3655, -5085, -7302, -8444, -9286, -6043, -5029, -5724, -8654, -9691, -11093, -5857, -4828, -10089, -13643, -10036, -7491, -4924, -11296, -12769, -6573, -5603, -5821, -10109, -9007, -5561, -4060, -7081, -9241, -7857, -5062, -4361, -8146, -8987, -7778, -4128, -6806, -9337, -8181, -8017, -3304, -13477, -9510, -6888, -7578, -3356, -8468, -7269, -6063, -7039, 8741, 3952, 6975, 8689, 7461, 7965, 4037, 6240, 8235, 7088, 5365, 3753, 3586, 6965, 5982, -709, 2291, -8624, 5319, 4748, -4470, -1068, 620, 4040, 4512, -2797, -1090, 558, 3121, 4183, -367, 1438, -3119, 1993, 3133, -592, 3228, -56, 84, 2502, -3397, 4205, 2057, -3665, 3187, -7182, 4323, 3214, -7878, 4075, 583, 4282, 4808, -2543, 4389, 3794, 4987, 6275, 193, 3820, 5394, 5719, 6925, 1546, 2253, 5734, 5810, 6541, 1361, -167, 4882, 5234, 4868, 613, -2154, 2816, 4206, 1450, 2241, -1280, 161, 2891, 1105, 3465, -94, -137, 982, 2355, 3369, -380, 154, -1515, 1786, 2095, -2752, -326, -166, -31, -185, -7063, -1308, 1459, -1995, -2564, -3374, -2490, 1997, -3375, -4284, -2141, -2608, 1926, -5535, -3928, -2394, -1395, 1648, -6430, -2423, -3605, -709, 1407, -5782, -3505, -4673, -1148, 1209, -7441, -5364, -4258, -3250, 862, -14465, -1560, -2896, -10573, 87, -6434, -360, -1859, -5823, -1257, -4715, -237, -1667, -3697, -2150, -4467, -520, -2329, -2695, -1664, -4289, -1902, -3308, -2223, -1493, -3401, -7242, -3745, -2694, -1736, -3402, -4590, -3741, -4302, -1632, -5902, -1390, -3761, -6770, -1434, -5788, -121, -3823, -8089, -1653, -3119, 547, -3750, -5731, -2427, -3391, 832, -4036, -3416, -3804, -6366, 572, -5602, -2191, -5673, -6006, -681, -10616, -1883, -7549, -4492, -4344, -8372, -2417, -7063, -5091, -6680, -6508, -3977, -5308, -5015, -2084, -6696, -7297, -4537, -3235, -970, -5048, -11384, -4676, -2338, -1043, -3625, -6729, -5139, -2746, -1931, -4086, -4856, -6156, -4940, -3320, -7477, -4850, -11532, -9552, -4050, -10210, -7748, -6825, -6017, -2984, -5601, -10312, -3707, -5121, -1871, -4374, -5851, -3115, -5930, -1696, -4228, -5661, -4027, -6161, -2534, -4901, -7737, -4717, -5627, -4341, -5874, -10902, -3761, -6915, -7455, -6447, -7895, -3654, -18720, -13483, -6889, -6565, -5180, -7222, -9348, -7138, -6865, -9112, -5547, -8639, -6701, -8530, -8968, -6065, -11853, -6201, -8321, -7126, -7279, -10446, -6732, -6220, -6626, -6673, -6152, -9638, -4512, -6631, -6094, -4599, -9879, -3458, -7760, -6785, -4192, -6707, -3481, -12012, -8925, -4470, -6211, -4762, -10526, -11451, -5108, -7719, -7049, -7306, -11076, -5739, -13789, -8367, -6461, -9835, -5993, -8478, -7185, -7141, -8315, -5675, -5652, -6084, -9976, -7564, -5021, -4584, -6254, -17176, -7346, -4589, -4718, -7559, -9942, -7128, -4647, -6373, -9423, -8840, -7063, -4976, -12287, -15035, -9816, -7145, -5328, -7967, -9515, -11203, -6917, -5561, -4906, -6676, -8212, -6556, -4962, -3648, -6157, -6806, -6157, -4169, -3571, -6516, -7052, -5704, -4041, -4950, -6261, -8524, -5911, -4554, -8975, -5784, -10226, -7143, -5486, -8860, -5819, -10541, -7835, -6689, -7483, -6120, -10127, -7749, -7490, -9826, -6313, -10173, -9714, -7104, -11192, 4458, 2870, 7118, 7575, -11243, 3348, 1685, 6636, 7254, -4944, -609, -1185, 5416, 6456, -1588, -1007, 1479, 4418, 5674, 1846, -1635, 2980, 4191, 5048, 4140, -5635, 3251, 3899, 4070, 5286, -975, 2726, 3097, 2906, 5483, -3298, 1238, 1617, 2440, 4715, -1532, -1686, -609, 1671, 2256, 3037, -3160, -3006, -1311, -3579, 5003, 1111, -937, -2107, 2997, 5863, 4373, 1221, 1334, 4453, 5773, 5938, 1434, 2093, 3956, 4642, 5925, -301, 2054, 2136, 2482, 4000, 794, 3022, 2635, 1047, -3405, 2476, 3858, 4138, 880, 467, 2019, 3438, 4503, -16, 1300, -669, 1587, 4082, -466, -1437, -4634, -1483, 3305, -533, -8420, -6667, -6500, 2350, -889, -2601, -5765, -5648, 864, -804, -2077, -1985, -2407, -1520, -198, -1745, -1615, -1994, -1470, 346, -1230, -3470, -2001, -12, 236, -1557, -10862, -1871, 353, -839, -2868, -6024, -2304, -86, -3463, -4276, -3767, -3760, -1369, -9859, -4134, -3319, -5611, -3591, -4525, -3073, -3684, -3931, -4325, -3927, -2727, -4850, -3074, -2305, -7892, -3983, -7513, -5005, -645, -4649, -6189, -13061, -6612, -176, -1450, -2832, -12060, -2315, -1227, -694, -1063, -7551, -1224, -4165, -1451, -781, -4934, -1604, -4534, -3464, -1419, -4606, -2728, -3025, -4085, -2318, -5605, -3903, -2358, -3239, -3209, -5515, -5165, -1846, -3741, -4852, -5936, -7169, -2057, -5461, -7091, -9465, -8962, -3333, -6245, -6562, -7129, -9671, -4477, -6273, -6751, -5552, -11221, -3905, -7579, -9701, -7571, -6112, -4143, -9314, -11239, -9671, -3291, -6937, -9167, -8239, -4276, -1935, -9456, -8446, -5746, -2875, -1615, -5504, -7196, -4037, -2975, -2231, -6170, -5945, -3717, -3918, -3490, -11158, -4926, -4759, -4549, -3561, -4858, -4167, -5523, -4314, -2564, -3533, -3755, -4182, -4855, -2477, -4788, -3605, -3583, -8525, -3652, -11478, -3554, -4205, -6096, -5556, -7369, -3680, -5724, -2706, -6369, -5545, -4411, -7552, -1721, -6916, -6312, -6501, -9040, -2130, -7502, -9788, -11790, -7529, -3799, -6730, -11512, -10105, -6241, -7233, -5022, -7393, -9046, -6171, -8237, -3758, -6358, -8040, -7227, -5758, -3342, -6662, -6714, -10113, -5566, -3729, -8050, -6617, -7486, -7133, -4795, -10028, -7793, -5152, -9578, -6239, -9313, -9877, -4713, -9609, -7260, -7252, -11532, -5531, -9312, -8461, -5703, -11067, -7127, -9298, -11221, -5150, -9746, -8573, -9261, -7140, -6157, -8772, -8980, -9628, -4919, -11494, -8258, -8132, -10059, -4307, -7427, -8265, -6819, -8427, -4611, -4321, -8843, -6113, -6823, -4983, -3504, -9175, -6057, -6212, -4853, -3996, -8911, -5606, -6328, -5217, -5402, -9312, -4622, -7036, -6732, -7241, -10592, -4093, -8669, -7196, -8304, -10786, -4047, -11327, -6214, -7631, -8903, -4054, -8959, -6600, -8118, -8014, -3898, -6536, -8753, -12148, -8668, -3674, -5627, -9694, -9457, -10135, -3660, -6112, -7095, -7659, -4829, -7102, -6498, -5768, -7102, -6936, -6734, -7755, -5765, -7561, -4010, -6378, -10869, -5938, -7981, -2349, -6027, -9615, -5920, -8148, -2201, -6023, -9381, -5366, -7391, -3445, -6148, -9821, -4920, -5938, -6092, -5824, -8314, -5159, -5012, -5167, -5281, -8243, -6280, -5023, -3392, -4739, -11745, -8310, -6182, -3030, -4111, -11193, -10530, -9371, -3623, -3622, -7625, -10460, -15111, -4370, -3745, -6713, -8825, -9433, -4118, -4924, -6975, -8062, -9147, -3587, -7154, -9096, -8549, -11286, -3679, -7569, -12180, -8767, -15624, -4455, -6400, -7286, -7822, -10345, -5084, -4614, -4905, -9334, -7582, -4162, -2134, -2845, -6630, -3609, -2167, -17, -740, -1735, -452, -502, 1187, 862, 480, 1284, 214, 1356, 1522, 1168, 1752, -121, 484, 1039, 556, 972, -1504, -1278, -845, -1431, -1274, -3916, -3357, -4865, -5202, -5812, -7535, -5205, -8171, -12697, -8842, -10191, -6426, -6474, -10853, -7187, -8928, -6003, -6521, -7274, -6582, -9937, -5139, -7692, -6007, -6221, -12284, -5021, -11105, -5926, -5930, -9419, -6087, -10641, -6514, -5528, -7850, -8223, -8236, -7463, -5493, -7054, -9559, -7551, -8722, -6216, -6346, -8339, -8193, -10419, -7790, -6011, -6303, -10805, -11837, -9272, -6640, -4770, -9711, -11618, -9646, -9355, -4113, -7521, -11748, -11232, -9333, -4237, -7380, -13581, -16033, -5474, -4666, -8751, -16529, -14081, -4155, -4990, -11089, -10811, -10738, -4401, -5478, -11609, -8690, -8725, -5911, -6111, -9299, -8324, -8702, -6955, -6697, -7727, -9391, -11741, -6187, -8326, -7471, -11304, -13708, -5902, -16418, -8593, -8898, -9336, -6526, -8725, -11389, -6642, -8172, -7757, -6779, -15746, -5817, -7703, -7228, -7294, -15452, -6349, -7830, -5863, -10127, -14359, -8933, -9199, -5960, -13144, -13676, -12484, -12232, -8559, -10365, -13134, -8452, -10297, -12472, -8164, -12280, -8102, -9018, -8343, -7143, -11929, -10335, -9879, -9266, -7373, -13421, -14360, -10807, -12668, -8397, -14255, -10952, -8965, -8240, -9241, -9871, -10460, -7929, -7171, -9145, -8414, -11568, -7746, -7378, -8297, -8713, -11369, -7947, -6951, -7257, -9695, -10045, -8383, -5811, -6687, -9494, -9430, -8879, -4912, -7073, -9061, -8905, -9013, -4489, -8822, -8683, -8541, -8780, -4744, -10384, -8191, -8858, -8695, -6062, -8407, -8082, -9874, -9036, -9017, -7240, -8356, -11460, -9588, -8399, -6772, -8776, -14374, -9760, -6181, -6490, -9244, -12994, -9444, -5628, -6383, -9540, -9428, -9244, -6381, -6598, -9933, -7944, -9549, -8644, -6929, -11073, -8064, -10229, -13556, -7220, -13279, -10255, -10962, -15329, -7872, -12613, -25624, -11789, -13159, -9007, -9435, -12071, -12529, -9989, -9948, -7981, -11921, -12561, -7856, -9965, -8073, -14185, -12093, -6894, -9528, -9832, -11276, -11549, -6884, -9140, -13116, -9690, -11024, -7704, -8890, -12101, -9682, -10647, -8939, -8893, -11875, -10968, -10730, -9519, -9104, -13947, -13496, -11562, -9776, -9449, -13752, -11391, -13395, -6389, -9624, -16465, -6442, -7466, -6840, -8839, -10579, -6320, -6329, -8537, -9431, -11509, -6801, -5775, -12776, -11379, -15505, -7008, -5151, -9260, -9727, -9754, -6292, -4510, -7001, -7445, -9310, -5955, -4042, -6402, -6402, -11807, -6881, -3903, -7043, -6345, -13333, -10060, -4227, -9048, -7133, -11438, -15372, -5080, -11930, -8676, -8836, -9456, -6219, -8870, -8569, -6909, -7821, -6827, -6598, -6804, -6603, -7425, -6689, -6119, -6132, -7994, -8306, -6495, -7395, -6363, -12395, -10567, -6375, -10852, -6267, -12735, -12963, -6237, -13169, -5422, -8806, -12784, -6011, -8836, -5921, -9344, -7571, -5404, -4695, -11035, -7611, -3635, -3964, -1767, -2650, -2313, -810, -1627, -153, 156, 10, 820, 120, 134, 1037, 737, 1271, 736, -1071, 492, 190, 517, 160, -4510, -1503, -1532, -1610, -1669, -11587, -5463, -4267, -5254, -4741, -8280, -15162, -7212, -6867, -7758, -8927, -12272, -8991, -6882, -7694, -6603, -11110, -9255, -7925, -6672, -4942, -10171, -7343, -9089, -6634, -4274, -9386, -6059, -9577, -6845, -4610, -9093, -6397, -9470, -6499, -6164, -9931, -8640, -9571, -6537, -7640, -13149, -9624, -10646, -7687, -7070, -15768, -7213, -14142, -10798, -7979, -13044, -6278, -11236, -14927, -12957, -15540, -6364, -7963, -10746, -7243, -13890, -7234, -6878, -9893, -5107, -9341, -8881, -7192, -11066, -4954, -7535, -11376, -8430, -12321, -6650, -6869, -15032, -9283, -9100, -14197, -6967, -15599, -7797, -8152, -8514, -7974, -11753, -5950, -9176, -6387, -10935, -9870, -5311, -10894, -6324, -16341, -9195, -6390, -11663, -7128, -10019, -9261, -11025, -11791, -7568, -9002, -9379, -8652, -9165, -7394, -9352, -8714, -6234, -8158, -7802, -9070, -7488, -5989, -9042, -9344, -8042, -6586, -6864, -12293, -10880, -7590, -6404, -8422, -10823, -10168, -7802, -6856, -9588, -7647, -9961, -8530, -7155, -9057, -6166, -11078, -9897, -6731, -8667, -5798, -14226, -12170, -6542, -9721, -6427, -16335, -13202, -7267, -13399, -7961, -11308, -11535, -9159, -17204, -9854, -9240, -10689, -11900, -12876, -11019, -8235, -11085, -12564, -9966, -10665, -7782, -13555, -11505, -8935, -8942, -7669, -14441, -11151, -10175, -7768, -7950, -10255, -12934, -12839, -7580, -8995, -8485, -17870, -11892, -7973, -12074, -7532, -11100, -16350, -7935, -14477, -6916, -9097, -11120, -7431, -9535, -6860, -8405, -8211, -7274, -8373, -7644, -8478, -8013, -7825, -8867, -8892, -9286, -9248, -9057, -10672, -9452, -11033, -9892, -10176, -13720, -10212, -14444, -9741, -10905, -15857, -11506, -18255, -10059, -11254, -11994, -10817, -13174, -10355, -11549, -10362, -10549, -10748, -10769, -14835, -10895, -11818, -9494, -11104, -12061, -14763, -13702, -9219, -11137, -9622, -10427, -15396, -9879, -11703, -9868, -7912, -13792, -11483, -13580, -11679, -7388, -10885, -13456, -23639, -12058, -8362, -9625, -13018, -12653, -11652, -11247, -9247, -11012, -10383, -11355, -17928, -9261, -9521, -10202, -11240, -15208, -9977, -9045, -11615, -12414, -10114, -3970, -8334, -5869, -8970, -9229, -4310, -13488, -5688, -9313, -7789, -4518, -13098, -6176, -6320, -6221, -4871, -11503, -6972, -5298, -5173, -5314, -10167, -8163, -5540, -4841, -5239, -10524, -10875, -6467, -5194, -4537, -9662, -12428, -7536, -6002, -3813, -6677, -8850, -8483, -6964, -3407, -5263, -6918, -9347, -8347, -3453, -4954, -5744, -10223, -10946, -4005, -5209, -5377, -11445, -14886, -4655, -5733, -5939, -11334, -14268, -4448, -6726, -7298, -9502, -10389, -4105, -8853, -8121, -8992, -8542, -4941, -11153, -8126, -9763, -8478, -7911, -8585, -8538, -12136, -8421, -9635, -5953, -6932, -11206, -5318, -5835, -3192, -3692, -4885, -2082, -2022, -652, -966, -1735, -91, 56, 997, 624, -174, 646, 569, 1520, 996, 80, 193, -421, 798, 70, -999, -1448, -3357, -1397, -2473, -3820, -4221, -12012, -4667, -7935, -10437, -7136, -8222, -5044, -15169, -7808, -7900, -8154, -6085, -15738, -6267, -7565, -9659, -9547, -10544, -5693, -7656, -8504, -8180, -8827, -5122, -9644, -6047, -7165, -7995, -4756, -13342, -4937, -8674, -7220, -4943, -8547, -5094, -16086, -6744, -5605, -7958, -6338, -8025, -6950, -6103, -10312, -8173, -6047, -7703, -6154, -11872, -9040, -5874, -8139, -6608, -7372, -8626, -6821, -8573, -7953, -5926, -8458, -8241, -10022, -9390, -6105, -9443, -8828, -12613, -9850, -7899, -11362, -8784, -12567, -12242, -10835, -9466, -9091, -9564, -11749, -9632, -7662, -9057, -7084, -8390, -8928, -7209, -7888, -5694, -8031, -9046, -7896, -7005, -5408, -10131, -8701, -9926, -7092, -6175, -15552, -8263, -14198, -8416, -7737, -10128, -7893, -19648, -12171, -8898, -8567, -6952, -12958, -14097, -9430, -8408, -5916, -8995, -10367, -11185, -9023, -5393, -7523, -10380, -13151, -10173, -5283, -8047, -13643, -9635, -11738, -5285, -10362, -15064, -7977, -12013, -5510, -7585, -10676, -7525, -10252, -6394, -5210, -9757, -7497, -9468, -8360, -4284, -10698, -7487, -10423, -11830, -4265, -12672, -7843, -14152, -16256, -4728, -11014, -8814, -10652, -14344, -5211, -9543, -10244, -8002, -10937, -5613, -8743, -13338, -7280, -9437, -6035, -8430, -14408, -8177, -8749, -6535, -8710, -9385, -11559, -7945, -7557, -9657, -7736, -17573, -7224, -8791, -12450, -7361, -12250, -7151, -7702, -15480, -7544, -10976, -7976, -6557, -10490, -7928, -9773, -9783, -6497, -9302, -9016, -9029, -12423, -7322, -9630, -11402, -8466, -14060, -8830, -10799, -12772, -8346, -11323, -11245, -10842, -13624, -9383, -9700, -15633, -10561, -14654, -11197, -9269, -11468, -10332, -10460, -10194, -8898, -9169, -8613, -8676, -9056, -8087, -8695, -7213, -8226, -8841, -7587, -9421, -6443, -8782, -9153, -8005, -10086, -6048, -10301, -9820, -9972, -9947, -6109, -12165, -10936, -15691, -10654, -6898, -12113, -13707, -12451, -12240, -8843, -11489, -16271, -10362, -10891, -13140, -11680, -10329, -9403, -9133, -14873, -12631, -8537, -8669, -8325, -13261, -13581, -8354, -8244, -8241, -15671, -13412, -9423, 8813, 10397, 10659, 8490, 6718, 8016, 9942, 10005, 7905, 6152, 5336, 8532, 7937, 6131, 4406, 2646, 6102, 4708, 3216, 1406, 3898, 3039, 3748, -79, -1617, 3079, 1561, 2902, -2100, -2952, 1341, 2545, 195, -3053, -11033, 2008, 3509, -1404, -1508, 91, 3027, 3571, -1222, 373, 2781, 2993, 2556, -2068, 1033, 3773, 1180, -249, -3393, 1549, 3892, -1764, -2551, -5508, 3372, 3544, -603, 2574, -5315, 4896, 2781, -1798, 4386, -3700, 5320, 1226, -148, 4572, -3826, 4542, -1227, 1932, 3323, -4813, 2329, 722, 1888, 248, -3533, -2016, 2718, -179, -2923, -978, -4124, 3098, -7186, -240, 829, -3245, 2120, -3145, 966, 1626, -3372, 108, -941, 1235, 1246, -2906, -3208, -446, 1013, -730, -2199, -3670, -1099, 775, -5065, -1910, 888, -3410, 562, -3306, -711, 1797, -3112, -131, -1919, 646, 210, -1290, -1860, -506, 648, -8568, -1965, -5820, 1012, -1470, -2090, -1702, -7525, 1603, -13126, -1030, -82, -2749, 1247, -2015, -1730, -1340, -1634, 414, -49, -693, -8504, -2743, -122, 377, 1062, -158, -7438, -409, -30, 1753, 991, -4883, -600, -115, 826, 387, -4172, -381, 605, -3979, -874, -6606, -627, 1205, -1725, -2647, -4240, -2689, 1415, 1168, -7682, -3140, -14648, 1137, 1515, -4479, -2758, -2630, 193, 427, -1744, -839, -862, -819, -2238, -1687, 103, -714, -218, -9737, -3465, -557, -1492, 439, -5712, -4673, -1832, -2782, 106, -4317, -3455, -177, -3986, -1112, -3988, -2608, 1099, -5197, -2516, -2516, -2493, 964, -5540, -3544, -1251, -3593, -604, -3070, -5482, -744, -7616, -3978, -1337, -12462, -1125, -7786, -8380, -742, -8535, -2774, -4063, -11811, -1018, -7103, -5773, -3582, -5192, -1771, -6211, -6737, -4687, -2416, -2447, -3962, -9365, -5494, -1557, -2921, -2362, -8857, -3950, -1830, -3256, -1536, -4470, -3112, -2783, -2844, -1492, -2905, -3625, -3987, -1998, -2360, -2419, -5022, -5214, -1659, -4169, -2912, -6536, -5247, -2094, -6068, -4404, -12883, -4173, -3040, -5744, -6282, -6009, -3920, -3782, -4821, -8265, -3423, -4906, -4196, -4536, -11284, -3433, -6995, -4462, -4385, -7178, -6038, -8637, -4578, -3974, -5469, -12730, -7578, -4933, -3589, -5236, -6031, -5920, -5391, -3457, -5734, -5707, -5407, -5162, -3782, -6514, -8844, -6256, -4151, -4442, -7372, -9864, -8398, -3579, -5075, -8072, -5520, -11035, -4064, -5974, -7418, -4383, -9173, -5413, -7400, -6295, -4422, -7142, -6321, -8876, -5980, -5285, -6607, -6100, -9986, -6726, -6866, -7026, -5898, -9719, -9170, -9123, -7579, -6793, -8407, -14646, -18011, -8116, -10370, -8259, -10472, -8183, -8928, -11228, -11437, -10430, -5390, -8883, -8491, -7834, -9696, -4587, -7441, -8322, -4980, -7794, -5017, -6123, -8598, -4332, -6821, -6314, -5720, -8598, -4967, -5271, -8158, -6420, -8336, -6520, -3875, -5633, 5939, 7498, 3816, -4110, -683, 4949, 6931, 3325, -2868, 505, 1173, 5324, 1999, -103, -833, 276, 3248, -27, 688, -4897, 2082, 1688, -1912, -381, -3131, 840, -120, -967, -2153, -1680, 262, -8665, -1243, -4695, -1078, 2055, 581, -249, -3880, -118, 2793, 3291, 1934, -1310, 732, 2875, 4391, 2177, -864, 1025, 2300, 4922, -22, 1560, 741, 209, 5020, 664, 3346, 174, -5471, 4348, 3231, 3735, -310, 664, 2497, 3428, 3167, -723, 2976, -596, 1225, 2238, -952, 3683, -853, -10966, 1769, -404, 3105, 129, 580, 2038, 690, 982, 575, 1900, 2110, 1487, -2467, 895, 1792, 1323, 1460, -1122, 695, 1478, -612, 98, -272, -430, 1702, -4604, -3266, -769, -1265, 2188, -9726, -3476, -2752, -435, 2395, -4439, -2936, -3515, -479, 2059, -3641, -4340, -1159, -2214, 1049, -3233, -5523, -933, -5408, -557, -1956, -6331, -3005, -3736, -2091, -1428, -5164, -7148, -1484, -2616, -2569, -6325, -3510, -129, -2039, -5926, -8524, -1105, 286, -1427, -4879, -3383, 539, -554, -1496, -3624, -1878, 1532, -3859, -1822, -4389, -1500, 1812, -6993, -1536, -6968, -1613, 1247, -2806, -1111, -12036, -2403, -315, -3363, -1365, -10198, -5101, -3183, -6179, -2557, -4521, -3642, -10706, -2277, -4067, -1316, -846, -6087, -392, -4254, 2, -513, -3761, -8, -2085, -262, -2486, -3954, -700, 279, -1985, -7065, -7600, -2532, 1410, -3414, -3956, -5137, -6374, 1188, -3260, -3883, -1687, -7568, -775, -4153, -3148, -403, -4011, -7901, -6251, -1121, 12, -2929, -3366, -9076, -538, -175, -3405, -1694, -10890, -1364, -1269, -5414, -2133, -11695, -3369, -3862, -4455, -3469, -13321, -5873, -5912, -2569, -4727, -12900, -7660, -4463, -2150, -5530, -10061, -6325, -4875, -2331, -6140, -8754, -5603, -6225, -2366, -6844, -9310, -7169, -6174, -2398, -8265, -8591, -9419, -5748, -2759, -11208, -6633, -8630, -4414, -3587, -6956, -6090, -11112, -3346, -4689, -5276, -6994, -12638, -3257, -5399, -6281, -8506, -7850, -3844, -4581, -12244, -8998, -5467, -4606, -3000, -7437, -11024, -3982, -5235, -2214, -5741, -14559, -3415, -5922, -2329, -5662, -8330, -3771, -7270, -2936, -5776, -6914, -5191, -9555, -3375, -5683, -7191, -8282, -11319, -2918, -5387, -8629, -11193, -14322, -1951, -4908, -10776, -7617, -10083, -1392, -4472, -11289, -6296, -7170, -1536, -4382, -8472, -6262, -6463, -2432, -4708, -6520, -7024, -7264, -4142, -5191, -5795, -7500, -9399, -6018, -5687, -6166, -6950, -11079, -5344, -6695, -7335, -6520, -9568, -4151, -9366, -7915, -6668, -7892, -3664, -11859, -7509, -7343, -6626, -3604, -8203, -7554, -8792, -5775, -3673, -7738, -8497, -8781, -5335, -3895, -10352, -12172, -6126, -5371, -4573, -10832, -11214, -4691, -5896, -6076, -7233, -7274, -4370, -6438, -8981, -6794, -6313, -4781, -6075, -13189, -8392, -6425, -2794, -5014, 2094, 4062, 775, 920, -1146, 2417, 2589, 4936, 3051, 1403, 3034, -10342, 6765, 3262, 2457, 3411, 2193, 6895, 1430, 2447, 3277, 3251, 5772, -1085, 1645, 2595, 1631, 3600, 407, 163, 1554, 580, 1491, 38, -2249, 561, 2839, 709, 1250, -4808, -409, 3087, 963, 3247, -3035, -3537, 1405, 2691, 3955, 288, -2711, 1159, 3357, 3626, 2891, 2046, 2533, 2067, 2343, 4115, 3543, 1477, 434, -88, 3895, 3370, -3691, 2722, -1088, 1912, 1934, 1207, 3667, 520, -1062, 770, 2300, 4338, 568, 928, 733, 877, 5272, -1201, 1467, -155, -3759, 5542, -4377, 614, -2033, -7205, 4832, -1541, -509, -3463, -4153, 3246, 619, -614, -4077, -3923, 1866, 1284, 58, -3159, -5763, 2323, 970, 376, -1191, -9738, 2746, 571, -167, 163, -2991, 2090, 518, -1675, 606, -1285, -9, -5, -3919, -66, -1182, -4671, -1455, -6022, -2343, -1636, -6281, -3871, -8176, -6628, -825, -2241, -6933, -6604, -3550, 737, -1412, -7588, -3941, -1937, 1675, -2996, -5979, -3184, -1677, 1721, -5206, -4511, -3779, -2436, 861, -2233, -3094, -4685, -4646, -1042, -1167, -1844, -4323, -12324, -5943, -1999, -1198, -3691, -5630, -4199, -7219, -1373, -3991, -2125, -623, -4238, -1845, -4512, 48, 499, -2786, -1957, -3037, 1229, 646, -6367, -2558, -2054, 1263, 280, -2470, -2945, -2372, -233, -556, -172, -2081, -3973, -2944, -1700, -275, -2455, -10596, -1288, -1024, -2207, -5302, -4313, -725, 450, -5139, -15950, -1506, -2403, 849, -4575, -11619, -1381, -5521, 241, -3617, -10848, -3952, -4205, -629, -2762, -9008, -10166, -4152, -1251, -2646, -13814, -3670, -7243, -2545, -4078, -6141, -2909, -7624, -5308, -7177, -4140, -3531, -3071, -7346, -6519, -4223, -4333, -1660, -7726, -5860, -5727, -4502, -1749, -7183, -6056, -7503, -4412, -3281, -4656, -5271, -6772, -4827, -7504, -3650, -3645, -5648, -5674, -9299, -3597, -2461, -5263, -5178, -6334, -3368, -2197, -5509, -3935, -7568, -2920, -2855, -6093, -3293, -11061, -3300, -3975, -6699, -3216, -6724, -5529, -4297, -7015, -3670, -5820, -8424, -3813, -6821, -5098, -6949, -4491, -3662, -6529, -8867, -9136, -3331, -4482, -6795, -12447, -9999, -3576, -6464, -8371, -8162, -10053, -4297, -6243, -11225, -7268, -8150, -4944, -5010, -7377, -7233, -6136, -5842, -5271, -5335, -8012, -5435, -6803, -6653, -4850, -9710, -6171, -6797, -8058, -5448, -11619, -7080, -5864, -8252, -6766, -11448, -5552, -5293, -7839, -8005, -9893, -4396, -5711, -7421, -8020, -8635, -4153, -7208, -6681, -7290, -7992, -4352, -8804, -5837, -7035, -7624, -4365, -8369, -5335, -7635, -7078, -3812, -8074, -5399, -9177, -6562, -2998, -8894, -6445, -13334, -6483, -2447, -9350, -9490, -11962, -6895, -2528, -7762, -14601, -8024, -7449, -3536, -6936, -11336, -7346, -8039, -5960, -7576, -12136, -9686, -7937, -8472, -9287, -3496, -7503, -8433, -8897, -10383, -4426, -5678, -6649, -7783, -6855, -7695, -4832, -4747, -6722, -5148, -7399, -4425, -3662, -6695, -4683, -4367, -4128, -3404, -7448, -5218, -3807, -3883, -3796, -8240, -6667, -4906, -3967, -4597, -8482, -9104, -7851, -4858, -5533, -8476, -10049, -10036, -6751, -6587, -8181, -7837, -7628, -6463, -8581, -7612, -7054, -7060, -4725, -11410, -7441, -7732, -8435, -4225, -7490, -8598, -9807, -9328, -5025, -5693, -12061, -14319, -6423, -7758, -5131, -9252, -16790, -5234, -17193, -4865, -7176, -12803, -5477, -7934, -4707, -6494, -11724, -6881, -6387, -5316, -6151, -11360, -9805, -6221, -7437, -5109, -10351, -13271, -7217, -9062, -3882, -9080, -7205, -10676, -7973, -3569, -9486, -5212, -11092, -9780, -4564, -12814, -4973, -8225, -13128, -7084, -12401, -6159, -7772, -7994, -9596, -10001, -8795, -7764, -6861, -9734, -8743, -13018, -8587, -6936, -10458, -7666, -16832, -13248, -7464, -11157, -6865, -13350, -8835, -8364, -12259, -6464, -10412, -6063, -9754, -10762, -6847, -8698, -5100, -11149, -9803, -8488, -7883, -4924, -10474, -11642, -13066, -7668, -5416, -8495, -11305, -13263, -8182, -6834, -8020, -8702, -9646, -9635, -7661, -9712, -8259, -8472, -10820, -6223, -12439, -8311, -7929, -10802, -5712, -8917, -8296, -8237, -10867, -6521, -6645, -9213, -9927, -9922, -7500, -5195, -10675, -10293, -8680, -6508, -4594, -9877, -8656, -7971, -5540, -4911, -7628, -8495, -7962, -5331, -6144, -6128, -9506, -8988, -5546, -8410, -5828, -10408, -12057, -5777, -11265, -6702, -9785, -14430, -5836, -8674, -8660, -8797, -10904, -5568, -6489, -10644, -8964, -10424, -4712, -5601, -9813, -11439, -11621, -3802, -5747, -8579, -11469, -11915, -3544, -6736, -8169, -8615, -9917, -4222, -7571, -8891, -7903, -9164, -5899, -7390, -11613, -8061, -9634, -7748, -7776, -12381, -8261, -10773, -7733, -10101, -9310, -8382, -11118, -7290, -13743, -8720, -8758, -9523, -7255, -9444, -9833, -9839, -8479, -7638, -8215, -11816, -11469, -8316, -8413, -8325, -11585, -11035, -8254, -8751, -9150, -11193, -9967, -8321, -8034, -10605, -11760, -9553, -9412, -7233, -14406, -11946, -9279, -11210, -6727, -12462, -12255, -8889, -10244, -6605, -8051, -15851, -8480, -9993, -7124, -6429, -14108, -8135, -12885, -8908, -6275, -11362, -7831, -14963, -12904, -7163, -12241, -7476, -10451, -9523, -8431, -23659, -7144, -9732, -8050, -9233, -10722, -6999, -10200, -8585, -9996, -8487, -7020, -11260, -9236, -11182, -8138, -7204, -13736, -8276, -10763, -9119, -7783, -18582, -7917, -9568, -11103, -9010, -14757, -8302, -9259, -14129, -10997, -14171, -8989, -9768, -14633, -13936, -12129, -11061, -10782, -10645, -20938, -10071, -19054, -11648, -9323, -16545, -9286, -10579, -11734, -9386, -14180, -9455, -9479, -11729, -10118, -13190, -10268, -10695, -11622, -11141, -12357, -11626, -14135, -9898, -12644, -12714, -13309, -18135, -8553, -14126, -16128, -13935, -11560, -8260, -13613, -15183, -13687, -5460, -5452, -11196, -9790, -6817, -6056, -5513, -9729, -8527, -7462, -6792, -6547, -8323, -8116, -7521, -7897, -8488, -7397, -7994, -6971, -9023, -9701, -7447, -8062, -7417, -9471, -8606, -8319, -8659, -8879, -9053, -7016, -9132, -9522, -9267, -8717, -5973, -9771, -9712, -8848, -8000, -5820, -10974, -9332, -8454, -7183, -6355, -9140, -9043, -8340, -7705, -7043, -6816, -7799, -9236, -11026, -8276, -5938, -6492, -11037, -13919, -12229, -6516, -6059, -12418, -10092, -11244, -9211, -6435, -12527, -10279, -8786, -16235, -7044, -12617, -10954, -8149, -9443, -7371, -12099, -10423, -6895, -7777, -8077, -10603, -10177, -5797, -6952, -9957, -11431, -8600, -5629, -6369, -10092, -13096, -6683, -6349, -5890, -7907, -8525, -5796, -7962, -5661, -7485, -7186, -5890, -10650, -5852, -9032, -7611, -6651, -9081, -6749, -12763, -8409, -7470, -7463, -9612, -12106, -7683, -7599, -8078, -13115, -12183, -6457, -7475, -9603, -7910, -17086, -5794, -8052, -7818, -7213, -14571, -6190, -9540, -7204, -8812, -11549, -7308, -10768, -8684, -14668, -10139, -7048, -10197, -12322, -13194, -9157, -6602, -9200, -12084, -10056, -8285, -7252, -8627, -12810, -7922, -7328, -8022, -8385, -11429, -6773, -6689, -7771, -8045, -8789, -7003, -6466, -7631, -7573, -8432, -8996, -6556, -8270, -7469, -10263, -11910, -7045, -9701, -8035, -15432, -10726, -7968, -9492, -8998, -12569, -11408, -8956, -7808, -9465, -9476, -11573, -9228, -7152, -8629, -7377, -9487, -8537, -7727, -7552, -6347, -7904, -7637, -10031, -7612, -6232, -6806, -7240, -15664, -9616, -6842, -6692, -7670, -9481, -10893, -8064, -7899, -9089, -7650, -7844, -10338, -9958, -11632, -7788, -6743, -15399, -9672, -14526, -9735, -6879, -9602, -9141, -14182, -9734, -7913, -7734, -9744, -13034, -7855, -10075, -7958, -10335, -12388, -7859, -12946, -10337, -9381, -12022, -9788, -8896, -15956, -8627, -11608, -12881, -7129, -11091, -9218, -11313, -10909, -7331, -9856, -12378, -10599, -9289, -8453, -10636, -14063, -9657, -8366, -7316, -14168, -9587, -9603, -7885, -6435, -12406, -8310, -10827, -7918, -6999, -9890, -8193, -13505, -8799, -8627, -9652, -8718, -16357, -10594, -10108, -11474, -9647, -11601, -9607, -9776, -16771, -10976, -8973, -7534, -8982, -12427, -12469, -7884, -6626, -9249, -10560, -12453, -7916, -6818, -11029, -9956, -11459, -8787, -8394, -14866, -10541, -11158, -10044, -12984, -16609, -13795, -11623, -11747, -11577, -15079, -15484, -11876, -18280, -9348, -13700, -10976, -11500, -12031, -9298, -12239, -9985, -10336, -9195, -9849, -11672, -10390, -9080, -8701, -9727, -10923, -11246, -8823, -9799, -8697, -8961, -9886, -9284, -12383, -7919, -7485, -7816, -9307, -15202, -8285, -6939, -6696, -9471, -12960, -10168, -7129, -6570, -10868, -10858, -11686, -7784, -7360, -12979, -9968, -10203, -8744, -8974, -13473, -9813, -9332, -10319, -11144, -14184, -10010, -8908, -14214, -12825, -16374, -10464, -8726, -12654, -12828, -21747, -11321, -8842, -9372, -12247, -13544, -12614, -9218, -9057, -9536, -11694, -10012, -10812, -9707, -14010, -13820, -12716, -10251, -6857, -14040, -13994, -9343, -12918, -5936, -9919, -10056, -7413, -13393, -6025, -8555, -6813, -6237, -9227, -5917, -9202, -5305, -5587, -7527, -5636, -14629, -4851, -5726, -6898, -6312, -9374, -5153, -6618, -7181, -8660, -6488, -5724, -7500, -8430, -12088, -5575, -6115, -7335, -8971, -12970, -5820, -6878, -5845, -7404, -11189, -7265, -9106, -4676, -6434, -8058, -11195, -11526, -4566, -6239, -6886, -12075, -9203, -5535, -6462, -6907, -8017, -8769, -7501, -6576, -7458, -6817, -9307, -10182, -6217, -8087, -7065, -9381, -14000, -5790, -9111, -7695, -9273, -14013, -5530, -9469, -6265, -7964, -8628, -5245, -7611, -5366, -6227, -6624, -4801, -6887, -6173, -5867, -6126, -4380, -8080, -8235, -7523, -6694, -4270, -12832, -8111, -10652, -7851, -4643, -11482, -8314, -8778, -9029, -5509, -8708, -8613, -9667, -9666, -6783, -7574, -6763, -15752, -8621, -8420, -6630, -5875, -10426, -7571, -11014, -5964, -6041, -8652, -7110, -16756, -6136, -6739, -7334, -7024, -8682, -7497, -7024, -6649, -7826, -6229, -9272, -6467, -6947, -10813, -5450, -9178, -6030, -7863, -13031, -5848, -9559, -6195, -8376, -10567, -7039, -11033, -7016, -8152, -13587, -8136, -12396, -8158, -7953, -11075, -9305, -14775, -8235, -8296, -6976, -9759, -12712, -8007, -9244, -5595, -7951, -10772, -9307, -8603, -5583, -7666, -10898, -11411, -6726, -6690, -9241, -12558, -9605, -5889, -8239, -9273, -16695, -9047, -6261, -8320, -8281, -12356, -8355, -7796, -8204, -9367, -9069, -6581, -10290, -9000, -12092, -7293, -5492, -12402, -10646, -11428, -6309, -5349, -13143, -13503, -11224, -5961, -5992, -12181, -11390, -11425, -6118, -6902, -10596, -9237, -9379, -6499, -6978, -10052, -9085, -7620, -6983, -6004, -9964, -10892, -6877, -7917, -4814, -9631, -13976, -6852, -9618, -4085, -10410, -10403, -7118, -11857, -4145, -16169, -9094, -7372, -14266, -5161, -10884, -9700, -7793, -11879, -7035, -8524, -12626, -8692, -9682, -7916, -8797, -15806, -9044, -8925, -7578, -11683, -11961, -8553, -8639, -8371, -13669, -11163, -8835, -8225, -10796, -11336, -10129, -9206, -7826, -11944, -11962, -8899, -9312, -7680, -11506, -13009, -8766, -11443, -7934, -14209, -11887, -9428, -15040, -8677, -16195, -10058, -9453, -9580, -9204, -11942, -8270, -9110, -7994, -8292, -11405, -7274, -9576, -7425, -7484, -11145, -7187, -10667, -7253, -7809, -10004, -7976, -10382, -7373, -9628, -9389, -9718, -9708, -8018, -13756, -9756, -13145, -10434, -10148, -25925, -11243, -16287, -13292, -19021, -16248, -14065, -11228, -23071, -9222, -13028, -12224, -9445, -14471, -7451, -13009, -9687, -8828, -11633, -7669, -19763, -8689, -8807, -10563, -9429, -13228, -8834, -9196, -10590, -11230, -10881, -9994, -9838, -10660, -10238, -10778, -11866, -10049, -10486, -9334, -11957, -12076, -9901, -10670, -9106, -15188, -10807, -10374, -11336, -9513, -16229, -10619, -11442, -12249, -10440, -12259, -12338, -11888, -11873, -11920, -8255, 8218, 8518, 4703, 137, -5140, 7753, 8166, 5106, 540, -3250, 6287, 7108, 5555, 791, -1631, 3470, 5348, 5428, 570, 1156, -2180, 2995, 4792, 899, 3233, -668, 588, 3980, 1142, 3964, 991, -1786, 3029, -304, 3094, 702, -8279, 1340, -3512, -478, -1112, -2044, -2134, 1037, -733, -2611, 604, -2068, 3033, 1683, -1222, 1844, 96, 3771, 1510, 67, 2656, 175, 4017, 111, 1671, 3035, -950, 3948, -1754, 2724, 2612, -511, 3152, -2003, 2721, 832, 1060, 745, -727, 1420, -4550, 1752, -1065, -971, -2190, -886, 1588, 2265, -2517, -4913, 1840, 1015, 3345, -3708, -1224, 2726, 1227, 2817, -8670, -906, 2485, 2340, 982, -2849, -1446, 1054, 3226, 62, 537, -684, -2201, 3490, -115, 1737, -56, -7898, 3096, -4738, 1778, -982, -6826, 2077, -1031, 828, -3160, -10160, 152, 2222, -1483, -1212, -4060, -4423, 3118, -5594, 248, -2787, -2026, 2878, -3903, 324, -3570, 406, 1755, -1324, -124, -2496, 719, -230, -71, 80, -720, 417, -1210, -232, 469, -854, 1272, 220, -1195, 159, -4591, 2291, 1101, -1698, -765, -3671, 2406, 1309, -821, -1862, -197, 1487, 1173, 791, -3180, 112, -262, 591, 1361, -5797, -1610, -1179, -998, 493, -6925, -5420, -742, -4666, -1194, -1936, -3467, -1125, -7554, -890, 178, -2146, -2983, -3930, -629, 876, -2217, -5998, -2068, -2152, 306, -2729, -7022, -1218, -7188, -2206, -3760, -5448, -1174, -7687, -10954, -4143, -3419, -1516, -5093, -3138, -2143, -1985, -2057, -4052, -2775, -1117, -1170, -2641, -2138, -5550, -995, -1224, -2670, -735, -9578, -567, -2007, -2219, -342, -7692, 524, -3086, -1683, -948, -7077, 1296, -5370, -1194, -2221, -3256, 1257, -4950, -1069, -3383, -1472, 233, -1693, -1771, -4892, -1180, -1980, -419, -3866, -6621, -2138, -5474, -156, -6157, -4795, -4213, -5127, -339, -4524, -3590, -6570, -3194, -780, -4325, -3557, -8074, -2608, -1703, -5544, -4800, -8634, -3328, -3206, -6749, -7973, -8729, -5125, -3443, -7786, -7871, -10310, -6026, -2155, -10906, -7845, -13434, -5541, -1414, -10743, -15660, -9978, -4354, -1374, -6485, -6403, -8967, -2751, -1939, -3752, -4951, -9769, -1632, -2963, -1807, -5986, -10566, -1131, -3689, -669, -9595, -13136, -1276, -3427, -415, -12170, -10248, -2242, -3000, -1194, -7320, -5671, -4156, -2917, -3317, -4703, -3638, -4702, -3214, -6274, -3608, -2845, -3237, -3756, -5799, -3894, -3093, -2684, -4211, -6050, -5378, -4583, -3074, -4323, -7715, -6447, -7930, -4186, -4257, -7771, -5940, -12505, -5731, -4563, -6867, -5028, -13601, -5859, -5985, -5732, -4149, -8554, -4586, -10478, -4734, -3890, -6391, -4026, -10602, -4790, -4268, -6069, -4167, -7309, -6658, -5053, -6613, -4131, -6262, -15018, -6338, -8256, -3866, -5088, -7044, -8316, -12071, -4221, -4230, -5000, 5922, 2877, -2652, 7225, -1942, 5515, 2353, 3865, 6686, 1766, 4165, 730, 5510, 4940, 3051, 1358, 904, 5010, 2671, 2092, -5564, 2646, 2289, 3628, -1862, -4151, 2909, 607, 4154, -5251, -1857, 1644, 3858, 3041, -1910, 10, -602, 4972, 1045, -3599, 1195, 605, 4873, 810, -9585, 1429, 2420, 3718, -155, -2336, 1055, 3117, 1407, -5780, -222, 808, 2803, 890, -817, 1013, 1218, 2085, 3289, 1366, 1234, 2027, 2761, 4672, 1799, 198, 3034, 3583, 5051, 1359, -1866, 4040, 3129, 4518, 319, -2769, 4706, 813, 3008, -854, -1545, 4699, -3603, 235, -113, -1184, 3630, -1158, -2969, 2063, -2284, 709, -774, -662, 3467, -4019, -992, -2120, 629, 3772, -6185, 1582, -4819, 128, 3272, -7246, 1865, -11520, -1190, 3004, -2061, 812, -2624, 278, 2945, -906, -60, -184, 1228, 1770, -859, 174, 294, 611, -203, 858, 249, -1086, -1130, 369, 2022, 241, -1940, -1573, 174, 1316, 853, 929, -1203, -2489, -2748, 1830, 2295, -2578, -11287, -3262, 2455, 2604, -3068, -6488, -1289, 2326, 2428, -89, -5309, -4264, 1290, 1918, 846, -5271, -4314, -320, 742, -190, -8586, -2029, -1024, -1542, -4638, -9557, -2594, -476, -4319, -4176, -6330, -1582, 565, -4829, -1713, -7113, 14, 1462, -5858, -2051, -10818, 631, 1639, -10144, -3800, -2388, 300, 683, -5406, -5103, 539, -1099, -2281, -2988, -3971, 1757, -3044, -12130, -3151, -2522, 1792, -3792, -3819, -4758, -1578, 714, -4145, -3659, -3347, -1303, -1851, -4225, -5126, -1984, -1914, -7118, -4073, -6039, -1921, -3745, -4571, -3449, -5360, -3066, -4057, -3408, -2754, -3995, -5962, -2056, -3713, -2999, -3494, -8482, -1508, -4204, -3874, -4233, -7004, -2412, -4300, -3411, -6686, -7724, -5074, -4663, -2566, -11435, -8951, -9769, -6523, -2522, -4694, -8805, -5417, -11164, -3203, -2571, -9365, -3728, -7995, -4366, -2390, -9768, -3197, -6963, -5469, -3829, -5474, -3229, -6954, -5628, -4607, -3508, -4104, -6926, -5201, -3017, -3258, -6781, -6688, -5292, -1676, -4259, -8702, -5994, -6273, -442, -6137, -8217, -5305, -7539, 275, -8081, -8464, -5335, -7354, 147, -8731, -3499, -5803, -6249, -888, -7789, -2032, -5607, -5626, -2776, -5259, -2924, -6184, -5689, -5352, -4394, -5429, -9887, -5982, -8624, -5787, -2827, -11662, -5790, -12709, -12312, -1539, -7007, -5155, -13300, -9568, -1918, -4272, -4926, -10232, -7642, -3585, -2757, -5668, -7063, -6153, -6748, -2676, -6399, -5254, -5138, -17375, -4308, -5488, -4550, -5500, -8419, -9177, -5281, -4523, -7549, -5931, -6620, -6823, -4509, -7848, -5396, -5237, -11409, -4001, -5616, -6506, -6804, -9460, -3360, -5102, -6861, -10260, -7357, -3247, -6051, -4702, -6499, -6841, -4070, -8027, -3936, -5306, -6850, -6079, -8982, -4609, -5490, -7067, -9131, -7701, -6456, -6575, -7263, 7862, 3577, -3578, 6519, 8233, 7387, 3047, -265, 6189, 8002, 5799, 1670, 1362, 5358, 7334, 2052, 840, 1291, 4485, 6244, -1155, 1285, -128, 3838, 4508, 3300, 1833, -1630, 2803, 2706, 4122, 2146, -633, 1071, 4250, 3709, 1664, 733, 1908, 5011, 3086, 48, 1542, 2952, 3427, 2686, -1076, 1275, 2652, -882, 1801, -599, -870, 1956, 3469, -227, -932, -10134, 1353, 4678, -4543, -2031, 84, 400, 4984, -3068, -3364, 2172, 945, 5524, 86, -5368, 2475, 1878, 5646, 1514, -4784, 1380, 1394, 5202, 1857, -1441, -806, -1002, 4984, 1045, 477, -635, -4379, 4954, -1648, 1641, 644, -2797, 4288, -3253, 2644, 972, -1322, 3020, 397, 3596, 687, -101, 2814, 1834, 4182, 349, 33, 3996, 2236, 4101, 852, -964, 4939, 1990, 3145, 1720, -2451, 5058, 1103, 1231, 1760, -3097, 3923, -603, -635, 322, -2722, 262, -3038, -1189, -4472, -2620, -1060, -2899, -2015, -3919, -3436, 2012, -984, -1798, -597, -2320, 1947, 383, -902, 216, 171, 124, 1242, -747, -309, 1428, -2713, 1657, -1183, -2483, 1433, -3601, 1756, -1977, -7766, 72, -2811, 1657, -2306, -10583, -3253, -2841, 1340, -2238, -6886, -4297, -3968, 519, -1825, -2592, -2136, -5200, -1223, -213, -715, -1543, -4770, -2527, 325, 291, -1608, -3019, -1503, -1502, 1062, -2140, -1168, -526, -6645, 1322, -3678, -154, -132, -1217, 627, -7430, -550, -1186, -480, -1285, -4158, -3529, -5876, -1895, -3438, -2063, -7058, -5493, -3733, -3336, -2027, -2192, -3358, -3342, -3693, -3797, -2182, -4358, -3690, -4396, -7597, -4956, -6387, -3553, -4124, -8527, -3015, -6323, -2577, -4534, -6396, -614, -4495, -3322, -6881, -3609, -8, -3697, -7313, -9857, -2506, -696, -4470, -5693, -9221, -3224, -2436, -6633, -4554, -7967, -5896, -3135, -4783, -6263, -6039, -5094, -2310, -2602, -6682, -6548, -3167, -2169, -1943, -6395, -13476, -2639, -2628, -2692, -6610, -7486, -2796, -3263, -5452, -3570, -5008, -3103, -4128, -14413, -2148, -4189, -2920, -5986, -6298, -2296, -3889, -2034, -9934, -5030, -3815, -3879, -1032, -9400, -5194, -6892, -3773, -352, -10041, -6318, -11567, -3246, -68, -11535, -8678, -11611, -2635, -19, -9312, -9926, -10994, -2358, -75, -16555, -8034, -10548, -2571, -458, -5942, -7471, -10320, -3233, -1499, -3288, -7675, -10172, -3883, -3313, -2820, -7216, -10202, -3874, -5729, -3540, -5958, -9375, -3945, -8679, -3976, -4982, -6867, -4869, -14072, -4032, -4766, -5660, -6485, -12797, -5370, -5521, -6325, -7500, -10770, -7950, -7705, -9406, -7495, -9962, -5439, -14339, -7057, -8173, -7902, -3887, -8710, -4512, -9782, -6912, -3828, -6140, -3589, -7110, -7707, -5054, -5275, -3751, -5350, -11512, -8205, -5413, -4861, -5301, -10081, -12683, -6424, -6305, -6681, -6900, -8432, -8580, -7125, -8259, -5725, -8012, -8535, -8108, -5274, -4485, -4669, -8641, -6926, -6248, -6259, -5340, -11387, -7950, -6505, -7441, -6765, -6574, -10861, -6476, -5437, -8423, -4254, -15479, -7169, -4629, -8620, -3606, -12207, -9201, -5047, -7602, -3747, -8709, -11083, -6616, -6982, -3893, -6456, -10302, -9628, -7076, -3962, -5050, -8471, -12842, -7508, -4693, -4689, -7345, -11734, -6814, -6884, -5827, -7439, -11003, -5609, -12702, -10190, -7761, -10101, -5059, -13157, -9423, -6792, -8744, -5142, -9739, -6426, -5961, -7578, -5798, -7210, -5659, -6137, -6867, -7190, -5969, -5808, -7719, -6570, -8674, -6533, -6466, -11384, -6787, -10674, -10207, -6446, -6049, -8001, -9156, -4805, -4379, -2756, -6357, -4016, -2200, -2543, -1038, -3515, -1868, -1601, -1907, -492, -2414, -1319, -2497, -2527, -1066, -2857, -2123, -4310, -4353, -2907, -4978, -4412, -4906, -5775, -6566, -9626, -8518, -5234, -5106, -10306, -12933, -10710, -6888, -5272, -8755, -11421, -11443, -8847, -6832, -9574, -10006, -14369, -8444, -8294, -12115, -10349, -17059, -8218, -6559, -12109, -12793, -14743, -8958, -5232, -10175, -11258, -13735, -8599, -5377, -8724, -9164, -15455, -7532, -7007, -8339, -8083, -13265, -7816, -9196, -8268, -7815, -11564, -9832, -9775, -6952, -7926, -13187, -13063, -10765, -5906, -7782, -15584, -12379, -10490, -6108, -8448, -12091, -9122, -7745, -7751, -11906, -13267, -7103, -6600, -10677, -10751, -17622, -6265, -7042, -12941, -9065, -14011, -6049, -8883, -9876, -10813, -20246, -5982, -9756, -7965, -14369, -10195, -5954, -8426, -8195, -13464, -7762, -6066, -7427, -10571, -16908, -7728, -6619, -6541, -17431, -10379, -10433, -8506, -5986, -12697, -9069, -11079, -12715, -6155, -8603, -9403, -7391, -8120, -7531, -6590, -9741, -6131, -6525, -10710, -5535, -10606, -5838, -6682, -8170, -4985, -13638, -6081, -7904, -6235, -4881, -13114, -6427, -9614, -6178, -5447, -11671, -6425, -10083, -7648, -6948, -11728, -6684, -8257, -10462, -9234, -10779, -8225, -6923, -12661, -10619, -9710, -13744, -6671, -16022, -11446, -9270, -10943, -7321, -12995, -13079, -9065, -8320, -8063, -9957, -11276, -9036, -7934, -8312, -9468, -8819, -9467, -8590, -8967, -10645, -7828, -10501, -9496, -10112, -11590, -8063, -11299, -8770, -10139, -10255, -8887, -10595, -7676, -9236, -9306, -8792, -9146, -7960, -8973, -8622, -8151, -7974, -10602, -10019, -8011, -7899, -7927, -14595, -12994, -7918, -8135, -9534, -10919, -13005, -8829, -9017, -14014, -12278, -11690, -11613, -9955, -15600, -15036, -12645, -19515, -9337, -14409, -10368, -12627, -13603, -8850, -15890, -9811, -10021, -14068, -9407, -16778, -11374, -8387, -13052, -10373, -14304, -14554, -8023, -11012, -10984, -11336, -16887, -9066, -10720, -12363, -9353, -14030, -11340, -11317, -15637, -8510, -12135, -12642, -11503, -16126, -8884, -12226, -13096, -11769, -12705, -10963, -14302, -13279, -13499, -9957, -19172, -16625, -12660, -15562, -8688, -13533, -15111, -11206, -13165, -8805, -11767, -13777, -10342, -11808, -10262, -11397, -12807, -10458, -6477, -8783, -9156, -7244, -9578, -6328, -9733, -13536, -7400, -7805, -7936, -9056, -8489, -8789, -6259, -11497, -8573, -7079, -7972, -5792, -7806, -8781, -7542, -4974, -6663, -6561, -8910, -10156, -3840, -9021, -7269, -8634, -12588, -4296, -11760, -9368, -8887, -8988, -6455, -9678, -11606, -9632, -8275, -8061, -6691, -10323, -9533, -9416, -6173, -4993, -7891, -9118, -12433, -5687, -4293, -6883, -9419, -16123, -6407, -4190, -7167, -9529, -14934, -8109, -4288, -8700, -7897, -9795, -12745, -4326, -12059, -6700, -7222, -10335, -4404, -16733, -6277, -6233, -6387, -5099, -11768, -5417, -6268, -5291, -8062, -6109, -3571, -5826, -6571, -8834, -2852, -1710, -3620, -8090, -3887, -1178, -580, -1986, -3856, -2366, -779, -430, -1643, -2432, -2403, -1609, -1343, -2671, -2818, -3680, -3795, -3377, -4520, -4806, -5870, -7664, -6535, -4420, -8343, -7916, -15536, -10653, -4084, -12695, -9889, -11828, -13098, -5003, -9736, -11340, -8721, -12170, -7176, -7383, -8885, -7056, -10148, -10846, -7232, -7236, -6012, -8370, -17930, -8908, -6677, -6057, -7995, -20861, -13738, -7012, -7767, -9371, -11406, -14260, -7883, -13412, -16421, -7421, -10815, -8644, -11246, -10137, -5665, -9564, -9488, -9443, -7578, -5485, -9463, -9239, -9567, -7295, -6693, -9922, -7080, -9377, -8432, -8617, -7936, -5892, -8845, -9031, -9569, -6097, -6073, -8837, -8300, -9826, -5514, -7909, -9189, -8287, -8081, -5938, -13439, -9856, -8392, -6871, -6969, -11578, -10508, -7797, -7008, -8090, -9814, -9997, -7225, -8278, -9567, -10223, -9397, -7195, -10334, -11868, -10981, -8329, -7907, -12488, -10352, -11151, -6826, -9507, -13503, -9198, -11249, -6094, -11238, -11431, -9771, -11613, -6580, -9476, -9627, -10380, -12747, -9020, -7275, -8856, -10247, -13736, -16003, -6086, -8414, -11570, -11831, -8566, -5962, -8008, -16748, -11574, -7193, -7054, -8048, -14475, -13484, -7650, -9263, -8539, -11817, -12244, -8730, -9245, -8822, -10515, -10283, -8339, -8075, -8612, -9537, -8883, -7938, -7841, -8409, -8677, -7755, -8264, -8050, -8787, -7793, -7192, -8081, -8359, -10367, -7308, -6991, -7332, -8931, -14232, -8007, -6797, -7132, -9800, -13835, -11501, -6596, -7893, -9831, -11601, -12887, -6679, -9853, -9139, -11078, -8894, -7338, -11703, -8684, -11386, -8556, -8925, -10719, -8095, -12223, -9890, -12600, -10678, -7601, -13352, -10997, -14219, -12580, -7914, -14900, -10834, -10587, -17160, -9606, -17509, -11831, -9792, -14535, -14620, -15935, -13545, -10180, -13387, -14109, -12626, -11733, -11259, -12852, -11649, -10359, -9112, -13805, -10874, -12114, -8940, -7478, -11162, -8905, -13014, -8389, -7070, -8300, -7873, -12301, -8759, -7897, -7516, -7945, -11441, -9479, -9758, -8260, -9257, -10055, -8912, -11370, -10436, -12243, -9002, -8078, -11958, -13352, -17471, -8733, -8008, -12959, -11729, -16054, -8775, -8649, -14557, -9828, -16015, -8934, -9793, -14432, -9459, -15591, -9838, -11052, -12957, -10547, -15496, -12015, -11458, -12524, -12694, -8230, -7691, -5468, -9481, -8670, -9001, -7408, -5868, -8990, -6591, -9581, -7771, -6956, -7195, -6580, -10393, -7327, -8931, -6473, -7471, -7970, -5549, -11685, -6128, -7159, -7631, -4150, -11748, -5513, -7929, -9741, -3795, -10485, -4303, -17918, -8069, -4614, -8971, -3127, -7586, -6064, -6814, -7951, -2698, -5489, -5580, -10569, -7771, -3189, -5469, -5785, -11898, -7226, -4466, -6865, -6114, -10132, -6694, -6073, -9733, -6129, -6873, -7455, -7364, -13436, -5859, -5163, -9935, -8014, -13410, -5672, -4931, -11197, -8088, -11952, -5759, -5908, -8516, -8227, -10857, -6700, -7381, -6294, -7948, -7578, -7593, -6226, -4093, -5630, -4017, -4501, -4020, -2154, -3361, -1993, -2598, -2742, -1072, -1949, -1330, -2120, -2586, -1063, -1517, -1931, -2742, -3767, -2267, -2219, -3885, -4222, -6305, -5003, -4359, -7515, -6275, -6329, -9340, -7607, -12642, -7451, -5676, -9219, -6602, -13829, -5922, -6883, -7370, -5890, -10794, -4729, -10218, -5433, -6630, -9067, -4538, -15278, -4265, -8349, -8557, -5277, -15622, -4066, -8880, -8228, -7025, -17999, -4908, -8895, -7876, -9730, -20204, -6995, -10528, -7947, -8986, -15609, -11480, -8558, -8529, -6973, -14060, -13132, -6336, -9480, -6072, -14891, -8563, -5576, -9787, -5940, -12477, -6978, -5672, -9075, -6201, -9322, -6417, -6451, -8859, -6523, -7573, -6467, -7443, -9016, -6973, -6791, -7238, -7352, -8515, -7959, -6689, -8750, -7373, -7939, -9814, -6907, -8398, -8020, -7907, -11790, -7184, -6899, -8017, -8015, -10770, -7572, -6198, -8602, -7580, -9305, -7928, -6155, -12835, -6869, -8482, -8451, -6730, -11413, -6489, -8152, -9575, -7862, -8206, -6709, -8087, -8522, -9050, -7654, -7533, -7890, -6803, -9935, -8072, -8451, -7253, -6535, -11353, -8295, -8740, -6322, -7893, -15348, -7725, -8988, -5476, -11460, -13262, -7221, -9483, -4995, -10780, -10224, -7251, -9437, -5058, -8963, -8837, -7649, -9570, -5841, -9093, -8473, -8169, -11427, -7607, -10154, -9463, -9020, -13397, -10596, -9380, -11766, -10451, -10172, -10965, -8168, -11446, -11564, -8940, -9038, -8329, -11145, -11019, -8637, -7810, -10112, -13124, -9888, -8452, -7159, -12460, -13661, -8969, -8120, -7365, -11740, -11131, -8617, -7994, -9199, -10800, -9901, -8864, -8338, -18405, -9328, -9597, -9573, -8683, -9092, -8348, -10440, -11231, -8532, -7338, -8315, -13288, -13336, -8470, -7996, -8943, -11069, -10472, -9040, -11538, -10138, -8492, -9458, -10575, -12131, -12718, -7794, -10389, -12879, -10330, -17404, -8374, -12979, -12355, -11566, -15374, -10212, -15777, -12279, -12726, -16126, -12892, -15051, -17251, -12160, -15098, -11206, -13405, -13200, -12773, -12624, -9967, -12677, -10384, -12458, -10770, -10191, -12112, -9969, -12304, -9488, -11298, -11629, -10552, -12837, -9005, -12997, -11904, -11543, -11254, -9555, -14936, -12024, -13036, -10176, -11863, -16570, -11122, -14227, -10661, -18824, -15736, -10527, -14187, -13092, -11981, -10996, -10305, -17064, -21464, -10450, -9195, -11056, 4273, -1175, 9553, 9450, 3052, 4463, 3879, 9185, 8848, 3751, 3691, 5671, 8199, 6996, 2976, -6, 5626, 6835, 3747, -666, 792, 4574, 5106, -1149, 3063, 2037, 4190, 3092, -4209, 3800, -358, 4688, 1661, -2811, 2384, 554, 4827, 2424, -2806, 1978, 2707, 4521, 3968, -690, 2707, 2711, 3757, 4130, 2386, 1913, 2064, 2494, 2508, 3667, 712, 2465, 1624, -715, 3416, 4000, 3141, 2531, -43, 2698, 6322, 3113, 4058, 1241, 3628, 7327, 2097, 4876, 2277, 4319, 7299, 1273, 4438, 3268, 3504, 6323, 1854, 3006, 3946, 376, 4314, 1023, 3672, 4062, -5035, 714, -3398, 4912, 3429, -584, -8156, -3245, 4998, 1886, 697, -982, 327, 4263, -1023, 1589, 1056, 3814, 3295, -5086, 2308, 1972, 5817, 2295, -2104, 3082, 2652, 6521, 377, -467, 3600, 3493, 6229, -3459, -114, 3379, 4039, 5186, 1078, -559, 2118, 3913, 3637, 3134, -594, -248, 2957, 1526, 3430, -111, -1222, 986, -1358, 2163, -472, 56, -2241, -835, -1865, -2532, 1237, -4694, -594, -748, -9471, 2363, -695, -6239, 2071, -3963, 3385, 1107, -315, 2712, -1725, 4066, 1139, 2838, 1943, -850, 4185, 385, 3798, -1034, -810, 3729, 409, 3633, -3631, -1834, 2835, 188, 2725, 946, -4437, 1381, -1223, 1115, 1704, -6992, -1534, -2586, -1552, 193, -4345, -4134, -2019, -2514, -5752, -3653, -1077, -1083, -444, -2084, -4006, -412, -207, 462, -456, -2819, -1217, 425, 537, -907, -1298, -3329, 342, 278, -2320, -650, -6489, -974, -53, -2929, -765, -4640, -4479, -814, -2364, -1373, -2710, -9811, -2690, -2639, -2160, -1708, -7460, -5063, -4249, -3165, -1116, -6249, -2842, -5023, -4942, -960, -3882, -1322, -3471, -8502, -1330, -3190, -894, -2532, -9041, -1644, -3392, -1071, -1851, -6633, -1087, -3902, -1602, -1002, -5609, -598, -5119, -2438, -522, -4698, -1066, -6220, -3522, -1088, -4180, -3025, -5845, -4633, -3574, -4309, -9354, -5815, -5317, -8883, -4318, -4059, -5763, -4295, -4753, -3956, -1188, -5059, -3028, -5161, -4196, -282, -4459, -2775, -9570, -4659, -623, -4394, -3602, -6541, -2769, -1731, -5262, -4933, -5054, -1102, -2424, -8236, -4875, -4457, -759, -1695, -5776, -4752, -4278, -1699, -657, -3225, -5190, -6168, -3979, -402, -2833, -3816, -9388, -7674, -1212, -3869, -2747, -4540, -11357, -3107, -5078, -3168, -3531, -8642, -5995, -4722, -5514, -4313, -5362, -8466, -3742, -12373, -6390, -3513, -7445, -3093, -5643, -8647, -2786, -5096, -3357, -3478, -8699, -3144, -3019, -4871, -3100, -8418, -4030, -1802, -7819, -4520, -8160, -3842, -1386, -9033, -9826, -8837, -3438, -1593, -5964, -4630, -9426, -3444, -2068, -3661, -1901, -7578, -3273, -2546, -2794, -963, -6642, -3195, -3431, -3491, -1447, -6127, -3465, -3316, -6683, -3872, -5921, -3687, -2004, -9602, 6954, 9472, -4937, 4408, 9914, 6202, 9072, -277, 4177, 9310, 3917, 7959, 2087, 3212, 7388, 683, 6428, 3014, 2072, 3868, 582, 4826, 3459, 2377, 1248, 2628, 3240, 3879, 2178, 2305, 3044, 2265, 4056, 802, 3017, 977, 2908, 4021, -218, 2782, -1481, 3752, 3866, 9, 1238, 1895, 3814, 3406, -734, -1246, 2452, 2890, 2862, -2419, -2154, 1980, 744, 2974, 458, -160, 2350, -3684, 3764, 1833, 1209, 2987, -188, 4442, 1831, 1820, 3272, 3009, 4590, 1979, 2915, 3663, 4306, 4297, 2743, 3739, 4182, 4135, 3864, 3231, 3347, 4460, 2066, 3431, 3057, 1366, 4330, -4188, 2732, 2029, -2450, 3903, 673, 1244, 597, -4712, 3501, 1868, -1737, 1065, -6321, 3025, 1724, -4798, 2014, -4691, 2115, 726, -4126, 2091, -2153, 873, -214, -4141, 2340, 833, -948, 3005, -788, 3695, 2866, -1217, 4662, 580, 4650, 3917, 1403, 4843, 599, 4670, 4315, 2157, 4046, 1278, 4078, 4281, 968, 2668, 1969, 3638, 3946, -3127, 868, 1315, 3439, 3449, -3484, -1794, -954, 2896, 2900, -913, -7509, -3831, 2195, 2366, -124, -8891, -3278, 2169, 1966, 447, -9929, -2773, 2353, 1726, 974, -7235, -4046, 1859, 1446, 1041, -4166, -4206, 167, 963, 362, -4972, -2035, -4366, 733, -1274, -4793, -1814, -2747, 1230, -3148, -1473, -3520, -65, 1452, -1912, -365, -4497, 161, 630, -1234, -1045, -2661, -1458, -1577, -2481, -4519, -1881, -2648, -5054, -7214, -6705, -1632, -918, -5935, -5615, -2820, -1622, -958, -7067, -2567, -3478, -2015, -3264, -8679, -1535, -8165, -2000, -5201, -6614, -1732, -1751, -1280, -3369, -6594, -3178, 554, -656, -3463, -5552, -6775, 1130, -171, -4938, -3561, -8282, 471, 41, -5423, -2609, -2999, -1300, -94, -3325, -2318, -1368, -3745, -379, -1975, -2221, -1283, -5095, -900, -1983, -2245, -2265, -4743, -2068, -3757, -2644, -3826, -3992, -4546, -8374, -3572, -5080, -4028, -10704, -6822, -3868, -5142, -5987, -4616, -6468, -2488, -4351, -9791, -2110, -7995, -1434, -3764, -4731, -1066, -5576, -1032, -3972, -3632, -1165, -2801, -647, -4636, -4538, -2905, -1633, -126, -4203, -4911, -9326, -1965, -14, -3423, -3255, -5919, -3705, -551, -3487, -2473, -5154, -6023, -1571, -4266, -2469, -9219, -7353, -2958, -4869, -2960, -9120, -8008, -5357, -5053, -3932, -6637, -6305, -7577, -4855, -5276, -6676, -3559, -5508, -3928, -8032, -5416, -1765, -4957, -3400, -7311, -3173, -977, -5631, -3807, -3876, -1883, -1052, -7343, -5107, -2784, -1889, -2034, -7426, -6933, -2888, -2758, -3039, -5105, -7268, -3435, -3180, -1892, -4394, -6583, -3779, -3925, -902, -5305, -7276, -4089, -6806, -1123, -7841, -8526, -5036, -5094, -2829, -12767, -7115, -6830, -3640, -4196, -6814, -6351, -5633, -5165, -2616, -4037, -7365, -3552, -12596, -2570, -3857, 5615, 3635, 5008, 8307, 8560, 5276, 3327, 4031, 7670, 8181, 4450, 2321, 1492, 5751, 7141, 3678, 319, 2251, 3453, 5936, 3177, -3642, 2484, 2769, 5359, 2469, -8211, 83, 1311, 5080, 1111, -4452, -710, -1942, 4119, -1054, -5164, 75, -988, 1760, -2503, -5947, -2624, 1559, 2341, -664, -399, -3492, 2666, 4350, 1598, 1249, -3523, 2324, 4896, 3228, 1656, -2654, -128, 5228, 4019, 2532, 406, -2052, 5724, 3668, 2788, -39, 2565, 5583, 1650, 1405, -870, 3978, 4515, -2496, 933, 2143, 3757, 2798, -1109, 2023, 2958, 2232, 2025, -625, 1457, 2016, 114, 2601, -1397, 894, 15, -1423, 2450, -2000, 2236, -1643, -11317, 1123, -1329, 2933, -2148, -170, -824, 557, 2647, -1452, 2212, -2245, 2466, 1557, -1140, 2175, -1229, 3422, -218, -1811, -164, 581, 3061, -2526, -3445, -5945, 1800, 1065, -5835, -5227, 176, 2800, -702, -8766, -4097, 2096, 3326, 706, -3323, -2528, 2868, 3305, 365, -1412, -980, 3057, 3440, -2261, -908, 566, 2721, 4059, -3183, -1116, 1551, 1749, 4440, -1772, -1045, 1894, 359, 4158, -2445, -643, 1789, -242, 3144, -4745, -967, 1530, -193, 1520, -4033, -2696, 1308, -892, 52, -2012, -5652, 978, -2084, 18, -1076, -4025, 301, -647, -37, -1324, -2462, -748, 993, -756, -4055, -1989, -1544, 1716, -216, -4336, -1713, -798, 1934, 646, -734, -585, 182, 1874, 632, -120, 181, 146, 1506, 245, -1036, -461, -1386, 874, 294, -1857, -2886, -4885, 226, 715, -1534, -4240, -3475, -156, 764, -1498, -4122, -2271, -228, 6, -1893, -7978, -2968, -98, -1350, -2696, -7527, -3951, 161, -2049, -4314, -4112, -2768, 377, -2023, -6945, -2920, -1353, 292, -2319, -8120, -2399, -663, -146, -3012, -6529, -2890, -708, -576, -3730, -5428, -5567, -1452, -537, -4195, -5525, -6484, -3160, -453, -4817, -7842, -2593, -7125, -1080, -5487, -7095, -1935, -11674, -2918, -3832, -3255, -3267, -7803, -5583, -1555, -1853, -3193, -4682, -4558, -248, -2116, -1765, -1967, -3151, 143, -4549, -2223, -635, -3122, -199, -11564, -4887, -375, -5590, -1244, -3692, -4172, -974, -6671, -3216, -1978, -1813, -2305, -2030, -4099, -1808, -942, -4570, -619, -1963, -2460, -1148, -8696, -699, -693, -2703, -2454, -6312, -2090, -404, -2307, -4238, -5549, -5742, -910, -2557, -4134, -8368, -6972, -1986, -3818, -4147, -5337, -2869, -2843, -5667, -5483, -2721, -1442, -2606, -6727, -5661, -2118, -1262, -2025, -6217, -4312, -2781, -2241, -1803, -5391, -4079, -3978, -4918, -2132, -5481, -4602, -4163, -8880, -3134, -7374, -4419, -3967, -5455, -4967, -8361, -3621, -3249, -4093, -6857, -4338, -2503, -1548, -3482, -6420, -2519, -1318, -657, -3514, -4889, -2151, -979, -1116, -5343, -2908, -3067, -2029, -3077, -8158, -1527, -6560, -5790, -3832, -2206, -4127, -3399, -4292, -4940, -4974, -2793, -2362, -2653, -10980, -5415, -3649, -2321, -1871, -4721, -2919, -4537, -2595, -2070, -2139, -2575, -1729, -2704, -3356, -1931, -3305, -753, -2510, -6063, -3729, -5163, -1706, -2349, -9383, -5256, -11377, -5034, -2566, -7340, -2712, -5787, -9046, -3593, -6261, -1699, -3302, -9886, -6186, -6696, -1792, -2738, -7512, -8622, -9946, -2511, -3281, -3572, -4661, -8071, -3873, -4912, -2319, -2313, -4209, -6451, -7637, -2129, -1412, -2828, -5466, -7336, -2281, -2182, -2979, -2911, -6517, -2539, -6309, -4981, -2174, -6412, -2590, -4489, -7737, -3255, -4516, -1907, -1229, -3607, -5026, -1662, -835, -276, -1725, -2208, 222, -152, -496, -1159, -920, 934, -298, -1543, -1731, -1278, 570, -1511, -3107, -3860, -2520, -665, -4148, -5063, -9601, -3563, -2338, -7677, -6647, -9347, -5738, -4128, -5612, -6055, -8722, -11473, -5027, -4799, -5335, -10194, -3950, -3216, -5976, -4666, -6511, -2263, -1858, -11547, -3776, -4016, -2056, -1812, -6608, -3305, -3151, -2510, -3001, -3221, -3992, -3655, -3160, -3823, -2022, -7049, -4559, -3915, -3231, -2280, -10880, -4556, -4119, -3716, -3862, -5402, -5662, -3493, -5324, -6761, -3992, -12154, -3430, -4389, -10854, -3634, -7926, -4819, -3306, -7653, -3998, -6180, -8424, -3646, -7246, -5270, -5766, -6096, -5140, -8179, -8096, -4530, -3860, -7042, -4222, -14070, -3643, -3048, -7790, -2448, -6400, -3436, -2945, -7516, -2289, -3818, -3584, -3237, -8134, -3080, -2611, -3866, -3720, -8361, -3900, -2253, -4413, -4300, -4948, -5062, -2574, -5451, -4891, -3104, -9966, -3473, -6412, -4902, -2675, -7509, -4489, -6146, -4202, -3286, -5122, -4607, -6019, -3941, -4588, -5910, -4538, -6926, -4744, -5937, -9521, -5491, -8071, -6459, -6309, -11466, -8106, -7592, -7168, -5891, -9960, -11277, -5992, -5987, -5797, -9214, -8528, -4722, -4286, -6720, -6405, -6920, -4206, -3205, -6913, -3869, -6418, -4041, -3431, -4272, -2550, -7061, -4052, -5496, -2653, -2424, -7305, -4873, -5290, -2181, -3493, -5061, -7351, -2919, -2649, -5876, -3521, -9266, -2294, -4077, -10095, -2802, -7212, -2773, -5907, -8717, -2538, -7541, -3682, -5534, -5626, -2788, -11674, -4209, -5122, -4904, -3801, -7671, -4054, -5863, -6040, -5899, -5640, -3933, -6746, -7308, -9937, -6103, -4673, -7159, -6200, -11302, -8101, -6783, -8030, -6107, -10018, -8576, -9051, -8822, -7101, -11354, -9780, -10360, -7996, -7714, -12917, -14236, -12235, -6338, -6552, -11621, -9197, -7458, -5166, -4849, -8419, -7984, -6006, -4844, -3899, -6185, -7370, -5861, -5552, -3962, -5079, -6536, -5921, -7571, -5142, -4988, -5869, -5594, -8610, -7533, -6242, -5003, -4945, -7103, -8357, -10606, -4213, -4411, -7081, -6808, -6725, -4030, -4417, -8126, -6290, -3779, -4559, -5224, -8156, -7091, -2724, -5747, -6887, -7593, -10336, -2890, -7675, -7564, -7008, -10528, -9120, -3096, -4727, -4287, -7491, -4825, -4498, -3189, -5400, -5052, -2316, -9808, -3096, -4647, -2070, -1095, -6897, -3549, -5188, -1297, -802, -4170, -4566, -6792, -1008, -1259, -3154, -7079, -7195, -699, -2081, -2734, -15953, -4835, -883, -3234, -2323, -6262, -3110, -1629, -6398, -2055, -4209, -3242, -2189, -8191, -2449, -3915, -5945, -2211, -3292, -3650, -4302, -8079, -2289, -1759, -5461, -3952, -6295, -2647, -1335, -7280, -3541, -8559, -3380, -1636, -6264, -3789, -13940, -5077, -2738, -4418, -4242, -9014, -9489, -4759, -3781, -4495, -5163, -5181, -6342, -4922, -5022, -3683, -2458, -8291, -7631, -6580, -4346, -1075, -8462, -2754, -4878, -3071, -243, -2870, -537, -1919, -316, 204, -1089, 0, -670, 949, 296, -995, -644, -856, 1038, -27, -2143, -1944, -2630, 177, -943, -3767, -2880, -7857, -1420, -2684, -4335, -3313, -6982, -3321, -5534, -4204, -3754, -4830, -5405, -9695, -4094, -4340, -5866, -8479, -13551, -3983, -5277, -8131, -10593, -13952, -3253, -5526, -5080, -10748, -15480, -2255, -3728, -3198, -8577, -12923, -1884, -2381, -2588, -6205, -8805, -2267, -2100, -3295, -5584, -7718, -2484, -2385, -6230, -5795, -5552, -1869, -2196, -8137, -4130, -3618, -1475, -1783, -4668, -2520, -3253, -1644, -2018, -3820, -2332, -4373, -2114, -3077, -3941, -3940, -5092, -2411, -4569, -4179, -8094, -3619, -2672, -4884, -4497, -4430, -2644, -4021, -3878, -5995, -2571, -2405, -8544, -3126, -13961, -2273, -2688, -7916, -2867, -5187, -2779, -3384, -6460, -2694, -2522, -3542, -4525, -8638, -2424, -1563, -4042, -6247, -15573, -2544, -1488, -4321, -7301, -10773, -3226, -1982, -4677, -5448, -7491, -3714, -2968, -4713, -3784, -4511, -3859, -4348, -4788, -3045, -2910, -4707, -5446, -6259, -3197, -2664, -6729, -5219, -8369, -4314, -3598, -10067, -4589, -5702, -6900, -4468, -14336, -4819, -4702, -15129, -3976, -12010, -5059, -4953, -8456, -3869, -11674, -3651, -5724, -6693, -4473, -12949, -2778, -7384, -6712, -4823, -12265, -3244, -8545, -6116, -4636, -12510, -5433, -7265, -4422, -4448, -10423, -12733, -7066, -3619, -3561, -7027, -7660, -6530, -3902, -2370, -5509, -5134, -6155, -4675, -1971, -5581, -4506, -7476, -5309, -2794, -7460, -5683, -10713, -6690, -5356, -12984, -11029, -9099, -8566, -9806, -12260, -7688, -7849, -6230, -7807, -9346, -5945, -8325, -4902, -7786, -6910, -7009, -8612, -5072, -9369, -5536, -10069, -6354, -6591, -10282, -5508, -8597, -4974, -9521, -9013, -7028, -7475, -4960, -12767, -7785, -11313, -6752, -6424, -12740, -7696, -11893, -5091, -9821, -12027, -8870, -7707, -3872, -8602, -12424, -10914, -5108, -3573, -6720, -12253, -11214, -3706, -4009, -6618, -10520, -8551, -3648, -4646, -8112, -8389, -6121, -5259, -4687, -12149, -7513, -4632, -10013, -3921, -11291, -8555, -4036, -8911, -3076, -9212, -12275, -4365, -7671, -2822, -8690, -8791, -5970, -9197, -3530, -8578, -6469, -5236, -4781, -6658, -2943, -1061, -7932, -4475, -8167, -934, -1390, -5860, -2757, -4476, -89, -2212, -2857, -2192, -2450, 167, -3011, -1371, -1832, -1663, -238, -3480, -972, -1294, -1547, -1734, -4059, -1244, -897, -1830, -3042, -5447, -1757, -863, -2291, -1205, -7176, -2443, -1068, -2025, -309, -6780, -3996, -1493, -1345, -773, -7187, -6478, -2689, -1326, -2301, -8534, -3977, -5782, -2000, -3862, -7084, -2219, -12366, -2773, -4157, -5134, -1684, -8569, -3243, -4514, -3676, -1609, -7788, -3766, -5119, -3547, -1606, -7236, -4041, -5522, -4209, -2205, -8857, -3681, -5065, -3096, -4882, -10267, -5416, -4456, -2720, -5063, -4605, -5564, -5785, -5154, -1789, -1874, -728, -5549, -5346, -1221, -874, 786, -2209, -2249, -2372, -1341, 650, -767, -1850, -3870, -3180, -695, -403, -3195, -3004, -5858, -2351, -602, -6531, -2624, -7577, -2869, -893, -7728, -3960, -8577, -3177, -1114, -5156, -6189, -9822, -3652, -1729, -4802, -4580, -9729, -3535, -3155, -6991, -3884, -9499, -3153, -4561, -8089, -3763, -8259, -3177, -3769, -5249, -3167, -6487, -3448, -2869, -6451, -2904, -5645, -3415, -2875, -6168, -3025, -5571, -2856, -3942, -2709, -3116, -6335, -2206, -6728, -1971, -2853, -8948, -2071, -11805, -3066, -1838, -12433, -2644, -6024, -5840, -967, -6445, -3627, -4214, -8153, -878, -4446, -4481, -3426, -6547, -1549, -3317, -5099, -2609, -5216, -2762, -2450, -5268, -1988, -4438, -4504, -1871, -4618, -2094, -3854, -7470, -1826, -3355, -2869, -3289, -17753, -2802, -2154, -3651, -2710, -7254, -5823, -1379, -3810, -2387, -4293, -7421, -1022, -3262, -2595, -2864, -4888, -984, -2695, -3096, -2603, -5210, -1266, -3076, -3220, -3347, -6868, -1982, -5280, -2894, -3896, -7007, -3145, -17998, -2759, -3266, -7738, -4097, -6380, -3554, -3183, -10779, -3979, -4415, -6024, -4240, -12735, -3976, -3511, -9161, -6071, -12265, -5311, -2484, -10379, -6941, -7090, -10284, -1505, -12420, -5684, -4708, -7921, -1099, -7151, -3929, -4140, -4845, -1423, -7725, -2906, -5352, -4079, -2415, -10884, -2767, -9575, -4751, -3868, -4996, -3267, -11989, -7115, -5006, -3391, -3812, -11979, -10810, -5188, -3586, -3784, -8891, -6382, -5441, -5553, -3438, -5727, -3479, -5894, -12436, -3191, -4619, -2024, -5517, -7064, -3122, -4018, -1711, -4483, -4948, -3381, -3236, -2307, -3707, -4471, -4159, -2468, -3365, -3586, -4439, -5249, -1958, -4202, -4446, -4159, -5909, -2016, -4686, -7049, -3815, -5830, -2881, -5316, -8985, -3897, -5727, -4315, -6894, -6111, -4099, -6446, -5802, -10967, -5680, -3778, -8126, -8852, -12693, -6969, -3660, -9269, -11311, -8799, -8984, -4230, -10135, -6885, -6827, -8416, -4706, -12410, -6134, -6142, -7269, -4802, -11045, -6734, -6913, -6875, -5306, -7901, -7838, -8307, -6747, -5268, -6268, -8514, -7424, -6007, -4627, -6013, -7963, -6595, -4887, -4943, -6881, -6893, -6953, -4348, -6424, 8312, 5887, 763, 6240, -363, 8294, 6155, 1032, 5545, -1258, 8007, 5877, 1907, 2928, -1251, 7048, 3746, 3572, -1938, 911, 5242, -371, 4533, 2396, 1978, 3126, 3069, 3923, 2713, 1787, 2172, 4094, 719, 14, 481, 3186, 4027, -121, -4285, 838, 4514, 3804, 2625, 180, 2550, 4919, 3657, 2521, 1067, 3483, 4582, 3362, 258, 2969, 3998, 4482, 2739, -6911, 4973, 4239, 4254, 3194, -2381, 5869, 4139, 2316, 4698, -612, 5539, 3654, -2238, 5395, -864, 3736, 2454, 913, 5114, -2219, 274, -5, 1216, 4154, -2132, 1318, -2522, -67, 2602, -1085, 2215, -2412, 131, -283, -886, 1268, -4026, 1186, -8097, -1710, -1149, -6953, 1561, -4291, -3347, -4797, -2354, 1522, -1303, -3727, -6138, -433, 1412, 133, -2083, -4125, -87, 815, -292, 172, -1455, -1082, -27, -3173, 1392, 845, -3508, 747, -2476, 1285, 1824, -1900, 1521, -1280, 820, 1686, 181, 1523, -4127, 1264, 491, 504, 1582, -1000, 1071, -3544, -907, 1450, 2030, -655, -2890, -3654, 3, 2817, -492, 659, -651, -4158, 2016, 1441, 818, 725, -10322, -840, 1979, -1194, -2, -8915, -5398, 1183, -1790, -2223, -6956, -2149, -1520, -56, -1105, -3460, -2442, -10631, 261, -303, -1559, -3357, -1627, -200, -1439, 167, -1243, -98, -570, -2185, 1208, 270, -178, -341, 51, 1412, 678, -1143, 5, 1425, 1216, -292, -1832, -159, 1825, 1256, -3538, -1494, -1115, 1555, 1587, -1977, -404, -2659, 1059, 1717, 80, 665, -3520, 841, 1159, 162, 792, -3107, 657, -448, -835, -464, -2113, 58, -3922, -1838, -3144, -1636, -806, -10528, -1556, -2638, -2444, -1534, -4173, -477, -1284, -3701, -2217, -3028, 311, -1290, -1968, -2833, -2955, 532, -2286, -406, -2998, -3034, 207, -3360, 179, -3012, -2639, -619, -2785, -62, -3928, -1952, -1977, -1827, -1392, -7686, -1681, -4262, -1592, -5592, -9053, -1987, -8758, -2354, -5422, -6045, -2718, -7035, -4539, -1752, -6965, -3828, -5662, -10232, -853, -7632, -5907, -6125, -6723, -855, -6549, -8259, -5978, -3467, -1133, -6529, -4785, -4562, -2279, -1386, -6847, -3401, -3669, -2823, -1427, -7821, -3833, -3606, -6032, -1374, -8088, -6000, -4148, -7704, -1368, -5769, -7785, -4977, -4936, -1565, -4181, -5556, -6132, -5997, -2140, -3599, -3794, -7335, -13081, -3091, -4133, -2413, -7218, -7692, -4501, -5860, -1528, -6840, -6739, -7249, -6578, -1438, -8422, -8001, -17811, -5284, -2387, -10105, -7352, -7847, -4947, -4342, -5643, -6214, -7228, -6386, -5210, -4781, -7105, -8778, -13916, -4956, -6509, -11004, -8787, -7620, -5986, -13650, -7198, -9389, -6170, -8564, -12574, -5441, -18478, -7578, -14813, -12988, -5656, -9929, -14786, -9762, -8635, -6950, -8535, -8450, -6373, -7771, -7891, -9058, -5077, -5412, -8878, -7258, -9097, -3639, 1446, 4870, 5496, 3432, 778, 2169, 4055, 4926, 2644, 1374, 2487, 1165, 2583, 1077, 1593, 1238, -9366, -4050, 2166, 1722, -1745, -4241, 2422, 3098, 2608, -1709, -11737, 3101, 2365, 2776, -656, -3138, 698, 90, 1600, -336, -1552, 42, 1775, 821, 87, -2168, 3276, 3289, 2542, -194, -1324, 4464, 2620, 4013, -3154, 646, 5129, 658, 5289, -802, 2092, 5542, 3390, 6094, 2705, 3242, 5233, 4793, 6071, 3909, 3952, 3664, 4131, 5190, 3726, 4040, -489, 463, 3738, 2159, 3503, -3730, 867, 2626, -1511, 2218, -177, 3882, 2668, -891, -258, -454, 4726, 2825, 821, -1874, 271, 4810, 2074, 230, -1089, 2122, 4593, -88, -2783, -2625, 2683, 4179, -4117, -7287, -3032, 1897, 3611, -3947, -3767, -1114, 377, 3060, -3057, -3805, -1994, 650, 2579, -4042, -6118, -6273, 1787, 1891, -5161, -6898, -5117, 1980, 863, -4271, -2408, -6868, 696, -89, -3863, -556, -3126, -4108, -359, -1906, 282, -431, -1615, -145, 439, 855, 479, 930, -166, 1445, 1122, 957, 828, -616, 1130, 775, 1433, -1303, -1174, -415, -162, 1415, -1521, -1711, -2517, -798, 37, -129, -1913, -2753, -848, -5232, -1012, -1887, -1764, -1762, -2590, -3901, -2498, -512, -2482, -429, -2118, -3514, 660, -1072, -597, -614, -4241, 1327, -790, -1868, -22, -3086, 1275, -2170, -2804, 433, -738, 732, -5131, -1557, 660, 408, 493, -6968, -83, 401, 317, 544, -3263, 920, -609, -882, 79, -592, 1584, -2882, -2961, -889, 747, 1898, -6333, -3936, -1213, 1066, 1671, -4477, -3040, -1196, 501, 605, -3687, -2741, -2076, -948, -1863, -3725, -3608, -3615, -3514, -8203, -2846, -5675, -4626, -7676, -5780, -2051, -5646, -4864, -7906, -4712, -1879, -4707, -4460, -8375, -6614, -2083, -5367, -4632, -16250, -14775, -2613, -7158, -5467, -7373, -10453, -3500, -9096, -6113, -6672, -12921, -4584, -8025, -7107, -9112, -8602, -5586, -6671, -8545, -6273, -4569, -6001, -6944, -6493, -3572, -3106, -5768, -6814, -5466, -2070, -2986, -5942, -6051, -6991, -1191, -3900, -7742, -5497, -10539, -980, -5624, -12196, -4103, -5565, -1540, -7062, -9523, -2878, -3827, -2988, -7111, -10643, -2372, -3418, -5831, -7249, -6598, -2449, -3770, -9218, -7702, -3064, -2873, -4524, -5252, -7390, -1470, -3361, -5234, -3699, -6322, -1108, -3863, -5805, -3796, -5425, -1798, -4517, -5806, -5718, -5233, -3353, -5104, -5088, -8064, -5966, -4350, -5365, -4661, -4926, -7452, -3960, -5678, -4644, -3868, -8402, -3993, -6276, -4768, -4497, -7430, -4679, -6686, -5100, -6680, -6008, -5367, -6348, -5765, -9584, -5354, -5330, -5759, -6800, -8074, -5635, -5118, -5631, -8313, -6312, -6572, -5525, -6352, -9706, -5356, -8122, -6676, -8115, -9754, -5232, -11807, -8113, -11082, -8604, -5830, -12132, -9036, -11127, -6709, 6577, 2520, 4753, 4151, -6277, 5589, 1368, 4321, 3621, 3271, 1874, 1192, 3362, 3087, 5773, -3867, 3437, 3263, 3753, 6554, 33, 4131, 3884, 3777, 6045, 1716, 3607, 3956, 2241, 4189, 2850, 2007, 3377, 1367, 1161, 1951, -1589, 2473, 3501, -395, 715, -2136, 1248, 4026, 2129, 3597, 349, -3343, 2390, 4017, 5389, -34, 904, 1934, 3345, 6038, 2492, 4607, 4228, -325, 5722, 4891, 5595, 3828, 4094, 4293, 5306, 4624, -1214, 5181, 1633, 3550, 792, 2721, 3531, 821, -5316, 717, 4457, 1230, 1080, 1384, 2685, 3550, 4020, -580, 2553, 2205, 205, 4954, -2816, 1369, 590, -8658, 4742, -1698, -1211, -629, -6616, 3828, -646, -3831, -237, -7037, 2574, -273, -4698, 467, -3754, 2042, -103, -5349, 849, -1731, 1984, 182, -8257, 951, -381, 1267, -129, -15880, 728, 94, 47, -1664, -9613, -14, -844, -405, -4780, -6293, -1484, -3930, -408, -5712, -3936, -4110, -1411, -383, -5165, -3535, -12188, 935, -295, -5321, -4553, -5474, 1539, -921, -1715, -3578, -2731, 969, -1541, 604, -1873, -1981, -490, -371, 1661, -1224, -2605, -2349, 191, 1867, -915, -4072, -4724, -641, 1362, -614, -5444, -7437, -1715, 46, -997, -7221, -4130, -770, -2305, -2440, -4308, -2677, -259, -4370, -3465, -1358, -2415, -715, -2586, -2698, -199, -2647, -834, -516, -1834, -588, -2857, -569, 258, -1793, -2251, -2194, -1192, -898, -1937, -2191, -852, -2583, -7152, 351, -1356, 102, -3698, -2950, 1852, -1932, 359, -6144, -1220, 1854, -2172, 55, -6653, -2009, 546, -1185, -340, -2419, -4113, -1290, -1150, -478, -1239, -6890, -2098, -2300, -959, -1842, -9870, -3081, -3299, -2614, -4334, -6524, -5286, -2315, -6323, -8689, -6324, -7051, -1389, -9340, -7912, -11485, -6039, -1331, -5992, -8125, -7089, -4737, -2125, -3981, -10595, -4020, -4177, -3806, -3357, -10943, -3272, -5259, -6807, -3837, -5883, -3671, -7274, -11253, -4242, -4281, -4544, -3604, -11765, -3483, -4209, -5169, -1853, -10870, -3008, -4896, -5876, -1572, -6055, -3923, -5510, -7833, -2223, -4625, -8226, -5841, -12540, -3583, -5274, -6509, -6567, -8375, -5407, -8003, -3287, -8715, -6207, -7424, -13138, -2446, -9753, -5663, -9630, -15199, -2672, -7218, -6661, -6037, -12704, -3539, -6174, -10491, -3939, -8698, -4719, -5061, -8431, -3339, -7629, -5801, -3775, -6080, -3854, -8518, -6103, -3128, -5811, -5276, -7916, -5332, -3191, -6563, -6015, -7152, -4632, -3752, -7412, -5063, -9671, -4680, -4701, -7650, -4302, -9953, -5723, -6167, -7995, -4104, -6363, -8287, -8535, -10190, -4399, -5858, -9631, -15346, -16341, -5128, -6659, -6771, -9534, -9119, -6612, -7005, -5858, -6761, -7614, -10632, -5834, -6800, -5861, -5931, -9280, -4667, -11591, -5616, -4315, -6135, -4309, -8330, -5613, -3928, -5865, -4985, -5460, -6193, -6200, -8553, -6508, -7937, -3343, -9220, -7479, -7092, -7098, -3815, -7377, -7211, -10560, -7407, -4573, -4819, -7566, -10829, -9354, -4967, -4005, -9157, -7836, -11251, -4939, -4060, -12517, -7841, -9124, -5106, -4032, -9702, -9763, -8266, -5876, -3708, -8169, -12969, -8955, -7321, -4019, -8001, -13153, -12277, -7778, -5533, -8327, -10652, -9170, -6266, -8421, -8485, -7668, -6262, -5238, -12272, -9176, -5981, -5445, -4819, -11447, -10176, -5855, -6189, -5005, -9051, -7100, -7117, -8724, -5961, -11311, -5790, -8166, -15544, -6816, -9360, -5149, -8190, -8935, -5866, -9914, -6606, -9288, -12789, -10198, -444, -785, 22, -512, -111, 3825, 3700, 4011, 3732, 4105, 5934, 5876, 6050, 5867, 6151, 6562, 6530, 6678, 6554, 6749, 5860, 5810, 6005, 5934, 6042, 3714, 3491, 3871, 3867, 3881, -362, -1720, -451, -332, -462, -8244, -5334, -9966, -11060, -13928, -14965, -3825, -7231, -7838, -7538, -14237, -5644, -11454, -9635, -12447, -11333, -7218, -10735, -7740, -14281, -7785, -7484, -7030, -8134, -10768, -7984, -8501, -5343, -10237, -8640, -10149, -11186, -5127, -16213, -8201, -9637, -11594, -6077, -11188, -8957, -7394, -11445, -8346, -8459, -9894, -6577, -12171, -11157, -7507, -9402, -7244, -8254, -10331, -7807, -8790, -9451, -6069, -11115, -9174, -9743, -15000, -5165, -15623, -9049, -13810, -14946, -4951, -14153, -7619, -17394, -12244, -5271, -10076, -7398, -15090, -10956, -6246, -8342, -8767, -16558, -10643, -7892, -8455, -11276, -11013, -12434, -9863, -11098, -10564, -8306, -14245, -11683, -14496, -10210, -7352, -10358, -11766, -9902, -11844, -7797, -8521, -9587, -9240, -12672, -9598, -7539, -8180, -10056, -9348, -11558, -6969, -8082, -10771, -7471, -10510, -7045, -8843, -10586, -6675, -9127, -8457, -8768, -9414, -6932, -8309, -12611, -7940, -7554, -8612, -8127, -10569, -7552, -6501, -11995, -8345, -8661, -7566, -6721, -11127, -8660, -8710, -7776, -8403, -9893, -9024, -10124, -8184, -9859, -9545, -8899, -13021, -8806, -8623, -9544, -8291, -12631, -9539, -8508, -10086, -8184, -10718, -11079, -9891, -10988, -8798, -9846, -15501, -12770, -12005, -9506, -9090, -11859, -16988, -13076, -9577, -8205, -10545, -15281, -12434, -9458, -7601, -10825, -15101, -10698, -9846, -7697, -9290, -15813, -9752, -11370, -8616, -8167, -14591, -9649, -15588, -9597, -8495, -15462, -9906, -14673, -9892, -9926, -20536, -9793, -11426, -11057, -10986, -12734, -9231, -10131, -14054, -10780, -10743, -8703, -9892, -13703, -10864, -10543, -8545, -10911, -13096, -11370, -11418, -9104, -13976, -11827, -11626, -12918, -11025, -13271, -9958, -11491, -14768, -15232, -11312, -9615, -11615, -13200, -12779, -11637, -10649, -12531, -11272, -11775, -13881, -10788, -13604, -10618, -12568, -17230, -9775, -13103, -10832, -13373, -17598, -9893, -12065, -11959, -13262, -15866, -11391, -11454, -14518, -13114, -14350, -13728, -11407, -14804, -13246, -14622, -13285, -11845, -13064, -12030, -18307, -11760, -12159, -12305, -10412, -15123, -6324, -9477, -9400, -7057, -5710, -6352, -8487, -9278, -5078, -6096, -6298, -7707, -8482, -4442, -8448, -5661, -7246, -8358, -4752, -12692, -5302, -6206, -10007, -5788, -7182, -6166, -4983, -13270, -7494, -5273, -8510, -4454, -10594, -9438, -4780, -10193, -4690, -8615, -10919, -5125, -11052, -5489, -7798, -13036, -5854, -12236, -6499, -7745, -7401, -6635, -10632, -7170, -7794, -4840, -7557, -11145, -7431, -7733, -3910, -8096, -11765, -8948, -8494, -4135, -6962, -9891, -12542, -10049, -5225, -5766, -10963, -10163, -8393, -7226, -7008, -9025, -7379, -6072, -8597, -9535, -13454, -7980, -10483, -10619, -10454, -524, -357, -673, -521, -913, 3774, 3850, 3806, 3801, 3726, 5896, 5951, 5941, 5949, 5967, 6539, 6579, 6562, 6618, 6666, 5850, 5857, 5818, 5968, 6006, 3680, 3600, 3535, 3900, 3852, -704, -1039, -1074, -41, -442, -20425, -13137, -8880, -7008, -7180, -7676, -7249, -9812, -10616, -7360, -10279, -5481, -10821, -11285, -6744, -11031, -5069, -9065, -12055, -6518, -9991, -6225, -8756, -16333, -8667, -10592, -8419, -8312, -11250, -10011, -12191, -13430, -7967, -10377, -10608, -12739, -13080, -6812, -11457, -12300, -13509, -10314, -6313, -16158, -13876, -18989, -8759, -6995, -16806, -12813, -11600, -7944, -8763, -18811, -7810, -8523, -8087, -8626, -13671, -5455, -7530, -9310, -6986, -10603, -4667, -7855, -10926, -6627, -10213, -5114, -9406, -10426, -7630, -10276, -6652, -10178, -9082, -9365, -9640, -9105, -8955, -8049, -10069, -9361, -12141, -8768, -8044, -10018, -10155, -15871, -8742, -9890, -9962, -13161, -22128, -8200, -13833, -10789, -16792, -13824, -8273, -10713, -12965, -14624, -10183, -8548, -10172, -10605, -20387, -7962, -7851, -11897, -8350, -13740, -6838, -7172, -13924, -7292, -11677, -6817, -7315, -12211, -6859, -11522, -8153, -8547, -10846, -6858, -11643, -11284, -10893, -10119, -7332, -10993, -11217, -11394, -10115, -8360, -10006, -9632, -11033, -10993, -9848, -9822, -9397, -11758, -12169, -11656, -11314, -9647, -10253, -11377, -15028, -17323, -9926, -8792, -9976, -15320, -14192, -10389, -8646, -9355, -11446, -12505, -11423, -9549, -9778, -10204, -13602, -12870, -11143, -11814, -10021, -18248, -12820, -12849, -14717, -10517, -16157, -11201, -13626, -10610, -12078, -13136, -9927, -13163, -8579, -14304, -11833, -9257, -12540, -7856, -12246, -10955, -9144, -12407, -8209, -10861, -10350, -9797, -13195, -9967, -10891, -10379, -11896, -15556, -14905, -11801, -11591, -19418, -16477, -13344, -11845, -15351, -14372, -14073, -11411, -10850, -18659, -12416, -13199, -12060, -10790, -15823, -12264, -12718, -14280, -12046, -18986, -12902, -11598, -15084, -12664, -17066, -13984, -10396, -15153, -11569, -16303, -14781, -9857, -17401, -11389, -22830, -13452, -10185, -27068, -12151, -13558, -11746, -11330, -16623, -13653, -11224, -11074, -13063, -14198, -16091, -10707, -11621, -15303, -13355, -14189, -11493, -13829, -17195, -14040, -11965, -13852, -18027, -14642, -17286, -11045, -17219, -15206, -12429, -22284, -10583, -15085, -14255, -5111, -8181, -6549, -4897, -8234, -8490, -18312, -7810, -5765, -17195, -9800, -10653, -8301, -7841, -9189, -8646, -14834, -8803, -9710, -7281, -9213, -10024, -8625, -9340, -7338, -8926, -7689, -7824, -9330, -9147, -8812, -8023, -6553, -11359, -13026, -9700, -9056, -5691, -13529, -8406, -8745, -9062, -5610, -9201, -6813, -7212, -9078, -5853, -7526, -6881, -7424, -9496, -6434, -7064, -7710, -9464, -9887, -8019, -8062, -9180, -11192, -8688, -9004, -14243, -11558, -10074, -6315, -7134, -10315, -9984, -10918, -5924, -6393, -10145, -11123, -9806, -6673, -6775, -7294, -7563, -10028, -6767, -6627, -6054, -8211, -673, -269, -153, -410, -462, 3658, 3899, 3790, 3794, 3863, 5808, 6013, 5839, 5920, 5990, 6444, 6660, 6471, 6571, 6643, 5689, 5989, 5790, 5895, 5987, 3325, 3884, 3647, 3761, 3929, -1754, -187, -639, -440, 50, -8211, -8616, -11834, -10163, -5789, -7590, -10466, -8996, -13313, -6715, -11943, -10600, -9727, -8406, -6591, -9097, -9376, -8364, -7190, -6668, -9015, -8462, -8907, -8539, -6303, -8460, -7343, -9806, -10953, -6011, -7663, -6472, -10571, -9496, -6413, -6880, -6655, -11790, -8082, -7031, -6522, -8223, -11268, -8737, -7692, -7118, -10117, -11663, -12041, -8448, -9533, -9593, -15313, -12392, -9478, -18602, -8816, -11429, -8895, -12054, -11179, -8822, -9217, -7784, -14643, -9564, -9603, -8496, -7855, -9020, -8861, -10482, -8191, -8705, -7733, -9082, -10202, -8062, -11167, -8627, -11604, -8907, -8473, -16546, -10658, -11858, -7812, -9627, -9355, -8890, -8190, -7538, -10633, -7706, -7730, -6849, -8080, -9108, -7559, -8057, -6720, -9112, -7655, -8306, -9830, -7647, -9889, -7064, -9763, -12763, -10007, -9471, -7045, -11985, -12538, -15469, -8243, -7479, -13782, -13003, -15736, -7151, -8434, -12474, -20353, -12992, -6507, -9800, -11537, -12301, -10376, -6345, -10815, -11652, -9995, -9366, -6590, -10528, -12500, -9541, -10271, -7098, -9549, -13197, -9750, -10632, -7794, -8985, -12956, -10146, -8248, -8486, -9275, -12169, -11215, -7216, -8669, -10398, -11343, -13727, -7454, -8569, -11756, -11006, -18229, -8521, -8946, -12224, -11114, -19315, -9737, -10248, -12077, -11015, -19702, -10458, -12370, -12977, -10475, -14351, -10803, -11973, -16841, -9938, -11685, -11222, -10314, -13740, -9705, -10829, -11841, -9569, -11818, -10113, -11856, -11386, -9666, -11946, -12096, -16134, -10401, -10214, -12794, -20737, -13145, -10467, -10065, -13294, -10923, -11149, -11854, -9264, -13455, -8919, -11022, -12777, -9041, -13589, -8787, -12370, -11861, -9846, -15421, -10085, -14716, -11869, -11867, -17826, -12719, -11822, -12688, -15281, -12752, -15662, -10433, -12735, -18034, -11246, -19506, -10818, -12305, -15670, -11170, -13583, -11790, -12741, -14857, -11642, -11180, -10749, -14781, -16906, -11816, -10866, -9400, -21844, -15369, -11386, -12020, -8669, -18289, -11859, -10840, -13480, -8294, -17206, -10414, -10607, -13398, -8217, -16096, -10103, -10802, -13232, -8573, -14197, -10582, -11426, -13681, -9469, 13787, 14482, 4978, 9252, 11837, 13142, 13944, 4781, 8623, 11115, 11041, 12305, 4122, 6636, 8769, 6500, 9549, 4653, 3113, 4014, 364, 6117, 5897, 1273, -1449, 4622, 4026, 5912, 1807, -4079, 4377, 4233, 4397, 762, -2972, 2131, 4306, 2088, -94, -1821, 731, 3764, 2965, 2827, 2767, 3262, 3394, 4029, 4634, 4859, 3406, 3613, 4412, 5302, 5672, 1375, 4227, 4558, 5029, 6061, -3400, 4918, 4488, 3616, 6377, -5761, 5197, 3982, 355, 6282, -1053, 4744, 2957, 363, 5315, 1144, 3424, 2115, 2646, 3131, 1395, 1044, 2637, 3056, 656, 956, -3300, 3401, 2110, 1208, 105, -6609, 3508, 681, 1312, -4040, -3827, 2964, 2051, 978, 1360, -3994, 2019, 3680, 1426, 4160, -4790, 653, 4368, 1589, 4987, -2691, -1786, 4311, 977, 4326, -936, -2880, 3675, -26, 1433, -152, -260, 2708, -1196, -3895, -336, 944, 2077, -1140, 1532, -1804, 1016, 2018, -230, 1660, -1298, -2, 1662, -783, -759, 725, -2655, 492, -2131, -5217, 1363, -4750, -1417, 88, -5661, 1034, -2778, -3746, 1317, -4242, 311, -3574, -8503, 817, -373, -340, -2916, -7619, -68, 2394, -443, 58, -4328, 1397, 3818, -149, 1292, -2863, 2312, 3943, -590, 1294, -1452, 1738, 2645, -2903, 176, -1242, -587, -913, -3009, -2557, -3482, -6100, -3543, -97, -9954, -8191, -6916, 150, 820, -8630, -3025, -6507, 1377, 444, -7535, -2068, -5282, 1773, -1119, -5293, -1568, -3256, 1565, -4468, -4636, -860, -2027, 631, -6159, -6005, -239, -1157, -1430, -4037, -5551, 152, -397, -5342, -3689, -2472, 10, 41, -3431, -3131, -596, -819, -40, -1561, -2261, 413, -2281, -549, -1152, -1936, 780, -3916, -1306, -1405, -1886, 549, -3835, -2180, -1917, -1818, -387, -2792, -3422, -2357, -2055, -2215, -2501, -6241, -2373, -2782, -4704, -3033, -8393, -2033, -4217, -6929, -4108, -6246, -1681, -8068, -11620, -5597, -7465, -1732, -6024, -6720, -8259, -13971, -2807, -3209, -4535, -10705, -11232, -6537, -2961, -4340, -6189, -8549, -6525, -4973, -5306, -4475, -6917, -3450, -8409, -6693, -4114, -8079, -3555, -4950, -7082, -4463, -11262, -6691, -4196, -5694, -5222, -4124, -9836, -4855, -3625, -6954, -1699, -5164, -4765, -1928, -14286, -663, -4169, -4080, -956, -6668, -472, -3927, -4223, -808, -4050, -927, -4054, -4659, -1518, -3273, -2043, -4659, -4806, -2857, -3485, -4026, -5012, -5753, -3289, -4506, -7114, -4157, -8458, -2383, -6814, -8776, -3046, -10124, -1919, -9729, -8006, -2438, -8481, -2476, -7223, -8942, -2651, -8119, -4495, -6713, -10699, -3729, -9751, -9391, -8462, -9084, -4869, -12085, -14189, -11420, -7217, -4537, -9290, -6958, -10445, -5602, -3890, -8713, -2884, -7885, -5075, -4081, -6824, -993, -5433, -6297, -5445, -6813, -581, -4298, -11537, -8013, -10279, -1352, -4068, -9035, 8985, 6518, 7563, 8877, 9046, 8234, 6594, 7027, 8347, 8532, 6331, 5677, 5772, 6952, 6924, 5024, 981, 5111, 5260, 4061, 3806, 2037, 5742, 3558, 440, 967, 4386, 6629, 2409, -783, -883, 3656, 7114, 1283, -349, 2952, 2413, 7141, -2137, -67, 5129, 3158, 6509, -1857, 1100, 5734, 3958, 4491, -2596, 2334, 5404, 4255, -814, -4981, 2856, 5080, 4016, 3871, 763, 3031, 5362, 3360, 5969, 2332, 2827, 5563, 3133, 6510, 2666, 2052, 5428, 3497, 6210, 2579, 1018, 5290, 3136, 5414, 2374, 388, 5181, 962, 4383, 1588, 226, 4666, -8481, 3193, -1021, -410, 3159, -2200, 1715, -119, -2705, -842, -2369, 539, 2781, -10846, -1682, -8065, 649, 3237, -2652, 2167, -6821, 272, 1411, -187, 3126, -4139, -1393, -1419, 809, 2593, -188, -2666, 1660, 526, 549, 1751, -2642, 2880, -2175, -3542, 2355, -1774, 3630, -3843, -7162, 2117, -33, 4132, 594, -10058, 1187, 935, 3783, 1152, -5997, -1100, 903, 2279, -742, -2986, -9530, -343, -685, -1943, -1738, -800, -4534, -5764, -203, -1451, 1532, -3386, -6807, -385, -1934, 2482, 154, -5475, -748, -492, 2676, 1176, -4795, -405, 1741, 2257, 901, -4046, -832, 3050, 1426, -528, -2648, -2209, 3695, 768, -3119, -495, -2869, 3888, 478, -7138, 1492, -1466, 3557, -528, -7174, 2892, -1106, 2438, -2650, -3884, 3745, -2364, -20, -2147, -2024, 4007, -3977, -5755, -2340, -122, 3501, -3717, -2271, -6275, 838, 1949, -2174, -28, -2191, 445, -1442, -698, 540, -615, -1399, -6006, -537, -92, -1203, -4365, -1382, -2154, -1656, -2113, -3715, -389, -7872, -2267, -1547, -2291, -928, -3354, -1762, -1495, -2020, -2464, -599, -1845, -2575, -2336, -4021, 372, -2314, -4497, -2622, -4010, 282, -2952, -6128, -2952, -3405, -535, -3805, -5759, -4534, -3411, -1497, -3776, -4343, -9672, -3453, -2263, -3392, -3115, -3355, -2792, -3364, -4273, -2577, -1414, -2260, -5289, -5577, -3117, -1496, -2341, -8298, -4319, -5022, -3242, -2912, -10586, -3495, -6735, -4189, -3526, -8272, -2519, -5886, -3111, -3694, -6397, -1252, -4882, -4093, -3443, -5273, -804, -4317, -8079, -3204, -5308, -1356, -5169, -5436, -3218, -6950, -2610, -7845, -5021, -3555, -7503, -3948, -7689, -5972, -4387, -6617, -5066, -6911, -3284, -5760, -8977, -5918, -6541, -1693, -5689, -10069, -5800, -5469, -1504, -3599, -6215, -5202, -4553, -2416, -2353, -5588, -4994, -3747, -4273, -2588, -5373, -5430, -3370, -6208, -5044, -4717, -6317, -4029, -6065, -5950, -4743, -6737, -6835, -5706, -3061, -5988, -6782, -8754, -7073, -2705, -8530, -6424, -4552, -7345, -4113, -12075, -5777, -3244, -3463, -6001, -15697, -6055, -2947, -1629, -6014, -9874, -7633, -2862, -1191, -6825, -7375, -9082, -2771, -1903, -6828, -6079, -12057, -3123, -3750, -5684, -5858, 7254, 3780, 5352, 8324, 7066, 7171, 3086, 5094, 7895, 6213, 6727, 851, 4354, 6526, 3843, 5390, -2087, 3193, 4117, 3207, 2262, -2314, 1654, 2565, 3126, 2013, 745, -46, 3361, 1325, 4042, 3062, -104, 3836, 2767, 4176, 3288, 1227, 4010, 3783, 3360, 1017, 1727, 3485, 2176, 2138, -2184, 1294, 1347, -6664, 531, 1541, -80, -1763, 1195, -1041, 2582, -3103, -380, 1419, -1732, 2633, 1146, -1351, 1509, -3214, 1956, 3383, 707, 3109, -4593, 393, 3552, 2910, 2673, 1140, -2294, 1842, 3182, 2083, 3269, -1350, -478, 1649, 4232, 3696, 858, 1509, -3165, 5058, 2523, 1699, 2458, -4177, 4411, -2484, 2717, 2408, -2617, 2814, 58, 3860, 2037, -6038, 2143, 3316, 4150, 1901, -3622, 2863, 4118, 3282, 2190, -1326, 3523, 3616, 979, 2192, -1138, 3638, 1956, -3769, 1246, -1925, 2589, -1005, -4772, -664, -3082, 144, -4808, -5487, -1236, -3921, 1631, -3920, -4314, -289, -1963, 3125, -997, -878, 536, 568, 3125, 1100, -87, 1132, 2375, 2481, 2173, -588, 916, 3384, 1815, 2460, -1252, -670, 3538, 1108, 2340, -1871, -4154, 2703, 850, 1950, -2672, -4339, 499, 1269, 1169, -3861, -2132, -4124, 1562, 169, -6132, -261, -2596, 1437, -843, -2396, 722, -781, 871, -1632, -1151, 484, -292, -168, -807, -2771, -188, -270, -1242, 784, -14377, 384, -752, -1214, 1457, -2334, 652, -2146, -1095, 669, -88, -423, -4151, -2159, -1953, 663, -2218, -4541, -2894, -2170, 348, -3093, -5154, -892, -404, -488, -3708, -4906, 109, -283, -802, -2311, -3105, -386, -1719, -713, -1343, -2995, -2943, -6075, -972, -1948, -5119, -4035, -6812, -2209, -3295, -11489, -1136, -4506, -5033, -2868, -7918, -847, -5278, -7842, -2304, -3639, -2461, -4408, -11924, -2104, -1206, -4600, -2108, -7483, -1639, -277, -4610, -1091, -4659, -1884, -464, -3838, -1260, -5409, -3828, -1361, -2961, -2613, -11108, -7331, -2289, -3521, -5412, -5253, -5834, -2362, -7268, -7961, -3699, -5927, -1680, -7667, -6690, -4054, -7101, -1061, -4319, -6204, -4494, -5229, -805, -4567, -6323, -4150, -3547, -893, -8945, -6568, -4867, -2577, -1066, -7158, -7404, -8847, -2021, -890, -4696, -10328, -8292, -2006, -644, -5885, -7639, -5119, -2603, -1086, -10119, -4971, -4890, -3480, -2684, -5412, -4289, -6038, -4012, -5439, -4182, -4826, -6486, -4081, -6591, -4286, -6108, -5920, -4195, -6369, -4245, -8101, -5814, -4660, -6888, -4094, -8298, -5812, -5539, -7734, -4961, -5751, -5919, -6810, -8659, -8082, -4912, -6634, -7885, -10439, -10783, -5265, -8314, -7614, -11534, -7287, -5005, -10458, -6328, -7728, -6504, -3880, -9864, -5156, -6502, -6430, -3550, -9472, -4517, -7652, -6597, -4643, -8696, -4595, -11083, -7127, -7788, -6724, -5271, -8046, -8521, -10178, -5892, -5092, -6057, -10780, -9513, -5852, -2958, -4130, -5138, -9591, -4239, -4771, -4595, -3537, -7593, -4988, -6791, -6457, -3617, -5186, -9184, -8984, -9752, -5332, -3757, -9695, -8023, -9904, -8192, -3567, -7496, -5663, -6636, -10251, -4988, -10139, -4265, -5209, -8259, -7312, -10026, -4064, -4842, -5919, -6798, -9178, -5491, -4279, -5506, -4718, -6877, -7453, -4436, -4938, -5641, -10793, -7051, -8165, -5146, -6237, -5783, -3706, -5657, -6567, -6163, -7552, -5332, -4544, -7934, -4428, -7473, -7132, -2816, -3669, -7263, -5272, -6182, -5161, -8287, 1297, 1380, 382, 427, 1207, -5695, -8279, -4121, -8316, -6680, 8561, 8618, 8700, 8553, 8437, 13004, 13007, 12983, 12916, 12893, 15159, 15134, 15101, 15057, 15049, 15814, 15765, 15745, 15709, 15700, 15123, 15045, 15056, 15018, 15001, 12934, 12800, 12884, 12824, 12786, 8481, 8155, 8507, 8337, 8234, -6212, -3159, -3672, -8783, -6067, 355, 1573, 140, 692, 704, -6870, -5118, -3656, -13381, -7976, -3363, -8489, -2432, -4041, -3085, -13187, -6128, -4945, -14447, -7311, -7663, -3928, -4995, -7782, -6564, -11356, -5002, -6850, -10812, -11615, -6916, -5388, -8674, -8337, -12006, -7994, -4573, -8011, -5441, -11762, -8180, -4139, -6462, -4421, -16667, -10089, -4886, -7481, -4405, -7607, -13750, -5921, -8591, -4365, -5118, -9873, -7548, -9934, -5196, -5328, -8781, -10656, -14920, -6792, -7727, -9037, -11447, -11389, -8594, -14847, -9884, -10947, -8958, -9617, -6934, -9289, -10973, -8780, -9326, -5223, -7221, -8742, -8512, -9119, -5599, -6083, -6824, -7067, -9787, -7035, -6014, -5755, -6035, -12388, -7980, -7264, -5557, -6080, -13525, -8373, -10795, -6081, -7427, -10104, -7020, -11727, -7375, -11093, -7431, -5927, -8775, -8995, -13316, -5955, -5824, -8544, -9358, -9168, -5567, -6647, -11194, -9332, -7582, -5880, -8291, -12999, -10338, -6506, -6668, -9652, -8827, -10795, -6129, -8010, -10285, -7865, -9139, -6920, -9528, -11676, -7471, -8425, -8858, -9571, -11366, -7427, -8712, -10255, -9618, -10512, -8751, -8954, -9471, -11316, -11523, -14983, -9112, -8722, -16038, -13343, -10452, -10208, -9099, -11641, -9484, -7683, -10772, -11344, -9792, -7278, -7034, -11116, -15446, -10288, -6693, -7359, -16187, -12218, -11828, -7788, -7894, -9483, -11724, -10789, -12571, -8252, -6930, -13333, -10655, -11221, -8965, -6238, -12123, -12075, -8249, -10092, -6645, -9684, -12421, -8088, -9963, -7965, -8294, -11999, -9632, -8837, -10239, -7443, -12000, -13315, -8706, -11505, -7439, -12416, -14043, -10646, -10071, -8528, -13571, -10865, -15017, -8877, -10497, -11921, -8804, -11247, -7730, -13069, -10791, -7478, -11828, -6398, -15423, -12001, -7192, -20448, -5201, -16101, -13201, -8376, -13641, -4585, -14289, -9748, -13001, -13041, -4645, -11616, -8328, -11523, -14627, -5170, -11110, -8451, -8356, -13502, -5950, -12049, -9883, -7761, -10373, -7152, -12526, -12659, -8455, -8713, -9156, -11939, -16142, -9589, -8459, -12138, -11687, -14965, -9961, -10498, -4366, -6670, -6268, -6777, -7229, -6131, -9281, -8240, -7699, -8929, -7196, -10164, -9029, -7444, -11207, -7603, -9629, -8669, -5848, -6033, -7414, -11634, -7184, -5213, -4398, -8612, -8062, -6308, -5370, -3304, -13810, -6177, -7408, -4579, -2825, -7811, -5579, -7973, -3825, -3546, -6430, -4992, -8108, -3809, -4781, -4527, -4429, -6506, -4269, -4491, -4848, -3487, -4891, -7768, -3571, -7588, -2584, -3465, -8846, -7026, -5220, -5205, -4060, -11604, -5445, -2622, -4630, -3540, -3661, -13629, -16253, -13092, -4810, -7932, 231, 618, -82, 543, 843, -6248, -7054, -4917, -3788, -8231, 8605, 8622, 8675, 8654, 8498, 12929, 12970, 12956, 12954, 12918, 15061, 15099, 15067, 15070, 15063, 15710, 15741, 15699, 15705, 15706, 15022, 15042, 14988, 14999, 15003, 12839, 12842, 12761, 12787, 12794, 8398, 8357, 8181, 8271, 8320, -6355, -9827, -5114, -8031, -11445, 742, 449, 897, 548, -492, -6196, -9566, -10589, -7494, -5073, -8525, -3144, -3699, -3026, -2223, -5070, -7672, -10938, -5874, -3889, -3862, -8293, -8123, -6864, -3393, -7232, -5562, -14238, -6677, -5029, -8078, -4318, -11472, -7169, -5990, -6359, -5438, -12955, -9248, -7282, -4699, -6061, -8298, -7138, -7975, -4437, -5255, -4977, -7199, -7408, -4404, -5040, -4346, -6498, -8164, -4424, -5932, -5922, -6287, -13094, -5022, -6947, -8673, -7353, -11799, -6385, -7265, -8889, -6892, -9465, -7244, -8190, -8641, -5854, -8326, -7533, -11441, -8925, -6478, -7704, -8121, -12430, -8424, -8580, -8303, -8555, -9459, -7952, -11706, -10874, -8801, -7781, -7932, -11601, -11746, -9392, -6681, -8702, -9492, -10771, -8897, -6269, -11134, -7989, -10751, -7531, -6453, -13250, -7211, -8926, -7404, -7610, -10312, -7486, -7607, -8600, -12793, -8181, -8674, -7479, -10202, -9162, -6921, -8904, -7697, -11286, -6098, -6608, -7722, -7804, -11937, -5398, -6998, -6592, -8510, -11931, -6006, -7656, -5732, -10168, -11643, -7700, -7865, -5153, -9670, -11404, -9945, -7621, -4734, -7718, -11938, -10592, -7930, -4469, -6955, -14370, -10031, -9183, -4556, -7329, -15667, -10284, -10498, -5050, -8892, -12373, -11084, -10118, -5802, -11839, -10744, -9393, -8932, -6557, -10599, -9939, -8174, -8555, -6929, -8379, -9147, -8371, -9724, -6772, -7539, -8646, -9213, -12563, -6454, -7698, -9055, -8331, -11230, -6225, -8717, -10672, -6809, -10830, -6241, -10608, -14785, -6331, -14765, -6812, -12383, -14279, -7241, -12980, -8388, -10530, -11516, -10115, -9969, -11681, -8633, -11517, -17696, -8967, -17098, -7730, -9999, -15671, -8469, -13164, -7734, -8058, -16219, -8806, -10957, -8309, -7622, -12298, -10108, -10766, -8402, -8250, -10221, -11010, -13232, -7994, -8410, -9360, -11065, -14546, -7912, -7768, -9280, -10873, -10923, -7989, -7800, -10287, -9905, -10087, -8439, -9129, -12060, -9325, -10332, -10265, -12743, -9949, -9270, -9962, -11686, -19639, -8180, -9033, -9152, -9150, -14519, -7532, -8746, -9194, -8408, -10822, -6541, -4087, -5366, -7217, -12242, -8318, -3539, -5595, -5565, -10054, -10115, -3416, -6678, -5715, -9487, -10487, -3463, -9138, -5286, -11194, -7805, -3598, -8649, -4087, -14458, -5912, -3513, -5294, -3330, -15491, -5595, -2995, -4509, -2842, -9703, -5078, -2744, -5044, -2878, -6441, -4684, -3510, -5504, -3700, -5324, -5093, -4428, -5770, -3850, -7746, -5534, -4368, -9431, -3672, -6965, -5120, -3532, -8148, -3980, -5835, -12972, -4140, -6914, -7836, -3209, -4326, -4421, -2653, -4978, -4388, -5867, -4333, -6509, -8827, 759, 1307, 1420, -92, 441, -7569, -6729, -8428, -3816, -5727, 8547, 8521, 8509, 8797, 8689, 12911, 12937, 12918, 13017, 12962, 15045, 15072, 15054, 15101, 15063, 15687, 15707, 15695, 15716, 15688, 14985, 14996, 14991, 14996, 14973, 12773, 12778, 12783, 12769, 12751, 8257, 8274, 8289, 8231, 8207, -5729, -13222, -9847, -7725, -6606, 365, -216, 347, 366, 774, -5794, -4154, -13970, -10100, -11214, -3024, -1610, -5056, -3311, -4302, -8556, -5486, -9925, -10494, -10449, -8816, -15377, -7035, -9377, -10897, -9692, -6966, -10351, -7962, -7623, -6415, -5614, -6263, -6224, -6176, -8085, -6004, -8928, -7974, -8482, -8961, -6683, -15713, -8733, -11044, -8909, -9524, -9595, -6530, -10027, -9220, -16761, -7156, -6052, -9278, -8183, -10191, -6519, -8056, -10499, -7503, -8314, -6524, -9726, -8568, -7912, -7454, -6168, -7788, -6564, -8006, -7323, -6360, -6623, -5660, -7513, -8958, -7956, -6270, -5558, -7624, -12761, -8830, -6275, -5664, -9072, -13250, -8080, -6211, -5807, -11441, -10268, -8066, -6481, -6255, -11688, -8512, -8791, -7602, -6731, -9345, -7804, -8950, -9074, -6544, -7603, -7631, -7568, -9252, -6544, -6215, -7159, -6531, -8562, -7341, -5194, -6266, -6163, -8140, -8458, -4865, -5520, -6092, -7987, -7760, -5326, -5329, -6243, -7926, -6852, -6405, -5870, -6721, -8345, -7595, -7663, -7234, -7119, -10125, -10775, -8350, -8534, -7286, -16410, -8787, -7965, -7840, -7968, -12117, -7281, -7110, -7247, -9360, -9899, -8670, -6584, -7114, -10510, -9248, -13548, -6732, -6288, -10753, -9136, -8383, -7539, -5229, -10635, -9847, -7519, -8798, -4756, -9004, -10133, -9215, -10716, -5047, -7250, -7926, -15045, -11737, -6079, -6478, -6366, -13869, -9279, -7261, -6801, -6041, -12884, -8079, -7599, -8272, -7054, -12862, -8067, -7855, -10268, -10148, -11724, -8568, -8570, -10879, -14031, -10273, -8699, -9357, -11814, -9495, -8848, -8366, -10098, -12661, -8400, -7876, -8351, -10997, -11791, -8652, -7701, -8922, -10359, -10201, -9356, -8575, -9593, -9505, -8288, -9822, -11194, -10080, -11126, -7323, -10529, -21742, -10828, -10949, -7205, -11905, -11172, -12073, -7210, -7450, -13675, -9491, -14562, -6110, -8045, -13884, -9622, -13397, -6723, -9438, -11220, -11368, -11545, -9052, -12156, -10030, -16389, -12288, -12561, -18890, -10493, -15268, -16791, -11629, -15410, -12913, -14502, -14921, -11217, -12042, -19888, -28647, 13098, 8550, 12481, 11510, 6595, 12477, 8828, 11738, 10975, 6030, 10405, 8846, 9290, 9300, 4418, 5407, 8596, 4699, 6340, 3498, 4144, 8868, 3899, 2446, 4495, 6787, 8970, 2932, 1036, 4904, 6608, 8465, 1355, 3923, 4740, 4907, 7665, 1149, 4657, 4591, 551, 6910, 744, 2513, 4346, 634, 6196, 1842, -279, 3940, 3736, 5306, 2460, 4698, 3741, 4214, 4093, 2261, 6028, 3943, 2999, 3252, 2051, 5861, 4558, -1126, 3221, 2513, 4490, 5250, -2272, 2371, 2501, 2731, 5767, 1238, 375, 1447, 3380, 5850, 1900, 2377, 1045, 3946, 5011, 2334, 3950, 2051, 3233, 2580, 3282, 3982, 2613, 1159, 159, 3710, 2869, 2481, 487, 1210, 3661, 1243, 1716, 2588, -657, 4677, 1926, -421, 3542, -546, 5690, 3141, -7300, 3727, 2018, 5486, 2751, 1503, 3443, 2021, 4042, 1177, 3537, 2839, 305, 2858, 2208, 3935, 2313, -2395, 2622, 2907, 3506, 1766, -2201, 820, 1286, 2877, 816, -25, -2138, -2230, 2460, -253, 1158, -185, 2089, 2181, -948, 1834, -429, 3619, 1837, -1815, 2181, -2963, 3555, 1253, -3382, 1436, -7497, 2318, -221, -1989, -2519, -3937, 466, -5658, -553, -383, 130, 109, -2147, -554, 2605, 1478, 993, 944, -327, 2950, 1038, 1962, 1665, 621, 1470, -1293, 2675, 1147, 637, -1902, -6527, 2557, -113, -766, -2756, -2414, 1072, -1280, -3066, -1732, 176, -407, -1687, -1358, -1275, 1793, 1532, -1903, 714, -738, 2727, 2283, -2128, 1424, -1013, 2830, 1480, -1826, 1085, -2187, 1872, -748, -1223, 504, -1724, -540, -3577, -1331, 302, -372, -3290, -3077, -2456, -212, 453, -1665, -2179, -2590, -1244, 769, -958, -2758, -1194, -2220, 646, -1298, -5466, -206, -3085, 298, -2484, -13396, 244, -3976, -448, -5072, -6577, 67, -3844, -1491, -15234, -3075, -866, -2785, -1116, -7562, -1541, -2665, -2528, -294, -7910, -1687, -5553, -3298, -160, -10161, -3578, -10016, -3192, -472, -3439, -5625, -9486, -2319, -951, -1201, -4550, -9342, -2459, -1431, -458, -4420, -6978, -3757, -1541, -854, -3911, -4840, -6298, -1450, -2480, -2853, -3829, -7433, -2031, -5517, -2518, -2354, -5552, -3672, -8558, -2856, -980, -3831, -4039, -6818, -3270, -177, -2357, -3496, -4436, -2980, 111, -1947, -5155, -3473, -2306, -187, -2633, -5752, -3380, -2078, -1182, -3664, -3089, -3429, -2692, -2826, -3918, -2817, -3812, -4573, -4250, -3465, -4590, -5220, -9117, -4231, -3124, -8516, -7993, -11830, -4338, -3576, -11939, -7717, -7077, -4823, -4840, -12315, -4104, -4608, -4103, -4752, -7408, -1875, -3730, -3127, -3489, -5600, -790, -4849, -3237, -3361, -3940, -662, -9472, -4932, -4740, -2668, -1493, -4366, -5298, -7908, -2498, -3603, -2126, -3150, -9119, -3642, -8609, -1767, -2772, -5899, -6106, -6767, -2754, -4208, -3280, -5059, 6690, -8153, 10131, 7048, -919, 6500, -1237, 9535, 7554, 1466, 5763, 2689, 7584, 8134, 2435, 4781, 4620, 3350, 8012, 1830, 5661, 5048, 658, 7105, 778, 6783, 4105, 3704, 5783, -74, 6618, 2593, 4285, 5187, 720, 5186, 2589, 3617, 5421, 1199, 4084, 2423, 1579, 5335, -518, 3879, 2804, -894, 4502, 692, 1989, 4329, 1791, 2961, 3354, 1889, 5035, 3692, 1175, 4608, 4214, 4861, 3955, 476, 5123, 4452, 4207, 2604, 1752, 4949, 2423, 3388, 1864, 3468, 3937, -2942, 2577, 4006, 4407, 2053, 2979, 2078, 5120, 4232, -451, 4465, 1539, 5069, 2721, -2834, 4398, -366, 4056, -1059, -4394, 3825, -1555, 2553, -3650, -4648, 3783, 984, 1518, 220, -2108, 4223, 1564, 1432, 1126, -416, 4287, 927, 1765, 985, -266, 3353, 180, 1171, 1319, -1422, 700, 323, -1087, 2497, -1730, -3577, 986, -4078, 3156, -379, -145, 804, -5633, 3189, 347, 692, -838, -2836, 3184, 591, 372, -3742, -1062, 3175, 815, 775, -4880, -1859, 2491, 1139, 1429, -2167, -6691, 487, 1412, 1693, -494, -3217, -4289, 1377, 2490, -297, -193, -6386, 972, 3451, -977, 1287, -4593, 571, 3687, -1970, 2053, -4635, 521, 3061, -3478, 2249, -3130, 572, 2009, -2216, 1942, -2060, 642, 1428, 431, 1191, -2079, 677, 1189, 1781, 15, -3089, 122, 430, 2063, -996, -816, -1523, -2164, 1360, -575, 1708, -3664, -6231, -374, 368, 2832, -4666, -355, -2308, 889, 2960, -3159, 1093, -1614, 588, 2495, -820, 1216, -287, -1047, 1888, -233, 463, 180, -5792, 1396, -1210, -1699, -456, -5831, 827, -1932, -4360, -1542, -3116, -181, -1081, -1611, -1293, -2754, -1835, -1012, -752, -892, -3009, -3416, -1665, -1331, -1022, -3744, -2976, -2081, -3307, -1008, -5304, -1919, -2296, -6978, -599, -9515, -1543, -2617, -2689, -324, -5503, -2134, -2837, -849, -552, -2105, -4034, -2991, -641, -1427, -987, -9344, -3313, -1334, -3026, -1507, -5572, -3958, -2143, -3900, -4232, -2728, -4591, -2131, -2097, -11497, -1606, -4683, -1188, -635, -4314, -772, -4588, -392, -95, -3143, 504, -5553, -420, -401, -3153, 1642, -12972, -1425, -1560, -3376, 2085, -5530, -3346, -3278, -3476, 1682, -3339, -6006, -4696, -2954, 318, -3931, -8714, -4326, -1709, -2490, -3776, -10887, -1777, -777, -10400, -1479, -12866, -745, -686, -5189, -826, -8513, -1537, -1478, -4025, -1742, -7835, -3353, -2888, -5665, -3837, -6347, -2788, -3952, -17953, -6267, -4056, -2692, -4012, -4997, -8544, -3186, -4337, -4604, -2943, -5270, -3660, -6473, -9815, -2948, -2994, -3978, -7759, -4141, -4830, -1837, -2409, -9588, -365, -8098, -1245, -1044, -7724, 1152, -7450, -1150, -518, -3907, 1373, -5088, -1650, -941, -1635, 501, -2392, -2714, -2385, -835, -1466, -920, -3973, 8763, 8553, -1506, 9043, 5045, 8329, 7818, 4856, 8679, 5189, 7124, 5235, 6475, 7547, 4899, 5539, -2724, 5978, 5518, 3051, 4243, 1960, 3948, 2257, -764, 3257, 2827, 3653, -4867, 3192, 1750, 1546, 4642, -1789, 4821, -503, -1688, 4092, 759, 4430, -877, -10154, 1867, 814, 540, 675, -6481, 292, -964, 1989, 2501, -5274, 1801, -2428, 5702, 3249, 984, 1939, -1699, 6847, 2841, 3143, 325, -4114, 7089, 2120, 3203, -449, -1716, 7005, 1932, 879, 1514, 1679, 6616, 1470, -1494, 1524, 2209, 5686, 383, 1209, -1306, 129, 4051, -917, 274, -2145, -4903, 1958, -3227, -10316, 421, -2018, 2525, -6570, 1371, 165, -7468, 4230, -1425, 3275, -1489, 652, 4741, 506, 3377, -3377, 3027, 3845, 1603, 2098, -3518, 3347, 845, 2379, -1130, -505, 2476, -1302, 2437, -2395, 1055, 832, 1731, 1313, -13, 1424, -1240, 1930, -1705, 66, 1181, -2536, -493, -10492, -1451, 1033, -3839, -1341, -10204, -4003, 1254, -2854, 2599, -4882, -4488, 1321, 1188, 3988, -429, -2851, 976, 3064, 4135, 1534, -2062, 521, 3641, 3510, 2383, -2765, 362, 3398, 2477, 2512, -4557, 551, 2803, 1501, 1934, -2537, 731, 2299, 1677, 334, -1009, 638, 1833, 3102, -2805, -1109, 447, 969, 4139, -2513, -2382, 332, 160, 4254, -556, -4855, 342, 1225, 3384, 230, -9011, 901, 2469, 1469, 344, -1342, 1682, 2800, -1616, -299, 1071, 1871, 2211, -4908, -1796, 1832, 1146, 841, -4058, -3723, 1510, -467, -884, -1918, -4119, 501, -1711, -2314, -531, -2890, -225, -1369, -3129, -539, -2156, -60, -1479, -3522, -2704, -2097, -308, -2167, -4943, -4489, -2310, -2024, -1823, -6980, -1326, -2668, -4405, -951, -3549, -759, -3620, -2580, -708, -1778, -1286, -4578, -2603, -1275, -1417, -1385, -4056, -6586, -2563, -2143, -1543, -3927, -5338, -3925, -3430, -2858, -3746, -2880, -4848, -3057, -6455, -3291, -3926, -5108, -1669, -7064, -3807, -11714, -3433, -786, -2551, -3780, -5750, -2579, -553, -530, -2358, -3964, -3609, -1075, 313, -1908, -4017, -7855, -2455, 274, -2862, -4266, -6328, -4246, -274, -4876, -3763, -3283, -5502, -747, -4153, -2845, -1491, -8382, -1394, -2877, -2209, -403, -9169, -2948, -2452, -2235, -95, -4587, -3623, -1834, -3028, -594, -2742, -2108, -1247, -4172, -2123, -1891, -1002, -1352, -4534, -5646, -1920, -289, -2096, -4388, -7798, -3139, -214, -3092, -5273, -5865, -6345, -1249, -3905, -8090, -9013, -7257, -4051, -3610, -4638, -7809, -5399, -7985, -2443, -2722, -4250, -5762, -4407, -1562, -2710, -3316, -6933, -2448, -1343, -3403, -2966, -9019, -1554, -1776, -3475, -3180, -8528, -1840, -2636, -4344, -4117, -2747, -3535, -3723, -9379, -4126, -312, -3640, -5202, -6598, -3572, 711, -1680, -6312, -3807, -3978, 831, -1188, -4245, -4310, -7584, -1936, -2416, -3598, -3759, -6397, -1902, -1112, -4363, -2385, -4368, -2542, -971, -7739, -1412, -4526, -2295, -1956, -5969, -909, -9751, -1952, -3951, -3203, -1013, -5079, -2482, -5007, -2823, -1841, -2115, -3485, -3893, -4508, -3042, -1813, -3944, -2476, -8390, -3065, -3524, -3411, -1102, -5568, -2684, -5474, -2825, -289, -5226, -3652, -2696, -2998, -310, -5345, -8172, -1250, -4284, -1246, -3334, -6708, -857, -7354, -2712, -2274, -3151, -1019, -9777, -2957, -2140, -2087, -1432, -5676, -2471, -2637, -2178, -2087, -3877, -2453, -4159, -3341, -3348, -3197, -2388, -7626, -5980, -5700, -3484, -2026, -4123, -5319, -5244, -4475, -1800, -1513, -2944, -2875, -4371, -1973, -696, -2443, -2122, -3853, -2977, -1062, -3546, -2808, -4503, -5683, -1769, -6391, -4870, -4615, -6658, -1760, -9873, -6902, -2950, -4382, -1757, -8724, -7033, -1944, -4151, -2451, -6731, -8317, -1880, -5179, -3833, -5847, -8860, -2768, -5707, -5330, -5913, -6610, -4725, -4401, -5875, -6154, -6022, -5516, -3292, -6049, -6410, -6349, -4202, -2875, -6326, -6422, -5028, -3904, -2945, -6690, -5428, -4164, -4081, -3296, -7285, -3982, -5411, -4086, -4066, -7589, -3160, -9155, -4876, -6195, -8635, -3481, -6154, -7075, -13717, -17795, -5003, -5407, -6101, -4434, -6576, -5973, -6237, -4436, -2085, -3952, -5654, -5689, -4266, -1523, -3278, -7182, -4895, -5054, -2485, -4046, -8509, -5342, -6065, -5898, -5987, -3994, -6742, -6265, -7377, -5848, -2032, -6876, -4901, -3902, -4456, -1474, -5497, -3380, -3330, -4201, -2127, -4147, -2510, -4583, -4967, -4416, -3244, -1952, -8653, -6811, -11506, -3228, -1339, -6706, -10673, -7462, -4530, -996, -4300, -9813, -5660, -7329, -1301, -3779, -7764, -4954, -5833, -2200, -4394, -8093, -4546, -4186, -3206, -5595, -9355, -4807, -4028, -4239, -6176, -8076, -5462, -4511, -6117, -5945, -6543, -5732, -4528, -9712, -5220, -5844, -5094, -4086, -9797, -4710, -5940, -3813, -4005, -6182, -4521, -7039, -3016, -4075, -4228, -3924, -8014, -2996, -3576, -3577, -3383, -6866, -3434, -3182, -3886, -3540, -6838, -3964, -3752, -4418, -4241, -8312, -4467, -5897, -4328, -4970, -7845, -4810, -10414, -4067, -5665, -7341, -5217, -8887, -4270, -6873, -8852, -6348, -9758, -5437, -10058, -9898, -8191, -11707, -8987, -10901, -9673, -6973, -7642, -9459, -6637, -15261, -6045, -7429, -5868, -5225, -6272, -7219, -10226, -4687, -5036, -3421, -10001, -13849, -4330, -5559, -2544, -8478, -12205, -4389, -6394, -3113, -7046, -11090, -4939, -7445, -5228, -6198, -9975, -6280, -9031, -9711, -5579, -11368, -6788, -10330, -11091, -5669, -10241, -4890, -8679, -8822, -6936, -7734, -3785, -6695, -7786, -7611, -6787, -3772, -5455, -7664, -6296, -6440, -4766, -5136, -8690, -6163, -5953, -6939, -6212, -9519, -7597, -5168, -8792, -10846, -8362, -11220, -4762, -7115, -7982, -8059, -14884, -5349, -6460, -5340, -4174, -1237, -4037, -530, -4954, -4174, -2522, -3614, -994, -6100, -2920, -3954, -2632, -2247, -9287, -1616, -4426, -2914, -4583, -5939, -845, -4044, -3528, -6908, -2561, -797, -4028, -2921, -4638, -1136, -1577, -4795, -2614, -3579, -1038, -3496, -5431, -3322, -3708, -2270, -7766, -4628, -3843, -4251, -5138, -7506, -3381, -3110, -4437, -7679, -4581, -2569, -2639, -4356, -7414, -3575, -2247, -2931, -4870, -6583, -3313, -2108, -3925, -6622, -4064, -3390, -1943, -5490, -7479, -2462, -3729, -1799, -7472, -5139, -1960, -4159, -1785, -11648, -3484, -2290, -4479, -1986, -10230, -2910, -2944, -5338, -2099, -6642, -4165, -4211, -8715, -1448, -5782, -8041, -8232, -8483, -722, -5205, -3221, -5106, -4944, -913, -4297, -1544, -3085, -3364, -2204, -3838, -1820, -3118, -1824, -2690, -3507, -4098, -3537, -968, -1757, -2774, -21301, -3335, -1385, -1588, -1829, -4718, -2810, -3704, -1814, -1186, -3376, -2211, -21827, -1887, -1290, -4445, -2342, -4557, -2236, -2360, -8339, -3652, -3064, -2763, -3372, -6379, -6009, -3624, -2998, -2490, -4106, -8994, -6324, -3087, -2093, -4128, -13751, -9152, -2466, -3083, -7281, -11801, -4567, -1805, -4833, -8001, -10322, -3041, -2281, -3630, -4067, -9236, -3017, -4560, -1911, -3684, -8263, -4517, -10479, -1119, -5675, -6364, -10327, -20358, -1023, -10732, -4767, -6247, -8368, -1528, -4746, -4216, -2983, -4246, -2913, -2574, -4841, -1884, -2734, -6145, -1727, -7198, -2100, -2697, -11135, -1772, -7530, -3580, -3827, -7508, -2708, -4040, -6147, -6024, -7296, -4290, -2445, -7961, -8740, -5872, -4995, -2092, -7900, -10261, -4057, -5117, -2828, -5617, -9008, -3259, -6224, -4583, -4048, -7363, -3309, -7746, -6672, -3700, -7212, -4105, -7622, -9777, -3554, -8676, -6131, -6578, -5873, -2582, -10892, -12501, -5608, -2886, -1768, -7949, -6930, -5185, -2165, -1734, -4853, -4810, -5409, -3225, -2563, -3271, -4393, -6393, -6190, -4328, -2921, -4492, -5464, -6662, -6721, -3605, -4504, -2806, -5473, -7027, -5113, -4566, -1484, -5975, -6032, -6411, -5262, -1418, -7516, -5429, -5497, -7180, -2201, -8448, -5025, -4215, -8562, -2727, -7362, -4902, -3800, -7443, -2685, -6053, -5415, -4525, -7229, -3456, -5082, -6395, -6904, -6703, -5888, -4365, -6522, -9974, -5301, -7193, -3975, -5716, -6555, -4081, -6234, -4262, -4815, -4722, -3544, -8030, -5932, -4538, -3835, -4174, -10042, -12196, -5802, -3681, -7210, -5852, -8365, -11229, -4208, -10922, -4575, -6589, -6415, -5101, -5875, -4948, -7750, -4057, -6052, -5357, -6997, -11230, -3570, -7159, -6148, -12133, -7698, -3994, -8878, -6703, -11760, -4551, -4813, -13831, -7419, -7405, -2793, -5913, -12081, -9096, -5796, -2280, -7953, -9445, -8924, -5801, -2982, -14337, -9974, -7061, -6966, -4944, -8875, -10837, -5828, -7896, -8018, -6489, -8304, -5412, -7048, -8014, -6504, -6799, -5686, -6278, -6303, -8279, -6485, -6170, -6540, -5936, -5547, -3390, -4884, 313, -2275, -5205, -3825, -4419, -712, -6002, -6433, -4252, -3189, -2211, -7314, -9619, -4710, -2507, -3601, -3322, -6767, -6094, -2362, -3490, -2405, -4586, -10020, -2379, -3266, -2906, -3675, -10631, -2392, -4206, -4625, -3173, -8286, -2611, -5431, -5448, -2849, -8566, -3250, -4016, -2558, -2961, -7528, -4419, -2752, -883, -4098, -5385, -6192, -2356, -731, -8262, -3910, -8129, -2542, -2219, -5083, -2952, -5691, -3190, -5673, -1978, -2423, -2901, -4317, -4986, -924, -2528, -1423, -5413, -3747, -850, -3729, -1128, -4775, -3680, -1003, -7519, -2264, -3471, -3324, -746, -8795, -6607, -2657, -2284, -461, -4480, -6069, -2310, -1272, -796, -3395, -3008, -2363, -836, -1808, -3736, -3082, -2986, -1026, -2795, -5576, -5211, -4724, -1269, -3337, -11530, -5590, -9675, -898, -3985, -7161, -3814, -7127, -399, -4453, -4459, -3717, -4424, -272, -4145, -3612, -4997, -3564, -698, -3620, -3438, -7013, -3593, -2199, -3800, -3317, -8395, -4469, -7607, -5528, -3399, -7366, -5659, -4618, -14263, -3532, -5910, -5974, -1672, -5954, -2692, -4889, -4994, -1074, -3646, -1954, -3507, -3351, -1526, -3297, -2598, -2770, -2700, -2589, -3889, -6451, -3521, -3070, -4159, -4155, -5944, -6990, -3590, -6149, -3818, -2166, -9168, -4215, -7917, -3963, -1372, -4878, -6426, -7147, -4834, -2278, -3570, -10798, -4734, -5753, -5726, -2839, -6221, -3579, -5617, -9161, -2446, -4039, -3903, -4882, -4570, -2575, -2848, -5119, -4334, -4000, -2973, -2471, -5503, -4278, -4478, -2937, -2861, -6736, -4598, -5032, -2978, -4320, -9367, -4628, -6017, -4192, -10281, -4014, -4672, -8068, -5377, -5145, -1725, -5761, -10937, -3245, -2092, -688, -4328, -10058, -1908, -1239, -363, -1743, -6145, -1607, -1582, -580, -715, -4074, -2175, -2512, -1221, -956, -3665, -3863, -3144, -2089, -1971, -5056, -4436, -3419, -2881, -2545, -9684, -2025, -3608, -3396, -2396, -12097, -994, -3362, -3588, -2442, -10976, -1438, -2872, -3295, -3008, -11353, -3386, -2753, -2876, -4564, -8431, -7063, -3675, -2700, -9427, -7128, -8582, -6544, -2614, -7480, -6192, -8026, -6297, -2497, -4253, -4874, -8420, -3969, -2731, -3707, -3623, -8860, -3467, -4105, -4764, -2854, -8585, -3975, -7415, -5983, -2595, -7169, -4972, -5572, -5020, -2861, -5735, -6013, -3911, -4773, -3655, -5287, -7482, -3890, -5173, -4776, -6153, -10354, -4815, -4027, -5856, -7702, -8618, -6613, -2938, -6685, -6564, -6505, -8551, -3061, -7454, -5335, -5890, -6235, -4488, -8389, -5273, -6417, -4250, -6685, -7292, -6254, -8490, -3528, -7534, -5091, -8071, -16270, -3670, -8866, -3933, -8751, -10555, -4230, -13174, -3898, -7635, -7917, -5234, -11510, -4896, -6785, -6733, -6968, -9992, -6789, -6312, -6186, -6140, -10876, -9400, -6279, -6354, -4174, -14447, -13489, -6691, -7307, -3387, -9865, -9254, -7337, -6874, -3650, -8955, -6250, -8217, -5054, -4855, 6703, 3204, 1586, 6835, -3668, 6345, 2720, 1801, 6394, -1134, 5365, 1177, 1741, 5107, 1061, 4119, -2197, 898, 3222, 2289, 3167, -8615, 284, 1169, 2993, 2409, -2027, 1073, -2036, 3106, 1086, -1293, 1938, -5374, 2331, 547, -1753, 2523, 5, 797, 1067, -24, 2946, 1931, 656, -1071, 1855, 2833, 2952, 2201, 1457, 3108, 1416, 3439, 3749, 4705, 4256, -32, 3213, 5112, 5749, 5414, 2752, 1872, 5989, 5477, 6280, 3819, -160, 6105, 4546, 6504, 2810, 1047, 5312, 3980, 5820, -433, 1945, 3821, 3567, 3844, 2125, 1419, 2976, 2419, -320, 3857, 176, 2403, 1613, 164, 3877, -1456, -24, 2528, 1172, 2732, -3532, -1812, 2889, -517, 1047, -144, -435, 2003, -408, 292, 1904, -883, -362, 1147, -1093, 2728, 1437, -5296, -94, -8915, 2993, 2659, -7021, -10282, 1091, 2931, 1639, -4613, 811, 3232, 2468, -3024, -2828, 2863, 3548, 1460, 1274, 126, 3568, 2711, -394, 3262, 1813, 3683, 1363, -4406, 3223, 2242, 3312, 403, -1225, 1673, 1474, 2497, 23, 1854, -1056, -1611, 1466, 825, 3183, -2861, -3901, 473, 1839, 3504, -5223, 1113, -398, 1868, 3128, -6163, 2229, -1538, 795, 2285, -3406, 1855, -2338, -252, 1237, -3807, 544, -276, -252, 395, -4846, -970, 948, -1082, -25, -2043, -860, 533, -2352, -229, 9, 484, -1634, -993, -505, 1165, 1547, -3511, -590, -974, 1707, 2050, -2970, -2518, -1589, 1697, 2108, -5249, -2631, -2542, 1152, 1867, -7052, -177, -3760, 137, 1291, -3246, -75, -3836, -1175, 229, -3124, -2183, -2316, -2709, -1316, -3948, -6511, -993, -4539, -3187, -2271, -6249, -588, -4778, -5457, -695, -10341, -1169, -3864, -4383, 156, -7273, -2097, -4081, -2309, 567, -4283, -1895, -5611, -1484, 490, -3179, -1638, -6577, -1538, -352, -2336, -2480, -5376, -2014, -2253, -1795, -4154, -4983, -2025, -3769, -2038, -3711, -5141, -1714, -2523, -3799, -2234, -4715, -2128, -1522, -9073, -1593, -3986, -4264, -1285, -7244, -1632, -3726, -5375, -2149, -8677, -1852, -4676, -1688, -4917, -7194, -1826, -8096, -492, -12282, -2964, -1637, -7885, -1091, -6994, -2175, -1556, -5414, -3828, -5926, -3777, -1687, -4540, -20328, -5444, -8621, -1951, -4144, -6359, -4912, -3849, -2310, -4653, -5526, -4968, -2186, -2929, -6903, -5798, -5746, -2091, -4192, -8093, -5356, -6310, -2948, -6581, -5592, -4002, -6308, -4391, -7763, -5412, -2773, -7445, -5002, -6596, -8029, -2051, -14411, -4477, -7266, -10649, -1923, -8147, -4639, -10554, -7352, -2289, -6031, -5873, -13132, -8828, -3032, -6298, -7359, -9153, -7857, -4502, -7934, -7195, -6047, -4379, -7915, -9677, -5741, -4285, -3318, -9178, -9480, -4826, -3693, -3636, -5388, -7589, -5189, -4258, -4850, -4741, -5690, -7230, -6325, -6145, -6763, -4460, -9858, -11254, -6214, 1293, 6143, 1369, 3002, -6919, 2589, 5625, 2395, 2359, 1396, 3514, 3919, 3497, -60, 4035, 2884, 548, 3781, -7328, 5095, 458, -776, 3353, -198, 5134, 590, 749, 2328, 1795, 4407, 3217, 1141, 412, 2568, 3058, 4693, 983, -4580, 2762, 858, 5438, 119, -3118, 2391, -2306, 5534, 1281, -1659, 1589, -3437, 5182, 4135, -72, 1068, -106, 5599, 5719, 3958, 1330, 2715, 6580, 6093, 5937, 1590, 3934, 6784, 5487, 6334, 1391, 3827, 6024, 4268, 5213, 2532, 2476, 4725, 2996, 1936, 4331, -143, 3626, 1903, -1202, 5311, -3511, 2869, 75, 1116, 5583, -4604, 1661, -5912, 358, 5407, -3736, -1659, -312, -3236, 4889, -4575, -6926, 993, -10314, 4077, -4774, -2910, -919, -8073, 3183, -3574, -2594, -1749, -4815, 2386, -4578, -223, 2025, -402, 1379, -3131, 1151, 3552, 1653, -307, -1652, 1588, 4067, 2550, -1863, -2704, 1634, 3913, 2716, 128, -4038, 1601, 3233, 2298, 1743, -976, 1691, 2509, 1212, 2014, 106, 1861, 2459, -545, 910, -530, 1893, 2695, -1881, -2392, -3240, 1653, 2586, -1497, -7493, -4522, 1314, 1810, -577, -1369, -554, 1343, -279, -149, -17, 1383, 1717, -1704, -736, -337, 2342, 1784, 1357, -2468, -1523, 2672, 1083, 2579, -4590, 301, 2526, -625, 2299, -4465, 2389, 1926, -3639, 566, -2154, 3378, 857, -5484, -3344, -534, 3636, -375, -2516, -12965, 58, 3478, -860, -379, -4807, -35, 3069, -38, 1062, -567, -587, 2468, 1059, 1903, 1600, -1397, 1548, 1590, 2101, 2320, -1832, -55, 1443, 1640, 1993, -2134, -1309, 726, 561, 1127, -3168, -521, -312, -1202, 354, -4864, -373, -945, -4005, -663, -6055, -1355, -869, -4117, -2990, -5865, -3041, -902, -2457, -8170, -5027, -4746, -1442, -2935, -10249, -4432, -5016, -2340, -7190, -6067, -4864, -4258, -3037, -6829, -2751, -6363, -3300, -3169, -4239, -1698, -5350, -2072, -3388, -5548, -2701, -3534, -1137, -4792, -7117, -7722, -2995, -814, -8137, -3626, -6399, -3808, -1096, -7043, -2003, -4058, -6258, -1518, -6399, -1569, -4900, -9322, -1486, -6839, -2077, -8802, -7117, -1405, -5116, -3519, -8928, -5047, -1596, -3431, -5787, -5447, -4194, -1928, -2840, -6319, -3920, -4545, -2079, -3631, -4603, -3377, -5533, -1722, -6507, -3148, -3755, -5508, -1590, -10105, -2108, -5016, -5074, -2436, -9812, -1715, -6540, -5372, -4575, -11719, -2270, -6622, -6098, -6740, -5126, -4204, -5991, -7256, -5343, -3221, -8612, -5590, -9812, -4101, -3040, -8594, -5369, -9472, -3783, -4275, -6415, -5323, -8459, -4783, -6485, -5315, -5352, -9788, -9495, -5953, -4822, -5571, -10721, -6150, -5775, -5135, -6381, -10666, -3189, -8294, -6049, -7777, -12603, -2586, -7554, -6878, -8223, -10970, -3410, -5760, -6977, -5866, -9642, -5563, -6499, -6528, -4094, -9282, -9337, -8436, -6019, 6460, 8585, 6506, -1671, 2320, 6263, 7904, 6607, 4638, 4738, 5687, 6070, 6838, 6771, 5155, 4927, 4654, 6804, 7110, 3835, 3991, 3955, 5957, 5941, 436, 2319, 1879, 3752, 2813, -1564, 1025, -2462, 1189, 481, -1290, 1768, -6966, 2144, 1278, -4873, 1698, -2827, 2060, 2646, -3446, 695, -839, 2309, 5169, 1280, 485, -121, 3583, 6523, 3448, 1856, 216, 3940, 6911, 4334, 2638, 242, 2952, 6260, 4036, 2291, -887, -240, 3493, 2322, 858, -4898, -6552, 1023, -1619, -2154, -1399, -694, 5282, -1276, -6278, 670, -750, 6114, 394, -1566, 783, -2170, 5681, -62, -1027, -185, -2775, 5170, -2306, -3586, -1760, -3144, 4729, -7322, -3833, -3287, -1245, 3711, -19766, -589, -3358, -222, 2242, -8093, 27, -3191, -970, 1022, -4243, -1122, -3548, -3359, 209, -3298, -4685, -2986, -5363, -298, -4225, -7646, -1347, -5386, -964, -8173, -6611, -132, -5248, -1823, -6344, -5415, 315, -4457, -999, -2598, -2179, 144, -3868, 105, -1560, -1501, -509, -3549, 279, -2197, -2952, -1794, -3053, -246, -3620, -5376, -3607, -2577, -1222, -2705, -4183, -4144, -3278, -3791, -1762, -2836, -2395, -6206, -5145, -1087, -2115, -305, -1526, -1274, 104, -2627, 818, 929, -498, 781, -4614, 704, 1460, -1142, 253, -4524, -603, 434, -2681, -2192, -2584, -777, -2499, -5398, -5049, -1574, 712, -11590, -2509, -2376, -1586, 1435, -3710, -250, -3423, -1846, 1829, -1418, 701, -2715, -487, 2131, -1248, 1073, 867, 716, 1818, -3331, 1106, 2047, 902, 523, -12523, 682, 1608, 253, -1466, -6181, -499, -528, -912, -1687, -5199, -2605, -6409, -2194, -639, -4671, -4952, -5239, -3145, -138, -4332, -7433, -3721, -3566, -337, -4663, -12593, -5254, -3552, -1391, -4762, -7195, -8644, -3370, -3758, -4647, -6089, -5053, -3458, -6957, -4791, -6491, -3648, -4299, -5356, -4950, -5986, -4012, -6366, -4894, -5337, -4762, -5765, -9859, -5770, -6680, -4250, -7849, -8077, -6539, -8993, -4049, -7880, -5595, -7021, -7878, -3440, -7817, -4289, -9246, -6359, -2550, -7828, -3690, -14931, -5444, -2002, -6701, -3536, -8096, -4238, -2251, -5883, -3852, -7104, -3132, -3703, -6021, -5128, -8187, -2707, -7868, -6281, -9567, -9829, -3158, -8433, -6121, -7803, -9826, -4530, -4120, -6513, -4211, -8745, -6605, -2590, -7734, -3280, -8554, -8064, -2129, -8656, -3965, -8337, -8232, -2411, -7856, -6265, -5359, -8473, -3191, -6319, -7133, -3973, -8603, -3961, -5119, -5602, -4297, -8081, -4038, -4657, -4597, -5804, -7912, -3391, -5386, -4008, -6926, -8704, -2602, -7435, -4229, -8161, -11275, -2156, -7266, -5466, -9710, -14398, -2307, -7574, -7933, -7565, -8732, -3190, -11110, -10776, -7046, -7437, -4874, -5258, -8394, -8759, -8230, -6787, -3350, -6713, -15560, -10338, -6749, -3291, -6291, -10373, -10250, -6686, -8081, -3861, -7544, -12242, -5296, -4990, -3638, -6283, -9534, -4842, -4384, -3611, -6077, -7659, -5782, -4796, -3644, -6173, -6376, -8535, -5620, -3851, -5851, -6373, -7229, -7298, -4720, -5509, -7419, -6000, -7694, -6763, -5797, -6459, -6692, -5630, -10988, -6929, -4902, -7763, -4236, -14770, -8883, -4496, -7651, -3452, -10059, -11134, -5015, -7245, -3129, -8703, -10550, -5908, -5993, -3172, -8592, -8335, -6287, -4910, -3536, -8320, -7303, -6516, -4655, -4341, -7341, -6919, -7810, -5046, -6037, -7272, -6556, -9608, -5551, -10399, -8040, -6681, -8608, -5595, -11077, -7942, -7533, -8245, -5352, -7727, -7381, -8621, -9242, -5506, -7582, -6260, -8946, -12264, -6541, -9181, -4954, -6697, -9602, -8278, -11606, -4501, -5073, -6425, -8221, -10750, -5169, -4816, -5116, -7345, -8677, -7055, -5554, -4801, -7546, -6583, -8102, -6044, -5165, -9019, -5398, -6459, -5659, -6100, -11315, -5408, -5590, -5940, -7048, -10794, -6623, -5433, -7994, -6872, -9456, -8768, -5395, -11278, -6691, -8343, -10468, -5121, -8059, -7592, -7063, -9210, -4766, -7158, -9540, -5863, -7060, -4729, -7870, -9096, -5170, -6140, -5375, -10321, -6839, -5354, -6402, -6812, -17832, -5637, -6724, -7307, -7519, -9106, -5496, -8705, -7919, -6604, -7291, -6224, -7896, -8120, -6267, -7301, -7367, -7235, -7994, -6827, -8576, -7996, -7929, -7577, -8062, -10179, -7451, -9083, -7175, -9730, -10866, -6625, -8186, -7108, -10845, -10002, -6490, -6085, -7891, -10350, -8082, -6925, -4784, -9322, -9988, -7385, -7246, -4706, -9306, -9214, -8374, -7127, -6081, -8930, -7544, -11900, -6299, -9353, -8191, -6706, -12636, -5464, -8912, -7071, -7185, -9948, -5367, -7078, -7114, -8801, -8905, -6146, -6768, -9244, -9259, -7689, -7835, -6756, -14682, -8430, -6448, -10286, -6334, -9283, -8936, -5805, -10398, -6232, -8215, -11595, -5907, -8780, -6925, -9266, -12734, -6654, -8245, -8377, -13011, -10854, -7601, -9180, -10070, -16819, -9726, -8044, -13164, -10194, -12386, -8277, -8308, -11393, -8966, -11102, -7739, -9389, -8107, -7966, -9149, -8758, -12630, -7110, -7712, -7642, -12974, -16843, -7381, -8716, -7506, -12816, -12094, -8807, -12294, -9444, -9445, -12427, -11430, -13088, -13175, -9000, -11861, -13592, -11056, -8018, -9609, -8138, -13507, -13650, -6437, -9416, -6223, -13215, -10254, -6645, -8461, -5572, -11994, -7187, -8797, -8068, -5900, -11103, -6167, -12028, -8353, -7192, -10938, -6353, -8272, -9002, -9690, -9898, -7507, -7329, -9624, -12416, -8870, -9500, -8506, -10184, -12048, -9132, -11676, -11289, -10610, -13399, -10614, -12017, -9963, -10329, -17632, -12277, -10225, -9342, -10059, -11794, -12810, -8551, -11024, -11152, -9739, -10594, -7666, -13738, -16279, -9015, -8973, -7541, -10362, -14029, -8803, -8840, -8188, -8717, -11141, -8518, -10270, -9868, -8657, -10411, -8097, -13847, -13647, -9581, -10752, -7837, -17834, -19148, -9836, -12529, -7931, -20091, -13792, -9977, -11735, -8497, -13887, -12597, -5991, -3744, -8902, -11410, -8909, -5391, -4875, -9033, -8824, -11574, -4686, -7483, -10082, -6786, -9772, -4221, -8386, -11713, -5534, -7215, -4427, -7160, -11370, -5162, -6295, -5663, -6160, -9608, -5567, -4910, -8094, -5465, -8462, -6479, -3906, -10248, -5571, -7955, -7540, -4028, -12081, -6664, -7881, -8728, -5443, -11211, -8168, -8236, -8905, -8792, -8369, -8285, -8463, -7148, -12392, -7433, -7569, -6835, -6183, -8421, -7292, -7064, -5297, -6863, -7661, -6998, -7198, -5058, -10533, -8750, -6326, -8437, -5922, -10417, -12173, -5678, -11215, -5797, -7091, -13441, -5301, -12537, -4946, -6199, -9546, -5184, -10470, -5456, -6234, -8400, -5204, -9073, -7572, -6855, -8838, -5254, -8304, -8123, -8270, -9406, -5340, -6641, -7515, -10446, -8337, -5466, -4801, -9911, -9273, -7318, -5471, -4036, -10924, -7826, -6955, -5336, -4542, -5788, -7617, -7424, -5559, -6493, -4346, -7735, -8804, -6796, -10525, -4645, -7064, -9692, -8022, -24960, -6532, -6083, -8804, -5864, -12193, -8419, -5556, -7612, -4576, -9891, -7835, -5563, -6365, -4740, -9331, -8463, -5905, -5533, -6383, -9772, -10027, -6335, -5503, -10656, -11335, -8994, -6706, -6632, -12304, -14695, -8003, -7338, -10125, -8839, -10698, -8142, -9166, -11785, -8201, -8931, -8256, -12605, -7731, -8399, -9187, -7673, -13029, -6747, -8740, -10575, -6812, -18001, -7123, -9667, -10123, -6003, -8773, -8340, -10541, -9335, -6346, -6194, -9319, -7978, -8672, -9434, -5109, -9667, -6188, -7126, -11739, -4909, -10658, -5687, -6117, -7850, -5786, -12360, -6263, -6042, -7688, -7843, -10842, -7874, -6553, -7756, -7997, -9353, -10055, -7000, -6986, -6754, -9075, -10057, -6836, -6558, -6460, -9185, -8933, -6373, -6269, -6889, -9051, -8414, -6409, -6204, -7961, -9056, -8596, -7465, -7027, -9355, -10020, -9444, -9167, -9397, -10302, -13686, -10432, -8710, -12956, -12171, -13586, -10825, -7945, -10608, -20602, -9473, -11381, -8347, -9115, -11084, -8096, -11883, -9886, -8625, -9771, -8113, -11845, -12840, -9157, -11089, -9648, -13506, -17357, -11322, -15611, -10725, -12426, -12935, -11703, -15018, -8182, -9198, -11329, -8610, -14320, -6861, -8047, -12005, -7322, -9497, -6595, -8139, -16254, -7258, -7208, -7013, -8970, -11442, -7916, -6760, -8093, -10028, -9065, -8420, -7990, -10361, -10859, -9035, -7877, -11779, -17250, -11230, -11400, -7004, -17858, -11925, -11498, -11424, -6944, -12917, -9719, -12969, -8998, -8374, -11280, -9195, -13799, -8777, -12118, -10145, -9121, -10062, -10183, -12353, -10403, -9174, -8311, -11381, -11711, -11370, -9726, -7643, -9668, -11575, -10860, -10616, -7382, -8398, -9651, -10141, -9582, -7492, -7666, -8988, -10232, -7922, -8451, -7308, -10074, -11430, -7321, -10715, -7654, -12915, -12854, -7852, -10677, -9120, -11435, -11781, -9380, -8932, -12507, -9987, -11731, -11085, -9085, -16788, -10218, -12420, -11560, -12065, -13337, -11069, -11049, -11568, -15013, -12380, -10784, -10065, -11213, -10293, -11080, -10060, -10459, -10470, -4645, -7279, -8322, -10262, -8200, -7235, -10412, -8067, -11503, -7272, -7172, -11788, -8851, -12891, -5541, -5762, -10109, -10237, -24390, -5888, -5896, -11184, -11610, -11714, -8864, -8080, -13501, -12644, -10258, -8987, -10534, -9757, -11648, -13154, -6682, -6602, -7124, -11465, -13310, -6786, -5208, -5621, -14978, -9388, -9169, -5411, -4955, -14351, -8002, -12895, -7435, -4944, -10748, -6909, -8310, -12699, -5243, -9682, -6661, -7229, -8543, -5389, -9297, -7954, -7459, -6961, -5349, -9556, -11466, -8024, -6584, -5736, -11375, -10080, -9118, -6553, -7427, -10460, -7665, -10338, -6999, -11786, -7307, -6465, -8590, -8550, -13963, -5895, -6046, -7109, -10132, -14164, -4839, -6536, -6678, -7674, -8115, -3733, -8272, -7110, -6862, -6329, -3312, -11836, -8294, -7997, -6689, -3960, -10943, -9089, -9066, -8144, -5551, -8517, -7720, -8118, -8383, -6593, -7131, -6316, -8435, -8351, -6436, -6196, -5747, -9933, -9374, -7091, -5701, -5978, -9258, -11383, -10144, -5677, -6655, -7256, -11110, -12618, -5888, -6986, -5780, -10439, -7687, -5980, -6480, -4776, -8935, -6403, -6059, -5546, -4204, -6751, -6283, -6454, -4842, -4038, -5731, -6589, -7155, -4825, -4279, -5682, -6878, -7933, -5746, -5162, -6189, -7117, -9120, -7767, -7193, -6874, -7464, -11775, -10395, -9418, -7089, -8237, -10760, -10105, -8380, -6914, -10549, -8362, -8312, -8602, -7812, -14282, -7759, -7345, -11042, -11655, -9857, -8144, -7312, -13243, -12635, -9634, -8513, -7797, -12732, -10126, -12235, -8198, -8174, -13280, -8696, -11478, -8139, -8563, -13062, -7110, -10727, -9314, -9222, -17312, -6665, -13161, -12697, -10077, -11454, -7278, -14893, -13504, -12326, -7911, -8250, -8763, -11000, -13215, -6521, -8694, -6221, -10134, -9276, -6203, -8828, -5189, -10501, -7422, -6533, -9168, -5264, -13122, -6549, -7343, -9686, -6382, -14479, -6508, -8844, -10154, -9085, -10108, -7377, -10863, -10607, -17692, -8197, -9145, -10507, -11689, -9599, -7331, -11922, -10398, -11527, -8239, -7226, -16751, -13203, -9232, -9399, -7455, -11164, -13717, -8828, -13202, -7527, -8539, -11117, -11690, -10044, -7620, -6948, -11590, -12705, -8974, -7925, -6103, -12496, -8686, -10038, -8381, -6360, -10878, -8348, -12467, -8828, -8132, -9960, -9718, -13730, -8801, -11835, -9764, -10661, -11965, -8838, -14391, -9139, -10330, -10710, -9810, -12038, -7957, -10940, -10779, -11834, -8383, -7025, -12421, -11755, -13472, -6596, -6669, -12898, -13153, -14344, -6041, -6955, -12086, -15793, -14101, -6451, -7941, -11562, -21332, -10627, -8039, -9853, -12192, -22607, -8947, -11731, -13727, -15488, -17383, -8963, -12440, -17614, -16423, -13197, -10609, -11382, -13433, -12505, -11141, -13491, -14398, -12776, -11681, -10186, -13165, -16676, -12033, -11957, -10227, -11562, -13239, -11000, -11789, -11349, -10535, -13464, -10916, -10743, -12834, -10362, -12974, -11947, -10160, -12579, -11610, -13058, -12664, -10771, -12170, -16505, -12734, -11097, -13525, -11957, -12217, -10174, -9629, -13331, -11881, -9968, -8909, }; +//int32_t position_embedding[1936] ={196, -7348, -7382, 1712, -10706, 1192, -2694, 1918, -6099, -3297, 121, -2851, -5180, -4712, -1750, 13596, 9600, 3479, -260, -4836, 1525, 4241, -2302, 4529, -900, 3399, -6545, -1652, 3663, -9180, 4876, 3043, -2909, -1064, 4044, 3782, 9062, 1131, -11358, 1565, -1527, -360, -8696, -9012, 1582, 12600, -3776, -1521, 5412, 2481, 1324, -4161, 13922, 5353, -4342, -1956, -1648, 2128, -11661, -6865, 6676, 3476, 3854, 8205, -6787, 6070, -2006, 2531, -13202, -4385, 2898, 2619, 7081, 7595, -1546, -9370, -2303, 2956, 6760, 5943, 4413, 4207, -3058, -4963, 6809, 5599, 3394, 460, 6411, -4390, -2761, -3172, 9835, -7277, -1952, 1675, -7690, 3179, -9750, -7583, 5347, 10512, -1649, 1281, 11435, -5484, 9637, 3355, 1422, 1506, 4282, -3563, 1374, 3387, 1124, -8658, -2358, -4699, -4142, 490, -3377, -2415, -7181, -1534, -597, 12306, 5111, 16385, -4726, -7888, 2951, 81, -2326, 7865, -5223, -6500, -3798, 4601, -3666, -618, -11033, 12947, -534, 10781, -9595, 6606, -209, 130, 1359, 3264, -4327, 2847, -302, -4247, -8282, 402, 7925, -2107, -2138, 8384, 2522, 6636, -777, 96, 3798, 8934, -10498, 2998, -1701, 4036, 4295, -6322, -4076, -118, -4425, 7939, -127, 2611, -3533, -13055, 776, -1126, -7048, -2041, -1031, -2451, -1461, -15072, 1542, 185, 22, -8805, -4022, 348, -5263, -5852, -8468, 6756, -3619, -4270, 2868, -5721, -4657, -3375, -2366, 7595, -591, 2305, 1837, 4089, 7194, 1445, 9971, -5729, -11176, -188, -6837, -3708, -7535, 8617, 3044, 10526, -2912, 2707, -5639, -671, 7353, 2677, 6239, 9202, -9854, -3893, 834, 2775, -7384, -2147, -2039, 9885, 1003, 3164, -7241, 6396, -3139, -10976, 8473, 1252, -10979, -1952, -134, 1954, -4129, -6521, -129, 1874, -234, -675, 1052, 14765, 896, 2509, 1602, -1855, -13043, -10309, -2265, 2743, -4266, -2706, 836, 2445, 512, 18564, 2667, 7664, -10884, -4509, -1825, 5502, -2222, 8628, -1803, -15446, 5921, -1472, 11098, 4316, 5132, -7807, -2586, 5918, -2599, -2611, 3376, 2489, -1817, 4732, 3388, -1536, -1365, -10085, 8422, -2155, 6762, -2014, -8955, 4150, 439, 4460, -1990, -2740, -1333, 349, -8757, -2081, -7922, -4516, -3423, 3926, -4, 1547, 979, 9047, -6177, 568, 1446, 6488, -6201, -2358, -7308, -391, -349, -4329, 2976, 8472, 5717, 2301, 5198, 1549, -3488, -6818, 896, 5382, -12555, -320, -1272, -1351, -11423, -5350, 114, 5480, -1229, 109, 2501, -11900, -944, 5306, 3113, -6048, -3661, -5327, 1334, 10289, -9589, -2279, -1588, -3509, -6272, 10002, 5967, 5551, -6935, -4327, 2791, 9216, -9959, 4473, 1978, -15959, 2149, -7863, 307, -4521, 9051, 6015, -897, 5300, -6371, -260, -800, 2709, -5341, -110, 9833, -7331, -49, -4877, 6976, -4835, 9914, -3133, -4385, 4190, -5738, -465, 2371, 9339, -7956, 6917, 550, -4353, -6041, -4530, 1078, -264, 7846, 3506, -3651, -6858, -126, 1678, 7383, 6218, -2889, 299, 2333, 651, 7628, -751, 2680, -1033, -2285, 7088, 1915, 3198, -17, -11549, 8693, 814, -2438, -2575, 134, 5825, -10139, -1796, 5422, -328, 3026, 7844, 7875, 151, 5205, 6808, 2670, 7859, -12952, 786, 3422, 7597, -6877, -8084, -5465, 532, -10992, 14251, 8151, -2947, 9253, -2637, 10375, 6905, -6967, 6725, -1279, 6702, -3149, 2110, -6067, -4028, -3569, 3633, 1111, -4331, -1496, 5413, 7091, 1720, -8921, -978, -1209, 829, 255, 1729, 1379, 307, -3612, 6083, 5152, 10108, -1758, -12600, 7086, 10504, -9339, 8476, 213, -3269, -8160, -720, 8930, 7891, 205, -2909, -1424, 2115, 8759, -2722, 4276, 10615, -4849, 1589, -6607, -6358, -16955, -355, 2535, 10376, 4434, 4805, 5135, 1439, -3213, -5002, 5087, 687, 1086, -4681, -2821, -14266, -11179, -2582, 7730, 104, 8271, 6464, 4981, 3696, -5874, -5849, 1397, 1046, -12206, -1665, 2201, -439, -2283, 2989, 6710, 167, 3424, 226, 5465, 1487, -3130, -5497, -2878, 3131, -4859, 1596, 4630, -7875, -3226, -7328, 5413, -1135, 3646, -3147, -4163, 1187, 6921, -4376, -394, 2658, -2362, -2453, -2948, -5, 2681, -9107, -1191, -11249, -9502, 2395, -4479, 5486, -9094, 4493, 2749, 9093, -13265, 1179, -2309, -4304, -943, 763, 7495, 1353, 6170, 5194, -2838, 5307, -6865, -789, 3717, 2676, -3582, 5513, 2849, -6748, -929, -452, -74, 10928, 4100, -2011, -4080, 7555, -5922, -4585, 2941, 5010, -9571, 3639, -7514, -8163, -9381, 6471, 6542, 10530, 1936, 12466, -8631, 2326, -2711, -5686, -3652, 9719, -5176, 4973, 3079, -2078, -3088, -1273, 4810, 7839, 4100, 2226, -10032, -1859, 3094, -588, 3594, -4821, -12113, 4966, -199, 8597, -5230, -9595, -2768, 1170, -7238, 6502, 3566, 1014, -859, -2509, 8922, 5700, 3053, -5515, 2418, -9141, -11804, -6197, -485, 3796, -3860, -249, -3930, 6901, -6496, -10185, 3596, 2732, -1355, 983, -527, -6415, -11871, 5991, 1217, 3176, 1131, 3719, 1786, -4878, 2575, 301, 1830, -1133, 1374, -3349, 164, 3352, -1368, -7919, -7348, 5071, -949, 9665, -510, 1889, -5429, -11519, -367, -329, -4465, 3694, -4588, 2112, 638, -7040, 3411, 6658, -1359, 6764, 1210, -5077, -1410, 11878, -1644, 7113, -1193, 424, -3177, 1180, -1788, -194, 2381, 7231, 583, 12532, -2873, 10938, 499, -1249, 5818, 4605, -4712, 4018, 8740, -4365, -45, -5998, 7774, -12177, -2624, 2729, 3998, -108, -8892, -3748, 5248, -2207, -5953, -1195, -2204, -11208, -7020, -3089, 591, 2701, 3647, 4811, 5174, -793, 1089, -4844, 3268, 42, -8431, -6365, -473, -6021, -7345, 4530, 1754, 9097, 1264, 3335, -4713, 5214, 8575, -4620, 4652, 4686, -5145, 4579, -5352, -7520, -5546, 5278, -1174, 3277, 5639, 6893, -6939, 889, -2533, 4578, -2099, -2107, -1194, 7229, 3163, -12403, -15160, 9385, -1258, 4658, 7070, 6925, 2730, 9222, -5450, -7277, 4427, 10517, 5277, 5046, 3242, -4736, -6004, -4718, 2550, -2531, -1704, -4376, -1463, -4121, -2849, 3464, 2406, 8299, -1272, -5814, 5850, -5042, -7367, -7965, 718, 6263, -2666, 4066, -1047, 10409, 4553, -2990, 13574, -1465, -9180, 5031, -2361, 828, -3184, -9065, -927, 9733, -2748, 1466, 4699, 5731, 6123, -6454, 195, 5271, -14124, -2202, -1832, 2, -12207, -3771, 420, -6557, -1144, 9838, -2994, 821, 5869, 4339, 2391, 11899, -8278, -4483, -2896, -1849, -8299, 5111, 260, 10086, 3929, 5539, -6377, 13205, -3131, -1461, 1465, -207, -6114, 1402, 5214, -7641, -973, -1233, -4298, 9744, 2985, 14273, 143, -2463, -1160, -7427, 6119, 7836, -4500, 921, 2153, -287, -5492, -7355, 322, 8465, -1047, 2054, 497, 10097, 7018, -4490, 2046, 6496, 1872, 3413, -9124, -779, 6169, -6458, 1514, -3490, -10698, 3100, -1862, 2875, 6368, 1318, 658, 1050, 219, 3709, -10295, -2636, -4041, 5012, -61, 4480, -3406, -2850, 302, -7649, 5732, 7661, 7424, 5693, -2459, -7557, -6075, -1802, -11208, 3080, -7096, 6845, 1575, 5391, -2403, -2489, -1433, 2278, 7747, 4970, -13012, -5878, 6852, -9159, -4405, -374, 4644, 948, 8329, 4469, 2672, -812, -5394, -11335, 5476, -1149, 831, 1394, -4572, -5319, -8258, 3435, 1955, -972, -4931, 4098, -362, 10748, -4493, -7594, 7251, 7377, -5753, 5011, 5545, 812, -9204, -5784, 3585, -2369, -2755, 6910, 3144, 9649, 1338, -4350, 8637, 10729, 4980, -2094, 2339, -9914, 4376, 1377, -3161, -9768, 10043, 2351, -5890, 3685, -5198, -198, 9585, -2097, 251, -271, -6207, 2402, -7706, 2448, -2452, 4762, -2401, 8514, -3997, -3465, -1079, -1985, 1855, 12959, -3239, 3580, -7527, -141, -10696, 1692, -1395, -4360, 3321, 8854, -1479, -556, 2118, -6509, 1766, 3286, 6377, 587, 2108, -3565, -4028, -1202, 6234, 10107, 4402, -3022, 1785, 11342, -2046, -8556, 10844, 9710, -6141, -2186, 7498, -6214, -10161, -706, 10836, -3416, 1141, 7550, 10477, -2297, -2264, 2035, 4234, 3055, -8828, 677, 4606, 5708, -8930, -12070, -3840, -1422, 7871, 3303, -1806, 3930, -8954, -14512, -6258, 3705, 2788, 7841, -5298, -2605, 9229, -6623, 6570, -1780, 8058, 2401, 82, 3209, -2819, 5653, 4950, 11482, -815, 2924, 13697, 538, -2681, -6465, 6221, -14698, 4160, -1397, -1421, 3050, -2808, -4229, 8893, 8020, -16289, 2108, 42, 1162, -7427, -6701, 7883, 8297, 1597, 5038, -2443, 931, -4441, -6867, 6905, 3184, -18314, 3272, 3904, -4514, -2738, -3360, 8473, 11965, -1353, 12774, 643, 3839, 3358, 2682, 8232, 6960, -4297, -836, -6527, -1543, -6549, -2445, 586, 11268, 246, 18235, 13, 1016, -1328, -669, -3472, 7036, -1343, -2877, 1927, 4696, -8023, -4754, 8818, 3667, 6334, 7176, 3254, 5146, 5763, -887, 1357, 5270, -12799, 5511, 7894, 830, -3383, -12477, -5669, 1653, -2524, 2412, -7996, -6546, -4264, -8583, 6337, -2213, -802, -2847, 2, -3954, -8564, 604, -1101, -887, 1889, 5294, 2636, 8182, -2383, -2636, -3763, 9006, -3445, -4557, -453, 6281, -10285, 493, 461, -237, 7249, 4140, 2612, 9505, -1959, -3777, 791, -1044, -5313, -5067, -1969, -4218, -5337, -761, 1536, 10589, 4648, 16378, -2512, 1416, -5251, -7837, 5860, -4262, -4829, -9612, -1219, -4834, -8699, 1980, -3450, 6160, -3204, 6195, 3463, 9506, -5485, -8112, -4138, -724, 1512, 918, 1741, -10433, -14466, -6574, 12705, 2220, 11707, -4228, 346, 10643, -2137, -4149, -1762, 5518, 7242, 5374, 1826, -2245, -30, 586, 4427, -10485, -212, -4218, 3951, 8882, 932, 1660, 1355, 2252, 250, -7325, 1686, 2198, -6366, -7720, 853, -3684, 972, 3909, 2243, 7001, -484, -1258, 3933, -1780, 1998, -2576, 3712, -10146, -1859, 694, 4870, 10322, 6968, 2166, -3058, 4834, -3061, -582, -2964, 8615, -4992, 11852, 1768, -9018, 221, -5394, 3845, 5675, -3122, -3868, -1592, -879, -7691, -2872, -424, 2273, -4646, 923, 3113, -4257, -10901, 3142, 4453, 943, -2176, -1475, 1806, 5221, -5723, -12716, 1026, 5810, -7981, 898, -4108, -3235, -9229, -3181, 5933, -3481, 1041, 8501, -8344, 7251, -346, -8282, -3530, 4398, -6469, 331, -1543, -7201, 5033, -3596, 2641, -2910, 5563, 3475, 3365, 8598, 3284, -9382, -1039, 8790, -3126, 4164, 9639, -8403, 4317, -9679, 12168, 1929, 4278, 13619, 2864, 3590, 532, -5407, -4325, -1887, -3285, -443, -2136, 4922, -13579, -1682, 3007, 1898, -5139, 12461, -1291, 3241, 2362, -4873, 4000, -1434, -4710, -4441, -1077, -9310, -3098, -2394, 8959, 2132, 3326, 10103, 7219, 7674, -3532, -3918, 2722, 4192, -7496, 3443, -2661, -5911, -13391, -6098, -6935, 3533, -4270, 9580, -2819, 10422, -1715, -6566, 1072, 7238, -7981, 5947, 6971, -2932, -8276, -6662, -2739, 1783, 7551, -822, 714, 6140, -2272, 1579, -1586, 2848, -4921, -5685, 2468, -4065, 8038, -1181, 3849, -7741, 8319, -4081, 540, -331, 2632, -8020, 3331, 2738, -10207, 10376, 1578, -6226, -7393, 1824, -3637, -2150, 4912, 3303, 97, 7901, -3422, -11877, 11709, 7670, 1157, -1433, 14410, -4035, -5654, -2636, 1646, -3398, 4553, 3448, 1590, 6668, 1229, -631, -639, 7354, -5577, -1004, -4027, -4623, 1226, -6965, 6190, 5682, 6399, -2992, -5282, 4553, -301, -5865, -1087, 5129, 372, -397, 7112, -11645, -7985, -3391, 886, -665, 1259, 3809, -7332, 3309, -5446, -1452, -3214, 7524, -7810, -4991, 6479, -5773, -2147, 504, 8548, -414, -1342, 4170, -2569, -570, 4688, 6138, 2469, 7672, -1794, -4615, 2466, -2698, -1092, -8501, 2056, -9155, -3875, 4456, -5823, 6540, 1286, -5507, 604, 3683, -5865, 1624, 10940, 397, -7894, -3904, 7932, -3332, -1916, -453, 4174, 9373, -8885, -11755, 2603, 1730, -4719, 2118, -3560, 2020, -5513, -828, 4869, 6686, 1224, 2484, -1048, 1258, -6406, -9003, -1844, 7966, -5982, 2834, 257, -12060, -2571, -399, 7284, 2855, 2137, 7453, -228, 8378, -5410, -7611, 2233, 10363, 959, 204, 6403, -2208, -9057, -1205, 10133, 6597, -3193, 1573, -9256, 1178, -1660, 423, 3115, 8276, -10066, -9202, 1808, -1862, -6246, -8949, -9359, 3781, 7604, 6050, 328, -2843, 1670, 5750, -1362, 490, -1824, -1695, -6753, 7309, -2915, -3351, -835, 4938, 1274, 839, 6488, -2967, -6740, -2742, 9887, 9589, -4916, 569, -583, -1105, 1792, -554, -677, -5544, -1202, 9332, 7015, 4194, 847, -5562, 6385, 7952, -13964, 3095, -2044, -4642, -12211, -11113, 803, 6275, 3938, 11288, -3246, 7863, 5390, 1234, -2093, 10643, -7571, 9591, -1187, -6426, -10116, -2729, -1892, 11679, 2705, 383, 5100, 290, -1186, -5636, 3468, 8022, -4437, -7619, 1079, -6484, -5701, -6167, 5154, 2463, -4677, -678, 1465, 2782, -1074, -3588, -1667, 8992, -10088, 5435, -2560, 3760, -13964, 941, -3134, 7520, -5560, 4607, -6430, 7678, -7308, -4429, 6823, -24, -6644, 9550, 8560, -8120, -6287, -1422, 5070, -3360, 10365, -1586, 2224, 2928, -6037, -9535, -4078, 7441, -2257, -2203, 3939, -2139, -854, -1630, 1062, 1906, 910, 510, -6428, 6919, -2506, -12797, -3276, 822, 1002, -2871, 8174, -8013, 47, -2337, 6914, -1141, 1825, -5894, 2829, 9621, -1258, -1760, -7474, 4528, -4157, 4937, 3116, -6704, -6168, 357, 11296, -721, -2325, 4340, 6459, 4289, -4798, -3662, 2985, 6979, -5045, 1388, 7683, -1556, -1681, -8961, 12688, -6371, -5467, 1561, 11487, 169, 5750, -6795, 3916, -2576, -10949, 6332, -7643, -3722, -8052, -6156, -2037, -713, -4781, 15583, 1208, 2386, 460, -923, -1273, 2499, -2653, 2952, -3185, -6835, -5247, -3670, 4576, 2211, 5279, -313, 806, 3856, -12356, -4425, 2318, 4636, -281, 4072, 11650, -4005, 3906, -4887, 10698, -2211, -1905, 191, }; +//int32_t encoder_out[1936] ={-3006, -13563, -12330, 18429, -5740, 7757, -11785, 19611, 5385, -14561, -4444, -13231, -273, -10749, 1769, 14144, 6853, -7264, -3989, 9728, 6174, 14216, -13342, 20866, 8739, -9327, -15258, -12849, 11503, -16206, 6678, 4712, -3368, -10248, -323, 17739, 14650, 9631, -22149, 18791, 8398, -12585, -14408, -19795, 9133, 7335, -2016, 218, 3745, -8689, -3055, 8517, 19150, 15896, -17422, 15479, 8259, -11139, -19673, -16118, 13716, -2489, 4658, 10756, -8425, -1803, -6892, 18482, -7281, 2743, -5683, 20533, 17587, -5318, -5861, -19906, 5187, -1484, 11114, 7230, 228, -6363, -6655, 9139, 10365, 14506, -7711, 16482, 16422, -16187, -11228, -14695, 18943, -13552, 882, 2345, -11537, -6686, -11743, 7935, 7791, 17995, -10134, 17477, 20963, -15352, 3390, -7308, 7919, -5904, 5447, -2132, -1507, -5768, -3574, 4260, 2652, 4375, -17098, 18282, 7600, -16904, -13845, -10678, 3984, 7624, 6440, 18787, -4814, -13887, -3132, 16328, 2480, 14219, -15608, 12369, 9305, -6755, -9780, -9805, -5951, 7635, -752, 10670, -12533, -1822, -5518, 14468, 5185, 10349, -16181, 20586, 11674, -16543, -15452, -10119, 14549, -6957, -6, 9185, -723, -2247, -6201, 13563, 6180, 16249, -20590, 20376, 10058, -7715, -3023, -17945, 3895, -5125, -2581, 8922, -2947, -8726, -6576, 454, 5031, 8435, -17115, 13176, 8105, -15541, -9771, -26546, 11608, -5647, 2820, -7509, -6901, -8206, -9755, 8543, -4364, 13458, -13971, 14118, 14418, -17485, -10573, -13533, 3500, 3417, 1789, 2659, -978, -5582, 1754, 15694, 16021, 4131, -25353, 19627, 4040, -17391, -14517, -908, 8276, 5537, -632, 4351, -5816, -9106, 1921, 17213, 11727, 17095, -21631, 14579, 12311, -9099, -14541, -11745, 4595, 4505, 1362, 3649, -8561, -4528, -7242, 1546, 12875, 10656, -23093, 14368, 9969, -10482, -12326, -17341, 8191, -4029, 394, 1754, -4055, 5990, -5765, 14625, 4312, 6787, -27034, 9123, 10688, -12565, -11754, -11023, 5809, -1559, 1929, 21333, -4137, -3938, -12844, 10591, -577, 14611, -11639, 24979, 7176, -26631, -1815, -11506, 18175, -2329, 7633, -5593, -5884, -4737, -5611, 11342, 7139, 11005, -11085, 19903, 12770, -13858, -8696, -21227, 17759, -8275, 9465, -767, -10777, -3937, -4997, 19747, 3537, 5078, -11440, 19340, 2302, -15039, -12820, -14607, 2856, -841, 3066, 3019, -3662, -1769, -10455, 13468, 4293, 16466, -18227, 16129, 3082, -13989, -7767, -13065, 8357, 2831, 6949, 5188, 3071, -9636, -7742, 5922, 5691, 15255, -25481, 17238, 8637, -13963, -19659, -15803, 6774, 81, -32, 1563, 2272, -18979, -5995, 21439, 8942, 882, -13145, 12693, 12852, -1774, -13667, -12866, 4715, -8892, -4644, 11093, -422, -5046, -10092, 9053, 4390, 18136, -20282, 20232, 11824, -28001, -6060, -18339, 7227, -10905, 11389, 7704, -5617, -4712, -9613, 13707, 2698, 10574, -14994, 15975, 19634, -19674, -6834, -15951, 15005, -10525, 13284, -2557, -7022, -5978, -9209, 13370, 5896, 17525, -17853, 23255, 10249, -15506, -12905, -14879, 7564, -6889, 9077, 4961, -5693, -13709, -3604, 18055, 9899, 13762, -11124, 16051, 12696, -9712, 1954, -12613, 9317, -8709, -1939, 8967, 1074, -7952, -4365, 1336, 14539, 11503, -16097, 14413, 10291, -7622, -18878, -11665, 12678, -6553, 3328, 10297, 6128, -7062, -776, 21889, 6628, 14075, -23131, 19239, 16078, -4247, -13226, -18217, 1223, -3829, -9830, 14185, 7628, -11920, 4644, 13153, 16201, 15229, -17074, 24769, 9515, -4742, -10565, -9459, 1060, -10122, -2606, 3948, -1114, -12072, -5986, 20459, 11262, 9498, -19128, 16965, 9743, -10716, -4806, -8878, 6640, -6002, -2477, 7561, 1982, -2676, -5055, 535, 11206, 21236, -22742, 25469, 9341, -15296, -17869, -11445, 16623, 1860, 1645, -1316, -3186, -7917, 3771, 11779, 10191, 20504, -18291, 20597, 3803, -19284, -25289, -9539, 8301, 5012, 5881, 5836, 423, -9288, -6980, 9044, 9488, 11661, -12011, 13275, 6737, -27917, -19263, -11345, 12851, -6200, 10087, 8955, 805, -7845, -9519, 6972, 5407, 11348, -25740, 15166, 12016, -13473, -11119, -7590, 13181, -6210, 4865, 1932, 1081, -9226, -6301, 8222, 638, 11695, -14984, 17147, 14184, -20129, -11090, -19273, 14319, -6545, 7140, -2883, -7634, -6844, 1066, 10066, 2738, 9623, -11962, 14367, 9260, -13035, -5203, -21472, 9516, -15976, -5773, 1460, -9266, -4569, -13189, 17706, 5167, 17608, -25065, 18705, 8341, -16412, -8140, -8555, 12759, -4921, 7306, 7143, -5731, -4578, -9634, 13517, 8002, 10713, -12955, 22717, 12124, -18190, -5714, -10473, 5509, 5176, 6163, -359, -8158, -2435, -10629, 8846, 6458, 14548, -23898, 22129, 3490, -21086, -17176, -1972, 10069, 4788, 2566, 15234, -10502, -7098, -6553, 8756, 422, 16611, -15354, 21749, 13913, -13106, -9909, -11836, 11777, 2514, 5699, 2834, -9025, -9450, -2209, 14080, 8578, 1880, -21538, 21410, 11247, -3034, -10588, -21030, 5698, -3899, -6210, 8263, 1423, -8707, -5358, 11613, 14847, 15042, -9044, 13159, 12370, -21378, -18525, -16342, 6187, -1641, -1324, 601, -6478, -3701, -10467, 3996, 8764, 12689, -15030, 19272, 9605, -18728, -19845, -3559, 5652, -3275, 1863, 5597, 953, -12340, -1849, 15916, 6577, 6932, -6837, 14165, 10642, -8840, -5685, -19038, -506, -466, 640, 11242, -2583, -8288, -9136, 1140, 3106, 8936, -15763, 19152, 5437, -10478, -6910, -17981, 11343, 596, -535, 9676, -956, -11538, -6862, 27331, 3241, 13859, -10920, 19079, 8564, -10570, -5761, -9812, 7378, 2110, 3067, 13426, -7632, 1378, -4034, 12624, 8594, 11389, -14816, 19965, 20021, -16429, -7859, -18291, 17532, -17084, 1335, 2532, -230, -10488, -12058, 9814, 9352, 7707, -17859, 16019, 7254, -23813, -13478, -12000, 4898, -3686, 4841, 7461, 2075, -11495, -3560, 8605, 9092, 10922, -23374, 13014, 9729, -19426, -15298, -4780, 6518, 3642, 2751, 5038, -7917, -4041, 3806, 10222, 9947, 13664, -18028, 22791, 5628, -20491, -13863, -4558, 4180, -2485, 7495, 8047, -8674, -6502, -7094, 20470, 4307, 5030, -11802, 25527, 13764, -24719, -19127, -150, 2611, -1029, 10121, 7295, -564, -2071, -8611, 7205, 7906, 19158, -4511, 22058, 12822, -15749, -13811, -15922, 10977, -8554, 572, -3316, -3058, -12151, -7466, 17638, 7109, 15570, -11320, 12053, 16600, -16480, -12338, -18142, 7339, 1133, -639, 4681, -2768, 563, 140, 10280, 18510, 7490, -20426, 21980, 7790, -12230, -10133, -20188, 7033, 4754, -724, 3781, 1123, -4142, 542, 6839, 4322, 13990, -27587, 16011, 10164, -13827, -21794, -13802, 6966, -11049, 212, 10254, -5240, -7852, 48, 18922, 7869, 20456, -21871, 15636, 8900, -14475, -15940, -3293, 4716, 4900, 4879, 5831, -10344, 5091, -8364, 12194, 5127, 6790, -17157, 19659, 17195, -20674, -6316, -10681, 818, 5437, 5760, 15987, 26, -12619, -5085, 5931, 11086, 16895, -15453, 17332, 11797, -11451, -12670, -18508, 8468, 2444, -226, 3621, -4802, 518, 1732, 9351, 3782, 13992, -8001, 21509, 2538, -13698, -2189, -17680, 11326, -8055, -7364, 2616, -4362, -5926, 1259, 17264, 6588, 10125, -11527, 23188, 336, -15507, -11028, -5887, 6504, -827, -376, -1999, -1245, -15610, 133, 23226, 13612, 13851, -13972, 12359, 5370, -14127, -16831, -6162, -1943, 1322, 3421, 5663, -5809, -11947, -5660, 15584, 12366, 13584, -25102, 11684, 17176, -21626, -11137, -10079, 10452, -5009, 10119, 5420, -65, -11647, -8754, 3245, 10677, 9533, -12684, 18626, 4942, -17226, -16617, -6602, 7393, -8438, -4143, 6338, -2537, 284, -9020, 5285, 10882, 15554, -17336, 21522, 16400, -11034, -17315, -17011, 11620, -7641, -1386, 8084, -2420, 69, -2624, 10573, 11725, 19946, -5672, 15176, 12457, -22436, -3894, -8411, 4078, -16955, 12734, 4176, -6871, -5084, -10675, 13733, 14814, 6282, -11763, 18189, 5281, -9665, -13267, -7431, 3116, -1217, -1328, 10698, -4987, -11999, -6191, 13751, 6734, 21035, -14470, 21428, 3669, -10964, -18630, -7913, 3893, -11562, 3538, 9623, -2585, -10690, -1158, 8651, 8416, 13162, -4612, 17794, 11025, -16093, -10889, -11824, 14167, 4031, 7210, -1987, -2342, 118, -6577, 4108, 14469, 19290, -20145, 15233, 18126, -18927, -19462, -10776, 17850, -8965, 2825, 8776, 9353, -12187, -6053, 16045, 10053, 11844, -18217, 17431, 14030, -6834, -14632, -22585, 3625, -7252, 9905, 4965, -6913, -6715, -10856, 1146, -4132, 13295, -5848, 22031, 3541, -14635, 853, -16929, 14867, -10080, 10242, 5538, -2911, -5900, -6975, 20120, 9190, 18659, -9922, 19385, 24080, -11026, -9187, -18048, 15138, -20644, 7384, -1591, -3322, -7729, -7178, 7882, 12850, 17169, -29152, 18653, 10324, -11162, -15366, -16757, 15256, 2707, 2295, 7212, -5099, -8408, -8961, 5473, 10208, 11194, -31132, 19405, 14988, -16836, -9705, -13365, 15011, 6886, -322, 15129, -2238, -4700, -2510, 15719, 12068, 15263, -17201, 18006, 5600, -14695, -13099, -10819, 5409, 6557, 1060, 20661, -1231, -8256, -6287, 13102, 1531, 15969, -12840, 14428, 12701, -8763, -15013, -14635, 16024, -1976, 8039, 8323, 1163, -4029, 1295, 13050, 5608, 12345, -22125, 21563, 18581, -11256, -10267, -24770, 3444, -2881, 479, 2431, -8476, -15408, -8011, 6272, 12904, 6282, -12405, 13611, 10172, -15424, -14768, -9625, 4751, -8107, 2882, 6915, 558, -1968, -7735, 11214, 1121, 18832, -16162, 14475, 10584, -7412, -18754, -9101, 6134, -5932, 8014, 5473, -2118, -128, -7230, 8462, 4284, 8683, -19400, 13767, 9541, -19055, -12613, -9168, 5520, 6085, 5818, 19566, -4967, -8263, -10320, 5186, 11308, 5608, -19345, 9650, 10010, -18178, -15500, -7019, 875, 728, -2431, 8600, -489, -1635, -8656, 6244, 627, 9692, -10156, 17995, 10687, -24421, -22420, -16582, 19462, -3430, 14473, -2169, -4748, 299, -5356, 11832, 777, 13351, -1567, 22147, 12026, -13901, -7808, -10741, 13146, -16640, 3079, -3068, 751, -285, -4640, 15415, 6281, 11059, -11255, 11059, 12984, -12162, -13589, -17987, 8424, -8545, 4051, 4753, -1922, -2756, -4453, 12951, 8903, 7796, -10048, 15724, 13579, -23594, -8454, -9019, 10395, 5265, 9772, 3949, -7364, -5175, -6215, 14174, -650, 14808, -12845, 28486, 12197, -19556, -5598, -16908, 11933, 1177, 331, -3723, -3169, -10619, -11448, 11612, 5069, 10765, -16340, 18499, 12963, -15722, -17082, -7403, 10093, -5279, -483, -1019, -2179, -6192, -9761, 138, 4022, 16176, -21635, 17535, 6239, -16161, -19177, -13231, 12251, -9925, 1566, 10893, -14047, -2666, -4217, 5942, -1564, 12132, -16661, 16392, 9506, -19765, -3372, -14345, 10870, -8606, 8542, 4691, -1876, -1064, -1200, 3602, 1012, 16364, -13975, 19559, 20924, -21303, -4196, -21408, 21603, -2487, 7945, 14237, 1470, -5301, -5154, 7858, 792, 6535, -16442, 18356, 9757, -8942, -21051, -11587, 8733, -2330, -4570, 13093, -5873, -6572, -2524, 8223, 7618, 8123, -18128, 12879, 9984, -23137, -11363, -12249, 15711, -3050, 5569, 12160, 4083, -2078, -8447, 9337, 6811, 12941, -19345, 21916, 8262, -18851, -20268, -15872, -1733, -1214, -2670, 11017, -4959, -157, -5468, 6929, 5662, 15289, -18151, 22569, 16912, -15083, -15593, -17894, 5010, -3382, 9746, -40, -5306, -3361, -6415, 16370, 952, 11072, -14498, 11353, 12985, -17035, 618, -11686, 12166, -13891, 12010, -3450, -1176, -9985, -753, 6891, 9043, 11060, -20824, 26305, 11316, -17920, -14594, -9230, 2777, -8907, 6890, 3935, -2320, -2538, -7024, 1691, 16832, 16628, -10460, 15082, 24286, -16158, -13634, -13556, 9365, -9506, 6446, 4493, -3193, -4061, -2893, 13112, 2437, 16475, -16245, 16377, 6162, -18041, -6740, -17056, 14220, 288, 9610, -2208, -8660, -4425, -4622, 8500, 3326, 12309, -10290, 16961, 18099, -23750, -14866, -14424, 8017, -5322, 4468, 3755, -11645, -5534, -10514, 12200, -474, 13851, -19413, 12801, 18684, -17540, -9202, -9935, 15524, -4871, 1224, 3998, -5864, -7892, -1162, 20918, 6517, 14193, -11343, 12942, 14462, -15089, -7462, -19859, 10933, -14142, 98, 3743, -7844, -3084, -3274, 8235, 5354, 10502, -16842, 17912, 22126, -11752, -15506, -15935, 17307, -7699, 1119, -935, 961, -2984, -12227, 813, 6519, 13134, -18401, 19312, 5803, -11180, -14533, -10765, 10838, 366, 1436, 5799, -6026, -9234, -9767, 4700, 524, 16873, -18033, 19048, 10559, -23621, -11091, -10671, 13415, -3442, 3701, 9035, -2814, -2557, -9638, 5850, 6306, 18884, -11488, 18210, 17064, -13909, -16839, -11630, 17459, 1751, -1371, 2436, -11033, -7206, -6848, 14214, 7744, 16099, -20816, 8966, 13109, -14437, -12666, -18172, -3320, -1772, 8626, 7304, 10, -11047, -3896, 21065, 4666, 9300, -11349, 16631, 3824, -5909, -7915, -14171, 7029, -667, 3960, 1565, 2782, -12537, -10300, 11758, 12762, 18572, -15625, 17045, 9661, -11897, -5784, -10756, 5216, -13503, -805, 11559, 3901, -6574, -3466, 6907, 10363, 17436, -26414, 20128, 8295, -17817, -20323, -20804, 7154, 1155, 5136, 13470, -5469, -1455, 807, 15944, 2686, 18128, -17961, 27966, 9550, -18449, -16653, -13179, 4493, 7287, 5197, 760, 1500, -10621, -5921, 7359, 7581, 17717, -17649, 10306, 11416, -18892, -14387, -16829, 13281, -2882, -1957, -351, 1159, -6311, -6635, 10989, 3535, 16933, -22238, 24300, 9058, -7718, -21583, -9173, 2480, 2573, -5305, 4740, -9380, -2832, -9839, 9766, 11385, 8620, -16707, 25052, 17508, -20031, -13020, -12162, 12100, -10151, 12370, -79, -1518, -7732, -9555, 4088, -686, 15800, -13213, 14653, 14378, -13888, -8837, -12851, 8542, -3624, 3106, 1206, -10739, -3570, -5822, 1881, 634, 8596, -9144, 13755, 18369, -20422, -7515, -13588, 15796, -6124, 5742, -5391, -2255, -170, -5938, 12486, -4898, 12070, -15414, 22543, 14595, -19373, -14154, -11389, 18806, -4725, 1237, 4293, 2099, -6089, -9000, 9513, 5640, 14807, -15826, 16983, 18406, -13532, -9893, -21230, 22742, -11495, -2039, 1731, 7707, -9512, 957, 6361, 8277, 5846, -22667, 24396, 3553, -17504, -15340, -16114, 3937, -5080, -2916, 16451, -2466, -7719, -3050, 13639, 2875, 11755, -13224, 19848, 6314, -19502, -12653, -14361, 11483, -3612, 7826, 924, -3683, -6214, -15062, 9777, 4574, 11937, -9206, 19258, 21549, -14860, -2556, -16578, 19355, -8190, 907, 1251, }; +int32_t prototypes[32] ={-1394, -5770, -6778, 762, 4001, -653, -5906, -20, 1220, 3795, -73, -3028, 635, -448, 7677, -6204, 5745, 3112, 1206, -1120, -3618, 1076, -649, 943, -3896, 2462, 4658, 2494, 3996, 1220, -1144, -1013, }; diff --git a/sw/applications/transformer/dense_layerC.c b/sw/applications/transformer/dense_layerC.c new file mode 100644 index 00000000..08d6c6b3 --- /dev/null +++ b/sw/applications/transformer/dense_layerC.c @@ -0,0 +1,69 @@ +// +// Created by alireza on 10/6/23. +// + +#include "dense_layerC.h" +#include + +void createDense(Dense* dense, size_t input_dim, size_t output_dim, quant_bit_width *weight, quant_bit_width* bias) { + dense->input_size_ = input_dim; + dense->output_size_ = output_dim; + dense->weight = weight; + dense->bias = bias; +} + +void destroyDense(Dense* dense) { + // Free the memory allocated for the Dense struct + free(dense); +} + +void multiplyweight(Dense* dense, size_t seq_len, int32_t* input, int32_t* output) { + for (int length = 0; length < seq_len; length++) { + for (int out_idx = 0; out_idx < dense->output_size_; out_idx++) { + int32_t* weight_ptr = dense->weight + out_idx; + int32_t* output_ptr = output + (length * dense->output_size_) + out_idx; + int32_t* input_ptr = input + (length * dense->input_size_); + int32_t sum = 0; + for (int i = 0; i < dense->input_size_; i++) { + sum += MUL_HQ(*weight_ptr, *input_ptr); // MUL_HQ macro + input_ptr++; + weight_ptr += dense->output_size_; + } + *(output_ptr) = (int32_t) (sum >> NUM_FRACTION_BITS); // NUM_FRACTION_BITS macro + } + } +} + +void addbias(Dense* dense, size_t seq_len, int32_t* output) { + for (size_t idx = 0; idx < seq_len; idx++) { + for (size_t feature_idx = 0; feature_idx < dense->output_size_; feature_idx++) { + output[idx * dense->output_size_ + feature_idx] += dense->bias[feature_idx]; + } + } +} + +void computeDense(Dense* dense, size_t seq_len, int32_t* input, int32_t* output) { + //multiplyweight(dense, seq_len, input, output); + printf("\rMul %dx%dx%d\n", seq_len, dense->input_size_, dense->output_size_); + multiply_cgra(input, seq_len, dense->input_size_, dense->weight, dense->output_size_, output); + if (dense->bias != NULL) { + addbias(dense, seq_len, output); + } +} + +void activation(Dense* dense, size_t length, int32_t* input, int32_t* output) { + float in_float, in_tanh; + int32_t x3, in_tanh_fxp; + for (int i = 0; i < length; i++) { + x3 = MUL(MUL(input[i], input[i]), input[i]); + x3 = MUL(x3, 183); // 183 = 0.044715 in fixed-point 12 bit + x3 += input[i]; + x3 = MUL(x3, 3268); // 3268 = sqrt(2/PI) in fixed-point 12 bit + in_float = (float) x3 / (float) (1 << NUM_FRACTION_BITS); + in_tanh = tanhf(in_float); + in_tanh_fxp = (int32_t) (in_tanh * (1 << NUM_FRACTION_BITS)); + in_tanh_fxp += (1 << NUM_FRACTION_BITS); + output[i] = MUL(in_tanh_fxp, input[i] >> 1); + } +} + diff --git a/sw/applications/transformer/dense_layerC.h b/sw/applications/transformer/dense_layerC.h new file mode 100644 index 00000000..c67d4571 --- /dev/null +++ b/sw/applications/transformer/dense_layerC.h @@ -0,0 +1,30 @@ +// +// Created by alireza on 10/5/23. +// + +#ifndef FVLLMONTITRANSFORMER_DENSE_LAYERC_H +#define FVLLMONTITRANSFORMER_DENSE_LAYERC_H + + +#include +#include +#include +#include "param.h" +#include "cgra.h" + +// Define the struct +typedef struct { + size_t input_size_; + size_t output_size_; + int32_t* weight; // quant_bit_width is a typedef for int32_t + int32_t* bias; // quant_bit_width is a typedef for int32_t +} Dense; + +void createDense(Dense* dense, size_t input_dim, size_t output_dim, quant_bit_width *weight, quant_bit_width* bias); +void destroyDense(Dense* dense); +void multiplyweight(Dense* dense, size_t seq_len, int32_t* input, int32_t* output); +void addbias(Dense* dense, size_t seq_len, int32_t* output); +void computeDense(Dense* dense, size_t seq_len, int32_t* input, int32_t* output); +void activation(Dense* dense, size_t length, int32_t* input, int32_t* output); + +#endif //FVLLMONTITRANSFORMER_DENSE_LAYERC_H diff --git a/sw/applications/transformer/main.c b/sw/applications/transformer/main.c new file mode 100644 index 00000000..a4c81ea4 --- /dev/null +++ b/sw/applications/transformer/main.c @@ -0,0 +1,156 @@ +// +// Created by alireza on 10/6/23. +// + +#include +#include +#include "main.h" +#include "data_cpp/signal.cpp" +//#include "data_cpp/signal_fft.cpp" +#include "SYLT-FFT/fft.h" +#include "weightsAndBiasesC.h" +#include "transformerBlockC.h" + +// For the cgra +#include "multiply_cgra.h" + + +// FFT +#include "stftVec.h" + + + +float error_check(const quant_bit_width* groundTruth, const quant_bit_width* output, size_t length){ + long error = 0; + for (int i=0; i> NUM_FRACTION_BITS); + return (float) error/ (float) length; +} + +void prototype_distances(quant_bit_width* prototypeVec, const quant_bit_width* modelOutput, int32_t* distVec, size_t prototypeLength, int prototypeNums){ + for (int p=0; p< prototypeNums; p++){ + long dist = 0; + quant_bit_width * prototypePtr = prototypeVec + (p * prototypeLength); + for (int i=0; i> NUM_FRACTION_BITS); + distVec[p] = (int32_t) dist; + } +} + +void transformerInference(quant_bit_width * transformerInput, quant_bit_width * transformerOutput, quant_bit_width* input_normalized, quant_bit_width* qkv, quant_bit_width* intermediate, void * kperf){ + quant_bit_width * weightVec[NUM_LAYERS*(3*NUM_HEAD+5)+5]; + quant_bit_width * biasVec[NUM_LAYERS*(3*NUM_HEAD+5)+5]; + //getWeights(weightVec); + //getBiases(biasVec); + quant_bit_width * clsTokenVector = getClassToken(); + quant_bit_width * posMatrix = getPosEmbedding(); + TransformerBlock* selfatten = createTransformerBlock(D_SEQ, D_MODEL, D_Q, NUM_HEAD, D_FF, weightVec, biasVec, clsTokenVector, posMatrix); + computeFixedPoint(selfatten, D_SEQ, transformerInput, input_normalized, transformerOutput, intermediate, qkv, kperf); +} + +quant_bit_width compute_log_amp(int32_t real, int32_t imag){ + real = MUL_HQ(real, 25) >> (NUM_FRACTION_BITS - 9); + imag = MUL_HQ(imag, 25) >> (NUM_FRACTION_BITS - 9); + int32_t real2 = MUL_LONG(real, real) >> NUM_FRACTION_BITS; + int32_t imag2 = MUL_LONG(imag, imag) >> NUM_FRACTION_BITS; + float pow2 = (float)(real2 + imag2) / (float) (1<< NUM_FRACTION_BITS); + float amp = sqrtf(pow2); + float stft = logf(amp+ 1e-10f); + quant_bit_width stft_int = (quant_bit_width) (stft * (1< +#include +#include "param.h" + +float error_check(const quant_bit_width* groundTruth, const quant_bit_width* output, size_t length); +void prototype_distances(quant_bit_width* prototypeVec, const quant_bit_width* modelOutput, int32_t* distVec, size_t prototypeLength, int prototypeNums); +void transformerInference(quant_bit_width * transformerInput, quant_bit_width * transformerOutput, quant_bit_width* input_normalized, quant_bit_width* qkv, quant_bit_width* intermediate, void * kperf); +quant_bit_width compute_log_amp(int32_t real, int32_t imag); + +#endif //FVLLMONTITRANSFORMER_TRANSFORMER_H diff --git a/sw/applications/transformer/matMulC.c b/sw/applications/transformer/matMulC.c new file mode 100644 index 00000000..eb60c96c --- /dev/null +++ b/sw/applications/transformer/matMulC.c @@ -0,0 +1,22 @@ +// +// Created by alireza on 10/6/23. +// + +#include "matMulC.h" +#include + + +void MatMul_multiply(size_t seq_len, quant_bit_width* input, quant_bit_width* weight, + quant_bit_width* output, size_t input_size, size_t output_size) { + printf("\rMul %dx%dx%d\n", seq_len, input_size, output_size); + multiply_cgra(input, seq_len, input_size, weight, output_size, output); +} + +void MatMul_scale(quant_bit_width* input, int shift_scale, size_t mat_size) { + + for (size_t i = 0; i < mat_size; i++) { + *input = (*input) >> shift_scale; + input++; + } +} + diff --git a/sw/applications/transformer/matMulC.h b/sw/applications/transformer/matMulC.h new file mode 100644 index 00000000..9844b787 --- /dev/null +++ b/sw/applications/transformer/matMulC.h @@ -0,0 +1,21 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_MATMULC_H +#define FVLLMONTITRANSFORMER_MATMULC_H + + +#include +#include "param.h" +#include "cgra.h" + +#define BLOCK_SIZE 4 + +typedef struct { +} MatMul; + +void MatMul_multiply(size_t seq_len, quant_bit_width* input, quant_bit_width* weight, quant_bit_width* output, size_t input_size, size_t output_size); +void MatMul_scale(quant_bit_width* input, int shift_scale, size_t mat_size); + +#endif //FVLLMONTITRANSFORMER_MATMULC_H diff --git a/sw/applications/transformer/multiply_cgra.c b/sw/applications/transformer/multiply_cgra.c new file mode 100644 index 00000000..69eef852 --- /dev/null +++ b/sw/applications/transformer/multiply_cgra.c @@ -0,0 +1,177 @@ +/* + ******************* +******************************* C SOURCE FILE ******************************* +** ******************* ** +** ** +** project : HEEPsilon ** +** filename : main.c ** +** version : 1 ** +** date : 01/10/23 ** +** ** +***************************************************************************** +** ** +** Copyright (c) EPFL ** +** All rights reserved. ** +** ** +***************************************************************************** +*/ + +/***************************************************************************/ +/***************************************************************************/ + +/** +* @file main.c +* @date 01/10/23 +* @brief An application to run a matrix multiplication. +* +*/ + +/****************************************************************************/ +/** **/ +/* MODULES USED */ +/** **/ +/****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "cgra_x_heep.h" +#include "cgra_bitstream.h" +#include "multiply_cgra.h" + +// For interrupt handling +#include "csr.h" +#include "handler.h" +#include "rv_plic.h" +#include "rv_plic_regs.h" +#include "hart.h" +#include "cgra.h" + + +/****************************************************************************/ +/** **/ +/* DEFINITIONS AND MACROS */ +/** **/ +/****************************************************************************/ + +// Size of the input buffer for the CGRA +#define CGRA_COL_INPUT_SIZE 4 + +/****************************************************************************/ +/** **/ +/* PROTOTYPES OF LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + + +// Handler for the CGRA interruption +void handler_irq_cgra(uint32_t id); + + +/****************************************************************************/ +/** **/ +/* GLOBAL VARIABLES */ +/** **/ +/****************************************************************************/ + +// Plic controller variables +volatile bool cgra_intr_flag; + +// CGRA variables +static cgra_t cgra; +static uint8_t cgra_slot; + +// CGRA input and output buffers +static int32_t cgra_input[CGRA_N_COLS][CGRA_COL_INPUT_SIZE] __attribute__ ((aligned (4))); + + +/****************************************************************************/ +/** **/ +/* LOCAL FUNCTIONS */ +/** **/ +/****************************************************************************/ + +void multiply_cgra(int * matrixA, int ROWS_A, int COLS_A, int * matrixB, int COLS_B, int * matrixC) +{ + int ROWS_B = COLS_A; + int ROWS_C = ROWS_A; + int COLS_C = COLS_B; + // Prepare the input vector for the CGRA + // Col 0: &B[0][0], nItLoopColsC, &A[0][0], &C[0][3] + cgra_input[0][0] = &matrixB[0]; + cgra_input[0][1] = COLS_C/CGRA_N_ROWS; + cgra_input[0][2] = &matrixA[0]; + cgra_input[0][3] = &matrixC[3]; + // Col 1: &C[1][0], &B[0][1], nItLoopsColsA, &A[1][0] + cgra_input[1][0] = &matrixC[COLS_C]; + cgra_input[1][1] = &matrixB[1]; + cgra_input[1][2] = COLS_A; + cgra_input[1][3] = &matrixA[COLS_A]; + // Col 2: &A[2][0], &C[2][1], &B[0][2], nItLoopColsC + cgra_input[2][0] = &matrixA[2*COLS_A]; + cgra_input[2][1] = &matrixC[2*COLS_C+1]; + cgra_input[2][2] = &matrixB[2]; + cgra_input[2][3] = COLS_C/CGRA_N_ROWS; + // Col 3: nItLoopRowsC, &A[3][0], &C[3][2], &B[0][3], + cgra_input[3][0] = ROWS_C/CGRA_N_COLS; + cgra_input[3][1] = &matrixA[3*COLS_A]; + cgra_input[3][2] = &matrixC[3*COLS_C+2]; + cgra_input[3][3] = &matrixB[3]; + + // Set CGRA kernel L/S pointers + for(int col_idx = 0 ; col_idx < CGRA_N_COLS ; col_idx++){ + cgra_set_read_ptr ( &cgra, cgra_slot, (uint32_t) cgra_input[col_idx], col_idx ); + } + + // CGRA Execution + cgra_intr_flag = 0; + cgra_set_kernel( &cgra, cgra_slot, 1 ); + // Wait until CGRA is done + while(cgra_intr_flag==0) { + wait_for_interrupt(); + } +} + +// Initialize the CGRA +void initCGRA(){ + // Init the PLIC + plic_Init(); + plic_irq_set_priority(CGRA_INTR, 1); + plic_irq_set_enabled(CGRA_INTR, kPlicToggleEnabled); + plic_assign_external_irq_handler( CGRA_INTR, (void *) &handler_irq_cgra); + + // Enable interrupt on processor side + // Enable global interrupt for machine-level interrupts + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + // Set mie.MEIE bit to one to enable machine-level external interrupts + const uint32_t mask = 1 << 11;//IRQ_EXT_ENABLE_OFFSET; + CSR_SET_BITS(CSR_REG_MIE, mask); + cgra_intr_flag = 0; + + // Load kernel + cgra_cmem_init(cgra_imem_bitstream, cgra_kmem_bitstream); + + cgra.base_addr = mmio_region_from_addr((uintptr_t)CGRA_PERIPH_START_ADDRESS); + // Select request slot of CGRA + cgra_slot = cgra_get_slot(&cgra); +} + +// Interrupt controller variables +void handler_irq_cgra(uint32_t id) { + cgra_intr_flag = 1; +} + +void countersInit(){ + // Enable and reset the CGRA performance counters + cgra_perf_cnt_enable(&cgra, 1); + cgra_perf_cnt_reset( &cgra ); +} + +/****************************************************************************/ +/** **/ +/* EOF */ +/** **/ +/****************************************************************************/ diff --git a/sw/applications/transformer/multiply_cgra.h b/sw/applications/transformer/multiply_cgra.h new file mode 100644 index 00000000..d43ba4fd --- /dev/null +++ b/sw/applications/transformer/multiply_cgra.h @@ -0,0 +1,6 @@ +#include "performance.h" + +// Multiply the matrix in the cgra +void multiply_cgra(int * matrixA, int rowsA, int colsA, int * matrixB, int colsB, int * matrixC); +void countersInit(); +void initCGRA(); \ No newline at end of file diff --git a/sw/applications/transformer/param.h b/sw/applications/transformer/param.h new file mode 100644 index 00000000..6e4163a4 --- /dev/null +++ b/sw/applications/transformer/param.h @@ -0,0 +1,26 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_PARAM_H +#define FVLLMONTITRANSFORMER_PARAM_H +#include "stdint.h" + +#define D_Q 4 +#define D_SEQ 120 +#define D_MODEL 16 +#define NUM_HEAD 4 +#define NUM_LAYERS 4 +#define D_FF 4 +#define D_EMBEDDING 400 + + +#define NUM_FRACTION_BITS 12 +#define MUL(x, y) (int32_t) (((int32_t)(x) * (int32_t)(y)) >> NUM_FRACTION_BITS) +#define MUL_LONG(x, y) (int64_t) (((int64_t)(x) * (int64_t)(y))) +#define MUL_HQ(x, y) (int32_t) (((int32_t)(x) * (int32_t)(y))) +#define SHIFT(x) ((x) >> NUM_FRACTION_BITS) + + +typedef int32_t quant_bit_width; +#endif //FVLLMONTITRANSFORMER_PARAM_H diff --git a/sw/applications/transformer/performance.c b/sw/applications/transformer/performance.c new file mode 100644 index 00000000..421d39be --- /dev/null +++ b/sw/applications/transformer/performance.c @@ -0,0 +1,62 @@ +#include "performance.h" + +// For the timer +#include "rv_timer.h" +#include "soc_ctrl.h" +#include "core_v_mini_mcu.h" + +// Timer +static rv_timer_t timer; + +void kcom_perfRecordStart( kcom_time_diff_t *perf ) +{ + timeStart( perf ); +} + +void kcom_perfRecordStop( kcom_time_diff_t *perf ) +{ + timeStop( perf ); +} + +void timeStart( kcom_time_diff_t *perf ) +{ + perf->start_cy = getTime_cy(); +} + +void timeStop( kcom_time_diff_t *perf ) +{ + perf->end_cy = getTime_cy(); + perf->spent_cy += perf->end_cy - perf->start_cy; +} + +uint64_t getTime_cy( ) +{ + static uint64_t out; + rv_timer_counter_read( &timer, HART_ID, &out ); + return out; +} + +//Initialize the timer +void timerInit() +{ + soc_ctrl_t soc_ctrl; + soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); + uint32_t freq_hz = soc_ctrl_get_frequency(&soc_ctrl); + + mmio_region_t timer_0_reg = mmio_region_from_addr(RV_TIMER_AO_START_ADDRESS); + + rv_timer_init( timer_0_reg, (rv_timer_config_t) { .hart_count = 2, .comparator_count = 1 }, &timer ); + + rv_timer_tick_params_t tick_params; + + // The same frequency is provaided to get one tick per cycle. + rv_timer_approximate_tick_params( freq_hz, freq_hz, &tick_params ); + rv_timer_set_tick_params(&timer, HART_ID, tick_params); + + // Juan: see if i cannot remove this! + rv_timer_irq_enable(&timer, HART_ID, 0, kRvTimerEnabled); + rv_timer_arm(&timer, HART_ID, 0, 1); + + rv_timer_counter_set_enabled(&timer, HART_ID, kRvTimerEnabled); + +} \ No newline at end of file diff --git a/sw/applications/transformer/performance.h b/sw/applications/transformer/performance.h new file mode 100644 index 00000000..301f4874 --- /dev/null +++ b/sw/applications/transformer/performance.h @@ -0,0 +1,63 @@ +#include +#include "cgra.h" + +typedef long int kcom_time_t; +typedef kcom_time_t kcom_param_t; + +typedef struct kcom_col_perf +{ + uint32_t cyc_act; + uint32_t cyc_stl; +} kcom_col_perf_t; + +typedef struct kcom_time_diff +{ + kcom_time_t start_cy; + kcom_time_t end_cy; + kcom_time_t spent_cy; +} kcom_time_diff_t; + +typedef struct kcom_timing +{ + kcom_time_diff_t sw; + kcom_time_diff_t cgra; + kcom_time_diff_t load; + kcom_time_diff_t input; + kcom_time_diff_t output; + kcom_time_diff_t reprogramCols; + kcom_time_diff_t bitstream; + kcom_time_diff_t proto; +} kcom_timing_t; + +typedef struct kcom_perf +{ + kcom_col_perf_t cols[CGRA_N_COLS]; + kcom_col_perf_t cols_max; + uint32_t cyc_ratio; // Stored *CGRA_STAT_PERCENT_MULTIPLIER + kcom_timing_t time; +} kcom_perf_t; + +typedef struct kcom_run +{ + kcom_param_t sw; + kcom_param_t conf; + kcom_param_t cgra; + kcom_param_t repo; +} kcom_run_t; + +typedef struct kcom_stats +{ + kcom_run_t avg; + uint32_t n; + uint32_t errors; + uint8_t *name; +} kcom_stats_t; + +#define HART_ID 0 + +void timerInit(); +uint64_t getTime_cy( ); +void timeStop( kcom_time_diff_t *perf ); +void timeStart( kcom_time_diff_t *perf ); +void kcom_perfRecordStop( kcom_time_diff_t *perf ); +void kcom_perfRecordStart( kcom_time_diff_t *perf ); \ No newline at end of file diff --git a/sw/applications/transformer/selfattentionC.c b/sw/applications/transformer/selfattentionC.c new file mode 100644 index 00000000..7b0c175a --- /dev/null +++ b/sw/applications/transformer/selfattentionC.c @@ -0,0 +1,68 @@ +// +// Created by alireza on 10/6/23. +// + +#include +#include "selfattentionC.h" + + +void create_SingleHeadSelfAttn(SingleHeadSelfAttn* self_attn, size_t pre_seq_len, size_t input_dim, size_t head_hidden_size, int32_t** weightVector) { + self_attn->pre_seq_len = pre_seq_len; + self_attn->head_hidden_size = head_hidden_size; + createDense(self_attn->query_layer, input_dim, head_hidden_size, weightVector[0], NULL); + createDense(self_attn->key_layer, input_dim, head_hidden_size, weightVector[1], NULL); + createDense(self_attn->value_layer, input_dim, head_hidden_size, weightVector[2], NULL); +} + +void destroy_SingleHeadSelfAttn(SingleHeadSelfAttn* self_attn) { + free(self_attn->query_layer_out); + free(self_attn->key_layer_out); + free(self_attn->key_transposed_layer_out); + free(self_attn->value_layer_out); + free(self_attn->attention_scores); + + destroyDense(self_attn->query_layer); + destroyDense(self_attn->key_layer); + destroyDense(self_attn->value_layer); + + free(self_attn); +} + +void removeExtraCols(int32_t* input, size_t rows, int cols) { + int nElems = 3; + for(int r = 1; r < rows; r++, nElems+=3){ + for(int c = 0; c < cols -3; c++){ + input[r*cols+c -nElems] = input[r*cols+c]; + } + } +} + +void compute_SingleHeadSelfAttn(SingleHeadSelfAttn* self_attn, int32_t* input, int32_t* output, int32_t* qkv, int32_t* intermediate) { + self_attn->query_layer_out = qkv; + self_attn->key_layer_out = qkv + self_attn->pre_seq_len * self_attn->head_hidden_size; + self_attn->value_layer_out = qkv + 2 * self_attn->pre_seq_len * self_attn->head_hidden_size; + self_attn->key_transposed_layer_out = qkv + 3 * self_attn->pre_seq_len * self_attn->head_hidden_size; + + // This 3 mmul need to think they have 124 rows instead of 121 + // TODO: Check that the outputs have enough space for the extra 3 rows + computeDense(self_attn->query_layer, self_attn->pre_seq_len +3, input, self_attn->query_layer_out); // 121x16x4 + computeDense(self_attn->key_layer, self_attn->pre_seq_len +3, input, self_attn->key_layer_out); // 121x16x4 + computeDense(self_attn->value_layer, self_attn->pre_seq_len +3, input, self_attn->value_layer_out); // 121x16x4 + + transpose_quant(self_attn->key_layer_out, self_attn->key_transposed_layer_out, self_attn->pre_seq_len +3, self_attn->head_hidden_size); + MatMul_scale(self_attn->key_transposed_layer_out, 1, (self_attn->pre_seq_len +3) * self_attn->head_hidden_size); + + // 121x4x121 + MatMul_multiply(self_attn->pre_seq_len +3, self_attn->query_layer_out, self_attn->key_transposed_layer_out, intermediate, self_attn->head_hidden_size, self_attn->pre_seq_len +3); + + printf("\rRemove cols\n"); + // 121x124 -> 121x121 Remove extra cols + removeExtraCols(intermediate, self_attn->pre_seq_len, 124); + + printf("\rSoftmax\n"); + // Now intermediate is 121x121 + computeSoftmax(intermediate, self_attn->pre_seq_len); + + // 121x121x4 + MatMul_multiply(self_attn->pre_seq_len +3, intermediate, self_attn->value_layer_out, output, self_attn->pre_seq_len, self_attn->head_hidden_size); +} diff --git a/sw/applications/transformer/selfattentionC.h b/sw/applications/transformer/selfattentionC.h new file mode 100644 index 00000000..b2e3ab2c --- /dev/null +++ b/sw/applications/transformer/selfattentionC.h @@ -0,0 +1,35 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_SELFATTENTIONC_H +#define FVLLMONTITRANSFORMER_SELFATTENTIONC_H + +#include +#include +#include +#include "dense_layerC.h" +#include "softmaxC.h" +#include "transposeC.h" +#include "matMulC.h" +#include "param.h" +#include "cgra.h" + +typedef struct { + Dense* query_layer; + Dense* key_layer; + Dense* value_layer; + int32_t* query_layer_out; + int32_t* key_layer_out; + int32_t* key_transposed_layer_out; + int32_t* value_layer_out; + int32_t* attention_scores; + size_t pre_seq_len; + size_t head_hidden_size; +} SingleHeadSelfAttn; + +void create_SingleHeadSelfAttn(SingleHeadSelfAttn*, size_t pre_seq_len, size_t input_dim, size_t head_hidden_size, int32_t** weightVector); +void destroy_SingleHeadSelfAttn(SingleHeadSelfAttn* self_attn); +void compute_SingleHeadSelfAttn(SingleHeadSelfAttn* self_attn, int32_t* input, int32_t* output, int32_t* qkv, int32_t* intermediate); + +#endif //FVLLMONTITRANSFORMER_SELFATTENTIONC_H diff --git a/sw/applications/transformer/softmaxC.c b/sw/applications/transformer/softmaxC.c new file mode 100644 index 00000000..f9f8bd2b --- /dev/null +++ b/sw/applications/transformer/softmaxC.c @@ -0,0 +1,38 @@ +// +// Created by alireza on 10/6/23. +// + +#include "softmaxC.h" + + +void computeSoftmax(int32_t* input, size_t seq_len) { + size_t width = seq_len; + float input_float = 0.0f; + for (int i = 0; i < seq_len; i++) { + // Look for the biggest value of the row + int32_t max_val = input[i * seq_len]; + for (int j = 1; j < width; j++) { // Assuming its squared (width = seq_len) + if (input[i * seq_len + j] > max_val) { + max_val = input[i * seq_len + j]; + } + } + for (int j = 0; j < width; j++) { + input[i * seq_len + j] = (int32_t) fmax(input[i * seq_len + j] - max_val, -32767); + } + // Sum all values on the row + int32_t sum = 0; + for (int j = 0; j < width; j++) { + input_float = (float) input[i * seq_len + j] / (float) (1 << NUM_FRACTION_BITS); + input_float = expf(input_float); + input[i * seq_len + j] = (int32_t) (input_float * (1 << NUM_FRACTION_BITS)); + sum += input[i * seq_len + j]; + } + float sum_float = (float) sum / (float) (1 << NUM_FRACTION_BITS); + float sum_inv = (float) (1 / (sum_float + 0.00001)); // prevent zero divide! + int32_t sum_inv_int = (int32_t) (sum_inv * (1 << NUM_FRACTION_BITS)); + for (int j = 0; j < width; j++) { + input[i * seq_len + j] = (int32_t) MUL(input[i * seq_len + j], sum_inv_int); + } + } +} + diff --git a/sw/applications/transformer/softmaxC.h b/sw/applications/transformer/softmaxC.h new file mode 100644 index 00000000..fa47176f --- /dev/null +++ b/sw/applications/transformer/softmaxC.h @@ -0,0 +1,17 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_SOFTMAXC_H +#define FVLLMONTITRANSFORMER_SOFTMAXC_H + +#include +#include +#include +#include +#include "param.h" + +void computeSoftmax(int32_t* input, size_t seq_len); + + +#endif //FVLLMONTITRANSFORMER_SOFTMAXC_H diff --git a/sw/applications/transformer/stftVec.h b/sw/applications/transformer/stftVec.h new file mode 100644 index 00000000..62243064 --- /dev/null +++ b/sw/applications/transformer/stftVec.h @@ -0,0 +1,3 @@ +#include + +int32_t stftVec[49920] = {14912, 16305, 15424, 7300, 9641, 14329, 15823, 14833, 8710, 8912, 12488, 14281, 12956, 9398, 6336, 9702, 11379, 9458, 8448, -1345, 9383, 7575, 5905, 6193, 3111, 9534, 6388, 5963, 4307, 3857, 8353, 3661, 5646, 4840, 2974, 7109, 3348, 5522, 5048, 3034, 7513, 5345, 5058, 3058, 4169, 7233, 5680, 3618, -1939, 4739, 5392, 5531, 33, 3007, 4967, 5296, 5527, 2470, 3793, 5821, 6674, 5596, 4762, 3355, 6805, 6530, 6062, 5061, 3296, 7232, 4892, 6914, 3984, 3459, 7001, 1128, 7354, 1476, 3216, 6049, -4246, 7120, -809, 2509, 4113, 1815, 6269, 1109, 1261, 649, 3559, 4808, 1742, -1118, -2260, 4541, 2638, 1333, -3683, -2573, 5324, 1096, -41, -624, -6914, 5797, 1474, -749, 1036, -1670, 5676, 1178, 1827, 1675, -136, 4838, -524, 2920, 1334, -531, 3606, -5997, 2613, -295, 48, 2645, -2879, 1699, -2664, 1454, 969, -350, 1126, -2504, 1496, -4513, 428, 343, -2119, -288, -2229, 1388, -1021, -1983, -3119, -993, 1492, -842, -2102, -953, -1, -371, 77, -3653, -82, 1169, -1377, 613, -13738, -824, 674, 323, 1161, -3526, -3042, -2042, -359, 1511, -495, -3982, -2008, -5367, 1620, 1015, -2366, 202, -646, 1594, 1724, -2351, 739, 1997, 1015, 1845, -2589, 177, 2716, -743, 1526, -470, -1415, 2187, -4764, 870, 808, -3751, 227, -6828, -105, 405, -2589, -2027, -4123, -1632, -2546, -762, -542, -3523, -4738, -7353, -263, -416, -3632, -11115, -1954, -1127, -2297, -2954, -4223, -1644, -3840, -5020, -878, -3430, -2904, -10526, -3978, 912, -4403, -3360, -6759, -4464, 1940, -4478, -2115, -5273, -6310, 2291, -4053, -1078, -4874, -7426, 2178, -5158, -729, -4946, -5026, 1817, -7019, -795, -4583, -3242, 1282, -4693, -973, -3386, -2762, 493, -3012, -1475, -2270, -2920, -526, -3119, -2724, -2058, -3040, -1411, -4985, -5214, -3154, -2122, -1653, -5183, -11004, -4021, -1058, -1492, -3140, -6113, -1651, -856, -1647, -2264, -3441, -398, -1874, -2567, -2166, -2328, -798, -4980, -4395, -2596, -2396, -3644, -6692, -6640, -3482, -3798, -7317, -2442, -9695, -4718, -7081, -2114, -1099, -12776, -6194, -10210, -933, -1213, -7281, -6705, -7503, -1230, -2569, -5561, -6399, -4361, -2941, -5049, -4606, -5694, -2735, -8393, -7371, -3951, -4559, -2440, -6246, -6732, -3286, -3792, -3112, -4097, -4957, -3010, -3817, -4315, -5844, -3629, -3569, -5020, -5387, -6388, -2664, -5189, -8333, -6113, -2933, -3172, -7335, -9106, -7623, -2443, -5793, -6899, -6885, -8790, -3850, -8549, -6246, -6705, -6422, -6173, -5584, -6214, -8112, -5561, -6842, -3056, -5853, -11115, -5960, -6204, -2619, -5710, -8982, -6899, -5422, -3612, -6354, -6516, -7562, -5662, -4805, -6666, -5380, -5988, -8942, -4464, -5836, -6103, -4564, -7665, -3820, -5569, -8363, -3404, 10828, 5093, 9764, -637, -1552, 10180, 2996, 9296, 6157, -1414, 7937, 1593, 7768, 8228, -1236, 3042, 5579, 4561, 8634, -1291, 5745, 5866, -6705, 8019, 155, 7198, 3995, 2562, 6854, 2672, 6888, 2944, 4211, 6122, 4286, 5550, 4832, 4819, 6019, 4892, 5059, 5588, 5210, 5793, 4758, 5333, 5427, 5537, 5286, 4384, 4038, 4426, 5806, 4500, 4318, 2973, 2464, 5976, 4362, 4433, 5399, 2003, 5762, 5286, 4124, 6167, 3180, 4809, 5521, 2925, 5501, 3242, 2970, 4332, 1057, 4220, 2436, 677, 1175, 673, 3549, 1524, -996, -167, 1419, 3283, 855, -620, 1349, 1891, 3126, 21, 330, 1025, 1342, 3396, -364, 327, -259, -1672, 3904, 71, -113, -1710, -6133, 4303, -450, 51, -3479, -1414, 4283, -3264, 810, -3551, -2265, 3610, -6553, 1101, -15, -3014, 2068, -975, 654, 2445, -489, -830, 960, -122, 3656, 93, -5306, 1371, -1404, 3822, -1012, -2156, 480, -2754, 3166, -4172, -672, -1771, -874, 2085, -8220, -826, -4369, 125, 855, -4587, -2741, -5810, -768, -817, -3047, -6434, -8304, -5387, -1710, -1638, -3329, -2813, -2703, -143, -570, -1822, -1158, 622, 1100, -62, -1450, -1265, 1921, 1670, -287, -1317, -885, 2352, 1712, -1175, -749, 658, 2223, 1136, -476, 383, 1404, 1729, -347, 1100, 1501, 1061, 1107, -1263, 1494, 2095, -436, 523, 769, 671, 1946, -3210, -247, 1958, -288, 949, -4718, -1497, 1982, 172, -953, -3906, -2817, 1200, 314, -3714, -2514, -3680, 118, -902, -5827, -757, -4795, -515, -4974, -5055, -82, -5592, -101, -5554, -3961, -884, -5933, 355, -1759, -3638, -3811, -7708, -148, -1153, -4611, -11004, -9064, -1975, -2050, -6628, -7066, -5638, -3629, -3916, -6914, -10138, -3680, -2139, -5897, -8982, -6516, -2553, -1392, -8304, -9106, -3362, -1838, -1752, -14784, -4184, -2143, -1250, -3007, -9936, -2855, -1925, -717, -3695, -7644, -3151, -2452, -369, -2181, -5988, -4708, -3049, -406, -1225, -4564, -6602, -2813, -792, -1364, -3741, -5897, -2208, -1155, -2590, -3824, -4028, -1736, -1501, -5768, -5031, -2655, -1393, -2299, -7426, -5979, -2328, -1391, -3447, -2811, -5085, -3314, -2265, -3927, -1129, -4344, -5091, -4821, -3474, -589, -3947, -4532, -5623, -2869, -734, -4086, -4238, -3644, -2960, -1232, -4991, -6388, -3824, -4195, -1711, -5189, -11115, -5121, -4853, -2061, -3415, -5208, -4620, -2935, -2325, -1779, -3653, -3518, -1713, -2205, -884, -3294, -2666, -1488, -1954, -786, -3284, -1922, -2323, -2517, -1617, -3324, -1739, -4929, -5037, -4168, -3501, -2587, -9479, -5646, -10613, -4234, -5299, -4821, -2382, -2999, -6504, -7066, -3704, -1370, -1359, -28777, -4180, -3334, -1195, -1571, -6457, -2863, -2720, -882, -3203, -4974, -1921, -2339, -720, -4649, -4918, -1642, -2490, -1214, -4693, 8017, 5947, 8461, -2751, 9815, 7223, 6127, 8022, 2956, 9154, 4829, 5941, 7036, 5360, 7050, 4691, 5145, 5777, 5602, 3055, 6247, 4556, 3163, 3280, 1784, 6437, 3659, 2851, -3773, 4380, 5688, 1593, 5111, 3385, 4920, 4215, -50, 5408, 4045, 2722, 2053, -1742, 5027, 3237, 1031, 686, -10526, 5369, 2846, 5125, 2484, -1146, 6142, 3540, 5804, 4808, 926, 6608, 4504, 5018, 5994, 2364, 6477, 4881, 5104, 5893, 3248, 5468, 4141, 5982, 4460, 3000, 3115, 1903, 6320, 1467, 1021, -374, -2309, 6455, -3121, -5933, 1092, -3853, 6291, -4226, -2543, 1916, -3034, 5247, -2984, -312, 1637, -1636, 2669, -1564, 1060, 993, 444, -5085, -348, 2313, 309, 2137, -1156, 752, 2779, -235, 3077, 440, 1579, 2012, 269, 3224, 1158, 1843, -941, 1646, 2635, 2681, 1328, -8165, 2411, 1417, 3713, -223, -1668, 2049, 42, 3602, -2294, -1941, 537, -310, 2031, -1652, -2813, -577, 669, 624, -1099, -1117, 2, 1906, 2465, -1414, -852, -10, 2704, 3213, -1290, -2107, -628, 2970, 2815, -1178, -3975, -987, 2822, 2019, -1959, -4119, -1014, 2387, 1699, -3856, -2022, -896, 1673, 1995, -4500, -99, -984, 548, 2192, -1913, 1011, -757, -1355, 1698, -643, 1138, 883, -4408, 100, -1165, 162, 2147, -2661, -3259, -1635, -1216, 2327, -155, -10284, 1244, -206, 1579, 1159, -5793, 2667, 1028, 571, 1620, -2739, 2356, 869, 144, 1279, -1083, 29, -1014, -14, 96, -609, -8754, -1797, -161, -2169, -1144, -3281, -350, -385, -5554, -1973, -2571, -1009, -768, -4274, -1250, -3947, -4929, -1129, -3638, -687, -5509, -7464, -1615, -4331, -1858, -6204, -5584, -2211, -2430, -3557, -5531, -10001, -2042, -703, -856, -3471, -4115, -1611, -507, 467, -2635, -2046, -1894, -2326, 329, -3692, -1847, -2990, -6007, -1055, -9479, -2388, -5020, -991, -3992, -4559, -2541, -9936, 756, -8718, -2172, -2325, -5115, 971, -5266, -1954, -2102, -2722, 152, -3879, -3031, -2394, -2316, -1551, -4837, -4810, -3609, -3436, -3927, -12123, -5960, -3615, -4980, -4319, -4003, -5380, -2853, -3299, -3027, -1630, -4795, -4064, -1941, -2835, -1077, -4963, -9238, -1576, -4226, -1491, -5836, -5735, -1713, -9873, -2353, -7484, -4478, -1912, -6666, -3025, -11629, -5509, -2004, -3923, -3124, -14195, -7503, -2003, -3735, -2847, -9238, -6928, -2170, -4550, -2569, -5020, -4597, -2973, -3876, -2259, -2514, -3147, -5360, -2971, -1992, -1383, -2703, -12319, -3367, -2531, -1215, -2447, -5524, -4674, -5043, -1759, -1943, -4270, -3930, -6719, -2637, -1755, -4555, -2320, -4064, -2416, -1813, -4743, -1622, -4659, -1259, -1760, -5422, -1971, -7774, -641, -2088, -9479, -3574, -5638, -733, -3194, -6943, -7034, -5465, -1246, -4307, -4230, -12319, -8942, -1642, -3947, -3735, -8220, -7464, -4545, -4420, -4100, -4527, -2182, -4157, -5654, -1990, -2831, -1894, -4089, -5888, -1433, -2648, -3083, -3365, -4659, -2673, -3172, -6225, -3215, -3261, -5988, -3647, -8333, -3191, -2580, -17034, -2939, -6928, -2590, -2912, -6553, -2438, -6759, -2232, -4230, -3594, -3465, -5718, -2718, -5988, -3135, -5599, -4219, -4365, -10069, -4274, -3331, -3748, -9022, -6842, -6225, -1217, -4238, -7408, -4980, -8304, -146, -4067, -4145, -5906, -8683, 89, -3286, -3362, -5638, -5031, -634, -3577, -3580, -4491, -3430, -2642, -5726, -3621, -6173, -3378, -6246, -11356, -3455, -7445, -4523, -5793, -7644, -3968, -5710, -6640, -4858, -7066, -4805, -5429, -7004, -5906, -10899, -4968, -3444, -4923, -7752, -8165, -5576, -3114, -3680, -4319, -4242, -7464, -4991, -2851, -2485, -2437, -6615, -8165, -1779, -2273, -1313, -5662, -7523, -1053, -3326, -705, -6870, -4858, -1173, -4831, -749, -9064, -3311, -2031, -5415, -1427, -10069, -2891, -3342, -4951, -2348, -6103, -2977, -4957, -4532, -2809, -3076, -2952, -5444, -4826, -2731, -1731, -2861, -4093, -5810, -2825, -1404, -2952, -3801, -6492, -3680, -1752, -3650, -5759, -6553, -5444, -2937, -5726, -8942, -6958, -7623, -5638, -10526, -5906, -7865, -9429, -6828, -12534, -6434, -8903, -8086, -4597, -10442, -11004, -8363, -4935, -4299, -7687, -5554, -6516, -3232, -5743, -5374, -3609, -4754, -3067, -8276, -4270, -3554, -3560, -4713, -6045, -4278, -4847, -3149, -8942, -4550, -4946, -6354, -3537, -14784, -4759, -5970, -5202, -4319, -8549, -6759, -7050, -4035, -4390, -3710, -6885, -6540, -3653, -3415, -1844, -3763, -5531, -3883, -2969, -1482, -2312, -4912, -4184, -4003, -2247, -2188, -4399, -3309, -7752, -3923, -3301, -3820, -2055, -7503, -5615, -5227, -3609, -1579, -5279, -5694, -5879, -4555, -2116, -5607, -4698, -5145, -7842, -3476, -7960, -3543, -4082, -8138, -4592, -15615, -2543, -3187, -5260, -5227, -10442, -1836, -3163, -4455, -6007, -9585, -1480, -4130, -3920, -5997, -12319, -1490, -4219, -2982, -4688, -13365, -1631, -2859, -2295, -3259, -9238, -1475, -2268, -2720, -2843, -7019, -1047, -2589, -5592, -3754, -5670, -787, -3692, -9238, -6321, -4211, -1091, -5776, -4779, -13738, -2752, -2452, -8247, -4616, -9936, -2111, -6016, -6856, -5170, -7644, -2749, -13365, -5951, -5170, -7623, -5115, -7936, -5646, -5458, -9238, -8393, -8192, -5480, -6153, -9193, -6214, -6143, -6354, -7464, -7912, -5862, -4718, -9380, -9238, -8517, -8304, -4523, -8165, -6800, -8304, -10799, -5183, -6504, -5380, -5437, -5630, -6133, -7796, -5026, -3741, -4028, -6153, -28777, -4455, -3261, -3717, -5844, -8582, -4258, -3707, -4254, -5836, -7113, -5020, -4464, -5554, -6163, -7179, -6679, -4842, -7130, -8009, -7353, -8718, -5266, -7960, -13049, -7503, -9585, -6214, -8034, -11945, -6973, -9106, -8192, -9284, -10284, -6267, -6899, -13738, -10613, -5487, -6246, -5408, -12776, -6007, -3717, -4555, -2540, -3259, -2526, -6814, -5214, -5014, -4513, -4361, -7665, -12123, -6914, -5266, -3850, -3689, -4858, -4176, -5827, -2472, -2419, -2973, -2615, -6773, -2116, -2401, -3982, -2319, -5759, -2344, -3165, -6540, -3404, -4683, -2664, -4759, -4100, -6299, -4611, -2778, -8683, -3279, -6528, -4625, -2470, -7623, -4097, -4718, -4555, -2247, -3804, -5801, -3741, -6143, -2831, -2311, -7623, -2743, -13365, -4674, -2091, -9429, -1872, -4946, -8165, -3203, -7603, -1785, -3001, -10284, -6516, -5208, -2929, -2557, -8942, -6288, -4315, -5924, -2735, -6528, -3817, -4093, -12534, -3441, -5592, -3449, -3399, -5333, -5897, -7523, -4003, -2567, -3135, -9639, -9753, -4518, -2483, -2655, -3329, -5121, -4509, -3479, -3701, -1581, -4810, -4541, -5599, -6173, -1304, -5743, -5768, -5480, -5319, -1830, -3889, -8333, -3281, -4104, -2596, -2847, -4564, -2084, -3893, -3220, -2945, -1420, -1892, -3641, -4003, -3096, 102, -2587, -3659, -5487, -3447, 272, -3763, -4395, -8086, -4784, -888, -4620, -4880, -10526, -5234, -3698, -5374, -4365, -7730, -3863, -8192, -6516, -4149, -5091, -3463, -3504, -8192, -3656, -3490, -4416, -1397, -10138, -2937, -2999, -7213, -731, -8982, -3296, -3635, -5221, -890, -6376, -5694, -4923, -2714, -1481, -3723, -12319, -4874, -2390, -2344, -1961, -5702, -3717, -4592, -3653, -1198, -4086, -2877, -9022, -6204, -1377, -3788, -2650, -2819, -13738, -2488, -4149, -3184, -1308, -7464, -4654, -5221, -4282, -1307, -6016, -8009, -8549, -5480, -2356, -6692, -11781, -8485, -7019, -4486, -7644, -6732, -3779, -8393, -8304, -5960, -3269, -1903, -5654, -17034, -4644, -1553, -1214, -3482, -13738, -4352, -1036, -1380, -2472, -8009, -4743, -1560, -2359, -2308, -6288, -5133, -3135, -4307, -2809, -7213, -4743, -5494, -7503, -3603, -5784, -4509, -5615, -10001, -4127, -2594, -5333, -4513, -9022, -4149, -1202, -7162, -4199, -7984, -3883, -1068, -8009, -4373, -6640, -3795, -2002, -6332, -4573, -5694, -4336, -4024, -4759, -4518, -5718, -5997, -7644, -4369, -4274, -7644, -9022, -9064, -5429, -4344, -10526, -7019, -6422, -8192, -4800, -5061, -4578, -6173, -9873, -4578, -3417, -3196, -8165, -8276, -3589, -3656, -2383, -12319, -6516, -3309, -5260, -2084, -11356, -4469, -4274, -6083, -2228, -10799, -3010, -7623, -6123, -2733, -12319, -2455, -10526, -7281, -3827, -28777, -2960, -5480, -5670, -5524, -10799, -4743, -4635, -3903, -6388, -6928, -4698, -5702, -3324, -6007, -4810, -2557, -7264, -3592, -5465, -3603, -1878, -6480, -4486, -5183, -3126, -2516, -6267, -5569, -5008, -3509, -3985, -7389, -5960, -4644, -5319, -5394, -8683, -5387, -4469, -9936, -6310, -8138, -4874, -4874, -8683, -5638, -6943, -5247, -5694, -7603, -4800, -5862, -6577, -6842, -8982, -5339, -4858, -7687, -8060, -12534, -7408, -4583, -7066, -8615, -17034, -6434, -5924, -6173, -8276, -8827, -5253, -12319, -6007, -7687, -5646, -6553, -1616, -3168, -4523, -6016, -3795, -1521, -2644, -7130, -5091, -1944, -1469, -2478, -11115, -4863, -1434, -1404, -2879, -4795, -4006, -2223, -1601, -3860, -2770, -1831, -3982, -2524, -5458, -2497, -198, -5026, -4698, -9064, -3600, 328, -4013, -9380, -8754, -4429, -321, -2904, -11004, -5844, -3707, -2216, -2825, -12123, -5630, -3964, -5827, -3476, -12319, -6773, -4853, -12776, -3989, -7445, -7752, -4569, -4837, -4644, -6093, -7066, -4597, -2904, -5524, -5654, -6054, -5170, -2916, -5401, -5569, -4455, -3735, -4420, -4344, -5451, -2621, -1704, -5630, -3493, -4674, -1621, -745, -5472, -2865, -2960, -1343, -1158, -7353, -1661, -1247, -1313, -3352, -12319, -744, -222, -1299, -7247, -7936, -858, 81, -1263, -4896, -10613, -2191, -231, -1343, -3261, -7644, -4482, -1159, -1726, -2947, -4679, -3474, -2504, -2605, -4142, -4053, -1219, -3286, -3913, -6183, -4010, 40, -3726, -3574, -4795, -3732, 355, -4880, -1321, -3883, -3208, -275, -7299, 124, -4630, -3463, -1966, -13049, 606, -6988, -6007, -3563, -5906, 326, -8942, -8865, -2741, -4278, -326, -8247, -5465, -2248, -4491, -836, -5292, -4601, -1898, -4635, -1391, -3729, -3827, -1090, -3551, -2791, -3971, -3175, -619, -2560, -5133, -6016, -2642, -662, -2094, -5008, -10704, -2646, -816, -2348, -4266, -11115, -3352, -1060, -3471, -4688, -6246, -2737, -1822, -5451, -4912, -4203, -1507, -3085, -6899, -3671, -3304, -1426, -4262, -5319, -2751, -2895, -2861, -5360, -4203, -2811, -2619, -6928, -7196, -3982, -3580, -2599, -10138, -9812, -4523, -3944, -3227, -6376, -6528, -5686, -3430, -4991, -4299, -4149, -5333, -3161, -7984, -2364, -3189, -3923, -3476, -6958, -1409, -3163, -3412, -3999, -5109, -1477, -3961, -3606, -3957, -4601, -2559, -6299, -4348, -3653, -5751, -4130, -11356, -5670, -4086, -10704, -4504, -7050, -5915, -5897, -10526, -4601, -8009, -4254, -7196, -8827, -4211, -6870, -2685, -5662, -8582, -2813, -2803, -1836, -5906, -5516, -2305, -1349, -1816, -9380, -4447, -3247, -1220, -2386, -10799, -5240, -6422, -1849, -3294, -5735, -8363, -8582, -2821, -4644, -3833, -17034, -5546, -3795, -4703, -3045, -15615, -5067, -4250, -3535, -2887, -8582, -5718, -4331, -3644, -2931, -4929, -7130, -5014, -5531, -3147, -3476, -7503, -6343, -7066, -3482, -3554, -4805, -6354, -5394, -3889, -5607, -2731, -5531, -5686, -4550, -28777, -1501, -6133, -9429, -5592, -6719, -926, -12534, -9331, -7130, -5988, -990, -6214, -6640, -9238, -9331, -1743, -3326, -7353, -11945, -8220, -3261, -2889, -9106, -17034, -5776, -4991, -4226, -8086, -13738, -5253, -5195, -8165, -7960, -11488, -3695, -4559, -9284, -6856, -10799, -2517, -4336, -6928, -4640, -11629, -2720, -4923, -6615, -3447, -13365, -4513, -6640, -6786, -3314, -13049, -8333, -9064, -6692, -3916, -28777, -9022, -8333, -6133, -4500, -9429, -7213, -7034, -6064, -4258, -7264, -6434, -6705, -6666, 932, 7831, 7734, 5628, 2792, 5612, 7584, 7412, 5643, 3008, 7135, 6918, 6604, 5495, 2765, 6849, 6058, 5777, 4981, 1614, 6250, 5237, 5093, 4168, 1506, 6575, 4429, 4081, 3167, 2167, 6332, 3603, 2703, 2383, 1879, 4534, 3082, 2056, 3001, 993, 3610, 3376, 2564, 4093, 389, 5459, 4085, 3280, 4615, 372, 6118, 4222, 3667, 4530, 2164, 5969, 3504, 3511, 3670, 4618, 5289, 2286, 2860, 1070, 6124, 3514, 1379, 2043, -2992, 6525, -1364, 1278, 1404, 1455, 5802, -978, 1386, 1268, 2186, 3730, 1196, 584, 1598, 1340, -866, 922, -1921, 1457, 769, -4713, -145, -4564, 368, 1357, -1004, -636, -1618, -1302, 1839, -702, -80, -725, -2412, 2166, -1106, 443, -2079, -3261, 2277, -1727, 577, -3618, -6365, 1796, -2718, 249, -744, -6045, 720, -4863, -707, 556, -2038, -108, -10799, -2226, 1149, -860, -359, -9193, -3430, 1821, -474, -807, -6528, -4184, 2401, -299, -1386, -4168, -5853, 2410, -639, -2007, -2487, -6786, 1465, -1693, -3311, -1512, -4365, -930, -3110, -6628, -773, -3529, -2578, -3985, -10526, -262, -4290, -251, -4918, -5121, -291, -6492, 561, -6153, -3378, -1169, -9064, -98, -4918, -1758, -3326, -5516, -2714, -3444, -714, -7796, -3103, -3788, -2713, -804, -6988, -1880, -81, -2328, -1839, -3184, -1669, 1150, -2536, -2733, -1206, -2677, 582, -4258, -2391, -935, -5333, -2257, -9753, -1548, -2621, -5702, -2871, -9936, -1141, -1943, -4082, -887, -5353, -1427, 350, -3735, -1374, -2737, -1841, 835, -3507, -2276, -2207, -1448, 107, -2900, -716, -4191, -453, -520, -2289, 295, -6045, 217, -106, -1898, 182, -2333, 101, 222, -2008, -1052, -1240, -1064, -119, -2873, -3853, -1394, -4017, -1567, -4482, -8865, -2108, -7842, -3399, -5710, -7984, -2900, -2879, -1551, -4290, -5960, -4082, -1188, -263, -2294, -2567, -4242, -932, -254, -1130, -479, -2597, -2079, -1087, -1029, 454, -2294, -5339, -1921, -1894, 557, -4003, -4779, -2204, -1987, 202, -8827, -2457, -2797, -806, -339, -6376, -2121, -4527, -431, -1240, -4416, -3027, -7464, -1214, -2699, -2728, -3126, -5879, -3220, -4743, -864, -1900, -3940, -7842, -7665, 373, -2057, -3213, -8247, -6016, 477, -5055, -3386, -4923, -2300, -848, -6354, -3683, -4738, -13, -3650, -2904, -2813, -5002, 1256, -4523, -3051, -1623, -5227, 1543, -4611, -6093, -971, -6958, 712, -6256, -9812, -884, -4713, -1903, -7066, -6288, -1225, -2655, -15615, -5686, -6225, -1772, -1821, -3577, -5422, -7317, -2079, -1233, -2217, -7247, -7445, -1820, -1109, -2010, -4940, -5494, -1430, -2050, -2150, -2705, -3873, -1524, -4513, -3163, -2322, -3577, -2619, -7019, -5031, -3140, -5279, -5718, -5026, -4885, -4991, -7842, -12534, -4254, -3726, -10362, -4728, -6204, -4262, -2906, -6565, -3512, -5678, 4316, 6840, 4580, 3259, 2961, 3196, 6302, 4364, 4515, 4850, -2189, 4595, 3767, 5579, 6678, -8, 1191, 3113, 5479, 7398, 1764, -3457, 3130, 4156, 7223, -72, 553, 3813, 980, 6468, -7371, 2078, 4266, -23, 5328, -2265, 2586, 4023, 2669, 3707, -2463, 2829, 3190, 2994, 2463, -102, 3540, 2562, 2035, 2297, 2715, 4283, 2588, 2467, 1653, 4380, 4206, 2668, 3759, 2099, 4951, 3010, 2580, 4152, 3622, 4324, 1384, 2176, 3648, 4382, 2404, 1373, 1205, 2377, 4348, 941, 1380, -7, 487, 3747, 2119, 362, -75, -1494, 2973, 2771, -1351, 64, -2320, 2439, 2497, -1677, -1025, -2226, 1842, 1102, 224, -3422, -1604, 663, -1923, 1872, -5061, -679, -443, -1422, 2804, -5139, -1046, 330, -8, 3132, -1012, -4578, 1123, -743, 3080, 1385, -1940, 966, -3101, 2873, 2456, 533, 283, -2601, 2558, 2671, 941, -133, -1694, 1944, 2146, 846, -549, -2331, 805, 739, 952, -1741, -3735, -908, -1928, 513, -3463, -3203, -3018, -6256, -680, -3647, -1755, -5115, -8034, -1650, -4564, -1343, -5266, -6856, -1319, -2139, -1374, -4611, -3732, -501, 441, -37, -5494, -1592, -474, 1434, 1374, -7162, -797, -1931, 1590, 1724, -5924, -1475, -7162, 1209, 792, -6732, -3999, -4774, 4, -1714, -3957, -7019, -1597, -2432, -4399, -515, -7004, -533, -4433, -3830, 886, -7213, -678, -3360, -2885, 914, -6469, -2046, -2772, -823, -221, -12123, -2254, -3201, 351, -2128, -5020, -269, -5043, 406, -3049, -2102, 720, -8247, -453, -2027, -1515, 723, -9429, -1477, -926, -1857, -35, -6288, -644, -118, -1424, -1418, -5121, 610, 332, -336, -3010, -7130, 1036, 334, 407, -3726, -5509, 532, -84, 788, -3266, -3337, -942, -752, 896, -2929, -4046, -3027, -1414, 705, -3738, -4258, -3944, -2129, 86, -6064, -2058, -3638, -3543, -1160, -5387, -1560, -3501, -6914, -3441, -3671, -2279, -3978, -5561, -7146, -2516, -2531, -5202, -2555, -7213, -1473, -1336, -7179, -1366, -5509, -786, -174, -6958, -1460, -4743, -383, 263, -4089, -2606, -4890, -250, -23, -2473, -3457, -5818, -641, -581, -2185, -2791, -4957, -1481, -1194, -3626, -2176, -3158, -1772, -2403, -12776, -1952, -2175, -1504, -4482, -3018, -2062, -1852, -1760, -9331, -537, -2648, -1958, -2752, -4946, 15, -3985, -1967, -4592, -1143, -841, -6267, -1828, -9429, 148, -3334, -8485, -2964, -6856, -115, -8827, -7796, -11004, -4234, -1987, -10069, -6469, -3603, -3989, -4429, -28777, -4774, -1689, -2833, -1841, -7196, -3425, -2690, -1066, -410, -4980, -3259, -7162, -712, -360, -4816, -4733, -3135, -2079, -1277, -5546, -5415, -506, -4842, -1949, -6411, -3717, 630, -3686, -1086, -6679, -3085, 724, -2351, -227, -5539, -1996, -194, -1837, -24, -4536, -775, -2095, -1846, -600, 4204, 4660, 8026, 4595, 10348, 5216, 6364, 7879, 6734, 10114, 6388, 7902, 7603, 8184, 9483, 6672, 8301, 7352, 8347, 8510, 6065, 7650, 6789, 7585, 6985, 4981, 5876, 5470, 5887, 4510, 4088, 2554, 3362, 2625, 913, 3100, -926, 1407, -2228, -1682, 1032, 1499, 500, 1081, -984, -5374, 2541, -499, 1444, 74, -63, 2881, -21, -1083, 380, 2868, 3249, 2361, -2468, 2511, 3658, 3656, 3250, 2448, 4665, 2668, 3597, 2784, 4143, 5772, -546, 3238, 2202, 4779, 6199, 1526, 3364, 2774, 4899, 6270, 3139, 3512, 3183, 4641, 5958, 2564, 2909, 2858, 4004, 5026, -600, 1562, 1949, 2914, 3245, -4270, 109, 896, 1058, 679, 400, -274, 447, -2273, 42, 1204, 271, 808, -1407, 771, 785, 102, 1315, 1105, 385, 659, -2121, 1218, 2230, -1169, 1082, -6705, -6, 2556, -2267, 537, -1325, -2918, 2243, -1235, -1197, -490, -2675, 1355, -1544, -853, -1973, -450, 731, -2145, -220, -5415, 436, 1433, 489, -1404, -5630, 824, 2053, 1834, -3647, -3933, 1111, 1895, 1760, -3840, -1071, 1164, 1358, 889, -5561, 379, 857, 1312, 299, -6332, 591, 524, 1344, 648, -3080, 239, 679, 365, 1063, -1778, 463, 1396, -2128, 683, -575, 1417, 2220, -1558, -613, -261, 1921, 2688, -201, -1114, -2478, 1256, 2491, -850, -483, -5234, -1437, 1384, -2399, -648, -747, -3603, -914, -1382, -941, -779, -244, -2722, -688, 270, -3504, 390, -1014, -1146, 1486, -1465, -367, 121, -2292, 1870, -288, -1530, 429, -3773, 1307, -1486, -2531, 51, -4728, -401, -5480, -4028, -988, -4352, -3476, -12123, -5531, -2524, -3031, -7912, -7213, -5569, -4536, -1974, -28777, -4620, -5085, -4674, -2094, -10210, -3367, -5170, -1721, -3471, -8304, -3213, -5561, -277, -4826, -6256, -3444, -4784, -27, -4951, -4164, -4286, -4907, -532, -2670, -2130, -7796, -8192, -1419, -372, -1249, -6640, -4365, -2580, 615, -1821, -2967, -1713, -4282, 474, -3883, -1777, -1338, -6705, -574, -6958, -1553, -2962, -7050, -1909, -6083, -1713, -7644, -5979, -2574, -4601, -2608, -5319, -6133, -3795, -5234, -6194, -2805, -7299, -9064, -9238, -6692, -1369, -7281, -3161, -8517, -3201, -1020, -3444, -403, -6773, -2432, -1950, -828, 488, -7819, -1538, -3638, 235, 262, -4816, -647, -3883, -250, -765, -1513, -668, -3428, -2956, -2107, 221, -1687, -3294, -5240, -2637, 845, -3227, -3321, -2197, -2455, 567, -4211, -2766, -1743, -3438, -578, -4429, -1332, -2407, -10362, -2926, -4923, -359, -3801, -3609, -7842, -7603, -317, -4810, -877, -4469, -6143, -1126, -2950, -247, -2541, -1842, -2576, -1837, -697, -2922, -164, -5480, -1197, -1926, -7004, 63, -9531, -408, -5319, -5942, -1040, -2975, -67, -5183, -2497, -3692, -1281, -558, -960, -1859, -3840, -2176, -4053, -3080, -4795, -4290, -1389, -3754, -2438, -2566, -7335, -483, -3187, -1656, -1071, -4769, 227, -2231, -1377, -274, -2779, 499, -2701, -1962, 11, -2603, 361, -5465, -3194, -105, -2339, 37, -4569, -3883, -603, -1494, -218, -2971, -3071, -1480, -1470, -339, -4112, -1980, -2726, -2605, -705, -6814, -1701, -3227, -2447, -1825, -4382, -2442, -1534, -464, -3982, -3964, -3574, 24, 504, -4017, -4219, -3662, 867, 149, -2107, -2889, -2908, 1201, -1943, -1336, -2090, -2165, 1240, -6093, -1559, -2105, -2086, 1110, -4968, -2231, -1734, -3692, 520, -5049, -2076, 39, -10526, -1695, -603, -447, 2042, -1748, -2943, 1814, 1402, 3282, 518, 1279, 2560, 2470, 3513, 1056, 2696, 2051, 2503, 2648, 589, 2458, 359, 1399, 535, -181, 801, -2617, -1019, -3023, -357, -1397, -6343, -3801, -5654, -84, -1883, -7562, -2964, -5743, -332, -2805, -5584, -1599, -7687, -1928, -4464, -3846, -705, -12776, -6123, -4013, -3334, -459, -6045, -5784, -3062, -3769, -902, -3975, -4278, -2322, -4764, -2051, -3680, -4644, -1726, -5906, -3795, -5726, -5646, -1544, -6577, -5299, -7408, -5576, -2053, -6399, -4968, -2601, -4390, -4042, -6553, -3650, -1226, -4191, -14195, -7445, -2893, -1850, -4968, -2821, -6528, -3083, -5319, -3546, -393, -4718, -3373, -5951, -1532, 218, -3704, -2361, -3401, -735, -517, -3306, -1231, -4067, -1150, -2356, -2257, -607, -7445, -2686, -3257, -765, -349, -8485, -5127, -3430, -172, -510, -5599, -7523, -5472, -1054, -1458, -3213, -7389, -6422, -3496, -3814, -2080, -5951, -4587, -2158, -7503, -2356, -4315, -4504, -671, -4880, -4168, -3005, -3814, -1130, -3843, -9585, -2867, -2065, -4028, -3833, -8165, -4142, -1002, -9106, -3319, -5554, -6732, -713, -3850, -2398, -5853, -11945, -1125, -2774, -1831, -7842, -8034, -2292, -2248, -1784, -6958, -4191, -4311, -2020, -2216, -5079, -2853, -7371, -2562, -3237, -4242, -2608, -6842, -3612, -5227, -3618, -2962, -4606, -4223, -7050, -2762, -4053, -3415, -4708, -5524, -2214, -6133, -2776, -5026, -5415, -2317, -5836, -2592, -5374, -7752, -3060, -4172, -3025, -8112, -10138, -4500, -4013, -4046, -6565, -6988, -4885, -5592, -4901, -3311, -4654, -2900, -10799, -5152, -2507, -3420, -1932, -8718, -6214, -3187, -3580, -2276, -6745, -7408, -4918, -4968, -3626, -7730, -5055, -5997, -5743, -5152, -14784, -3206, -5827, -4282, -5924, -8034, -2182, -6422, -2920, -6528, -5387, -1613, -7936, -2179, -7408, -4386, -1411, -8718, -2104, -9238, -4138, -1513, -9639, -2728, -8942, -4842, -1716, -8683, -4226, -7842, -7335, -1868, -6288, -6288, -10526, -12123, -2152, -5888, -5933, -9753, -9380, -2941, -7708, -5067, -5458, -10799, -4442, -10284, -5195, -4587, -10001, -6035, -8649, -5494, -5888, -7774, -7081, -10799, -5306, -10442, -8009, -8304, -11356, -5055, -5988, -9812, -8615, -3900, -553, -5221, -2473, -2213, -3140, -1576, -5247, -3701, -4282, -2123, -3837, -3425, -6026, -2889, -1109, -3563, -4412, -11629, -1478, -291, -1218, -8333, -4157, -894, 217, 97, -3012, -1869, -830, 310, 567, -1073, -1373, -1528, -156, 288, -260, -2328, -3626, -1521, -787, 241, -4698, -8165, -5253, -2875, 333, -5026, -8060, -6054, -6565, -417, -3383, -6214, -2006, -7213, -2264, -3049, -3509, -1206, -3723, -3184, -3906, -1796, -2219, -2139, -2108, -3659, -1083, -5662, -1870, -1939, -1976, -998, -10001, -2316, -2718, -1005, -1446, -3650, -2795, -3978, -562, -2661, -972, -2877, -3735, -168, -4985, 1098, -740, -1271, 673, -3735, 2599, 1206, 435, 1678, -1448, 3280, 1886, 935, 1957, -1076, 2983, 1328, 255, 1045, -2863, 1566, -630, -1661, -1194, -6422, -1276, -4564, -4630, -2668, -2473, -5988, -3824, -4078, -2334, -1148, -6469, -1571, -2292, -2235, -1289, -5561, -511, -1786, -1513, -1826, -5710, -14, -3038, -1143, -1943, -6828, 6, -9380, -1432, -2883, -7408, -558, -2845, -1815, -8192, -5871, -1991, -925, -2204, -3817, -4482, -4858, -1420, -2675, -1124, -4006, -7389, -4784, -2574, -812, -3650, -5472, -7912, -2470, -1980, -1889, -5067, -3479, -3441, -3903, -280, -5509, -2686, -5576, -4723, 199, -4550, -2943, -4654, -4348, -712, -2378, -3554, -2825, -3597, -3244, -867, -4142, -2356, -3092, -2935, -259, -4315, -3455, -3172, -1121, -393, -3763, -7445, -4038, -624, -1052, -2999, -8649, -5312, -716, -2066, -2893, -6163, -3686, -813, -3447, -3247, -5970, -2030, -804, -3866, -3203, -5465, -1772, -1001, -3182, -2877, -4578, -2606, -1740, -3638, -2863, -3094, -3701, -3378, -4195, -3417, -1825, -3735, -6310, -2845, -5531, -1286, -2517, -4606, -2580, -6492, -1435, -1390, -2545, -4089, -3215, -2314, -1072, -2380, -5394, -2340, -4071, -1687, -3900, -3863, -3151, -5988, -3208, -5360, -3098, -5630, -4597, -4795, -3817, -2967, -12319, -2807, -5638, -3137, -3140, -9585, -1914, -7371, -3344, -3683, -5879, -2235, -6225, -4242, -4901, -2847, -4478, -5299, -6814, -7426, -826, -6310, -7445, -7603, -8220, 71, -3704, -4896, -4254, -5942, 63, -3269, -2205, -3373, -5319, -536, -3954, -1660, -3665, -5002, -1393, -4800, -2724, -3232, -3665, -2205, -5970, -5176, -2031, -2599, -2107, -8393, -5444, -1426, -2375, -1440, -8086, -4149, -1504, -2529, -1431, -5768, -3788, -2152, -2610, -2323, -5091, -4327, -3485, -2952, -3671, -5871, -5127, -5906, -3843, -4340, -8615, -4207, -8363, -5214, -3827, -28777, -3175, -6928, -6745, -3289, -10442, -3254, -6480, -6719, -3471, -8827, -4442, -6204, -6800, -3954, -7523, -6173, -4784, -9284, -3893, -6590, -6870, -4226, -10138, -3785, -6376, -6773, -5158, -8220, -4134, -6640, -6732, -7819, -9149, -4733, -6653, -6899, -10069, -12319, -5139, -5942, -7484, -7865, -13738, -5273, -5353, -8247, -4115, -1217, -1712, 369, -2442, -2083, -1941, -2851, 474, -4053, -1533, -2184, -3225, -137, -6163, -1936, -2447, -3096, -1098, -4438, -2583, -5008, -3352, -1674, -2681, -2956, -7371, -4386, -1320, -1531, -3135, -2855, -5979, -676, -577, -3817, -2679, -7196, -238, -143, -6026, -5561, -7644, -40, -688, -6565, -4266, -6988, -80, -2787, -6399, -1821, -5592, -539, -5312, -15615, -1349, -5415, -1734, -2429, -5494, -2051, -8304, -4578, -805, -3615, -3213, -3609, -10704, -387, -2097, -2969, -955, -3321, -1073, -650, -1614, -438, -1816, -2465, -1057, -992, -1442, -1947, -2954, -9022, -2679, -3498, -1970, -2764, -199, -5924, -2047, -73, -560, 2556, 351, 586, 1562, 1676, 2931, 1882, 1790, 2018, 2694, 1170, 1523, 1804, 1111, 2643, -8086, -394, 860, -1328, 1838, -705, -2546, -795, -2574, 862, 729, -1582, -2835, -1761, -163, 56, -617, -4748, -2222, -2720, -1583, -416, -6045, -2931, -5569, -3592, -790, -6045, -2737, -1166, -6958, -1225, -5319, -2470, -295, -8865, -1251, -3964, -2666, -1258, -7912, -1126, -2514, -3563, -3571, -4532, -1563, -1660, -5202, -4847, -1441, -2992, -1781, -4774, -4611, -322, -4997, -3198, -2952, -5942, -603, -5394, -6214, -2440, -6411, -1917, -4901, -5584, -3543, -5793, -3729, -4390, -3415, -7264, -8582, -5234, -5014, -2235, -8942, -4395, -6310, -8549, -1569, -6054, -2170, -7603, -5002, -1463, -5195, -2267, -9149, -2964, -1978, -3792, -4644, -9022, -3714, -2735, -2034, -13365, -7146, -6480, -2779, -635, -5444, -6256, -2807, -2774, 63, -3879, -7247, -1273, -4226, -70, -3677, -11781, -1544, -8138, -1093, -4003, -6590, -2997, -3151, -3254, -4810, -3279, -4555, -983, -7247, -5014, -1831, -5227, -463, -7984, -4195, -1944, -6565, -1102, -6828, -4395, -3334, -12319, -2986, -7146, -5784, -3218, -7936, -6246, -4250, -7371, -2606, -6074, -4935, -1803, -10526, -3769, -6045, -3198, -607, -6256, -6565, -4455, -3161, -278, -4082, -6692, -3105, -4649, -535, -4199, -6045, -3027, -7842, -1292, -5279, -7264, -3944, -13049, -2367, -5202, -6457, -5299, -13738, -2007, -6445, -3586, -6828, -13365, -764, -10704, -2758, -8549, -6988, -510, -3187, -3717, -10704, -3529, -1626, -918, -6365, -9695, -1779, -4504, -310, -7819, -7050, -1367, -7264, -937, -7179, -7583, -2398, -5516, -2448, -7050, -12776, -5827, -4523, -3203, -6565, -5415, -8517, -4331, -3549, -6376, -3776, -5097, -5888, -4764, -6615, -4748, -4816, -28777, -2793, -6988, -10362, -5862, -6469, -875, -7796, -4006, -6035, -4331, -367, -10001, -1756, -4693, -3635, -1064, -8903, -1414, -3436, -3360, -3012, -6422, -2417, -2677, -3375, -6973, -6225, -4344, -2743, -3863, -14195, -7484, -5836, -3795, -4578, -7213, -5546, -6016, -5374, -4935, -4896, -3975, -5380, -5759, -4842, -3415, -4010, -5374, -5437, -4980, -2817, -5221, -6928, -5844, -5037, -3156, 12134, 7964, 12326, 10783, 8293, 11562, 8697, 11639, 10187, 7721, 9797, 9075, 9413, 8177, 5757, 6745, 8684, 5434, 3553, 1036, 2902, 8678, 4881, 1333, -516, 1823, 8693, 5646, 2537, 403, 3576, 7805, 5197, 2556, -1100, 5226, 5757, 2662, 4307, 2672, 6239, 1909, -1969, 4505, 4656, 6247, -1849, 2392, 2524, 5823, 5138, 2186, 1376, -1860, 6818, 4252, 3845, 103, 2758, 7621, 4605, 5084, 4192, 4503, 8004, 3809, 5968, 5470, 4831, 7712, 622, 6074, 5073, 4209, 6425, -6679, 4972, 2877, 2824, 3429, -5164, 2167, -4142, 1406, -8549, -254, 641, -189, 942, 154, 1927, 1996, 1319, 726, 1413, 2212, 1668, 1070, 265, 2423, 1716, 12, 453, -417, 3108, 2143, -2306, -3, -1206, 2777, 3224, -3244, -712, -1927, 1433, 3625, -1742, -2493, -1672, -996, 2959, 346, -6504, -480, -8304, 997, 1689, -1503, -141, -2200, -1954, 1909, 1933, -1517, 408, -2375, 799, 3496, -6666, 976, -2447, -1733, 3721, -3311, 504, -1611, -2677, 2714, -318, -471, 66, -2573, 362, 1279, -1383, 1364, -3261, -2514, 2050, -1263, 2640, -1199, -1031, 1912, -97, 3743, 202, 656, 674, 932, 4287, 22, 1240, -1732, 1284, 4099, -1622, 768, -1030, 436, 3021, -3128, -625, 1057, -2791, 1251, -2083, -3056, 2130, -644, 832, -490, -7230, 2697, 1892, 1129, 612, -2488, 2826, 2021, 417, 637, -804, 2143, -284, -901, -111, -1250, 718, -1130, -1436, -548, -2861, 1279, 1877, -849, -1431, -3532, 2499, 2692, -522, -2977, -6074, 2475, 2350, -1123, -951, -3923, 1304, 1465, -2312, -112, -1156, -249, 583, -3003, -787, -954, -804, 120, -3309, -1418, -2543, -593, 238, -3344, -2008, -5960, 15, 460, -2340, -5049, -6759, 779, 33, -949, -6469, -4242, 1171, -1478, -87, -2747, -2863, 889, -3827, -225, -1086, -2411, 233, -4278, -1848, 671, -3433, -26, -2569, -4119, 1954, -8549, -109, -1791, -2231, 2352, -4382, -702, -3220, -2050, 1745, -2109, -1562, -7050, -6343, -110, -2562, -2239, -2225, -3133, -2871, -2801, -4003, -1242, 602, -1289, 430, -6064, -2657, 1996, -53, 2403, -2204, -5879, 2294, -654, 3164, -1335, -5465, 1706, -2933, 2983, -3291, -4184, 44, -1375, 2118, -8138, -1631, -2612, 607, 1069, -3158, 0, -1480, 1163, 425, -3184, 521, 27, 762, 102, -6705, 352, 610, -302, -556, -12534, -36, 795, -1710, -2253, -10899, -454, 87, -2580, -6133, -5702, -1070, -2807, -3187, -15615, -3076, -1921, -5208, -5487, -11004, -2322, -2148, -2003, -4743, -9812, -2473, -1118, -1889, -4003, -4620, -1991, 36, -3135, -4230, -2651, -848, 485, -2877, -1197, -2191, -399, -140, -1445, 146, -2805, -40, -2277, -1081, 335, -3644, 906, -6885, -1855, 568, -3094, 1723, -2910, -586, -256, 7955, 9431, 7065, 269, 75, 7232, 8576, 6787, 1631, -256, 4806, 5686, 5683, 2868, -1796, 3336, 5812, 3812, 3894, -1495, 5162, 7834, 4017, 4552, 1094, 4830, 7956, 4750, 4861, 3850, 1106, 6837, 4338, 4962, 5514, 800, 5479, 3551, 4794, 5981, 3929, 4838, 3787, 3849, 5465, 3666, 3666, 4655, 627, 4800, 720, 1166, 5579, -280, 4901, 572, 944, 6224, 4326, 4821, 3216, 2376, 6230, 5673, 3729, 3832, 2642, 5575, 5501, 1086, 3499, 1583, 4508, 4214, -2672, 2922, -1994, 3126, 3119, 8, 2423, -5915, 1204, 3471, 1033, 1761, -1943, -24, 3162, 631, 1150, -714, 851, 1134, -949, 1902, 1243, 1468, 1570, -4369, 3274, 1994, 1620, 3885, -9479, 3924, 1147, 1842, 4298, -4270, 3576, 129, 2110, 3005, -2621, 2410, 1788, 2122, 1103, -1865, 1274, 2796, 2517, 2250, -1522, 116, 2496, 3813, 2815, -591, -3668, 1378, 4765, 2004, 1073, -4718, 1297, 4694, 198, 2431, -1400, 2068, 3266, -1733, 3082, -1815, 2156, -550, -1699, 2937, -4331, 1401, -6093, -469, 2000, -4669, -324, -1580, 643, 947, -1557, -3957, -2226, 1428, 1061, 608, -3518, -5509, 1763, 1542, 2110, -519, -4974, 1758, 1922, 3083, 211, -1113, 1653, 1831, 3528, -551, 1174, 1511, -43, 3505, -2153, 2361, 1082, -3671, 3210, -2075, 2579, 86, 1497, 2916, 341, 2010, 1027, 2721, 2776, 2116, 1060, 3151, 1887, 2684, 2497, 299, 3847, -784, 2382, 1115, -347, 2894, -1433, 1655, -4779, -1533, 159, -313, 523, -1456, -2114, 157, -871, -383, 966, -1124, 1575, -2049, -438, 1143, -1455, 1545, -898, -255, 324, -5465, 849, 421, -349, -858, -3003, 1005, 757, -693, -2019, 380, 1884, 276, -930, -2885, 1472, 2254, -768, -871, -3412, 1381, 2043, -2011, -793, -4635, 364, 1345, -2132, -786, -7752, -1583, -157, -411, -743, -5607, -5208, -3289, 990, -759, -3560, -8790, -5827, 1501, -1095, -2847, -4348, -2801, 1092, -2051, -2086, -4412, -1752, -335, -3856, -1374, -6577, -2093, -3007, -5654, -554, -1904, -3978, -5960, -4611, 637, 121, -8942, -5569, -3087, 1370, 16, -7542, -4541, -1814, 1094, -2973, -3982, -3354, -391, -429, -6016, -2182, -2138, 1014, -2211, -1538, -1358, -1084, 2016, -374, -1303, -1492, -436, 2426, 943, -672, -2139, -757, 2059, 875, 559, -1998, -2170, 494, -265, 449, -1837, -1204, -2453, -1385, -1280, -2470, 446, -954, -3457, -2635, -3062, 911, 1, -3814, -233, -2333, 724, -1087, 166, 1384, -1346, -17, -3606, 818, 2076, -1003, -1745, -3692, -859, 2164, -1148, -4644, 820, -1743, 1766, -1029, -9639, 3229, 533, 1085, -708, -874, 4011, 1923, 925, -1191, 2077, 3458, 2779, 1197, -3196, 3238, 1601, 2975, 871, 8368, 8649, 11217, 9089, 2759, 7908, 8822, 10713, 8645, 4004, 6361, 8682, 9264, 7484, 3829, 3050, 7720, 7245, 6263, 2746, 4369, 6465, 6179, 5962, 5013, 7078, 5942, 6877, 6620, 5809, 7743, 5666, 7310, 7571, 4972, 6510, 4500, 6983, 8385, 3025, 2319, 222, 6253, 8565, 1389, 4631, 1123, 5188, 7790, 1940, 6545, 3968, 3206, 6076, 1376, 6721, 4951, 2413, 3870, -2165, 6022, 5664, 4337, -24, 72, 4580, 5524, 4530, -49, 1007, 2039, 4130, 2161, 3787, 149, -2783, 2257, -2276, 4606, 1418, -10284, 1590, 2613, 4302, 3173, -8363, 838, 3291, 3659, 4100, -7708, -81, 2399, 2572, 4251, -4191, -1082, 909, -69, 4001, -3121, -2404, 161, -2764, 3990, -2610, -1734, 696, 1203, 4170, -2382, -1397, 1343, 2686, 4120, -2219, -3580, 1245, 2895, 3752, -1654, -9479, -172, 2030, 3066, -842, -2916, -4509, -654, 1982, -244, -1865, -5253, -6800, 166, -472, -228, -2414, 789, -2945, -2887, 1391, -1107, 2896, -760, -4669, 1701, 112, 3687, 2489, 765, 1401, 839, 3641, 4129, 2694, 2037, 1305, 2869, 4570, 3362, 2311, 1486, 1344, 3977, 3261, 1359, 1306, -1243, 2830, 2727, 1584, 920, -8220, 2106, 2319, 2777, -212, -2982, 993, 2216, 2533, -28, 17, -3172, 1340, 677, 3016, 933, -1860, -2178, -2514, 4559, 302, 906, -1548, -3811, 4762, -2580, 1320, 453, -1516, 3905, -2883, 544, -1645, -2470, 2311, 152, -1839, -1755, -2768, 859, 1208, -2805, 1956, 2011, 659, 1685, 626, 2727, 3104, 1089, 2186, 1663, 1896, 1687, 889, 2434, 1138, -647, -5097, -473, 2128, -377, -8192, 684, -2125, 1721, -1707, -3170, 1992, -1529, 2441, -2756, -1328, 978, -908, 3470, -2191, -883, -1999, -1055, 3681, -430, -1117, -3741, -1670, 2816, -52, -2023, -705, -2356, 1098, -1448, -3433, 1467, -2311, 187, -4980, -5067, 2617, -1736, -55, -3577, -6469, 2823, -1540, -1337, -2260, -5810, 2055, -1671, -2555, -1247, -3549, -59, -1492, -1813, 482, -2118, -5422, -679, -877, 1674, -2066, -6928, 259, -607, 2092, -3903, -6590, 744, -2232, 1816, -8615, -3498, 622, -5260, 741, -5951, -43, 421, 526, -1446, -8517, 1176, 1159, 2573, -5702, -4821, 908, 2032, 3070, -8903, -768, -686, 2148, 2411, -3515, 585, -3067, 1365, 545, -609, 695, -5202, 537, -3163, 1236, 374, -7113, 1267, -11115, 2140, 292, -1455, 1836, -3683, 2020, 391, 1074, 1342, -1850, 595, 377, 2525, 211, -986, -2414, 302, 3370, -620, -451, -1466, 393, 3637, -941, -732, -7, 729, 3411, -223, -2720, -287, 1064, 2898, 603, -6732, -1899, 1126, 2168, 1134, -4234, -3701, 909, 1051, 1792, -4837, -2735, 567, -326, 2142, -5208, -1141, -38, -755, 1773, -1419, -35, -2401, 1021, -1310, 2214, -734, -1046, 1163, 74, 2339, -108, 464, 995, 557, 1910, 256, 1384, 727, 460, 861, 786, 1638, 420, -148, -433, 848, 1214, -147, -2297, -672, 503, 272, -1359, -3692, -1173, 571, -866, -2984, -1435, -2510, 1166, -2139, -1773, -2351, 640, 1466, -3843, -179, -2956, 2624, 940, -2248, 163, 338, 3240, 331, 359, -603, 1445, 3055, 1130, 1453, -1188, 1111, 2416, 1872, 1213, -124, -178, 1485, 1970, -125, 468, -1385, 265, 1849, -1076, -142, -824, -1423, 1800, -827, -1193, 336, -4258, 1409, -1427, -650, 1351, -2988, -710, -1215, 416, 2394, 176, -5670, 1344, 1570, 3240, 1391, 1708, 2979, 2617, 3518, 1122, 3488, 3494, 2930, 3063, -448, 3412, 3022, 2164, 1990, -2592, 1725, 1634, 104, 907, -2585, -1732, -379, -2039, 152, -460, -2986, -2271, -920, -1273, 602, -3189, -2933, 222, -4464, 280, -6745, -1325, 733, -7603, -761, -6204, -55, 617, -7819, -1402, -2612, 224, -39, -6026, -2046, -805, -556, -965, -3798, -2642, 364, -2829, -2007, -3232, -2904, 971, -3247, -2889, -3337, -2813, 791, -1196, -3291, -3029, -1963, -700, -923, -3744, -2615, -2053, -4455, -1889, -2841, -3417, -4923, -636, -3083, -1414, -6153, -3876, 1858, -3523, -1351, -3177, -231, 2562, -3971, -2929, -1513, 890, 1812, -4997, -1550, -2245, 528, -386, -6225, 776, -7623, -1071, -1521, -7819, 1657, -4082, -3128, -616, -8903, 1601, -1009, -3269, -108, -4153, 939, 41, -1668, 287, -778, -379, 368, -191, 91, 964, -2500, 350, 587, -994, 1328, -3215, 340, 657, -3062, 306, -1489, 529, 10, -6299, -2411, -92, 619, -1182, -6928, -7371, 616, 356, -2316, -6565, -15615, 762, -194, -4331, -8220, -5043, 724, -1022, -9753, -3471, -1832, 663, -2186, -2314, -533, -711, 320, -2711, -301, 909, -782, -392, -2819, 108, 1408, -1240, -881, -3863, -496, 1299, -1441, -1028, -5145, -1819, 965, -2118, -1966, -4464, -4215, 864, -4266, -5139, -3843, -10799, 1222, -9812, -11945, -4180, -2918, 1641, -5979, -6365, -5615, -599, 1531, -3311, -7984, -5793, -119, 402, -2430, -8276, -3853, -1016, -2244, -2673, -5127, -2871, -2861, -5380, -2668, -4573, -3003, -3344, -4805, -1763, -6204, -3795, -2265, -4985, -1516, -9812, -4348, -1511, -4723, -2566, -3632, -5026, -1407, -3471, -5662, -1293, -6504, -2102, -2140, -6842, -448, -4774, -3944, -1350, -3906, -475, -2825, -7819, -1278, -2950, -890, -2205, -6093, -1735, -2419, -1524, -2390, -3866, -2319, -2043, -2599, -2626, -3546, -2411, -2305, -4172, -2416, -4688, -1973, -3526, -4826, -2057, -7542, -1689, -5002, -4274, -2111, -10210, -2322, -4486, -4311, -3189, -7752, -4748, -4097, -5531, -6504, -5670, -6143, -4929, -8485, -11356, -3801, -3299, -9238, 3235, -1902, 2421, -281, -4365, 2278, -5073, 1347, -2247, 385, 134, -2239, 163, -5871, 2801, -5576, -2430, -974, -1976, 3776, -934, -9812, -1749, 750, 3595, 1489, -2077, -1443, 1740, 2481, 1780, 87, -1497, 1524, 992, 272, 130, -2540, 224, -483, -4923, -157, -2887, -2162, -2630, -4108, 423, -2018, -5569, -3779, -1699, 562, -1319, -7113, -2305, -1973, -482, -1226, -4340, -2170, -1603, -2545, -2254, -1782, -4486, -334, -3671, -4089, 69, -8138, -297, -3876, -3735, 1142, -3133, -1600, -4378, -2064, 1357, -1610, -2348, -5103, -598, 705, -423, -2036, -6064, 479, -488, 1160, -3695, -2672, 1635, -1005, 2546, -3362, -512, 2897, -660, 3138, 23, -3, 3646, -692, 2680, 1304, -940, 3516, -2080, 1062, 1287, -2497, 2303, -9284, -1376, 345, -1213, -399, -787, -3074, -334, 340, -6235, 2101, -4532, 731, 1017, -3665, 3170, -6054, 1665, 884, -1263, 3003, -5670, 1733, -465, -434, 1425, -3479, 1125, -5853, 66, -3594, -2391, 197, -2545, 872, -2211, -2926, -792, 240, 1239, 624, -5195, -1469, 345, 758, 845, -4564, -1862, -1661, -366, -134, -1559, -2641, -6256, -1721, -965, 75, -2863, -1780, -2279, -163, 570, -2445, 247, -1578, 870, -191, -1463, 1078, -1081, 1164, -1765, 586, 1244, -565, 472, -182, 2058, 841, 456, -1163, 1455, 2495, 43, 1297, -2098, 1862, 1844, -686, 1570, -1537, 1555, -361, -1224, 1274, -1375, 1274, -10362, -1018, 535, -955, 1616, -1261, 475, -446, -188, 2302, 1276, 1669, -1429, -372, 2583, 2101, 2073, -2245, -2432, 2063, 1842, 1812, -2569, -9531, 558, 522, 1053, -1720, -9149, -2040, -2024, -170, -332, -6828, -3370, -3900, -1635, 590, -1777, -2311, -1914, -1857, 782, -68, -2460, -760, -1298, 254, -149, -4569, -642, -1302, -681, -1680, -8454, -1348, -2018, -824, -4723, -3782, -2827, -3261, 206, -10613, -2435, -5002, -3378, 828, -8086, -2610, -4968, -2524, 239, -4172, -2967, -2427, -2184, -1878, -3108, -2229, -861, -1519, -2374, -3521, -867, -620, -313, -913, -2350, 98, -2163, 597, -901, -191, 355, -5836, 905, -1969, 892, -116, -2500, 510, -3485, 959, -1134, -1562, -630, -4587, 113, -1826, -3038, -1367, -4199, -1613, -1599, -1941, -333, -3213, -4323, -1772, 531, 251, -2314, -9238, -3264, 1372, -247, -1668, -9238, -5678, 1039, -1707, -1516, -6640, -4219, -130, -4071, -1967, -6814, -2912, -1719, -8247, -3304, -7281, -2829, -3089, -8060, -5202, -5915, -3779, -3615, -6173, -4067, -3944, -4968, -3665, -5897, -2977, -2437, -3391, -4093, -5133, -2817, -1864, -1847, -4907, -3723, -2681, -2473, -1310, -5836, -2555, -2420, -4541, -1505, -6759, -2175, -2599, -5888, -2142, -7299, -2673, -2969, -4382, -2797, -6528, -3883, -2191, -4573, -1230, -335, 645, 429, 357, -3038, -152, -1412, 1329, -229, -4348, -47, -6083, 1594, -1982, -3309, 23, -4635, 1187, -3170, -1646, -1013, -1054, 323, -2394, -1340, -5879, 314, -334, -1773, -3301, -3720, 584, -752, -361, -3698, -1733, 174, -1032, 678, -538, -2670, -549, -864, 491, 78, -2460, -1508, -953, -411, -1808, -976, -2973, -2054, -21, -5844, -672, -4075, -4093, 532, -251, -1414, -1376, -2827, 120, 1505, -3189, 1322, -685, -1286, 2352, -4664, 2820, 588, -7162, 2829, -2247, 3202, 1410, -1640, 2225, -732, 2496, 1687, 1589, -426, -1668, 523, 713, 2413, 912, -3003, -1305, -3247, 1645, 2977, 1544, 1310, -897, -313, 2760, 3205, 2988, 1433, 430, 603, 3140, 3446, 1385, 2077, 454, 1813, 2967, -406, 2819, 1991, 766, 1707, -4138, 3058, 1834, 1570, -371, -9149, 2707, 181, 2282, -3537, -4693, 1413, -2916, 2590, -5810, -1620, -276, -6732, 2826, -6988, -743, -284, -6786, 2924, -9193, -1535, -798, -4013, 2843, -7865, -2470, -2460, -1686, 3096, -2430, -1810, -1476, 143, 3503, 435, -1444, -855, 1322, 3261, 1347, -1227, -1814, 1695, 1779, 552, -487, -3208, 1165, -2364, -2550, 436, -2545, -395, -3334, -6528, 641, -1313, -2999, -573, -3005, -353, -1292, -3947, -842, -2326, -2500, -3001, -2988, -2835, -2207, -2135, -5127, -2670, -4433, -2040, -279, -4683, -2328, -3615, -1618, 769, -6732, -1543, -3242, -848, 1473, -5429, -742, -2061, -292, 1818, -2673, -499, -46, -804, 1349, -1369, -1100, 1304, -3738, -24, -104, -2344, 1780, -2843, -290, 1044, -4759, 1564, 381, 749, 1582, -6256, 1045, 1368, 939, 1323, -1788, 626, 1164, 359, 375, -843, 32, 220, -337, -773, -1428, -1186, -939, -1168, -2023, -988, -1232, -1241, -2205, -3378, 86, -133, -473, -340, -2383, 686, -380, 89, 1460, -1666, 1007, -2470, -263, 1945, -2977, 793, -6093, -1781, 1250, -6973, -227, -5599, -4211, -789, -2994, -2270, -3792, -6528, -5031, -938, -6376, -3144, -7371, -3498, -517, -12534, -4211, -7034, -1516, -1733, -7445, -4654, -13365, -1254, -8112, -6469, -3769, -3266, -1563, -3103, -5879, -4369, -751, -1213, -395, -6183, -5718, -361, -640, 288, -7371, -6332, -1802, -691, 277, -10704, -5260, -7523, -1131, -162, -10362, -3227, -4997, -1278, -1484, -5662, -2720, -2657, -1381, -2382, -4164, -4688, -2956, -2107, -587, -4153, -9238, -4738, -4078, 349, -5139, -2992, -6310, -8247, -127, -6504, -1722, -7213, -5103, -2330, -6565, -2236, -12534, -3509, -4890, -5164, -3886, -7081, -3656, -2385, -4123, -6492, -4258, -4416, -1680, -4295, -13365, -3482, -4455, -2478, -5599, -7562, -3662, -3656, -4215, -3866, -6153, -4078, -2550, -6504, -1831, -7113, -4361, -1401, -10526, -1369, -9064, -4327, -696, -12776, 10974, 5133, 12179, 10614, -15615, 10339, 6509, 11570, 10083, -5710, 8267, 7039, 9596, 8403, -3137, 3870, 5751, 5533, 5286, -2242, 966, 3967, -1683, 389, -1745, 3039, 4025, 615, -2125, -725, 3074, 3004, -787, 404, -66, 2859, 647, -159, 1152, 251, 3039, 1753, -97, -867, 1275, 3871, 2657, 291, -122, 2316, 4697, 2636, 1038, 3007, 2920, 4654, 3017, 300, 4325, 3402, 3192, 3945, -3589, 4568, 3727, -441, 4302, -1647, 3895, 3687, 164, 3558, -93, 2359, 3268, 1703, 1790, -2194, 715, 2426, 1429, 682, -1157, 245, 689, 605, 508, 1833, 125, -4669, 152, -366, 2668, 92, -1704, -620, -1566, 2372, 146, 1236, -1799, -3266, 1346, 211, 1634, -1900, -5942, -366, 469, 661, -1627, -4021, -2935, 903, -746, -1696, -2648, -3751, 1215, -1950, -1262, -2507, -3151, 1423, -4901, -391, -1911, -4644, 1646, -2849, -174, -1012, -8423, 1633, -298, -1270, -1283, -7389, 1189, 127, -3923, -3889, -4728, 492, -991, -6256, -5726, -2366, 48, -3744, -9585, -2028, -1419, 43, -9064, -8485, -1286, -1956, 16, -12534, -5214, -2153, -4774, -291, -6800, -5599, -4464, -7984, -796, -3540, -8165, -7752, -2726, -1325, -1898, -5380, -5988, -1576, -1583, -1682, -2815, -3597, -2080, -1550, -3076, -1475, -1975, -3441, -1987, -4743, -1014, -1593, -4500, -3850, -2366, -1427, -3124, -5561, -9585, -850, -2361, -12123, -8165, -5554, -393, -2359, -3707, -28777, -3741, -652, -1657, -2057, -10284, -4142, -1452, -1378, -3018, -11629, -6800, -2621, -1553, -6354, -12123, -7562, -3580, -2061, -3975, -8138, -4816, -3641, -2711, -2571, -7264, -4378, -3311, -3114, -3018, -6445, -5374, -3189, -3012, -4601, -4550, -7960, -3349, -2900, -6590, -2473, -17034, -3729, -3422, -8086, -1169, -5862, -4258, -4679, -8304, -848, -2760, -5067, -5422, -7066, -1276, -1302, -5997, -5444, -5465, -2008, -968, -6173, -6376, -4134, -2722, -1477, -5576, -7774, -3142, -3490, -2425, -4611, -6354, -2621, -4759, -3401, -3695, -4748, -2914, -7081, -4038, -3577, -4331, -4486, -7097, -3618, -4769, -5176, -7335, -5768, -2735, -6759, -5607, -7542, -5906, -2531, -5176, -4395, -6365, -6842, -3375, -3425, -4168, -5176, -7603, -4985, -2557, -5353, -4447, -7912, -5702, -2040, -6007, -4191, -6469, -6870, -1432, -4842, -2811, -4688, -10799, -782, -3656, -1336, -4203, -7389, -400, -2703, -899, -5312, -6692, -471, -2238, -1490, -5638, -8220, -1081, -2448, -2841, -3632, -9064, -1976, -3158, -4847, -3301, -7050, -2688, -3677, -8903, -5401, -4311, -3615, -3452, -6246, -6692, -2340, -4504, -3056, -3455, -3665, -1210, -3301, -3276, -2726, -3362, -831, -2499, -4957, -3393, -5339, -1122, -3126, -10613, -5103, -6590, -1967, -5487, -9380, -6666, -4278, -3686, -9753, -8220, -7034, -3373, -8138, -10704, -11004, -6235, -2895, -8034, -5374, 1449, 3197, 8375, 3840, -7960, 766, 2347, 7777, 4367, -4940, -1927, -133, 5842, 4880, -1305, -1580, 693, 2403, 4831, 1131, 2049, 2339, 1975, 4742, 2473, 3660, 2578, 2608, 5005, 2976, 4273, 2325, 1635, 5258, 2788, 4387, 1910, 339, 5076, 1996, 4280, 63, 1772, 4314, 901, 3961, -3168, 3391, 3087, -510, 3944, 1918, 4603, 1415, -3362, 4884, 3749, 5577, -1033, 0, 5577, 4087, 5888, -1456, 2902, 5178, 3504, 5074, -1015, 4127, 3391, 2664, 2516, -2295, 4236, 613, 2383, 76, -3089, 3453, 332, 2188, 2452, -3065, 1995, 160, 1504, 2824, -3989, 165, -862, 661, 1778, -4319, -1510, -815, 798, 159, -3383, -2204, 245, 1772, -533, -3182, -1799, 1191, 2324, -12, -5408, -1462, 1702, 2092, 276, -9812, -1961, 1717, 1328, -549, -6321, -2754, 1152, 741, -1920, -2046, -3163, 25, 663, -727, 677, -3247, -632, 751, 513, 1750, -1624, 202, 608, 711, 1575, -453, 946, -73, 120, 269, -470, 832, -861, -948, -2514, -1427, -582, -556, -1909, -5183, -3452, -5221, -79, -2022, -2472, -8718, -3471, -247, -1626, -1334, -4918, -1045, -310, -1642, -1216, -1966, -1503, 105, -2305, -1482, -828, -4853, -154, -3242, -1581, -565, -7113, -1817, -3720, -1001, -713, -5020, -4810, -3606, -92, -903, -4223, -4625, -3444, 437, -1189, -2597, -3393, -3474, 438, -1976, -1954, -2776, -3592, 166, -3103, -2003, -3360, -3532, -40, -1821, -2192, -6445, -3184, -114, -146, -2861, -4361, -3352, -154, 150, -4352, -1705, -4874, 68, -1157, -5183, -974, -8827, 680, -5139, -4847, -1104, -7484, 1084, -6745, -5735, -1184, -4311, 786, -4790, -7542, -1326, -2522, -276, -7097, -5702, -2488, -1661, -1495, -6194, -4985, -4523, -1326, -2377, -3401, -6492, -3203, -922, -4282, -3286, -8333, -2480, -599, -5037, -4869, -5121, -4142, -968, -2825, -3961, -3695, -6719, -2038, -2608, -2208, -3889, -3701, -2312, -4112, -1963, -5333, -3388, -1825, -5960, -2990, -4464, -4348, -2090, -6640, -5067, -2737, -3632, -3326, -5164, -7130, -2590, -3025, -4869, -3225, -5897, -4238, -3603, -6299, -3054, -4336, -7687, -4748, -10442, -4425, -3624, -4885, -4769, -7752, -4769, -3391, -3457, -3632, -5509, -4513, -3853, -3773, -3074, -6083, -6163, -6225, -5599, -3151, -8165, -5260, -8942, -7644, -2745, -5380, -3471, -4013, -5480, -2030, -2992, -2743, -2835, -3820, -1931, -1673, -1823, -3580, -3549, -2599, -1216, -1275, -6973, -4733, -3964, -1741, -1987, -6528, -7281, -5422, -3054, -4659, -3083, -5853, -4138, -3222, -4649, -1944, -3999, -2292, -2743, -2148, -1918, -3523, -1709, -3362, -1462, -2440, -3837, -2587, -4790, -2038, -3140, -4348, -5569, -6194, -3999, -3274, -4800, -8865, -9936, -6354, -2197, -5008, -5183, -8903, -3866, -1736, -4885, -3671, -5183, -2751, -2791, 3552, 2546, 6803, 2428, -607, 2619, 2288, 6397, 3673, 1962, 1236, 1293, 5440, 4737, 2974, 2997, -807, 4409, 4499, 1728, 3993, -904, 2855, 2610, -2696, 3693, 1618, 148, -2758, -1072, 2198, 2870, -14, -1298, 672, -1000, 2921, 490, -235, 318, -5979, 1866, 38, -1825, -2166, -2345, -23, 446, -2661, -3222, -109, -1863, 1191, -1836, 1712, 1648, -2407, 1575, -1586, 3739, 2695, -1357, 1647, -262, 4435, 2996, -539, 1369, 1681, 4231, 2582, 322, 530, 2755, 3487, 1325, 1291, -1313, 2575, 2805, -1219, 1520, -3701, 933, 2599, -6679, 799, -839, -231, 2571, -11781, -520, 673, 1176, 2401, -6399, -1760, 423, 1187, 1965, -3137, -2926, -1317, -990, 1329, -3036, -4361, -3415, -15615, 606, -4282, -2655, -4123, -2158, 219, -583, -251, -4382, -323, 477, 922, 934, -3846, 267, 371, 410, 1118, -3665, 532, -796, -2006, 247, -3266, 866, -2875, -3342, -2342, -1843, 1332, -3798, -2236, -7865, -941, 1451, -1651, -2768, -3757, -1011, 825, 1, -4250, -2979, -1875, -568, 486, -4278, -3927, -2897, -2071, 45, -3409, -5836, -3360, -2050, -1226, -3067, -7819, -3554, -848, -4138, -2843, -7230, -4180, -67, -7264, -2155, -5592, -4885, -265, -2637, -1579, -5103, -3501, -1388, -1746, -2314, -5480, -1786, -1016, -3496, -6026, -5853, -1022, 890, -7687, -3031, -4523, -960, 1892, -1701, -917, -2473, -996, 1951, 293, -1295, -1526, -839, 1363, 995, -3788, -1756, -767, 320, 890, -4698, -3094, -832, -1592, -26, -3615, -5292, -838, -4963, -1790, -4130, -3957, -792, -3010, -3010, -4550, -1954, -1098, -1471, -2610, -4082, -1511, -2256, -771, -2268, -3947, -2411, -5109, 87, -1683, -4270, -3957, -8393, 608, -1141, -4890, -4049, -2707, 521, -784, -5710, -3754, -679, -22, -643, -7179, -4112, -211, -1247, -1275, -10613, -4207, -1117, -4455, -3201, -7464, -2971, -3900, -6045, -3479, -3840, -1497, -6163, -2075, -1089, -2219, -770, -3083, -1019, 77, -2185, -1022, -1958, -1396, 53, -4093, -2083, -1809, -2891, -1158, -8423, -3108, -2282, -4509, -3430, -4433, -3665, -3463, -4142, -3695, -3512, -4303, -6093, -3259, -2548, -5208, -4378, -9812, -2316, -2468, -14195, -4003, -5818, -1296, -3237, -4021, -4180, -5279, -531, -4097, -1752, -4901, -8333, -295, -3866, -1062, -5970, -9695, -686, -3284, -1441, -7542, -5776, -1918, -3031, -2626, -10442, -5031, -4874, -3140, -3804, -7708, -4017, -5561, -3961, -4774, -4779, -3117, -2331, -5853, -7603, -3964, -3577, -1508, -8393, -11945, -5170, -6565, -2225, -9380, -6343, -6602, -7066, -4161, -7819, -4447, -4266, -4303, -6773, -7247, -3220, -3618, -4831, -12123, -6480, -2613, -3441, -5784, -7623, -4723, -2512, -2097, -3242, -3937, -4482, -2564, -1195, -2500, -3137, -5374, -2617, -1416, -3597, -4442, -4203, -10362, -6153, -2210, -5827, -2538, -8304, -8549, -1947, -7034, -1447, -7389, -10704, -2833, -9812, -1377, -6310, -6225, -5702, -8086, -1451, -5247, -4853, -11629, -4754, -1137, -4654, -4559, -9064, -2745, -972, -4644, -5008, -5592, -2411, -985, -5387, -6759, -2653, -4199, -622, -7484, -12534, -1134, -28777, -234, -10210, -8192, -774, -5031, -609, -7146, -6958, -1491, -3698, -2265, -5516, -9106, -3367, -4723, -6653, -4046, -12776, -6480, -8454, -5694, -3119, -7960, -10284, -6958, -2222, -3635, -7019, -11488, -4006, -849, -5067, -8165, -10210, -2893, -477, -4698, -10704, -9479, -3051, -798, -5451, -28777, -9936, -4980, -1666, -17034, -6759, -10284, -11629, -3163, -5067, -3126, -4918, -5615, -4991, -2438, -2012, -2438, -4303, -4211, -1262, -2540, -1617, -5273, -2624, -861, -4532, -1962, -7317, -2075, -1135, -7687, -3441, -7484, -2468, -1991, -7097, -7644, -5662, -3618, -3324, -6064, -7583, -3220, -5145, -4858, -5451, -3795, -1769, -6745, -5810, -3701, -2984, -1371, -10362, -6602, -2211, -3644, -1822, -7353, -8333, -1469, -5509, -3040, -4523, -7583, -1289, -7708, -4985, -3804, -5735, -1540, -9936, -7562, -4064, -5195, -2403, -8192, -10362, -4042, -5933, -4550, -4592, -10899, -3367, -8393, -9193, -3259, -8165, -3020, -8790, -5502, -3438, -5502, -3766, -5960, -3674, -4795, -3496, -6786, -5183, -3007, -6540, -2176, -10613, -6422, -2895, -7426, -1522, -5279, -6988, -3689, -7389, -1313, -4348, -3391, -6074, -7774, -1412, -4442, -1439, -7034, -9429, -1988, -3968, -693, -4880, -9064, -3375, -3668, -825, -4093, -8942, -5599, -4733, -1587, -4323, -11356, -7281, -5694, -2637, -5592, -5145, -7774, -3218, -3923, -7687, -2138, -9284, -1734, -6445, -8683, -714, -15615, -1277, -10362, -8060, -463, -10210, -1379, -7130, -7213, -1375, -7687, -1668, -7888, -8304, -3415, -6640, -1912, -12534, -11356, -6016, -4997, -2139, -6800, -7113, -6928, -3096, -2752, -5234, -5401, -4555, -2047, -3903, -4504, -4616, -3409, -2040, -4541, -4168, -4191, -3543, -2809, -4270, -5569, -4460, -3306, -3992, -4211, -9284, -6163, -2253, -4826, -5394, -4640, -13049, -1625, -3801, -8086, -2997, -8942, -1742, -2637, -4067, -2887, -7081, -2728, -2027, -2256, -3463, -6705, -4929, -1902, -2330, -4238, -7004, -9873, -2606, -3978, -4951, -10138, -9064, -4606, -7912, -5055, -11945, -5979, -8192, -12776, -4606, -7774, -5026, -14784, -9022, -4583, -7335, -4853, -10799, -10138, -5576, -7842, -4754, -9331, -9873, -6653, -7842, -4703, -17034, -7179, -5862, -6399, -4929, -8138, -5988, -5422, -5306, -5170, -5472, -6026, -6214, -4997, -5360, -5422, -8615, -8615, -4583, -5726, -7687, -8009, -12534, -3744, -5933, -11115, -4157, -9331, -3092, -5546, -9380, -2975, -7912, -2829, -4974, -10284, -3168, -8192, -2883, -5097, -7752, -4357, -8485, -3020, -6745, -6035, -6445, -6958, -3182, -7687, -6163, -8982, -6103, -3644, -5531, -7464, -9331, -5678, -2807, -4495, -3326, -5183, -10362, -2509, -5554, -5646, -3329, -4527, -2958, -7888, -10069, -1869, -1568, -4486, -9873, -10799, -2146, -470, -8615, -11781, -8754, -3540, -470, -6054, -10138, -5569, -3001, -1149, -2688, -6422, -3101, -2306, -2075, -1407, -3671, -1899, -3344, -3337, -1431, -2316, -2138, -4473, -6133, -2612, -2375, -4035, -3259, -6376, -4486, -3996, -6267, -3085, -3264, -5115, -8138, -5189, -4545, -2274, -5049, -13365, -4262, -8276, -2774, -6434, -8276, -3449, -7034, -4569, -5776, -6288, -2651, -4315, -4630, -3281, -4134, -2014, -3490, -2548, -2696, -2383, -1828, -3452, -1414, -3920, -1431, -2363, -2319, -1207, -7066, -1259, -3863, -895, -1834, -8683, -1945, -6267, -589, -3151, -7687, -3889, -5524, -1604, -4980, -7644, -7299, -3401, -2783, -7583, -8112, -5494, -2427, -1750, -14784, -6602, -3896, -2526, -1144, -9531, -4795, -3417, -3707, -1616, -5888, -4495, -3798, -5546, -2303, -4149, -5718, -5784, -5615, -2473, -3662, -7562, -8865, -4805, -3242, -4408, -6256, -5353, -4532, -5810, -6469, -5189, -4060, -4433, -13738, -10899, -5286, -3893, -4180, -15615, -9812, -6035, -3609, -4024, -8549, -5292, -6173, -2653, -4541, -4644, -3644, -5073, -1612, -5801, -3404, -3471, -3978, -1255, -6123, -3798, -4149, -3833, -2344, -4100, -5339, -4980, -5121, -7445, -2521, -6376, -5531, -7264, -4723, -2119, -5539, -6183, -6376, -2442, -2383, -4145, -7408, -5085, -3147, -1805, -2809, -5073, -3957, -7445, -888, -1777, -2801, -3827, -7464, -804, -1374, -1879, -5933, -4738, -1888, -1745, -1844, -9380, -4774, -4853, -2701, -2369, -5103, -5678, -11004, -3465, -3476, -4234, -6640, -4946, -3512, -5862, -4620, -10362, -3062, -3476, -9284, -4997, -8615, -2197, -3540, -4416, -4573, -4963, -2325, -3686, -1999, -3474, -4518, -3896, -4149, -665, -2825, -6343, -6732, -5266, -92, -3147, -14195, -4831, -7774, -307, -4532, -8942, -3543, -11781, -1481, -6528, -6064, -3741, -8304, -4311, -8086, -4295, -5026, -4968, -8363, -10442, -3383, -6988, -3089, -4153, -10899, -3507, -9531, -2644, -2912, -8942, -5020, -9149, -3689, -2510, -9331, -9193, -5735, -6528, -1839, -10526, -6332, -4918, -6958, -1345, -7004, -4282, -6083, -5097, -1682, -4918, -4425, -8582, -4408, -3094, -4010, -6800, -7912, -3433, -5915, -3615, -28777, -8247, -2378, -10526, -3163, -6988, -13738, -2036, -7912, -2605, -5458, -5776, -2507, -5227, -2369, -5374, -3249, -3433, -3388, -2819, -6267, -2448, -4067, -2142, -4127, -8754, -2724, -4180, -1590, -5266, -13049, -3937, -4017, -1875, -5339, -6928, -6516, -3723, -3239, -6745, -4874, -13049, -3487, -6553, -13738, -4149, -10613, -3824, -12534, -7066, -4180, -8790, -5408, -5718, -5853, -4532, -8165, -9873, -3612, -7819, -4940, -8086, -9753, -2531, -14195, -5353, -9479, -8827, -2228, -6288, -5915, -13738, -13738, -2887, -4669, -6856, -11629, -9193, -4659, -4569, -8683, -9812, -7445, -2651, -2851, -5401, -4168, -3496, -2574, -6246, -5429, -1510, -4963, -2764, -11781, -5710, -402, -8165, -3218, -5827, -5292, -525, -4708, -2366, -3776, -3498, -1852, -3714, -1358, -2694, -2216, -4578, -5067, -1531, -2730, -1665, -4728, -12123, -3014, -4082, -1831, -3025, -6310, -5827, -5494, -2228, -2522, -4555, -9193, -4997, -1787, -2619, -5422, -7644, -5333, -1144, -2908, -7730, -5662, -6565, -1139, -3618, -6026, -3940, -6365, -1816, -6480, -4532, -2347, -5768, -3299, -7299, -3493, -1326, -5480, -5951, -2170, -2601, -1012, -5208, -5924, -677, -2071, -1429, -5726, -4545, -934, -1721, -2573, -9022, -4669, -3047, -1401, -4395, -10284, -4331, -9284, -1276, -5818, -6321, -3365, -5170, -1650, -5208, -6842, -3549, -3194, -2776, -4352, -14784, -4078, -2419, -3840, -4527, -7708, -2091, -1914, -2960, -6870, -6800, -401, -1620, -1995, -11781, -9639, 142, -1557, -1474, -4527, -5827, -284, -1511, -1121, -2282, -3726, -1313, -1456, -1343, -1242, -3735, -1643, -1672, -2497, -1083, -5031, -950, -2163, -2130, -2026, -4703, -581, -2521, -537, -4713, -3244, -871, -2573, -167, -8683, -2751, -2004, -2424, -558, -6016, -3027, -4654, -2225, -245, -6256, -3261, -7665, -2297, 176, -9284, -3184, -4161, -2778, -287, -5437, -3723, -2962, -3656, -1282, -2713, -6123, -3054, -5312, -1651, -1511, -8304, -4172, -8165, -1834, -1285, -3677, -7752, -8827, -2931, -1833, -1797, -8423, -7484, -4748, -3051, -1197, -3785, -6759, -3360, -4408, -1485, -2270, -6422, -1912, -4509, -1774, -1575, -6173, -2083, -4344, -549, -1022, -4180, -3971, -5091, 589, -576, -2121, -7408, -6074, 661, -530, -1054, -7562, -5576, -424, -1143, -1001, -9479, -5584, -2398, -2606, -1882, -11488, -8086, -3455, -4951, -3135, -6666, -12776, -2883, -6133, -3863, -5638, -8304, -1753, -4455, -4518, -5091, -11004, -903, -3900, -4219, -4625, -10069, -860, -5494, -2472, -4669, -7562, -1756, -12534, -1041, -4145, -11945, -3763, -4541, -302, -3560, -6692, -6773, -2211, -329, -4583, -3577, -8517, -1398, -1249, -8549, -2731, -10362, -1701, -3254, -4674, -2941, -9753, -3074, -5494, -2747, -3436, -8138, -4679, -4365, -2937, -3526, -7281, -5862, -3992, -5247, -3201, -3893, -6653, -6183, -8517, -2817, -2072, -4215, -11781, -4683, -2528, -1878, -2902, -4311, -3447, -2253, -2690, -2971, -2300, -3665, -2051, -2855, -4021, -1583, -5026, -2118, -2545, -5576, -1572, -7371, -2589, -2406, -6278, -1963, -8363, -3465, -2069, -6246, -2642, -5374, -4226, -2273, -7542, -3876, -2853, -4842, -3306, -13365, -6153, -1499, -6973, -3985, -7523, -10613, -1173, -14195, -4698, -5879, -9531, -1611, -6103, -8485, -6577, -6113, -2189, -4611, -7097, -9193, -4601, -2317, -4821, -3999, -8034, -4429, -2361, -6256, -3476, -5970, -5387, -2823, -9585, -4460, -5793, -7196, -4157, -10362, -6800, -7353, -8615, -7687, -5592, -8683, -11629, -7865, -7665, 11108, 15036, 9902, 5969, 8435, 10914, 14606, 9535, 5610, 7636, 10259, 13280, 8492, 4280, 4800, 9422, 10943, 6856, 1240, -2483, 9204, 7308, 4388, -3235, 1828, 8919, 3366, 1632, -1922, 1982, 7442, 5799, 2713, -651, 980, 5082, 7154, 2829, 935, 942, 6232, 7188, 1098, 1365, 1948, 7247, 6255, 1483, 1173, 2999, 6938, 5352, 3522, 1440, 3995, 5610, 5482, 4188, 2033, 4887, 3614, 5927, 3668, 2194, 5521, 584, 6675, 1852, 1440, 5831, -8423, 7046, -2606, -424, 5716, -1380, 6420, -4464, -2599, 5131, -1733, 4583, -901, -2407, 4112, -1003, 1460, -264, -729, 2474, 691, 817, -635, -73, -609, 1211, 2572, -1883, -1241, -9936, 1423, 3290, -1665, -5759, -5026, 1054, 3031, 860, -7389, -6113, -782, 1510, 2398, -6299, -6828, -5353, -1940, 2896, -10442, -4161, -1883, 801, 2600, -5380, -4071, -463, 3135, 1766, -4195, -6516, -1500, 3716, 680, -4149, -13365, -3989, 2859, -453, -3299, -7819, -3741, 332, -1673, -2477, -8034, -13365, -2952, -3846, -2815, -5897, -589, -1263, -8138, -5776, -3362, 2448, 594, -3504, -7146, -2363, 3450, 1412, -1259, -2282, -1884, 3247, 756, -2, -934, -848, 2118, -2114, 877, -981, -23, 214, -5988, 1408, -1870, -234, -2158, -1113, 1581, -3126, -1725, -4013, 441, 1466, -3629, -3014, -5208, 718, 1164, -2359, -1782, -7081, 44, 663, -1002, -1315, -7912, -1241, -240, -489, -2153, -4885, -2417, -1843, -955, -4250, -2749, -3383, -4390, -2438, -6653, -1816, -4049, -7523, -4831, -5678, -2068, -3551, -7162, -7335, -4180, -3393, -3331, -4664, -7842, -3417, -5472, -4042, -3049, -4907, -3252, -6143, -4980, -2152, -3254, -3449, -4104, -6354, -1642, -2969, -3523, -2670, -11115, -1391, -3680, -3133, -2073, -7888, -1386, -4935, -2653, -2008, -4331, -1605, -6411, -2569, -2317, -3225, -1934, -7371, -3098, -3040, -3999, -2350, -6194, -4112, -4215, -7708, -2956, -5176, -5279, -6310, -8754, -4093, -5253, -6928, -11629, -5646, -6246, -6388, -10284, -6321, -4890, -10526, -7464, -12776, -4703, -4616, -8942, -6973, -13365, -4784, -4601, -6123, -6666, -10799, -3365, -4901, -4890, -7066, -6842, -1870, -5615, -4578, -8304, -5694, -1904, -6399, -5227, -11356, -6035, -3769, -5997, -7281, -9936, -5654, -9639, -5299, -8942, -7281, -4278, -8454, -6133, -8165, -7371, -4130, -7665, -7912, -9479, -10069, -5844, -10210, -6399, -9479, -8790, -12123, -4429, -6204, -7445, -6732, -9639, -1990, -7603, -7146, -6469, -8517, -1330, -7665, -7936, -6719, -9936, -2139, -5367, -8903, -6615, -9479, -4683, -4164, -9753, -6602, -7888, -9284, -4195, -11781, -7542, -6365, -5915, -4532, -17034, -8517, -5170, -3999, -4331, -8517, -6434, -5091, -4108, -4184, -6299, -4573, -6422, -5623, -5260, -5662, -3557, -9284, -6278, -9873, -6064, -3254, -11945, -5979, -8982, -7146, -3795, -11356, 7346, 1030, 4464, -12776, 6407, 6665, -1088, 3741, 2106, 6164, 4364, 1993, 1345, 3857, 5496, 1284, 4528, -2681, 3721, 4783, 3733, 4839, -1622, 2856, 4553, 5041, 3469, -864, 2763, 4348, 5302, 546, -810, 3205, 3649, 5070, 1732, -354, 3293, 2757, 4538, 4194, 1158, 3094, 2563, 3228, 5489, 3174, 2986, 3516, 2562, 5913, 4779, 3166, 5004, 5725, 5512, 5750, 3532, 6105, 7544, 4199, 6060, 3726, 6505, 7944, 1810, 5627, 3153, 6212, 7105, -1287, 4297, 784, 5368, 4947, -2125, 1953, -4997, 4230, 1269, -2118, -881, 1771, 3053, -1202, -3259, -2867, 3564, 1792, -908, -2815, -4997, 3953, -231, -569, -514, -6973, 3645, -4728, 873, 382, -5429, 3074, -1582, 1973, 239, -1874, 2533, 100, 2028, 55, 79, 1891, -702, 1148, 898, 817, 513, -4230, -68, 2067, 650, -1868, -3409, -704, 2675, -138, -1249, -2279, -801, 2473, -1144, 212, -4278, -1384, 1477, -1967, 688, -8865, -3850, 209, -2587, 414, -5319, -3801, 34, -3170, -1018, -6814, -1080, 633, -3594, -5240, -5630, -1246, 1007, -3227, -2851, -2353, -5906, 1011, -1982, -62, -1427, -2010, 733, -754, 838, -1663, 798, 344, -266, 609, -2386, 1455, -24, -885, -784, -3168, 1090, -282, -3023, -3883, -3051, 228, -322, -7603, -4810, -2347, -897, -449, -15615, -2098, -2375, -2336, -1301, -8517, -621, -3301, -3659, -3203, -4997, 351, -3430, -3551, -4853, -3920, 980, -2036, -2698, -3232, -3870, 1142, -1050, -2136, -1216, -3168, 779, -988, -1918, -419, -2175, -38, -1907, -1711, -1141, -1970, -1097, -3574, -1369, -3999, -2659, -2160, -4311, -1197, -6958, -3920, -3331, -3744, -1381, -4703, -5145, -4968, -3717, -2034, -5662, -6299, -6054, -4774, -3597, -7281, -8192, -4500, -7066, -7445, -4901, -10526, -3324, -8683, -8009, -4601, -8165, -3189, -8086, -5319, -6035, -6899, -3515, -7665, -4816, -4587, -7730, -3314, -7708, -5299, -2776, -13738, -2440, -9284, -6653, -2396, -8363, -1484, -15615, -5862, -2859, -6214, -724, -6842, -3989, -3378, -6565, -286, -4912, -3808, -3923, -8942, -328, -5818, -6173, -5346, -9106, -998, -8865, -10001, -8304, -7665, -2295, -3635, -4659, -7687, -8138, -3501, -1721, -3485, -5367, -9149, -3900, -1484, -3373, -4790, -8582, -4625, -2366, -3062, -6235, -8485, -6800, -3748, -2465, -12776, -8247, -11232, -4545, -2345, -6225, -6332, -8718, -4713, -3249, -4412, -4555, -6679, -4495, -5776, -4616, -3683, -5319, -4307, -10704, -5979, -3554, -4184, -5031, -8393, -6103, -3951, -3490, -7865, -6786, -5408, -4625, -3551, -13738, -6083, -6354, -5266, -4486, -6958, -6267, -8582, -5988, -5531, -5387, -6973, -6016, -7523, -4616, -4713, -7066, -4940, -10069, -3532, -4578, -7097, -5784, -9380, -3301, -5662, -8138, -8363, -9479, -3933, -10704, -8754, -8790, -10526, -5279, -7960, 1875, 1724, 3700, 3654, 5666, -1330, 1474, 4377, 5065, 5505, 1877, 1044, 5653, 6627, 5593, 4579, 1016, 6246, 7116, 5737, 4478, 542, 5706, 6436, 4948, 2431, -1265, 3984, 4567, 2879, 1205, -512, 1353, 1792, 371, 2124, 888, -1480, -779, 830, 1858, 794, -2540, -2176, 3201, 2063, 23, 1239, -2311, 4719, 3801, -450, 3452, 1213, 5149, 5054, 1528, 4350, 3267, 5136, 5319, 3439, 3872, 3312, 5286, 4516, 3922, 1105, 1387, 5024, 2733, 2864, -738, -414, 3647, 1405, -5, 2700, 306, 816, 1501, -937, 3033, -975, -1782, 1262, 335, 1386, -4223, -699, 548, 18, -3023, -9284, -965, -222, -907, -6814, -1691, -4412, -163, -1271, -2443, 1211, -400, 546, -1384, -898, 2188, 1882, 979, -1953, 214, 2303, 2226, 905, -2548, 940, 2185, 1392, 268, -2336, 1093, 1793, 107, -954, -2075, 442, 810, -690, -2947, -2019, -1257, -802, -1338, -6016, -2049, -2764, -2194, -1307, -5654, -2447, -1529, -1536, -550, -3827, -3535, -967, -178, -353, -2626, -5133, -1504, 415, -710, -1543, -8333, -2259, 45, -1111, -1052, -5879, -1926, -1219, -310, -1749, -1318, -795, -3119, 721, -4184, 411, -32, -2720, 632, -3054, 525, -70, -1071, -512, -956, -748, -454, -1151, -1681, -1015, -3396, 0, -3930, -3299, -3788, -9284, 946, -4469, -9479, -4907, -6045, 1387, -1624, -5164, -1598, -2766, 1209, -843, -3723, -1680, -2244, 870, -495, -4282, -5103, -2902, 655, -458, -6103, -5346, -2322, 90, -1083, -12319, -2809, -1287, -1212, -1908, -7484, -3692, -1202, -2933, -2319, -4723, -9193, -2071, -3811, -3428, -4060, -7196, -3748, -3509, -7299, -5451, -4912, -5970, -3119, -7247, -9873, -5299, -7623, -3393, -4425, -5702, -7774, -7371, -4748, -4674, -4365, -17034, -6343, -7708, -7130, -4853, -11356, -6457, -9479, -7730, -4616, -10613, -8615, -6411, -4104, -3067, -9380, -7752, -4373, -1994, -2516, -9193, -4946, -2906, -1286, -3194, -12319, -4086, -2028, -1984, -4821, -12534, -4703, -2011, -4119, -6943, -9695, -6800, -3098, -5286, -8649, -9479, -8276, -4946, -4230, -7353, -13365, -5286, -5139, -3944, -6732, -9106, -2881, -4842, -4187, -7888, -4532, -1735, -4957, -4842, -7542, -2574, -1898, -4659, -5988, -6225, -1827, -3471, -4764, -6928, -7281, -1880, -5942, -5524, -6565, -28777, -2460, -6163, -5924, -5879, -6133, -3537, -5942, -5103, -5509, -4097, -5531, -6411, -4536, -5097, -4119, -9531, -7113, -5286, -4810, -5686, -7603, -7984, -8220, -5170, -8615, -5607, -9812, -9812, -6411, -10001, -5487, -12776, -8615, -7936, -9064, -6653, -11781, -10799, -8060, -10704, -7623, -11356, -9238, -6814, -15615, -6035, -8615, -6411, -5694, -10001, -4935, -6528, -5516, -4946, -9022, -5103, -5735, -6045, -4242, -8393, -6504, -5546, -9106, -3569, -8247, -9064, -5164, -10899, -3299, -9936, -5979, -5292, -8582, -5480, -9429, -7230, -3843, -10442, -8454, -8247, -9429, -3194, -15615, -9193, -8060, -5979, -3540, -13049, -9022, -8192, -4357, -5139, -9064, -8009, -7665, -4669, -5793, -8165, -6332, -6732, -7523, -4940, -8165, -6016, -6278, -12319, -4038, -7179, -6943, -7281, -8333, -3130, -6899, -8393, -10442, -7984, -2920, -9064, -10138, -7299, -9106, -3218, -9149, -15615, -5247, -8827, -3846, -5702, -13049, -4901, -5670, -4659, -4578, -11488, -5227, -4344, -5152, -4774, -12319, -5145, -4340, -5260, -5630, -8192, -4630, -4649, -5871, -5451, -6035, -4764, -4587, -6842, -4853, -5429, -6914, -5079, -5702, -5152, -6026, -11781, -6299, -3438, -5247, -7484, -4616, -6679, -1875, -4369, -8112, -2758, -5273, -1447, -3689, -6914, -2505, -3916, -1950, -3512, -5979, -3441, -3319, -2772, -3989, -6163, -5554, -3444, -3130, -5380, -7353, -8363, -4060, -3020, -6577, -7389, -7842, -4826, -2945, -5951, -6246, -7034, -6332, -3023, -6422, -5871, -6870, -9479, -3271, -10362, -6553, -6492, -7774, -3717, -7066, -8517, -5933, -6143, -4112, -4654, -11781, -5662, -5924, -4469, -4541, -9936, -5710, -6705, -5451, -6113, -7603, -5915, -8220, -7774, -9873, -5951, -5827, -7819, -11232, -28777, -4606, -5576, -6204, -13365, -13738, -3760, -5401, -5465, -9380, -12534, -3512, -5333, -6007, -7408, -13365, -3900, -5516, -8034, -7264, -28777, -4863, -6123, -8165, -7503, -28777, -6434, -6759, -5924, -7247, -11945, -8549, -6666, -4985, -7247, -8582, -10526, -6007, -5103, -7623, -6640, -10899, -5240, -5960, -7936, -5662, -11004, -4447, -7464, -7583, -5367, -13049, -3903, -10526, -6928, -5623, -13049, -3923, -11232, -6565, -6480, -7865, -4592, -6267, -6914, -8138, -5710, -5615, -4295, -7865, -11356, -5085, -6540, -3732, -8754, -17034, -5844, -7623, -4207, -10442, -9479, -8517, -8982, -5546, -28777, -6988, -13365, -9064, -7687, -8790, -6163, -9064, -7464, -10442, -6786, -6602, -8165, -6083, -13738, -7230, -8304, -9331, -5670, -28777, -10362, -10210, -13738, -6214, -14784, -15615, -9064, -12534, -7213, -10069, -28777, -8754, -8276, -7888, -7247, -14195, -10362, -6590, -8718, -5836, -13738, -11004, -5960, -10442, -5444, -12319, -9331, -5759, -13738, -5710, -8086, -8363, -5380, -15615, -6278, -6653, -7644, -5020, -10442, -6870, -6321, -7247, -5176, -9064, -7050, -6800, -7623, -5979, -9585, -6973, -8112, -8790, -7426, -12776, -6759, -9695, -8903, -9429, -14195, -6732, -10613, -7542, -10799, -9193, -7426, -10899, -7335, -10069, -7299, -9936, -11115, -9064, -9812, -6399, -28777, -12776, -13365, -10799, -6365, -11945, -28777, -11232, -12776, -6988, -14784, -11232, -13049, -9753, -7644, -11781, -9873, -11115, -7523, -7562, -8865, -12319, -8615, -6590, -7004, -9193, -15615, -9936, -6615, -6814, -10362, -10362, -10210, -7665, -7562, -8718, -8903, -6516, -10001, -8865, -7752, -7865, -5387, -13365, -8454, -8393, -6653, -5599, -11629, -7842, -10526, -5970, -6666, -8827, -8138, -7317, -7179, -9936, -6870, -4800, -6388, -6828, -8982, -7708, -4207, -6153, -7912, -6988, -7644, -5176, -5810, -8683, -5718, -7842, -7623, -5208, -6083, -5793, -9429, -7819, -4896, -4550, -7603, -14784, -7019, -5008, -4361, -10001, -14195, -8454, -5451, -5158, -7623, -11004, -7281, -5979, -5458, -6899, -7196, -4935, -6365, -4592, -7730, -4784, -4532, -6973, -4319, -8423, -3801, -6007, -8423, -4951, -7888, -3886, -9639, -9064, -6299, -8304, -4896, -8485, -7960, -8192, -10704, -6719, -8086, -8754, -11115, -10069, -8582, -11629, -8790, -28777, -7819, -9064, -7097, -5759, -10362, -7644, -7936, -4112, -4442, -6445, -7389, -5576, -2668, -4266, -4100, -4495, -4042, -1848, -4698, -2920, -2499, -3773, -1382, -5415, -2851, -1803, -4907, -1347, -6388, -4035, -2419, -8220, -2045, -7912, -6310, -4555, -12776, -4142, -9639, -5906, -6399, -8718, -10704, -7984, -4654, -4606, -8192, -7179, -5933, -4500, -3978, -8754, -5279, -4980, -4748, -4365, -9479, -5554, -5115, -4386, -5145, -10442, -6759, -6504, -3920, -5546, -13365, -8363, -9429, -4438, -5247, -12319, -11004, -13738, -6870, -4733, -7687, -10899, -14784, -12123, -4569, -5844, -7542, -11004, -5638, -5055, -5472, -6814, -7464, -3583, -6045, -6376, -8649, -5531, -2871, -6745, -8754, -28777, -4790, -3025, -6376, -14195, -7774, -5189, -3840, -5494, -28777, -5726, -6565, -5152, -5139, -28777, -5286, -8454, -7034, -5743, -14195, -6123, -10001, -7603, -6988, -11781, -9106, -9695, -6016, -6492, -17034, -10362, -8615, -5367, -5319, -9380, -5942, -8276, -5924, -5247, -6045, -4097, -8615, -7665, -6299, -5240, -3417, -9479, -10799, -7842, -6299, -3493, -11781, -13738, -8423, -9753, -4028, -28777, -11488, -8903, -13738, -4912, -13365, -10704, -9812, -8942, -5988, -10069, -11629, -10284, -7623, -6288, -8112, -15615, -9380, -7730, -6256, -7281, -10704, -8112, -8485, -7389, -7523, -9429, -7912, -7464, -8982, -8683, -11115, -8754, -5768, -8138, -8982, -28777, -10069, -4951, -7445, -8549, -13049, -12319, -5494, -7335, -9331, -9429, -13049, -8333, -6628, -12319, -7299, -8138, -14784, -5862, -17034, -6365, -5862, -8982, -5561, -9639, -7097, -5085, -9936, -5360, -7984, -11004, -5319, -9284, -5286, -8220, -10001, -6113, -7050, -5784, -10284, -6885, -7687, -7335, -6692, -15615, -6943, -13049, -8304, -7113, -12319, -10138, -7752, -7162, -6973, -11629, -13738, -5539, -7484, -6885, -12534, -9106, -5374, -10899, -6602, -10799, -8582, -6399, -9479, -5743, -10442, -9639, -8276, -7247, -5247, -11115, -14784, -9238, -7389, -5759, -10210, -11781, -7842, -9106, -7665, -9429, -9936, -6842, -10526, -10799, -9639, -11115, -6773, -10069, -9812, -9812, -9585, -7317, -10613, -8827, -9064, -8393, -7774, -13738, -9193, -7842, -9812, -7335, -28777, -10210, -7113, -17034, -6759, -12776, -10799, -7503, -11232, -6540, -9873, -10284, -9149, -9149, -6800, -8454, -9585, -13365, -8827, -7542, -8192, -9585, -28777, -9585, -8982, -9238, -10442, -10799, -4473, -6516, -3817, -7464, -9936, -4089, -5979, -5458, -4907, -9429, -4357, -7484, -8034, -4344, -10138, -5299, -8942, -7665, -5615, -13049, -6457, -8517, -7842, -10362, -12123, -7146, -10362, -11356, -10362, -10526, -8060, -13738, -7888, -7130, -9479, -10001, -9238, -5061, -6469, -7034, -11629, -7708, -3873, -6007, -6026, -10799, -7196, -3656, -5422, -7213, -10001, -7130, -4369, -5360, -9429, -8754, -7888, -5260, -5997, -6235, -7317, -10704, -4896, -7113, -5133, -6225, -11629, -4219, -8363, -5871, -5401, -9753, -3230, -9284, -7162, -4733, -6256, -2040, -8517, -6457, -4640, -4082, -1359, -6376, -5247, -5776, -3707, -1356, -4592, -3710, -6332, -4532, -1954, -3589, -2300, -4215, -5002, -3110, -2768, -1620, -3354, -4545, -4805, -1815, -1807, -3992, -4447, -6434, -1261, -2851, -6163, -4683, -5871, -1434, -4688, -9106, -4659, -4980, -2270, -6943, -8754, -4172, -4918, -3600, -8582, -8304, -3560, -5465, -4826, -8423, -7819, -3108, -6988, -5139, -8086, -6553, -3085, -11356, -6074, -9193, -5266, -3808, -6093, -7644, -11781, -4597, -5487, -3798, -5924, -9479, -4918, -6943, -3306, -5202, -8649, -6045, -6411, -3751, -6516, -8790, -6354, -6492, -4161, -8034, -8683, -5951, -7389, -4215, -5465, -8333, -6343, -7708, -4968, -3900, -6480, -6705, -7146, -8247, -3393, -4532, -6411, -6343, -10704, -3444, -3507, -6666, -5253, -6083, -3624, -3407, -7562, -4112, -5170, -3801, -4299, -8138, -3415, -5401, -4250, -6332, -8942, -3370, -6256, -5214, -8942, -11488, -3876, -7960, -6943, -9149, -9639, -4713, -10613, -11004, -9479, -7503, -5924, -13365, -11781, -11115, -7464, -7796, -10704, -7960, -11629, -9753, -10210, -7644, -7960, -10899, -13365, -17034, -6457, -11488, -10284, -9238, -10362, -7644, -12534, -8982, -7687, -6565, -8903, -11781, -8034, -7623, -5422, -5014, -15615, -7912, -8517, -5879, -3535, -7936, -8333, -9331, -7774, -3357, -6434, -9022, -10069, -9639, -3594, -6828, -9812, -10799, -10442, -3910, -8485, -11115, -10001, -10899, -4708, -8304, -13738, -8549, -8454, -5751, -6457, -12123, -6565, -7503, -5202, -5942, -8754, -5097, -8549, -4583, -6163, -7066, -4564, -9022, -5214, -6163, -6074, -4912, -7213, -6480, -6943, -5584, -5862, -7317, -6388, -9639, -5630, -6153, -10069, -6445, -7484, -6246, -5472, -17034, -7097, -5319, -6773, -5049, -11488, -6469, -4826, -6602, -5253, -12123, -5871, -5569, -6615, -6183, -13365, -6422, -7842, -6653, -7865, -13049, -8304, -9695, -6074, -9022, -12776, -13049, -6705, -5970, -8220, -10069, -13365, -5049, -7146, -8034, -8454, -10138, -4303, -9695, -9585, -7484, -9812, -4399, -10799, -13738, -6026, -13738, -5759, -9639, -10001, -4640, -9812, -10138, -8034, -8582, -4149, -5646, -7752, -7034, -9284, -4559, -4112, -4837, -7264, -10899, -5718, -3856, -3817, -8423, -9531, -7426, -4569, -3720, -9639, -7004, -9753, -6045, -4238, -9380, -5531, -13365, -7984, -5189, -8423, -4826, -17034, -8827, -6204, 10085, 11221, 8963, 11018, 8334, 9316, 10859, 8285, 10493, 7927, 7109, 9776, 6180, 8944, 6627, 6461, 8059, 4071, 6596, 4456, 7327, 6182, 4924, 4416, 3687, 6875, 5014, 5059, 3515, 4214, 4988, 4298, 3876, 2967, 3293, 2754, 3230, 899, 2199, 122, 5608, 1801, -3779, 2184, -2036, 6931, 770, 1667, 1695, 1483, 6717, 487, 2971, -1433, 3730, 6108, 9, 2941, -490, 5580, 5814, 1001, 3414, 3220, 6865, 4438, 3648, 4125, 4494, 7290, -670, 4812, 3796, 4447, 6636, 531, 4412, 2070, 3617, 4561, 2454, 2450, -1029, 2858, -167, 1760, -304, -2020, 2464, -1854, 314, -278, -1401, 1950, -249, 50, -185, -1652, 1419, -1168, 992, -816, -1865, 1288, -1944, 1695, -1462, -1035, 1282, -1156, 1557, -1074, -138, 745, -301, 145, 338, -193, -773, -409, -1961, 1326, -1428, -4545, -1606, 840, 1391, -2253, -3656, -2188, 2628, 590, -206, 146, -1766, 3111, -645, 1245, 1269, -2146, 2745, -1472, 1586, 646, -1205, 1636, -1472, 912, -2046, 621, 718, -1254, -677, -3996, 1552, 1851, -1340, -2597, -2210, 1793, 2748, -1003, -2853, -3837, 1757, 2764, -220, -1321, -6528, 1499, 2660, -245, 117, -692, 697, 2803, -2121, 1046, 881, -893, 2547, -5599, 1485, 710, -3420, 1743, -892, 1465, -765, -9695, 847, 294, 1035, -1621, -3744, 60, -765, 367, -1573, -816, -704, -3252, -262, -4336, 410, -996, -1746, -635, -2386, 1060, -803, -526, -674, 787, 1419, -916, -433, -969, 1473, 1277, -2055, -1387, -2391, 458, 445, -5031, -3714, -5827, -2699, -1258, -8454, -4991, -10704, -5516, -4816, -5630, -3177, -5002, -2000, -8192, -5487, -1236, -1732, -415, -3034, -7583, -54, -280, 585, -1935, -10442, -31, -159, 1112, -2766, -5970, -1386, -1286, 969, -5561, -3653, -5061, -4115, 9, -4890, -2635, -8060, -6540, -2042, -2758, -2328, -5176, -4573, -6194, -1894, -2409, -4779, -4754, -6365, -1980, -2873, -3457, -6321, -3600, -3294, -4258, -2686, -6870, -2791, -7708, -6653, -3498, -5292, -2637, -7213, -2648, -4774, -2666, -2345, -4728, -148, -3404, -991, -1798, -5942, 881, -2534, -497, -1494, -7984, 964, -3080, -1008, -1873, -5480, 294, -4723, -1962, -3080, -6035, -1210, -4311, -2273, -3951, -7644, -4149, -3563, -1740, -3286, -4184, -6870, -4278, -1111, -2703, -2793, -3827, -6267, -1123, -2571, -2918, -2766, -9149, -1928, -2541, -4127, -2485, -8034, -2679, -2534, -5784, -2323, -6399, -2679, -3054, -6553, -2873, -7162, -2289, -4451, -6899, -3729, -13365, -1483, -5951, -7665, -1936, -8304, -1236, -5451, -6163, -606, -8138, -2143, -4649, -3626, -686, -8718, -4191, -4890, -2596, -2069, -3843, -4946, -6577, -3386, -4408, -2314, -3720, -8333, -7353, -5554, -2406, -2975, -6214, -9585, -4800, -3147, -2778, -3468, -7464, 5303, 7699, 9187, 7182, 4567, 4998, 6945, 8808, 6800, 6044, 4016, 4641, 7734, 5870, 7372, 2124, 2279, 6223, 5179, 7694, -1627, 1455, 4947, 4994, 7330, -6590, -3557, 4399, 4182, 6588, -993, -433, 3796, 1087, 5559, 501, 2203, 3461, -3198, 4384, 1062, 2649, 4003, 1569, 4012, 14, 2320, 3825, 506, 4519, -168, 2061, 2599, 225, 5207, 4308, 2727, 2718, 4269, 5699, 6329, 3881, 3698, 5604, 5512, 6863, 4638, 3582, 5193, 4359, 6259, 4768, 2425, 2746, 2310, 4553, 4327, 1066, -8363, 817, 1687, 3442, 421, 985, 1515, 656, 2389, -848, 2451, 2318, 1567, 1285, -1548, 2667, 2153, 802, -781, 1189, 2677, 623, -3449, -1863, 2437, 2450, -3399, -2374, 653, 2143, 1299, -4115, 1206, 1239, 557, -672, -877, 2275, 137, -340, 442, -147, 2466, -2253, 976, 1057, -322, 2106, -3583, 1713, -346, -583, 853, -3846, 1280, -1516, -992, -2467, -5002, -1289, -382, -1966, -6786, -5561, -2173, -867, -2024, -953, -3735, 1651, -3235, -468, 821, -1702, 2434, -3665, -100, 1454, -754, 1052, -2165, -2054, 1425, -1578, -2705, -1941, -10442, 1399, -6332, -615, -2427, -1236, 1845, -3179, 545, -2807, 660, 2260, -1174, 79, -3618, 1333, 2397, -1057, -1225, -4486, 1769, 2385, -526, -2787, -3879, 2168, 2090, 369, -2082, -2198, 2192, 1022, 839, -326, 302, 1657, -1595, 736, 328, 1621, 759, -3808, -205, -284, 1520, -113, -2126, -1482, -2129, 10, -749, -3329, -886, -5020, -2924, -1653, -9936, -6, -9695, -5793, -4149, -4564, 217, -10210, -6113, -14195, -3114, 243, -5539, -5020, -4754, -1482, 361, -3546, -3906, -3354, -311, 278, -2435, -2505, -3291, -413, -266, -1920, -1134, -3698, -1820, -953, -1626, -478, -4573, -4831, -901, -1300, -715, -5726, -14195, -316, -1038, -1913, -6457, -7523, 226, -1105, -4336, -7888, -4733, 698, -1600, -5654, -28777, -3191, 860, -2720, -3798, -7730, -2130, 313, -5408, -3354, -5306, -1169, -1352, -7665, -4157, -4842, -298, -4491, -4093, -4869, -5202, 100, -4500, -3846, -4270, -5339, -226, -2999, -6299, -3101, -4847, -1356, -2743, -8333, -2342, -4601, -3360, -3094, -10613, -2462, -6026, -6163, -3680, -5906, -3580, -10001, -7503, -4270, -1680, -6143, -6310, -5615, -3910, -100, -7371, -4303, -4086, -2900, 241, -4226, -2191, -3665, -2779, -208, -2799, -864, -4564, -3529, -1405, -2465, -897, -6828, -3137, -3961, -3156, -2231, -8865, -2653, -28777, -5221, -3689, -6885, -3580, -5014, -4885, -3007, -4433, -5638, -3444, -3326, -2057, -3362, -6235, -4703, -3735, -1624, -3071, -4195, -9812, -6679, -1640, -2300, -3220, -2326, -17034, -1880, -1144, -4837, -67, -7146, -2072, -453, -7299, 484, -3294, -2210, -548, -1998, -191, -911, -2596, -1527, -374, -1921, 206, -2990, 9559, 7043, -6183, 6970, 8473, 9287, 7540, 4242, 7206, 8535, 8438, 8037, 6533, 7465, 8612, 6931, 7830, 7230, 7288, 8385, 5091, 6974, 6978, 6565, 7458, 4710, 5715, 6004, 5247, 5457, 4882, 4077, 4551, 3744, 2095, 3670, 937, 3061, 3880, -710, -698, -4254, 1885, 4317, 484, 1705, 1691, -752, 3453, 1833, 4786, 2420, -2163, 2260, 608, 6022, 3268, 3204, 3217, -7179, 6134, 4795, 4331, 3255, 1001, 4940, 4841, 2835, 2286, 1770, 1232, 2483, -8247, 3633, 3913, -1412, -585, 2881, 4654, 6081, 1930, 2905, 4320, 4163, 6732, 1310, 3242, 3768, 2312, 6124, -2728, 1981, 2061, -740, 4500, -4089, 265, 512, -6411, 2225, -305, -331, 978, -3114, 1372, 487, 6, 2036, 32, 2416, -278, -552, 2470, 1348, 3030, -3526, -3490, 2160, 1784, 3221, -5638, -5702, 1329, 1637, 3304, -1798, -2912, 588, 965, 3035, -994, -4031, 389, -566, 1631, -1134, -8683, 247, -2347, -3194, -1934, -4176, -10, 254, -1407, -3054, -3482, 306, 2206, 1354, -2420, -2764, 1077, 2902, 1785, -1372, -919, 1499, 2692, 1317, -777, -231, 1376, 1797, 150, -448, -109, 870, 348, -3137, -437, 418, 109, -1810, -1811, -833, 539, -1189, -5662, 1290, -1392, -226, -2524, -10001, 1924, -1753, -1592, -15, -4869, 653, -828, -5380, 1940, -3172, -3674, 944, -4226, 2535, -2639, -3151, 1641, -765, 2104, -3507, -800, 766, -1104, 1027, -5654, -257, -2217, -4654, -283, -2302, -188, -4858, -967, -2071, -43, -587, -3860, 476, -4021, 818, -1277, -5592, -405, -3913, 852, -1505, -9695, -3526, -4207, 227, -1956, -12319, -7353, -6143, -1072, -3947, -7004, -9238, -9936, -2320, -10526, -4800, -4311, -10001, -1716, -6870, -4021, -2198, -8060, -1390, -4373, -3600, -2490, -7484, -2427, -2781, -3124, -5367, -7523, -4119, -1721, -3012, -6103, -8582, -4968, -1534, -3698, -3365, -13049, -6885, -2672, -5768, -2490, -8615, -7960, -7247, -11629, -2020, -6590, -5380, -5326, -5768, -1643, -8454, -3360, -1516, -3089, -1556, -9149, -1952, -158, -2075, -1707, -3692, -1761, 150, -2348, -1825, -1774, -3549, -32, -4053, -1852, -1175, -7113, -372, -7623, -2175, -1237, -2192, -1107, -13365, -3586, -1344, -520, -2596, -10799, -7542, -1507, -454, -3444, -6705, -4583, -2282, -1439, -2034, -5164, -2522, -3876, -3124, -815, -4303, -2545, -5319, -5718, -198, -3944, -3846, -5401, -6288, -160, -4307, -4230, -6183, -3179, -900, -4764, -2032, -9695, -2094, -2779, -4223, -257, -8454, -2651, -5561, -3108, 589, -5960, -5312, -5091, -2297, 614, -4266, -10210, -2999, -1944, 83, -2891, -4963, -1704, -1814, -748, -2793, -4361, -1597, -1838, -1921, -3738, -5487, -2557, -2182, -3551, -2916, -2722, -3717, -2988, -4344, -1685, -503, -3521, -4299, -3785, -1759, 237, -2698, -4161, -2540, -3201, -1264, -6492, -4254, -1427, -4442, -132, -3196, -3729, -1206, -5437, 23, -1994, -1991, -2014, -4348, -570, -2107, -1103, -3635, -4323, -1759, -2247, -1505, -5408, -6773, -3220, -1610, -2956, -6434, -6163, -3933, -984, -3367, -4425, -4307, -3515, -668, -2754, -2282, -6457, -2435, -517, -3058, -1276, -5170, -1661, -564, -3474, -1444, -986, -1564, -981, -2311, -2924, 375, -1932, -1674, -1232, -4369, 301, -2655, -1935, -1002, -2731, -760, -3930, -1590, -1680, -1602, -2168, -6256, -1473, -3795, -1616, -2827, -8192, -1865, -8683, -3029, -3194, -5776, -2040, -3016, -8138, -4764, -4541, -1183, -594, -4853, -2869, -4620, -291, 217, -2458, -436, -4997, -117, -229, -2540, 269, -4748, -985, -1822, -4420, -393, -5073, -3347, -2914, -7888, -2388, -5299, -7774, -2262, -8304, -5031, -3732, -6225, -2130, -5584, -5387, -2650, -5037, -2815, -4478, -6103, -2445, -4451, -4550, -5079, -8304, -2979, -3726, -8220, -5394, -7774, -4550, -2956, -6540, -3811, -5049, -6759, -2213, -4963, -3198, -3314, -5915, -1666, -5394, -3438, -2984, -4896, -1567, -7819, -3680, -4172, -4108, -2055, -8454, -3589, -6602, -3621, -3225, -6628, -4093, -6054, -4157, -5279, -7034, -6828, -4625, -6745, -8942, -8582, -7665, -4795, -15615, -4611, -8423, -3989, -7335, -6628, -1768, -7464, -3386, -7445, -5516, -681, -6988, -4912, -4382, -6246, -1021, -7819, -6943, -4176, -7842, -3005, -10526, -3833, -6666, -8754, -6422, -11629, -1928, -6628, -7162, -4545, -9873, -1080, -3096, -4880, -3121, -8165, -1126, -1561, -3080, -2785, -7004, -2165, -931, -1746, -3016, -6540, -4290, -949, -991, -3264, -6388, -7960, -1656, -944, -3360, -6516, -9238, -2843, -1525, -3526, -7299, -5607, -3049, -2195, -3978, -7162, -4315, -2562, -2458, -4545, -5678, -4573, -2952, -3154, -4242, -5061, -6183, -4826, -4923, -3569, -5103, -8220, -9106, -5524, -3074, -5079, -7299, -6842, -4340, -2672, -5061, -4442, -4816, -3811, -2339, -5584, -2774, -4064, -3820, -1939, -7623, -2497, -3650, -4219, -1680, -11232, -3415, -3498, -4837, -1778, -6800, -4929, -3801, -5079, -1995, -5623, -5702, -4545, -5214, -2173, -6422, -5266, -5049, -5793, -2785, -9022, -4597, -5286, -7196, -4532, -10138, -4315, -6376, -10442, -9284, -8790, -3748, -7936, -7819, -7865, -10069, -3175, -6653, -4640, -4974, -9193, -3615, -5960, -3126, -4223, -4923, -5879, -7213, -2540, -4399, -3331, -11232, -9149, -2585, -4779, -3438, -6528, -8060, -3121, -4935, -5387, -4708, -8454, -4180, -5260, -11781, -3971, -12319, -5638, -6445, -10001, -3674, -9429, -6113, -8683, -7317, -3704, -7281, -5234, -10001, -5979, -4142, -7196, -4929, -8304, -5638, -5240, -7842, -5599, -6332, -6800, -7247, -7371, -7264, -5014, -10362, -8982, -5942, -10210, -5002, -8865, -9022, -5055, -17034, -7335, -6434, -10442, -5422, -7752, -12123, -6035, -11004, -8060, -5516, -5793, -3130, -236, -4142, 321, -2964, -3846, -1086, -4779, -411, -3373, -2334, -2833, -4307, -1961, -5546, -639, -5569, -4578, -4559, -10704, 158, -5374, -4550, -9331, -3751, -90, -3321, -3213, -8086, -1527, -1549, -2776, -2756, -6732, -836, -4826, -3913, -3837, -7503, -1241, -6054, -8549, -5279, -6332, -2613, -3401, -7213, -4184, -4274, -4885, -2507, -4266, -3695, -3257, -7730, -2594, -3618, -4223, -3331, -10069, -3479, -3476, -5067, -4743, -8333, -4805, -3140, -6153, -8903, -5121, -5139, -2735, -7281, -10284, -2910, -4795, -2502, -7503, -5718, -1936, -4874, -2342, -6705, -3951, -2385, -5415, -1580, -5933, -4093, -4805, -4447, -434, -4369, -9380, -3058, -2414, 136, -2390, -3866, -399, -1215, -426, -1308, -730, 367, -624, -2422, -1214, 94, -143, -300, -3342, -1780, -573, -1341, -574, -2416, -2420, -2895, -2159, -2264, -3468, -2696, -6399, -2192, -7865, -3546, -2739, -5516, -1920, -3992, -1381, -3071, -6828, -1953, -1986, -627, -4438, -14195, -2675, -1817, -783, -6759, -5429, -4545, -2529, -1280, -4578, -3751, -9753, -3906, -1992, -3179, -4357, -7842, -6973, -2774, -3563, -9873, -5531, -9936, -3833, -6235, -5801, -5472, -3763, -6988, -9284, -3349, -5654, -1719, -6267, -4157, -3870, -4885, -1131, -3433, -2553, -7299, -3586, -1625, -3430, -1965, -5726, -2724, -2450, -4885, -1753, -3130, -2713, -1726, -3279, -2045, -2039, -3677, -778, -1615, -2952, -1468, -6133, -805, -1362, -4064, -1174, -7408, -1804, -2257, -4640, -1264, -3776, -3375, -4361, -4108, -1838, -1954, -4295, -8549, -3249, -2900, -1471, -3782, -10001, -2904, -4429, -2339, -2827, -6054, -3056, -6183, -5465, -2378, -4583, -3650, -6516, -13738, -2657, -4286, -4733, -5415, -7730, -3047, -5061, -5997, -4215, -7389, -2510, -6914, -6225, -3785, -3804, -1699, -6679, -6278, -4573, -2396, -1465, -4390, -7389, -6590, -2912, -2189, -3232, -9149, -6943, -5554, -4399, -2912, -7426, -3677, -10001, -6666, -3010, -4985, -1450, -8485, -4119, -3344, -3254, -568, -10284, -3244, -3529, -2336, -888, -17034, -3594, -2933, -2283, -2065, -9149, -4478, -2283, -2912, -2756, -7503, -5247, -2583, -3626, -2553, -6565, -5539, -4464, -3866, -2741, -5346, -5273, -6590, -4067, -3624, -4100, -4664, -4616, -4523, -4968, -3509, -3985, -4597, -5266, -6492, -3944, -3124, -5524, -6225, -7583, -5662, -2516, -3460, -7213, -7019, -7865, -2841, -2186, -7371, -6540, -7503, -4896, -2291, -6143, -6153, -7408, -9873, -3326, -5726, -6113, -8393, -5759, -4869, -7819, -7317, -10362, -4311, -6615, -11488, -8865, -8034, -4395, -8034, -6422, -7299, -4203, -4923, -8485, -5509, -5654, -2205, -4985, -8304, -5646, -4847, -1551, -5103, -9064, -5339, -4800, -2020, -6332, -13049, -4226, -5002, -3574, -8192, -12319, -3304, -4858, -6528, -6628, -9284, -3101, -4683, -9193, -6054, -8649, -3589, -4912, -6705, -7299, -9106, -4344, -5561, -6163, -5654, -3549, -3222, -81, -2244, -5694, -3554, -5638, -1350, -2713, -5339, -3027, -5408, -4119, -4455, -6194, -2274, -3850, -28777, -5121, -9812, -2179, -2739, -5367, -3698, -10613, -3042, -1953, -4399, -3656, -5152, -4536, -1574, -7644, -5623, -2448, -4790, -1786, -6492, -6653, -946, -3504, -2783, -2534, -2347, -607, -2427, -4805, -1712, -595, -1822, -1884, -8790, -2567, -433, -7146, -1591, -12776, -4104, -1813, -3913, -1258, -5810, -3748, -4625, -1117, -894, -2475, -3647, -3804, -437, -716, -436, -3507, -2452, -641, -852, 417, -1026, -2107, -1092, -1494, -59, 838, -1694, -742, -3096, -2222, 1690, -683, 137, -4674, -3689, 1758, 488, 596, -3029, -1825, 1156, 1340, 616, -2158, -1854, -73, 1654, 396, -2458, -4157, -2088, 1349, -157, -3281, -8333, -5662, 427, -1249, -3362, -5234, -17034, -968, -2817, -2841, -4482, -7066, -2256, -3999, -2679, -3804, -5247, -3457, -3509, -2519, -3239, -3860, -7097, -3284, -1890, -3830, -2747, -6553, -4869, -1263, -5646, -2155, -2383, -10799, -657, -7371, -1975, -1187, -5415, 69, -6565, -1622, -1250, -3103, 421, -4373, -1006, -1950, -2528, -141, -3349, -964, -2803, -3560, -2305, -3954, -2142, -3493, -7247, -11629, -6870, -4097, -3428, -5360, -3638, -15615, -3401, -2622, -3266, -1790, -7603, -2939, -2188, -3276, -1917, -6399, -4086, -2624, -4790, -3067, -6083, -5539, -4172, -9106, -3989, -6083, -3444, -5509, -8086, -4536, -6388, -1885, -3647, -4112, -6343, -4816, -1435, -2997, -2596, -10362, -2791, -1630, -4869, -2279, -7562, -2232, -2659, -10138, -2918, -6332, -3230, -6016, -2855, -4790, -6376, -3893, -3465, -755, -14195, -6516, -1941, -690, 113, -3804, -5465, -770, -83, 316, -1040, -3686, -543, -1045, -65, -259, -2401, -954, -3692, -983, -763, -2179, -1711, -8649, -1742, -1899, -3078, -1957, -14784, -1571, -2358, -4134, -1236, -6885, -1391, -2152, -3996, -703, -5333, -1912, -1945, -4191, -1024, -5933, -3208, -2184, -5319, -2294, -4601, -4723, -3624, -6310, -4336, -3391, -4115, -8485, -5871, -6093, -4826, -2345, -7796, -5759, -6214, -7623, -1213, -5061, -5292, -6516, -2841, -1245, -5183, -3723, -9812, -1501, -3203, -5979, -2939, -8112, -1826, -12534, -5710, -3144, -4319, -3117, -3329, -5422, -3677, -3105, -3913, -1615, -6083, -3788, -3393, -4130, -1546, -8718, -3612, -5306, -4901, -2473, -9585, -3274, -8683, -4951, -4365, -5599, -2956, -6399, -4184, -7503, -4478, -3347, -5444, -4365, -5662, -4837, -5279, -6123, -6133, -3142, -5743, -12776, -7196, -9753, -2478, -6183, -7299, -7146, -11356, -3168, -6773, -5260, -6267, -28777, -3349, -8276, -4929, -5339, -8192, -2032, -9936, -5599, -4896, -5546, -1317, -10210, -7281, -5260, -4764, -1018, -9531, -9812, -6183, -5221, -639, -8718, -11232, -6602, -6732, -524, -7213, -10138, -6504, -6719, -1026, -6480, -8517, -6856, -5158, -2107, 6798, 7074, 7441, 9543, 2855, 6478, 6828, 7179, 8840, 2171, 5702, 5860, 6589, 6326, 401, 4828, 4017, 6047, -2122, 1098, 3984, 3277, 5626, 3316, 2604, 3289, 3498, 5202, 3879, 2561, 1875, 2019, 4429, 2168, 451, -1842, -115, 2741, 2939, -1832, 3531, 2571, 365, 4447, 2033, 5403, 3833, -34, 4609, 3804, 5307, 4087, -1236, 3605, 4946, 3812, 4262, -3680, 1407, 5968, 1780, 4856, 708, -262, 6632, 1250, 5453, 2222, 1059, 6630, 1805, 5377, 1890, 1673, 5727, 1285, 4189, -82, 1402, 3735, -469, 1713, -524, 663, 1218, 1025, 533, 1409, -74, -756, 1815, 1403, 2102, -127, -2165, 789, 1467, 1872, 660, 1720, 1703, 1005, 1135, 1470, 3094, 4127, 567, 369, 1856, 2864, 5396, 582, 70, 1788, 1698, 5552, 653, 202, 1342, 115, 4523, 342, 326, 482, -8, 1890, -92, 520, -1235, 1628, -3653, 246, 1153, -4935, 2207, -3187, 1469, 1582, -6332, 1355, -3179, 2284, 1064, -6492, -1092, -2778, 2077, -247, -3641, -6045, -616, 583, -208, -1200, -7752, 1076, -2776, 116, -852, -2553, 2368, -5333, -1078, -1647, 123, 3239, -2182, -1962, -1747, 1543, 3547, -1483, -493, -948, 1965, 3185, -2791, -188, -767, 1346, 2088, -8220, -1372, -1261, -671, 383, -5933, -2661, -1453, -5472, -871, -3399, -1666, -1409, -6143, -949, -3535, -1652, -2146, -3889, -1023, -4890, -3830, -3594, -3247, -1568, -2897, -6225, -4365, -2619, -2571, -1023, -5451, -3766, -2181, -3563, -591, -9695, -3543, -2599, -4046, -1336, -6163, -5079, -4078, -3833, -2941, -3535, -13049, -5793, -3144, -4659, -2505, -5494, -7213, -2893, -4826, -1204, -3671, -9639, -3225, -3923, -315, -3814, -8333, -3468, -3264, -473, -3833, -7162, -2914, -2906, -1773, -2008, -5836, -2130, -2827, -3913, -676, -4223, -1717, -3281, -5387, -372, -3316, -1943, -4486, -6553, -1151, -3105, -3126, -7644, -6214, -3471, -3128, -5960, -9936, -3982, -10069, -2975, -4541, -4340, -3294, -6615, -2720, -1559, -2567, -4258, -5871, -2841, -264, -2189, -5743, -8138, -3833, -190, -2597, -4669, -9585, -6516, -1363, -3203, -4123, -8247, -8333, -4075, -3811, -5152, -7213, -4842, -6528, -4901, -7050, -5960, -3583, -5480, -7162, -5630, -4901, -3808, -5451, -10442, -3692, -3507, -5768, -6434, -7484, -2633, -2631, -10138, -7796, -5465, -2197, -2778, -5988, -7503, -4683, -2079, -4142, -4923, -7687, -4688, -1940, -7752, -6225, -8454, -5380, -1899, -10284, -9429, -6565, -7050, -2239, -5458, -7353, -5487, -9936, -2929, -4491, -6457, -5784, -8393, -3230, -4764, -7583, -7179, -6399, -2646, -5037, -9531, -9193, -5615, -2264, -5079, -10069, -9064, -5546, -2677, -5121, -7583, -7687, -5988, -3529, -5158, -5638, -7162, -6653, -3629, -5465, -5793, -6899, -7050, -3609, -6183, -9429, -6577, -6679, -4469, -6590, -6332, -2286, 7785, 7586, 8379, 8107, -3208, 7386, 7148, 7748, 7426, 846, 5927, 5541, 5936, 5140, 2902, 2135, 2276, 5262, -603, 3380, -1943, 3251, 6434, -509, 3575, 2411, 4432, 6523, 1883, 4396, 2794, 3957, 5366, 1586, 5210, 2766, 3328, 3344, -922, 5465, 2846, 3027, 1746, -3360, 4925, 2466, 976, 66, -3331, 3307, 1795, -4311, -3189, -1952, 2354, 1665, 2686, 980, 243, 4576, 2192, 4186, 2379, -316, 5805, 2692, 3983, 1994, -5592, 5902, 2750, 2765, 734, -3968, 5346, 2049, 1378, -448, -2512, 4722, 95, 611, -1438, -5472, 4100, -4644, -379, -2910, -7484, 2689, -3837, -1771, -695, -2590, -2022, -836, 109, 1915, -835, -314, 152, 1830, 2369, 168, 2944, 271, 2218, 117, 767, 3371, 119, 1649, -2699, 925, 2096, 265, 517, 1989, 268, -653, 674, -1380, 3055, -1068, -2062, 842, -8138, 3049, 722, -1236, 346, -2594, 3098, 2574, 36, -1193, -40, 3165, 2749, 1334, -2954, -41, 2734, 1090, 2301, 283, -2465, 1732, -3276, 2716, 2783, -7484, 565, -4816, 2094, 4090, -3689, -180, -5299, -632, 4546, -6093, -1008, -3526, -4985, 4304, -4500, -2683, -1453, 797, 3432, -379, -3060, -976, 2427, 2034, 624, -874, -1425, 2972, 531, 188, 855, -1370, 2824, -466, -794, 1954, -140, 1800, -1478, -1714, 2464, 280, -494, -4207, -3301, 2270, -372, -5026, -11232, -2791, 1055, -1574, -7503, -6492, -1003, -2345, -2666, -5592, -11356, -742, -5879, -2997, -3638, -2393, -1761, -1065, -2847, -2280, -33, -3264, -443, -3130, -2528, 336, -4491, -1681, -3474, -5037, -690, -4679, -4790, -4963, -8754, -2661, -2170, -9873, -7888, -5367, -3058, -441, -11488, -3018, -5710, -2650, 279, -6828, -1573, -7665, -3430, 375, -4831, -2123, -4258, -4373, 148, -4592, -4469, -2175, -3801, -292, -5014, -6973, -1410, -3373, -1063, -4536, -5942, -1623, -2213, -2129, -3554, -6083, -2990, -933, -2785, -2904, -7004, -6457, -852, -3110, -2779, -6615, -12319, -2250, -4031, -3187, -5158, -8138, -5067, -4145, -3971, -3900, -7984, -6973, -3554, -5037, -3232, -4826, -7464, -4164, -6480, -3165, -2950, -7097, -5524, -6666, -3626, -2472, -5531, -6007, -5043, -4654, -2933, -4429, -6899, -4460, -6856, -3754, -3954, -5312, -5145, -28777, -4215, -4082, -3367, -6469, -6299, -4469, -4779, -3087, -6516, -3883, -5607, -5067, -4134, -5158, -3329, -8615, -4611, -5208, -3937, -3893, -9331, -4718, -5465, -3686, -4997, -8192, -5743, -6870, -4527, -6083, -9753, -7196, -8615, -6640, -7542, -17034, -8393, -6692, -9812, -9585, -12123, -8276, -5401, -13365, -9064, -11629, -5951, -5026, -14195, -7842, -14195, -3837, -5951, -8138, -8034, -13049, -3003, -9753, -5970, -9022, -10526, -3754, -11232, -4831, -10442, -9695, -7389, -8649, -4067, -14784, -9639, -9429, -10704, -3600, -11356, 6658, 8051, 3191, 5852, 6426, 5577, 7421, 2768, 5544, 5464, 1428, 5620, 1553, 4373, 1558, 2037, 4506, 1016, 2219, -204, 4467, 5472, 3102, 2415, 3090, 5690, 5947, 4428, 3626, 3214, 6069, 5574, 4416, 4380, 2260, 4960, 4051, 3397, 5238, 1077, 1852, -454, 2164, 5482, 453, 2458, 649, 988, 4630, 834, 3979, 3454, -1805, 2821, 243, 3994, 4088, -2935, 907, -4373, 3141, 4061, 1336, -2793, -2906, 1326, 3585, 2243, -795, -1146, -2617, 2485, 467, 2605, -6007, -622, 865, -5768, 3440, 133, 1673, -1535, 1741, 2965, 3133, 1685, -3512, 3312, 1936, 4194, -718, -1045, 3316, 1025, 4256, -3311, 146, 2550, -603, 3830, 950, 521, 1779, -3362, 3464, 2255, 508, 1732, -360, 3331, 2248, 3, 2168, 1211, 3124, 1261, -1391, 2269, 1214, 2613, -934, -4644, 1496, 18, 1691, -5509, -8683, -625, -1999, 343, -3817, -4108, -6565, -1026, -1347, -2552, -908, -3659, 1291, -3007, -4100, 854, -258, 2611, -597, -2462, 1039, 870, 3040, 1617, -75, 242, 609, 2647, 2241, 480, 571, -1064, 1349, 1493, -95, 1096, -4991, -310, -230, -1198, 551, -7687, 247, -1626, -2499, -439, -1502, 1179, -3249, -4583, -1799, 1162, 1165, -2823, -4923, -4597, 2471, 329, -63, -3814, -2795, 2747, -1219, 1003, -2331, -2619, 2139, -3496, 996, 671, -10526, 918, -4728, 536, 1922, -1693, 58, -2460, 160, 1144, 243, 81, -548, 326, -2391, -519, -113, 261, 1099, -1476, -3321, -964, -23, 1681, -98, -1402, -1852, -1229, 1539, -1240, -712, -1507, -2756, 604, -4442, -2833, -1025, -4327, -877, -8363, -6653, -1325, -5988, -2664, -5451, -3615, -1683, -4017, -4266, -3482, -3792, -1126, -1661, -4743, -3717, -5531, -734, -39, -4153, -7371, -6214, -1065, 761, -3076, -4698, -5942, -1607, 739, -3020, -1880, -6343, -1837, -11, -3961, -1380, -7445, -2548, -1373, -4262, -2569, -4527, -4764, -3577, -3463, -6173, -2239, -8615, -6914, -2425, -11115, -1532, -8649, -5422, -2115, -7371, -2241, -11781, -3468, -3117, -7146, -4929, -10001, -2541, -5164, -6321, -12534, -6666, -2105, -5569, -5662, -6457, -6133, -1836, -5546, -6235, -5115, -7247, -1349, -6814, -7389, -4935, -10138, -908, -7603, -6504, -5615, -7865, -984, -6123, -5026, -7264, -5584, -1760, -4853, -4536, -6103, -5394, -3247, -4344, -5444, -4203, -6692, -4664, -4946, -8220, -4134, -8615, -4049, -6705, -8903, -6814, -8582, -3007, -8827, -7019, -10001, -6540, -2745, -9873, -6516, -4880, -5002, -3444, -9812, -6759, -4108, -4625, -5346, -7050, -8247, -5031, -5273, -5970, -4433, -13365, -6615, -6786, -3769, -2615, -6399, -7865, -9429, -2733, -1760, -4134, -7162, -11945, -2538, -1992, -3729, -4774, -9064, -2952, -3537, -4674, -3621, -7264, -4412, -6163, -6469, -4053, -6786, -8582, -5408, -6343, -5888, -4968, -5422, -3647, -6705, -5592, -4119, -4038, -3119, -7179, -5686, -4246, -3096, -3951, -5353, -4997, -6540, -2613, -5888, -3843, -4089, -10704, -2698, -6732, -3710, -4003, -5759, -3529, -5979, -4831, -4728, -4282, -4940, -6943, -6786, -5546, -3795, -5480, -11629, -7912, -5353, -3792, -4536, -9812, -7247, -4963, -4500, -3518, -7865, -6705, -5195, -6653, -2859, -7912, -6732, -5494, -14195, -2716, -8086, -6615, -5152, -10284, -3339, -7247, -6267, -4616, -8454, -5164, -5494, -7408, -4527, -6480, -8718, -3748, -13738, -5127, -4089, -6899, -2610, -13738, -7213, -2345, -6434, -2613, -7960, -7317, -853, -7353, -4597, -2216, -1503, 455, -2504, -2910, 184, 805, 1343, -59, 191, 874, 1438, 1525, 822, 1243, 203, 718, 790, 591, 720, -1761, -1390, -1001, -513, -1610, -4592, -4980, -3698, -2163, -8009, -6692, -7819, -5710, -3612, -6565, -8942, -6399, -6246, -3999, -6214, -12534, -4863, -7113, -3618, -6973, -13738, -4195, -8165, -3337, -4957, -11232, -4184, -8363, -3566, -3735, -7888, -4597, -10210, -4509, -3543, -5710, -5487, -10799, -6093, -3947, -5037, -6504, -8718, -6504, -4693, -6064, -7583, -8138, -5960, -5897, -10613, -9331, -6842, -6214, -7113, -8549, -9238, -6469, -6759, -7004, -5942, -9022, -9380, -6343, -7130, -5735, -8865, -9380, -5569, -7730, -7353, -7371, -5415, -5037, -7019, -14195, -7464, -4974, -4901, -6194, -6504, -10362, -6480, -5115, -6310, -3580, -11629, -8942, -5465, -6528, -2353, -7335, -8485, -5810, -5776, -2136, -5776, -5997, -5933, -5103, -2770, -5312, -4035, -5726, -5394, -4361, -5646, -3370, -5654, -6943, -7247, -7542, -4038, -6133, -10069, -13049, -10704, -6388, -7542, -8827, -12123, -6492, -9064, -11356, -7426, -10613, -5253, -6943, -10526, -7774, -10704, -5942, -6653, -7936, -8060, -10001, -8393, -8754, -7708, -6870, -9531, -9753, -28777, -8393, -6565, -10899, -7819, -11232, -8718, -7408, -10704, -6732, -9695, -9639, -8790, -7730, -6183, -9149, -14784, -9284, -6288, -6376, -8485, -10899, -9479, -5561, -7066, -7603, -7984, -10526, -5152, -7408, -6856, -7019, -11945, -5158, -8276, -6540, -6759, -11945, -5853, -11115, -6411, -6705, -10001, -7179, -13738, -6376, -6516, -8982, -6577, -9936, -6376, -6173, -9585, -5339, -7542, -6267, -5836, -9695, -5444, -6800, -6422, -5630, -7542, -7113, -7113, -7752, -5844, -5988, -9064, -6973, -11004, -6434, -5061, -7264, -6745, -10442, -7644, -4896, -6163, -7623, -11356, -9812, -5951, -6123, -9873, -13738, -11629, -9873, -6388, -13049, -8649, -11232, -10069, -6628, -13738, -7464, -13049, -6590, -7464, -10442, -7752, -28777, -6035, -9022, -8276, -9284, -9936, -6786, -9585, -7542, -13365, -7960, -8517, -9936, -8423, -13365, -7730, -11115, -12319, -10362, -9585, -9193, -13365, -17034, -8790, -9331, -13049, -12776, -14784, -7708, -11781, -13049, -10526, -13738, -8086, -13738, -12319, -8582, -11115, -8454, -8903, -13049, -7623, -9479, -6759, -15615, -3457, -6278, -8247, -10069, -10613, -3647, -4331, -6679, -8517, -10442, -4348, -4270, -5408, -5539, -14195, -6194, -6480, -4550, -5871, -11356, -11945, -17034, -3843, -8790, -7146, -7299, -8582, -3242, -8790, -5678, -4336, -9639, -3069, -6504, -5401, -2992, -11356, -3498, -5960, -5726, -2420, -6299, -4295, -6103, -6388, -2374, -4923, -5253, -5531, -7503, -2694, -4733, -5951, -4784, -9064, -3299, -4482, -5784, -5085, -9380, -4134, -3840, -6074, -6615, -7842, -4569, -3507, -7097, -9639, -6278, -4211, -3692, -8423, -9238, -5367, -3763, -4315, -11781, -9022, -4469, -3220, -4654, -5061, -9064, -2776, -2306, -3537, -1168, -2399, -686, -940, -1132, 793, 53, 718, 307, 677, 1358, 724, 1026, 774, 1301, 571, -17, 17, 304, 671, -1900, -2108, -2881, -880, -1281, -7888, -4451, -14784, -2030, -4541, -6928, -4010, -6183, -3018, -5776, -6278, -3170, -5360, -4940, -4123, -8009, -2947, -6299, -8393, -2945, -11945, -3225, -7484, -10526, -2359, -9936, -3551, -5844, -28777, -2485, -5862, -3710, -5043, -8718, -3671, -4238, -4295, -6204, -6679, -6773, -3923, -6540, -8754, -7019, -12123, -4357, -11004, -8060, -7912, -5988, -5067, -6246, -8333, -8276, -4469, -6143, -5055, -8754, -9531, -4688, -7562, -5152, -7097, -11629, -6528, -7912, -5844, -7004, -10210, -7752, -8220, -7247, -8304, -8220, -5576, -8942, -8865, -8865, -7247, -4513, -8754, -6354, -8718, -7281, -4191, -8423, -4295, -8138, -7752, -4258, -9193, -3512, -6007, -7523, -4733, -10899, -3726, -4923, -7389, -5793, -11356, -4831, -5115, -8304, -7936, -10526, -6958, -6093, -9695, -13365, -7888, -10704, -6553, -10284, -13049, -6035, -28777, -6123, -11356, -8942, -5615, -13738, -6035, -10899, -6445, -6628, -14195, -6928, -8034, -4980, -8683, -12534, -7888, -6732, -4592, -7842, -9149, -7247, -6103, -5189, -6885, -7034, -6943, -5686, -6640, -7281, -6163, -7503, -5726, -7796, -8903, -6064, -8112, -6745, -7426, -11629, -6083, -7842, -9238, -7583, -28777, -5942, -7353, -14195, -8582, -13738, -6093, -6540, -9380, -8615, -10362, -6988, -5109, -8138, -8942, -9380, -8485, -4378, -8827, -9936, -9695, -9812, -4985, -9873, -6773, -11115, -8683, -7081, -10899, -4759, -9585, -7317, -10362, -8112, -4270, -7146, -7247, -9022, -5353, -4963, -6113, -7819, -6973, -4578, -6719, -6332, -6388, -6083, -5810, -8220, -7708, -4991, -6288, -10613, -6899, -9873, -4640, -7050, -6958, -5888, -10284, -4974, -6692, -5020, -6007, -9873, -5638, -5694, -5221, -6225, -9639, -6800, -5319, -7281, -5422, -9380, -9479, -5694, -13738, -5115, -8982, -28777, -6759, -10799, -5933, -9873, -13738, -8086, -9753, -7179, -15615, -11945, -8865, -11629, -7247, -11629, -10442, -9639, -14195, -6814, -8393, -9238, -12776, -12534, -6705, -7281, -8060, -13738, -9812, -6928, -7213, -6628, -8220, -8485, -7299, -8220, -5670, -6773, -8865, -7912, -11629, -5387, -7464, -10899, -9193, -6246, -7523, -7113, -6602, -4049, -4616, -8363, -5576, -3701, -3626, -3933, -4703, -3866, -2564, -4127, -4416, -4805, -3449, -2429, -5871, -6299, -7299, -4238, -3412, -8754, -10442, -11629, -5915, -6332, -8827, -12123, -13049, -7583, -8485, -5933, -11781, -10613, -8276, -5008, -3714, -13738, -6666, -9149, -3840, -2499, -14784, -4826, -11945, -3580, -2023, -10210, -4223, -14784, -3549, -2270, -7583, -4837, -12534, -3468, -3227, -6602, -7247, -10138, -3319, -4790, -6943, -10899, -7603, -3321, -6445, -8903, -6914, -6016, -3415, -7066, -13738, -5465, -5451, -3112, -6745, -12534, -7819, -6422, -2366, -6602, -7445, -4985, -6759, -1265, -5844, -2259, -255, -2435, 46, -2403, 132, 1713, -43, 902, -53, 802, 2295, 890, 780, 936, -73, 1840, 631, -684, 803, -2672, 524, -828, -4532, -246, -5306, -1502, -3626, -7213, -1797, -5768, -3714, -7464, -3968, -3457, -8790, -4800, -8423, -3339, -5195, -7264, -5415, -8112, -3701, -6640, -6103, -6590, -8865, -4800, -11004, -7426, -7353, -10069, -6204, -7264, -12123, -8138, -10001, -6299, -3710, -13738, -9936, -9695, -4997, -2754, -10704, -11232, -9380, -4486, -3065, -9585, -7960, -8942, -5646, -3222, -9193, -5208, -9812, -9022, -2548, -9873, -3751, -11232, -8165, -2231, -13738, -3266, -7353, -7665, -2639, -11781, -3621, -5008, -8582, -3726, -7796, -4985, -3586, -6376, -5451, -6615, -8009, -2733, -4946, -7888, -6973, -28777, -2571, -4564, -10613, -9429, -11629, -3257, -4644, -6773, -14784, -10001, -4997, -4907, -5037, -7819, -8517, -7464, -5516, -5299, -6035, -7583, -7774, -7264, -8582, -5710, -7984, -7130, -11232, -10613, -6074, -9331, -7426, -6914, -6045, -6399, -8060, -8865, -5085, -5020, -6007, -6719, -12319, -5183, -5360, -5260, -6885, -8942, -6828, -7523, -4769, -8485, -5997, -7603, -8942, -4842, -9531, -5115, -6732, -4536, -5509, -8363, -5710, -7004, -2764, -6786, -8247, -6103, -6958, -2388, -7623, -7912, -5091, -6035, -2941, -6856, -6267, -4759, -6035, -3773, -6457, -5374, -5346, -6958, -3900, -7426, -5554, -6376, -7842, -3580, -9936, -6528, -7445, -8276, -3603, -9812, -7503, -8582, -8276, -4108, -8485, -7644, -9064, -7162, -4790, -9238, -7130, -8942, -6123, -5988, -12123, -6692, -9149, -5670, -8615, -10899, -6653, -8549, -5827, -8485, -9695, -7389, -7389, -5607, -6628, -11945, -9429, -6914, -4250, -6640, -14784, -12534, -7353, -3112, -8086, -10442, -14784, -8333, -2827, -10362, -9936, -13049, -9639, -3422, -10069, -10526, -12534, -11488, -4728, -8192, -10799, -9380, -14195, -6133, -7445, -11115, -6388, -17034, -7196, -7644, -13365, -5103, -28777, -8485, -8034, -28777, -4918, -14195, -9695, -8982, -12776, -5374, -11488, -8363, -11356, -10362, -6183, -11356, -6899, -12534, -9585, -7299, -13049, -6365, -11356, -9380, -9284, -15615, -6800, -8754, -9380, -10210, -28777, -8827, -6773, -9380, -7408, -13365, -17034, -6553, -9936, -6194, -9331, -8903, -8086, 11376, 9600, 11660, 11728, 10794, 10645, 9661, 10965, 11136, 10261, 8080, 9419, 8674, 9319, 8615, -18, 8340, 3679, 6278, 6050, 4297, 6180, -3083, 2848, 4811, 4815, 2931, -853, 375, 4712, 3398, -367, 841, -643, 3351, 2719, -1859, 1574, 86, -243, 545, -2462, 2805, 696, -6745, -297, -1544, 3809, 558, -6745, 5101, 348, 3513, 1460, 543, 6903, 1140, 3359, 3129, 4304, 7444, 2841, 4499, 4339, 6106, 7259, 5262, 5216, 4899, 6658, 6464, 6493, 5168, 4629, 6041, 4908, 6444, 4650, 3293, 3916, 2536, 5282, 3973, 311, -1635, 1323, 3644, 2994, -3650, -1062, 1611, 2734, 1071, 469, 991, 1308, 2214, -3412, 2037, 1585, 1509, 2032, -5458, 2347, 1907, 2238, 2269, -3266, 2357, 791, 2229, 2248, -5422, 2591, -10210, 1589, 1720, -2922, 2683, 1545, 1385, 414, -449, 2201, 4051, 1681, -218, -28, 1164, 4505, 1891, 1978, -683, 1006, 3441, 1794, 3098, -1833, 1661, 361, 980, 2706, -5326, 1731, -9873, -128, 1255, -3420, 1665, -3563, 609, 528, -83, 1988, -6899, 1023, -182, 822, 2326, -4764, -818, -3080, 789, 2510, -1636, -4416, -1648, 747, 2369, -395, 464, -533, 563, 1582, 348, 1789, -2585, -454, 230, 171, 1626, -6163, -2612, -261, -1567, 690, -712, -5623, -11, -9022, -642, 887, -5670, -553, -2770, -2791, 1072, -3910, -1872, 156, -8683, 157, -3659, -2248, 1306, -5487, -1837, -4831, -1674, 1494, -3961, -4831, -6928, -1717, 914, -6365, -5091, -8138, -1934, 148, -8192, -2128, -6602, -1076, 504, -3913, -887, -4703, -1, 1157, -2837, -1026, -4153, 495, 1065, -2509, -2064, -6278, 377, 131, -2153, -2997, -6469, -308, -1456, -1927, -2485, -1819, -1437, -2975, -2003, -1340, -322, -2673, -3010, -1298, -769, -276, -2409, -2447, -143, -840, -1041, -825, -2165, 321, -1030, -2071, 107, -1844, -8, -941, -3194, 137, -1774, -805, -729, -4536, -425, -2424, -1370, -618, -6943, -654, -3714, -1699, -795, -4262, -197, -4821, -3071, -1489, -1746, 121, -4997, -6628, -2735, -1214, -4, -4654, -5014, -3916, -2289, -681, -4723, -3365, -4743, -5539, -2107, -4408, -3354, -5784, -14784, -4003, -2754, -3876, -4991, -8517, -5339, -1248, -3521, -4800, -10442, -5444, -396, -2247, -6615, -6705, -3049, -21, -1444, -5516, -4654, -1859, 102, -1650, -4262, -5326, -2053, 59, -3062, -4669, -5401, -2490, -141, -6354, -4896, -2895, -2370, -507, -4630, -4361, -2871, -2778, -1177, -1438, -4258, -6565, -3380, -2364, 127, -5569, -2495, -2071, -3347, 786, -10001, -135, -656, -2253, 525, -7960, 125, -63, -1122, -1137, -5487, -1067, -40, -1082, -5531, -3773, -3457, -352, -2497, -4319, -3165, -6399, -1491, -6565, -2819, -4226, -12534, -4438, -8942, -3215, -5509, -4698, -3083, -11945, 1793, 7416, 7860, 8286, 5452, 1371, 6707, 7367, 7598, 4865, 859, 4671, 6004, 5249, 3697, 1201, 3925, 4138, -188, 3502, 1367, 4927, 1968, 1484, 3547, 1083, 4869, -311, 2595, 3202, 1199, 3943, -770, 2255, 2986, 2004, 2805, 798, 1919, 2818, 2829, 2493, 2401, 1837, 2409, 3360, 2435, 3461, 1020, 2198, 4199, 2700, 4312, -1683, 3264, 5536, 4216, 5425, 452, 4817, 6465, 5055, 6365, 2468, 5736, 6588, 4760, 6417, 2299, 5879, 5957, 3956, 5170, 312, 5403, 4907, 3864, 1965, -1370, 4463, 4040, 3762, -8718, -732, 3017, 3628, 2079, -3647, 5, 1101, 3116, -4664, -6943, 1374, -280, 2106, -571, -5195, 2164, -1166, 1542, -359, -3782, 2141, -2699, 1374, -2999, -4017, 1695, -4361, -142, -58, -4564, 1226, -3076, -3683, 394, -7299, 659, 12, -2952, -183, -1849, -163, 1972, -465, 1043, -1064, 175, 3156, 1730, 1835, -4821, 1291, 3878, 2879, 1654, -2385, 1302, 4166, 2946, 817, -301, -126, 3942, 2059, -691, -1304, -1654, 3174, 283, -1281, -3726, -618, 1811, -2470, 796, -3954, 438, -478, -6504, 1793, -3386, 1220, -5333, -6123, 1070, -1175, 1843, -2470, -2900, -2622, -39, 1965, 110, -788, -4195, 73, 922, 774, 211, -345, -154, -3286, 238, -9, -127, -353, -1614, -1113, -1513, -1868, -778, 1504, -2358, -1355, -6278, -1746, 2188, -2576, 517, -7162, -2918, 1649, -1753, 1130, -4164, -3612, 174, -191, 631, -2526, -3149, -2462, 1037, -441, -2036, -2006, -5871, 1282, -1180, -2265, -1462, -1961, 118, -1614, -1123, -1900, 403, -3347, -2291, 688, -3014, 1543, -7484, -1928, 1715, -3124, 1816, -7819, -171, 1837, -2129, 1362, -5569, 1082, 1220, -1526, 336, -955, 1433, 536, -1068, -1154, 340, 843, 424, -287, -3515, -196, -471, 35, 240, -10526, -3040, -931, -1404, -147, -4625, -7912, -232, -3683, -1975, -2468, -2130, -132, -4901, -7097, -2363, -719, -894, -3846, -6278, -2897, -536, -2411, -1727, -3049, -3065, -987, -4880, -815, -1836, -1671, -1654, -8549, -1481, -1872, 526, -1587, -5686, -3680, -3629, 1639, -788, -3650, -3189, -8247, 1469, -235, -3208, -1495, -7230, 58, -191, -4408, -921, -10069, -2302, -912, -6692, -979, -7034, -4266, -3189, -2900, -1201, -3804, -4278, -7960, -1328, -752, -3135, -3850, -3504, -1635, -181, -2008, -4495, -1849, -2219, -498, -514, -3284, -1613, -1161, -2030, 177, -1225, -2644, -818, -4250, 22, -892, -6480, -1725, -3067, -911, -2745, -5487, -2646, -1057, -2191, -2666, -2741, -2821, 89, -2427, 166, -2277, -3714, 265, -2612, 874, -2207, -4278, -848, -4532, -226, -1957, -3027, -4500, -12776, -4495, -1318, -1769, -6035, -4940, -4743, -55, -906, -2462, -2648, -1382, 517, -714, -1779, -2086, -870, -413, 3125, 4077, 7513, 329, 5137, 2368, 4078, 7330, 2346, 5914, 4496, 4120, 7077, 4812, 6870, 6162, 4241, 6907, 5747, 7093, 5901, 4017, 6273, 5135, 6445, 3593, 2714, 4624, 2982, 4950, -3704, -676, 1298, -573, 3187, -516, -3903, -6732, -2302, 2372, -807, -1953, -2929, -599, 1732, -3726, -1857, -1777, 933, 969, 2994, -108, 189, 2259, 1100, 5327, 2648, 1713, 2849, 1221, 5969, 4394, 1652, 2570, 933, 5191, 4743, -337, 2764, 2724, 2707, 3459, 601, 3544, 4731, -2994, -82, 2471, 3461, 5554, -6469, 336, 2253, 2219, 5207, -3247, 1469, -86, 388, 3696, -1460, 270, -7426, -368, 1416, -454, -2015, -4795, -135, 303, 1089, -1209, -3034, 67, -227, 2194, -100, -2114, -395, -81, 2402, 201, -1272, -2277, 886, 1891, -98, -612, -6399, 1092, 871, -943, -174, -2201, 1433, -395, -2229, -45, 100, 2453, -821, -3808, -306, 952, 2811, -228, -3597, -1055, 861, 2073, -232, -1474, -2223, -70, 931, -1636, -308, -2646, -1899, 910, -6045, -82, -1747, -4718, 1230, -6553, -297, -722, -5487, 1521, -2622, -855, 190, -3609, 1725, -1241, -2361, 899, -1630, 1705, -921, -5539, 1178, 565, 2127, -1912, -11232, 733, 2054, 2927, -5970, -6204, -594, 2509, 3207, -3566, -2813, -1411, 1982, 2359, -720, -1594, -82, 1084, -559, -83, -1879, 952, 872, -3218, -927, -3314, 1339, 668, 961, -2615, -4420, 1314, -327, 2380, -1076, -2819, 1241, -2238, 2687, 352, -1664, 1511, -5584, 2189, 137, -2259, 1823, -3951, 807, -1777, -5339, 1587, -1368, -1627, -2950, -3455, 416, -294, -2294, -1077, -1773, -2355, 233, -465, -544, -2626, -9753, 520, 412, -1343, -6856, -2722, 345, 363, -2819, -6332, -479, -383, -635, -2681, -3788, 496, -1391, -3036, -1817, -2631, 649, -2460, -6842, -1766, -1320, -39, -3804, -2833, -2022, -242, -1637, -4669, -749, -1838, 117, -2737, -4172, 351, -1682, -605, -1030, -4399, 968, -2404, -2937, 672, -7179, 867, -4352, -8582, 1503, -12123, -470, -2603, -6914, 1408, -7130, -3367, -386, -6885, 355, -8790, -1598, 179, -9022, -1652, -6143, 178, -691, -4295, -3388, -2548, 541, -3463, -2015, -3023, -894, 301, -6692, -1305, -3618, -388, -122, -2510, -1773, -7503, -1050, -809, -1005, -3210, -5394, -3337, -1807, -894, -4831, -3269, -3603, -2675, -1827, -8138, -2294, -1187, -2514, -3089, -6007, -972, -224, -1807, -3597, -1361, -187, -99, -1843, -4086, 148, -406, -730, -3357, -5743, -237, -1953, -2622, -4420, -11945, -3124, -6553, -6376, -1752, -6365, -8247, -6267, -5487, -1097, -3683, -3441, -3615, -4482, -3124, -2567, -2076, -1518, -3329, -7081, -1771, -180, 215, -1460, -2073, -1183, 856, 567, -1010, -923, -1428, 553, -630, -3040, -942, -3635, -4315, -2251, -1484, -4226, -3468, -4688, -2135, -2475, -1104, -3741, -9639, -4207, -7389, -309, -4086, -6666, -5049, -3957, -702, -3632, -3989, -2831, -1501, -596, -3191, -4115, -2514, -586, 129, -3025, -6705, -2534, -976, 439, -2861, -13365, -1102, -3923, 1053, -3177, -6786, 293, -5853, 1860, -3738, -4779, 885, -1515, 1766, -3830, -4795, 757, -824, 165, -5933, -7603, 154, -2038, -4046, -5702, -5195, -627, -5951, -5784, -1778, -2076, -1206, -6074, -3218, -931, -1020, -1165, -3276, -1953, -2197, -1397, -771, -2762, -1080, -7984, -3566, -936, -3147, -509, -2615, -11945, -1678, -2280, 304, 632, -2681, -179, 325, 1363, 2254, -344, 1602, 2122, 2034, 2937, 100, 2137, 2605, 1773, 2796, -949, 1536, 1657, 104, 1900, -3507, -96, -987, -3583, 480, -6354, -3210, -4017, -2514, -1136, -6299, -9106, -4810, -968, -2801, -7371, -2893, -4527, -937, -3773, -9531, -1233, -2573, -1604, -3662, -2502, -1258, -2289, -2458, -3856, -224, -2875, -3447, -2845, -4640, 336, -8060, -5576, -2699, -5678, -279, -8276, -5759, -3054, -6288, -1724, -7562, -4527, -4513, -5970, -3744, -7230, -4412, -6267, -5227, -6628, -2641, -4386, -4880, -4738, -6411, -968, -3119, -3471, -4991, -4348, -782, -2090, -3659, -6143, -3149, -1591, -1651, -6828, -5133, -2176, -2992, -1445, -7842, -2910, -1830, -4433, -1449, -3817, -1525, -2807, -5836, -1595, -3698, -371, -5718, -7984, -1610, -5561, 637, -3701, -13365, -1774, -4974, 1135, -1673, -10362, -2592, -4319, 973, -1406, -9331, -4319, -7774, 277, -2432, -28777, -6814, -5487, -603, -4723, -5353, -6653, -1424, -1394, -7603, -2031, -4718, 68, -2140, -7130, -436, -3635, 450, -2914, -5836, -59, -3301, 278, -4067, -5451, -911, -3271, 2, -7213, -5195, -3112, -3098, -164, -8982, -3271, -6445, -2731, -503, -4348, -2165, -7130, -1869, -1571, -2731, -2497, -4985, -930, -3509, -1847, -3754, -3757, -513, -3344, -1672, -4738, -2248, -679, -2409, -3130, -5333, -476, -1378, -2596, -8485, -6045, 553, -2087, -3850, -3279, -6045, 736, -1773, -9429, -1341, -4527, 148, -930, -4703, -1067, -3603, -1199, -164, -1736, -1507, -3365, -3463, 149, -1435, -2150, -3521, -6225, -406, -3170, -2720, -4769, -4219, -1961, -6516, -2540, -6577, -2608, -4089, -3927, -1720, -5055, -2448, -6214, -2881, -1466, -4495, -3177, -9429, -3814, -2119, -5759, -3814, -12534, -6528, -3036, -9812, -3689, -10526, -6553, -3042, -9873, -3574, -6565, -4625, -3096, -5718, -4258, -5152, -4134, -4078, -4161, -6035, -6267, -5879, -6163, -3441, -8112, -28777, -12534, -7371, -2939, -7687, -5718, -4184, -5502, -2482, -5279, -4031, -2505, -4365, -2140, -3873, -4469, -2521, -4038, -1940, -4416, -4985, -3707, -3850, -1894, -9380, -4234, -6123, -3344, -2119, -5286, -4365, -10210, -3319, -2939, -2799, -6093, -11629, -1542, -2366, -3201, -1569, -4416, -3449, -4104, -8582, -3261, -4230, -2619, -6745, -6103, -6376, -1076, -517, -6343, -3856, -10069, -669, 406, -4238, -4513, -8393, -1117, 415, -2236, -5097, -6565, -1002, -163, -583, -2331, -4003, -1060, -1210, 310, 52, -2735, -2211, -3543, 244, 1264, -3518, -2847, -11945, -851, 1255, -6457, -2040, -2617, -3012, -118, -4021, -2223, -628, -6800, -3540, -2887, -3954, -380, -7708, -12319, -3621, -9695, -1351, -3704, -5306, -4644, -6194, -2843, -1240, -3476, -2776, -2768, -2480, 116, -1819, -907, -1489, -1339, 132, -782, -722, -650, -1144, -1346, -1181, -3271, 1068, -1040, -735, -3378, -1696, 2818, 351, 1279, -1225, 1663, 3821, 1190, 1568, 958, 2741, 4022, 696, -42, 1361, 2391, 3459, -1100, -4774, 352, 804, 2211, -3515, -5247, -1807, -1492, 565, -4606, -4195, -2516, -2778, -787, -3425, -4097, -1961, -2841, -1460, -1834, -3482, -2845, -1598, -2148, -859, -4438, -4997, -460, -4071, -542, -8276, -4112, -56, -11629, -1088, -7730, -2701, -218, -4555, -3319, -5942, -1887, -793, -2879, -7708, -6814, -1078, -1925, -3027, -1839, -8718, -303, -4254, -3383, 105, -4390, 327, -6540, -3496, 557, -1976, 392, -3906, -4262, 150, -1095, -813, -2468, -5879, -665, -1458, -5085, -1777, -7426, -1503, -2954, -4123, -1046, -5429, -2472, -4946, -1647, 120, -3034, -3779, -5367, -1913, 1154, -1711, -2893, -4365, -4352, 1504, -1025, -1050, -4495, -7299, 960, -618, -275, -8582, -4254, -661, -454, -437, -6354, -3367, -3540, -830, -1450, -3110, -4003, -4769, -2076, -3886, -2587, -6194, -4278, -3597, -9064, -3352, -13049, -3964, -2543, -2785, -4863, -9238, -2435, -1218, -270, -6214, -6540, -1810, -726, 1002, -4559, -4795, -2999, -891, 1576, -3117, -3968, -5367, -1825, 1555, -3168, -5031, -3071, -3964, 897, -4464, -6288, -2057, -7819, -626, -4929, -3067, -2863, -9022, -3982, -4134, -1598, -5273, -4703, -6732, -4361, -1378, -7426, -1883, -2803, -5979, -1983, -8615, -586, -1935, -7752, -3830, -6565, -557, -1762, -6814, -10069, -3896, -1704, -771, -6480, -4311, -3276, -2956, 83, -6914, -2112, -4416, -2372, -117, -6388, -2111, -8423, -2065, -1687, -5299, -4238, -8982, -2241, -5319, -4611, -17034, -6321, -1842, -8790, -4021, -4659, -8393, -1534, -7644, -3198, -2781, -8333, -1922, -9193, -2581, -2244, -3954, -2531, -4442, -2851, -2197, -2745, -2833, -1551, -4513, -2659, -2926, -3076, -324, -5906, -4176, -4153, -3098, -378, -4810, -7819, -6565, -2507, -1616, -6422, -6074, -8982, -1713, -4097, -9936, -3455, -8276, -1388, -8827, -3870, -2514, -6914, -2191, -7603, -2986, -2519, -5576, -5326, -3042, -4907, -3140, -5043, -9695, -1066, -11232, -4064, -5502, -5554, -455, -3913, -4738, -6732, -6504, -1077, -2425, -5067, -8060, -8982, -3133, -2677, -5726, -8683, -6278, -3161, -1181, -2789, -5743, -1790, -5607, -4918, -2787, -532, -5055, -4863, -5437, -3438, 1153, -4923, -3968, -2285, -7936, 1457, -939, -1872, -441, -3521, 789, 191, -697, 563, -1176, -606, -186, -867, 711, -702, -1288, -2086, -1765, -68, -1274, -346, -5115, -2460, -1966, -1774, 337, -4664, -3515, -5546, -960, 213, -5793, -6354, -11629, -85, -884, -9873, -9479, -6204, 186, -3551, -5115, -3321, -3644, -237, -8276, -3537, -497, -2560, -1990, -2730, -2142, 1089, -2578, -7752, -346, -1516, 1883, -3474, -1892, 753, -1222, 1911, -5319, -316, 1015, -157, 984, -8865, -1908, 604, -58, -97, -1940, -2442, 101, -2462, 1006, 1032, 1535, 786, -2319, 1736, 2215, 2780, 1759, 652, 996, 2082, 2543, 2055, 1236, -1352, 728, 1643, 1718, 336, -4723, -1878, 1452, 877, -1159, -3218, -5735, 1720, -448, -791, -1093, -4703, 1435, -1644, -20, -108, -2698, 551, -1859, -581, 153, -2569, -187, -2229, -2216, -45, -4238, -26, -2438, -266, -1116, -5888, 353, -1402, 1424, -3571, -3638, 339, -416, 1442, -3114, -2412, -388, 29, 143, -1792, -2065, -2305, 182, -778, -2512, -2000, -5615, 77, -606, -5145, -1980, -4433, -566, -1487, -2422, -2414, -3142, -2107, -2069, -94, -3811, -2821, -5214, -569, 790, -4311, -3101, -15615, 275, 718, -2225, -4644, -5170, 80, -188, -922, -10284, -2774, -1011, -1732, -682, -4545, -1800, -1369, -2178, -1427, -1727, -1899, -487, -1194, -1952, -300, -2926, -540, -804, -103, 464, -2677, -2123, -1423, 1369, 671, -915, -5862, -3334, 1645, 235, -12, -10613, -5853, 708, -1123, -92, -6516, -4258, -1471, -4172, -824, -3896, -3543, -3843, -11115, -1507, -2291, -4420, -4703, -6173, -1923, -1647, -6577, -4532, -5970, -2681, -1674, -8582, -2305, -8333, -3047, -2119, -5615, -1080, -12123, -1630, -2419, -4262, -1087, -5546, -86, -1908, -5408, -1884, -2348, 810, -1678, -9531, -2799, -546, 935, -2883, -3975, -3798, 191, 250, -4024, -1848, -5638, -80, -929, -1782, -1066, -7752, -1378, -1106, -938, -870, -7264, -3433, -510, -1741, -928, -3592, -6540, -792, -4331, -1053, -951, -6928, -2651, -6914, -1189, 250, -3067, -6528, -4254, -1197, 169, -1952, -3933, -3020, -957, -1095, -2309, -1879, -2895, -608, -2228, -3401, -973, -3729, -478, -1579, -4469, -606, -5195, -864, -886, -5247, -554, -5008, -1788, -425, -5584, -799, -2973, -2552, -508, -7146, -1484, -1085, -2841, -1664, -14784, -2701, -54, -4049, -4028, -5970, -4031, -53, -8517, -6194, -4569, -4262, -1013, -6640, -6026, -5109, -3707, -1882, -4089, -3779, -5960, -3417, -1490, -3808, -2288, -5429, -3549, -1206, -4858, -2153, -4810, -3944, -1691, -7113, -3438, -5208, -4191, -3161, -13738, -6411, -7196, -3923, -6828, -7113, -6256, -11781, -3471, -6183, 4555, 15411, 7007, 10967, 10737, 8875, 14992, 7271, 10267, 10109, 10369, 13697, 7163, 7923, 8085, 9998, 11391, 5948, 2320, 4153, 8634, 7948, 3896, -513, 552, 7384, 6331, 2489, 442, 440, 6092, 7580, 1513, 355, -2028, 5616, 7957, -317, 1608, -1364, 6813, 7370, -3060, 1339, 780, 6555, 5815, -2195, 251, 2419, 3138, 3196, 430, 757, 3938, 2245, 1437, 3113, 2371, 5047, 5984, 4148, 4832, 3588, 5594, 6338, 6446, 5374, 4266, 5513, 5190, 7346, 4652, 4298, 4535, 3562, 6799, 2430, 3586, 1997, 2533, 4485, 765, 2135, -1617, 1314, -1242, 1843, 164, 184, -1490, -1172, 1405, -1369, -411, -3232, -1131, -1009, -1508, -4093, -927, -3632, -6332, -879, -4119, -297, -1135, -3237, -139, -2075, -671, 60, -1756, 223, -1356, -2143, -962, -2730, 109, -877, -4718, -7097, -2726, -515, -497, -4759, -2241, 518, -1817, -808, -4890, 893, 1886, -3748, -2483, -9695, 2311, 1818, -3444, -7247, -2799, 3001, 615, -1488, -5037, -1157, 3018, -1370, -308, -2401, -1672, 2199, -2904, -13, -1314, -3766, 387, -2545, -743, -705, -6504, -2024, -1526, -2924, -419, -2208, -3449, -1261, -6943, -254, 319, -6026, -1999, -7865, -143, 1382, -8718, -3133, -8393, -323, 1337, -4769, -3677, -8112, -806, 21, -4592, -3751, -9238, -1176, -3632, -5133, -2502, -7665, -1149, -5827, -5026, -1637, -4664, -1204, -2470, -5615, -2340, -4378, -1817, -2118, -8220, -5686, -7264, -3172, -3140, -8827, -8582, -8718, -4708, -4743, -5710, -4858, -4460, -4912, -4573, -4708, -4764, -3769, -4754, -3563, -5133, -6365, -4748, -5607, -3496, -6469, -7484, -6278, -7819, -3827, -6602, -5623, -5319, -8276, -3227, -5539, -3820, -3603, -6732, -2855, -5306, -2772, -2517, -6411, -3729, -6602, -2637, -1956, -6885, -6973, -8582, -3266, -1771, -7408, -11356, -8827, -3827, -1948, -7583, -5915, -6480, -3744, -2819, -7562, -5247, -4518, -3889, -5292, -7408, -5646, -3441, -4940, -17034, -6434, -5607, -2545, -7687, -5422, -5202, -5189, -2416, -7644, -4067, -4555, -5026, -3543, -5158, -4635, -4703, -4683, -5599, -5026, -6577, -5502, -4583, -6973, -6773, -9873, -6246, -5924, -7730, -6153, -17034, -5960, -8060, -9936, -4800, -7960, -4880, -6628, -14784, -5221, -4759, -4127, -7464, -8138, -7774, -3222, -3846, -6074, -6602, -12776, -2809, -3603, -3208, -6288, -7281, -3203, -3375, -2325, -6615, -5472, -3985, -3417, -2935, -7708, -4880, -4635, -3843, -5189, -9585, -5306, -4821, -5279, -8304, -11356, -6516, -4573, -10704, -5103, -13738, -6016, -3951, -7960, -4046, -14784, -5240, -3594, -5020, -4929, -9429, -5306, -3824, -4250, -7730, -7019, -5879, -4601, -4344, -9479, -5401, -7247, -5853, -5189, -8112, -5312, -9429, -7984, -7050, -6732, -7230, -11629, -15615, -9639, -6267, -6267, -12776, -9106, -8582, -6943, -4573, -8138, -5951, -7264, 8226, 411, 6776, 10899, 8024, 7438, 1696, 6047, 10370, 7498, 4785, 3410, 3550, 8707, 5851, -1383, 4361, 1496, 5573, 3279, -6615, 4550, 3681, 387, 2930, -1050, 4148, 3959, 966, 3766, 2183, 3331, 2484, 2219, 3780, 3329, 2233, -378, 2612, 3424, 3556, 789, -265, 2591, 3346, 2596, 234, -611, 2600, 3792, 1704, 2757, 1456, 3414, 4338, 5176, 4562, 5128, 4379, 4499, 7056, 5170, 6859, 4481, 4032, 7438, 4820, 7148, 3264, 2816, 6602, 3842, 6041, 1187, 666, 4649, 2801, 2942, 2185, -3294, 1847, 2180, -28777, 3045, -6235, -819, 1672, -245, 2564, -3208, -2505, 535, -232, 1386, -2964, -3465, -1451, -786, 438, -2538, -942, -1457, -669, -469, -1540, 1080, -175, -2370, -2226, -1040, 1762, 391, -11488, -4907, -976, 1432, 604, -1869, -5408, -1245, 210, 656, -377, -5487, -1874, -1962, 337, -1040, -7097, -2851, -5836, -747, -4168, -6759, -4504, -9064, -2438, -6163, -4278, -8112, -4473, -1415, -2795, -2837, -5584, -3074, 223, -2270, -2149, -2984, -3286, 756, -3321, -1587, -2331, -5584, 356, -5906, -846, -2378, -12319, -710, -10284, -286, -1996, -5195, -2247, -11629, -341, -776, -3580, -5152, -7644, -1509, 500, -2709, -9284, -4536, -4946, 1008, -1621, -3225, -2841, -2102, 543, -1136, -2386, -2075, 960, -628, -1855, -4500, -2111, 2341, -1690, -4286, -4940, -3112, 2706, -2705, -12776, -2372, -5202, 2177, -4738, -6615, -2807, -4327, 689, -9695, -4295, -5247, -2340, -1011, -6528, -3460, -2610, -1849, -776, -3592, -3482, -1296, -2954, -621, -3225, -4718, -2172, -7335, -1218, -4486, -7644, -6411, -7603, -1245, -5360, -7542, -5576, -4858, -559, -5214, -5630, -3112, -6288, -321, -5202, -4587, -3417, -11945, -932, -4564, -4097, -5286, -6973, -2536, -4307, -4315, -6856, -6692, -5097, -5097, -5240, -5273, -8982, -5353, -7445, -5735, -2914, -10704, -3597, -28777, -4408, -2203, -6885, -2507, -10526, -3301, -3951, -4199, -2107, -9284, -3291, -8034, -2779, -2259, -6928, -4923, -2902, -2630, -2743, -5465, -10899, -2016, -3860, -3331, -5429, -7097, -3391, -6457, -4056, -5346, -5494, -8220, -7842, -4991, -4616, -5422, -6870, -9022, -5253, -5020, -4774, -3920, -17034, -3910, -6602, -3927, -2772, -9022, -2550, -5079, -3441, -2510, -7281, -1973, -3665, -3563, -3140, -6528, -2169, -4028, -3748, -4764, -6553, -2960, -6278, -2954, -6469, -8304, -3717, -7730, -2132, -6103, -14784, -3433, -5678, -2176, -5924, -11004, -2855, -5109, -3339, -6411, -9284, -3042, -5960, -6103, -7019, -9238, -4134, -9106, -14784, -8009, -10362, -5145, -9429, -9873, -10210, -12776, -4853, -5260, -7389, -7842, -9585, -4774, -3644, -6278, -4874, -6870, -5906, -3438, -5576, -3380, -5509, -9238, -4438, -4733, -2918, -5584, -7247, -5979, -3843, -3347, -7464, -4361, -5793, -3266, -4625, -10001, -3638, -5091, 1053, 8110, 8914, 8307, 6042, 624, 7849, 8377, 7697, 6023, 614, 6830, 6761, 5694, 5584, 1187, 4282, 4227, 1468, 3982, 547, -3409, 2171, -3076, 110, -1225, 2598, 2072, -3543, 1042, -665, 4111, 1684, -506, 2658, -964, 3751, -446, 2235, 1984, -7146, 2103, -7936, 2601, -337, 2168, 462, -1580, 2579, 1717, 5343, 1916, 1908, 4177, 4251, 6921, 4386, 3752, 5080, 5244, 7424, 5647, 4202, 4292, 4783, 6883, 5311, 2971, 305, 2614, 5111, 2609, -777, -620, 3635, 1736, -4464, 1146, 2544, 5977, -629, 2458, 2514, 1870, 6709, -634, 3097, 1606, -2359, 6413, -2823, 2131, -1302, -3342, 5643, -7623, 316, -6773, -908, 4793, -5487, -2306, -13049, -1451, 3640, -3151, -4555, -9695, -3574, 1736, -2908, -5234, -6388, -5592, -904, -4759, -9238, -3996, -3723, -2510, -17034, -4274, -2615, -2599, -1828, -5394, -2601, -1887, -1611, -2331, -2945, -3496, -1453, -538, -7752, -2242, -4464, -1450, 44, -1051, -2606, -2166, -1784, 49, 1245, -3773, -1528, -2204, -388, 1328, -4429, -2473, -3158, -1272, -587, -3686, -3594, -5085, -2728, -7081, -2881, -4123, -7408, -5202, -3215, -2132, -5339, -11629, -8982, -1488, -1471, -5031, -4940, -4299, -1189, -1473, -4923, -1805, -1452, -797, -2510, -4010, -677, -91, -222, -4545, -2633, -1019, 204, -349, -6666, -3563, -2386, -385, -1899, -6183, -11356, -1821, -1716, -3036, -4620, -3710, -342, -3817, -531, -4149, -2615, -216, -4386, 781, -4013, -4518, -1874, -2895, 948, -3194, -4010, -6590, -2019, 322, -2008, -1979, -4344, -670, -624, -1414, -2191, -2979, 628, -990, -1710, -4597, -4071, 1114, -976, -3110, -8982, -8754, 807, -1502, -7665, -6914, -7984, -33, -2829, -6045, -7179, -5170, -977, -4620, -2677, -7299, -4336, -1666, -5743, -2254, -6183, -3319, -2350, -5615, -3647, -5853, -2339, -3933, -5539, -7130, -5158, -2069, -8423, -5546, -8903, -4438, -2690, -10069, -4640, -7644, -4403, -4149, -7865, -3586, -7213, -4784, -5494, -12319, -2897, -5686, -4940, -4985, -8485, -2608, -4108, -4847, -4130, -5247, -3027, -3239, -5133, -3940, -4064, -4935, -2950, -6553, -4532, -3683, -10526, -2933, -10613, -5951, -3927, -5735, -3038, -11945, -8333, -5037, -3930, -3433, -7730, -11232, -7146, -3647, -4473, -6016, -13049, -6719, -3629, -6083, -5451, -14195, -4940, -3299, -7960, -6083, -13365, -4331, -3172, -10526, -8304, -17034, -4733, -3843, -15615, -10069, -9695, -6113, -5584, -15615, -9149, -6492, -8220, -7230, -12319, -11004, -5195, -7960, -6123, -6719, -17034, -4759, -6615, -4907, -5043, -9193, -4523, -6376, -3748, -5584, -7644, -4523, -7081, -2651, -7484, -6113, -4698, -8192, -2111, -6640, -4438, -5195, -8363, -2429, -5145, -3795, -6914, -7842, -3843, -4067, -4408, -13049, -7936, -6469, -3840, -5988, -5638, -8718, -8718, -4940, -7708, -3201, -9812, -7936, -7960, -4748, -6653, -4769, -7050, -7603, -6332, -6615, -4513, -7019, -5942, -7299, -6388, -4869, -7774, -4805, -6225, -5879, -5710, -6828, -5429, -5654, -6388, -6590, -4460, -11356, -5879, -8582, -7113, -3680, -5710, -6842, -7960, -7796, -4157, -3375, -7819, -6469, -8333, -5253, -3296, -7445, -6928, -7774, -6528, -4620, -6870, -8247, -6640, -7708, -7445, -6528, -8754, -6153, -8247, -14784, -5844, -9812, -6602, -8009, -11629, -5415, -9753, -8333, -7603, -9193, -5306, -7464, -17034, -7146, -8790, -5554, -5569, -8718, -6786, -7774, -7066, -4482, -5818, -5933, -5569, -8304, -3415, -6064, -4795, -3247, -4890, -1853, -13049, -3291, -1092, -1488, -282, -2670, -1180, 441, 194, 903, 44, 464, 1064, 369, 1400, 853, 1121, 561, -758, 998, 249, 726, -1463, -2859, -374, -1779, -805, -6988, -4679, -2714, -4863, -3757, -5401, -4923, -5784, -5367, -7335, -3383, -5055, -8942, -5374, -6343, -3744, -5951, -12534, -6045, -5638, -5524, -7050, -12534, -6365, -5960, -7730, -6914, -7484, -6516, -7842, -6973, -5879, -5654, -6602, -11488, -6026, -5509, -5085, -6173, -7353, -6602, -5933, -5312, -6045, -6235, -8649, -6422, -6113, -6814, -6928, -11004, -6083, -5888, -8276, -8615, -10284, -5073, -4659, -9380, -8582, -6745, -4238, -4442, -9753, -7865, -4733, -4153, -6083, -9238, -7644, -3954, -4800, -12776, -8582, -6628, -4071, -5686, -9064, -8192, -5079, -4728, -6074, -7464, -8982, -3937, -5189, -5810, -8393, -10613, -3512, -5026, -5509, -11004, -8549, -3954, -5109, -5394, -17034, -7113, -5654, -6434, -5061, -15615, -6666, -9479, -11004, -4438, -11488, -6288, -7353, -9753, -4064, -9695, -6422, -4918, -8485, -4373, -8454, -8060, -4089, -13049, -5408, -8165, -9022, -4226, -6988, -6376, -9331, -6422, -5465, -4482, -6885, -13738, -5623, -8485, -4246, -8276, -10799, -6666, -8718, -5646, -11629, -8423, -10613, -7281, -8363, -13738, -7960, -10899, -9149, -8112, -13365, -8304, -8582, -11945, -6653, -15615, -8138, -9193, -7034, -6235, -11356, -7464, -10069, -5726, -6800, -8615, -7389, -7796, -5743, -8423, -7264, -7774, -6310, -6516, -10442, -7179, -7264, -5776, -7687, -11232, -7819, -6343, -5686, -7445, -9064, -8138, -6123, -5827, -6422, -6870, -7912, -6256, -6278, -6278, -5988, -8165, -6590, -7097, -7004, -6343, -9380, -6745, -8615, -8304, -7562, -11781, -6480, -11115, -10526, -7503, -11356, -6376, -10069, -15615, -7050, -10210, -7353, -7819, -11781, -7960, -9639, -9753, -7162, -10799, -11356, -9380, -10799, -7936, -14784, -15615, -9380, -10284, -10069, -11356, -12776, -8903, -11945, -10210, -8192, -12123, -8903, -13738, -9639, -7130, -8192, -11004, -9380, -11629, -6928, -5853, -11488, -7888, -11356, -7389, -5115, -9193, -8138, -9238, -8790, -5678, -10001, -10362, -9531, -12123, -7230, -11115, -28777, -11356, -28777, -8683, -8903, -10284, -11488, -14784, -8683, -8615, -7960, -10362, -12776, -7984, -10362, -7179, -9380, -11781, -3117, -6870, -7644, -4630, -5247, -3659, -11232, -6016, -7146, -6422, -5561, -12319, -5026, -6457, -8754, -10362, -7130, -4679, -5103, -17034, -5801, -5158, -5346, -5176, -8903, -3801, -4674, -6914, -6842, -6692, -3668, -5195, -7819, -14195, -6719, -4874, -6133, -8112, -8304, -8112, -6288, -6602, -9331, -6054, -8423, -6354, -6093, -8034, -6267, -7774, -6814, -5286, -6899, -7113, -7708, -6842, -4847, -7213, -6045, -7583, -6422, -5103, -6842, -5726, -7066, -7213, -6640, -5437, -7034, -6870, -7708, -13365, -5145, -8790, -6914, -7162, -6928, -5531, -8790, -6153, -6814, -4929, -6054, -6615, -4880, -5055, -5554, -11004, -3296, -2813, -2438, -4230, -4082, -524, -733, -656, -1370, -833, 1182, 493, -67, -185, 223, 1807, 608, -783, -417, -86, 1336, -519, -3058, -2075, -1452, -316, -3094, -6988, -5694, -3417, -3130, -5871, -7603, -7936, -5189, -4963, -6516, -6388, -6885, -6705, -4698, -6299, -4918, -7562, -9812, -4616, -4649, -4348, -8649, -12776, -4518, -4060, -5333, -9695, -10210, -4258, -4344, -9149, -10210, -11945, -4195, -4679, -7796, -9284, -8165, -4912, -4460, -5152, -8009, -5546, -7371, -4035, -4869, -6943, -4532, -12319, -3989, -6074, -6516, -4282, -6343, -4601, -6469, -6786, -4504, -4635, -5759, -4611, -7583, -5133, -4464, -6615, -3751, -8790, -6602, -4790, -6332, -4184, -10899, -10704, -4997, -6365, -6103, -13738, -10799, -6388, -7936, -11488, -12319, -6640, -17034, -13365, -10069, -9812, -5306, -6856, -11004, -7034, -7426, -5008, -4963, -9064, -5646, -5997, -5286, -5465, -6828, -4451, -5710, -6035, -8683, -4754, -3509, -6553, -7389, -11356, -4064, -3194, -8034, -10704, -6842, -4774, -3680, -7162, -13738, -5702, -7213, -5085, -5266, -8034, -5458, -11356, -7371, -4290, -6528, -5444, -11945, -10210, -4258, -6123, -5569, -28777, -9331, -5170, -5836, -6007, -9022, -6958, -6943, -5444, -7097, -6759, -5623, -8903, -5735, -9873, -6480, -5079, -9585, -7644, -10284, -6958, -5103, -9149, -14784, -7019, -6679, -5702, -8034, -9106, -5735, -5554, -6814, -7066, -7353, -5554, -4764, -7708, -6899, -7562, -6332, -4425, -7066, -7353, -8865, -7464, -4455, -6516, -8034, -10613, -6856, -4863, -7004, -8754, -10613, -5836, -5592, -8276, -10069, -8549, -5836, -6153, -9873, -13738, -6732, -6719, -6590, -11356, -12123, -5844, -7603, -7162, -13365, -8165, -5997, -8247, -7752, -10799, -6885, -7389, -9284, -8009, -9106, -7113, -10362, -11488, -8333, -9284, -8718, -14195, -14784, -9380, -10799, -11115, -13365, -11232, -9585, -11781, -10799, -12776, -10284, -8582, -10362, -9331, -13365, -11004, -8333, -9106, -8903, -13365, -10284, -8333, -9193, -9331, -9585, -9380, -8333, -10001, -9936, -7730, -9429, -9238, -8942, -10069, -7523, -8649, -11004, -8247, -9331, -8754, -8454, -12776, -9380, -8220, -11629, -10799, -28777, -14784, -7583, -11356, -14784, -11488, -13049, -8086, -9531, -9022, -9380, -11356, -10899, -9064, -7562, -9873, -7081, -9429, -2805, -8718, -6899, -6800, -10899, -4226, -6653, -7179, -5718, -8827, -8517, -5401, -9193, -5638, -6480, -7034, -4518, -9531, -6133, -4946, -5306, -3804, -6246, -6732, -3830, -5759, -3444, -4527, -5933, -3014, -8192, -3485, -4344, -4138, -2827, -9238, -4056, -5387, -3203, -3523, -5915, -5480, -7162, -3352, -5152, -4282, -6565, -10442, -4649, -6958, -3316, -5437, -11232, -6943, -7665, -2574, -4592, -7081, -7213, -7445, -2163, -4395, -6492, -6376, -7113, -2312, -4460, -8276, -7583, -7146, -3191, -4578, -28777, -8790, -5801, -5183, -4559, -9193, -6885, -5127, -12776, -4545, -6516, -6828, -4769, -5292, -3920, -3900, -3447, -1899, -1621, -1802, -1198, -706, 111, 92, -225, 391, 418, 753, 503, 157, 682, 253, 191, -422, -702, -432, -1141, -1561, -3304, -2975, -3615, -3853, -4532, -7603, -6759, -10284, -7503, -7389, -4901, -7426, -4688, -12123, -7623, -5458, -6928, -3546, -10613, -7299, -9238, -8086, -3482, -7196, -6800, -9106, -11356, -4053, -6469, -6434, -7130, -11356, -5531, -7503, -7353, -7247, -7066, -7752, -11488, -11232, -8903, -5576, -7196, -9380, -11004, -9064, -6153, -6267, -7464, -9380, -5638, -9531, -6225, -8903, -11488, -3592, -10704, -6153, -28777, -9585, -2642, -10069, -5678, -8582, -7179, -2483, -12123, -5516, -8393, -6615, -2912, -6376, -5818, -11945, -7562, -3879, -4323, -6388, -8865, -10704, -4912, -3876, -6553, -7426, -8982, -4774, -4555, -6332, -8034, -6354, -4115, -6399, -6540, -7130, -5592, -4075, -10069, -7774, -5374, -6103, -4640, -10799, -10284, -4985, -7281, -5751, -7888, -12776, -5670, -8138, -7542, -7113, -11488, -5853, -7819, -9531, -7888, -11945, -5008, -7281, -9022, -8615, -28777, -4774, -7371, -7912, -7445, -11115, -5810, -8276, -7213, -6773, -7960, -8615, -10899, -7179, -6565, -6035, -15615, -10442, -8060, -6204, -4759, -15615, -7113, -9873, -6083, -4153, -9429, -6376, -10210, -6422, -4447, -7213, -7960, -10138, -6504, -6074, -6194, -10362, -11232, -5960, -10442, -5234, -6786, -9429, -5630, -12319, -4597, -5768, -7179, -5979, -10799, -4912, -6133, -6026, -7196, -12123, -6376, -6133, -5743, -9380, -8086, -8865, -5415, -6343, -11004, -5793, -9695, -5176, -7583, -10442, -4935, -8423, -5164, -8220, -9531, -5127, -8247, -5164, -7936, -8333, -6310, -9380, -5702, -8333, -6988, -8582, -10704, -6973, -8192, -5897, -12534, -9873, -8485, -7004, -5561, -28777, -8549, -9331, -6800, -6225, -12534, -7888, -10526, -8247, -7281, -11232, -7888, -14195, -11781, -7162, -17034, -8517, -28777, -10704, -6885, -10613, -10001, -17034, -8754, -7196, -8009, -11232, -11004, -8247, -7708, -8247, -8683, -8165, -8790, -7796, -8582, -7162, -7247, -8549, -7687, -6602, -6943, -7796, -7730, -7730, -5784, -7730, -9064, -7936, -8165, -6577, -9429, -8333, -9106, -9936, -9380, -11781, -7066, -10069, -11115, -14195, -11356, -6602, -9429, -7247, -8982, -9429, -6653, -8903, -5735, -7984, 10044, 12648, 12998, 9252, 6231, 9325, 12187, 12390, 8700, 5681, 6793, 10765, 10421, 7132, 3998, -1825, 8281, 6402, 5122, 1148, 3219, 4758, 1900, 3557, -2152, 4456, 1711, 3145, 2012, -3412, 3991, 1942, 1400, 204, -5079, 2605, 2961, -1604, -3856, -5020, 1397, 3208, -3417, -3557, -71, 1218, 2542, -2979, -39, 2241, -2135, 353, -2745, 1046, 3469, -1404, -6856, -1711, 2768, 4068, 1609, 1799, -53, 4306, 4109, 1189, 4070, -76, 4861, 3454, 671, 4427, -2467, 4441, 2259, 1918, 3028, -3788, 3064, 2550, 1989, -1738, -1385, 411, 3822, 681, -1108, -1853, -4693, 4093, -654, 1442, -5979, -2592, 3171, -213, 1945, -4064, -520, 1371, 312, 1726, -2731, 491, -451, 514, 673, -4172, 1095, -4067, 545, -219, -3140, 1267, -3468, 233, 1160, -1015, 1002, -20, -487, 2224, -2, 267, 293, -1090, 2237, 417, -1484, -1315, -949, 1348, 442, -6399, -5152, -560, -150, 79, -6399, -4038, -1063, -1862, -811, -3961, -1042, -3078, -3600, -2512, -4491, 588, -1589, -6153, -4420, -6528, 1425, 177, -5374, -5133, -10284, 1468, -12, -1979, -4847, -6480, 442, -2155, -888, -3274, -3468, -2145, -4403, -1535, -3281, -1610, -2664, -1884, -3529, -7004, -258, -546, -685, -5539, -6235, 641, 7, -525, -6856, -3087, 948, -599, -815, -3659, -3047, 583, -2345, -1077, -2153, -5145, -396, -6235, -1402, -2756, -7162, -1909, -5979, -2105, -3910, -4583, -3996, -3094, -2743, -1780, -4957, -5085, -2401, -2268, -343, -15615, -4616, -2809, -1703, -181, -4509, -5380, -3105, -1949, -1173, -2628, -6235, -2039, -3087, -3465, -2982, -5509, -391, -4491, -8060, -4035, -5827, 967, -4918, -9331, -3944, -7796, 1574, -4774, -3798, -3540, -9429, 1143, -5394, -1564, -3490, -6064, -731, -7752, -671, -3748, -3551, -3738, -5437, -746, -3889, -2417, -1854, -2714, -1722, -3521, -2465, -738, -1511, -3910, -2918, -3286, -1072, -1174, -8060, -2807, -4382, -2477, -1487, -7464, -3817, -6016, -4826, -2521, -5726, -6679, -8034, -7542, -4395, -5539, -10526, -12319, -6828, -5979, -6256, -6480, -6123, -4918, -5584, -5862, -3933, -2470, -4038, -4816, -4071, -2659, -1201, -4303, -4592, -2883, -2589, -1456, -5793, -6035, -2460, -4028, -3042, -7984, -11781, -2988, -7230, -5751, -8138, -4491, -5227, -5043, -7865, -7523, -2336, -6590, -3916, -6553, -7426, -1857, -3170, -5299, -5031, -7230, -2367, -1790, -10362, -4985, -6054, -3674, -1497, -7583, -6204, -4935, -6256, -1909, -7162, -5751, -4733, -6225, -2686, -10001, -4097, -5646, -3695, -2793, -28777, -3757, -8649, -2722, -1804, -11232, -4800, -7984, -2733, -812, -9695, -4464, -4357, -3196, -222, -9936, -3005, -3025, -3399, -19, -6719, -3529, -2975, -3094, -215, -4831, -8060, -3659, -3218, -1018, -4541, -4097, -3975, -3947, -2937, -4491, -1958, -3487, -4134, 7316, 10225, 10623, 7748, -1098, 6444, 9621, 10019, 6996, 330, 3271, 7799, 8140, 4473, -135, 1316, 4928, 4844, -755, -2958, 3602, 1795, 905, -1315, -4578, 3296, -1449, -120, -2182, -543, 2161, -5133, 69, -4108, 879, 2607, -1265, -838, -5164, 1283, 3323, 2438, -72, -4365, 1191, 3383, 3844, 822, -5299, 1048, 2823, 4299, -288, -2566, 1369, 1264, 4253, -757, -248, 1858, -2958, 3479, 1529, -219, 1962, -613, 1344, 2185, -1117, 1743, 2218, -4821, 1460, -1255, 1702, 3058, -2541, 806, -793, 2155, 2695, -548, 1142, 382, 2651, 1144, -873, 1061, 1030, 2641, -1772, -2039, 567, 433, 1850, -1000, -2305, 388, -1616, 94, 759, -1155, 220, -5524, -2779, 1119, -359, -388, -10899, -3128, 900, -437, -1029, -9149, -1604, 812, -1352, -970, -4518, -1346, 688, -3425, -397, -1838, -1963, 276, -4455, 54, -450, -2752, -201, -922, 230, -180, -3003, -514, 990, 258, -1194, -2776, -737, 1673, -29, -3391, -3191, -772, 1287, -1143, -2430, -5487, -663, -184, -3641, -919, -10704, -869, -2573, -9695, -833, -5286, -739, -4790, -5662, -1888, -3846, 539, -5654, -2054, -3289, -4486, 1249, -8009, -517, -4003, -6640, 580, -10442, -43, -6183, -2065, -2142, -4805, 189, -6194, -122, -14195, -3130, 952, -2241, -240, -3769, -2325, 2173, -986, -2333, -2605, -1918, 3172, -964, -2885, -3222, -2003, 3383, -1800, -835, -3850, -2724, 2442, -3811, -587, -2578, -3824, -47, -4564, -2234, -1983, -3083, -1844, -2789, -8276, -2234, -1771, -329, -2622, -4606, -2673, -1662, -251, -4112, -2457, -3860, -3425, -1346, -7371, -2355, -6083, -7196, -2443, -11781, -3168, -4929, -2754, -1961, -9331, -3760, -4238, -1298, -1088, -6083, -3130, -5299, -1543, -916, -4344, -2309, -6457, -2969, -1777, -3951, -2170, -5145, -5394, -3850, -4348, -2918, -3509, -9695, -6016, -4991, -4784, -2406, -9022, -5451, -6602, -8138, -1928, -5480, -5387, -6235, -10362, -1952, -4592, -6278, -2902, -7523, -2291, -5599, -5960, -1404, -4907, -2952, -6480, -5121, -990, -3817, -4327, -4968, -5286, -1119, -4254, -7687, -4957, -6457, -1582, -5055, -12123, -7371, -8086, -2442, -4067, -6973, -15615, -8423, -3707, -3422, -5871, -8304, -7050, -5183, -3773, -5516, -5437, -6267, -7888, -4573, -5451, -3518, -7179, -9585, -4837, -5408, -2683, -9380, -3714, -4545, -5844, -2918, -5599, -1799, -4779, -8649, -3846, -3863, -1524, -6225, -8165, -3985, -3600, -2374, -8718, -4541, -3449, -4021, -3447, -9149, -3344, -3635, -4630, -3937, -9639, -3329, -4564, -5818, -4795, -7162, -4089, -4616, -6469, -5776, -4067, -5221, -3886, -4378, -4028, -2320, -5897, -4134, -3110, -2399, -1634, -5801, -5662, -2855, -1746, -2036, -5458, -9531, -2724, -1821, -3624, -4003, -7113, -1902, -2417, -5615, -2626, -3698, -1022, -3235, 2765, 10743, 11015, 7835, 5167, 2573, 10288, 10453, 7230, 4978, 1899, 8926, 8676, 5477, 4404, 431, 6717, 5342, 2971, 3601, -2510, 4089, 826, -759, 2738, -1116, 2331, 280, -2247, 1585, 1335, 1862, -849, 2278, 958, 2037, 1137, -1499, 3142, 1914, 2121, -359, -1606, 2056, 2766, 2493, -1087, -3067, -531, 3083, 2981, -162, -2845, 1494, 2837, 3208, 1678, 256, 2898, 1355, 2995, 3017, 1510, 2431, -5353, 2078, 3266, 983, 412, 1537, 495, 2329, -2220, -1382, 4611, 45, 753, -3692, -1259, 6111, 41, 850, -150, -1056, 6663, -1833, 1379, 313, -442, 6245, -1875, 1210, -688, -234, 4738, 1059, 939, -2566, -954, 2413, 2204, 1007, -4013, -2999, 1451, 2071, 1366, -3296, -7984, 1487, 869, 1630, -1712, -3840, 921, -915, 1398, -1065, -1305, -226, -2019, 816, -2412, -412, -1913, -2990, 328, -8865, -255, -3626, -5214, -124, -1636, -262, -8009, -10138, -168, 335, -17, -4482, -14784, 497, 609, 795, -1324, -17034, 752, -8, 1509, -1330, -7583, 127, -1352, 1536, -3714, -3417, -922, -4438, 861, -2962, -956, -1306, -9695, -311, -1326, 369, -1134, -4601, -2112, -830, 420, -911, -6376, -5164, -172, -1578, -598, -4880, -1971, 136, -5286, -43, -182, 497, -448, -712, 141, 1578, 1353, -1463, -152, -869, 1793, 1056, -1937, -2879, -3883, 367, -338, -2367, -7353, -7230, -3760, -2299, -3354, -2711, -7644, -1205, -1284, -5008, -3989, -10210, 633, 187, -4754, -7335, -4127, 682, 458, -2353, -3213, -2992, -90, -576, -1166, -1239, -3876, -1210, -2589, -1417, 41, -6577, -3225, -1869, -3316, 408, -13365, -7353, -451, -3827, -439, -9238, -4060, 7, -1758, -2403, -5844, -2334, -20, -1021, -2962, -4555, -2334, -169, -989, -2364, -4046, -3504, -466, -932, -3279, -3856, -5735, -1293, -626, -6565, -4161, -12534, -3003, -228, -8649, -4386, -7066, -3961, 29, -5592, -4071, -4536, -2517, -22, -4327, -4258, -4885, -1637, -541, -3723, -5097, -5494, -1446, -1642, -3689, -5678, -3083, -1635, -3085, -4115, -6064, -1838, -2204, -3523, -4100, -7371, -1822, -2881, -3096, -3833, -11004, -2730, -2391, -2975, -4250, -11115, -4578, -1473, -3105, -5784, -8982, -8060, -1479, -2754, -8138, -9284, -10899, -2883, -2100, -8754, -4425, -7583, -5097, -2042, -6870, -2015, -5121, -3005, -2716, -3999, -1423, -3546, -1384, -3054, -2741, -2403, -3342, -965, -2557, -3194, -4880, -5253, -1343, -2505, -4606, -4733, -11629, -2238, -3184, -4307, -3326, -5139, -3401, -4395, -3393, -2979, -4038, -4601, -6163, -1689, -2849, -4784, -5818, -7335, -26, -2541, -5776, -6577, -5260, 622, -2262, -6278, -6173, -4270, 176, -2344, -8485, -4395, -5164, -1242, -3154, -9064, -2849, -8034, -3225, -4912, -4940, -2698, -8034, -4611, -5646, -3286, -5240, -7665, -2419, -6615, -3482, -1846, -3281, -626, -3304, -2130, -2175, -3569, -105, -1262, -1182, -2008, -3566, -743, -1087, -1198, -1819, -3225, -2300, -2635, -2576, -1603, -3257, -4060, -7146, -3626, -1013, -4438, -5437, -7936, -2214, -312, -9238, -7708, -5997, -2372, -132, -4957, -6666, -6958, -5862, -837, -2285, -3566, -10613, -5049, -2419, -1986, -1772, -13365, -1771, -3680, -3837, -688, -7752, -1085, -3624, -5906, -101, -5844, -1654, -3683, -2975, -80, -5067, -3108, -4336, -2094, -818, -3653, -4071, -4399, -2458, -2770, -2002, -2608, -3158, -3163, -8423, -1108, -1685, -2458, -3751, -6204, -1100, -2282, -2364, -4010, -3210, -1825, -4769, -1646, -3237, -2445, -2762, -5240, -595, -1689, -2711, -3840, -3751, -258, -376, -3744, -6745, -4738, -699, 97, -5367, -9812, -10613, -1406, -557, -6256, -3866, -7796, -1864, -2613, -5008, -1892, -6528, -2502, -5915, -3961, -1087, -9585, -4365, -5387, -3766, -939, -8549, -9753, -3092, -4323, -1217, -6153, -8827, -1828, -5444, -1731, -6246, -7984, -1501, -6745, -2312, -6492, -7230, -1312, -7335, -2475, -4923, -5374, -1098, -7081, -1852, -3586, -4395, -1695, -7842, -1203, -3354, -3992, -3412, -9873, -1341, -4654, -5026, -4382, -8982, -2635, -8649, -8247, -4403, -9022, -4907, -10799, -5801, -6434, -11004, -4858, -9284, -4644, -13049, -8086, -3537, -8060, -5623, -10526, -6469, -3049, -6173, -8683, -28777, -5607, -3119, -4968, -28777, -9753, -5273, -3900, -4161, -13049, -8276, -5437, -6540, -3833, -11232, -5214, -4831, -10526, -3760, -8517, -2564, -4592, -6814, -3386, -5818, -1433, -6528, -7317, -2829, -4082, -1436, -14784, -11945, -2726, -3085, -2257, -8582, -11488, -3365, -2514, -3656, -10799, -11629, -4482, -2470, -4985, -8333, -28777, -4611, -3554, -4597, -5319, -12319, -4361, -7730, -3785, -4858, -13738, -5026, -6773, -4104, -5408, -8942, -5784, -3362, -6615, -5768, -6214, -5451, -2619, -12534, -6026, -5221, -5127, -3054, -5415, -7130, -4951, -5319, -3954, -3927, -8220, -4940, -6590, -3920, -4246, -7936, -5333, -8549, -2853, -6759, -7888, -7213, -6553, -2364, -12319, -5801, -28777, -4863, -3415, -5576, -3668, -6759, -3641, -8517, -3741, -2813, -4764, -2541, -5615, -2982, -3177, -4518, -1999, -2945, -2505, -4918, -4963, -2257, -2580, -2165, -9429, -5158, -3309, -3096, -2128, -11488, -5020, -4929, -3529, -2610, -7960, -5189, -5615, -3927, -3827, -8517, -6204, -4460, -4718, -5678, -13365, -8827, -3455, -5623, -7389, -11945, -13738, -3135, -6388, -9429, -9753, -9479, -3319, -7644, -7503, -10138, -7752, -3583, -10442, -4723, -11945, -7562, -3635, -28777, -3735, -17034, -8517, -3804, -9585, -3906, -12319, -9639, -4282, -7247, -4640, -9531, -9022, -4042, -5942, -5437, -8363, -8582, -3038, -4912, -6492, -7774, -7774, -2550, -4207, -8060, -7335, -7019, -2895, -4024, -10362, -7603, -7936, -4172, -4532, -14195, -9812, -13365, -6786, -6153, -9380, -6365, -2564, -2516, -966, -3968, -5607, -4513, -2347, -2244, -4991, -3339, -8304, -2545, -4968, -7317, -2173, -4764, -3215, -5097, -14784, -2146, -4278, -5037, -4323, -9812, -2937, -6054, -9479, -3662, -8903, -4408, -4728, -9936, -2453, -8827, -7034, -2265, -7426, -2132, -5429, -4929, -1286, -6422, -3182, -3776, -2223, -1296, -5888, -5502, -3196, -1202, -1811, -5793, -6256, -2943, -1328, -2093, -6480, -6133, -2835, -2396, -2184, -7162, -8754, -2781, -4199, -3110, -4028, -12123, -2592, -5638, -5630, -1975, -6759, -2487, -4837, -4847, -1230, -5487, -2758, -3999, -2492, -1394, -4138, -3523, -4718, -1697, -2239, -2191, -4935, -10138, -2014, -3671, -654, -8112, -5951, -3362, -6074, 198, -10284, -3029, -5531, -11629, 268, -4164, -2677, -5743, -12319, -477, -2062, -4038, -4640, -8333, -1868, -1537, -4963, -4060, -6422, -3038, -2447, -3910, -3110, -5240, -2929, -5164, -4550, -2166, -3957, -2080, -7819, -8649, -2393, -3112, -1543, -4907, -7004, -4748, -3357, -1671, -2475, -4649, -12776, -5079, -2528, -1033, -4278, -4123, -8942, -3893, -933, -4640, -2488, -5561, -3583, -2696, -4805, -2419, -3087, -2260, -9639, -4344, -3094, -2082, -1644, -3624, -3923, -3018, -2107, -1825, -1752, -4046, -2219, -3201, -2922, -1724, -4821, -1952, -5584, -5726, -2803, -5871, -2374, -6679, -8138, -4718, -6183, -3114, -5286, -4795, -6773, -5158, -3580, -4759, -3337, -8304, -4242, -3420, -3222, -2967, -9873, -3468, -3083, -1514, -3916, -8942, -2737, -3196, -851, -7213, -7371, -2628, -4290, -1397, -8220, -5031, -3441, -6565, -3518, -8517, -2924, -5306, -7623, -9639, -7936, -2083, -6666, -7730, -7623, -4199, -2509, -3910, -10526, -5871, -3420, -3331, -2225, -5279, -6113, -4307, -3147, -2053, -2893, -7335, -5879, -3314, -3463, -2398, -8393, -6870, -4980, -7542, -3314, -5915, -7484, -8683, -11115, -5979, -4420, -10442, -15615, -7389, -12319, -4319, -9695, -10284, -6973, -5924, -5227, -5862, -5997, -7162, -3720, -6615, -5133, -4323, -6786, -3023, -7230, -5853, -4336, -5623, -3650, -7179, -7730, -5115, -4974, -5862, -7687, -13049, -4153, -5818, -5997, -8247, -10210, -2795, -8754, -3618, -5836, -6928, -2115, -6332, -2590, -3686, -6343, -1878, -4246, -2450, -2675, -7371, -1699, -4067, -2889, -2369, -11004, -1353, -5678, -4017, -2450, -11781, -1020, -12123, -6745, -2751, -8247, -1076, -6615, -8165, -3114, -7426, -1890, -4056, -4616, -3412, -7960, -4046, -3571, -3707, -3883, -8485, -10069, -4754, -4386, -5079, -6786, -5662, -8423, -6732, -7865, -4957, -3373, -7281, -14195, -9753, -3906, -2778, -5152, -8982, -5784, -3501, -3058, -4748, -5853, -3961, -3641, -3707, -4429, -4616, -3227, -4086, -4274, -3487, -4587, -3154, -4559, -4918, -2617, -5735, -3507, -4880, -6074, -2248, -8034, -4307, -5109, -7335, -2512, -9064, -5924, -5292, -8086, -3463, -8276, -8754, -5502, -7299, -5170, -8393, -9639, -6204, -5646, -5638, -4606, -2845, -6278, -11115, -8718, -5008, -3045, -1236, -9106, -4946, -4323, -2920, 372, -6540, -2630, -1996, -2108, 535, -6123, -2531, -1262, -1384, -353, -4842, -3879, -2378, -1149, -2111, -3078, -3910, -5561, -1536, -4319, -2291, -2204, -4134, -2692, -6288, -2541, -1237, -2711, -4199, -8649, -3375, -1152, -2827, -4142, -11004, -3729, -1662, -3744, -3720, -5176, -3523, -2288, -5599, -4286, -2929, -3856, -3194, -7960, -5988, -2138, -5387, -5710, -4963, -10362, -2385, -6492, -28777, -3114, -7299, -3850, -3624, -7146, -2550, -4644, -7583, -1693, -6800, -2875, -4097, -5286, -1039, -9064, -4064, -3615, -2458, -1752, -12319, -6679, -1793, -1298, -4336, -5888, -8165, -202, -1070, -6828, -3449, -5686, 616, -1634, -4664, -3074, -4821, 710, -2984, -5145, -4810, -4425, 164, -4664, -10899, -8192, -5014, -985, -3856, -6870, -4464, -8790, -2733, -2241, -4433, -2904, -8485, -4890, -1319, -4754, -2799, -5561, -6399, -1020, -7264, -3626, -5360, -7730, -1508, -9812, -4946, -6113, -9429, -3215, -8827, -5924, -7984, -5502, -6692, -9284, -6480, -12123, -3989, -5387, -8649, -6786, -8247, -4985, -3609, -6653, -7562, -6267, -9695, -3594, -4460, -9106, -5487, -4013, -5662, -3119, -5726, -5670, -2075, -11781, -2709, -2931, -7004, -1868, -4805, -2964, -1551, -6422, -2709, -2941, -3504, -1157, -4134, -4464, -2254, -4161, -1587, -3487, -7317, -2155, -4810, -2900, -4460, -8754, -2803, -4826, -5751, -6590, -7146, -3889, -4504, -28777, -7213, -5768, -3692, -5085, -5933, -5906, -4532, -3161, -6653, -3729, -3814, -3504, -3971, -7623, -2557, -2758, -2924, -7081, -8112, -1713, -3179, -2924, -6705, -8790, -1219, -4863, -3566, -3968, -9149, -1239, -4611, -5158, -3357, -9380, -1735, -3342, -9106, -4344, -7353, -2398, -3518, -9380, -6943, -5654, -3014, -5561, -6321, -6064, -4365, -3944, -12319, -5710, -4611, -3526, -5710, -8485, -5444, -5312, -3474, -8549, -7004, -4395, -10899, -4382, -14195, -5539, -3729, -6007, -6354, -14784, -3732, -4262, -2947, -6988, -12776, -3108, -6504, -2071, -4940, -7665, -3644, -11629, -2495, -3804, -4541, -4748, -8903, -4082, -3624, -2947, -5152, -7752, -6973, -3900, -2166, -4416, -7146, -10899, -4112, -1940, -3644, -6016, -8138, -4644, -2419, -3853, -5524, -5319, -6492, -3795, -5810, -5997, -4053, -8754, -5933, -13738, -7542, -3896, -6299, -6828, -6093, -10899, -4455, -5353, -5145, -3837, -17034, -5253, -5710, -3860, -3184, -9812, -6399, -6705, -3479, -2956, -7936, -8865, -7146, -3964, -2407, -7371, -14195, -5979, -5208, -2008, -7484, -10899, -5109, -7162, -2302, -7603, -8903, -5214, -10001, -3428, -6480, -8060, -5584, -11781, -5654, -5227, -7335, -5408, -15615, -7865, -4858, -6204, -5176, -8304, -5214, -5751, -5043, -5266, -4963, -3804, -8718, -4153, -5292, -3769, -3951, -8034, -3407, -4951, -3840, -5702, -5091, -2760, -4688, -4616, -10442, -4168, -2538, -5170, 2924, -234, 1360, 6807, -8942, 2066, -2370, 4384, 6357, -5810, -141, -2316, 6118, 5078, -3900, 1102, 864, 6272, 3574, -2939, 2871, 2029, 4982, 2947, -2191, 3429, 2929, 1313, 2390, -2148, 2957, 3148, -353, 643, -5437, 1123, 2033, 3041, -4403, -2204, -4885, -1104, 3754, -2053, 1954, -1183, -6719, 3043, 205, 3676, 1865, -4172, 491, -267, 4413, 2821, -3653, -7752, -1049, 4868, 2344, -1888, -199, 1694, 5207, -359, -9, 972, 3120, 5050, -1632, 595, 83, 3046, 3874, 1955, -1268, -1515, 1653, 578, 2733, -2034, -634, -75, -912, 1786, 2552, 214, 1121, 2255, -864, 3972, 473, 2128, 2530, -2273, 3661, 640, 1934, 1253, -825, 1861, 457, 1079, -446, 292, 123, -219, 514, -4874, 1881, 460, -1259, 630, 63, 3071, 42, -3388, 1278, 3589, 3387, -516, -9639, 1572, 4619, 2800, -265, -1659, 633, 4027, 1366, -817, 320, -2517, 1686, -799, -2762, 270, -7665, -3930, -3968, -4713, -1864, -3692, -3304, -8718, -6299, -8363, -1474, -2526, -3249, -5234, -3128, 612, -2094, -1855, -1449, -2152, 1371, -497, -3147, -19, -3518, 798, 62, -7562, -156, -7317, -391, -900, -2639, -1790, -4858, -388, -3518, -1365, -3726, -2659, -173, -2541, -1549, -2762, -1254, -1080, -837, -1402, -3177, -87, -3883, -672, -1136, -3546, 612, -14195, -1556, -2185, -1011, 683, -5189, -3092, -3299, -127, 255, -4810, -4674, -1074, -408, 469, -5158, -5810, -458, -152, 1380, -2644, -7730, -1654, -81, 1634, -864, -9193, -1208, -2163, 1154, -51, -2672, 674, -4991, 832, 155, -175, 1435, -1433, 1013, -131, 761, 1314, -1182, 998, -1065, 724, 444, -1811, 564, -3135, 65, -1033, -1320, -218, -5221, -1064, -2295, -1850, -1008, -2359, -3001, -2817, -4985, -1698, -306, -5472, -3717, -3147, -3766, 626, -2825, -5915, -875, -8517, 689, -1373, -9695, -643, -1522, 110, -1799, -10284, -1952, 328, -645, -4550, -8393, -5158, 462, -1073, -10704, -4880, -6958, -523, -1486, -3526, -2364, -4800, -1611, -3433, -1904, -806, -4017, -1034, -5607, -2280, -95, -3671, 811, -744, -5607, -347, -3247, 2261, 644, -6480, -1863, -3210, 2734, 110, -1799, -5103, -4810, 2098, -2285, 184, -4659, -28777, 205, -6692, 1041, -2109, -4049, -3264, -9531, 934, -473, -1838, -10704, -5037, -22, 605, -915, -4630, -2875, -1556, 1152, -403, -688, -2859, -2705, 1070, -564, 939, -4733, -2610, 57, -1773, 1155, -6814, -2105, -2377, -3521, 70, -4006, -1277, -6842, -3920, -2624, -2128, -785, -7230, -2054, -4800, -1131, -268, -5480, 427, -2743, -550, 863, -1591, 1982, -1959, -690, 1399, 994, 2627, -2102, -2931, 751, 2205, 2455, -2624, -3235, -981, 2081, 1425, -2661, 732, -2168, 111, -357, -1579, 1804, -2049, 4113, 8691, 7936, 8773, 6012, 3561, 8072, 7149, 8102, 5618, 2114, 6090, 4494, 5874, 4286, 385, 2467, -1467, 1335, 1442, 105, 335, -1512, 891, -3557, 1448, 19, -294, 1187, -653, 1670, 457, 2284, -59, 86, -162, 3511, 3895, 1882, -446, -6310, 5241, 4882, 3950, -804, -1085, 5595, 5534, 4332, 72, 356, 4540, 5713, 2430, 2068, -210, 2264, 5244, -849, 3407, -2129, 3099, 3913, 3563, 3660, -2831, 4469, 1707, 4593, 2972, -179, 4352, 1895, 3800, 1685, 2669, 2937, 3096, 1376, 261, 4384, 420, 2850, -1704, -616, 4854, -2821, 1300, 224, 367, 4011, -3808, -1286, 1808, 2210, 2310, -734, -2758, 2566, 3511, 3004, 259, 414, 3084, 3724, 3945, -255, 2119, 3767, 2385, 3371, -1544, 2519, 4192, -706, 1226, -2429, 2071, 3811, 1582, 282, -1773, 1347, 2525, 3374, 1664, 379, 898, 1309, 3933, 1804, 2168, 288, 1062, 3877, 646, 3217, -1270, 233, 3216, -1975, 3667, -4164, -1948, 1802, -2098, 3631, -8333, -6113, 150, 474, 3106, -8790, -8220, -278, 1453, 1924, -3837, -2977, -114, 1011, 19, -2664, -1399, 94, -1305, -645, -4176, -949, 577, -9064, 109, -5988, -689, 1392, -3321, -468, -1586, -771, 2221, -2843, -2881, 62, -2235, 2652, -4847, -3319, 490, -8304, 2491, -3296, -2752, 628, -4119, 1624, -1343, -3792, 1106, -1913, -182, -769, -3468, 1773, -1367, -3732, -871, -2650, 2176, -909, -5394, -1065, -2475, 2162, -896, -2016, -1130, -4299, 1644, -2359, -556, -1455, -6422, 532, -5037, -201, -2679, -824, 28, -2585, -882, -4451, 369, 777, -1683, -2733, -3365, -473, 747, -3401, -5387, -1928, -1848, -261, -6692, -6365, -1282, -987, -1277, -1773, -4270, -1254, -573, -2485, -30, -2253, -1887, -1288, -5897, 664, -1411, -4299, -3025, -8718, 914, -1321, -6528, -4620, -6973, 688, -1803, -1524, -3971, -5121, -178, -4003, -500, -3689, -2490, -1697, -8112, -1699, -3574, -1091, -3811, -2169, -4250, -3142, -530, -6928, -593, -4357, -3040, -547, -7842, -284, -8138, -3349, -1001, -5195, -504, -3089, -3996, -1679, -4620, -1564, 149, -5561, -2452, -6064, -5333, 1287, -5960, -3624, -12534, -6640, 1418, -2448, -5915, -6133, -2910, 947, -686, -5979, -2606, -2756, -117, -344, -3409, -751, -4266, -2165, -1087, -2391, 30, -7960, -4119, -1837, -1825, -57, -11356, -3225, -1303, -1099, -336, -8549, -3779, -1152, -668, -39, -9022, -8517, -2114, -534, 504, -3420, -7484, -3543, -1040, 1034, -1859, -5415, -3301, -3321, 1024, -2789, -4985, -1226, -3566, -591, -7281, -2912, 223, -1232, -11781, -3479, -1176, 639, -825, -757, -1218, -333, 583, -482, 1616, -476, -729, 900, 508, 2382, -451, -3326, 1327, 1147, 2418, -949, -4473, 1318, 1271, 1921, -2132, 6050, 7975, 8032, 3262, 3201, 5282, 7235, 7407, 4445, 2276, 2882, 4845, 5384, 5737, 1543, -1581, 449, 1204, 6321, 2762, -4365, -1218, -3344, 6202, 1952, 697, 1027, -807, 4913, -3001, 1699, 2207, -634, 394, 156, 1344, 1875, -264, 1794, -994, 1845, 390, 450, 4710, 1510, 2609, -843, -70, 5194, 4848, 2799, 63, -4254, 4680, 5567, 2411, 370, -2308, 3521, 5001, 1114, -894, 1299, 1143, 4606, -326, -3257, 2247, -1267, 4612, 1278, -6666, 1843, 1748, 4153, 2514, -7819, 240, 2820, 3522, 2479, -2283, -3457, 2246, 3871, 1252, 316, -4963, -251, 4898, -861, 2145, -449, -4184, 5257, -1712, 3381, 1314, 194, 4585, -2030, 4337, 2095, 1821, 3929, -4491, 5204, 2646, 2246, 5191, -8220, 5754, 3360, 2008, 6461, -3023, 5697, 3878, 1433, 6915, -40, 4936, 3757, 724, 6530, 1680, 3604, 2780, -300, 5228, 2082, 1923, 676, -2526, 2835, 897, -653, -3668, -5103, -394, -2621, -5853, -5176, -921, -537, -1319, -3142, -1849, 1016, 1414, 647, -2320, -801, 1527, 2562, 925, -3433, -294, 822, 2712, 282, -4842, 242, -1181, 1703, -850, -2309, 769, -1463, -1062, -781, -1052, 1003, 651, -1707, 543, -2061, 541, 1790, 194, 1207, -2345, -1065, 2238, -233, 958, 605, -1566, 2360, -3110, -13, 1942, 931, 2335, -4238, -883, 2114, 2319, 2134, -1013, -851, 1496, 2564, 1534, 32, -915, 278, 1735, 223, -847, -1878, -919, -350, -1991, -4403, -3606, -914, -2020, -3996, -3729, -3729, -993, -544, -4340, -3279, -2585, -2173, -113, -5266, -7774, -2133, -2378, -1091, -6113, -3526, -2512, -1154, -2937, -5458, -1749, -3840, -1378, -2273, -4929, -1987, -5646, -3798, -779, -5286, -2500, -4223, -4698, -480, -5979, -1443, -1889, -2670, -1206, -3674, -34, -395, -3515, -2195, -1741, 739, 45, -10613, -2889, -1006, 747, -929, -6163, -4176, -1250, -63, -3677, -7353, -4800, -1811, -1627, -2330, -4378, -2793, -1310, -2519, -720, -535, -1182, -200, -1823, -1173, 333, -240, 992, -1736, -3930, -823, 254, 1875, -2877, -14195, -4327, 429, 1936, -5827, -6504, -7523, 100, 813, -9531, -2797, -14784, -1054, -2146, -3889, -581, -4420, -3133, -14195, -1062, 378, -1799, -3269, -5465, 192, 678, -927, -1330, -3866, -7, 821, -670, 64, -2156, -1573, 914, -1065, 811, -1184, -1349, 635, -1633, 984, -1702, 282, -463, -217, 855, -4344, 555, -2393, 1105, 618, -4805, -601, -3294, 1347, -242, -3110, -3362, -1070, 658, -2683, -4420, -8615, 1182, -686, -3766, -8086, -7708, 2334, -1922, -1963, -3096, -3438, 2464, -2055, -2703, -1314, -1462, 1785, -1641, -7865, -740, -628, 493, -1010, -5702, -958, -332, -1390, -484, -3337, -2440, -311, -4017, -811, -2766, -4013, -576, -2857, -601, -209, 1245, -2673, 1298, 661, 654, 252, -3543, 2971, 1013, 516, 721, -1936, 3338, 131, -1375, 1236, 68, 3018, -2696, -3785, 1177, 1327, 2426, -9479, 78, 947, 1651, 1838, -2398, 1391, 788, 1071, 1239, -1269, 853, 440, 207, 422, -2348, -1860, -494, -280, -847, -6943, -6679, -1943, -1402, -2452, -3386, -2319, -2529, -4097, -2941, -1127, -1404, -1853, -3172, -1189, -1047, -1489, -1293, -1244, 742, -1659, -1798, -999, -860, 1749, -437, -1694, -812, -1739, 1622, 713, -542, -1050, -4649, 172, 485, 468, -2975, -4469, -2941, -1694, 432, -6943, -1207, -3695, -9064, -1197, -156, -526, -2305, -1646, -6842, 2017, -2334, -1990, 112, -4635, 2738, -3665, -1633, -169, -2789, 2674, 337, -998, -2152, -2605, 2265, 1508, -769, -989, -1740, 1727, 820, -1605, 824, -1331, 879, -2153, -4486, 998, -2066, -701, -5726, -7984, 154, -2473, -3347, -1741, -3680, -452, -1129, -5988, -295, -2648, 89, -513, -7912, 518, -2935, 827, -1335, -6973, 1122, -3586, 1136, -4013, -3137, 1470, -3014, 998, -3760, -1580, 1242, -1921, 720, -1046, -2050, 383, -1482, 581, -225, -6828, -213, -2076, 381, -1055, -3856, -468, -4669, -379, -4119, -941, -1887, -8086, -1652, -10001, -525, -5319, -2455, -1481, -5686, -1408, -8865, -498, -429, -4764, -3586, -6988, 264, -220, -4340, -10899, -2564, -67, -1095, -4790, -4145, -1311, -2416, -2619, -7752, -1577, -1593, -10442, -2425, -6814, -1118, -1611, -2668, -1617, -2906, -1637, -1051, -2626, -1753, -1652, -1893, -945, -4769, -2670, -1755, -2032, -746, -1679, -4130, -2514, -1775, 111, -362, -5871, -2797, -574, 893, -1074, -6800, -2849, -138, 908, -3609, -5531, -4003, -1267, -211, -3094, -3923, -7542, -5208, -2813, -1256, -3373, -15615, -4963, -6692, -761, -4184, -9479, -2522, -8517, -1169, -5979, -6856, -2100, -11232, -2406, -6870, -5458, -1852, -8942, -4112, -5924, -4089, -900, -7146, -3294, -5002, -1823, 169, -4784, -1973, -5638, -466, 480, -2480, -2023, -9753, -169, -562, -1384, -3373, -7819, -484, -3529, -1255, -4242, -5793, -726, -2587, -1207, -3507, -5960, -532, -732, -1140, -3689, -5531, -269, -583, -1970, -4805, -4896, -342, -1430, -4010, -4089, -5630, -886, -2861, -5097, -2887, -7281, -1953, -4728, -4042, -2988, -7936, -3518, -7408, -2683, -4901, -7230, -4425, -10799, -2119, -8582, -4974, -4064, -10799, -3194, -4486, -3365, -3757, -10069, -8220, -2703, -2653, -3603, -9149, -4718, -2659, -2714, -3249, -8086, -1904, -4378, -3665, -2720, -6870, -1067, -10284, -5718, -2090, -5480, -1219, -6480, -8718, -1369, -4104, -2034, -3975, -9331, -729, -3105, -3286, -2929, -7484, -376, -2741, -4723, -2309, -7665, -337, -3261, -6411, -2066, -9812, -478, -5091, -8517, -2555, -5152, -695, -9873, -6679, -709, 749, 1073, 789, -4541, 740, -577, 904, -1058, -8549, 1156, -3551, 870, -2166, -4386, 753, -10001, 436, -1854, -2253, -719, -4433, -1178, -2129, -1395, -3856, -3428, -5888, -2566, -1168, -8363, -2084, -7562, -2633, -1356, -4616, -531, -5942, -3401, -2072, -258, 85, -6183, -5810, -3054, 1888, -54, -3161, -11781, -3119, 2511, -246, -2468, -7644, -2450, 1853, -121, -3147, -6278, -2181, -247, 11, -3612, -7066, -2650, -5299, -127, -3151, -10284, -4038, -6445, -541, -1998, -6173, -4527, -3045, -1063, -1405, -3321, -2004, -2385, -1916, -2125, -2698, -337, -3695, -3870, -4395, -3023, 292, -6045, -4863, -5502, -1621, 209, -1432, -3023, -4172, -233, -193, 118, -2617, -4299, 0, -488, -440, -2986, -5768, -739, -495, -3142, -2155, -5333, -2004, -517, -1988, -821, -2964, -2662, -907, -31, 89, -1550, -1799, -1979, 87, 592, -1302, -483, -3498, -1293, 585, -2385, 208, -2361, -4738, -436, -5170, -160, -283, -7097, -4053, -8220, -2018, 734, -3827, -4635, -7730, -3386, 706, -3060, -911, -8060, -798, -471, -4067, -11, -7912, 597, -3827, -9531, 182, -6480, 923, -4578, -5437, 365, -5429, 456, -925, -1790, 118, -5394, -811, 63, -111, -1167, -6064, -3532, -400, 533, -3989, -7213, -10526, -2068, 359, -6422, -10138, -2003, -4071, -239, -3110, -10069, 33, -3732, -1289, -949, -4361, 77, -3266, -4464, -87, -2066, -2130, -4056, -7019, -314, -1101, -13365, -6628, -2339, -1238, -1084, -3460, -15615, -1271, -2168, -1814, -3509, -10001, -1096, -3409, -2799, -8683, -8247, -1614, -4874, -3360, -6885, -6653, -2813, -1683, -3244, -5127, -4592, -2119, 410, -2815, -5607, -2984, -1017, 1034, -2849, -4718, -2339, -1382, 479, -3621, -2865, -2699, -3227, -1015, -4659, -1931, -4149, -5623, -2973, -5037, -2545, -7389, -5353, -5997, -5189, -6256, -6074, -3352, -5306, -6457, -7317, -2653, -2153, -1521, -8304, -3496, -1321, -1957, -14, -6899, -2977, -1733, -2514, 171, -5933, -3723, -4425, -3744, -520, -5008, -4946, -2383, -5299, -1011, -3349, -5472, 306, -3824, -392, -1729, -4344, 1274, -1784, 296, -718, -2797, 1281, -1105, 520, -301, -2020, 748, -1867, 155, -361, -2268, -138, -4649, -1076, -1074, -3468, -1559, -11115, -3370, -2871, -5312, -4112, -4620, -3449, -6256, -7665, -8982, -2952, -1940, -11488, -9753, -5960, -2522, -1542, -15615, -8192, -4390, -2945, -1807, -14195, -4412, -4115, -4620, -2347, -10210, -1902, -4075, -7888, -2982, -5509, -675, -3999, -5240, -3449, -3098, -513, -3982, -3792, -3249, -1768, -1423, -4031, -3923, -2986, -1088, -3837, -3493, -2879, -3624, -915, -10704, -2670, -1344, -5810, -1065, -8247, -2505, -1144, -9022, -1416, -7389, -3147, -2672, -7912, -2207, -9284, -3971, -7562, -8112, -3779, -7179, -4153, -7264, -10001, -5844, -5319, -3853, -6204, -2741, -1903, -147, -1215, -9380, -3463, -862, 2102, -2152, -7247, -632, -530, 3003, -3222, -3889, 647, -1274, 2930, -3201, -3563, 860, -3294, 2001, -1062, -5997, 307, -6035, 89, 314, -7426, -960, -5480, -2146, 416, -3436, -3007, -4295, -1282, -359, -2462, -4108, -4172, -637, -1090, -2999, -2728, -4853, -1076, -1717, -3485, -1733, -3686, -1728, -2482, -2156, -1543, -1748, -1637, -2655, -1439, -1873, -858, -793, -2897, -2606, -1940, -1012, -339, -3375, -7004, -1064, -1882, -1002, -4718, -2574, -63, -2596, -3474, -5465, -942, 266, -3837, -6434, -2720, -1802, -687, -9106, -1718, -2477, -5915, -5026, -1501, 50, -5247, -3540, -3177, 1141, 87, -3487, -1670, 33, 2131, -1875, -1046, -1908, 910, 2149, -3886, -485, -2378, 1063, 1523, -375, -819, -1366, 804, 560, 919, -1498, -714, 76, -571, 758, -2396, -1143, -510, -2152, -573, -3776, -2192, -1300, -4564, -2908, -6016, -2500, -4373, -6194, -4951, -9936, -2613, -8549, -7004, -4728, -10899, -3792, -3515, -7912, -2312, -6590, -6388, -2443, -5979, -383, -3996, -6679, -2241, -5422, 538, -2018, -4698, -3393, -6332, 634, -883, -4149, -8423, -7445, -6, -973, -2641, -6773, -9479, -1308, -2745, -347, -4053, -14195, -3140, -7113, 920, -3114, -7503, -4654, -6914, 1292, -2040, -6204, -1914, -7299, 1184, -1188, -5615, 295, -8718, 830, -897, -4295, 986, -5458, -97, -1002, -3512, 450, -3354, -2265, -1050, -3529, -858, -2170, -5751, -827, -3760, -2152, -1726, -3038, -749, -3804, -3773, -1651, -663, -1448, -3906, -5888, -1802, 726, -3982, -4060, -4108, -2247, 1211, -7353, -3526, -2184, -2785, 685, -2774, -2952, -1182, -3014, -1072, -2000, -3860, -1123, -3142, -4266, -4056, -10138, -1974, -4038, -4395, -7912, -4238, -2404, -7130, -3103, -2256, -1768, -1397, -10284, -3603, -916, -1850, -798, -6565, -6310, -1300, -4536, -1077, -5509, -5437, -3175, -5960, -1790, -3274, -2552, -7034, -2596, -1533, -1529, -1532, -13738, -1816, -679, -836, -1527, -8942, -2083, -526, -1005, -2541, -6786, -2910, -1432, -1894, -6899, -8333, -5020, -3597, -3455, -4831, -5607, -11945, -7130, -5623, -1396, -2879, -6422, -6225, -6299, -824, -2887, -5152, -3893, -4764, -1813, -4630, -4784, -2783, -3754, -3951, -2653, -3551, -2612, -3087, -5176, -1005, -2781, -3347, -2534, -3244, -877, -2825, -4929, -2350, -1650, -1693, -3433, -4779, -2696, -1063, -2150, -4769, -3076, -3452, -1459, -1511, -7445, -2646, -4403, -2964, -1259, -9193, -3714, -5097, -6332, -2214, -8615, -6399, -4940, -13365, -5091, -10001, -7960, -4918, -7335, -11356, -13049, -6235, -5429, -8060, -5367, -9753, -4523, -3903, -8138, -3621, -6914, -2847, -2291, -3521, -3144, -6163, -1782, -2057, -1672, -3535, -7004, -1395, -3130, -1264, -4482, -7842, -1332, -5002, -1865, -5465, -7984, -1394, -5776, 9769, 6855, 9619, 7873, -3078, 9177, 6752, 9152, 7200, -1055, 7333, 6116, 7837, 4981, 348, 4069, 4419, 6083, 1119, 1049, 119, 1465, 4351, 1858, 1673, -395, 163, 2094, 2644, 1980, 500, 1204, -1384, 2232, 1923, -56, 1983, -1361, 1315, 1625, 5, 2429, -92, 134, 947, 2500, 2451, -816, -968, 213, 4231, 2225, -1921, -654, 1059, 5210, 2732, 574, 95, 2593, 5428, 3905, 1860, 549, 3684, 4655, 4581, 1394, 1347, 4413, 2737, 4293, -2031, 1791, 5014, 1532, 2643, -494, 881, 5499, 2091, -1937, 2910, -2235, 5614, 1513, -798, 3929, -1957, 5017, 1211, 1418, 3626, 37, 3356, 2627, 1121, 2149, 162, 263, 3491, -1133, -964, -645, -2483, 3994, -6299, -5951, -1007, 677, 4492, -6745, -2576, -229, 3384, 4505, -3089, -2109, 219, 4694, 3663, -587, -3254, -430, 4865, 2234, 59, -4447, -1858, 4118, 1442, -1265, -3632, -1008, 2796, 1035, -4451, -2447, 231, 1771, 52, -1766, -3049, 359, 1503, -253, -28, -6492, -305, 1201, 696, 906, -1032, -1226, 422, 1320, 1853, 1128, -576, -569, 1342, 2422, 1451, 1376, -663, 898, 2146, 613, 2591, -229, 323, 491, -535, 2781, -729, 332, -5139, -770, 1932, -3034, 880, -1125, -904, -161, -7113, 1135, 1081, -2159, -4097, -4513, 594, 806, -5662, -7371, -3449, -813, -1595, -10899, -7066, -3012, -2521, -2262, -4683, -4597, -2924, -3058, -570, -2429, -2622, -3135, -2624, -941, -1569, -2289, -2967, -2924, -2677, -2184, -2869, -2228, -5726, -2550, -4863, -3085, -1432, -8086, -1446, -8333, -3189, -1390, -2975, -1159, -4145, -4748, -2608, -1704, -1385, -2234, -8649, -5026, -1918, -1864, -1439, -6365, -5014, -2857, -2550, -1763, -5942, -4569, -3294, -3296, -2954, -8009, -6516, -3683, -3726, -3254, -7623, -5326, -5152, -4262, -2592, -5784, -2538, -6640, -6007, -2288, -5260, -2069, -7019, -8165, -2334, -6246, -3744, -13049, -6666, -2601, -5979, -8754, -5997, -6565, -2720, -3487, -8034, -3163, -6814, -2534, -2499, -7665, -2601, -4254, -2698, -2969, -5784, -3449, -2380, -3665, -4997, -5247, -5429, -1660, -5415, -9531, -6899, -8165, -1889, -6773, -8220, -5509, -8982, -3121, -5509, -5561, -4078, -6504, -5569, -3474, -4412, -4399, -4246, -9812, -2548, -4119, -6445, -3020, -14784, -2606, -4082, -5133, -2853, -9479, -2988, -3978, -2267, -3388, -6773, -3291, -4504, -1141, -3154, -4831, -3632, -6666, -1165, -2105, -3554, -4089, -8393, -1857, -1498, -3124, -4795, -5638, -2644, -1553, -3873, -5906, -4311, -3276, -2347, -6434, -7389, -2920, -3846, -4299, -7213, -7752, -1706, -3476, -9284, -3194, -5008, -933, -2935, -9284, -941, -2543, -461, -3339, -5827, 185, -1084, -645, -4373, -4880, 258, -545, -1922, -4184, -5623, -864, -852, -4545, -2571, -10704, -3014, -1778, -8363, -777, 3635, 4384, 1687, -227, 2784, 3471, 4154, 4135, -37, 2584, 2680, 3439, 5566, 480, 2660, 359, 2276, 5339, 1050, 3081, -3546, 859, 3326, 1143, 3028, 373, -932, -2956, 435, 2454, 1205, -2433, 1387, 454, 1202, 35, -1587, 3163, 1920, -1775, -2811, 337, 3076, 2428, -7752, -6246, 2418, 1908, 1587, -5576, -198, 4141, -330, -500, -1397, 2932, 5306, -2173, -3518, 1349, 4328, 5803, -968, -4486, 2056, 4561, 5567, -2273, -1465, 946, 3988, 4576, -1794, 1865, -2495, 3117, 2839, 2138, 4000, -1786, 2268, 392, 3583, 4893, -155, 1083, -3105, 3671, 4613, -186, -471, -7247, 2895, 2933, 226, -2122, -812, 1924, -1329, 1588, -6786, 1411, 1640, -888, 2786, -3391, 1831, 1708, 652, 3294, -1073, 817, 1269, -1542, 2676, -1802, 1615, -347, -745, 171, -5079, 3858, -4738, 2705, -10138, -2724, 4731, -5195, 3710, -1281, -1320, 4285, -3326, 3817, 496, -1303, 2613, -4683, 4140, 1152, -981, 266, -5266, 4415, 1026, -591, 143, -4545, 3915, 175, -1142, 1680, -5020, 2466, -375, -2482, 2820, -4523, 624, 506, -2887, 3223, -4523, -28, 1665, -1000, 2880, -4234, -139, 2264, 731, 1805, -1455, -680, 2045, 1351, 251, 232, -1189, 946, 817, -297, 610, -1208, -155, -841, 144, -186, -1581, -113, -3496, 22, -2140, -3326, -461, -5183, -444, -5176, -3457, -1548, -4912, -760, -7264, -489, -2770, -4779, -1446, -5743, 929, -4738, -3870, -2353, -4738, 1264, -4842, -3449, -2497, -4669, 861, -3893, -4784, -1963, -5638, -160, -5145, -6914, -1119, -9064, -1499, -4683, -5031, -849, -9064, -1748, -2772, -4006, -1664, -5014, -1656, -2716, -3717, -1998, -3615, -2504, -4748, -3208, -611, -3316, -2483, -6516, -2253, -227, -3927, -1044, -4583, -1548, -1515, -5988, -241, -5569, -1716, -4219, -6786, -118, -10210, -2982, -3695, -4620, -555, -4703, -3471, -3677, -4821, -1762, -3460, -2817, -6492, -8903, -4219, -4067, -3837, -8086, -6870, -4821, -5234, -7213, -5008, -3754, -2370, -3830, -4743, -3474, -2236, -1043, -1611, -3773, -2659, -1469, -546, -485, -5183, -3020, -1864, -786, -695, -8942, -5061, -3785, -1819, -2730, -5422, -5415, -4863, -3309, -8549, -2685, -2799, -3294, -3334, -4049, -1298, -1514, -2941, -1864, -2835, -819, -1047, -3975, -666, -3074, -938, -987, -6745, -243, -2578, -1491, -806, -6602, -575, -1707, -2417, -263, -5333, -1176, -1434, -3668, 77, -8903, -1542, -1819, -5615, -327, -5451, -1773, -2916, -8615, -1697, -1753, -1809, -4348, -9022, -4207, -614, -1748, -4331, -5960, -8754, -801, -2046, -3804, -4006, -12534, -1666, -2893, -3944, -3468, -9531, -2319, -4086, -4703, -4021, -11356, -3038, -4031, -5152, -5487, -8112, -4784, -2420, -4234, -9873, -4491, -2608, -1307, -4067, -8982, -2578, -325, -1029, -5561, 2080, 5215, 106, 2922, 2841, 3014, 5221, 172, 2269, 4181, 4165, 5141, 2035, 2117, 5452, 4538, 4770, 3580, 3754, 5490, 4196, 3956, 3785, 4526, 3901, 3537, 2557, 2738, 4043, -932, 2591, 269, 703, 2291, 1136, 458, -2306, -1136, -365, 2445, -4555, 45, -577, 826, 1757, -4031, 1951, 1058, 3043, 3471, -2994, 2842, 1736, 4276, 5582, -12, 3222, 1102, 4634, 6587, 1515, 3365, -537, 4061, 6540, 1412, 3187, -369, 2224, 5179, 512, 2445, 532, -1320, 1188, 389, 926, 4, -310, -1679, 422, -1736, -2046, 1038, 2003, -644, -3957, -3179, 699, 2666, -3080, -385, -2058, -1343, 3228, -5394, 1313, -1268, -15615, 3414, -8615, 1454, -339, -1452, 2847, -1385, 980, 822, 629, 1934, 1523, 1624, 1683, 733, 1499, 2381, 2301, 1903, -531, 1708, 1669, 2042, 1588, -2626, 1667, -601, 1059, 1265, -2390, 326, -2688, -727, 972, -1036, -5638, -1495, -4199, 37, -371, -735, -1308, -2012, -371, -271, 1794, -3417, -1298, 900, -525, 1968, -4035, -4046, 1326, -799, 465, -1141, -2648, 552, -834, -1868, -967, 96, -976, -816, -1463, -3040, 1115, -2933, -1254, -476, -2918, 1369, -6278, -2399, 238, -440, 928, -5906, -1975, 454, 118, 163, -3007, -295, -71, -1624, -79, -549, 188, -1409, -9106, -364, 849, -588, -2843, -907, -671, 917, -2383, -2450, 312, 221, 113, -3261, -1683, -1227, 1036, -36, -1566, -969, -10613, 1015, 105, -454, -418, -1932, 620, -840, -350, -629, -864, 409, -3156, -802, -2172, -2226, -97, -5735, -1373, -5422, -5801, -1458, -5374, -2366, -5686, -7603, -3621, -4980, -4500, -5615, -4282, -5451, -5509, -4578, -6035, -2720, -5091, -5933, -2382, -6256, -2559, -4679, -6007, -1722, -12319, -3438, -4420, -4625, -2339, -5531, -4327, -5253, -2594, -3436, -3321, -5387, -28777, -1814, -2631, -3339, -8138, -3324, -2372, -1339, -4378, -7562, -854, -3415, -992, -4885, -8683, -247, -2984, -1777, -5387, -10069, -818, -2282, -3804, -9149, -4743, -2475, -1983, -7562, -6692, -3710, -5189, -1753, -28777, -3463, -4625, -6007, -1887, -7335, -2960, -7888, -4784, -2910, -3662, -3954, -8393, -3811, -5121, -1665, -5319, -5037, -3124, -7583, -941, -4764, -3551, -3441, -8754, -1377, -3311, -2442, -5678, -28777, -2803, -3274, -1479, -10362, -6553, -4659, -5346, -1108, -7796, -3422, -5844, -4738, -1702, -4100, -2047, -5240, -2448, -3170, -890, -1210, -3600, -1640, -3665, 753, -627, -2344, -1449, -2829, 1092, -773, -2008, -1364, -2458, 217, -1782, -2875, -1402, -2453, -1925, -2336, -5234, -1950, -2683, -4625, -2229, -8754, -3213, -3886, -6163, -3509, -7523, -4460, -7196, -12123, -4644, -5836, -4134, -4042, -5897, -2203, -4957, -3603, -1553, -3175, -1107, -4733, -3910, -755, -2407, -1088, -5326, -5202, -6577, -2509, -2453, -7034, 339, -3108, -1198, -1880, -4611, 522, -1729, -1155, -1035, -4093, -162, -1394, -2205, -734, -4997, -1186, -1895, -4601, -1124, -6615, -1296, -3428, -7936, -1670, -8060, -843, -7179, -5509, -1585, -8423, -717, -8942, -4028, -1123, -5115, -886, -5387, -2975, -822, -2891, -1418, -4469, -1714, -1076, -1874, -3045, -3441, -1076, -2173, -1815, -6388, -2205, -1487, -3940, -2799, -3103, -1495, -2825, -4816, -4880, -1481, -1315, -2566, -4611, -3650, -1877, -1534, -854, -4659, -1245, -4438, -1843, 29, -5152, -156, -9238, -2306, -47, -6225, -106, -5208, -3509, -1227, -8827, -1007, -4006, -5043, -4425, -10899, -3062, -4119, -4901, -6973, -6035, -6553, -5133, -5584, -3707, -4145, -5670, -4858, -10210, -3237, -3769, -4270, -2587, -9193, -3149, -4464, -4438, -1303, -6183, -2316, -4929, -5623, -1301, -4759, -1826, -3417, -5367, -2683, -3016, -2108, -2034, -3535, -5793, -1842, -3069, -1681, -2369, -6445, -1514, -4331, -2621, -1698, -4918, -1800, -5195, -5422, -1742, -4420, -2125, -5115, -10526, -3284, -3978, -2004, -4486, -6786, -8942, -3930, -2014, -3846, -5751, -8333, -5189, -2939, -3337, -6074, -8865, -10799, -5776, -2990, -6553, -8086, -6321, -12776, -3042, -4826, -3738, -3606, -5266, -3352, -3119, -2979, -3569, -3689, -3947, -2644, -4172, -6163, -3430, -5554, -3227, -7687, -9479, -3103, -5387, -4378, -9331, -6163, -1904, -3347, -4997, -4968, -5897, -969, -2984, -4331, -2747, -6278, -912, -4278, -3563, -1466, -6332, -1704, -7796, -3220, -1170, -6745, -2935, -12123, -3112, -2130, -8276, -3896, -7264, -3903, -5079, -9284, -4597, -7050, -7583, -7562, -7299, -5429, -10899, -5810, -3603, -4382, -7066, -6800, -2811, -2087, -2317, -8192, -4242, -2045, -1884, -1615, -5444, -3689, -2297, -3012, -2181, -4195, -3971, -2937, -6288, -3876, -4286, -4295, -3798, -9753, -7523, -5227, -4907, -5115, -5127, -8423, -6928, -5844, -5115, -3049, -3449, -8112, -5085, -4089, -1868, -1882, -6814, -4403, -4056, -1379, -1733, -6354, -5561, -4869, -1489, -2331, -7583, -9585, -5988, -2086, -2914, -10526, -7247, -7623, -3083, -2637, -11004, -6083, -9193, -4473, -1753, -8138, -7503, -9064, -6026, -1228, -6267, -6759, -8942, -4837, -1526, -5879, -4578, -8393, -3393, -2933, -6113, -3913, -8138, -3422, -6103, -4869, -4242, -9331, -5037, -17034, -3788, -5097, -11781, -6133, -6653, -4028, -5888, -11115, -4597, -4138, -5997, -6016, -7603, -4112, -2997, -13365, -5576, -4853, -4759, -2861, -9380, -5152, -3455, -5480, -3436, -7408, -5227, -3163, -5253, -4315, -7665, -6173, -3798, -5429, -5726, -8649, -8827, -4826, -7542, -7113, -8138, -7542, -4991, -28777, -5049, -6899, -4769, -4800, -7936, -3916, -6719, -3944, -5960, -7213, -4187, -8165, -4611, -11945, -9106, -5422, -10899, -6928, -7264, -12534, -6786, -8009, -10799, -4266, -11488, -7317, -6445, -8790, -3370, -8582, -7865, -5326, -1923, 445, -1426, -4795, -4847, -2690, 167, -2256, -2211, -6480, -5630, -872, -3276, -1275, -8423, -5279, -2445, -4130, -1697, -5494, -2369, -4429, -4464, -2703, -4683, -1072, -7503, -4086, -2482, -6064, -546, -9429, -3133, -2452, -5367, -837, -6183, -2417, -4587, -2292, -2488, -4929, -2435, -11488, -959, -6399, -4056, -3399, -3683, -1087, -5735, -3532, -5061, -2276, -3054, -4795, -3833, -4683, -2465, -12776, -6411, -4307, -3189, -3689, -4089, -8903, -3306, -2969, -5718, -2326, -8865, -1875, -4486, -5970, -2785, -10138, -1058, -5678, -4112, -5394, -10704, -986, -3468, -3449, -9479, -9149, -1589, -3142, -4491, -6457, -7050, -2855, -5183, -7984, -5942, -6035, -5055, -6214, -7503, -6759, -5139, -6786, -2931, -7665, -6123, -3968, -4149, -1355, -8485, -3996, -3824, -2482, -812, -3856, -2655, -5002, -2176, -1260, -1868, -2128, -4693, -3274, -3227, -845, -2239, -2988, -6267, -10284, -485, -2859, -2531, -8485, -5654, -959, -3710, -3051, -6267, -4826, -2011, -4420, -3975, -6653, -5312, -2865, -4708, -4683, -9022, -2411, -4373, -4698, -4901, -8549, -892, -6422, -4523, -3975, -10069, -684, -2960, -4108, -2791, -9064, -1157, -1516, -3856, -2325, -3947, -1793, -1693, -4369, -2791, -2102, -2478, -3137, -4395, -4282, -1538, -3194, -5234, -3239, -6267, -1655, -3792, -5326, -2733, -5718, -2198, -4733, -4460, -2994, -4042, -3624, -7050, -4523, -3600, -3133, -8333, -8086, -5818, -4134, -3286, -6814, -4373, -7730, -3910, -4997, -3788, -2737, -6786, -3569, -9022, -3526, -2536, -6615, -3954, -6183, -4698, -3748, -7912, -4805, -4262, -5014, -6885, -4630, -5718, -3365, -3597, -7097, -2336, -7819, -2472, -2997, -4790, -1603, -13049, -1875, -3485, -3978, -2115, -9284, -2236, -4810, -3893, -3964, -9022, -3535, -6732, -4469, -8276, -12123, -3425, -10362, -6759, -8304, -9380, -2873, -14784, -12319, -5437, -6388, -4307, -10442, -5879, -4805, -4968, -9193, -6376, -5073, -4486, -4390, -4199, -4282, -5942, -3034, -4138, -2601, -4086, -4951, -1771, -4104, -2847, -5472, -4290, -1703, -4382, -4659, -7842, -4541, -3388, -4403, -8549, -8649, -3632, -6235, -3329, -5367, -7484, -3244, -3177, -2453, -3089, -7445, -4464, -1921, -2560, -2260, -9479, -5465, -1873, -3814, -2337, -8827, -4478, -2213, -6103, -3264, -8754, -4408, -3007, -6842, -4592, -13738, -5584, -4748, -6007, -3856, -6528, -7542, -4869, -6123, -2351, -4541, -6692, -3409, -7230, -1662, -4473, -4569, -3135, -9429, -1779, -5615, -3067, -3856, -11356, -2540, -7687, -2231, -4991, -10001, -3680, -11115, -2276, -5630, -8549, -4790, -12534, -3386, -5768, -7665, -5599, -6679, -5871, -6225, -7389, -6332, -4451, -12319, -6679, -6064, -7004, -4067, -10138, -5253, -4266, -6602, -5862, -7665, -3944, -3501, -5888, -17034, -7752, -3833, -3496, -5942, -5960, -8865, -5049, -3425, -6666, -4412, -8903, -7819, -3239, -7408, -5037, -7687, -13365, -1137, -2559, -1426, -6299, -6773, -2512, -3158, -1682, -5109, -7730, -3886, -3940, -2182, -4250, -10069, -3964, -4513, -3198, -5810, -9149, -4134, -4980, -3474, -11115, -6565, -4250, -7146, -2964, -3732, -6123, -3999, -8276, -3007, -1831, -6615, -3788, -4578, -2322, -1531, -7097, -3726, -3103, -1208, -2194, -7523, -3853, -2533, -1122, -3773, -8192, -2969, -2809, -2204, -7960, -9479, -1736, -4035, -3707, -6828, -12534, -1417, -5801, -3940, -2853, -10899, -2083, -6411, -3269, -1472, -9585, -3624, -3707, -3067, -1500, -10442, -6074, -1999, -4559, -3010, -6045, -9429, -1872, -8649, -5346, -3710, -11356, -3259, -4482, -3281, -2531, -9022, -5145, -3347, -2011, -1359, -6640, -3025, -5014, -2111, -419, -5623, -885, -9695, -3080, -238, -5670, 387, -3463, -4416, -812, -5951, 943, -1497, -5702, -1848, -7066, 897, -952, -7247, -2997, -12123, 607, -1319, -12534, -4238, -9479, 547, -2557, -7230, -5888, -6842, 461, -4403, -4509, -8790, -6113, -341, -4258, -4491, -28777, -5020, -2248, -3092, -7562, -10613, -3804, -4021, -2849, -5273, -9695, -3903, -2533, -3444, -2191, -8454, -6246, -1432, -3923, -1086, -4578, -7371, -1526, -3415, -994, -2309, -5367, -2815, -3182, -1505, -1452, -5784, -3944, -3933, -2242, -1813, -6842, -3449, -5694, -2891, -3074, -5776, -3674, -7796, -3407, -4082, -4361, -5253, -6732, -3975, -4654, -3108, -8086, -4195, -4769, -6343, -2264, -10284, -2543, -5853, -8086, -1987, -8060, -1844, -7066, -6133, -2216, -6399, -1868, -8517, -5584, -2578, -6016, -1864, -10362, -7066, -2487, -7317, -1236, -10210, -12123, -1979, -11945, -479, -6759, -7230, -1711, -7230, -266, -4180, -4935, -2328, -4644, -981, -2559, -4234, -4718, -3342, -2958, -1860, -4541, -11781, -2242, -6457, -2057, -5836, -5176, -1033, -6828, -3130, -7503, -3957, -168, -4963, -4532, -8034, -4693, -21, -4238, -4874, -6469, -6814, -643, -4816, -4963, -4592, -8165, -1863, -6480, -4991, -4352, -7213, -2982, -7819, -3535, -6153, -5906, -3269, -7464, -2111, -5020, -4408, -3425, -4640, -1471, -2707, -3916, -3668, -3010, -1532, -2277, -5234, -3386, -3027, -2238, -3452, -9585, -3279, -4513, -3430, -6343, -6411, -4659, -7097, -4307, -9380, -5286, -7888, -8649, -3592, -8485, -7130, -5678, -6988, -2737, -9284, -11488, -5202, -5026, -2416, -14195, -5997, -6745, -3795, -2051, -8718, -4733, -5312, -3331, -1759, -6299, -4698, -3487, -3788, -2305, -5623, -4089, -2847, -5367, -4274, -5339, -3163, -3117, -7426, -7353, -4907, -3056, -3957, -7730, -7034, -4336, -4130, -5312, -8615, -7097, -3879, -6870, -8549, -9149, -7623, -3444, -15615, -12123, -7408, -7299, -2933, -11356, -7335, -7687, -7213, -2813, -10704, -6856, -12319, -7687, -3296, -9238, -5942, -9106, -8754, -3856, -7130, -4425, -6310, -8754, -3856, -6332, -3723, -5751, -8112, -3933, -6321, -3668, -5951, -8615, -4597, -5836, -3766, -5827, -8942, -5776, -4082, 15079, 1996, 10173, 9749, 8284, 14678, 5449, 9501, 9080, 10074, 13441, 6789, 7260, 6834, 10033, 11279, 6239, 2289, 1501, 9131, 8396, 4271, 379, 853, 8032, 7499, 1618, 725, 1957, 6314, 8352, 35, -328, -609, 3415, 8633, -837, 177, -7019, 5102, 8143, -501, -542, -380, 5954, 6802, 1346, 1343, 1246, 4327, 4699, 3374, 3619, 2342, -3430, 3032, 4847, 4777, 2973, 1407, 3215, 5570, 5121, 3062, 1920, 4733, 5418, 4779, 2581, -1020, 5585, 4180, 3864, 1055, -6773, 4934, 1705, 2704, -2482, -3741, 2161, 513, 1702, -3133, -2997, -1296, 1091, 825, -1759, -4896, 1491, 453, 65, -1928, -2165, 1940, -1082, -638, -2567, -645, 977, -2097, -1932, -6173, -178, -1760, -1270, -4157, -3879, 1276, -5827, -543, -4104, -904, 2354, -3018, -950, -3820, -853, 2725, -2578, -2445, -6565, -1860, 2679, -3512, -2155, -6988, -956, 2077, -6577, -713, -4550, -176, 74, -6928, -394, -5158, -589, -9064, -1549, -1189, -5339, -1860, -1729, 496, -3284, -4046, -2935, -333, 1063, -7774, -3754, -2238, -1078, 587, -28777, -3401, -946, -1641, -483, -9812, -3161, -315, -1799, -1278, -5214, -3999, -675, -3441, -1319, -3465, -5189, -2244, -5472, -1206, -3326, -6365, -3863, -4382, -1671, -4373, -10799, -2475, -5615, -3269, -6007, -9429, -1656, -8754, -4620, -6628, -8683, -2049, -3674, -3286, -5979, -12534, -3177, -2743, -2646, -5333, -8086, -4238, -3600, -2829, -5554, -5266, -6256, -5139, -3321, -6943, -3635, -10001, -6074, -3738, -8034, -3087, -4951, -4323, -4123, -6786, -3840, -3526, -2317, -4635, -6719, -5055, -3860, -1154, -4929, -9429, -3347, -5380, -554, -4630, -11629, -2049, -7299, -448, -4161, -6899, -2022, -7371, -976, -3996, -5451, -2807, -6615, -2339, -4541, -4664, -3476, -6973, -5061, -6035, -4403, -3647, -8615, -9531, -7644, -4896, -4089, -8333, -7865, -6973, -6074, -5494, -6246, -7542, -6411, -7230, -9380, -4373, -7034, -7445, -7317, -9106, -3005, -6083, -11629, -6225, -5569, -2430, -4974, -9936, -5055, -4733, -2701, -4130, -6376, -4307, -5429, -3741, -4340, -4323, -4078, -7281, -5247, -5743, -3130, -4274, -10284, -6267, -7644, -2817, -4625, -14195, -5793, -7687, -3309, -4649, -9531, -5465, -6800, -4395, -4649, -9064, -6565, -8649, -5480, -5509, -12319, -9193, -8903, -5818, -8333, -11115, -8009, -3612, -5970, -13365, -8454, -6540, -1952, -6299, -8754, -8165, -6577, -1671, -6343, -7523, -9331, -7842, -2169, -5801, -7687, -9479, -9639, -3396, -5061, -7281, -8485, -9380, -5827, -4880, -5710, -8718, -9639, -11629, -5853, -4980, -10362, -13365, -9873, -7708, -5158, -11004, -13738, -7004, -6422, -5879, -9753, -9106, -5906, -4573, -6943, -9429, -7752, -5067, -4336, -8276, -9331, -7774, -3683, -6445, -10210, -8582, -8423, -2869, -12776, -9380, -7264, -8138, -3291, -6800, -7445, -6332, -7299, 8604, 3945, 6864, 8571, 7383, 7855, 3964, 6139, 8137, 7006, 5364, 3619, 3539, 6914, 5897, -274, 2199, -7523, 5283, 4622, -5240, -1046, 484, 3958, 4359, -3119, -1418, 512, 3032, 4121, -662, 1403, -3342, 1925, 3168, -599, 3199, -151, 3, 2474, -3054, 4122, 1936, -3827, 3063, -7081, 4206, 3093, -8683, 3985, 714, 4162, 4738, -2758, 4335, 3758, 4887, 6199, 115, 3745, 5275, 5632, 6833, 1408, 2127, 5620, 5737, 6451, 1162, -254, 4831, 5174, 4797, 469, -1992, 2837, 4148, 1409, 2100, -1279, 135, 2813, 989, 3339, -287, -241, 872, 2252, 3304, -571, 65, -1625, 1699, 2089, -2726, -411, -245, -88, -215, -6745, -1345, 1370, -2047, -2749, -3498, -2432, 1928, -3498, -4486, -2320, -2672, 1882, -5743, -3824, -2580, -1515, 1601, -6640, -2564, -3609, -797, 1335, -5933, -3824, -4669, -1195, 1133, -7353, -5702, -4460, -3244, 810, -14784, -1836, -3078, -10069, 47, -6943, -506, -2064, -6173, -1304, -4946, -315, -1832, -3735, -2182, -4486, -667, -2311, -2621, -1766, -4299, -2057, -3177, -2264, -1648, -3551, -7281, -3738, -2849, -1826, -3597, -4664, -3886, -4395, -1638, -6143, -1424, -3824, -6577, -1468, -5862, -165, -3698, -7865, -1752, -3187, 485, -3720, -5906, -2541, -3430, 761, -4130, -3529, -3817, -6246, 486, -5694, -2200, -5615, -6133, -790, -11356, -1873, -7644, -4630, -4486, -8790, -2473, -7162, -5133, -6814, -6577, -4078, -5360, -5008, -2217, -6411, -7247, -4606, -3309, -1123, -5133, -11115, -4784, -2452, -1197, -3937, -6640, -5319, -2845, -2043, -4266, -4816, -6299, -4997, -3362, -7230, -4929, -11232, -9695, -4112, -11004, -7842, -7146, -6016, -3092, -5546, -11004, -3837, -5133, -2020, -4327, -6288, -3187, -5951, -1836, -4331, -5970, -4123, -6163, -2664, -5121, -7774, -4842, -5718, -4523, -5988, -10899, -3824, -7097, -7752, -6457, -8112, -3662, -28777, -13365, -7019, -6745, -5103, -7603, -9429, -7371, -7050, -8942, -5853, -8549, -6914, -8790, -9149, -6278, -11488, -6457, -8192, -7146, -7408, -10704, -6958, -6016, -6615, -6814, -6235, -9429, -4532, -6719, -6173, -4693, -9639, -3674, -7865, -6870, -4331, -6745, -3714, -11945, -9106, -4597, -6256, -4816, -10899, -11781, -5170, -7730, -6885, -7464, -11629, -5853, -13049, -8454, -6577, -10362, -6143, -8582, -7687, -7213, -8615, -5735, -5592, -6540, -10001, -7644, -4974, -4573, -6628, -28777, -7281, -4564, -4795, -7842, -10069, -7179, -4728, -6434, -9149, -8942, -7299, -5158, -11629, -13365, -10069, -7542, -5480, -8582, -9531, -11781, -7162, -5607, -5049, -6615, -8517, -6615, -5067, -3729, -6214, -6958, -6235, -4348, -3729, -6553, -7097, -5933, -4226, -5240, -6299, -8517, -6133, -4708, -9284, -5979, -10362, -7317, -5686, -8982, -5924, -11115, -8112, -7066, -7583, -5960, -10526, -7842, -7774, -9531, -6163, -10069, -9429, -7213, -12776, 4310, 2708, 6990, 7471, -15615, 3226, 1575, 6534, 7170, -5319, -565, -1330, 5369, 6403, -1790, -1323, 1284, 4390, 5600, 1713, -1967, 2902, 4127, 4938, 4045, -6163, 3210, 3792, 3977, 5217, -1403, 2642, 2997, 2856, 5416, -3629, 1050, 1590, 2355, 4620, -1743, -1913, -605, 1507, 2126, 2935, -3040, -3168, -1542, -3626, 4946, 1173, -948, -2146, 2887, 5787, 4314, 1140, 1218, 4354, 5668, 5813, 1252, 2007, 3854, 4538, 5779, -493, 2074, 2001, 2451, 3882, 611, 2980, 2509, 942, -3210, 2276, 3721, 4021, 702, 231, 1892, 3317, 4409, -103, 1213, -609, 1603, 4021, -608, -1343, -4495, -1340, 3247, -650, -9429, -6540, -6540, 2242, -958, -2698, -6093, -5871, 719, -927, -2102, -2073, -2619, -1591, -356, -1857, -1686, -2222, -1594, 196, -1391, -3626, -2175, -136, 147, -1688, -11356, -1900, 259, -920, -2887, -6246, -2314, -224, -3656, -4234, -3863, -3866, -1571, -10001, -4176, -3259, -5516, -3729, -4527, -3187, -3635, -4021, -4299, -3996, -2847, -5008, -3314, -2316, -7708, -4093, -7912, -5121, -761, -4759, -6299, -13738, -6870, -336, -1613, -2912, -12776, -2495, -1371, -860, -1158, -7562, -1300, -4199, -1588, -863, -5176, -1625, -4532, -3463, -1439, -4784, -2737, -3071, -4053, -2289, -5509, -4010, -2447, -3242, -3225, -5524, -5509, -1953, -3671, -4974, -6093, -7603, -2178, -5286, -7445, -9429, -9022, -3444, -6246, -6885, -7335, -9695, -4532, -6399, -6928, -6026, -12123, -3971, -7623, -9639, -8247, -6590, -4219, -9331, -12319, -9753, -3422, -6988, -9429, -8454, -4469, -2002, -9753, -8615, -5853, -3005, -1741, -5646, -7299, -4142, -3119, -2416, -6310, -5979, -3814, -4138, -3618, -11232, -4946, -4885, -4688, -3571, -5008, -4226, -5554, -4442, -2670, -3707, -3840, -4176, -5067, -2688, -4918, -3680, -3644, -8865, -3886, -11356, -3580, -4307, -6354, -5646, -7603, -3683, -5784, -2825, -6602, -5584, -4473, -7503, -1782, -7146, -6235, -6653, -8982, -2195, -7426, -9753, -11629, -7708, -3913, -6679, -11781, -9873, -6411, -7353, -5091, -7603, -9106, -6214, -8220, -3846, -6553, -8363, -7281, -5871, -3436, -6719, -6973, -10613, -5751, -3798, -8060, -6759, -7644, -7371, -4821, -10210, -7888, -5299, -9873, -6214, -9064, -9873, -4831, -9753, -7353, -7113, -11629, -5584, -9479, -8790, -5793, -11781, -7081, -9812, -11232, -5374, -10442, -8649, -9753, -7484, -6457, -8903, -9238, -10069, -5183, -11945, -8247, -8454, -10442, -4464, -7708, -8423, -7113, -8517, -4679, -4513, -9149, -6411, -6870, -4997, -3621, -9380, -6235, -6376, -4951, -4086, -9284, -5735, -6528, -5415, -5524, -9695, -4759, -7066, -6914, -7353, -10613, -4168, -8649, -7335, -8333, -10899, -4013, -11629, -6354, -7687, -9284, -4010, -8827, -6732, -8192, -8192, -3947, -6565, -9331, -13049, -8333, -3773, -5818, -9149, -9331, -9531, -3785, -6321, -6773, -7623, -5139, -5897, -6973, -6074, -7230, -7281, -6365, -7912, -6256, -7842, -4587, -6288, -10799, -6628, -8454, -2613, -5768, -10526, -6504, -8754, -2219, -5970, -9149, -5561, -7445, -3540, -6528, -9873, -4946, -5879, -6914, -6288, -8517, -5266, -5133, -5576, -5183, -8138, -6628, -5214, -3916, -4060, -11945, -8790, -6343, -3549, -3386, -11004, -10899, -9639, -3801, -3409, -7865, -10799, -14195, -4215, -4157, -6973, -8903, -8827, -4078, -5539, -6914, -7752, -8942, -3551, -7730, -9022, -7912, -12319, -3751, -7865, -12123, -8517, -14195, -4654, -6204, -7445, -7912, -10362, -4957, -4478, -5202, -9639, -7774, -4093, -2210, -3027, -6814, -3580, -2316, -69, -818, -1828, -467, -735, 1194, 803, 382, 1201, 75, 1347, 1438, 1068, 1630, -57, 377, 925, 464, 862, -1274, -1599, -921, -1469, -1321, -3863, -4031, -4774, -5121, -5686, -8615, -5997, -8827, -12319, -8942, -15615, -6602, -6492, -10001, -7603, -12319, -6204, -6434, -7179, -6899, -11115, -5844, -7888, -6163, -6194, -10613, -6183, -11629, -5888, -5970, -9284, -7464, -11781, -5997, -5897, -8423, -8790, -8393, -6577, -6035, -7484, -8423, -7146, -7960, -6719, -6007, -7912, -7464, -10284, -7960, -5422, -6773, -9936, -11781, -8982, -6469, -5139, -10362, -11232, -9639, -11629, -4211, -7888, -11488, -11356, -8009, -4097, -7623, -13365, -15615, -5055, -4369, -8942, -14784, -14195, -4286, -4616, -11629, -11356, -10799, -4853, -5152, -11945, -9064, -8865, -6628, -6083, -9284, -8304, -9022, -7774, -7019, -7912, -8903, -12319, -6745, -8790, -7708, -10442, -13365, -6256, -17034, -8683, -9106, -9149, -6885, -9753, -10799, -6899, -8165, -8247, -7752, -13738, -5942, -8060, -7213, -8582, -17034, -6246, -8615, -5853, -13365, -28777, -8454, -9936, -6204, -14195, -17034, -13365, -12534, -8982, -11356, -13738, -8683, -10613, -11945, -9064, -12534, -8247, -8865, -9193, -7484, -12776, -10613, -9531, -9936, -7247, -17034, -14195, -11004, -14195, -8060, -13365, -11232, -8423, -9695, -9149, -10210, -11488, -7353, -7644, -9238, -9064, -13049, -7583, -7484, -8220, -9106, -11945, -8304, -7408, -6988, -9695, -10284, -8754, -6113, -6615, -9639, -9238, -8865, -4929, -7408, -9639, -8363, -8903, -4307, -9284, -9639, -8276, -8754, -4495, -10362, -8827, -9064, -8615, -5888, -9022, -8393, -10362, -9064, -8754, -7665, -8582, -11781, -9936, -8582, -6828, -8903, -14195, -10442, -6528, -6615, -9193, -12123, -10210, -5888, -6973, -9429, -8982, -10001, -6540, -7562, -9753, -7888, -10001, -9022, -7730, -10613, -8220, -10362, -17034, -7730, -12319, -10362, -11488, -15615, -8582, -12534, -28777, -13049, -15615, -11004, -9429, -14195, -12776, -9380, -13365, -7865, -12776, -11945, -7146, -10799, -8009, -14784, -11945, -6411, -8754, -10001, -12534, -12534, -6828, -8423, -12534, -10899, -11945, -8192, -9812, -10899, -10138, -10526, -9585, -12776, -10799, -10362, -9585, -9695, -13365, -12776, -11356, -9936, -9429, -10442, -13049, -10799, -11945, -6602, -9331, -17034, -6692, -7960, -7113, -8754, -11781, -6745, -6504, -8165, -9331, -13365, -7196, -5988, -11115, -10899, -14195, -7066, -5444, -9585, -9585, -10001, -6343, -4743, -6958, -7603, -9873, -6235, -4168, -6376, -6666, -12123, -7281, -4006, -7230, -6553, -13738, -10526, -4361, -9380, -7230, -11488, -15615, -5306, -12534, -8754, -8615, -9531, -6480, -9585, -8903, -6842, -7752, -6958, -6745, -7196, -6590, -7408, -6759, -6064, -6434, -8086, -8393, -6577, -7353, -6602, -13365, -10210, -6504, -10526, -6376, -12123, -11945, -6732, -12534, -5387, -8790, -15615, -6565, -9106, -5942, -9479, -7687, -5576, -4923, -10362, -7752, -3535, -3840, -1920, -2664, -2432, -788, -1616, -269, 35, -115, 743, 13, 29, 912, 614, 1152, 624, -1164, 438, 96, 421, 120, -4541, -1426, -1563, -1617, -1613, -12123, -5279, -4215, -5183, -4644, -8649, -28777, -7179, -6800, -7842, -8649, -11629, -9106, -6719, -7730, -6856, -11115, -9238, -7842, -6540, -5121, -9639, -7353, -9064, -6615, -4303, -8718, -6083, -9585, -7264, -4713, -8718, -6343, -9238, -7019, -6376, -9873, -8393, -9149, -6943, -7426, -13049, -10210, -10210, -8060, -7213, -28777, -7426, -14784, -11356, -8718, -14195, -6153, -11488, -14195, -12534, -15615, -6143, -8112, -11004, -7389, -17034, -6988, -7050, -10613, -5380, -10001, -8549, -7335, -12123, -5097, -7936, -11004, -8582, -12319, -6615, -7130, -15615, -9429, -9064, -14195, -7281, -15615, -8009, -8276, -8485, -8517, -11115, -6064, -9429, -6422, -11945, -9585, -5422, -11488, -6628, -15615, -8982, -6469, -12123, -7623, -10613, -8982, -11004, -11629, -7960, -9585, -9022, -9106, -9331, -7819, -9429, -8549, -6516, -8165, -8138, -9022, -7281, -6163, -8903, -9479, -8138, -6411, -6899, -11781, -10799, -7484, -6310, -8333, -10362, -10362, -7523, -6856, -9639, -7644, -10442, -8423, -7299, -9022, -6343, -12123, -10210, -7019, -8517, -5924, -14784, -12123, -6914, -9873, -6434, -28777, -13365, -7644, -15615, -8009, -13365, -12534, -9380, -14784, -10001, -9531, -10899, -11781, -12534, -10526, -8112, -10799, -13049, -10001, -10613, -7842, -13049, -11945, -8865, -9022, -7936, -28777, -11356, -10138, -7888, -8165, -10442, -12319, -14784, -7687, -8903, -8865, -17034, -12776, -8034, -11232, -8009, -12123, -17034, -7796, -15615, -6973, -9429, -11629, -7196, -9753, -6745, -8485, -8517, -7281, -8485, -7730, -8549, -8393, -8060, -8865, -9380, -9331, -9812, -9331, -10001, -9639, -10799, -10613, -10138, -12319, -10210, -13365, -10138, -10613, -15615, -11629, -17034, -10210, -11488, -11781, -10704, -15615, -10613, -12776, -10526, -10526, -11356, -11356, -28777, -11488, -12123, -9639, -11781, -12319, -28777, -14195, -9064, -11115, -9873, -10069, -15615, -9531, -11004, -10138, -7687, -15615, -10899, -12776, -11945, -7317, -11232, -13049, -28777, -12776, -8363, -9429, -12123, -11945, -12534, -11232, -8865, -10526, -9812, -11945, -14195, -9022, -9429, -9695, -11004, -14784, -10442, -9238, -11004, -11629, -10069, -4104, -8333, -5801, -9149, -9429, -4447, -14784, -5554, -9106, -8060, -4654, -13365, -5871, -6399, -6299, -4985, -10613, -6745, -5472, -5253, -5326, -10069, -8086, -5678, -5026, -5234, -10526, -10613, -6434, -5422, -4625, -9531, -13365, -7408, -6143, -3937, -6628, -8982, -8423, -7019, -3507, -5312, -7019, -9284, -8247, -3546, -5073, -5951, -9936, -10526, -4127, -5353, -5584, -11488, -14784, -4728, -5743, -6026, -11781, -15615, -4447, -6565, -7146, -9936, -10613, -4180, -8754, -8009, -9284, -8790, -5234, -12123, -8009, -9639, -8827, -8517, -8865, -8220, -11488, -8549, -9812, -6093, -6679, -11629, -5061, -5670, -3237, -3656, -4826, -2012, -1978, -693, -1030, -1746, -188, -34, 920, 530, -283, 484, 425, 1414, 892, -63, 72, -546, 703, -42, -1096, -1479, -3375, -1434, -2578, -3738, -4234, -11781, -4774, -8060, -10069, -7179, -8333, -5279, -15615, -8060, -7665, -8009, -6183, -17034, -6365, -7665, -9753, -9873, -11004, -5906, -8165, -8549, -8247, -8942, -5339, -10138, -5988, -7213, -8192, -4800, -13738, -5014, -8942, -7353, -4863, -9193, -5360, -14195, -6773, -5524, -8454, -6640, -7960, -6943, -6267, -10613, -8276, -6143, -7708, -6457, -12776, -8942, -5915, -8304, -6732, -7774, -8615, -6745, -9106, -7644, -6007, -8549, -8247, -10899, -8903, -6016, -9695, -9022, -13049, -9873, -7865, -12319, -8903, -12123, -12776, -11629, -10069, -9064, -9331, -12123, -9695, -7912, -8942, -7050, -8754, -9022, -7196, -7960, -5801, -8220, -9479, -7912, -7281, -5554, -10001, -9106, -10704, -7389, -6288, -17034, -8333, -28777, -8649, -7819, -10526, -7936, -28777, -12319, -8982, -8454, -7408, -13049, -15615, -9193, -8165, -6422, -8423, -10899, -10704, -8982, -5623, -7196, -10799, -14784, -10442, -5286, -8138, -14784, -9331, -12123, -5266, -10799, -15615, -7583, -12319, -5516, -7603, -10362, -7464, -10613, -6445, -5247, -9639, -7687, -9695, -8615, -4336, -10613, -7687, -10526, -12776, -4295, -13365, -8034, -17034, -28777, -4733, -12123, -9022, -10362, -15615, -5286, -9812, -10799, -7842, -11488, -5768, -8683, -14784, -7353, -9873, -6045, -8333, -14195, -8582, -8683, -6332, -8615, -9479, -13049, -7774, -7230, -9639, -7752, -17034, -7247, -8683, -12534, -7299, -12776, -7445, -8009, -17034, -7503, -11356, -8393, -6814, -11004, -8060, -9695, -10284, -6590, -9812, -9380, -8754, -13365, -7179, -10210, -11945, -8165, -14784, -8582, -11232, -13738, -8363, -12776, -11232, -10613, -15615, -9753, -10704, -28777, -10442, -15615, -11781, -9531, -11781, -10704, -11115, -10210, -8615, -9429, -9064, -9284, -8903, -7912, -9193, -7503, -8683, -8582, -7819, -9753, -6504, -9193, -8942, -8582, -9873, -6064, -10704, -9873, -10284, -9873, -6235, -13049, -11781, -14784, -11232, -7097, -13049, -14195, -14784, -13365, -8982, -11781, -17034, -10362, -11356, -13738, -11945, -10899, -8827, -9380, -15615, -13049, -8827, -8333, -8393, -12319, -13365, -8549, -8363, -8304, -14784, -13738, -9585, 8691, 10305, 10541, 8363, 6601, 7910, 9849, 9903, 7804, 6059, 5271, 8450, 7889, 6106, 4381, 2415, 6066, 4679, 3269, 1449, 3746, 3056, 3635, -135, -1732, 2977, 1488, 2915, -2326, -3242, 1084, 2377, 314, -3227, -10362, 1812, 3353, -1552, -1758, -9, 2880, 3452, -1317, 255, 2692, 2860, 2480, -2229, 1058, 3712, 1121, -330, -3824, 1567, 3828, -1906, -2217, -5784, 3306, 3465, -906, 2508, -5367, 4815, 2717, -2032, 4277, -3779, 5221, 1198, -297, 4506, -3801, 4428, -1244, 1773, 3323, -4874, 2258, 699, 1762, 222, -3574, -1859, 2634, -210, -3474, -1026, -4230, 2955, -6786, -395, 729, -3103, 1975, -3235, 766, 1489, -3182, 25, -913, 1107, 1108, -3036, -3247, -458, 987, -859, -2470, -3695, -1216, 718, -5214, -1939, 724, -3490, 430, -3417, -674, 1651, -3034, -301, -1909, 543, 121, -1499, -2123, -570, 478, -8220, -2148, -6422, 845, -1650, -2236, -1663, -7665, 1426, -28777, -1095, -287, -3016, 1119, -2076, -1716, -1664, -1746, 342, -150, -677, -8517, -2730, -131, 258, 982, -354, -7408, -391, -114, 1613, 886, -5109, -628, -244, 676, 383, -4412, -501, 496, -4067, -910, -6565, -777, 1177, -1882, -2829, -4412, -2807, 1366, 1056, -7960, -3401, -15615, 993, 1442, -4541, -2871, -2735, 13, 377, -1948, -930, -955, -888, -2300, -1862, -33, -836, -284, -10069, -3493, -756, -1612, 337, -5853, -4831, -1978, -2877, 10, -4500, -3692, -220, -4089, -1151, -4089, -2716, 1032, -5346, -2460, -2605, -2490, 888, -5646, -3606, -1341, -3621, -652, -3147, -5879, -839, -8112, -3903, -1432, -14195, -1252, -7445, -8165, -824, -8865, -2881, -4112, -13365, -1057, -7484, -5670, -3704, -5055, -1760, -6321, -6773, -4728, -2445, -2448, -4021, -9695, -5576, -1677, -2988, -2416, -8790, -4100, -1923, -3375, -1634, -4597, -3187, -2762, -2935, -1601, -3062, -3674, -4010, -2057, -2430, -2516, -5240, -5333, -1733, -4290, -2943, -6899, -5164, -2188, -6376, -4420, -13365, -4274, -3094, -5735, -6422, -6278, -4176, -3808, -4901, -8485, -3586, -5079, -4262, -4640, -11945, -3557, -6856, -4635, -4357, -7464, -6173, -8454, -4800, -3951, -5546, -13049, -7865, -4968, -3686, -5253, -6183, -6214, -5214, -3683, -5793, -5759, -5458, -5049, -3978, -6692, -8683, -6103, -4336, -4482, -7623, -10210, -8304, -3840, -4997, -8086, -5569, -11356, -4250, -5888, -7371, -4378, -9695, -5487, -7484, -6332, -4442, -7081, -6516, -9022, -6113, -5367, -6480, -6388, -9753, -6885, -7034, -7230, -6173, -9531, -9284, -9429, -7912, -6899, -8718, -14195, -28777, -8138, -10442, -8649, -10362, -7936, -8683, -11781, -11781, -10613, -5401, -8615, -8683, -8247, -9873, -4708, -7213, -8615, -5170, -7936, -5164, -6143, -9106, -4382, -6988, -6445, -5906, -9022, -4940, -5465, -8363, -6365, -8649, -6540, -4089, -5646, 5776, 7356, 3662, -4733, -891, 4819, 6828, 3205, -2859, 332, 1246, 5321, 1950, -203, -938, 82, 3287, -24, 509, -5103, 1880, 1533, -2011, -545, -3311, 673, -508, -1247, -2386, -1726, 81, -8517, -1443, -5299, -1130, 1969, 499, -263, -3964, -234, 2762, 3183, 1844, -1575, 614, 2807, 4262, 2043, -974, 942, 2151, 4793, -92, 1499, 666, 24, 4919, 621, 3218, 66, -5031, 4265, 3095, 3609, -451, 562, 2416, 3298, 3098, -804, 2856, -732, 1155, 2234, -976, 3584, -1030, -11945, 1723, -486, 3028, 96, 444, 1906, 586, 914, 578, 1841, 1995, 1404, -2605, 808, 1760, 1269, 1355, -1232, 521, 1411, -642, -42, -377, -578, 1605, -4723, -3383, -871, -1250, 2108, -9531, -3824, -2795, -475, 2321, -4559, -3168, -3526, -563, 1969, -3714, -4250, -1292, -2276, 950, -3316, -5380, -1071, -5266, -620, -2173, -6343, -3067, -3698, -2121, -1644, -5615, -7708, -1516, -2692, -2690, -6719, -3741, -222, -2179, -5960, -8982, -1137, 155, -1559, -5097, -3615, 536, -715, -1587, -3769, -1940, 1480, -4086, -1873, -4478, -1514, 1701, -7066, -1580, -7004, -1689, 1130, -2935, -1197, -12534, -2581, -372, -3468, -1499, -10526, -5319, -3175, -6256, -2664, -4550, -3748, -11004, -2422, -4049, -1393, -977, -6074, -513, -4215, -142, -642, -3843, -126, -2155, -431, -2592, -4149, -813, 157, -2058, -7179, -8247, -2589, 1296, -3417, -4123, -5145, -6183, 1086, -3378, -3968, -1775, -7371, -866, -4258, -3215, -509, -3985, -7984, -6388, -1246, -78, -2958, -3523, -9193, -662, -246, -3490, -1799, -11004, -1445, -1325, -5353, -2192, -11629, -3367, -3906, -4486, -3496, -12534, -5844, -6026, -2701, -4831, -12776, -7796, -4693, -2236, -5662, -10613, -6553, -5183, -2350, -6225, -9106, -5853, -6388, -2388, -6899, -9284, -7213, -6235, -2458, -8363, -8454, -9429, -5759, -2839, -11004, -6773, -9193, -4569, -3689, -7146, -6365, -11629, -3529, -4826, -5494, -7179, -12534, -3365, -5516, -6445, -8718, -7984, -3876, -4649, -11781, -9380, -5584, -4654, -3117, -7730, -11356, -4097, -5286, -2355, -5888, -15615, -3521, -5897, -2443, -5710, -8423, -3860, -7317, -2999, -5853, -6899, -5292, -9753, -3383, -5768, -7113, -8393, -11232, -2979, -5437, -8517, -11488, -14784, -2084, -4957, -10799, -7819, -9812, -1522, -4559, -11781, -6480, -7081, -1630, -4478, -8517, -6399, -6540, -2505, -4795, -6516, -7130, -7389, -4230, -5306, -5897, -7644, -9238, -6143, -5827, -6388, -7146, -10899, -5380, -6870, -7603, -6666, -9936, -4219, -9479, -8086, -6759, -8009, -3785, -12123, -7583, -7464, -6457, -3710, -8304, -7542, -8790, -5630, -3701, -7936, -8649, -8903, -5360, -3910, -10899, -13049, -6214, -5494, -4679, -11004, -11232, -4795, -5862, -6321, -7562, -7484, -4478, -6288, -9331, -7130, -6492, -4901, -6113, -12776, -8549, -6457, -2505, -4842, 2010, 3905, 962, 931, -1150, 2331, 2455, 4825, 2939, 1276, 2948, -12123, 6643, 3103, 2313, 3325, 1971, 6810, 1326, 2360, 3195, 3111, 5724, -1206, 1605, 2525, 1581, 3512, 149, 81, 1509, 532, 1417, -60, -2447, 528, 2746, 835, 1160, -4805, -479, 2964, 1023, 3140, -3042, -3788, 1231, 2606, 3882, 269, -2610, 1012, 3180, 3560, 2815, 1979, 2340, 1817, 2254, 3991, 3427, 1267, 245, -174, 3757, 3255, -3526, 2637, -1163, 1815, 1866, 974, 3641, 347, -1141, 667, 2125, 4254, 427, 760, 598, 835, 5135, -1214, 1375, -187, -3487, 5450, -4168, 602, -1979, -7687, 4788, -1616, -490, -3554, -4153, 3180, 491, -645, -4274, -3927, 1757, 1151, -23, -3232, -5933, 2244, 860, 300, -1203, -9429, 2633, 495, -227, 95, -3069, 1981, 450, -1686, 478, -1450, -36, -83, -3830, -208, -1324, -4644, -1547, -6045, -2422, -1701, -6310, -3964, -8485, -6590, -855, -2226, -7019, -6628, -3571, 705, -1452, -7542, -4184, -1956, 1596, -3042, -5915, -3420, -1749, 1607, -5576, -4592, -3827, -2578, 742, -2460, -3203, -4611, -4810, -1168, -1341, -1930, -4361, -12123, -6214, -2116, -1302, -3853, -5768, -4307, -7130, -1501, -4191, -2182, -743, -4416, -1949, -4455, 17, 415, -2943, -2045, -3103, 1169, 582, -6267, -2578, -2211, 1153, 183, -2608, -3025, -2472, -375, -695, -344, -2277, -4089, -3014, -1815, -394, -2603, -10899, -1472, -1127, -2189, -5253, -4425, -875, 327, -5145, -15615, -1682, -2442, 743, -4708, -11629, -1515, -5615, 166, -3540, -11115, -3971, -4340, -688, -2787, -9639, -10799, -4184, -1343, -2785, -13365, -3744, -7389, -2690, -4093, -6246, -2950, -7523, -5509, -7066, -4303, -3600, -3161, -7562, -6814, -4348, -4451, -1787, -8060, -5827, -5776, -4601, -1865, -7623, -5897, -7464, -4495, -3365, -4907, -5339, -6928, -4946, -7583, -3817, -3808, -5844, -5793, -9585, -3692, -2564, -5380, -5273, -6516, -3425, -2257, -5524, -4104, -7730, -3001, -2971, -6194, -3457, -10613, -3433, -4161, -6928, -3342, -6773, -5718, -4373, -7113, -3763, -5970, -8363, -3889, -6786, -5152, -6988, -4635, -3830, -6590, -8865, -8982, -3482, -4683, -7004, -12534, -10210, -3656, -6376, -8718, -8165, -10284, -4399, -6354, -11488, -7230, -8112, -5085, -5189, -7562, -7247, -6083, -5836, -5133, -5415, -8034, -5494, -6615, -6173, -4842, -9936, -6343, -6745, -7819, -5472, -12123, -7281, -6074, -8827, -6943, -11945, -5751, -5472, -8363, -8247, -10284, -4564, -5710, -7281, -8034, -8865, -4207, -7130, -6343, -7247, -8112, -4348, -8942, -5844, -7081, -7665, -4382, -8517, -5599, -7708, -7130, -3873, -8220, -5451, -9380, -6692, -3071, -8982, -6204, -14784, -6759, -2517, -9429, -9429, -11945, -7113, -2597, -7842, -14195, -8517, -7603, -3624, -7034, -10799, -7936, -8220, -6054, -7644, -13365, -10284, -7196, -9106, -9193, -3674, -8086, -7445, -9812, -10799, -4541, -5997, -6153, -8086, -7426, -7623, -5020, -4504, -6814, -5451, -7299, -4573, -3501, -6759, -4779, -4473, -4266, -3306, -7542, -5306, -3920, -4046, -3766, -8454, -7097, -4940, -4142, -4635, -8683, -10138, -7687, -4907, -5451, -8549, -10210, -10526, -6540, -6434, -7984, -8192, -7936, -6640, -8549, -7213, -7230, -7281, -4929, -11004, -7066, -7623, -8718, -4323, -7888, -8615, -9812, -9331, -5073, -5970, -11945, -15615, -6577, -7796, -5037, -8615, -13738, -5437, -28777, -4611, -7230, -12776, -5623, -8192, -4513, -6745, -12534, -6973, -6492, -5273, -6173, -11232, -10284, -6235, -7484, -4963, -9695, -12123, -7179, -8790, -3853, -9193, -7097, -11115, -7984, -3701, -9873, -5319, -11004, -10001, -4805, -12319, -5115, -8112, -15615, -7230, -12319, -6267, -8009, -8683, -9531, -10526, -9022, -8485, -7213, -9812, -8827, -14784, -9380, -7130, -10899, -7426, -28777, -14784, -7888, -11781, -6759, -12534, -9479, -9238, -12123, -6692, -10138, -6267, -11356, -10526, -7146, -8517, -5061, -13365, -8903, -8549, -7583, -4853, -12319, -9331, -12123, -7389, -5444, -9936, -10899, -12776, -8060, -7004, -8754, -9064, -9193, -9639, -7562, -9695, -7842, -8393, -11232, -6064, -13049, -7819, -8423, -11356, -5615, -9331, -8247, -8615, -10613, -6469, -6719, -9193, -10069, -9331, -7353, -5208, -10442, -10362, -8304, -6602, -4620, -9812, -8393, -7819, -5879, -4985, -7708, -8304, -8034, -5686, -6256, -6267, -9695, -9022, -5638, -8485, -5960, -10613, -11781, -5654, -10613, -6773, -9531, -17034, -5743, -8549, -8683, -8454, -11004, -5592, -6615, -10526, -9106, -10138, -4874, -5924, -8942, -13365, -10799, -4112, -6246, -7730, -10704, -10899, -3893, -7426, -7623, -8423, -9695, -4433, -8192, -8454, -8086, -9193, -5862, -7774, -10704, -8138, -9639, -7708, -8086, -13049, -8060, -10613, -7730, -10704, -10001, -8220, -10613, -7162, -13365, -8683, -8942, -9479, -7484, -9429, -9193, -10138, -8718, -8247, -8582, -11488, -11004, -8718, -8649, -8827, -11945, -10704, -8615, -8549, -9193, -11115, -10069, -8754, -8220, -10284, -11629, -9479, -10210, -7426, -14784, -12319, -8942, -11945, -6628, -11629, -12776, -8615, -10442, -6434, -7708, -17034, -8517, -10442, -7213, -6480, -17034, -8393, -14195, -9695, -6504, -12534, -8192, -14195, -13365, -7281, -13738, -7687, -10069, -9639, -8333, -28777, -7230, -9380, -8517, -9479, -10210, -7113, -9695, -9064, -11232, -8192, -7299, -10526, -9284, -12319, -7960, -7426, -12534, -7984, -11004, -9193, -7819, -28777, -7730, -9695, -11488, -8903, -14195, -8718, -9585, -14784, -11356, -14784, -10138, -10704, -13365, -15615, -12319, -12534, -13049, -10362, -28777, -9936, -28777, -12534, -9238, -28777, -9479, -10799, -11004, -9238, -17034, -10001, -9585, -11004, -9812, -14195, -10704, -10799, -11945, -11629, -12776, -11781, -28777, -10799, -14784, -12534, -13738, -17034, -8982, -14195, -14784, -15615, -11629, -8192, -13049, -17034, -17034, -5554, -5502, -11115, -10284, -6759, -6153, -5472, -9531, -8790, -7371, -6973, -6492, -8220, -8138, -7562, -8112, -8718, -7562, -7936, -7050, -9022, -9873, -7819, -8086, -7542, -9284, -8423, -8683, -8790, -9022, -9064, -6958, -9479, -9753, -9380, -8942, -6074, -10138, -10001, -8790, -8220, -5997, -11629, -9479, -8485, -7353, -6540, -9429, -9106, -8517, -7752, -7371, -6786, -7912, -9585, -10704, -8582, -5862, -6577, -11232, -15615, -12123, -6492, -6163, -12534, -10704, -12319, -9380, -6615, -12776, -10704, -8942, -28777, -7371, -12776, -11232, -8086, -9812, -7687, -11945, -10526, -6914, -7888, -8138, -10799, -10442, -5879, -6928, -9639, -11781, -8827, -5853, -6332, -10362, -13365, -6870, -6602, -5970, -8333, -8790, -5988, -7984, -5818, -7583, -7523, -6016, -11115, -5942, -8718, -7865, -6653, -9380, -6692, -12534, -8363, -7426, -7445, -9429, -13049, -7523, -7665, -8034, -12776, -13049, -6469, -7665, -9585, -7865, -17034, -5979, -8192, -8060, -7335, -14784, -6434, -9479, -7665, -9149, -11629, -7408, -10613, -9193, -15615, -10069, -7081, -10210, -12776, -15615, -8942, -6653, -9531, -14195, -11356, -8276, -7281, -9064, -17034, -8423, -7730, -8165, -8683, -12776, -6928, -6943, -7888, -8138, -9380, -6973, -6422, -7562, -7542, -8615, -9064, -6516, -8220, -7484, -10001, -13049, -7146, -9936, -8165, -13738, -10526, -8086, -9695, -9149, -11945, -11115, -8790, -7865, -9479, -9531, -12776, -8903, -7130, -8485, -7503, -9753, -8517, -7774, -7644, -6376, -7865, -7888, -10069, -7888, -6204, -6719, -7371, -28777, -9936, -6958, -6615, -7583, -10069, -11488, -8582, -7912, -8827, -8034, -8086, -11232, -10284, -11629, -7912, -6842, -28777, -10284, -28777, -9531, -6914, -10704, -9936, -17034, -9585, -8112, -7960, -10362, -14195, -7912, -10799, -7819, -10442, -12776, -7888, -13738, -10210, -9149, -12776, -9873, -9106, -15615, -8363, -12776, -12776, -7353, -11232, -9284, -12123, -10899, -7389, -10526, -14784, -10799, -9149, -8485, -10799, -12319, -9639, -8192, -7464, -13365, -9238, -9531, -7774, -6422, -12776, -8615, -11004, -7960, -6828, -9585, -8615, -14784, -8865, -8517, -9585, -8827, -17034, -10526, -10362, -12123, -9639, -12123, -9873, -10138, -17034, -11629, -9331, -7796, -9149, -12776, -13365, -8086, -6705, -9429, -11488, -11629, -8060, -6705, -11232, -11115, -11004, -9022, -8165, -15615, -11232, -11115, -10526, -13049, -28777, -13738, -11781, -12534, -11488, -28777, -28777, -11629, -28777, -9531, -13738, -11115, -10799, -12319, -9873, -12123, -9639, -9639, -9531, -10210, -11945, -10001, -9064, -8982, -9531, -11232, -11115, -9106, -10069, -8363, -8982, -9812, -9331, -12776, -7865, -7503, -7984, -9238, -17034, -8485, -6899, -7113, -9695, -14195, -10362, -7081, -7019, -11488, -11115, -11232, -7819, -7542, -15615, -9936, -10210, -8982, -8683, -17034, -9753, -9585, -10799, -10704, -17034, -10210, -9106, -15615, -13365, -17034, -10899, -8790, -12776, -13365, -14784, -11356, -9022, -9429, -13365, -13049, -12534, -9531, -9331, -9695, -11629, -10362, -11945, -10001, -13738, -14195, -12776, -11004, -7034, -14784, -14195, -9106, -12776, -5960, -10069, -9873, -7353, -28777, -6035, -8649, -6828, -6332, -9753, -5970, -9238, -5531, -5759, -7426, -5726, -14784, -5109, -5897, -6745, -6492, -9531, -5299, -6745, -7081, -8982, -6553, -5702, -7623, -8649, -11945, -5654, -6113, -7503, -9753, -11945, -5888, -7034, -6045, -7687, -11115, -7317, -9284, -4901, -6457, -8276, -11356, -11488, -4759, -6026, -7019, -12123, -9531, -5630, -6045, -7004, -8009, -8827, -7464, -6365, -7644, -6842, -9106, -10210, -6492, -8582, -7213, -9695, -15615, -5988, -9812, -7708, -9639, -13365, -5480, -9695, -6256, -7730, -8582, -5085, -7623, -5472, -6225, -6640, -4693, -6958, -6354, -6113, -6204, -4464, -8304, -8454, -7960, -6828, -4460, -14195, -8333, -10899, -8086, -4759, -11781, -8393, -8718, -9284, -5569, -9064, -8903, -9479, -9639, -7019, -7796, -7066, -15615, -8754, -8942, -6653, -5933, -10799, -8034, -11356, -5879, -6026, -8649, -7353, -28777, -6064, -6786, -7353, -7034, -9585, -7583, -7247, -6759, -7912, -6528, -9639, -6800, -7130, -11356, -5516, -9429, -6225, -8165, -12534, -5853, -10069, -6204, -8827, -10613, -6842, -11781, -6870, -8649, -14784, -7665, -13365, -7960, -8393, -10613, -9149, -14784, -8220, -8683, -6914, -10069, -11781, -8009, -9479, -5678, -8060, -10138, -9193, -8549, -5726, -7752, -10613, -11356, -6828, -6870, -9639, -13365, -9753, -6007, -8615, -9873, -28777, -9238, -6299, -8649, -8393, -12319, -8485, -7730, -8423, -9429, -9284, -6745, -9873, -9429, -13049, -7445, -5718, -11488, -11115, -11232, -6388, -5561, -12776, -13738, -10138, -6083, -6026, -12319, -12319, -10442, -6267, -6692, -10799, -9429, -8903, -6565, -6732, -10284, -9149, -7264, -6928, -5951, -10284, -11004, -6615, -7936, -4885, -10069, -15615, -6745, -9936, -4180, -10899, -11004, -7247, -12776, -4250, -17034, -9531, -7644, -15615, -5286, -11232, -9812, -7984, -11781, -7213, -8683, -11781, -8790, -9695, -8112, -8754, -17034, -9106, -8982, -7912, -11629, -12534, -8754, -8485, -8683, -14195, -10799, -9238, -7984, -10704, -11629, -9873, -9531, -7936, -12319, -12776, -9106, -9479, -7912, -12534, -14784, -9022, -11945, -7984, -14784, -12534, -9639, -15615, -8363, -28777, -10138, -9639, -9936, -9064, -12776, -8304, -9479, -8549, -8517, -11356, -7299, -10210, -8034, -7623, -11004, -7179, -11115, -7523, -7842, -10001, -7796, -10613, -7408, -9695, -9380, -9531, -10526, -7912, -14195, -9812, -13738, -11356, -10001, -28777, -11781, -17034, -13738, -28777, -28777, -14195, -11945, -28777, -9429, -13365, -12123, -10138, -14784, -7708, -12534, -10001, -9106, -12776, -7936, -17034, -9022, -8790, -11356, -9479, -14195, -9022, -9380, -10704, -11629, -10613, -10001, -10613, -10526, -11115, -10362, -12123, -10799, -10284, -9531, -11629, -13738, -10138, -10284, -8827, -15615, -11629, -10704, -10704, -9284, -17034, -11004, -12319, -11629, -10613, -12123, -12534, -12319, -11488, -12534, -7912, 8129, 8421, 4616, -91, -5208, 7667, 8075, 5018, 389, -3412, 6217, 7030, 5460, 639, -1710, 3433, 5274, 5332, 427, 1114, -2217, 2927, 4709, 850, 3155, -662, 578, 3903, 1078, 3852, 970, -1786, 2948, -412, 2963, 594, -8393, 1261, -3701, -587, -1247, -2245, -2217, 919, -951, -2749, 439, -2153, 2934, 1518, -1398, 1739, -17, 3694, 1447, 72, 2577, 49, 3955, 134, 1663, 2943, -1025, 3872, -1774, 2634, 2519, -565, 3053, -2194, 2594, 766, 973, 632, -985, 1323, -4518, 1671, -1203, -1142, -2094, -979, 1525, 2144, -2555, -5183, 1761, 946, 3236, -3748, -1343, 2641, 1113, 2723, -8549, -981, 2386, 2234, 930, -3067, -1508, 953, 3135, -57, 413, -727, -2273, 3407, -346, 1639, -181, -8192, 3019, -5061, 1671, -1185, -7113, 1992, -1153, 673, -3436, -10799, 44, 2113, -1646, -1458, -4278, -4527, 3050, -5444, 107, -2885, -2182, 2826, -4064, 295, -3540, 293, 1696, -1480, -95, -2478, 637, -295, -243, -21, -812, 326, -1317, -374, 306, -1037, 1164, 100, -1299, 74, -4901, 2180, 1009, -1759, -752, -3763, 2296, 1240, -832, -1872, -349, 1388, 1079, 676, -3339, 2, -304, 441, 1219, -6064, -1645, -1207, -1156, 393, -7230, -5531, -861, -4640, -1244, -2071, -3543, -1275, -7603, -1078, 108, -2222, -3080, -4097, -773, 777, -2339, -5979, -2231, -2156, 148, -2924, -7004, -1341, -6958, -2383, -3947, -5458, -1268, -7583, -11232, -4195, -3471, -1645, -5026, -3344, -2294, -2049, -2220, -4123, -2877, -1233, -1253, -2783, -2232, -5472, -1025, -1301, -2756, -872, -10284, -589, -2064, -2294, -487, -8247, 466, -3187, -1788, -1037, -6958, 1229, -5480, -1302, -2305, -3225, 1182, -5139, -1156, -3566, -1562, 155, -1846, -1830, -5008, -1327, -2032, -539, -3886, -6679, -2234, -5487, -243, -6235, -4784, -4157, -5176, -421, -4669, -3641, -6528, -3220, -884, -4442, -3751, -8112, -2661, -1820, -5592, -5014, -8718, -3404, -3316, -6800, -7936, -8754, -5214, -3518, -7865, -7984, -10210, -6054, -2198, -10899, -8086, -14195, -5554, -1443, -11004, -14195, -9936, -4455, -1409, -6553, -6705, -8982, -2877, -1998, -3798, -5247, -10001, -1698, -3056, -1842, -6103, -11232, -1157, -3830, -744, -9429, -13738, -1310, -3612, -526, -13365, -9873, -2330, -3121, -1324, -7426, -5654, -4307, -2992, -3422, -4821, -3701, -4790, -3306, -6267, -3704, -2889, -3360, -3883, -5879, -3971, -3089, -2819, -4323, -6113, -5451, -4532, -3201, -4373, -7583, -6422, -7984, -4278, -4331, -7687, -6054, -13049, -5844, -4664, -6885, -5299, -13738, -6074, -6045, -5768, -4315, -8865, -4649, -10210, -4764, -3937, -6640, -4089, -11232, -4869, -4303, -6256, -4286, -7445, -6800, -5247, -6759, -4327, -6256, -15615, -6679, -8276, -4145, -5055, -7081, -8276, -12319, -4509, -4286, -5031, 5810, 2751, -3003, 7114, -1794, 5418, 2238, 3725, 6585, 1614, 4093, 685, 5400, 4857, 2891, 1271, 812, 4932, 2564, 1994, -6143, 2495, 2201, 3529, -1765, -4078, 2793, 446, 4063, -5646, -2043, 1563, 3779, 2944, -1987, -73, -741, 4886, 951, -3641, 1109, 535, 4795, 682, -9380, 1309, 2366, 3656, -273, -2364, 977, 3028, 1304, -5924, -327, 785, 2696, 784, -983, 822, 1122, 2017, 3220, 1278, 1077, 1885, 2691, 4575, 1727, 180, 2938, 3463, 4949, 1296, -1754, 3983, 2996, 4442, 255, -2783, 4638, 729, 2959, -985, -1745, 4593, -3589, 119, -174, -1396, 3498, -1326, -3201, 2031, -2305, 626, -854, -706, 3390, -4017, -1043, -2162, 473, 3675, -6786, 1434, -4863, -47, 3198, -6914, 1734, -11488, -1307, 2907, -2245, 728, -2637, 106, 2779, -1092, -103, -201, 1108, 1615, -884, 94, 218, 542, -373, 777, 109, -1231, -1205, 134, 1873, 98, -2015, -1610, 41, 1161, 808, 797, -1238, -2432, -2831, 1786, 2177, -2685, -10526, -3615, 2351, 2540, -3112, -6504, -1518, 2203, 2385, -201, -5480, -4352, 1230, 1832, 710, -5776, -4679, -322, 609, -284, -9238, -2265, -1097, -1628, -4564, -10442, -2677, -516, -4230, -4460, -6814, -1613, 538, -4810, -1797, -7503, -42, 1397, -6064, -2071, -10001, 538, 1530, -11356, -3814, -2455, 176, 566, -5465, -5109, 413, -1173, -2320, -3175, -3957, 1652, -3060, -13738, -3301, -2560, 1715, -3896, -3933, -4759, -1663, 636, -4262, -3641, -3449, -1377, -1990, -4336, -5121, -2095, -1987, -7299, -4064, -6225, -2019, -3763, -4795, -3479, -5437, -3154, -4115, -3618, -2863, -4123, -6016, -2204, -3776, -3058, -3656, -8615, -1599, -4089, -3873, -4307, -7019, -2412, -4195, -3529, -6565, -7687, -5014, -4713, -2694, -12123, -8903, -9936, -6653, -2657, -4795, -8754, -5444, -11629, -3347, -2709, -9531, -3751, -8304, -4478, -2605, -9812, -3237, -7004, -5494, -4078, -5458, -3286, -7019, -5702, -4688, -3609, -4161, -7019, -5401, -3010, -3449, -6958, -6628, -5516, -1701, -4473, -8982, -5970, -6399, -549, -6299, -8393, -5509, -7623, 134, -8086, -8363, -5662, -7523, 20, -8549, -3560, -6064, -6310, -985, -7708, -2178, -5853, -5638, -2893, -5451, -3085, -6411, -5743, -5615, -4527, -5472, -9936, -6133, -9106, -5827, -2956, -11945, -5970, -13365, -12319, -1656, -6885, -5273, -13738, -9585, -1994, -4319, -4951, -10442, -7730, -3644, -2833, -5710, -7247, -6299, -6842, -2720, -6565, -5380, -5306, -28777, -4315, -5546, -4644, -5702, -8423, -9149, -5279, -4659, -7796, -6133, -6842, -6885, -4698, -7842, -5662, -5444, -11781, -4161, -5654, -6602, -6988, -9531, -3465, -5164, -6705, -10210, -7623, -3324, -6016, -4810, -6615, -7034, -4180, -7752, -4060, -5408, -6885, -6183, -8754, -4683, -5576, -7066, -8982, -7730, -6540, -6577, -7426, 7775, 3486, -3409, 6394, 8147, 7302, 2951, -449, 6089, 7915, 5722, 1586, 1184, 5311, 7244, 2010, 796, 1186, 4451, 6152, -1259, 1258, -143, 3733, 4391, 3176, 1783, -1680, 2617, 2593, 4027, 2024, -818, 940, 4178, 3651, 1508, 642, 1854, 4899, 3008, -50, 1485, 2837, 3291, 2594, -1202, 1176, 2496, -949, 1762, -714, -1098, 1766, 3303, -217, -906, -9193, 1214, 4537, -4536, -1948, -20, 431, 4869, -3051, -3428, 2048, 862, 5421, 9, -5654, 2373, 1696, 5574, 1413, -4912, 1299, 1275, 5145, 1772, -1607, -880, -945, 4881, 977, 366, -679, -4644, 4832, -1743, 1576, 555, -2873, 4192, -3360, 2583, 878, -1392, 2959, 293, 3527, 613, -306, 2757, 1714, 4104, 309, -101, 3943, 2141, 4010, 797, -980, 4874, 1935, 3045, 1596, -2488, 4965, 1063, 1165, 1614, -3301, 3808, -674, -618, 227, -2893, 170, -3163, -1216, -4382, -2688, -1249, -2943, -2112, -4060, -3407, 1858, -1005, -1935, -613, -2294, 1852, 326, -1055, 170, 94, 143, 1129, -904, -427, 1297, -2583, 1531, -1292, -2635, 1298, -3665, 1668, -2020, -7730, -15, -2960, 1607, -2366, -12123, -3208, -2994, 1257, -2372, -7196, -4491, -4108, 349, -1875, -2801, -2228, -5312, -1377, -277, -804, -1556, -4754, -2490, 165, 258, -1644, -2973, -1534, -1685, 980, -2268, -1210, -632, -6666, 1193, -3923, -272, -311, -1448, 502, -7960, -698, -1348, -619, -1335, -4357, -3680, -5836, -1920, -3479, -2168, -7230, -5801, -3846, -3417, -2079, -2309, -3396, -3523, -3808, -3776, -2241, -4226, -3738, -4601, -7335, -4912, -6235, -3606, -4254, -8363, -3158, -6278, -2698, -4723, -6278, -739, -4569, -3433, -7230, -3644, -133, -3792, -7503, -9936, -2613, -839, -4555, -5988, -9106, -3357, -2545, -6504, -4654, -7984, -6103, -3208, -4764, -6225, -6365, -5401, -2424, -2701, -6899, -6800, -3316, -2280, -2060, -6628, -13365, -2724, -2745, -2776, -6745, -7583, -2871, -3360, -5444, -3735, -4985, -3254, -4211, -14784, -2288, -4219, -3078, -6214, -6310, -2404, -4010, -2121, -10362, -5049, -3913, -3957, -1096, -9193, -5273, -7097, -3840, -438, -9936, -6399, -12319, -3326, -169, -11232, -8615, -11945, -2688, -95, -10001, -10210, -11488, -2409, -150, -14195, -8138, -11115, -2670, -566, -5924, -7523, -10613, -3354, -1602, -3430, -7774, -10001, -3940, -3354, -2922, -7408, -10284, -3947, -5662, -3589, -6113, -9429, -4112, -8517, -4064, -5109, -6988, -5067, -13738, -4089, -4907, -5879, -6628, -12319, -5394, -5718, -6540, -7408, -10799, -8138, -8009, -9429, -7317, -10284, -5546, -14784, -7179, -8304, -7888, -4064, -8754, -4606, -10210, -6885, -4100, -6163, -3665, -7146, -7687, -5319, -5292, -3837, -5444, -11781, -8454, -5444, -4997, -5444, -10284, -13365, -6528, -6411, -6679, -6928, -8423, -8865, -7113, -7960, -5827, -8034, -8393, -8903, -5516, -4659, -4713, -8982, -7464, -6492, -6480, -5422, -11232, -8363, -6856, -7426, -6842, -6666, -11488, -6745, -5494, -8485, -4438, -28777, -7196, -4718, -8827, -3766, -12123, -8827, -5170, -7888, -3856, -8615, -10613, -6814, -7034, -4024, -6457, -10284, -10138, -7004, -4145, -5127, -8754, -13365, -7484, -4901, -4826, -7426, -11488, -6958, -7066, -6035, -7335, -10704, -5694, -12776, -10442, -7445, -9695, -5091, -13365, -9479, -6640, -8517, -5158, -9695, -6457, -6035, -7542, -5844, -7335, -5592, -6225, -6958, -7408, -6173, -5678, -7796, -6602, -9193, -6745, -6411, -11781, -6786, -11629, -10362, -6666, -6163, -7960, -8790, -4869, -4536, -2833, -6422, -3989, -2273, -2716, -1138, -3641, -1965, -1694, -2068, -603, -2534, -1450, -2610, -2617, -1166, -2945, -2211, -4416, -4311, -2994, -4963, -4455, -5133, -5818, -6692, -9238, -8582, -5592, -5339, -10362, -13049, -10704, -7335, -5465, -8718, -11781, -11115, -9585, -6928, -9380, -10284, -14195, -9064, -8165, -11115, -10442, -17034, -8423, -6640, -10799, -13365, -13738, -8827, -5401, -9331, -11781, -13365, -8754, -5353, -8220, -9193, -15615, -8034, -6800, -7984, -8138, -13049, -8276, -9331, -8363, -7960, -12534, -9873, -9753, -7066, -8192, -14195, -12319, -10138, -5888, -8009, -14784, -12776, -10362, -6074, -8615, -13049, -9479, -7819, -7665, -12319, -15615, -7162, -6759, -10526, -11004, -17034, -6194, -7464, -12776, -8903, -14784, -6183, -9331, -10210, -10442, -28777, -6288, -9479, -8454, -15615, -10001, -6143, -8393, -8582, -14784, -7665, -6083, -7523, -10526, -17034, -7752, -6653, -6615, -17034, -10526, -10799, -8790, -5960, -12123, -9149, -11232, -12534, -6183, -8333, -9479, -7503, -8034, -7774, -6516, -9873, -6343, -6719, -11781, -5554, -10799, -6045, -6828, -8517, -5121, -14784, -6204, -7796, -6411, -5103, -14195, -6388, -9695, -6246, -5662, -11945, -6422, -10284, -7603, -7034, -11945, -6828, -8086, -10613, -9022, -11115, -8485, -6973, -13738, -10284, -9873, -14195, -7034, -28777, -11356, -9238, -11488, -7687, -12319, -13049, -8942, -8423, -8138, -9479, -11781, -8982, -7842, -8333, -9193, -9193, -9531, -8423, -9022, -10613, -8192, -10526, -9695, -9812, -11945, -8304, -11356, -8982, -9695, -10362, -8982, -10613, -7888, -9238, -9380, -8942, -9193, -8276, -9193, -8827, -8363, -8086, -11356, -10138, -8247, -7865, -8009, -17034, -12776, -8060, -7912, -9380, -11945, -14195, -9022, -8827, -13365, -13738, -12319, -11945, -10069, -15615, -17034, -12319, -28777, -9695, -13738, -10899, -11629, -15615, -8982, -15615, -10284, -9812, -15615, -9479, -17034, -12123, -8615, -12776, -10526, -14195, -17034, -8304, -11356, -11115, -10799, -28777, -9149, -11356, -12319, -8982, -15615, -11232, -11356, -15615, -8276, -12534, -13049, -11115, -17034, -8903, -12123, -14784, -11356, -13365, -11356, -13738, -15615, -13738, -10284, -28777, -28777, -14195, -17034, -8683, -12534, -17034, -11488, -12776, -8485, -11004, -13365, -10899, -11004, -9429, -10613, -11781, -10069, -6553, -8903, -8865, -7353, -9284, -6332, -9812, -14784, -7281, -7708, -7842, -8942, -8982, -9064, -6343, -11115, -8517, -7281, -8393, -5933, -7819, -8903, -7644, -4901, -6786, -6615, -8942, -10210, -3833, -9022, -7353, -8485, -13365, -4469, -11488, -9531, -8649, -9429, -6856, -9479, -12123, -9695, -8582, -8423, -6628, -10284, -9936, -9531, -6365, -4985, -8009, -9238, -12319, -5810, -4319, -6973, -9193, -17034, -6457, -4238, -7196, -9531, -15615, -8192, -4327, -8790, -8276, -10442, -14195, -4327, -12123, -7004, -7464, -9695, -4395, -14784, -6411, -6354, -6434, -5133, -10799, -5437, -6321, -5607, -8220, -5888, -3589, -5888, -6828, -8649, -2902, -1778, -3641, -8276, -3989, -1348, -695, -2039, -4082, -2509, -972, -555, -1717, -2545, -2517, -1735, -1415, -2737, -2841, -3707, -3804, -3373, -4555, -4826, -5888, -7644, -6469, -4527, -8517, -8138, -17034, -10442, -4203, -13365, -10442, -12534, -12319, -5085, -9531, -11781, -8865, -11781, -7162, -7426, -9022, -7130, -10362, -10799, -7542, -7196, -6246, -8827, -28777, -9531, -6504, -6457, -8247, -28777, -14784, -6842, -8276, -9380, -11004, -14784, -7912, -13049, -17034, -7230, -11115, -8865, -11356, -10001, -5630, -10001, -9479, -9695, -7665, -5584, -9936, -9022, -9639, -7583, -6914, -10069, -7335, -9429, -9022, -8942, -7819, -6153, -8865, -9936, -9639, -6035, -6143, -8942, -9022, -9753, -5502, -7774, -9429, -8649, -8060, -5997, -12776, -10069, -8333, -6973, -7264, -11488, -10613, -7562, -7162, -8718, -9812, -10001, -6988, -8454, -10069, -10362, -9380, -7034, -10613, -11945, -11232, -8304, -7888, -14195, -10899, -11488, -6856, -9753, -14784, -9380, -11629, -6235, -11356, -11004, -9639, -12319, -6814, -9284, -9284, -10704, -14784, -9331, -7230, -8718, -10442, -28777, -15615, -6103, -8423, -11356, -12776, -8903, -5970, -8165, -17034, -12534, -7389, -7019, -8304, -13738, -14784, -7752, -9531, -8790, -11115, -12123, -8790, -9585, -8865, -10442, -10138, -8517, -8086, -8549, -9936, -9149, -8220, -7888, -8363, -8865, -7960, -8423, -8247, -8827, -7796, -7179, -8060, -8615, -10526, -7503, -6800, -7264, -9106, -14784, -8517, -6679, -7162, -9873, -13738, -12123, -6719, -8009, -10138, -11488, -14195, -6958, -9753, -9531, -11004, -9429, -7583, -11004, -8982, -11232, -8754, -9193, -10210, -8393, -11945, -9639, -13365, -10362, -7819, -12319, -10442, -13049, -12319, -8112, -13738, -10704, -9936, -28777, -9753, -14784, -12123, -9479, -17034, -14784, -12776, -13738, -10069, -14784, -14195, -11356, -11781, -11488, -14195, -12123, -10210, -9022, -14195, -11356, -12534, -9193, -7445, -11232, -8982, -13365, -8718, -7130, -8393, -7842, -11945, -9022, -8060, -7644, -7936, -10704, -9873, -9812, -8454, -9585, -9531, -9238, -11232, -10899, -13738, -8942, -8165, -12534, -14195, -28777, -9064, -7865, -13738, -11488, -15615, -9585, -8363, -15615, -9479, -15615, -9753, -9753, -15615, -8982, -17034, -10613, -11781, -13049, -10001, -15615, -12534, -12776, -12776, -13049, -8138, -7865, -5554, -10001, -8649, -9193, -7842, -5818, -9429, -6653, -9936, -7888, -6679, -7426, -6628, -10526, -7162, -8517, -6640, -7523, -8060, -5615, -11629, -6299, -7335, -7912, -4336, -12776, -5615, -8276, -10442, -3923, -11232, -4274, -28777, -8220, -4611, -9284, -3137, -7464, -6235, -6870, -8165, -2801, -5539, -5751, -11232, -7842, -3311, -5592, -5933, -11781, -7097, -4532, -7034, -6235, -10069, -6540, -6163, -9936, -6194, -7066, -7445, -7865, -13365, -5862, -5387, -10526, -8649, -13049, -5678, -5055, -11232, -8454, -11945, -5818, -5897, -8517, -8615, -10526, -6773, -7317, -6411, -8220, -7335, -7796, -6007, -4149, -5584, -3982, -4616, -3930, -2168, -3281, -2036, -2698, -2823, -1128, -1967, -1420, -2253, -2741, -1185, -1613, -2040, -2889, -3920, -2462, -2334, -3971, -4336, -6365, -5234, -4386, -7562, -6267, -6278, -10138, -7623, -14784, -7503, -5599, -9479, -6773, -13738, -6074, -6856, -7281, -5924, -11004, -4880, -10362, -5451, -6565, -9531, -4664, -28777, -4299, -8423, -8790, -5380, -17034, -4075, -9873, -8549, -7066, -28777, -4946, -9936, -8304, -9531, -28777, -7196, -10442, -8363, -8903, -15615, -11945, -8363, -8903, -6973, -14195, -14195, -6365, -10210, -6143, -14195, -9193, -5576, -10526, -6083, -12776, -7130, -5662, -9531, -6365, -9695, -6310, -6577, -9284, -6628, -7730, -6504, -7708, -9331, -7019, -6856, -7562, -7445, -8683, -8060, -6800, -8790, -7389, -8112, -10138, -7066, -8138, -8086, -8112, -12123, -7179, -7066, -8086, -8220, -11115, -7426, -6492, -8865, -7936, -9380, -7888, -6310, -14784, -7081, -8423, -8582, -6653, -10442, -6422, -8138, -9873, -7562, -8009, -6434, -8276, -8790, -8517, -7687, -7213, -8086, -6899, -9479, -8138, -8247, -7371, -6469, -11488, -8393, -8683, -6343, -7687, -28777, -7984, -9022, -5429, -11488, -13365, -7730, -9531, -4957, -11004, -10799, -7865, -9639, -5061, -9238, -9531, -8220, -9873, -5853, -9531, -8754, -8582, -11945, -7603, -10799, -9193, -9284, -14195, -10284, -9695, -11356, -10799, -10362, -11115, -8454, -12319, -12319, -9064, -9238, -8582, -11004, -11781, -8649, -8034, -10442, -12319, -10613, -8517, -7464, -13049, -14784, -9639, -8363, -7665, -11629, -11629, -9149, -8454, -9331, -10442, -10001, -9149, -8754, -28777, -9106, -9531, -9531, -8718, -9238, -8423, -10526, -11232, -8247, -7247, -8517, -14195, -15615, -8192, -7774, -9106, -10704, -11945, -8865, -11232, -10442, -8363, -10442, -10704, -11945, -14195, -7960, -11115, -13049, -10138, -28777, -8649, -13049, -12123, -11781, -14784, -10442, -17034, -12776, -14195, -15615, -12534, -28777, -28777, -12123, -15615, -11232, -15615, -12319, -12319, -13365, -10210, -13738, -9936, -13365, -10899, -10362, -11488, -9479, -13365, -9380, -11629, -10526, -10210, -12776, -8982, -13365, -11356, -11488, -11781, -9753, -15615, -12123, -13365, -11232, -12319, -28777, -11781, -17034, -11945, -17034, -17034, -10799, -28777, -14195, -12123, -12123, -9639, -28777, -28777, -10526, -10001, -10284, 4117, -1741, 9439, 9312, 2929, 4284, 3780, 9089, 8741, 3537, 3546, 5573, 8139, 6969, 2777, 77, 5538, 6789, 3793, -832, 507, 4484, 5032, -1375, 2805, 1841, 4026, 2905, -4071, 3685, -490, 4578, 1425, -2758, 2398, 458, 4783, 2331, -3201, 1941, 2624, 4456, 3865, -749, 2661, 2622, 3622, 4037, 2250, 1839, 2018, 2369, 2478, 3507, 644, 2440, 1644, -681, 3310, 3949, 3087, 2569, -214, 2662, 6229, 3034, 3999, 1167, 3524, 7221, 2032, 4742, 2237, 4177, 7205, 1220, 4302, 3191, 3378, 6255, 1632, 2944, 3826, 324, 4266, 755, 3572, 3941, -5662, 652, -3412, 4796, 3351, -770, -8165, -3357, 4906, 1831, 557, -985, 358, 4203, -1154, 1485, 947, 3721, 3249, -5266, 2252, 1828, 5710, 2217, -2133, 3012, 2522, 6438, 254, -589, 3494, 3352, 6161, -3589, -192, 3259, 3915, 5106, 963, -496, 2047, 3842, 3530, 3031, -504, -223, 2924, 1435, 3332, -164, -1337, 954, -1360, 2077, -599, -29, -2297, -866, -1878, -2659, 1208, -4373, -668, -883, -9531, 2301, -707, -6504, 1977, -3968, 3284, 981, -403, 2637, -1710, 3956, 1025, 2695, 1865, -885, 4103, 302, 3660, -1123, -897, 3684, 222, 3544, -3586, -1897, 2782, 35, 2671, 818, -4331, 1276, -1210, 1024, 1553, -6773, -1669, -2617, -1780, 71, -4527, -4478, -2152, -2730, -5670, -3860, -1207, -1155, -566, -2241, -4123, -442, -263, 373, -511, -3007, -1201, 340, 491, -918, -1462, -3367, 250, 208, -2363, -759, -6759, -1057, -143, -3065, -858, -4795, -4550, -870, -2470, -1504, -2823, -9873, -2795, -2651, -2312, -1758, -7936, -5374, -4215, -3254, -1158, -6299, -2873, -5085, -4923, -1030, -3927, -1384, -3594, -8304, -1410, -3342, -940, -2659, -8827, -1766, -3583, -1076, -1906, -6705, -1193, -4049, -1614, -1075, -5726, -683, -5221, -2495, -660, -4795, -1190, -6553, -3583, -1224, -4262, -3252, -6163, -4679, -3641, -4429, -10001, -5960, -5306, -9193, -4564, -4134, -5836, -4295, -5085, -4270, -1272, -5234, -3135, -5458, -4386, -361, -4718, -2859, -9812, -4630, -674, -4664, -3744, -6745, -2861, -1711, -5472, -5312, -5109, -1241, -2348, -8304, -4991, -4425, -891, -1728, -5818, -4738, -4278, -1773, -806, -3342, -5221, -6214, -3968, -556, -2918, -3989, -10138, -7542, -1268, -3856, -2881, -4826, -11232, -3067, -4974, -3175, -3760, -8865, -6153, -4713, -5465, -4473, -5531, -8942, -3720, -12776, -6388, -3662, -7464, -3069, -5726, -8517, -2941, -5014, -3378, -3650, -8827, -3294, -3076, -5061, -3274, -8192, -4123, -1979, -8086, -4683, -8086, -3937, -1515, -8683, -9936, -9064, -3546, -1564, -5818, -4616, -8982, -3523, -1957, -3741, -1935, -7484, -3319, -2576, -2992, -1060, -6814, -3227, -3629, -3638, -1564, -6365, -3404, -3479, -6615, -3879, -6235, -3566, -2186, -9531, 6803, 9364, -4743, 4275, 9806, 6092, 8981, -377, 4063, 9215, 3944, 7910, 1949, 3178, 7333, 886, 6396, 2910, 2059, 3891, 539, 4752, 3404, 2191, 1230, 2443, 3137, 3821, 2050, 2253, 2887, 2212, 3979, 886, 2908, 935, 2848, 3917, -157, 2637, -1532, 3687, 3734, -219, 1128, 1752, 3753, 3302, -985, -1205, 2359, 2832, 2821, -2288, -2016, 1916, 716, 2936, 264, -266, 2262, -3396, 3667, 1652, 1017, 2916, -293, 4315, 1773, 1691, 3217, 2884, 4483, 1961, 2831, 3601, 4208, 4235, 2651, 3658, 4113, 4035, 3815, 3109, 3289, 4379, 1922, 3346, 2946, 1350, 4232, -4258, 2606, 1940, -2472, 3801, 545, 1129, 540, -4968, 3411, 1727, -1748, 1032, -6235, 2953, 1598, -4698, 1944, -4693, 2074, 634, -4513, 1989, -2300, 757, -121, -4486, 2266, 700, -1212, 2880, -918, 3610, 2747, -1140, 4536, 460, 4539, 3819, 1327, 4779, 542, 4573, 4236, 2028, 4032, 1154, 4013, 4197, 881, 2632, 1796, 3564, 3842, -3010, 736, 1195, 3340, 3341, -3692, -1967, -945, 2819, 2825, -1001, -7335, -3729, 2154, 2324, -172, -9585, -3404, 2086, 1895, 379, -9753, -2977, 2253, 1590, 868, -7464, -4184, 1805, 1304, 925, -4382, -4230, 159, 876, 240, -5067, -2104, -4336, 667, -1389, -4810, -1882, -2749, 1094, -3201, -1576, -3606, -125, 1286, -2071, -437, -4654, 30, 482, -1386, -1085, -2873, -1636, -1678, -2569, -4455, -2055, -2859, -5014, -7050, -6914, -1747, -1120, -6016, -5630, -2958, -1727, -1106, -7299, -2686, -3668, -2101, -3342, -9284, -1620, -8192, -2082, -5494, -7066, -1754, -1736, -1399, -3515, -6870, -3149, 466, -749, -3449, -5751, -6800, 1016, -236, -4826, -3662, -8276, 385, -15, -5374, -2675, -3147, -1336, -179, -3339, -2437, -1522, -3808, -489, -2068, -2378, -1380, -5326, -975, -2128, -2409, -2273, -4991, -2112, -3903, -2815, -3785, -4184, -4625, -8220, -3748, -5115, -4142, -11004, -7097, -3893, -5176, -6143, -4764, -6653, -2510, -4403, -9479, -2203, -7730, -1546, -3833, -4708, -1125, -5429, -1141, -4049, -3766, -1216, -2813, -684, -4703, -4733, -2958, -1710, -160, -4299, -5020, -9106, -2054, -124, -3512, -3401, -6113, -3741, -712, -3560, -2661, -5367, -6083, -1682, -4433, -2673, -9284, -7464, -2952, -5202, -3040, -9873, -7603, -5253, -5139, -3779, -6943, -5960, -7484, -4764, -5115, -6628, -3606, -5451, -3951, -8165, -5253, -1947, -4847, -3412, -7603, -3154, -1143, -5502, -3744, -4089, -1949, -1174, -7264, -5049, -2926, -1984, -2088, -7583, -6973, -2964, -2871, -3101, -5260, -7317, -3529, -3383, -2129, -4504, -6814, -3937, -4153, -1065, -5451, -7665, -4086, -6828, -1231, -7912, -8393, -4946, -5208, -2937, -12776, -6988, -6973, -3714, -4191, -7146, -6434, -5422, -5097, -2644, -4238, -7464, -3490, -13738, -2661, -4157, 5486, 3550, 4844, 8175, 8460, 5170, 3253, 3870, 7568, 8093, 4392, 2279, 1352, 5729, 7079, 3654, 309, 2109, 3368, 5881, 3139, -3668, 2386, 2603, 5308, 2364, -8718, 25, 1314, 5027, 954, -4592, -1019, -1668, 4008, -1091, -5694, -124, -885, 1579, -2493, -5401, -2617, 1393, 2270, -812, -468, -3650, 2522, 4231, 1549, 1044, -4078, 2252, 4803, 3187, 1508, -2751, -310, 5157, 3896, 2408, 242, -2160, 5623, 3491, 2656, -224, 2457, 5488, 1534, 1314, -926, 3846, 4459, -2553, 733, 1956, 3667, 2790, -1379, 1855, 2803, 2220, 1933, -639, 1429, 1960, 41, 2406, -1353, 895, 35, -1813, 2323, -2060, 2131, -1625, -13049, 1137, -1410, 2833, -2186, -281, -752, 498, 2583, -1550, 2102, -2289, 2368, 1526, -1194, 2105, -1291, 3310, -269, -1906, -200, 423, 2948, -2686, -3580, -5988, 1673, 944, -6035, -5227, 44, 2718, -748, -8549, -4336, 1949, 3219, 624, -3420, -2696, 2753, 3215, 240, -1534, -1060, 2976, 3404, -2350, -1011, 456, 2636, 3995, -3354, -1177, 1455, 1662, 4339, -1947, -1081, 1825, 307, 4072, -2610, -688, 1728, -275, 3103, -5097, -1049, 1468, -274, 1509, -4145, -2833, 1249, -1048, -3, -1979, -5694, 910, -2216, -152, -1130, -4127, 189, -751, -208, -1515, -2531, -918, 877, -835, -4262, -2002, -1690, 1630, -395, -4395, -1661, -840, 1837, 461, -897, -621, 139, 1759, 545, -180, 34, 72, 1428, 226, -1002, -608, -1502, 841, 222, -1966, -2914, -4847, 164, 579, -1713, -4451, -3612, -274, 639, -1577, -4319, -2460, -340, -86, -1999, -7865, -3054, -164, -1470, -2859, -8009, -4127, 94, -2163, -4433, -4303, -2969, 286, -2071, -7097, -2997, -1438, 197, -2385, -8086, -2427, -750, -224, -3085, -6411, -2945, -831, -647, -3757, -5615, -5630, -1552, -668, -4290, -5897, -6628, -3189, -624, -4963, -7984, -2752, -7034, -1196, -5531, -7162, -2084, -11488, -2897, -3860, -3399, -3433, -7687, -5429, -1557, -1965, -3365, -4795, -4644, -287, -2211, -1878, -2088, -3354, 54, -4664, -2297, -765, -3352, -291, -11488, -4963, -507, -5768, -1282, -3707, -4399, -1078, -6577, -3203, -2057, -1956, -2407, -2091, -3992, -1900, -1040, -4769, -717, -1906, -2507, -1232, -8790, -824, -740, -2735, -2528, -6163, -2170, -543, -2407, -4234, -5546, -5638, -1051, -2666, -4108, -8790, -7426, -2071, -3853, -4153, -5502, -2971, -2943, -5576, -5576, -2823, -1522, -2783, -6653, -5888, -2222, -1382, -2201, -6332, -4447, -2897, -2361, -1945, -5615, -4172, -4142, -4901, -2239, -5743, -4635, -4262, -8790, -3237, -7603, -4348, -3978, -5554, -4997, -8754, -3632, -3261, -4130, -6666, -4447, -2597, -1600, -3535, -6288, -2571, -1420, -776, -3560, -4869, -2213, -1073, -1289, -5326, -2952, -3149, -2082, -3218, -8247, -1549, -6719, -5997, -3763, -2377, -3992, -3662, -4254, -4985, -5202, -2762, -2493, -2635, -11356, -6113, -3760, -2419, -1961, -4907, -3076, -4659, -2787, -2257, -2323, -2555, -1855, -2967, -3487, -2100, -3266, -850, -2670, -5897, -3856, -5061, -1705, -2414, -9585, -5408, -10138, -4842, -2644, -7865, -2825, -6133, -9639, -3757, -6457, -1792, -3449, -10362, -6321, -6814, -1902, -2835, -7752, -8112, -10362, -2628, -3436, -3653, -4491, -8165, -3930, -5061, -2342, -2330, -4238, -6411, -7146, -2232, -1533, -2910, -5623, -7247, -2560, -2306, -3184, -3027, -6828, -2813, -6278, -5319, -2311, -6469, -2641, -4743, -7503, -3465, -4469, -1841, -1353, -3704, -4968, -1794, -867, -386, -1854, -2222, 59, -291, -631, -1258, -1011, 840, -452, -1650, -1797, -1335, 566, -1607, -3069, -3883, -2512, -619, -4211, -4764, -9380, -3641, -2355, -7774, -6376, -9695, -5818, -4282, -5718, -6225, -8827, -11629, -4968, -4816, -5429, -10362, -4064, -3165, -5853, -4559, -6354, -2305, -1973, -10362, -3665, -3916, -2135, -1928, -6705, -3289, -3261, -2754, -3036, -3388, -4042, -3903, -3566, -4104, -2140, -7113, -4559, -4270, -3621, -2326, -10704, -4460, -4352, -3893, -3886, -5408, -5678, -3714, -5569, -7066, -4003, -11945, -3683, -4863, -11356, -3723, -8363, -5043, -3441, -7730, -4130, -6388, -8549, -3626, -7335, -5374, -5686, -6504, -5247, -8060, -8220, -4460, -4112, -7583, -4311, -17034, -3650, -3194, -8192, -2510, -6786, -3543, -3007, -7371, -2286, -3975, -3766, -3276, -7960, -3087, -2610, -3947, -3824, -8192, -3999, -2271, -4408, -4500, -4769, -5127, -2739, -5472, -5152, -3126, -9238, -3779, -6692, -5367, -2837, -8423, -4748, -6528, -4764, -3476, -5394, -4795, -6246, -4357, -4769, -5784, -4733, -6914, -4974, -6204, -8865, -5630, -7708, -6653, -6310, -11115, -8086, -7213, -7523, -5592, -9695, -11232, -5836, -6267, -5592, -9022, -8649, -4703, -4336, -6814, -6445, -6885, -4238, -3144, -6943, -3886, -6256, -4112, -3362, -4348, -2540, -6870, -4112, -5451, -2793, -2488, -7317, -4918, -5408, -2306, -3732, -5176, -7503, -3056, -2690, -6278, -3638, -9380, -2420, -4049, -10138, -2859, -7004, -2865, -6026, -8517, -2594, -7335, -3741, -5827, -5638, -2885, -12776, -4282, -5326, -5152, -3923, -8034, -4195, -5988, -6504, -5879, -5710, -4164, -6732, -7299, -9479, -6103, -4997, -7213, -6143, -12123, -8138, -7130, -8333, -6026, -9585, -9064, -8903, -9479, -6719, -10362, -11115, -10210, -8363, -7066, -17034, -12534, -12534, -6504, -6214, -11232, -8754, -7371, -5292, -4896, -7936, -8086, -5988, -5020, -4108, -5906, -7644, -6007, -5759, -4207, -4869, -6759, -6204, -7796, -5260, -4923, -6016, -5654, -9022, -7230, -6434, -5183, -4759, -7464, -8034, -10704, -4460, -4270, -7264, -6705, -6590, -4352, -4625, -8192, -6310, -3913, -4863, -5933, -8827, -7445, -2891, -5915, -7912, -8304, -12319, -2992, -7484, -7960, -7213, -10138, -9380, -3198, -4853, -4295, -8247, -5208, -4573, -3269, -5286, -4901, -2557, -9106, -3225, -4863, -2065, -1252, -7542, -3662, -5561, -1290, -945, -4390, -4583, -6928, -994, -1398, -3222, -6928, -6800, -747, -2217, -2823, -28777, -4683, -983, -3344, -2512, -6540, -3242, -1728, -6354, -2286, -4420, -3471, -2276, -8827, -2631, -4104, -6016, -2254, -3543, -3827, -4416, -8615, -2257, -1908, -5702, -4145, -6842, -2597, -1442, -7426, -3846, -8827, -3412, -1750, -6163, -4089, -28777, -5227, -2910, -4433, -4412, -9331, -9873, -4880, -3913, -4583, -5401, -5654, -6445, -5127, -5234, -3870, -2733, -8942, -7644, -7097, -4357, -1243, -7960, -2900, -4940, -3049, -371, -2897, -697, -2018, -369, 88, -1191, -128, -795, 869, 184, -1080, -729, -956, 933, -136, -2139, -2060, -2672, 54, -1031, -3735, -3042, -7774, -1542, -2696, -4482, -3367, -7264, -3399, -5374, -4478, -3820, -4935, -5360, -9380, -4369, -4504, -5888, -8060, -14784, -4142, -5429, -8393, -9639, -15615, -3324, -5638, -5202, -10284, -28777, -2351, -4003, -3266, -8363, -12123, -2019, -2683, -2657, -6153, -8827, -2455, -2333, -3352, -5862, -8247, -2631, -2492, -6278, -5871, -5801, -1885, -2223, -8683, -4115, -3683, -1462, -1820, -4935, -2724, -3309, -1690, -2053, -4024, -2566, -4513, -2232, -3080, -4064, -4024, -5253, -2517, -4451, -4286, -8086, -3714, -2739, -4784, -4728, -4625, -2716, -4060, -3951, -6267, -2622, -2462, -8485, -3254, -13365, -2336, -2751, -8165, -3003, -5465, -2941, -3521, -6732, -2766, -2605, -3754, -4743, -8942, -2455, -1535, -4157, -6528, -17034, -2562, -1482, -4336, -7503, -11232, -3239, -2075, -4620, -5726, -7583, -3754, -3128, -4541, -4089, -4460, -3940, -4429, -4616, -3271, -2875, -4759, -5346, -6256, -3352, -2730, -6814, -5109, -8903, -4460, -3782, -10138, -4606, -5801, -7146, -4597, -13738, -4997, -4759, -17034, -4145, -12319, -5043, -5061, -8754, -4164, -10362, -3515, -5988, -7034, -4810, -11004, -2789, -7687, -7034, -4985, -12534, -3391, -8423, -6246, -4649, -12534, -5584, -7562, -4464, -4478, -9936, -11945, -7484, -3653, -3732, -6615, -8112, -6988, -3896, -2578, -5374, -5374, -6719, -4708, -2130, -5853, -4683, -7888, -5546, -2867, -8333, -5801, -10284, -6958, -5408, -15615, -11232, -8827, -8683, -10442, -12123, -7687, -7912, -6399, -7603, -9479, -5801, -8790, -4907, -7562, -6885, -6773, -8827, -4901, -9479, -5437, -10442, -6310, -6299, -11004, -5401, -8615, -5061, -9284, -9531, -7066, -7464, -5127, -13049, -7936, -12319, -6943, -6615, -13049, -7796, -11115, -5234, -10138, -11488, -9106, -7230, -3992, -8865, -11356, -11356, -5031, -3686, -7097, -11781, -11356, -3804, -4093, -7130, -11232, -8304, -3741, -4713, -8582, -9193, -6123, -5195, -4754, -12534, -7960, -4842, -9479, -4006, -13049, -8304, -4311, -8903, -3191, -9873, -11356, -4504, -7213, -3025, -8982, -10069, -5862, -8333, -3863, -8718, -6870, -5247, -4654, -6411, -3069, -1035, -7730, -4555, -7819, -1087, -1342, -5793, -2967, -4473, -272, -2170, -2918, -2353, -2538, 8, -3001, -1487, -1935, -1790, -342, -3540, -1089, -1391, -1646, -1800, -4266, -1343, -995, -1936, -3040, -5735, -1846, -942, -2416, -1246, -7445, -2502, -1150, -2128, -392, -7081, -4060, -1581, -1503, -831, -7317, -6445, -2747, -1493, -2198, -8304, -4067, -5879, -2066, -3692, -7213, -2385, -13738, -2741, -4382, -5451, -1823, -8454, -3304, -4693, -4078, -1647, -7842, -3961, -5026, -3906, -1611, -7503, -4184, -5494, -4469, -2280, -8865, -3814, -5253, -3334, -5014, -10526, -5686, -4821, -2962, -4963, -4779, -5793, -6143, -5509, -1939, -1962, -893, -5339, -5801, -1399, -953, 636, -2308, -2420, -2447, -1412, 543, -889, -1892, -3827, -3210, -730, -471, -3133, -3080, -5793, -2355, -653, -6577, -2703, -7562, -2999, -1036, -7644, -4017, -8865, -3334, -1310, -4923, -6399, -10210, -3788, -1838, -4703, -4748, -9812, -3717, -3144, -6988, -3916, -9936, -3266, -4583, -8393, -3689, -8247, -3201, -3957, -5793, -3252, -6504, -3441, -3128, -7389, -3158, -5768, -3457, -3119, -6914, -3281, -5759, -2950, -4093, -3047, -3242, -6590, -2303, -6692, -2143, -2924, -9284, -2162, -11356, -3069, -1932, -12534, -2743, -6093, -5735, -1068, -6759, -3751, -4234, -8192, -985, -4597, -4664, -3444, -6457, -1686, -3314, -5227, -2646, -5299, -2897, -2437, -5253, -2032, -4718, -4559, -1932, -4559, -2176, -4142, -7445, -1959, -3367, -3051, -3378, -28777, -2960, -2257, -3840, -2677, -6988, -5888, -1494, -3889, -2366, -4262, -7371, -1097, -3279, -2641, -2988, -4968, -1021, -2743, -3249, -2762, -5326, -1308, -3184, -3428, -3409, -7034, -2049, -5437, -3087, -3850, -7264, -3208, -15615, -2939, -3321, -8034, -4207, -6745, -3698, -3244, -11004, -4157, -4597, -6083, -4203, -12776, -4119, -3529, -9238, -5844, -11945, -5292, -2458, -11232, -6692, -6988, -9812, -1581, -11115, -5615, -4679, -8363, -1255, -6856, -4013, -4203, -4985, -1556, -7752, -3065, -5524, -4219, -2495, -11356, -2926, -9695, -4923, -3961, -5127, -3347, -12534, -7299, -5221, -3580, -3779, -13738, -11115, -5394, -3704, -3735, -8790, -6457, -5487, -5346, -3485, -5879, -3493, -5751, -11004, -3311, -4800, -2051, -5401, -7523, -3276, -4097, -1771, -4399, -5008, -3493, -3249, -2398, -3569, -4569, -4164, -2488, -3490, -3474, -4654, -5176, -2023, -4336, -4482, -4357, -5951, -2102, -4784, -7389, -4049, -5979, -2962, -5401, -9238, -4115, -5776, -4382, -7213, -6354, -4064, -6267, -5759, -12319, -5897, -3798, -7936, -8485, -12534, -6943, -3933, -9639, -11945, -8982, -8582, -4478, -10284, -6828, -6870, -8363, -4754, -11629, -6074, -6183, -7503, -4863, -10442, -6914, -7019, -7146, -5516, -7730, -8333, -8276, -7004, -5818, -6278, -8790, -7130, -6204, -5109, -6214, -7960, -6445, -5067, -5214, -7213, -7050, -7113, -4564, -6653, 8198, 5825, 565, 6157, -726, 8211, 6039, 937, 5454, -1500, 7961, 5718, 1930, 2821, -1419, 6996, 3610, 3491, -2125, 778, 5105, -701, 4384, 2225, 1888, 2860, 2874, 3799, 2570, 1659, 1944, 3990, 757, 6, 290, 2955, 3960, -313, -4550, 736, 4407, 3787, 2482, -13, 2463, 4907, 3661, 2428, 1038, 3412, 4593, 3283, 160, 2893, 3943, 4378, 2556, -6653, 4867, 4183, 4084, 3063, -2468, 5775, 4065, 2255, 4607, -936, 5456, 3534, -2251, 5324, -1104, 3646, 2312, 637, 5050, -2286, 152, -54, 1147, 4049, -2288, 1191, -2440, -34, 2488, -1036, 2116, -2567, -18, -227, -804, 1244, -4290, 1057, -7113, -1859, -1124, -6516, 1512, -4416, -3569, -5055, -2477, 1477, -1324, -3920, -6054, -589, 1325, 33, -2380, -4064, -160, 762, -497, 55, -1526, -1123, -42, -3455, 1225, 705, -3501, 694, -2492, 1104, 1705, -2016, 1467, -1420, 769, 1596, 43, 1437, -4223, 1187, 339, 402, 1444, -1094, 918, -3930, -1041, 1311, 1932, -814, -2984, -3964, -87, 2749, -571, 483, -760, -4067, 1963, 1360, 691, 598, -11781, -884, 1887, -1220, -117, -9193, -5292, 1071, -1963, -2268, -7081, -2286, -1614, -180, -1212, -3618, -2590, -10210, 186, -399, -1580, -3367, -1739, -271, -1497, 119, -1307, -209, -666, -2229, 1094, 208, -312, -470, -27, 1304, 583, -1302, -130, 1320, 1171, -440, -1944, -270, 1714, 1237, -3624, -1451, -1228, 1456, 1535, -2159, -400, -2783, 980, 1626, -77, 549, -3580, 757, 1075, 81, 654, -3140, 555, -480, -854, -543, -2197, -50, -3856, -1857, -3220, -1787, -894, -11115, -1628, -2835, -2587, -1603, -4311, -553, -1333, -3695, -2292, -3056, 260, -1349, -2020, -2916, -2982, 472, -2470, -460, -3080, -3140, 130, -3557, 129, -3126, -2797, -666, -2879, -131, -4100, -2022, -2007, -1925, -1522, -7984, -1648, -4473, -1732, -5862, -9022, -1961, -9331, -2541, -5516, -6163, -2875, -7004, -4693, -1872, -7034, -4203, -5888, -9873, -937, -7484, -6354, -6577, -6628, -914, -6422, -8192, -6256, -3523, -1178, -6399, -4853, -4587, -2443, -1405, -6885, -3543, -3603, -2986, -1479, -7888, -3985, -3574, -6035, -1498, -7912, -6054, -4254, -8138, -1556, -5686, -7984, -5189, -5043, -1677, -4254, -5630, -6321, -5810, -2093, -3827, -3701, -7562, -11115, -3005, -4464, -2432, -7389, -8060, -4625, -6153, -1654, -6828, -7019, -7819, -6679, -1536, -8247, -8393, -17034, -5360, -2342, -9695, -7389, -7984, -5103, -4203, -5638, -6194, -7353, -6679, -5279, -4918, -7299, -8718, -14784, -5164, -6732, -11781, -8718, -8034, -6388, -12776, -7389, -9106, -6528, -8827, -13365, -5686, -17034, -7865, -14784, -13365, -5793, -9873, -17034, -8865, -9531, -6828, -8549, -8454, -5942, -8333, -7796, -9331, -5183, -5387, -8903, -7503, -9380, -3754, 1488, 4732, 5435, 3299, 860, 2075, 3934, 4830, 2558, 1286, 2330, 1112, 2417, 1071, 1434, 1165, -8363, -3886, 2056, 1478, -1660, -4616, 2254, 3008, 2384, -1958, -10362, 2932, 2279, 2697, -718, -3479, 629, -65, 1658, -270, -1728, 11, 1675, 800, 77, -2100, 3171, 3169, 2379, -347, -1384, 4349, 2465, 3936, -3521, 511, 5009, 619, 5251, -852, 2031, 5436, 3324, 6009, 2604, 3193, 5140, 4662, 5949, 3812, 3872, 3587, 3984, 5094, 3644, 3951, -497, 399, 3731, 2084, 3418, -3961, 651, 2635, -1610, 2150, -303, 3766, 2558, -978, -292, -478, 4689, 2681, 720, -2050, 274, 4780, 1965, 118, -1257, 2008, 4519, -164, -2843, -2743, 2550, 4088, -4184, -7004, -3179, 1817, 3563, -3798, -3860, -1303, 299, 3029, -3076, -3940, -2207, 505, 2487, -4115, -6469, -6235, 1721, 1771, -5214, -7213, -5394, 1936, 830, -4606, -2642, -6800, 615, -7, -4042, -706, -3289, -4299, -335, -1880, 224, -629, -1722, -274, 326, 795, 420, 779, -327, 1319, 1012, 995, 639, -702, 1040, 654, 1419, -1532, -1244, -445, -207, 1283, -1665, -1869, -2528, -804, -170, -231, -2112, -2962, -937, -5401, -1052, -2047, -1992, -1880, -2900, -3944, -2583, -605, -2653, -581, -2295, -3704, 611, -1237, -618, -710, -4451, 1218, -912, -1821, -88, -3085, 1122, -2241, -2902, 337, -823, 645, -5091, -1728, 559, 342, 452, -7081, -194, 312, 296, 440, -3393, 847, -706, -910, -13, -696, 1511, -3036, -3067, -868, 661, 1809, -6565, -4089, -1280, 971, 1570, -4532, -3222, -1412, 392, 500, -3698, -2879, -2223, -1051, -1976, -3689, -3707, -3554, -3563, -8220, -2958, -5662, -4545, -7708, -6153, -2225, -5686, -5055, -8165, -5031, -2030, -4863, -4816, -8582, -6870, -2188, -5480, -4764, -17034, -15615, -2677, -7034, -5387, -7299, -10526, -3618, -8683, -6225, -6653, -13365, -4784, -7960, -7464, -9238, -8549, -5735, -6828, -8718, -6299, -4693, -6083, -7081, -6745, -3569, -3329, -5997, -6628, -5554, -2073, -3242, -6343, -5726, -6692, -1243, -4089, -8138, -5260, -9936, -1058, -5686, -11629, -4064, -5630, -1614, -6988, -9639, -2895, -3863, -3023, -7097, -10899, -2377, -3425, -5827, -7264, -6914, -2443, -3754, -9695, -7665, -3184, -2885, -4532, -5326, -7281, -1505, -3407, -5240, -3668, -6288, -1109, -3896, -5810, -3779, -5531, -1808, -4569, -5801, -5836, -5319, -3409, -5164, -5170, -8363, -5879, -4564, -5380, -4923, -4968, -7264, -4195, -5810, -4991, -3940, -8423, -4108, -6492, -5020, -4649, -7562, -4779, -6705, -5189, -7066, -5933, -5561, -6083, -5853, -10799, -5214, -5472, -5531, -7019, -8333, -5569, -5176, -5623, -8454, -6225, -6705, -5646, -6504, -9429, -5292, -8333, -7019, -8192, -10001, -5326, -12123, -8790, -10526, -9479, -5997, -12534, -9479, -11115, -7299, 6416, 2356, 4664, 4031, -5299, 5458, 1289, 4241, 3522, 3198, 1889, 1076, 3307, 2987, 5682, -4035, 3271, 3179, 3621, 6467, 59, 4035, 3779, 3662, 5954, 1569, 3567, 3884, 2134, 4082, 2618, 1938, 3351, 1349, 1174, 1829, -1816, 2461, 3482, -75, 696, -2000, 1162, 3919, 2162, 3512, 195, -3866, 2144, 3865, 5329, -174, 928, 1771, 3107, 5968, 2492, 4503, 4015, -511, 5618, 4771, 5457, 3596, 3888, 4171, 5142, 4513, -1174, 5022, 1539, 3408, 845, 2442, 3508, 593, -4985, 461, 4277, 1141, 911, 1157, 2545, 3506, 3875, -508, 2441, 2172, 332, 4892, -2675, 1350, 582, -8615, 4703, -1820, -1203, -755, -6321, 3747, -788, -3971, -398, -7464, 2446, -422, -4918, 387, -3692, 1952, -274, -5394, 804, -1739, 1899, 15, -7984, 865, -494, 1162, -218, -28777, 590, -50, -82, -1703, -8827, -114, -985, -533, -4795, -6163, -1497, -4119, -419, -5710, -4226, -4134, -1442, -325, -5319, -3792, -13049, 877, -304, -5444, -4688, -5360, 1446, -1034, -1832, -3843, -2853, 881, -1636, 495, -1986, -2173, -539, -513, 1571, -1239, -2722, -2480, -15, 1774, -952, -3996, -5026, -761, 1241, -701, -5346, -8060, -1784, -104, -1099, -7179, -4266, -891, -2424, -2472, -4176, -2655, -268, -4307, -3557, -1370, -2465, -664, -2546, -2875, -335, -2845, -877, -605, -1921, -770, -3067, -707, 113, -1986, -2306, -2276, -1312, -1001, -2125, -2260, -961, -2552, -6800, 205, -1553, -26, -3680, -3230, 1694, -2138, 262, -6411, -1366, 1734, -2295, 14, -6759, -2095, 468, -1256, -340, -2545, -4219, -1418, -1221, -522, -1363, -7050, -2198, -2366, -1086, -1909, -10362, -3119, -3306, -2743, -4258, -6856, -5451, -2386, -6214, -8276, -6692, -7299, -1541, -8942, -7936, -12534, -6321, -1470, -6163, -8517, -7019, -4968, -2194, -4172, -11232, -4134, -4386, -3769, -3465, -11781, -3409, -5437, -6602, -3923, -6194, -3735, -7097, -11488, -4307, -4403, -4447, -3782, -12534, -3487, -4295, -5091, -1998, -10899, -3058, -5121, -5924, -1595, -6422, -4053, -5951, -7888, -2160, -4968, -8247, -6235, -12123, -3532, -5458, -6692, -6679, -8517, -5458, -7984, -3465, -8454, -6590, -7665, -13365, -2592, -9106, -6064, -10001, -15615, -2795, -7019, -6814, -6035, -12776, -3577, -6225, -9873, -3856, -8454, -4555, -5202, -8754, -3294, -7687, -5415, -3827, -6194, -3951, -8754, -5888, -3140, -5836, -5531, -8276, -5516, -3276, -6628, -6194, -7708, -4774, -3910, -7623, -5195, -10442, -4683, -4698, -7752, -4482, -10210, -5759, -5906, -7888, -4219, -6590, -8393, -8165, -9936, -4319, -5988, -9585, -15615, -28777, -4929, -6759, -6973, -9149, -9585, -6553, -7034, -5924, -6828, -7888, -11004, -5793, -6759, -6083, -6007, -9106, -4790, -11945, -5615, -4527, -6434, -4620, -8034, -5480, -4238, -6214, -5273, -5480, -6343, -6343, -9238, -6773, -8009, -3386, -8683, -7960, -7113, -7213, -3776, -8009, -7162, -10362, -7708, -4536, -5339, -7665, -11356, -10069, -5031, -4195, -9873, -7819, -11629, -4997, -4199, -12319, -8034, -9936, -5208, -4382, -10526, -10284, -9106, -6123, -4035, -8982, -12776, -9479, -7665, -4180, -7960, -14195, -13049, -7796, -5546, -7865, -10613, -10069, -6388, -8304, -8754, -7464, -6565, -5465, -11781, -9429, -5879, -5546, -4896, -13049, -10069, -5970, -6214, -5014, -8549, -7687, -7097, -8649, -5924, -9936, -6288, -7281, -13738, -6480, -8790, -5031, -6988, -8220, -5458, -10284, -6492, -9284, -12776, -9936, -304, -622, 154, -394, 27, 3828, 3713, 4003, 3698, 4086, 5846, 5794, 5951, 5755, 6050, 6437, 6405, 6546, 6426, 6623, 5763, 5698, 5893, 5839, 5941, 3711, 3461, 3829, 3848, 3851, -232, -1519, -371, -255, -389, -8865, -5630, -10362, -11115, -14784, -11232, -3671, -7113, -7426, -6973, -15615, -5458, -12123, -10284, -11488, -11781, -7484, -10442, -7774, -12123, -8034, -7708, -7081, -8086, -10284, -7408, -8009, -5312, -9639, -8790, -8718, -10442, -5115, -14784, -8649, -9479, -13738, -6133, -11004, -9064, -7408, -11781, -8393, -8247, -9585, -6310, -12776, -10704, -7542, -9639, -6958, -8683, -10210, -7888, -9479, -9639, -6256, -11356, -8790, -10210, -17034, -5202, -17034, -8683, -13365, -14784, -5031, -15615, -7842, -28777, -13049, -5360, -10613, -7708, -17034, -12123, -6183, -8247, -8790, -14784, -12319, -7583, -8304, -11488, -10799, -14784, -9380, -11629, -11781, -8165, -15615, -10899, -14195, -10704, -7264, -11232, -11004, -10001, -11945, -7687, -8649, -9479, -9429, -13365, -9284, -7113, -8423, -9812, -9149, -10899, -6445, -8423, -10704, -7408, -10362, -6786, -9284, -11356, -6899, -9331, -8423, -9149, -9531, -7247, -8718, -11945, -8423, -7665, -8683, -8363, -11356, -8165, -6679, -11232, -8247, -9064, -7984, -6814, -10704, -8304, -8454, -8086, -8454, -10069, -8827, -9331, -8582, -10362, -9873, -9193, -11629, -9284, -8754, -9479, -8517, -11629, -9936, -8517, -9531, -8138, -10284, -11232, -10069, -10704, -8790, -10138, -15615, -13738, -13049, -10138, -9531, -13049, -15615, -14784, -10362, -8112, -10799, -15615, -12776, -9639, -7281, -10362, -15615, -11232, -9753, -7542, -8903, -13365, -10138, -11488, -8454, -7984, -12534, -9812, -28777, -8790, -8485, -14784, -10069, -14195, -9531, -10210, -28777, -10001, -11115, -12319, -11356, -12776, -9479, -9936, -17034, -11356, -11232, -8942, -9873, -14784, -11488, -11004, -8754, -11004, -14784, -11945, -11488, -9238, -15615, -11781, -11781, -11781, -11356, -13365, -10613, -12319, -12776, -28777, -10799, -10899, -13365, -13049, -13049, -11356, -11629, -13738, -11356, -11781, -15615, -10704, -14195, -10704, -13049, -28777, -9873, -13365, -10899, -14784, -28777, -10210, -11004, -12123, -14195, -14784, -11781, -10613, -15615, -13365, -14195, -14195, -11115, -14784, -13049, -17034, -13049, -11945, -12123, -11356, -28777, -12319, -11781, -11004, -9753, -14195, -6365, -9753, -9238, -7113, -5810, -6492, -8903, -8615, -5115, -5751, -6745, -8276, -8009, -4541, -7842, -6153, -7623, -8363, -4858, -12319, -5599, -6332, -10613, -5836, -7196, -6321, -5079, -12776, -7708, -5702, -8718, -4569, -10442, -10704, -5422, -10069, -4831, -8790, -11945, -5531, -11356, -5630, -8138, -13365, -5818, -12123, -6480, -7936, -7796, -6640, -10284, -7019, -7687, -5079, -8247, -11356, -7247, -7445, -4021, -8903, -12319, -8942, -8615, -4157, -6943, -9695, -12776, -10613, -5055, -5776, -11356, -10001, -8112, -6973, -7665, -8393, -7066, -5599, -7644, -8304, -17034, -7842, -10362, -10704, -10899, -463, -258, -579, -346, -735, 3740, 3829, 3777, 3803, 3715, 5796, 5856, 5835, 5855, 5858, 6417, 6453, 6427, 6491, 6529, 5751, 5747, 5709, 5866, 5905, 3657, 3566, 3521, 3875, 3843, -577, -903, -882, 30, -296, -28777, -15615, -8982, -7130, -7081, -7004, -6943, -8615, -10284, -7623, -9479, -5662, -11488, -11004, -7230, -11945, -5266, -9429, -10799, -6343, -10799, -6332, -9238, -15615, -8718, -10210, -8112, -8582, -10138, -11356, -11232, -11945, -8423, -9753, -11488, -12123, -17034, -7335, -11232, -11945, -12776, -10899, -6615, -17034, -13365, -17034, -8718, -6928, -28777, -12123, -13738, -8009, -8009, -28777, -7503, -9149, -8454, -8009, -13738, -5487, -7842, -9695, -6786, -10899, -4784, -8165, -10613, -6553, -10613, -5158, -10001, -10210, -7730, -11232, -6590, -10704, -9639, -9585, -10526, -9193, -9331, -8615, -9812, -9585, -12319, -8982, -8220, -9429, -9936, -14195, -8865, -9531, -9429, -12534, -17034, -8086, -13049, -10799, -28777, -13738, -8086, -10284, -13049, -14784, -10613, -8790, -9753, -10362, -17034, -7984, -7888, -12534, -8790, -13049, -6745, -7113, -14784, -7796, -11629, -6828, -7523, -12123, -7019, -11356, -8192, -8827, -11115, -6759, -11115, -10526, -10899, -10138, -7264, -10138, -11356, -11232, -9639, -8649, -9284, -9936, -11004, -10704, -10799, -9695, -9106, -11945, -12776, -13365, -11945, -9149, -10704, -11945, -17034, -28777, -9873, -8683, -10069, -17034, -13738, -10899, -8485, -9331, -12776, -12776, -11629, -9695, -9936, -11004, -14195, -11945, -11781, -12534, -10442, -28777, -12534, -13738, -14195, -10613, -17034, -12319, -14784, -10799, -11781, -12534, -10526, -14784, -8982, -14784, -11004, -9064, -13738, -8086, -12319, -10442, -8903, -13365, -8333, -10442, -10362, -10069, -13365, -10001, -10704, -10613, -13049, -14784, -14784, -12319, -11629, -28777, -17034, -13365, -12123, -14195, -14784, -17034, -11232, -11004, -28777, -13049, -13738, -11488, -11356, -17034, -11781, -12776, -13738, -13049, -17034, -11629, -11488, -17034, -12776, -17034, -12534, -10284, -15615, -11945, -17034, -14195, -9639, -15615, -12319, -28777, -14195, -9873, -28777, -13365, -15615, -12534, -11115, -28777, -14195, -12319, -12534, -13365, -14195, -14195, -11488, -13365, -15615, -13365, -14195, -12123, -14784, -15615, -15615, -13365, -14784, -15615, -14784, -17034, -11629, -28777, -17034, -13365, -28777, -10799, -17034, -15615, -5253, -8454, -6615, -5133, -8982, -7865, -28777, -7865, -6054, -28777, -9639, -10442, -8333, -8138, -10001, -8865, -13738, -8615, -9812, -7912, -9380, -10210, -8718, -9284, -7445, -8485, -7752, -8165, -9531, -8865, -8060, -8363, -6732, -12534, -12534, -9380, -9812, -5726, -13365, -8247, -8649, -9429, -5694, -9331, -6885, -7247, -8827, -6103, -7665, -6943, -7796, -8827, -6973, -6914, -7426, -9873, -9479, -8754, -7730, -8517, -10704, -8718, -9238, -14195, -10442, -9753, -6332, -7230, -10284, -8865, -11488, -6288, -6679, -10613, -10613, -8485, -6914, -6899, -7019, -7484, -9531, -6870, -6773, -6204, -8517, -466, -145, -95, -355, -422, 3651, 3885, 3750, 3753, 3830, 5698, 5914, 5730, 5808, 5899, 6308, 6529, 6341, 6438, 6532, 5592, 5882, 5697, 5793, 5904, 3327, 3857, 3651, 3756, 3930, -1577, -60, -461, -267, 173, -7796, -8649, -11629, -10001, -5951, -6899, -9695, -8060, -11232, -6870, -13049, -11488, -10001, -9193, -6786, -9284, -9238, -8393, -7213, -6745, -9531, -8333, -8942, -8615, -6602, -8086, -7665, -10799, -11781, -6103, -7097, -7113, -12534, -9380, -6278, -6615, -7066, -13049, -7936, -6814, -6705, -8276, -11945, -8718, -7353, -7264, -9812, -12534, -13049, -7865, -9331, -9284, -28777, -11945, -8754, -28777, -8790, -11004, -8827, -11781, -11004, -8982, -9106, -7912, -15615, -9284, -9753, -8683, -7888, -9585, -9106, -10526, -8454, -8982, -8333, -9585, -10210, -8247, -12319, -8903, -11488, -8718, -8517, -14784, -10362, -10799, -7665, -9695, -10210, -9106, -7960, -7730, -10069, -8423, -7819, -6732, -8790, -8754, -7687, -8009, -6745, -10001, -7842, -7984, -9873, -7819, -9639, -7503, -9585, -13365, -10362, -8454, -7603, -13365, -13049, -17034, -7542, -8060, -13738, -12776, -17034, -7050, -8865, -11945, -17034, -12776, -6732, -9812, -11781, -15615, -9639, -6540, -10526, -12319, -11356, -8754, -6773, -10442, -12776, -10210, -10362, -7408, -9639, -13049, -10210, -10799, -8247, -9284, -13738, -10526, -8333, -8903, -9695, -13049, -11629, -7426, -9106, -10899, -11781, -15615, -7523, -8982, -11781, -10526, -28777, -8333, -9064, -11115, -10284, -17034, -9639, -9753, -11004, -11004, -28777, -11004, -11356, -12319, -10704, -17034, -11115, -11945, -17034, -9695, -12123, -10613, -10704, -17034, -9753, -11356, -11004, -10001, -13738, -11004, -13049, -11629, -9639, -12319, -14784, -14784, -10799, -9812, -12319, -28777, -13738, -10069, -9812, -14195, -11945, -12319, -11004, -9106, -17034, -9812, -11781, -14195, -8790, -14195, -9106, -12534, -12776, -9695, -14784, -9753, -13365, -12534, -12123, -17034, -12319, -12319, -13738, -28777, -11945, -28777, -11356, -12123, -28777, -10613, -28777, -12319, -11488, -28777, -11115, -14784, -12123, -13049, -15615, -12776, -11115, -9639, -28777, -17034, -14195, -10613, -8582, -28777, -28777, -13049, -11629, -8247, -28777, -14195, -11004, -12319, -7912, -28777, -10899, -10799, -11781, -8009, -17034, -9936, -11781, -12123, -8649, -13738, -10284, -12534, -13365, -9585, 13663, 14366, 4813, 9113, 11708, 13034, 13853, 4611, 8494, 11025, 10985, 12278, 4030, 6553, 8801, 6567, 9566, 4556, 3159, 4258, 23, 5985, 5758, 1153, -1510, 4596, 3621, 5802, 1683, -3940, 4343, 4039, 4320, 489, -3597, 2011, 4334, 2002, -489, -2114, 583, 3693, 2781, 2757, 2647, 3150, 2999, 3816, 4459, 4923, 3320, 3110, 4217, 5034, 5775, 1425, 3950, 4379, 4757, 6105, -2950, 4772, 4336, 3451, 6336, -4779, 5028, 3919, 436, 6201, -1146, 4583, 3020, 206, 5210, 888, 3344, 2187, 2548, 2965, 1294, 1055, 2540, 2995, 508, 1023, -2831, 3195, 2080, 1107, 250, -3920, 3249, 899, 1211, -3422, -2881, 2700, 2154, 958, 1131, -3707, 1843, 3627, 1307, 4062, -4060, 550, 4293, 1474, 4927, -2178, -2010, 4267, 970, 4235, -928, -2791, 3646, 26, 1260, -346, -392, 2637, -1267, -3707, -201, 601, 1883, -1302, 1531, -1050, 632, 1692, 3, 1726, -1791, -271, 1323, -476, -535, 412, -2737, 283, -2330, -4810, 1448, -5227, -1626, 131, -5718, 1085, -2871, -4307, 1252, -4536, 95, -3425, -8454, 590, -364, -333, -2939, -7960, -143, 2446, -253, 306, -3792, 1164, 3844, -286, 1537, -2555, 1973, 3894, -777, 1300, -1574, 1533, 2500, -2628, -71, -1296, -489, -1166, -3121, -2726, -3433, -5670, -3792, -128, -8582, -8485, -6235, -58, 854, -7687, -2871, -6143, 1347, 377, -7730, -2181, -5759, 1924, -1303, -6183, -2034, -3184, 1734, -4352, -4901, -1175, -1961, 690, -6123, -6163, -380, -1114, -1276, -4134, -6434, -104, -255, -4373, -3757, -3147, -476, 242, -4180, -3269, -1111, -1338, 104, -2061, -2219, 166, -2512, -538, -1373, -1912, 685, -4003, -1385, -1579, -1990, 342, -4191, -2155, -2162, -1939, -832, -3269, -3213, -2741, -2222, -2703, -2967, -5960, -2692, -3177, -4837, -3360, -10138, -2100, -4946, -7464, -4119, -7264, -1641, -7960, -17034, -5208, -7912, -1717, -6457, -6163, -7603, -10526, -3117, -3422, -4688, -10362, -11629, -9873, -2331, -5694, -4713, -12123, -4805, -3354, -8220, -2881, -14195, -2801, -9380, -10442, -2935, -28777, -3447, -5569, -8423, -4078, -9149, -6445, -4630, -5853, -5031, -3927, -10362, -5208, -4369, -5818, -1274, -6123, -4115, -2705, -9238, -275, -4299, -4246, -1044, -6786, -542, -2567, -5085, -193, -2811, -1527, -2231, -4769, -594, -1943, -2416, -3638, -4795, -2257, -2841, -3760, -5607, -6354, -3386, -5115, -7445, -4826, -12123, -2664, -8982, -11945, -3455, -8485, -2128, -9873, -8304, -2768, -6814, -2460, -6786, -9531, -2829, -8790, -4532, -7034, -10210, -3428, -9873, -9639, -10613, -6480, -4238, -8112, -11232, -11115, -5623, -4386, -10799, -7408, -12123, -5319, -3916, -9106, -2730, -8034, -5103, -4319, -8393, -1135, -5539, -6332, -6093, -9936, -994, -4447, -7019, -10362, -8393, -1819, -4451, -8220, 8822, 6405, 7399, 8736, 8940, 8108, 6463, 6945, 8230, 8444, 6300, 5574, 5860, 6894, 6892, 4971, 1103, 5156, 5220, 4105, 3752, 1794, 5631, 3523, 308, 941, 4355, 6534, 2315, -1042, -1475, 3609, 7092, 1064, -262, 2831, 2053, 7104, -2149, 141, 5010, 3075, 6424, -2136, 967, 5572, 3899, 4428, -3080, 2160, 5193, 4063, -1720, -3971, 2729, 4869, 3813, 3597, 729, 2838, 5201, 3285, 5870, 2287, 2616, 5477, 3139, 6462, 2691, 1934, 5416, 3392, 6174, 2617, 1037, 5274, 2939, 5375, 2343, 409, 5104, 835, 4338, 1477, 20, 4546, -6434, 3082, -1333, -794, 3018, -3301, 1368, -551, -3161, -1070, -3110, 82, 2614, -7752, -1746, -8485, 427, 3135, -2280, 2055, -6928, 76, 1302, -39, 2952, -4674, -1500, -1419, 786, 2431, -367, -2659, 1626, 321, 516, 1682, -2716, 2762, -2399, -3096, 2207, -1478, 3437, -4842, -5170, 1807, 292, 3899, -40, -6480, 826, 1054, 3570, 669, -6422, -1270, 853, 2182, -1006, -2841, -10001, -349, -527, -1803, -1647, -1090, -4195, -5524, -187, -1622, 1487, -3321, -7752, -444, -1934, 2397, 37, -5576, -772, -613, 2402, 782, -4991, -122, 1514, 1893, 341, -4315, -382, 2946, 1275, -874, -2813, -1966, 3649, 905, -2939, -385, -2994, 3805, 447, -6705, 1507, -1546, 3452, -891, -8086, 2821, -1213, 2358, -2705, -4234, 3670, -2559, -119, -2245, -2073, 3915, -4115, -7179, -2847, -282, 3381, -3521, -2299, -6732, 646, 1818, -2195, -74, -2236, 308, -1558, -804, 581, -606, -1475, -5584, -561, 125, -1294, -3961, -1442, -2034, -1497, -2772, -3249, -499, -8138, -2528, -1841, -2152, -958, -3546, -1837, -1595, -2038, -2450, -634, -2030, -2883, -2504, -4258, 264, -2891, -5208, -2893, -4266, 104, -3498, -6786, -3304, -3571, -714, -4049, -6299, -5195, -3726, -1544, -3975, -5020, -8683, -3971, -2061, -3776, -3471, -3027, -2982, -3042, -4810, -2534, -1400, -2198, -5152, -5524, -3170, -1548, -2393, -8683, -4234, -6870, -3309, -3577, -7623, -2933, -6343, -6093, -5079, -5115, -1865, -4447, -4500, -5260, -4442, -1204, -4518, -4625, -3944, -4769, -918, -4215, -8649, -3393, -5333, -1063, -4234, -5020, -4038, -5759, -2000, -5871, -4500, -4659, -6267, -4108, -7865, -6173, -4491, -6814, -6870, -6204, -2407, -4386, -6679, -9429, -6256, -920, -5037, -6133, -7562, -5408, -1164, -3735, -5387, -4805, -4369, -2677, -2198, -5646, -4299, -4089, -5085, -2396, -6434, -5097, -3843, -6026, -4592, -5502, -6504, -4464, -5221, -6194, -5067, -6899, -7050, -5906, -3182, -5951, -5879, -14195, -10069, -2356, -7130, -5509, -5339, -7796, -3476, -8423, -5333, -2999, -3944, -5494, -15615, -5710, -2583, -1894, -5465, -9331, -8165, -3291, -989, -7665, -9149, -6540, -3370, -1182, -7730, -10526, -7353, -3507, -2797, -5933, -9238, 7163, 3687, 5260, 8213, 6927, 7099, 2930, 4980, 7774, 6104, 6680, 494, 4202, 6396, 3805, 5330, -2238, 3077, 4062, 3177, 2075, -2030, 1648, 2540, 3088, 1958, 913, -385, 3181, 857, 3995, 2958, -693, 3621, 2641, 4066, 3034, 1153, 3868, 3757, 3306, 881, 1696, 3399, 2009, 2354, -2000, 1067, 1075, -7335, 972, 1108, -542, -2813, 1110, -754, 2354, -2477, -681, 1451, -1726, 2622, 1049, -1597, 1460, -3038, 2053, 3143, 894, 2779, -4559, 424, 3398, 2886, 2453, 1076, -2425, 1810, 3045, 1969, 3164, -1512, -599, 1551, 4105, 3482, 703, 1603, -2733, 5065, 2147, 1542, 2633, -4086, 4530, -3331, 2566, 2539, -2406, 2913, 76, 3736, 2075, -5286, 2058, 3235, 4006, 1889, -3621, 2842, 4099, 3106, 2235, -1203, 3599, 3643, 834, 2223, -1038, 3658, 1940, -3701, 1122, -2016, 2423, -1124, -4357, -1084, -3574, 113, -4071, -4378, -1717, -5031, 1767, -2879, -5158, -511, -2135, 3054, -760, -1125, 505, 548, 3064, 974, -66, 1112, 2247, 2563, 2056, -524, 927, 3215, 1915, 2428, -1174, -555, 3404, 1122, 2253, -1849, -4064, 2614, 788, 1757, -2546, -4997, 329, 1078, 931, -3546, -2900, -5401, 1319, -44, -6422, -567, -2659, 1296, -811, -2208, 732, -833, 861, -1465, -1203, 497, -430, -227, -904, -3296, -324, -495, -1476, 583, -10899, 290, -957, -1272, 1293, -2485, 515, -2176, -1158, 596, -350, -718, -4438, -2345, -1813, 460, -2560, -5408, -2924, -2211, 262, -3230, -5487, -956, -522, -364, -4053, -4805, 120, -213, -522, -2793, -2733, -241, -1401, -573, -1804, -2594, -2897, -5387, -1062, -2271, -5020, -4640, -6856, -2235, -3257, -12319, -1258, -4460, -4509, -3215, -9479, -1044, -5214, -7247, -2801, -3944, -2756, -4038, -11629, -2226, -1211, -4754, -1913, -7583, -1734, -355, -4923, -1044, -4352, -2238, -647, -4640, -1345, -4640, -4728, -1616, -3396, -2811, -9380, -8304, -2655, -3490, -5516, -5638, -5862, -2514, -7146, -9106, -3215, -7230, -1398, -6163, -12534, -2817, -7281, -679, -3126, -9238, -3399, -4795, -641, -3618, -7034, -4010, -3577, -981, -8192, -6885, -4935, -2589, -1117, -7523, -9585, -7865, -2090, -989, -5818, -10613, -6577, -2225, -910, -7842, -7665, -5127, -2641, -1227, -10284, -7179, -5702, -2793, -2450, -7445, -7179, -6469, -3020, -5718, -5871, -6103, -6516, -3729, -10069, -4664, -5599, -6204, -4693, -6083, -3964, -6332, -5710, -5615, -6016, -3906, -7213, -5933, -6354, -6899, -4601, -6457, -6434, -7066, -7503, -6958, -5183, -6653, -8363, -10613, -11629, -4821, -7213, -8517, -7912, -5827, -5127, -9331, -7888, -5333, -5008, -3782, -10001, -6133, -5516, -5871, -3242, -8485, -4664, -7912, -6692, -5353, -11115, -4464, -9873, -7317, -28777, -8517, -4246, -5997, -9639, -9284, -7130, -3971, -4805, -11629, -9106, -5623, -3029, -4323, -5451, -6204, -4112, -4089, -4035, -3659, -5299, -4191, -5743, -5346, -4130, -4447, -7603, -7523, -8138, -5801, -3479, -8683, -7066, -8454, -7317, -3252, -6343, -5247, -6093, -13049, -4307, -8220, -3760, -5319, -7247, -6133, -8363, -3580, -5121, -4980, -6590, -10526, -5480, -4266, -5630, -6422, -11629, -8582, -5189, -6183, -8903, -6173, -4274, -10442, -5576, -5458, -3391, -2406, -4491, -5346, -6083, -9238, -5906, -4536, -6615, -3594, -4527, -5844, -2210, -2393, -5073, -4974, -5444, -4425, -7708, 1869, 1882, 1049, 1145, 1714, -6035, -8192, -4104, -7984, -7066, 8644, 8718, 8778, 8646, 8552, 12957, 12975, 12939, 12875, 12866, 15047, 15028, 14991, 14946, 14945, 15688, 15638, 15619, 15581, 15573, 15034, 14952, 14964, 14925, 14906, 12932, 12802, 12877, 12820, 12782, 8632, 8327, 8645, 8488, 8397, -6528, -2889, -3769, -8903, -5915, 1222, 2427, 1013, 1494, 1667, -7408, -2831, -4042, -6828, -5509, -3170, -7426, -2312, -3641, -2776, -10899, -6388, -4901, -11488, -7603, -7426, -2621, -4278, -6204, -4858, -10138, -3518, -6103, -10704, -6679, -5394, -5073, -7865, -8718, -13049, -8363, -4369, -7623, -5326, -12534, -7034, -3306, -4896, -3689, -10799, -7912, -4187, -6016, -4373, -9753, -14195, -6480, -8754, -4743, -4874, -10001, -8718, -9695, -5266, -4748, -9429, -9022, -11232, -6666, -8582, -10069, -8086, -12123, -7583, -9936, -11488, -9531, -10799, -10442, -6278, -9380, -10799, -8683, -9873, -5247, -7484, -8549, -9585, -10704, -5374, -6163, -6973, -8138, -13365, -7066, -5933, -6045, -6354, -12776, -9531, -6759, -5768, -6153, -11945, -10799, -10001, -5662, -7752, -11781, -6235, -9873, -4997, -8582, -9531, -4157, -7888, -5539, -8485, -7130, -4559, -9531, -8454, -9380, -5458, -6719, -11629, -10899, -6590, -4795, -7004, -7066, -8582, -4821, -5026, -6602, -5933, -8112, -4587, -6026, -7730, -6914, -8060, -5924, -8165, -9753, -8034, -8165, -9238, -11488, -10362, -6988, -8582, -11945, -9479, -10799, -8034, -8517, -10526, -9812, -12776, -15615, -9238, -9064, -17034, -13738, -10526, -10001, -9873, -11781, -9022, -9284, -9284, -13738, -10704, -7162, -8942, -10799, -17034, -11488, -6480, -6914, -28777, -12776, -10362, -6856, -6504, -10284, -11232, -9585, -9429, -8304, -7842, -28777, -9585, -14784, -9812, -6786, -10442, -10799, -8333, -12319, -6786, -9695, -11945, -8192, -14784, -7623, -8060, -8485, -10442, -11004, -9639, -6590, -7842, -11115, -11629, -13365, -6973, -9331, -10362, -13738, -12319, -8423, -11115, -8790, -10613, -12534, -10138, -8942, -6628, -7464, -10799, -10799, -7687, -5546, -8247, -7484, -11945, -9064, -6173, -17034, -5195, -28777, -13738, -9149, -11115, -4486, -17034, -10284, -17034, -11781, -5055, -11781, -8138, -15615, -14784, -5933, -10284, -7819, -11232, -10899, -6354, -11781, -9284, -8827, -8790, -6773, -15615, -12776, -8009, -7665, -7623, -14195, -28777, -8903, -7730, -9331, -12123, -28777, -10210, -11004, -4307, -6577, -6590, -7389, -5776, -4923, -13365, -6256, -8582, -6885, -6445, -11488, -6321, -11488, -11781, -7730, -9380, -7644, -6235, -6870, -6640, -11781, -6653, -5702, -4858, -8423, -6516, -6842, -6153, -3349, -8086, -4713, -15615, -5997, -2956, -5960, -4282, -10138, -5346, -3586, -6516, -4774, -8582, -3975, -3493, -5942, -5195, -5176, -4142, -2552, -9695, -2924, -3354, -8649, -2383, -11781, -1787, -2612, -5979, -8060, -4683, -5195, -4583, -9331, -4504, -1870, -3425, -3391, -3012, -7408, -8903, -9639, -4847, -7371, 1023, 1298, 733, 1225, 1518, -6235, -6732, -4935, -3870, -8649, 8697, 8728, 8774, 8757, 8620, 12889, 12938, 12926, 12920, 12889, 14951, 14991, 14962, 14962, 14956, 15584, 15612, 15572, 15578, 15579, 14929, 14946, 14892, 14903, 14907, 12833, 12834, 12757, 12777, 12785, 8538, 8507, 8347, 8410, 8461, -6553, -9585, -5158, -7752, -12534, 1497, 1372, 1741, 1370, 603, -4625, -8790, -6422, -5970, -8423, -7484, -2807, -3339, -2589, -2065, -5539, -7484, -9064, -6064, -3811, -3071, -8718, -5480, -7335, -2463, -5678, -8276, -7665, -10001, -4130, -6692, -4299, -11629, -7408, -6093, -6007, -5273, -13738, -9639, -7912, -3529, -7264, -13738, -5273, -9022, -3474, -6914, -6958, -5897, -8060, -4357, -5319, -4748, -7299, -7752, -4805, -5546, -5726, -6732, -11232, -4518, -7888, -9812, -7687, -9812, -4698, -10210, -10069, -9331, -7247, -6093, -9639, -9695, -6679, -7408, -7464, -11115, -9639, -6310, -7623, -8549, -12319, -7708, -8827, -7464, -8718, -8304, -7034, -14784, -8718, -8942, -7623, -8333, -12319, -10899, -8304, -6732, -10138, -8363, -9380, -8393, -5678, -10001, -8333, -10613, -8683, -5592, -7445, -10001, -15615, -8615, -7247, -7050, -10613, -11629, -9022, -13049, -8138, -8982, -7426, -8393, -12319, -8649, -6914, -6054, -7562, -8827, -8192, -5554, -5678, -7842, -7113, -8615, -5158, -6445, -10069, -6565, -8865, -5458, -8754, -14195, -7389, -7819, -5623, -8304, -14784, -8982, -7960, -5158, -7865, -14195, -9284, -9022, -4620, -8060, -13738, -10001, -9284, -4674, -7623, -11629, -9531, -8942, -5516, -7389, -10001, -8865, -8485, -6899, -8827, -11629, -9380, -8485, -7162, -10704, -8582, -7796, -7842, -6267, -8754, -6828, -6856, -7752, -6225, -9022, -7708, -7445, -9284, -7281, -9812, -10526, -7523, -10362, -7503, -9022, -11629, -7019, -10899, -6399, -10138, -10210, -7247, -14784, -6093, -28777, -10138, -8034, -10799, -7299, -9585, -11488, -10210, -9639, -10799, -7583, -10284, -13738, -9531, -14195, -7130, -7687, -9936, -9936, -9531, -6422, -5871, -10069, -10284, -7583, -6123, -5942, -28777, -10613, -8220, -7408, -7819, -10210, -11004, -12534, -8454, -8718, -8649, -10899, -12534, -7912, -7865, -9193, -10069, -11232, -8683, -8009, -11629, -9149, -11629, -10069, -9193, -17034, -9380, -11781, -10899, -11781, -9753, -9873, -11115, -10799, -14195, -8615, -10138, -9331, -9936, -14195, -8582, -9064, -8903, -9284, -11004, -6615, -4323, -5546, -7464, -7984, -6074, -4408, -7146, -8304, -6870, -6553, -3798, -6528, -7484, -7842, -8865, -3689, -7796, -5286, -10210, -6870, -4134, -8034, -4578, -10138, -6343, -4031, -4831, -2960, -7730, -9639, -2918, -3964, -1644, -6064, -6705, -2709, -4523, -2032, -6235, -4805, -3641, -5531, -3804, -7066, -4006, -3498, -5915, -3133, -8363, -3563, -3031, -13049, -2590, -4573, -3496, -2594, -6553, -2954, -6246, -14195, -4545, -6469, -8903, -3121, -3375, -4616, -2267, -3985, -4708, -3900, -3314, -5546, -5055, 1399, 1967, 2093, 896, 1351, -7623, -6928, -8549, -3824, -5743, 8664, 8640, 8637, 8910, 8824, 12887, 12912, 12897, 12993, 12948, 14942, 14968, 14952, 14998, 14964, 15560, 15579, 15567, 15588, 15559, 14886, 14896, 14890, 14893, 14870, 12760, 12763, 12765, 12748, 12730, 8405, 8412, 8417, 8354, 8329, -5924, -13365, -9022, -7562, -6103, 1189, 779, 1209, 1178, 1529, -7113, -4442, -7542, -12319, -7162, -2817, -1299, -3996, -2751, -3422, -7819, -5569, -12123, -9429, -9380, -5743, -7542, -4748, -6504, -5836, -14195, -6064, -10899, -14784, -9193, -6640, -5266, -6354, -6480, -6504, -7960, -5933, -9022, -7819, -8790, -7912, -5546, -10138, -13738, -10799, -7888, -7097, -8485, -9753, -12776, -10442, -13738, -6842, -6653, -9429, -9812, -12534, -6093, -7984, -9193, -6988, -8363, -7281, -10362, -9149, -6540, -7523, -8276, -7353, -7865, -7445, -7162, -7335, -6321, -6343, -7819, -8549, -8034, -6310, -5654, -6786, -17034, -8247, -7299, -5710, -7130, -10442, -6988, -8112, -5784, -10210, -10799, -7464, -7230, -5924, -13738, -10210, -7912, -7389, -6163, -8165, -7583, -8903, -11488, -5933, -5380, -5592, -10799, -10362, -5576, -4769, -5494, -8549, -9193, -7335, -5312, -6445, -5933, -8517, -8220, -5599, -6679, -4997, -8333, -6540, -5380, -5862, -4901, -9429, -7081, -5960, -5853, -5437, -10362, -8582, -7819, -7464, -7004, -9873, -9873, -9380, -9531, -8649, -11356, -9479, -7984, -8304, -8086, -13738, -7583, -6469, -7066, -8034, -8827, -8009, -6457, -7281, -10001, -9193, -14195, -7774, -7752, -10704, -9531, -7050, -8549, -6153, -10899, -8649, -6399, -9238, -4940, -8982, -9695, -9284, -11781, -5247, -6615, -7984, -17034, -9479, -7130, -6365, -5569, -10069, -8517, -9193, -8086, -5014, -9284, -8982, -8790, -10526, -6310, -10362, -8790, -7644, -10704, -10526, -11781, -7603, -7066, -14195, -10442, -9639, -6958, -7317, -17034, -8393, -7426, -7179, -8454, -14784, -8485, -6800, -7464, -10001, -13049, -8454, -7353, -7179, -10138, -12776, -8485, -8276, -6973, -9149, -12123, -9812, -9479, -7752, -9695, -9106, -12319, -14195, -10138, -10799, -7281, -12123, -10613, -13738, -7842, -6800, -11945, -8304, -14195, -6321, -7960, -14784, -9639, -13365, -6288, -10799, -14784, -15615, -13738, -7623, -13738, -13049, -28777, -14195, -10526, -15615, -12776, -17034, -14784, -12776, -14784, -17034, -15615, -13738, -11232, -11356, -14195, -28777, 12983, 8466, 12344, 11392, 6461, 12380, 8703, 11634, 10869, 5922, 10364, 8737, 9285, 9233, 4385, 5508, 8522, 4691, 6360, 3469, 3990, 8762, 3806, 2616, 4362, 6738, 8873, 3098, 927, 4760, 6552, 8370, 1133, 3740, 4637, 4825, 7566, 1153, 4516, 4528, 505, 6857, 585, 2372, 4276, 326, 6123, 1571, -416, 3811, 3583, 5147, 2412, 4610, 3586, 4122, 3992, 2286, 5935, 3851, 2898, 3285, 1987, 5780, 4498, -1384, 3170, 2228, 4459, 5196, -2026, 2326, 2240, 2699, 5702, 1171, 506, 1386, 3207, 5755, 1764, 2206, 904, 3826, 4887, 2222, 3757, 1995, 3129, 2468, 3180, 3870, 2658, 942, 52, 3634, 2839, 2456, 320, 976, 3623, 1191, 1604, 2480, -885, 4603, 1822, -525, 3460, -782, 5581, 2952, -7583, 3661, 1818, 5375, 2516, 1379, 3371, 1904, 3979, 1095, 3413, 2724, 295, 2803, 2173, 3843, 2163, -2385, 2485, 2834, 3487, 1736, -2409, 713, 1200, 2875, 930, -201, -2075, -2698, 2360, -206, 1030, -335, 1973, 2030, -1165, 1748, -562, 3507, 1755, -2140, 2111, -2956, 3447, 1208, -3479, 1329, -7774, 2264, -274, -2064, -2785, -4100, 446, -5810, -735, -425, 42, -35, -2204, -666, 2481, 1366, 911, 852, -333, 2815, 934, 1890, 1563, 554, 1385, -1336, 2567, 1102, 550, -1894, -6376, 2435, -70, -911, -2829, -2457, 958, -1321, -3425, -1625, 208, -495, -1875, -1609, -1192, 1831, 1443, -1879, 491, -833, 2715, 2199, -1954, 1279, -1153, 2768, 1427, -1787, 1024, -2191, 1800, -707, -1361, 429, -1825, -546, -3438, -1469, 132, -506, -3306, -3067, -2342, -434, 361, -1826, -2148, -2438, -1419, 693, -1060, -2789, -1291, -2326, 540, -1398, -5646, -281, -3230, 120, -2630, -11488, 255, -4086, -627, -5260, -6332, 89, -3741, -1594, -15615, -3076, -947, -2797, -1242, -8009, -1610, -2895, -2657, -440, -8192, -1745, -5759, -3449, -303, -10613, -3589, -10442, -3436, -614, -3603, -5997, -10613, -2567, -1078, -1281, -4863, -10138, -2612, -1569, -520, -4495, -7408, -3833, -1657, -926, -3920, -4923, -6388, -1532, -2597, -2969, -3811, -7523, -2140, -5735, -2642, -2462, -5569, -3792, -8903, -2857, -1095, -3814, -4282, -7081, -3203, -232, -2463, -3808, -4550, -3029, 77, -2125, -5353, -3463, -2450, -288, -2714, -5827, -3230, -2220, -1383, -3518, -3274, -3360, -2747, -3014, -3735, -2954, -3860, -4664, -4266, -3515, -4620, -5145, -10138, -4303, -3276, -8549, -7408, -11232, -4743, -3592, -13049, -7523, -7371, -5367, -4664, -12534, -4142, -4679, -4075, -4683, -7819, -1976, -3738, -2964, -3396, -6064, -914, -4863, -3261, -3286, -4100, -790, -9873, -5026, -4779, -2705, -1613, -4451, -5115, -7912, -2533, -3729, -2303, -3540, -8982, -3714, -8485, -2100, -3257, -5897, -6267, -6828, -3168, -4416, -3299, -5208, 6641, -9022, 10014, 6932, -1285, 6421, -1480, 9436, 7458, 1188, 5645, 2610, 7535, 8047, 2195, 4735, 4517, 3383, 7927, 1683, 5629, 4916, 677, 7040, 793, 6675, 4017, 3672, 5761, 24, 6487, 2575, 4180, 5137, 538, 5092, 2426, 3491, 5309, 924, 3984, 2299, 1425, 5228, -717, 3747, 2723, -1441, 4428, 616, 1867, 4179, 1667, 2892, 3293, 1701, 4930, 3607, 1086, 4534, 4106, 4823, 3888, 466, 5018, 4366, 4170, 2549, 1764, 4844, 2309, 3279, 1656, 3391, 3867, -3065, 2441, 3906, 4277, 2018, 2846, 1991, 5039, 4113, -508, 4320, 1427, 4954, 2669, -2954, 4298, -544, 3932, -1070, -4532, 3797, -1827, 2483, -3689, -4800, 3753, 796, 1513, 252, -2135, 4138, 1456, 1353, 1074, -456, 4171, 898, 1583, 871, -337, 3238, 175, 1024, 1179, -1526, 566, 287, -1177, 2338, -1895, -3903, 874, -4447, 3044, -501, -182, 686, -5702, 3154, 282, 680, -897, -3301, 3143, 548, 350, -3985, -1326, 3063, 734, 651, -5208, -1914, 2360, 1041, 1284, -2238, -6615, 387, 1321, 1603, -596, -3417, -4340, 1313, 2419, -419, -267, -6343, 929, 3345, -1096, 1233, -4509, 503, 3560, -2006, 1986, -4578, 421, 2957, -3375, 2159, -3137, 481, 1964, -2125, 1832, -2116, 563, 1390, 388, 1080, -2204, 597, 1090, 1687, -76, -3194, 23, 254, 1963, -1079, -834, -1623, -2399, 1268, -702, 1592, -3647, -6113, -443, 252, 2691, -4482, -453, -2270, 784, 2846, -3208, 1029, -1537, 470, 2426, -989, 1175, -343, -1194, 1835, -405, 404, 38, -5933, 1317, -1371, -1761, -562, -5784, 731, -2118, -4500, -1603, -3154, -261, -1164, -1740, -1446, -2731, -1899, -1024, -816, -1005, -2999, -3609, -1717, -1398, -1076, -3817, -3087, -2260, -3447, -1105, -5458, -1917, -2435, -7050, -742, -9429, -1559, -2653, -2837, -443, -5487, -2207, -2908, -1002, -616, -2232, -4184, -3210, -769, -1488, -1135, -9380, -3577, -1431, -3196, -1630, -5793, -4157, -2182, -4172, -4311, -2885, -4743, -2132, -2201, -11629, -1680, -4784, -1212, -723, -4270, -814, -4708, -487, -185, -3133, 428, -5784, -565, -483, -3220, 1544, -14784, -1568, -1605, -3515, 1989, -5524, -3415, -3294, -3600, 1609, -3452, -5997, -4774, -2975, 283, -4138, -9106, -4412, -1765, -2497, -3996, -12123, -1937, -904, -10799, -1660, -12776, -887, -837, -5429, -947, -9022, -1666, -1611, -4250, -1784, -8086, -3455, -3007, -5897, -3900, -6299, -2897, -3947, -17034, -6590, -4089, -2849, -3896, -5091, -9022, -3326, -4532, -4754, -3110, -5524, -3833, -6842, -11629, -3213, -3038, -3996, -8393, -4017, -5152, -1874, -2465, -9753, -476, -8138, -1381, -1210, -7523, 1019, -7389, -1357, -724, -4049, 1292, -5152, -1799, -1083, -1897, 459, -2644, -2716, -2390, -1028, -1522, -1132, -3989, 8639, 8433, -1228, 8965, 4876, 8228, 7718, 4726, 8594, 5063, 7076, 5210, 6354, 7458, 4833, 5526, -2424, 5894, 5453, 3010, 4164, 1836, 3901, 2248, -1123, 3075, 2791, 3507, -4997, 3103, 1547, 1485, 4525, -1727, 4722, -669, -1895, 4015, 660, 4281, -1112, -9812, 1797, 682, 357, 551, -7081, 203, -1030, 1809, 2363, -4805, 1729, -2295, 5573, 3098, 957, 1841, -1607, 6763, 2731, 3022, 246, -4138, 7010, 2067, 3062, -430, -1722, 6901, 1854, 751, 1400, 1568, 6515, 1354, -1704, 1351, 2000, 5632, 229, 1042, -1413, -132, 4024, -1084, 157, -2303, -5333, 1880, -3399, -11115, 231, -2480, 2450, -6615, 1257, 103, -8112, 4125, -1409, 3194, -1411, 408, 4623, 513, 3307, -3373, 2865, 3766, 1561, 2018, -3659, 3266, 886, 2293, -1206, -615, 2429, -1319, 2346, -2475, 1007, 750, 1659, 1237, -173, 1398, -1381, 1832, -1701, -92, 1144, -2637, -613, -9873, -1564, 975, -3933, -1284, -11356, -4097, 1184, -2793, 2481, -5079, -4620, 1234, 1121, 3869, -593, -2943, 907, 2930, 4064, 1427, -2205, 494, 3505, 3465, 2313, -2933, 318, 3319, 2384, 2448, -4587, 446, 2791, 1361, 1854, -2659, 610, 2286, 1592, 246, -1155, 575, 1779, 3000, -2831, -1207, 415, 890, 4033, -2644, -2430, 240, 52, 4175, -656, -4991, 246, 1121, 3334, 146, -8903, 865, 2385, 1424, 232, -1411, 1617, 2712, -1662, -424, 975, 1771, 2113, -4935, -1887, 1733, 1068, 756, -4042, -3817, 1432, -459, -953, -1926, -4336, 443, -1721, -2394, -605, -3133, -275, -1533, -3187, -620, -2311, -118, -1638, -3644, -2713, -2172, -356, -2204, -5109, -4733, -2364, -2047, -1807, -6553, -1473, -2793, -4447, -1011, -3526, -836, -3814, -2730, -825, -1912, -1361, -4713, -2764, -1393, -1556, -1480, -4195, -6719, -2564, -2201, -1628, -3999, -5686, -3843, -3430, -2891, -3732, -3144, -4946, -3047, -6321, -3289, -4071, -5079, -1706, -7004, -3824, -11004, -3433, -897, -2590, -3853, -6093, -2707, -684, -628, -2450, -4021, -3788, -1165, 208, -2008, -3951, -7819, -2500, 203, -2997, -4278, -6480, -4340, -338, -5020, -3850, -3388, -5776, -845, -4230, -2887, -1583, -8754, -1543, -2960, -2257, -490, -8942, -3168, -2522, -2334, -160, -4664, -3656, -1959, -3130, -648, -2910, -2090, -1419, -4211, -2229, -2087, -1033, -1469, -4664, -5906, -2068, -348, -2148, -4654, -7752, -3187, -275, -3163, -5662, -6103, -6332, -1275, -4010, -8363, -9753, -7523, -4038, -3732, -4738, -7796, -5539, -7960, -2495, -2902, -4361, -5793, -4640, -1578, -2839, -3396, -6856, -2698, -1377, -3396, -3108, -9193, -1689, -1841, -3557, -3357, -8247, -1904, -2670, -4491, -4130, -2811, -3618, -3729, -9284, -4108, -436, -3801, -5286, -6914, -3671, 602, -1820, -6457, -3964, -4149, 782, -1314, -4429, -4278, -7583, -1988, -2573, -3798, -3401, -6153, -1867, -1335, -4478, -2322, -4093, -2514, -1215, -7081, -1609, -4550, -2581, -2153, -6143, -1119, -10362, -2172, -4089, -3417, -1093, -5127, -2505, -5158, -2906, -1857, -2259, -3479, -3964, -4416, -3257, -1897, -4089, -2550, -8276, -3396, -3482, -3662, -1197, -6093, -2956, -5561, -3005, -405, -5516, -3860, -2622, -3133, -451, -5776, -8086, -1141, -4541, -1394, -3543, -6958, -915, -7936, -2776, -2172, -3319, -1323, -10799, -2906, -1923, -2242, -1740, -6235, -2445, -2545, -2337, -2102, -4226, -2470, -4149, -3449, -3112, -3321, -2437, -7484, -5662, -5592, -3479, -2050, -4509, -5176, -4929, -4679, -1811, -1759, -3147, -2711, -4853, -2040, -792, -2628, -2217, -4046, -3154, -1075, -3624, -2964, -4518, -5862, -1859, -6411, -4743, -4620, -6705, -1925, -9753, -6899, -3031, -4573, -1916, -7984, -7179, -2091, -4262, -2578, -6958, -7542, -2058, -5109, -3923, -6653, -8276, -2975, -5592, -5353, -6365, -6899, -5008, -4478, -5844, -5718, -6399, -5367, -3396, -5988, -5702, -5776, -3695, -2863, -6007, -5942, -4262, -3360, -2791, -6411, -5133, -3843, -3930, -3191, -7603, -3916, -5444, -4451, -4199, -7445, -3154, -9695, -5240, -6640, -7865, -3415, -5942, -7299, -14195, -15615, -4896, -5227, -6786, -4635, -6653, -6123, -6225, -4759, -2279, -3999, -5836, -5554, -4319, -1663, -3329, -7371, -4874, -4935, -2594, -4010, -8517, -5670, -5951, -6083, -5801, -3951, -7130, -6399, -7179, -5871, -2030, -6958, -5097, -3883, -4307, -1505, -5853, -3540, -3460, -3886, -2225, -4438, -2613, -4869, -4784, -4611, -3316, -1983, -8718, -7335, -12319, -3144, -1329, -6800, -14784, -8112, -4172, -971, -4532, -9149, -6492, -6469, -1242, -3954, -7842, -5569, -5897, -2128, -4469, -8276, -4669, -4473, -3286, -5592, -8582, -4674, -4282, -4500, -6246, -7888, -5480, -4460, -6278, -6113, -6870, -6143, -4382, -9331, -5374, -5970, -5429, -4365, -10526, -4759, -5793, -3773, -4518, -6705, -4486, -6692, -2902, -4215, -4569, -4021, -7819, -3098, -3537, -3760, -3609, -6899, -3717, -3225, -3930, -3754, -6745, -4149, -3748, -4451, -4282, -8247, -4386, -5759, -4573, -4800, -7960, -4495, -10210, -4420, -5458, -7230, -4901, -8454, -4482, -6943, -8718, -6214, -9479, -5516, -10899, -10899, -8304, -11781, -9064, -11004, -11356, -6914, -8034, -8790, -6759, -11781, -6074, -8112, -5793, -5339, -5997, -7523, -10704, -4896, -4991, -3452, -10284, -13738, -4644, -5353, -2605, -8790, -12319, -4664, -6183, -3156, -7503, -11232, -5073, -7623, -5394, -6354, -11232, -6246, -9873, -11232, -5346, -12776, -6692, -11356, -10442, -5079, -10613, -4951, -8549, -8718, -6026, -8393, -3886, -6445, -8485, -7389, -7389, -3985, -5394, -8304, -6516, -6842, -5227, -5253, -8363, -6123, -5960, -7752, -6434, -8192, -7371, -4769, -9695, -10613, -7299, -11232, -4234, -7865, -8304, -7213, -12534, -4940, -6719, -5607, -4097, -1277, -4093, -629, -5152, -4299, -2417, -3748, -1023, -6214, -3029, -3933, -2964, -2319, -8790, -1610, -4625, -3218, -4769, -6163, -842, -4211, -3641, -7162, -2624, -879, -4157, -3047, -5055, -1195, -1696, -5061, -2690, -3820, -1165, -3476, -5784, -3326, -3686, -2430, -7230, -4698, -3989, -4086, -5133, -7230, -3367, -3259, -4420, -7796, -4545, -2624, -2795, -4555, -7774, -3674, -2399, -3130, -5202, -6679, -3373, -2347, -4024, -6958, -4086, -3360, -2149, -5266, -7484, -2455, -3788, -1884, -7050, -4968, -1965, -4340, -1810, -11781, -3393, -2325, -4688, -2060, -9873, -2950, -3067, -5599, -2166, -6914, -4203, -4438, -9380, -1485, -6064, -8649, -8903, -8718, -856, -5133, -3589, -5623, -5127, -1114, -4282, -1720, -3334, -3430, -2282, -3889, -1959, -3244, -1872, -2597, -3540, -4395, -3609, -1138, -1833, -2787, -15615, -3391, -1660, -1713, -1877, -4708, -2941, -4013, -1927, -1303, -3518, -2364, -28777, -1980, -1443, -4504, -2414, -4625, -2305, -2499, -7687, -3689, -2969, -2867, -3586, -6321, -6194, -3415, -3187, -2863, -4134, -8982, -6064, -3201, -2422, -4180, -12776, -8683, -2528, -3274, -7603, -13049, -4532, -1939, -4779, -7708, -10362, -3103, -2490, -3571, -3927, -8942, -3031, -4858, -1898, -3621, -8060, -4286, -10799, -1147, -5630, -6480, -9331, -28777, -1127, -11004, -4779, -6528, -8393, -1725, -5103, -4134, -3005, -4352, -3071, -2831, -4821, -1917, -2809, -5970, -1917, -7484, -2166, -2728, -12123, -1922, -7426, -3656, -3866, -8060, -2875, -4038, -6153, -6173, -7644, -4527, -2514, -7583, -8827, -6007, -5380, -2143, -7484, -10069, -4006, -5623, -2831, -5638, -9149, -3117, -6899, -4482, -4319, -7389, -3045, -8304, -6445, -4161, -7196, -3741, -7542, -9873, -3916, -8485, -5827, -6445, -5915, -2758, -10526, -14195, -5516, -2969, -1825, -8220, -7113, -5158, -2289, -1682, -4974, -5133, -5374, -3386, -2433, -3357, -4784, -6035, -6214, -4230, -2986, -4748, -5247, -6343, -6814, -3656, -4587, -3036, -5422, -7130, -5127, -4606, -1727, -6113, -6054, -6434, -5380, -1586, -7665, -5387, -5524, -7213, -2316, -8304, -4974, -4282, -8086, -2943, -7081, -4874, -3903, -7335, -2924, -5915, -5480, -4644, -7445, -3566, -5127, -6565, -6988, -7004, -5759, -4500, -6705, -9585, -5615, -7299, -4075, -5970, -6679, -4378, -6411, -4299, -5002, -4869, -3804, -7936, -5933, -4669, -3870, -4412, -10138, -11781, -5879, -3612, -7484, -6113, -8683, -11232, -4191, -10613, -4795, -6828, -6640, -5253, -5844, -5109, -7888, -4153, -6411, -5472, -6973, -11232, -3594, -7665, -6445, -11356, -7583, -4108, -9193, -6814, -13049, -4545, -5176, -13738, -7317, -7445, -2939, -6332, -13365, -9022, -5646, -2470, -8138, -10442, -9106, -5654, -3089, -13738, -11232, -7066, -6943, -4805, -8615, -11488, -5844, -7842, -7583, -6411, -8333, -5623, -7179, -7984, -6692, -6745, -6173, -6628, -6343, -7888, -6376, -6800, -6973, -6194, -5630, -3504, -5152, 304, -2356, -5279, -3930, -4513, -717, -5924, -6469, -4290, -3215, -2268, -7562, -9873, -4769, -2571, -3833, -3468, -7066, -6267, -2463, -3785, -2490, -4738, -10442, -2478, -3476, -2926, -3785, -11356, -2457, -4357, -4550, -3247, -8615, -2642, -5546, -5444, -2900, -8790, -3309, -3996, -2730, -2979, -7936, -4573, -2752, -1042, -4138, -5576, -6492, -2429, -863, -8718, -4038, -8754, -2630, -2257, -5055, -3108, -5888, -3218, -5353, -2028, -2580, -2947, -4315, -5008, -1020, -2605, -1484, -5353, -3776, -923, -3729, -1239, -4693, -3609, -1018, -7484, -2447, -3463, -3259, -800, -8942, -6928, -2709, -2299, -601, -4611, -6045, -2361, -1372, -976, -3546, -3096, -2396, -920, -1943, -3896, -3189, -3007, -1016, -2869, -5718, -5306, -4790, -1264, -3337, -11781, -5630, -9812, -1020, -3889, -7247, -3873, -7130, -521, -4408, -4500, -3751, -4513, -359, -4319, -3632, -4985, -3668, -828, -3896, -3501, -6958, -3677, -2409, -3968, -3444, -8790, -4469, -7842, -5539, -3501, -7623, -5630, -4869, -13738, -3409, -6045, -6074, -1869, -5784, -2553, -4890, -5103, -1226, -3563, -1982, -3463, -3498, -1678, -3349, -2756, -2799, -2789, -2799, -4071, -6666, -3571, -3168, -4303, -4246, -5979, -6973, -3853, -5988, -3732, -2285, -9585, -4500, -7408, -3896, -1483, -4997, -6653, -6828, -4946, -2378, -3606, -11356, -4723, -6054, -5776, -2871, -6093, -3701, -5862, -9639, -2545, -3999, -4056, -4968, -4774, -2677, -2916, -5189, -4390, -4130, -3078, -2567, -5569, -4357, -4674, -3085, -2967, -6899, -4703, -5408, -3117, -4527, -9238, -4688, -6246, -4149, -11488, -4064, -4842, -7730, -5380, -5049, -1793, -6278, -9695, -3441, -2143, -734, -4654, -10613, -1937, -1323, -417, -1908, -6299, -1546, -1647, -674, -812, -4127, -2146, -2541, -1348, -1010, -3763, -3951, -3149, -2207, -2024, -5139, -4654, -3404, -2999, -2639, -9284, -2200, -3563, -3515, -2386, -14195, -1123, -3378, -3615, -2391, -11629, -1485, -2977, -3254, -3027, -11488, -3365, -2929, -2933, -4723, -8754, -7213, -3886, -2855, -9753, -7081, -8718, -6692, -2745, -7774, -5915, -7960, -6590, -2543, -4509, -4698, -8790, -4230, -2776, -3795, -3650, -9812, -3589, -4230, -4630, -2952, -9064, -3968, -7542, -5997, -2698, -7281, -4946, -5670, -5202, -2922, -5836, -6064, -4010, -4842, -3665, -5367, -7542, -3866, -5152, -4738, -6153, -10613, -4569, -4006, -5924, -7752, -9149, -6093, -2958, -6988, -6856, -6828, -8363, -3124, -7623, -5615, -6153, -6653, -4625, -8304, -5509, -6540, -4527, -6899, -7445, -6376, -8276, -3735, -7562, -5145, -8220, -13738, -3776, -8649, -3937, -8982, -11488, -4246, -12534, -3975, -7865, -8220, -5360, -12534, -5073, -7019, -6814, -7583, -11115, -7034, -6590, -6278, -6399, -11356, -9479, -6540, -6504, -4266, -28777, -14784, -7081, -7353, -3386, -11945, -10138, -7665, -7004, -3512, -9873, -6480, -8165, -5429, -4578, 6593, 3030, 1538, 6735, -3388, 6250, 2597, 1701, 6297, -1212, 5305, 1149, 1623, 5029, 852, 4075, -2288, 823, 3180, 2145, 3078, -7796, 216, 1115, 2889, 2249, -2043, 993, -2197, 2992, 943, -1459, 1852, -5133, 2263, 410, -1761, 2430, -72, 800, 819, -179, 2860, 1829, 553, -1209, 1652, 2740, 2877, 2116, 1362, 3020, 1299, 3377, 3701, 4582, 4225, -37, 3143, 5044, 5643, 5346, 2696, 1786, 5895, 5377, 6168, 3704, -242, 6002, 4448, 6394, 2690, 929, 5225, 3888, 5742, -526, 1833, 3773, 3467, 3792, 1936, 1358, 2873, 2329, -393, 3745, 94, 2228, 1512, 75, 3814, -1690, -93, 2392, 1020, 2661, -3612, -1816, 2772, -695, 969, -287, -583, 1903, -561, 232, 1779, -974, -475, 969, -1284, 2667, 1299, -5494, -222, -8393, 2952, 2553, -6988, -11115, 945, 2854, 1571, -5109, 688, 3075, 2353, -2945, -3071, 2798, 3446, 1365, 1195, -7, 3496, 2658, -465, 3161, 1703, 3593, 1298, -4625, 3128, 2164, 3229, 325, -1254, 1624, 1362, 2432, -48, 1774, -1066, -1865, 1408, 750, 3080, -3012, -3893, 411, 1726, 3408, -5312, 961, -517, 1730, 3047, -6332, 2111, -1748, 678, 2222, -3487, 1821, -2429, -403, 1194, -3814, 564, -382, -424, 331, -4842, -989, 817, -1142, -140, -2101, -939, 432, -2326, -365, -87, 378, -1663, -1107, -599, 1056, 1447, -3629, -744, -1047, 1613, 1991, -3142, -2698, -1760, 1621, 2080, -5380, -2630, -2714, 1089, 1814, -7162, -266, -3795, 104, 1204, -3391, -181, -3860, -1191, 177, -3213, -2232, -2369, -2751, -1324, -3893, -6590, -1126, -4578, -3365, -2383, -6640, -771, -4821, -5793, -834, -10362, -1288, -4021, -4378, 73, -7644, -2118, -4211, -2409, 533, -4386, -2004, -5615, -1627, 432, -3156, -1762, -6565, -1683, -450, -2336, -2546, -5531, -2115, -2312, -1854, -4180, -5079, -2083, -3860, -2130, -3751, -5145, -1793, -2752, -3883, -2356, -4748, -2251, -1627, -9193, -1781, -4053, -4464, -1368, -7665, -1781, -3798, -5360, -2297, -9106, -1923, -4728, -1756, -5031, -7264, -1875, -8165, -585, -11115, -3117, -1738, -8086, -1181, -7264, -2344, -1690, -5487, -3840, -5879, -3910, -1807, -4659, -17034, -5380, -8549, -2040, -4258, -6705, -5139, -3933, -2396, -4790, -5678, -5333, -2265, -3034, -7213, -5853, -5906, -2168, -4327, -7912, -5451, -6411, -3010, -6615, -5494, -4145, -6759, -4352, -7623, -5451, -2871, -8086, -4912, -6705, -8060, -2115, -17034, -4495, -7317, -11781, -2000, -8517, -4754, -10138, -7752, -2409, -6113, -5970, -12534, -9022, -3239, -6093, -7299, -8982, -7984, -4738, -7603, -7097, -6074, -4482, -8112, -9531, -5793, -4348, -3401, -8865, -9585, -4991, -3744, -3757, -5458, -7865, -5353, -4311, -4968, -4923, -5970, -7317, -6343, -6153, -6856, -4597, -9873, -10899, -6204, 1100, 6058, 1262, 2909, -8304, 2480, 5532, 2293, 2255, 1405, 3401, 3810, 3401, -217, 3985, 2749, 476, 3689, -7819, 4990, 398, -847, 3265, -284, 5012, 553, 668, 2244, 1759, 4306, 3124, 1150, 286, 2546, 2994, 4618, 1022, -4974, 2675, 810, 5369, 61, -3067, 2254, -2435, 5451, 1225, -1758, 1528, -3618, 5105, 4067, -62, 1110, -161, 5514, 5608, 3900, 1295, 2631, 6450, 5978, 5828, 1423, 3820, 6658, 5414, 6206, 1258, 3695, 5953, 4252, 5103, 2447, 2361, 4714, 2964, 1905, 4220, -153, 3574, 1759, -1407, 5231, -3373, 2705, -175, 986, 5531, -4713, 1455, -6083, 310, 5342, -4071, -1755, -483, -3218, 4798, -4821, -7842, 874, -10442, 3995, -4874, -3170, -946, -8649, 3129, -3744, -2666, -1948, -4769, 2334, -4713, -280, 1915, -440, 1301, -3311, 1086, 3469, 1578, -460, -1780, 1468, 3979, 2469, -1979, -2764, 1497, 3816, 2633, 65, -4086, 1528, 3136, 2198, 1650, -1067, 1651, 2419, 1097, 1922, -8, 1788, 2395, -647, 826, -665, 1778, 2654, -1939, -2472, -3354, 1547, 2531, -1566, -7603, -4442, 1264, 1722, -675, -1455, -575, 1309, -370, -272, -99, 1310, 1612, -1725, -852, -430, 2251, 1652, 1252, -2540, -1670, 2593, 1005, 2489, -4620, 217, 2450, -641, 2245, -4536, 2304, 1829, -3729, 548, -2219, 3283, 760, -5546, -3334, -639, 3546, -400, -2587, -14784, -60, 3408, -842, -471, -4991, -119, 3013, -117, 982, -638, -645, 2390, 931, 1808, 1517, -1510, 1431, 1485, 1993, 2218, -2069, -135, 1363, 1547, 1881, -2363, -1277, 650, 499, 1021, -3237, -583, -364, -1250, 259, -4795, -439, -978, -4145, -734, -6054, -1390, -930, -4270, -2990, -5888, -3014, -990, -2590, -7936, -5073, -4664, -1563, -3137, -10210, -4555, -5061, -2414, -7445, -6035, -4985, -4357, -3042, -7247, -2813, -6256, -3309, -3225, -4601, -1790, -5286, -2068, -3580, -5678, -2762, -3563, -1158, -5061, -6914, -7484, -3078, -849, -8454, -3704, -6928, -3913, -1121, -7317, -2083, -4319, -6246, -1507, -6504, -1624, -5073, -8903, -1521, -6666, -2095, -8942, -6988, -1499, -4963, -3490, -8903, -5121, -1668, -3441, -5810, -5437, -4311, -1918, -2900, -6773, -3971, -4640, -2062, -3650, -4826, -3476, -5584, -1869, -6321, -3237, -3893, -5630, -1827, -10138, -2213, -5109, -5273, -2617, -10704, -1868, -6492, -5569, -4630, -11232, -2455, -6565, -6183, -6943, -5221, -4447, -6123, -7230, -5415, -3386, -8790, -5836, -9873, -4089, -3184, -8615, -5539, -9753, -3840, -4369, -6705, -5380, -8517, -4935, -6528, -5524, -5408, -9873, -9479, -6133, -4951, -5751, -11232, -6267, -5979, -5266, -6628, -10799, -3321, -8393, -6246, -7888, -12319, -2666, -7819, -6973, -8363, -11232, -3422, -5933, -7050, -6204, -9936, -5509, -6565, -6679, -4447, -9639, -9064, -8454, -7865, 6384, 8433, 6336, -1661, 2254, 6190, 7798, 6460, 4567, 4610, 5623, 6069, 6709, 6674, 5012, 4822, 4554, 6703, 6995, 3751, 3834, 3798, 5914, 5827, 458, 2226, 1892, 3772, 2775, -1699, 919, -2082, 1070, 361, -1205, 1609, -7162, 1990, 1068, -4578, 1643, -3184, 1957, 2505, -3412, 715, -877, 2185, 5062, 1287, 500, -36, 3480, 6450, 3364, 1762, 233, 3873, 6837, 4204, 2522, 91, 2879, 6135, 3929, 2207, -1136, -383, 3287, 2281, 788, -5319, -6602, 1016, -1621, -2222, -1546, -911, 5163, -1417, -6399, 602, -1000, 6003, 314, -1749, 715, -2538, 5599, -180, -1145, -336, -3284, 5076, -2475, -3656, -1872, -3535, 4641, -7230, -3957, -3306, -1466, 3675, -14195, -678, -3571, -320, 2228, -8009, -95, -3269, -952, 907, -4451, -1287, -3529, -3311, 22, -3375, -4880, -2945, -5751, -427, -4100, -8276, -1433, -5458, -1026, -8009, -7034, -302, -5008, -1895, -6225, -5646, 172, -4403, -1174, -2648, -2351, 92, -4035, -23, -1707, -1615, -535, -3751, 230, -2340, -2964, -1887, -3140, -276, -3632, -5710, -3680, -2605, -1382, -2845, -4416, -4071, -3436, -4184, -1916, -2918, -2391, -6411, -5306, -1193, -2234, -422, -1541, -1468, 25, -2686, 676, 819, -617, 708, -4583, 616, 1322, -1187, 154, -4693, -595, 305, -2733, -2350, -2639, -810, -2528, -5346, -5109, -1642, 636, -12534, -2644, -2534, -1726, 1346, -3811, -352, -3600, -1944, 1705, -1487, 634, -2813, -585, 1998, -1370, 995, 746, 581, 1725, -3485, 1000, 1936, 794, 496, -12534, 578, 1525, 184, -1491, -6553, -574, -590, -981, -1893, -5387, -2650, -6434, -2317, -783, -4718, -5049, -5374, -3316, -217, -4361, -7708, -3763, -3677, -430, -4708, -14195, -5227, -3618, -1553, -4896, -7644, -8649, -3482, -3992, -4779, -6376, -5247, -3632, -7113, -4912, -6565, -3886, -4473, -5516, -5085, -5942, -4211, -6492, -4929, -5422, -4759, -5776, -9812, -5615, -6705, -4234, -7687, -8165, -6480, -8982, -4013, -7888, -5776, -7196, -7912, -3412, -7665, -4420, -9753, -6434, -2589, -7665, -3766, -15615, -5494, -2086, -6786, -3589, -8485, -4270, -2326, -5970, -3930, -7408, -3189, -3763, -6045, -5279, -8247, -2781, -7936, -6214, -9936, -9479, -3244, -8549, -6153, -7865, -9753, -4587, -4278, -6679, -4282, -9331, -6640, -2747, -7888, -3347, -8942, -7960, -2222, -8754, -4031, -8363, -8165, -2447, -7912, -6214, -5360, -8615, -3269, -6376, -6943, -4082, -8718, -4180, -5260, -5576, -4597, -8138, -4234, -4880, -4640, -6093, -8086, -3460, -5576, -4127, -6679, -9022, -2662, -7542, -4311, -7960, -11781, -2289, -7353, -5458, -9639, -13738, -2447, -7408, -7936, -7730, -8790, -3232, -11356, -10899, -7162, -7623, -4863, -5346, -8192, -8423, -8454, -7004, -3388, -6653, -14784, -10704, -7230, -3404, -6332, -11115, -10442, -7281, -8009, -3903, -7687, -12776, -5387, -5189, -3686, -6422, -9429, -4991, -4555, -3686, -6183, -7623, -5915, -4935, -3710, -6256, -6469, -8549, -5694, -3808, -5862, -6457, -7389, -7426, -4611, -5380, -7464, -6123, -8276, -6759, -5702, -6504, -6786, -5759, -11488, -7066, -4957, -7623, -4282, -13738, -9429, -4541, -7389, -3571, -10284, -11781, -5133, -7162, -3269, -8790, -11004, -6054, -6133, -3242, -8549, -8423, -6288, -5152, -3546, -8549, -7281, -6492, -4929, -4344, -7687, -6828, -7603, -5260, -6016, -7730, -6516, -8942, -5623, -10210, -8903, -6786, -8423, -5630, -11232, -8454, -7774, -8363, -5524, -7583, -7730, -9064, -9284, -5801, -7179, -6504, -9149, -11945, -6899, -8649, -5109, -6899, -10362, -8827, -11629, -4640, -5353, -6759, -8649, -11629, -5279, -5055, -5247, -7464, -9331, -7004, -5630, -4810, -7603, -6899, -8112, -5942, -5133, -9284, -5539, -6653, -5592, -6026, -12534, -5429, -5801, -6016, -6914, -11356, -6590, -5623, -8454, -7004, -9695, -8683, -5561, -11115, -6943, -8304, -10362, -5312, -7888, -7865, -6885, -9331, -5020, -7264, -10001, -5630, -7281, -4935, -8138, -9695, -4968, -6343, -5415, -10799, -7097, -5292, -6565, -6705, -28777, -5662, -6814, -7353, -7484, -9429, -5401, -8517, -7912, -6540, -7503, -6045, -7644, -8333, -6214, -7445, -7130, -7113, -8138, -6899, -8454, -7752, -7796, -7623, -8192, -9873, -7335, -8649, -7230, -9585, -10613, -6732, -7774, -7299, -10704, -9873, -6692, -5988, -8165, -10899, -8060, -7113, -4805, -9284, -10210, -7371, -7445, -4644, -8865, -9284, -8220, -7426, -5836, -8718, -7819, -11781, -6602, -9149, -8333, -6958, -14195, -5670, -9479, -7542, -7299, -10362, -5599, -7196, -7796, -8982, -8982, -6422, -6705, -10210, -9753, -7665, -8112, -6640, -17034, -8827, -6422, -10704, -6376, -9531, -9193, -5836, -10442, -6399, -8485, -11629, -6007, -8549, -7081, -9531, -13049, -6856, -8060, -8517, -13049, -11232, -7819, -9149, -10362, -28777, -10284, -8060, -13738, -10613, -14195, -8683, -8333, -11232, -9429, -11356, -7912, -9585, -8086, -8086, -8942, -8615, -13738, -7066, -7774, -7484, -12319, -28777, -7247, -8903, -7408, -14195, -12123, -8363, -13365, -9380, -9753, -12776, -10526, -12776, -13738, -8982, -12319, -12776, -11004, -7936, -9284, -8393, -13738, -13049, -6288, -9238, -6434, -13365, -10069, -6445, -8485, -5718, -11945, -7523, -8333, -8112, -5951, -10613, -6504, -12123, -8423, -7213, -10526, -6321, -9022, -9238, -9639, -10284, -7081, -7644, -9873, -12319, -9238, -9193, -8423, -10138, -12123, -9149, -12123, -11004, -10284, -14195, -10442, -12534, -10069, -10210, -28777, -12123, -10210, -9284, -10069, -12123, -12319, -8304, -11356, -11356, -10442, -10138, -7687, -14784, -28777, -9873, -8827, -7936, -10613, -13365, -9531, -8790, -8865, -9106, -11004, -8790, -10284, -10526, -9193, -10526, -8112, -13738, -14195, -10138, -10899, -7730, -28777, -28777, -10138, -11945, -7865, -17034, -13365, -10210, -10138, -8485, -15615, -12123, -6246, -4003, -9331, -11945, -9284, -5569, -5002, -9531, -9284, -13049, -4728, -7426, -10526, -7081, -9873, -4238, -8393, -11945, -5793, -7464, -4504, -7426, -11488, -5401, -6602, -5759, -6422, -9479, -5801, -5121, -7960, -5561, -8333, -6692, -4031, -10284, -5599, -7960, -7562, -4064, -12776, -6800, -8060, -8582, -5451, -11232, -8165, -8485, -8790, -9064, -8615, -8276, -8485, -6870, -11945, -7503, -7819, -6814, -6026, -8649, -7213, -7335, -5360, -6928, -8034, -7113, -7464, -5139, -10704, -8903, -6666, -8683, -5988, -11356, -12123, -5951, -11232, -5960, -7687, -12776, -5458, -13365, -5189, -6422, -9331, -5360, -10526, -5710, -6204, -8423, -5546, -9331, -7819, -6786, -8942, -5710, -8718, -8112, -8393, -9753, -5638, -6590, -7583, -10799, -8454, -5607, -4713, -10001, -9585, -7299, -5678, -4097, -11356, -8138, -6914, -5638, -4779, -5979, -7842, -7408, -5853, -6842, -4491, -7865, -8903, -6885, -10613, -4759, -7130, -10001, -7542, -28777, -6516, -6143, -9238, -5906, -12319, -8454, -5607, -7912, -4764, -9695, -8086, -5615, -6388, -4874, -9238, -8582, -5888, -5472, -6299, -9936, -9936, -6267, -5465, -10362, -11488, -8942, -6666, -6679, -12534, -14784, -8009, -7335, -10210, -8549, -11629, -8112, -9064, -11781, -8086, -9331, -8138, -11945, -7819, -8333, -9284, -7644, -12534, -6899, -8517, -10284, -6842, -28777, -7264, -9936, -9936, -6133, -9149, -8276, -10526, -9585, -6553, -6469, -9238, -7912, -8982, -9695, -5408, -10069, -6411, -7146, -11629, -5202, -11356, -5960, -6204, -7936, -5988, -13365, -6321, -6246, -7774, -7888, -11945, -7708, -6732, -8086, -7960, -10138, -9753, -7050, -7371, -6828, -9429, -9479, -6870, -6602, -6469, -9284, -8247, -6553, -6194, -6732, -9149, -8220, -6577, -6267, -7644, -9331, -8903, -7299, -7213, -9106, -10138, -9812, -8582, -9585, -10526, -13738, -10526, -8754, -13049, -12534, -14195, -11115, -8304, -10899, -28777, -9284, -11781, -8718, -9429, -11629, -7936, -12123, -10284, -8982, -10069, -8165, -12776, -13049, -9193, -11356, -9753, -14195, -28777, -10899, -17034, -10613, -13365, -13049, -12123, -17034, -8615, -9429, -11232, -8754, -13738, -7179, -7796, -11781, -7213, -9331, -6719, -7752, -14195, -7050, -7196, -7081, -8827, -11488, -7774, -6842, -8333, -10069, -9106, -8485, -8165, -10799, -10362, -9064, -8034, -12319, -28777, -10613, -11781, -7113, -28777, -12534, -12123, -11629, -6943, -13049, -10001, -14195, -8903, -8363, -11115, -9331, -12534, -8615, -12319, -10138, -9380, -10210, -9695, -13049, -10899, -9238, -8790, -10704, -12319, -11781, -9585, -7912, -9873, -11945, -10899, -10704, -7353, -8827, -9639, -10526, -9479, -7426, -7888, -8942, -11004, -7960, -8517, -7299, -10138, -12123, -7542, -10526, -7562, -14195, -12319, -8060, -10069, -9064, -12776, -11115, -9331, -9193, -12534, -10210, -11356, -10799, -10138, -17034, -9873, -12534, -11629, -14784, -15615, -10704, -11115, -12123, -13738, -14784, -11004, -9812, -11629, -10442, -12123, -10362, -10138, -10362, -4863, -7264, -8363, -10001, -8582, -7353, -10138, -7842, -11004, -7146, -7335, -12776, -8615, -12534, -5702, -5915, -10613, -10284, -28777, -6299, -5997, -11232, -12534, -11629, -9531, -8393, -13738, -12319, -10138, -8615, -10799, -9812, -11004, -13365, -6615, -6732, -7281, -11945, -13738, -6885, -5346, -5759, -28777, -9429, -9284, -5429, -4968, -15615, -8138, -13365, -7299, -4923, -12319, -7213, -8982, -11945, -5286, -10613, -7034, -7774, -8754, -5524, -9429, -8276, -7960, -7503, -5472, -9531, -12319, -8718, -7097, -5768, -13049, -10284, -9695, -6615, -7408, -10526, -7484, -10799, -6814, -11945, -7317, -6434, -9064, -8754, -17034, -6214, -6267, -7230, -10284, -12534, -5195, -6786, -6516, -7542, -7842, -3989, -8192, -6719, -7113, -6399, -3422, -11115, -7819, -8454, -6914, -3930, -11004, -8549, -9193, -8220, -5380, -8485, -7371, -8304, -8423, -6457, -7281, -6288, -8615, -8582, -6745, -6492, -5915, -9429, -9812, -7464, -5906, -6214, -8827, -11488, -9753, -5630, -6828, -7583, -10899, -14784, -5784, -6988, -6123, -11004, -7842, -6143, -6256, -4847, -9479, -6225, -6288, -5374, -4161, -7162, -6093, -6480, -4974, -4075, -6074, -6504, -6773, -5158, -4523, -5879, -6870, -7179, -5853, -5561, -6163, -7004, -8549, -7213, -7583, -6705, -7247, -12319, -9238, -9695, -6973, -8363, -11232, -9936, -8517, -6885, -11781, -8485, -8649, -8582, -7752, -13738, -7730, -7426, -11004, -11232, -10138, -7819, -7034, -13738, -14195, -10138, -7960, -7389, -13049, -10613, -12319, -7960, -7819, -13738, -9022, -12319, -8333, -8423, -13365, -7264, -11781, -9639, -9812, -17034, -6745, -14195, -11945, -10799, -12319, -7264, -14784, -12123, -12123, -8112, -8086, -9531, -10704, -11629, -6628, -8423, -6914, -10899, -8649, -6332, -8615, -5592, -11781, -7426, -6666, -9064, -5360, -13738, -6899, -7317, -9753, -6214, -17034, -6928, -8549, -10210, -8942, -10799, -7730, -10526, -10899, -28777, -8165, -9531, -10899, -12776, -9695, -7097, -12319, -10799, -11781, -8754, -7050, -28777, -13738, -9238, -10442, -7484, -12123, -14195, -8903, -13738, -7796, -8683, -11629, -11356, -10362, -7842, -7034, -12123, -15615, -9380, -8034, -6246, -11945, -9380, -10442, -8517, -6628, -10210, -8582, -13365, -9149, -8790, -9812, -9695, -13365, -9380, -13738, -10001, -11004, -11629, -9479, -13365, -9238, -10799, -10442, -10526, -10526, -8060, -11232, -10799, -13049, -7960, -7247, -12319, -12319, -14195, -6653, -6928, -12319, -15615, -13365, -6299, -7113, -12123, -28777, -12776, -6666, -7842, -11629, -28777, -10284, -7865, -9479, -12319, -28777, -8827, -10613, -13049, -14784, -28777, -8903, -17034, -28777, -17034, -14784, -10284, -13365, -13365, -12123, -11629, -12319, -14195, -12123, -11356, -9936, -13365, -28777, -11629, -11945, -9695, -11629, -14195, -11488, -12319, -10799, -10138, -13365, -11781, -10799, -13365, -9873, -14195, -11945, -10284, -12534, -11781, -14784, -12319, -11356, -11232, -28777, -13365, -11488, -17034, -11629, -11115, -10138, -9812, -13738, -13049, -9585, -8790, }; \ No newline at end of file diff --git a/sw/applications/transformer/tokenPosEmbeddingC.c b/sw/applications/transformer/tokenPosEmbeddingC.c new file mode 100644 index 00000000..39a63e40 --- /dev/null +++ b/sw/applications/transformer/tokenPosEmbeddingC.c @@ -0,0 +1,33 @@ +// +// Created by alireza on 10/6/23. +// + +#include "tokenPosEmbeddingC.h" + + +void createTokenPosEmbedding(TokenPosEmbedding* tokenPosEmbedding, quant_bit_width* pos_matrix, quant_bit_width* cls_token_vector, size_t seq_len, size_t input_dim, size_t pos_matrix_dim) { + tokenPosEmbedding->cls_token_vector_ = cls_token_vector; + tokenPosEmbedding->pos_matrix_ = pos_matrix; + tokenPosEmbedding->seq_len_ = seq_len; + tokenPosEmbedding->input_dim_ = input_dim; +} + +void clsConcatenate(TokenPosEmbedding* tpe, quant_bit_width* input, quant_bit_width* concatenated_input) { + // Copy cls_token_ into the concatenated array column-wise at the beginning + for (size_t i = 0; i < tpe->input_dim_; ++i) { + concatenated_input[i] = tpe->cls_token_vector_[i]; + } + // Copy the input array into the concatenated array + for (size_t i = 0; i < tpe->seq_len_ * tpe->input_dim_; ++i) { + concatenated_input[i + tpe->input_dim_] = input[i]; + } +} + +void posEmbedding(TokenPosEmbedding* tpe, quant_bit_width* input) { + for (size_t i = 0; i < (tpe->seq_len_ + 1); ++i) { + for (size_t j = 0; j < tpe->input_dim_; ++j) { + input[i * tpe->input_dim_+ j] += tpe->pos_matrix_[i * tpe->input_dim_ + j]; + } + } +} + diff --git a/sw/applications/transformer/tokenPosEmbeddingC.h b/sw/applications/transformer/tokenPosEmbeddingC.h new file mode 100644 index 00000000..9357a153 --- /dev/null +++ b/sw/applications/transformer/tokenPosEmbeddingC.h @@ -0,0 +1,24 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_TOKENPOSEMBEDDINGC_H +#define FVLLMONTITRANSFORMER_TOKENPOSEMBEDDINGC_H + +#include "param.h" +#include "stdlib.h" + +typedef struct{ + quant_bit_width* cls_token_vector_; + quant_bit_width* pos_matrix_; + size_t seq_len_; + size_t input_dim_; +} TokenPosEmbedding; + + +void createTokenPosEmbedding(TokenPosEmbedding*, quant_bit_width* pos_matrix, quant_bit_width* cls_token_vector, size_t seq_len, size_t input_dim, size_t pos_matrix_dim); +void clsConcatenate(TokenPosEmbedding* tpe, quant_bit_width* input, quant_bit_width* concatenated_input); +void posEmbedding(TokenPosEmbedding* tpe, quant_bit_width* input); + + +#endif //FVLLMONTITRANSFORMER_TOKENPOSEMBEDDINGC_H diff --git a/sw/applications/transformer/transformerBlockC.c b/sw/applications/transformer/transformerBlockC.c new file mode 100644 index 00000000..4d7a5fdb --- /dev/null +++ b/sw/applications/transformer/transformerBlockC.c @@ -0,0 +1,115 @@ +// +// Created by alireza on 10/6/23. +// + +#include +#include "transformerBlockC.h" +#include "multiply_cgra.h" + +SingleHeadSelfAttn global_selfatten [NUM_LAYERS * NUM_HEAD]; +Dense global_query_layer[NUM_LAYERS * NUM_HEAD]; +Dense global_key_layer[NUM_LAYERS * NUM_HEAD]; +Dense global_value_layer[NUM_LAYERS * NUM_HEAD]; + +Dense global_condense[NUM_LAYERS]; +Dense global_patch; +Dense global_FF[NUM_LAYERS * 2]; +Dense global_mlp; + +TransformerBlock global_transformer_block; +TokenPosEmbedding global_token_embedding; + +TransformerBlock* createTransformerBlock(size_t pre_seq_len, size_t input_dim, size_t head_hidden_size, size_t num_heads, size_t ff_size, int32_t** weightVector, int32_t** biasVector, int32_t* clsTokenVector, int32_t* posMatrix) { + TransformerBlock* transformerBlock = &global_transformer_block; + transformerBlock->num_heads_ = num_heads; + transformerBlock->head_hidden_size_ = head_hidden_size; + transformerBlock->input_dim_ = input_dim; + transformerBlock->ff_size_ = ff_size; + + transformerBlock->addNorm = createAddNormalize(pre_seq_len, D_EMBEDDING, weightVector[0], biasVector[0]); + transformerBlock->patchEmbedding = &global_patch; + createDense(transformerBlock->patchEmbedding, D_EMBEDDING, D_MODEL, weightVector[1], biasVector[1]); + transformerBlock->addNorm2 = createAddNormalize(pre_seq_len, D_MODEL, weightVector[2], biasVector[2]); + transformerBlock->token = &global_token_embedding; + createTokenPosEmbedding(transformerBlock->token, posMatrix, clsTokenVector, pre_seq_len, input_dim, D_SEQ + 1); + + for (int l = 0; l < 4; l++) { + transformerBlock->transformer_layer_0_addNorm[l] = createAddNormalize((pre_seq_len + 1), D_MODEL, weightVector[l * 17 + 3], biasVector[l * 17 + 3]); + + for (int n = 0; n < num_heads; n++) { + transformerBlock->selfatten[l * num_heads + n] = &global_selfatten[l * num_heads + n]; + transformerBlock->selfatten[l * num_heads + n]->query_layer = &global_query_layer[l * num_heads + n]; + transformerBlock->selfatten[l * num_heads + n]->key_layer = &global_key_layer[l * num_heads + n]; + transformerBlock->selfatten[l * num_heads + n]->value_layer = &global_value_layer[l * num_heads + n]; + + create_SingleHeadSelfAttn(transformerBlock->selfatten[l * num_heads + n], (pre_seq_len + 1), input_dim, head_hidden_size, weightVector + l * 17 + 4 + n * 3); + } + + transformerBlock->condense[l] = &global_condense[l]; + createDense(transformerBlock->condense[l], num_heads * head_hidden_size, input_dim, weightVector[l * 17 + num_heads * 3 + 4], biasVector[l * 17 + num_heads * 3 + 4]); + + transformerBlock->transformer_layer_1_addNorm[l] = createAddNormalize((pre_seq_len + 1), input_dim, weightVector[l * 17 + num_heads * 3 + 5], biasVector[l * 17 + num_heads * 3 + 5]); + + transformerBlock->feedForward0[l] = &global_FF[2*l]; + createDense(transformerBlock->feedForward0[l], input_dim, ff_size, weightVector[l * 17 + num_heads * 3 + 6], biasVector[l * 17 + num_heads * 3 + 6]); + + transformerBlock->feedForward1[l] = &global_FF[2*l + 1]; + createDense(transformerBlock->feedForward1[l], ff_size, input_dim, weightVector[l * 17 + num_heads * 3 + 7], biasVector[l * 17 + num_heads * 3 + 7]); + } + + transformerBlock->mlp_head_norm = createAddNormalize(1, D_MODEL, weightVector[(NUM_LAYERS - 1) * 17 + NUM_HEAD * 3 + 8], biasVector[(NUM_LAYERS - 1) * 17 + NUM_HEAD * 3 + 8]); + + transformerBlock->mlp_head_linear = &global_mlp; + createDense(transformerBlock->mlp_head_linear, D_MODEL, D_MODEL, weightVector[(NUM_LAYERS - 1) * 17 + NUM_HEAD * 3 + 9], biasVector[(NUM_LAYERS - 1) * 17 + NUM_HEAD * 3 + 9]); + + return transformerBlock; +} + + +void destroyTransformerBlock(TransformerBlock* transformerBlock) { + // Free dynamically allocated memory + + free(transformerBlock); +} + +void computeFixedPoint(TransformerBlock* transformerBlock, size_t seq_len, quant_bit_width * input, + quant_bit_width * input_normalized, quant_bit_width * output, + quant_bit_width* intermediate, quant_bit_width* qkv, void * kperf) { + + printf("\rStep 1\n"); + normalize(&transformerBlock->addNorm, input, input); + computeDense(transformerBlock->patchEmbedding, seq_len, input, output); // 120x400x16 + normalize(&transformerBlock->addNorm2, output, output); + + clsConcatenate(transformerBlock->token, output, input); + seq_len++; + posEmbedding(transformerBlock->token, input); + + printf("\rStep 2\n"); + for (int l = 0; l < 4; l++) { + normalize(&transformerBlock->transformer_layer_0_addNorm[l], input, input_normalized); + for (int n = 0; n < NUM_HEAD; n++) { + printf("\rStep 3\n"); + compute_SingleHeadSelfAttn(transformerBlock->selfatten[l * NUM_HEAD + n], input_normalized, + output + n * (seq_len * transformerBlock->head_hidden_size_), qkv, intermediate); +// destroy_SingleHeadSelfAttn(transformerBlock->selfatten[l * NUM_HEAD + n]); + } + printf("\rStep 4\n"); + multihead_transpose(output, intermediate, seq_len, transformerBlock->head_hidden_size_, transformerBlock->num_heads_); + + computeDense(transformerBlock->condense[l], seq_len +3, intermediate, output); // 121x16x16 + + add(input, output, seq_len, transformerBlock->input_dim_ ); + + normalize(&transformerBlock->transformer_layer_1_addNorm[l], input, input_normalized); + computeDense(transformerBlock->feedForward0[l], seq_len +3, input_normalized, intermediate); // 121x16x4 + activation(transformerBlock->feedForward0[l], seq_len * transformerBlock->ff_size_, intermediate, intermediate); + + computeDense(transformerBlock->feedForward1[l], seq_len +3, intermediate, output); // 121x4x16 + add(input, output, seq_len, transformerBlock->input_dim_ ); + } + printf("\rStep 5\n"); + normalize(&transformerBlock->mlp_head_norm, input, input_normalized); + computeDense(transformerBlock->mlp_head_linear, 1, input_normalized, output); // 1x16x16 +} + diff --git a/sw/applications/transformer/transformerBlockC.h b/sw/applications/transformer/transformerBlockC.h new file mode 100644 index 00000000..0663f92a --- /dev/null +++ b/sw/applications/transformer/transformerBlockC.h @@ -0,0 +1,48 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_TRANSFORMERBLOCK_H +#define FVLLMONTITRANSFORMER_TRANSFORMERBLOCK_H + +#include +#include +#include "selfattentionC.h" +#include "addNormC.h" +#include "dense_layerC.h" +#include "tokenPosEmbeddingC.h" +#include "param.h" +#include "transposeC.h" +#include "cgra.h" + +typedef struct { + size_t num_heads_; + size_t head_hidden_size_; + size_t input_dim_; + size_t ff_size_; + SingleHeadSelfAttn* selfatten[NUM_LAYERS*NUM_HEAD]; + int32_t* multihead_out; + int32_t* condense_out; + int32_t* intermediateFF; + int32_t* intermediateFFBlockWise; + AddNormalize addNorm; + AddNormalize addNorm2; + AddNormalize transformer_layer_0_addNorm[NUM_LAYERS]; + AddNormalize transformer_layer_1_addNorm[NUM_LAYERS]; + AddNormalize mlp_head_norm; + TokenPosEmbedding* token; + Dense* condense[NUM_LAYERS]; + Dense* feedForward0[NUM_LAYERS]; + Dense* feedForward1[NUM_LAYERS]; + Dense* patchEmbedding; + Dense* mlp_head_linear; + #ifndef REARRANGE + int32_t* multihead_out_reshape; + #endif +} TransformerBlock; + +TransformerBlock* createTransformerBlock(size_t pre_seq_len, size_t input_dim, size_t head_hidden_size, size_t num_heads, size_t ff_size, int32_t** weightVector, int32_t** biasVector, int32_t* clsTokenVector, int32_t* posMatrix); +void destroyTransformerBlock(TransformerBlock* transformerBlock); +void computeFixedPoint(TransformerBlock* transformerBlock, size_t seq_len, int32_t* input, int32_t* input_normalized, int32_t* output, int32_t* intermediate, int32_t* qkv, void * kperf); + +#endif //FVLLMONTITRANSFORMER_TRANSFORMERBLOCK_H diff --git a/sw/applications/transformer/transposeC.c b/sw/applications/transformer/transposeC.c new file mode 100644 index 00000000..2c27aa52 --- /dev/null +++ b/sw/applications/transformer/transposeC.c @@ -0,0 +1,31 @@ +// +// Created by alireza on 10/6/23. +// + +#include "softmaxC.h" + + +void multihead_transpose(const quant_bit_width * input, quant_bit_width* output, size_t seq_len, + size_t head_hidden_size, size_t num_head) { + const quant_bit_width * initial_input = input; + for (int i=0; i < seq_len; i++){ + for (int n=0; n< num_head; n++){ + input = initial_input + i*head_hidden_size + n*seq_len*head_hidden_size; + for (int j=0; j < head_hidden_size; j++){ + *output++ = *input++; + } + } + } +} + + +void transpose_quant(const quant_bit_width * input, quant_bit_width* output, + size_t width, size_t height) { + for (size_t i = 0; i < height; i++) { + for (size_t j = 0; j < width; j++) { + output[i * width + j] = input[j * height + i]; + } + } +} + + diff --git a/sw/applications/transformer/transposeC.h b/sw/applications/transformer/transposeC.h new file mode 100644 index 00000000..500c100e --- /dev/null +++ b/sw/applications/transformer/transposeC.h @@ -0,0 +1,22 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_TRANSPOSEC_H +#define FVLLMONTITRANSFORMER_TRANSPOSEC_H + + + +#include +#include "param.h" + +// Replace class with struct +typedef struct { + // struct members +} Transpose; + +// Function prototypes +void transpose_quant(const quant_bit_width* input, quant_bit_width* output, size_t width, size_t height); +void multihead_transpose(const quant_bit_width * input, quant_bit_width* output, size_t seq_len, size_t head_hidden_size, size_t num_head); + +#endif //FVLLMONTITRANSFORMER_TRANSPOSEC_H diff --git a/sw/applications/transformer/weightsAndBiasesC.c b/sw/applications/transformer/weightsAndBiasesC.c new file mode 100644 index 00000000..2fd600f0 --- /dev/null +++ b/sw/applications/transformer/weightsAndBiasesC.c @@ -0,0 +1,181 @@ +// +// Created by alireza on 10/6/23. +// +#include "weightsAndBiasesC.h" +#include +#include +#include "data_cpp/data.cpp" + +void getWeights(quant_bit_width * weightVec[]){ + + int weightVectorIndex = 0; + weightVec[weightVectorIndex++] = to_patch_embedding_layer_norm1_weight; + weightVec[weightVectorIndex++] = to_patch_embedding_linear_weight; + weightVec[weightVectorIndex++] = to_patch_embedding_layer_norm2_weight; + + + /* *************************** Layer 1 ***************************** */ + weightVec[weightVectorIndex++] = transformer_layers_0_0_norm_weight; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_Q_H0; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_K_H0; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_V_H0; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_Q_H1; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_K_H1; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_V_H1; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_Q_H2; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_K_H2; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_V_H2; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_Q_H3; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_K_H3; + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_to_qkv_weight_V_H3; + + weightVec[weightVectorIndex++] = transformer_layers_0_0_fn_projection_weight; + + weightVec[weightVectorIndex++] = transformer_layers_0_1_norm_weight; + + weightVec[weightVectorIndex++] = transformer_layers_0_1_fn_ff1_weight; + weightVec[weightVectorIndex++] = transformer_layers_0_1_fn_ff2_weight; + + /* *************************** Layer 2 ***************************** */ + weightVec[weightVectorIndex++] = transformer_layers_1_0_norm_weight; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_Q_H0; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_K_H0; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_V_H0; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_Q_H1; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_K_H1; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_V_H1; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_Q_H2; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_K_H2; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_V_H2; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_Q_H3; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_K_H3; + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_to_qkv_weight_V_H3; + + weightVec[weightVectorIndex++] = transformer_layers_1_0_fn_projection_weight; + + weightVec[weightVectorIndex++] = transformer_layers_1_1_norm_weight; + + weightVec[weightVectorIndex++] = transformer_layers_1_1_fn_ff1_weight; + weightVec[weightVectorIndex++] = transformer_layers_1_1_fn_ff2_weight; + + /* *************************** Layer 3 ***************************** */ + weightVec[weightVectorIndex++] = transformer_layers_2_0_norm_weight; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_Q_H0; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_K_H0; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_V_H0; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_Q_H1; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_K_H1; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_V_H1; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_Q_H2; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_K_H2; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_V_H2; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_Q_H3; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_K_H3; + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_to_qkv_weight_V_H3; + + weightVec[weightVectorIndex++] = transformer_layers_2_0_fn_projection_weight; + + weightVec[weightVectorIndex++] = transformer_layers_2_1_norm_weight; + + weightVec[weightVectorIndex++] = transformer_layers_2_1_fn_ff1_weight; + weightVec[weightVectorIndex++] = transformer_layers_2_1_fn_ff2_weight; + + /* *************************** Layer 4 ***************************** */ + weightVec[weightVectorIndex++] = transformer_layers_3_0_norm_weight; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_Q_H0; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_K_H0; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_V_H0; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_Q_H1; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_K_H1; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_V_H1; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_Q_H2; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_K_H2; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_V_H2; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_Q_H3; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_K_H3; + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_to_qkv_weight_V_H3; + + weightVec[weightVectorIndex++] = transformer_layers_3_0_fn_projection_weight; + + weightVec[weightVectorIndex++] = transformer_layers_3_1_norm_weight; + + weightVec[weightVectorIndex++] = transformer_layers_3_1_fn_ff1_weight; + weightVec[weightVectorIndex++] = transformer_layers_3_1_fn_ff2_weight; + + /* *************************** MLP HEAD ***************************** */ + weightVec[weightVectorIndex++] = mlp_head_layer_norm_weight; + weightVec[weightVectorIndex++] = mlp_head_linear_weight; + +} + +void getBiases(quant_bit_width * biasVec[]){ + int biasVectorIndex = 0; + biasVec[biasVectorIndex++] = to_patch_embedding_layer_norm1_bias; + biasVec[biasVectorIndex++] = to_patch_embedding_linear_bias; + biasVec[biasVectorIndex++] = to_patch_embedding_layer_norm2_bias; + + /* *************************** Layer 1 ***************************** */ + biasVec[biasVectorIndex++] = transformer_layers_0_0_norm_bias; + for (int i=0; i<3*4; i++) + biasVec[biasVectorIndex++] = (quant_bit_width *) NULL; + + biasVec[biasVectorIndex++] = transformer_layers_0_0_fn_projection_bias; + biasVec[biasVectorIndex++] = transformer_layers_0_1_norm_bias; + + biasVec[biasVectorIndex++] = transformer_layers_0_1_fn_ff1_bias; + biasVec[biasVectorIndex++] = transformer_layers_0_1_fn_ff2_bias; + + /* *************************** Layer 2 ***************************** */ + biasVec[biasVectorIndex++] = transformer_layers_1_0_norm_bias; + + for (int i=0; i<3*4; i++) + biasVec[biasVectorIndex++] = (quant_bit_width *) NULL; + + biasVec[biasVectorIndex++] = transformer_layers_1_0_fn_projection_bias; + biasVec[biasVectorIndex++] = transformer_layers_1_1_norm_bias; + + biasVec[biasVectorIndex++] = transformer_layers_1_1_fn_ff1_bias; + biasVec[biasVectorIndex++] = transformer_layers_1_1_fn_ff2_bias; + + /* *************************** Layer 3 ***************************** */ + biasVec[biasVectorIndex++] = transformer_layers_2_0_norm_bias; + + for (int i=0; i<3*4; i++) + biasVec[biasVectorIndex++] = (quant_bit_width *) NULL; + + biasVec[biasVectorIndex++] = transformer_layers_2_0_fn_projection_bias; + biasVec[biasVectorIndex++] = transformer_layers_2_1_norm_bias; + + biasVec[biasVectorIndex++] = transformer_layers_2_1_fn_ff1_bias; + biasVec[biasVectorIndex++] = transformer_layers_2_1_fn_ff2_bias; + + /* *************************** Layer 4 ***************************** */ + biasVec[biasVectorIndex++] = transformer_layers_3_0_norm_bias; + + for (int i=0; i<3*4; i++) + biasVec[biasVectorIndex++] = (quant_bit_width *) NULL; + + biasVec[biasVectorIndex++] = transformer_layers_3_0_fn_projection_bias; + biasVec[biasVectorIndex++] = transformer_layers_3_1_norm_bias; + + biasVec[biasVectorIndex++] = transformer_layers_3_1_fn_ff1_bias; + biasVec[biasVectorIndex++] = transformer_layers_3_1_fn_ff2_bias; + + /* *************************** MLP HEAD ***************************** */ + biasVec[biasVectorIndex++] = mlp_head_layer_norm_bias; + biasVec[biasVectorIndex++] = mlp_head_linear_bias; +} + +quant_bit_width * getPosEmbedding(){ + quant_bit_width * posMatrix; + posMatrix = pos_embedding; + return posMatrix; +} + +quant_bit_width * getClassToken(){ + quant_bit_width * clsTokenVector; + clsTokenVector = cls_token; + return clsTokenVector; +} + + diff --git a/sw/applications/transformer/weightsAndBiasesC.h b/sw/applications/transformer/weightsAndBiasesC.h new file mode 100644 index 00000000..b16d6468 --- /dev/null +++ b/sw/applications/transformer/weightsAndBiasesC.h @@ -0,0 +1,15 @@ +// +// Created by alireza on 10/6/23. +// + +#ifndef FVLLMONTITRANSFORMER_WEIGHTSANDBIASESC_H +#define FVLLMONTITRANSFORMER_WEIGHTSANDBIASESC_H + +#include "param.h" + +void getWeights(quant_bit_width * weightVec[]); +void getBiases(quant_bit_width * biasVec[]); +quant_bit_width * getPosEmbedding(); +quant_bit_width * getClassToken(); + +#endif //FVLLMONTITRANSFORMER_WEIGHTSANDBIASESC_H diff --git a/sw/applications/transformer_without_cgra/SYLT-FFT b/sw/applications/transformer_without_cgra/SYLT-FFT new file mode 160000 index 00000000..c6f58caa --- /dev/null +++ b/sw/applications/transformer_without_cgra/SYLT-FFT @@ -0,0 +1 @@ +Subproject commit c6f58caa8d3d01c622768b5c66a0be1d7953235b