From 1aab2637d8986ab994695dba6dc69985ca5cce74 Mon Sep 17 00:00:00 2001 From: Diyou Shen Date: Fri, 11 Apr 2025 13:31:05 +0000 Subject: [PATCH 01/17] [Spatz] Add Spatz dependency and some simple setup for CachePool --- .gitmodules | 3 + Bender.yml | 23 + Makefile | 119 ++ README.md | 14 +- hardware/deps/spatz | 1 + hardware/src/cachepool_cluster.sv | 1495 +++++++++++++++++++ hardware/src/cachepool_cluster_simple.sv | 1656 ++++++++++++++++++++++ hardware/src/cachepool_pkg.sv | 146 ++ hardware/src/cachepool_tile.sv | 369 +++++ hardware/src/cachepool_tile_simple.sv | 1515 ++++++++++++++++++++ hardware/tb/cachepool_cluster_wrapper.sv | 176 +++ hardware/tb/testharness.sv | 203 +++ software/.gitignore | 1 + 13 files changed, 5720 insertions(+), 1 deletion(-) create mode 100644 .gitmodules create mode 100644 Bender.yml create mode 100644 Makefile create mode 160000 hardware/deps/spatz create mode 100644 hardware/src/cachepool_cluster.sv create mode 100644 hardware/src/cachepool_cluster_simple.sv create mode 100644 hardware/src/cachepool_pkg.sv create mode 100644 hardware/src/cachepool_tile.sv create mode 100644 hardware/src/cachepool_tile_simple.sv create mode 100644 hardware/tb/cachepool_cluster_wrapper.sv create mode 100644 hardware/tb/testharness.sv create mode 100644 software/.gitignore diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4351438 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "hardware/deps/spatz"] + path = hardware/deps/spatz + url = https://github.com/pulp-platform/spatz.git diff --git a/Bender.yml b/Bender.yml new file mode 100644 index 0000000..0c777e5 --- /dev/null +++ b/Bender.yml @@ -0,0 +1,23 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.1 + +package: + name: cachepool + +dependencies: + snitch: { path: "hardware/deps/snitch" } + spatz: { path: "hardware/deps/spatz" } + +workspace: + checkout_dir: "./hardware/deps" + +export_include_dirs: + +sources: + - hardware/src/cachepool_pkg.sv + # - hardware/src/cachepool_tile_simple.sv + - hardware/src/cachepool_cluster_simple.sv + # testbench + - hardware/tb/cachepool_cluster_wrapepr.sv + - hardware/tb/cachepool_simple_tb.sv diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..10bdc49 --- /dev/null +++ b/Makefile @@ -0,0 +1,119 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +# Author: Diyou Shen, ETH Zurich + + +SHELL = /usr/bin/env bash +ROOT_DIR := $(patsubst %/,%, $(dir $(abspath $(lastword $(MAKEFILE_LIST))))) +CACHEPOOL_DIR := $(shell git rev-parse --show-toplevel 2>/dev/null || echo $$CACHEPOOL_DIR) + +# Include configuration +config_mk = $(abspath $(ROOT_DIR)/config/config.mk) +include $(config_mk) + +# Directories +INSTALL_PREFIX ?= install +SOFTWARE_DIR ?= software +INSTALL_DIR ?= ${ROOT_DIR}/${INSTALL_PREFIX} +GCC_INSTALL_DIR ?= ${INSTALL_DIR}/riscv-gcc +ISA_SIM_INSTALL_DIR ?= ${INSTALL_DIR}/riscv-isa-sim +LLVM_INSTALL_DIR ?= ${INSTALL_DIR}/llvm +HALIDE_INSTALL_DIR ?= ${INSTALL_DIR}/halide +BENDER_INSTALL_DIR ?= ${INSTALL_DIR}/bender +VERILATOR_INSTALL_DIR ?= ${INSTALL_DIR}/verilator +RISCV_TESTS_DIR ?= ${ROOT_DIR}/${SOFTWARE_DIR}/riscv-tests +SPATZ_DIR ?= $(CACHEPOOL_DIR)/hardware/deps/spatz + +# Tools +COMPILER ?= llvm + +CMAKE ?= cmake +# CC and CXX are Makefile default variables that are always defined in a Makefile. Hence, overwrite +# the variable if it is only defined by the Makefile (its origin in the Makefile's default). +ifeq ($(origin CC),default) + CC ?= gcc +endif +ifeq ($(origin CXX),default) + CXX ?= g++ +endif +BENDER_VERSION = 0.28.1 + + +# Initialize, setup the toolchain for Spatz +init: + git submodule update --init --recursive + ln -sf /usr/scratch2/calanda/diyou/flamingo/spatz-mx/spatz/install $(SPATZ_DIR)/install + +# Bender +bender: check-bender +check-bender: + @if [ -x $(BENDER_INSTALL_DIR)/bender ]; then \ + req="bender $(BENDER_VERSION)"; \ + current="$$($(BENDER_INSTALL_DIR)/bender --version)"; \ + if [ "$$(printf '%s\n' "$${req}" "$${current}" | sort -V | head -n1)" != "$${req}" ]; then \ + rm -rf $(BENDER_INSTALL_DIR); \ + fi \ + fi + @$(MAKE) -C $(ROOT_DIR) $(BENDER_INSTALL_DIR)/bender + +$(BENDER_INSTALL_DIR)/bender: + mkdir -p $(BENDER_INSTALL_DIR) && cd $(BENDER_INSTALL_DIR) && \ + curl --proto '=https' --tlsv1.2 https://pulp-platform.github.io/bender/init -sSf | sh -s -- $(BENDER_VERSION) + +.PHONY: rm-spatz +rm-spatz: + source /home/dishen/saferm.sh $(SPATZ_DIR) + + +# Build bootrom and spatz +.PHONY: generate +generate: + rm -rf $(SPATZ_DIR)/sw/toolchain/riscv-opcodes + make -C $(SPATZ_DIR) update_opcodes; + make -C $(SPATZ_DIR)/hw/system/spatz_cluster generate; + + +# QuestaSim +VSIM = questa-2021.3-kgf vsim +VLOG = questa-2021.3-kgf vlog +VSIM_HOME = /usr/pack/questa-2021.3-kgf/questasim + +VSIM_FLAGS += -t 1ps +VSIM_FLAGS += -voptargs=+acc +VSIM_FLAGS += -suppress vsim-3999 +VSIM_FLAGS += -do "log -r /*; run -a" + +VLOG_FLAGS += -svinputport=compat +VLOG_FLAGS += -override_timescale 1ns/1ps +VLOG_FLAGS += -suppress 2583 +VLOG_FLAGS += -suppress 13314 +VLOG_FLAGS += -64 + +USE_CACHE ?= 1 +USE_PRINT ?= 1 + + +############ +# Modelsim # +############ +# Currently highjack the simulation flow from spatz +.PHONY: sw +sw: + make -BC $(SPATZ_DIR)/hw/system/spatz_cluster sw DEFS="-t cachepool" USE_CACHE=$(USE_CACHE) ENABLE_PRINT=$(USE_PRINT) + rm -rf ${ROOT_DIR}/${SOFTWARE_DIR}/build + mkdir -p ${ROOT_DIR}/${SOFTWARE_DIR}/build + cp -r $(SPATZ_DIR)/hw/system/spatz_cluster/sw/build ${ROOT_DIR}/${SOFTWARE_DIR}/ + + +.PHONY: vsim +vsim: + make -BC $(SPATZ_DIR)/hw/system/spatz_cluster sw.vsim DEFS="-t cachepool" USE_CACHE=$(USE_CACHE) ENABLE_PRINT=$(USE_PRINT) + rm -rf bin + mkdir -p bin + cp -r $(SPATZ_DIR)/hw/system/spatz_cluster/bin/* bin/ + rm -rf ${ROOT_DIR}/${SOFTWARE_DIR}/build + mkdir -p ${ROOT_DIR}/${SOFTWARE_DIR}/build + cp -r $(SPATZ_DIR)/hw/system/spatz_cluster/sw/build ${ROOT_DIR}/${SOFTWARE_DIR}/ + diff --git a/README.md b/README.md index f5cc7e9..8c5dc54 100644 --- a/README.md +++ b/README.md @@ -1 +1,13 @@ -# ManyRVData +# CachePool + +This reporistory is still under construction... +It will be transferred to GitHub once we have a working demo. + +## Get Started + +Make sure you clone this repository recursively to get all the necessary submodules: + +```bash +git submodule update --init --recursive +``` +>>>>>>> 0d74201... [Spatz] Add Spatz dependency and some simple setup for CachePool diff --git a/hardware/deps/spatz b/hardware/deps/spatz new file mode 160000 index 0000000..42b9d42 --- /dev/null +++ b/hardware/deps/spatz @@ -0,0 +1 @@ +Subproject commit 42b9d423234629fccee981418f2b12f86df96b52 diff --git a/hardware/src/cachepool_cluster.sv b/hardware/src/cachepool_cluster.sv new file mode 100644 index 0000000..bc1303a --- /dev/null +++ b/hardware/src/cachepool_cluster.sv @@ -0,0 +1,1495 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Author: Matheus Cavalcante + +`include "axi/assign.svh" +`include "axi/typedef.svh" +`include "common_cells/assertions.svh" +`include "common_cells/registers.svh" +`include "mem_interface/assign.svh" +`include "mem_interface/typedef.svh" +`include "register_interface//assign.svh" +`include "register_interface/typedef.svh" +`include "reqrsp_interface/assign.svh" +`include "reqrsp_interface/typedef.svh" +`include "snitch_vm/typedef.svh" +`include "tcdm_interface/assign.svh" +`include "tcdm_interface/typedef.svh" + +/// Spatz many-core cluster with improved TCDM interconnect. +/// Spatz Cluster Top-Level. +module spatz_cluster + import spatz_pkg::*; + import fpnew_pkg::fpu_implementation_t; + import snitch_pma_pkg::snitch_pma_t; + #( + /// Width of physical address. + parameter int unsigned AxiAddrWidth = 48, + /// Width of AXI port. + parameter int unsigned AxiDataWidth = 512, + /// AXI: id width in. + parameter int unsigned AxiIdWidthIn = 2, + /// AXI: id width out. + parameter int unsigned AxiIdWidthOut = 2, + /// AXI: user width. + parameter int unsigned AxiUserWidth = 1, + /// Address from which to fetch the first instructions. + parameter logic [31:0] BootAddr = 32'h0, + /// Address to indicate start of L2 + parameter logic [AxiAddrWidth-1:0] L2Addr = 48'h0, + parameter logic [AxiAddrWidth-1:0] L2Size = 48'h0, + /// The total amount of cores. + parameter int unsigned NrCores = 8, + /// Data/TCDM memory depth per cut (in words). + parameter int unsigned TCDMDepth = 1024, + /// Cluster peripheral address region size (in kB). + parameter int unsigned ClusterPeriphSize = 64, + /// Number of TCDM Banks. + parameter int unsigned NrBanks = 2 * NrCores, + /// Size of DMA AXI buffer. + parameter int unsigned DMAAxiReqFifoDepth = 3, + /// Size of DMA request fifo. + parameter int unsigned DMAReqFifoDepth = 3, + /// Width of a single icache line. + parameter unsigned ICacheLineWidth = 0, + /// Number of icache lines per set. + parameter int unsigned ICacheLineCount = 0, + /// Number of icache sets. + parameter int unsigned ICacheSets = 0, + // PMA Configuration + parameter snitch_pma_t SnitchPMACfg = '{default: 0}, + /// # Core-global parameters + /// FPU configuration. + parameter fpu_implementation_t FPUImplementation [NrCores] = '{default: fpu_implementation_t'(0)}, + /// Spatz FPU/IPU Configuration + parameter int unsigned NumSpatzFPUs = 4, + parameter int unsigned NumSpatzIPUs = 1, + /// Per-core enabling of the custom `Xdma` ISA extensions. + parameter bit [NrCores-1:0] Xdma = '{default: '0}, + /// # Per-core parameters + /// Per-core integer outstanding loads + parameter int unsigned NumIntOutstandingLoads [NrCores] = '{default: '0}, + /// Per-core integer outstanding memory operations (load and stores) + parameter int unsigned NumIntOutstandingMem [NrCores] = '{default: '0}, + /// Per-core Spatz outstanding loads + parameter int unsigned NumSpatzOutstandingLoads [NrCores] = '{default: '0}, + /// ## Timing Tuning Parameters + /// Insert Pipeline registers into off-loading path (response) + parameter bit RegisterOffloadRsp = 1'b0, + /// Insert Pipeline registers into data memory path (request) + parameter bit RegisterCoreReq = 1'b0, + /// Insert Pipeline registers into data memory path (response) + parameter bit RegisterCoreRsp = 1'b0, + /// Insert Pipeline registers after each memory cut + parameter bit RegisterTCDMCuts = 1'b0, + /// Decouple external AXI plug + parameter bit RegisterExt = 1'b0, + parameter axi_pkg::xbar_latency_e XbarLatency = axi_pkg::CUT_ALL_PORTS, + /// Outstanding transactions on the AXI network + parameter int unsigned MaxMstTrans = 4, + parameter int unsigned MaxSlvTrans = 4, + /// # Interface + /// AXI Ports + parameter type axi_in_req_t = logic, + parameter type axi_in_resp_t = logic, + parameter type axi_out_req_t = logic, + parameter type axi_out_resp_t = logic, + /// SRAM configuration + parameter type impl_in_t = logic, + // Memory latency parameter. Most of the memories have a read latency of 1. In + // case you have memory macros which are pipelined you want to adjust this + // value here. This only applies to the TCDM. The instruction cache macros will break! + // In case you are using the `RegisterTCDMCuts` feature this adds an + // additional cycle latency, which is taken into account here. + parameter int unsigned MemoryMacroLatency = 1 + RegisterTCDMCuts, + /// # SRAM Configuration rules needed: L1D Tag + L1D Data + L1D FIFO + L1I Tag + L1I Data + parameter int unsigned NrSramCfg = 64 + 8 + 2 + ICacheSets + ICacheSets + ) ( + /// System clock. + input logic clk_i, + /// Asynchronous active high reset. This signal is assumed to be _async_. + input logic rst_ni, + /// Per-core debug request signal. Asserting this signals puts the + /// corresponding core into debug mode. This signal is assumed to be _async_. + input logic [NrCores-1:0] debug_req_i, + /// Machine external interrupt pending. Usually those interrupts come from a + /// platform-level interrupt controller. This signal is assumed to be _async_. + input logic [NrCores-1:0] meip_i, + /// Machine timer interrupt pending. Usually those interrupts come from a + /// core-local interrupt controller such as a timer/RTC. This signal is + /// assumed to be _async_. + input logic [NrCores-1:0] mtip_i, + /// Core software interrupt pending. Usually those interrupts come from + /// another core to facilitate inter-processor-interrupts. This signal is + /// assumed to be _async_. + input logic [NrCores-1:0] msip_i, + /// First hartid of the cluster. Cores of a cluster are monotonically + /// increasing without a gap, i.e., a cluster with 8 cores and a + /// `hart_base_id_i` of 5 get the hartids 5 - 12. + input logic [9:0] hart_base_id_i, + /// Base address of cluster. TCDM and cluster peripheral location are derived from + /// it. This signal is pseudo-static. + input logic [AxiAddrWidth-1:0] cluster_base_addr_i, + /// Per-cluster probe on the cluster status. Can be written by the cores to indicate + /// to the overall system that the cluster is executing something. + output logic cluster_probe_o, + /// AXI Core cluster in-port. + input axi_in_req_t axi_in_req_i, + output axi_in_resp_t axi_in_resp_o, + /// AXI Core cluster out-port to core. + output axi_out_req_t axi_out_req_o, + input axi_out_resp_t axi_out_resp_i, + /// AXI Core cluster out-port to L2 Mem. + output axi_out_req_t axi_out_l2_req_o, + input axi_out_resp_t axi_out_l2_resp_i, + /// SRAM Configuration: L1D Data + L1D Tag + L1D FIFO + L1I Data + L1I Tag + input impl_in_t [NrSramCfg-1:0] impl_i, + /// Indicate the program execution is error + output logic error_o + ); + // --------- + // Imports + // --------- + import snitch_pkg::*; + import snitch_icache_pkg::icache_events_t; + + // --------- + // Constants + // --------- + /// Minimum width to hold the core number. + localparam int unsigned CoreIDWidth = cf_math_pkg::idx_width(NrCores); + localparam int unsigned TCDMMemAddrWidth = $clog2(TCDMDepth); + localparam int unsigned TCDMSize = NrBanks * TCDMDepth * (DataWidth/8); + // The short address for SPM + localparam int unsigned SPMAddrWidth = $clog2(TCDMSize); + // Enlarge the address width for Spatz due to cache + localparam int unsigned TCDMAddrWidth = 32; + localparam int unsigned BanksPerSuperBank = AxiDataWidth / DataWidth; + localparam int unsigned NrSuperBanks = NrBanks / BanksPerSuperBank; + + function automatic int unsigned get_tcdm_ports(int unsigned core); + return spatz_pkg::N_FU + 1; + endfunction + + function automatic int unsigned get_tcdm_port_offs(int unsigned core_idx); + automatic int n = 0; + for (int i = 0; i < core_idx; i++) n += get_tcdm_ports(i); + return n; + endfunction + + localparam int unsigned NrTCDMPortsCores = get_tcdm_port_offs(NrCores); + localparam int unsigned NumTCDMIn = NrTCDMPortsCores + 1; + localparam logic [AxiAddrWidth-1:0] TCDMMask = ~(TCDMSize-1); + + // Core Request, SoC Request + localparam int unsigned NrNarrowMasters = 2; + + // Narrow AXI network parameters + localparam int unsigned NarrowIdWidthIn = AxiIdWidthIn; + localparam int unsigned NarrowIdWidthOut = NarrowIdWidthIn + $clog2(NrNarrowMasters); + localparam int unsigned NarrowDataWidth = 64; + localparam int unsigned NarrowUserWidth = AxiUserWidth; + + // TCDM, Peripherals, SoC Request + localparam int unsigned NrNarrowSlaves = 3; + localparam int unsigned NrNarrowRules = NrNarrowSlaves - 1; + + // Core Request, DMA, Instruction cache + /// Additional one for L1 DCache + localparam int unsigned NrWideMasters = 3 + 1; + localparam int unsigned WideIdWidthOut = AxiIdWidthOut; + localparam int unsigned WideIdWidthIn = WideIdWidthOut - $clog2(NrWideMasters); + // DMA X-BAR configuration + localparam int unsigned NrWideSlaves = 3 + 1; // one prot for L2, one for L3/LLC (virtual) + + // AXI Configuration + localparam axi_pkg::xbar_cfg_t ClusterXbarCfg = '{ + NoSlvPorts : NrNarrowMasters, + NoMstPorts : NrNarrowSlaves, + MaxMstTrans : MaxMstTrans, + MaxSlvTrans : MaxSlvTrans, + FallThrough : 1'b0, + LatencyMode : XbarLatency, + AxiIdWidthSlvPorts: NarrowIdWidthIn, + AxiIdUsedSlvPorts : NarrowIdWidthIn, + UniqueIds : 1'b0, + AxiAddrWidth : AxiAddrWidth, + AxiDataWidth : NarrowDataWidth, + NoAddrRules : NrNarrowRules, + default : '0 + }; + + // DMA configuration struct + localparam axi_pkg::xbar_cfg_t DmaXbarCfg = '{ + NoSlvPorts : NrWideMasters, + NoMstPorts : NrWideSlaves, + MaxMstTrans : MaxMstTrans, + MaxSlvTrans : MaxSlvTrans, + FallThrough : 1'b0, + LatencyMode : XbarLatency, + AxiIdWidthSlvPorts: WideIdWidthIn, + AxiIdUsedSlvPorts : WideIdWidthIn, + UniqueIds : 1'b0, + AxiAddrWidth : AxiAddrWidth, + AxiDataWidth : AxiDataWidth, + NoAddrRules : NrWideSlaves - 1, + default : '0 + }; + + // L1 Cache + localparam int unsigned L1AddrWidth = 32; + localparam int unsigned L1LineWidth = 512; + localparam int unsigned L1Associativity = 4; + localparam int unsigned L1BankFactor = 2; + localparam int unsigned L1CoalFactor = 2; + // 8 * 1024 * 64 / 512 = 1024) + localparam int unsigned L1NumEntry = NrBanks * TCDMDepth * DataWidth / L1LineWidth; + localparam int unsigned L1NumWrapper = L1LineWidth / DataWidth; + localparam int unsigned L1BankPerWP = L1BankFactor * L1Associativity; + localparam int unsigned L1BankPerWay = L1BankFactor * L1NumWrapper; + localparam int unsigned L1CacheWayEntry = L1NumEntry / L1Associativity; + localparam int unsigned L1NumSet = L1CacheWayEntry / L1BankFactor; + localparam int unsigned L1NumTagBank = L1BankFactor * L1Associativity; + localparam int unsigned L1NumDataBank = L1BankFactor * L1NumWrapper * L1Associativity; + + // -------- + // Typedefs + // -------- + typedef logic [AxiAddrWidth-1:0] addr_t; + typedef logic [NarrowDataWidth-1:0] data_t; + typedef logic [NarrowDataWidth/8-1:0] strb_t; + typedef logic [AxiDataWidth-1:0] data_dma_t; + typedef logic [AxiDataWidth/8-1:0] strb_dma_t; + typedef logic [NarrowIdWidthIn-1:0] id_mst_t; + typedef logic [NarrowIdWidthOut-1:0] id_slv_t; + typedef logic [WideIdWidthIn-1:0] id_dma_mst_t; + typedef logic [WideIdWidthOut-1:0] id_dma_slv_t; + typedef logic [NarrowUserWidth-1:0] user_t; + typedef logic [AxiUserWidth-1:0] user_dma_t; + + typedef logic [TCDMMemAddrWidth-1:0] tcdm_mem_addr_t; + typedef logic [TCDMAddrWidth-1:0] tcdm_addr_t; + typedef logic [SPMAddrWidth-1:0] spm_addr_t; + + typedef logic [$clog2(NumSpatzOutstandingLoads[0])-1:0] reqid_t; + typedef logic [$clog2(NumSpatzOutstandingLoads[0]):0] tcdm_meta_t; + + typedef logic [$clog2(L1NumSet)-1:0] tcdm_bank_addr_t; + + typedef struct packed { + logic [CoreIDWidth-1:0] core_id; + logic is_core; + reqid_t req_id; + } tcdm_user_t; + + // Regbus peripherals. + `AXI_TYPEDEF_ALL(axi_mst, addr_t, id_mst_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_ALL(axi_slv, addr_t, id_slv_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_ALL(axi_mst_dma, addr_t, id_dma_mst_t, data_dma_t, strb_dma_t, user_dma_t) + `AXI_TYPEDEF_ALL(axi_slv_dma, addr_t, id_dma_slv_t, data_dma_t, strb_dma_t, user_dma_t) + + `REQRSP_TYPEDEF_ALL(reqrsp, addr_t, data_t, strb_t) + + `MEM_TYPEDEF_ALL(mem, tcdm_mem_addr_t, data_t, strb_t, tcdm_user_t) + `MEM_TYPEDEF_ALL(mem_dma, tcdm_mem_addr_t, data_dma_t, strb_dma_t, logic) + + `TCDM_TYPEDEF_ALL(tcdm, tcdm_addr_t, data_t, strb_t, tcdm_user_t) + `TCDM_TYPEDEF_ALL(tcdm_dma, tcdm_addr_t, data_dma_t, strb_dma_t, logic) + `TCDM_TYPEDEF_ALL(spm, spm_addr_t, data_t, strb_t, tcdm_user_t) + + `REG_BUS_TYPEDEF_ALL(reg, addr_t, data_t, strb_t) + `REG_BUS_TYPEDEF_ALL(reg_dma, addr_t, data_dma_t, strb_dma_t) + + // Event counter increments for the TCDM. + typedef struct packed { + /// Number requests going in + logic [$clog2(NrTCDMPortsCores):0] inc_accessed; + /// Number of requests stalled due to congestion + logic [$clog2(NrTCDMPortsCores):0] inc_congested; + } tcdm_events_t; + + // Event counter increments for DMA. + typedef struct packed { + logic aw_stall, ar_stall, r_stall, w_stall, + buf_w_stall, buf_r_stall; + logic aw_valid, aw_ready, aw_done, aw_bw; + logic ar_valid, ar_ready, ar_done, ar_bw; + logic r_valid, r_ready, r_done, r_bw; + logic w_valid, w_ready, w_done, w_bw; + logic b_valid, b_ready, b_done; + logic dma_busy; + axi_pkg::len_t aw_len, ar_len; + axi_pkg::size_t aw_size, ar_size; + logic [$clog2(AxiDataWidth/8):0] num_bytes_written; + } dma_events_t; + + typedef struct packed { + int unsigned idx; + addr_t start_addr; + addr_t end_addr; + } xbar_rule_t; + + typedef struct packed { + acc_addr_e addr; + logic [5:0] id; + logic [31:0] data_op; + data_t data_arga; + data_t data_argb; + addr_t data_argc; + } acc_issue_req_t; + + typedef struct packed { + logic accept; + logic writeback; + logic loadstore; + logic exception; + logic isfloat; + } acc_issue_rsp_t; + + typedef struct packed { + logic [5:0] id; + logic error; + data_t data; + } acc_rsp_t; + + `SNITCH_VM_TYPEDEF(AxiAddrWidth) + + typedef struct packed { + // Slow domain. + logic flush_i_valid; + addr_t inst_addr; + logic inst_cacheable; + logic inst_valid; + // Fast domain. + acc_issue_req_t acc_req; + logic acc_qvalid; + logic acc_pready; + // Slow domain. + logic [1:0] ptw_valid; + va_t [1:0] ptw_va; + pa_t [1:0] ptw_ppn; + } hive_req_t; + + typedef struct packed { + // Slow domain. + logic flush_i_ready; + logic [31:0] inst_data; + logic inst_ready; + logic inst_error; + // Fast domain. + logic acc_qready; + acc_rsp_t acc_resp; + logic acc_pvalid; + // Slow domain. + logic [1:0] ptw_ready; + l0_pte_t [1:0] ptw_pte; + logic [1:0] ptw_is_4mega; + } hive_rsp_t; + + // ----------- + // Assignments + // ----------- + // Calculate start and end address of TCDM based on the `cluster_base_addr_i`. + addr_t tcdm_start_address, tcdm_end_address; + assign tcdm_start_address = (cluster_base_addr_i & TCDMMask); + assign tcdm_end_address = (tcdm_start_address + TCDMSize) & TCDMMask; + + addr_t cluster_periph_start_address, cluster_periph_end_address; + assign cluster_periph_start_address = tcdm_end_address; + assign cluster_periph_end_address = tcdm_end_address + ClusterPeriphSize * 1024; + + localparam int unsigned ClusterReserve = 4096; // 4 MiB + localparam int unsigned ClusterL2Size = 8192; // 8 MiB + addr_t cluster_l2_start_address, cluster_l2_end_address; + assign cluster_l2_start_address = L2Addr; + assign cluster_l2_end_address = L2Addr + L2Size; + + // ---------------- + // Wire Definitions + // ---------------- + // 1. AXI + axi_slv_req_t [NrNarrowSlaves-1:0] narrow_axi_slv_req; + axi_slv_resp_t [NrNarrowSlaves-1:0] narrow_axi_slv_rsp; + axi_mst_req_t [NrNarrowMasters-1:0] narrow_axi_mst_req; + axi_mst_resp_t [NrNarrowMasters-1:0] narrow_axi_mst_rsp; + + // DMA AXI buses + axi_mst_dma_req_t [NrWideMasters-1:0] wide_axi_mst_req; + axi_mst_dma_resp_t [NrWideMasters-1:0] wide_axi_mst_rsp; + axi_slv_dma_req_t [NrWideSlaves-1 :0] wide_axi_slv_req; + axi_slv_dma_resp_t [NrWideSlaves-1 :0] wide_axi_slv_rsp; + + // 2. Memory Subsystem (Banks) + mem_req_t [NrSuperBanks-1:0][BanksPerSuperBank-1:0] ic_req; + mem_rsp_t [NrSuperBanks-1:0][BanksPerSuperBank-1:0] ic_rsp; + + mem_dma_req_t [NrSuperBanks-1:0] sb_dma_req; + mem_dma_rsp_t [NrSuperBanks-1:0] sb_dma_rsp; + + // 3. Memory Subsystem (Interconnect) + tcdm_dma_req_t ext_dma_req; + tcdm_dma_rsp_t ext_dma_rsp; + + // AXI Ports into TCDM (from SoC). + spm_req_t axi_soc_req; + spm_rsp_t axi_soc_rsp; + + tcdm_req_t [NrTCDMPortsCores-1:0] tcdm_req; + tcdm_rsp_t [NrTCDMPortsCores-1:0] tcdm_rsp; + + core_events_t [NrCores-1:0] core_events; + tcdm_events_t tcdm_events; + dma_events_t dma_events; + snitch_icache_pkg::icache_events_t [NrCores-1:0] icache_events; + + // 4. Memory Subsystem (Core side). + reqrsp_req_t [NrCores-1:0] core_req, filtered_core_req; + reqrsp_rsp_t [NrCores-1:0] core_rsp, filtered_core_rsp; + + // 5. Peripheral Subsystem + reg_req_t reg_req; + reg_rsp_t reg_rsp; + + // 6. BootROM + reg_dma_req_t bootrom_reg_req; + reg_dma_rsp_t bootrom_reg_rsp; + + // 7. Misc. Wires. + logic icache_prefetch_enable; + logic [NrCores-1:0] cl_interrupt; + + // 8. L1 D$ + spm_req_t [NrTCDMPortsCores-1:0] spm_req; + spm_rsp_t [NrTCDMPortsCores-1:0] spm_rsp; + + tcdm_req_t [NrTCDMPortsCores-1:0] unmerge_req, strb_hdl_req, cache_req; + tcdm_rsp_t [NrTCDMPortsCores-1:0] unmerge_rsp, strb_hdl_rsp, cache_rsp; + + logic [NrTCDMPortsCores-1:0] cache_req_valid; + logic [NrTCDMPortsCores-1:0] cache_req_ready; + tcdm_addr_t [NrTCDMPortsCores-1:0] cache_req_addr; + tcdm_user_t [NrTCDMPortsCores-1:0] cache_req_meta; + logic [NrTCDMPortsCores-1:0] cache_req_write; + data_t [NrTCDMPortsCores-1:0] cache_req_data; + + logic [NrTCDMPortsCores-1:0] cache_rsp_valid; + logic [NrTCDMPortsCores-1:0] cache_rsp_ready; + logic [NrTCDMPortsCores-1:0] cache_rsp_write; + data_t [NrTCDMPortsCores-1:0] cache_rsp_data; + tcdm_user_t [NrTCDMPortsCores-1:0] cache_rsp_meta; + + logic [L1NumTagBank-1:0] l1_tag_bank_req; + logic [L1NumTagBank-1:0] l1_tag_bank_we; + tcdm_bank_addr_t [L1NumTagBank-1:0] l1_tag_bank_addr; + data_t [L1NumTagBank-1:0] l1_tag_bank_wdata; + logic [L1NumTagBank-1:0] l1_tag_bank_be; + data_t [L1NumTagBank-1:0] l1_tag_bank_rdata; + + logic [L1NumDataBank-1:0] l1_data_bank_req; + logic [L1NumDataBank-1:0] l1_data_bank_we; + tcdm_bank_addr_t [L1NumDataBank-1:0] l1_data_bank_addr; + data_t [L1NumDataBank-1:0] l1_data_bank_wdata; + logic [L1NumDataBank-1:0] l1_data_bank_be; + data_t [L1NumDataBank-1:0] l1_data_bank_rdata; + logic [L1NumDataBank-1:0] l1_data_bank_gnt; + + logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_req; + logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_we; + tcdm_bank_addr_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_addr; + data_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_wdata; + strb_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_be; + data_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_rdata; + logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_gnt; + + logic l1d_insn_valid, l1d_insn_ready; + logic [1:0] l1d_insn; + tcdm_bank_addr_t cfg_spm_size; + tcdm_addr_t spm_size; + logic l1d_busy; + + // High if a port access an illegal SPM region (mapped to cache) + logic [NrTCDMPortsCores-1:0] spm_error; + + + // 9. SRAM Configuration + impl_in_t [L1NumWrapper-1:0][L1BankPerWP-1:0] impl_l1d_data; + impl_in_t [L1NumTagBank-1:0] impl_l1d_tag; + impl_in_t [1:0] impl_l1d_fifo; + + impl_in_t [ICacheSets-1:0] impl_l1i_data; + impl_in_t [ICacheSets-1:0] impl_l1i_tag; + + assign {impl_l1d_data, impl_l1d_tag, impl_l1d_fifo, impl_l1i_data, impl_l1i_tag} = impl_i; + assign error_o = |spm_error; + + + // ------------- + // DMA Subsystem + // ------------- + // Optionally decouple the external wide AXI master port. + axi_cut #( + .Bypass (!RegisterExt ), + .aw_chan_t (axi_slv_dma_aw_chan_t), + .w_chan_t (axi_slv_dma_w_chan_t ), + .b_chan_t (axi_slv_dma_b_chan_t ), + .ar_chan_t (axi_slv_dma_ar_chan_t), + .r_chan_t (axi_slv_dma_r_chan_t ), + .axi_req_t (axi_slv_dma_req_t ), + .axi_resp_t (axi_slv_dma_resp_t ) + ) i_cut_ext_wide_out ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (wide_axi_slv_req[SoCDMAOut]), + .slv_resp_o (wide_axi_slv_rsp[SoCDMAOut]), + .mst_req_o (axi_out_req_o ), + .mst_resp_i (axi_out_resp_i ) + ); + + axi_cut #( + .Bypass (!RegisterExt ), + .aw_chan_t (axi_slv_dma_aw_chan_t), + .w_chan_t (axi_slv_dma_w_chan_t ), + .b_chan_t (axi_slv_dma_b_chan_t ), + .ar_chan_t (axi_slv_dma_ar_chan_t), + .r_chan_t (axi_slv_dma_r_chan_t ), + .axi_req_t (axi_slv_dma_req_t ), + .axi_resp_t (axi_slv_dma_resp_t ) + ) i_cut_ext_l2_wide_out ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (wide_axi_slv_req[L2Mem]), + .slv_resp_o (wide_axi_slv_rsp[L2Mem]), + .mst_req_o (axi_out_l2_req_o ), + .mst_resp_i (axi_out_l2_resp_i ) + ); + + axi_cut #( + .Bypass (!RegisterExt ), + .aw_chan_t (axi_mst_aw_chan_t), + .w_chan_t (axi_mst_w_chan_t ), + .b_chan_t (axi_mst_b_chan_t ), + .ar_chan_t (axi_mst_ar_chan_t), + .r_chan_t (axi_mst_r_chan_t ), + .axi_req_t (axi_mst_req_t ), + .axi_resp_t (axi_mst_resp_t ) + ) i_cut_ext_narrow_in ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (axi_in_req_i ), + .slv_resp_o (axi_in_resp_o ), + .mst_req_o (narrow_axi_mst_req[SoCDMAIn]), + .mst_resp_i (narrow_axi_mst_rsp[SoCDMAIn]) + ); + + logic [DmaXbarCfg.NoSlvPorts-1:0][$clog2(DmaXbarCfg.NoMstPorts)-1:0] dma_xbar_default_port; + xbar_rule_t [DmaXbarCfg.NoAddrRules-1:0] dma_xbar_rule; + + assign dma_xbar_default_port = '{default: SoCDMAOut}; + assign dma_xbar_rule = '{ + '{ + idx : TCDMDMA, + start_addr: tcdm_start_address, + end_addr : tcdm_end_address + }, + '{ + idx : BootROM, + start_addr: BootAddr, + end_addr : BootAddr + 'h1000 + }, + '{ + idx : L2Mem, + start_addr: cluster_l2_start_address, + end_addr : cluster_l2_end_address + } + }; + + localparam bit [DmaXbarCfg.NoSlvPorts-1:0] DMAEnableDefaultMstPort = '1; + axi_xbar #( + .Cfg (DmaXbarCfg ), + .ATOPs (0 ), + .slv_aw_chan_t (axi_mst_dma_aw_chan_t), + .mst_aw_chan_t (axi_slv_dma_aw_chan_t), + .w_chan_t (axi_mst_dma_w_chan_t ), + .slv_b_chan_t (axi_mst_dma_b_chan_t ), + .mst_b_chan_t (axi_slv_dma_b_chan_t ), + .slv_ar_chan_t (axi_mst_dma_ar_chan_t), + .mst_ar_chan_t (axi_slv_dma_ar_chan_t), + .slv_r_chan_t (axi_mst_dma_r_chan_t ), + .mst_r_chan_t (axi_slv_dma_r_chan_t ), + .slv_req_t (axi_mst_dma_req_t ), + .slv_resp_t (axi_mst_dma_resp_t ), + .mst_req_t (axi_slv_dma_req_t ), + .mst_resp_t (axi_slv_dma_resp_t ), + .rule_t (xbar_rule_t ) + ) i_axi_dma_xbar ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .test_i (1'b0 ), + .slv_ports_req_i (wide_axi_mst_req ), + .slv_ports_resp_o (wide_axi_mst_rsp ), + .mst_ports_req_o (wide_axi_slv_req ), + .mst_ports_resp_i (wide_axi_slv_rsp ), + .addr_map_i (dma_xbar_rule ), + .en_default_mst_port_i (DMAEnableDefaultMstPort), + .default_mst_port_i (dma_xbar_default_port ) + ); + + addr_t ext_dma_req_q_addr_nontrunc; + + axi_to_mem_interleaved #( + .axi_req_t (axi_slv_dma_req_t ), + .axi_resp_t (axi_slv_dma_resp_t ), + .AddrWidth (AxiAddrWidth ), + .DataWidth (AxiDataWidth ), + .IdWidth (WideIdWidthOut ), + .NumBanks (1 ), + .BufDepth (MemoryMacroLatency + 1) + ) i_axi_to_mem_dma ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .busy_o (/* Unused */ ), + .test_i (1'b0 ), + .axi_req_i (wide_axi_slv_req[TCDMDMA] ), + .axi_resp_o (wide_axi_slv_rsp[TCDMDMA] ), + .mem_req_o (ext_dma_req.q_valid ), + .mem_gnt_i (ext_dma_rsp.q_ready ), + .mem_addr_o (ext_dma_req_q_addr_nontrunc ), + .mem_wdata_o (ext_dma_req.q.data ), + .mem_strb_o (ext_dma_req.q.strb ), + .mem_atop_o (/* The DMA does not support atomics */), + .mem_we_o (ext_dma_req.q.write ), + .mem_rvalid_i (ext_dma_rsp.p_valid ), + .mem_rdata_i (ext_dma_rsp.p.data ) + ); + + assign ext_dma_req.q.addr = tcdm_addr_t'(ext_dma_req_q_addr_nontrunc); + assign ext_dma_req.q.amo = reqrsp_pkg::AMONone; + assign ext_dma_req.q.user = '0; + + spatz_tcdm_interconnect #( + .NumInp (1 ), + .NumOut (NrSuperBanks ), + .tcdm_req_t (tcdm_dma_req_t ), + .tcdm_rsp_t (tcdm_dma_rsp_t ), + .mem_req_t (mem_dma_req_t ), + .mem_rsp_t (mem_dma_rsp_t ), + .user_t (logic ), + .MemAddrWidth (TCDMMemAddrWidth ), + .DataWidth (AxiDataWidth ), + .MemoryResponseLatency (MemoryMacroLatency) + ) i_dma_interconnect ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .req_i (ext_dma_req), + .rsp_o (ext_dma_rsp), + .mem_req_o (sb_dma_req ), + .mem_rsp_i (sb_dma_rsp ) + ); + + // ---------------- + // Memory Subsystem + // ---------------- + for (genvar i = 0; i < NrSuperBanks; i++) begin : gen_tcdm_super_bank + + mem_req_t [BanksPerSuperBank-1:0] amo_req; + mem_rsp_t [BanksPerSuperBank-1:0] amo_rsp; + + mem_wide_narrow_mux #( + .NarrowDataWidth (NarrowDataWidth), + .WideDataWidth (AxiDataWidth ), + .mem_narrow_req_t (mem_req_t ), + .mem_narrow_rsp_t (mem_rsp_t ), + .mem_wide_req_t (mem_dma_req_t ), + .mem_wide_rsp_t (mem_dma_rsp_t ) + ) i_tcdm_mux ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .in_narrow_req_i (ic_req [i] ), + .in_narrow_rsp_o (ic_rsp [i] ), + .in_wide_req_i (sb_dma_req [i] ), + .in_wide_rsp_o (sb_dma_rsp [i] ), + .out_req_o (amo_req ), + .out_rsp_i (amo_rsp ), + .sel_wide_i (sb_dma_req[i].q_valid) + ); + + // generate banks of the superbank + for (genvar j = 0; j < BanksPerSuperBank; j++) begin : gen_tcdm_bank + + logic mem_cs, mem_wen; + tcdm_mem_addr_t mem_add; + tcdm_mem_addr_t mem_add_max; + strb_t mem_be; + data_t mem_rdata, mem_wdata; + tcdm_meta_t mem_req_meta; + assign mem_add_max = 0 - 1'b1; + + spatz_sram_wrapper #( + .NumBanks (L1BankPerWP ), + .NumWords (TCDMDepth ), + .ByteWidth (8 ), + .DataWidth (DataWidth ), + .MemoryResponseLatency (1 ), + .impl_in_t (impl_in_t ) + ) i_data_mem ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .spm_size_i (cfg_spm_size ), + /// Cache Side TODO: Connect cache + .cache_req_i (l1_cache_wp_req [j] ), + .cache_we_i (l1_cache_wp_we [j] ), + .cache_addr_i (l1_cache_wp_addr [j] ), + .cache_wdata_i(l1_cache_wp_wdata[j] ), + .cache_be_i (l1_cache_wp_be [j] ), + .cache_rdata_o(l1_cache_wp_rdata[j] ), + .cache_ready_o(l1_cache_wp_gnt [j] ), + /// SPM Side + .spm_req_i (mem_cs ), + .spm_we_i (mem_wen ), + .spm_addr_i (mem_add_max - mem_add), // swap the position of stack and data + .spm_wdata_i (mem_wdata ), + .spm_be_i (mem_be ), + .spm_rdata_o (mem_rdata ), + /// SRAM Configuration + .impl_i (impl_l1d_data[j] ) + ); + + data_t amo_rdata_local; + + // TODO(zarubaf): Share atomic units between mutltiple cuts + snitch_amo_shim #( + .AddrMemWidth ( TCDMMemAddrWidth ), + .DataWidth ( DataWidth ), + .CoreIDWidth ( CoreIDWidth ) + ) i_amo_shim ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .valid_i (amo_req[j].q_valid ), + .ready_o (amo_rsp[j].q_ready ), + .addr_i (amo_req[j].q.addr ), + .write_i (amo_req[j].q.write ), + .wdata_i (amo_req[j].q.data ), + .wstrb_i (amo_req[j].q.strb ), + .core_id_i (amo_req[j].q.user.core_id ), + .is_core_i (amo_req[j].q.user.is_core ), + .rdata_o (amo_rdata_local ), + .amo_i (amo_req[j].q.amo ), + .mem_req_o (mem_cs ), + .mem_add_o (mem_add ), + .mem_wen_o (mem_wen ), + .mem_wdata_o (mem_wdata ), + .mem_be_o (mem_be ), + .mem_rdata_i (mem_rdata ), + .dma_access_i (sb_dma_req[i].q_valid ), + // TODO(zarubaf): Signal AMO conflict somewhere. Socregs? + .amo_conflict_o (/* Unused */ ) + ); + + // Insert a pipeline register at the output of each SRAM. + shift_reg #( + .dtype(data_t ), + .Depth(int'(RegisterTCDMCuts)) + ) i_sram_pipe ( + .clk_i (clk_i ), + .rst_ni(rst_ni ), + .d_i (amo_rdata_local ), + .d_o (amo_rsp[j].p.data) + ); + + // delay the req_id two cycles: 1 for bank access, 1 for reg + shift_reg #( + .dtype(tcdm_meta_t ), + .Depth(int'(RegisterTCDMCuts)) + ) i_reqid_pipe1 ( + .clk_i (clk_i ), + .rst_ni(rst_ni ), + .d_i ({amo_req[j].q.user.req_id, amo_req[j].q.write}), + .d_o (mem_req_meta ) + ); + shift_reg #( + .dtype(tcdm_meta_t ), + .Depth(int'(RegisterTCDMCuts)) + ) i_reqid_pipe2 ( + .clk_i (clk_i ), + .rst_ni(rst_ni ), + .d_i (mem_req_meta ), + .d_o ({amo_rsp[j].p.user.req_id, amo_rsp[j].p.write}) + ); + + // tie unused field to 0 + // TODO: remove these fields + assign amo_rsp[j].p.user.core_id = '0; + assign amo_rsp[j].p.user.is_core = '0; + end + end + + logic [NrTCDMPortsCores-1:0] unmerge_pready, strb_hdl_pready, cache_pready; + assign spm_size = cfg_spm_size * L1Associativity * L1LineWidth / 2; + + // split the requests for spm or cache from core side + spatz_addr_mapper #( + .NumIO (NrTCDMPortsCores ), + .AddrWidth (L1AddrWidth ), + .SPMAddrWidth (SPMAddrWidth ), + .DataWidth (DataWidth ), + .mem_req_t (tcdm_req_t ), + .mem_rsp_t (tcdm_rsp_t ), + .mem_rsp_chan_t (tcdm_rsp_chan_t ), + .spm_req_t (spm_req_t ), + .spm_rsp_t (spm_rsp_t ) + ) i_tcdm_mapper ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + // Input + .mem_req_i (tcdm_req ), + .mem_rsp_o (tcdm_rsp ), + .error_o (spm_error ), + // Address + .tcdm_start_address_i (tcdm_start_address[L1AddrWidth-1:0] ), + .tcdm_end_address_i (tcdm_end_address[L1AddrWidth-1:0] ), + .spm_size_i (spm_size ), + .flush_i (l1d_busy ), + // Output + .spm_req_o (spm_req ), + .spm_rsp_i (spm_rsp ), + .cache_req_o (unmerge_req ), + .cache_pready_o (unmerge_pready ), + .cache_rsp_i (unmerge_rsp ) + ); + + localparam int unsigned NumIOPerCore = get_tcdm_ports(0); + logic [NrTCDMPortsCores-1:0] strb_req_ack; + + spatz_strbreq_merge_tree #( + .NumIO (NrTCDMPortsCores ), + .NumOutstandingMem (NumSpatzOutstandingLoads[0] ), + .MergeNum (NrTCDMPortsCores - NrCores ), + .DataWidth (DataWidth ), + .mem_req_t (tcdm_req_t ), + .mem_rsp_t (tcdm_rsp_t ), + .req_id_t (reqid_t ), + .tcdm_user_t (tcdm_user_t ) + ) i_strbreq_merge_tree ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .unmerge_req_i (unmerge_req ), + .unmerge_pready_i(unmerge_pready ), + .merge_rsp_i (strb_hdl_rsp ), + .merge_req_o (strb_hdl_req ), + .merge_pready_o (strb_hdl_pready ), + .unmerge_rsp_o (unmerge_rsp ) + ); + + for (genvar j = 0; j < NrTCDMPortsCores; j++) begin: gen_strb_hdlr + spatz_strbreq_handler #( + .DataWidth (DataWidth ), + .mem_req_t (tcdm_req_t ), + .mem_rsp_t (tcdm_rsp_t ), + .reqrsp_user_t (tcdm_user_t ) + ) i_strbreq_handler ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .strb_req_i (strb_hdl_req[j] ), + .strb_rsp_ready_i (strb_hdl_pready[j] ), + .strb_rsp_i (cache_rsp[j] ), + .strb_req_o (cache_req[j] ), + .strb_rsp_ready_o (cache_pready[j] ), + .strb_rsp_o (strb_hdl_rsp[j] ) + ); + + assign cache_req_valid[j] = cache_req[j].q_valid; + assign cache_rsp_ready[j] = cache_pready[j]; + assign cache_req_addr[j] = cache_req[j].q.addr; + assign cache_req_meta[j] = cache_req[j].q.user; + assign cache_req_write[j] = cache_req[j].q.write; + assign cache_req_data[j] = cache_req[j].q.data; + + assign cache_rsp[j].p_valid = cache_rsp_valid[j]; + assign cache_rsp[j].q_ready = cache_req_ready[j]; + assign cache_rsp[j].p.data = cache_rsp_data[j]; + assign cache_rsp[j].p.user = cache_rsp_meta[j]; + + assign cache_rsp[j].p.write = cache_rsp_write[j]; + end + + flamingo_spatz_cache_ctrl #( + // Core + .NumPorts (NrTCDMPortsCores ), + .CoalExtFactor (L1CoalFactor ), + .AddrWidth (L1AddrWidth ), + .WordWidth (DataWidth ), + // Cache + .NumCacheEntry (L1NumEntry ), + .CacheLineWidth (L1LineWidth ), + .SetAssociativity (L1Associativity ), + .BankFactor (L1BankFactor ), + // Type + .core_meta_t (tcdm_user_t ), + .impl_in_t (impl_in_t ), + .axi_req_t (axi_mst_dma_req_t ), + .axi_resp_t (axi_mst_dma_resp_t) + ) i_l1_controller ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .impl_i (impl_l1d_fifo ), + // Sync Control + .cache_sync_valid_i (l1d_insn_valid ), + .cache_sync_ready_o (l1d_insn_ready ), + .cache_sync_insn_i (l1d_insn ), + // SPM Size + // The calculation of spm region in cache is different + // than other modules (needs to times 2) + .bank_depth_for_SPM_i ((cfg_spm_size<<1) ), + // Request + .core_req_valid_i (cache_req_valid ), + .core_req_ready_o (cache_req_ready ), + .core_req_addr_i (cache_req_addr ), + .core_req_meta_i (cache_req_meta ), + .core_req_write_i (cache_req_write ), + .core_req_wdata_i (cache_req_data ), + // Response + .core_resp_valid_o (cache_rsp_valid ), + .core_resp_ready_i (cache_rsp_ready ), + .core_resp_write_o (cache_rsp_write ), + .core_resp_data_o (cache_rsp_data ), + .core_resp_meta_o (cache_rsp_meta ), + // AXI refill + .axi_req_o (wide_axi_mst_req[DCache] ), + .axi_resp_i (wide_axi_mst_rsp[DCache] ), + // Tag Banks + .tcdm_tag_bank_req_o (l1_tag_bank_req ), + .tcdm_tag_bank_we_o (l1_tag_bank_we ), + .tcdm_tag_bank_addr_o (l1_tag_bank_addr ), + .tcdm_tag_bank_wdata_o (l1_tag_bank_wdata ), + .tcdm_tag_bank_be_o (l1_tag_bank_be ), + .tcdm_tag_bank_rdata_i (l1_tag_bank_rdata ), + // Data Banks + .tcdm_data_bank_req_o (l1_data_bank_req ), + .tcdm_data_bank_we_o (l1_data_bank_we ), + .tcdm_data_bank_addr_o (l1_data_bank_addr ), + .tcdm_data_bank_wdata_o(l1_data_bank_wdata ), + .tcdm_data_bank_be_o (l1_data_bank_be ), + .tcdm_data_bank_rdata_i(l1_data_bank_rdata ), + .tcdm_data_bank_gnt_i (l1_data_bank_gnt ) + ); + + for (genvar j = 0; j < L1NumTagBank; j++) begin: gen_l1_tag_banks + tc_sram_impl #( + .NumWords (L1CacheWayEntry/L1BankFactor), + .DataWidth ($bits(data_t) ), + .ByteWidth ($bits(data_t) ), + .NumPorts (1 ), + .Latency (1 ), + .SimInit ("zeros" ), + .impl_in_t (impl_in_t ) + ) i_meta_bank ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .impl_i (impl_l1d_tag [j]), + .impl_o (/* unsed */ ), + .req_i (l1_tag_bank_req [j]), + .we_i (l1_tag_bank_we [j]), + .addr_i (l1_tag_bank_addr [j]), + .wdata_i(l1_tag_bank_wdata[j]), + .be_i (l1_tag_bank_be [j]), + .rdata_o(l1_tag_bank_rdata[j]) + ); + end + + for (genvar i = 0; i < L1NumWrapper; i++) begin + for (genvar j = 0; j < L1Associativity*L1BankFactor; j++) begin + assign l1_cache_wp_req [i][j] = l1_data_bank_req [i + j*L1NumWrapper]; + assign l1_cache_wp_we [i][j] = l1_data_bank_we [i + j*L1NumWrapper]; + assign l1_cache_wp_addr [i][j] = l1_data_bank_addr [i + j*L1NumWrapper]; + assign l1_cache_wp_wdata[i][j] = l1_data_bank_wdata[i + j*L1NumWrapper]; + assign l1_cache_wp_be [i][j] = (l1_data_bank_be [i + j*L1NumWrapper]) ? {(NarrowDataWidth/8){1'b1}} : '0; + + assign l1_data_bank_rdata[i + j*L1NumWrapper] = l1_cache_wp_rdata[i][j]; + assign l1_data_bank_gnt [i + j*L1NumWrapper] = l1_cache_wp_gnt [i][j]; + end + end + + // We have multiple banks form a pesudo bank (BankWP) + spatz_tcdm_interconnect #( + .NumInp (NumTCDMIn ), + .NumOut (L1NumWrapper ), + .tcdm_req_t (spm_req_t ), + .tcdm_rsp_t (spm_rsp_t ), + .mem_req_t (mem_req_t ), + .mem_rsp_t (mem_rsp_t ), + .MemAddrWidth (TCDMMemAddrWidth ), + .DataWidth (DataWidth ), + .user_t (tcdm_user_t ), + .MemoryResponseLatency (1 + RegisterTCDMCuts) + ) i_tcdm_interconnect ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .req_i ({axi_soc_req, spm_req} ), + .rsp_o ({axi_soc_rsp, spm_rsp} ), + .mem_req_o (ic_req ), + .mem_rsp_i (ic_rsp ) + ); + + hive_req_t [NrCores-1:0] hive_req; + hive_rsp_t [NrCores-1:0] hive_rsp; + + for (genvar i = 0; i < NrCores; i++) begin : gen_core + localparam int unsigned TcdmPorts = get_tcdm_ports(i); + localparam int unsigned TcdmPortsOffs = get_tcdm_port_offs(i); + + axi_mst_dma_req_t axi_dma_req; + axi_mst_dma_resp_t axi_dma_res; + interrupts_t irq; + dma_events_t dma_core_events; + + sync #(.STAGES (2)) + i_sync_debug (.clk_i, .rst_ni, .serial_i (debug_req_i[i]), .serial_o (irq.debug)); + sync #(.STAGES (2)) + i_sync_meip (.clk_i, .rst_ni, .serial_i (meip_i[i]), .serial_o (irq.meip)); + sync #(.STAGES (2)) + i_sync_mtip (.clk_i, .rst_ni, .serial_i (mtip_i[i]), .serial_o (irq.mtip)); + sync #(.STAGES (2)) + i_sync_msip (.clk_i, .rst_ni, .serial_i (msip_i[i]), .serial_o (irq.msip)); + assign irq.mcip = cl_interrupt[i]; + + tcdm_req_t [TcdmPorts-1:0] tcdm_req_wo_user; + + logic [31:0] hart_id; + assign hart_id = hart_base_id_i + i; + + spatz_mempool_cc #( + .BootAddr ( BootAddr ), + .RVE ( 0 ), + .RVM ( 1 ), + .RVV ( RVV ), + .XFVEC ( XFVEC ), + .XFDOTP ( XFDOTP ), + .XFAUX ( XFAUX ), + .RVF ( RVF ), + .RVD ( RVD ), + .XF16 ( XF16 ), + .XF16ALT ( XF16ALT ), + .XF8 ( XF8 ), + .XDivSqrt ( XDivSqrt ), + .NumMemPortsPerSpatz ( NumMemPortsPerSpatz ), + .TCDMPorts ( NumDataPortsPerCore ), + .BankOffset ( ByteOffset+$clog2(NumBanksPerTile)), + .NumCoresPerTile ( NumCoresPerTile ), + .TileLen ( $clog2(NumTiles) ), + .NumBanks ( NumBanks ) + ) i_spatz_cc ( + .clk_i (clk_i ), + .rst_i (!rst_ni ), + .hart_id_i (hart_id ), + // IMEM Port + .inst_addr_o (snitch_inst_addr[c/NumCoresPerCache][c%NumCoresPerCache] ), + .inst_data_i (snitch_inst_data[c/NumCoresPerCache][c%NumCoresPerCache] ), + .inst_valid_o (snitch_inst_valid[c/NumCoresPerCache][c%NumCoresPerCache]), + .inst_ready_i (snitch_inst_ready[c/NumCoresPerCache][c%NumCoresPerCache]), + // Data Ports + .data_qaddr_o (snitch_data_qaddr[i] ), + .data_qwrite_o (snitch_data_qwrite[i] ), + .data_qamo_o (snitch_data_qamo[i] ), + .data_qdata_o (snitch_data_qdata[i] ), + .data_qstrb_o (snitch_data_qstrb[i] ), + .data_qid_o (snitch_data_qid[i] ), + .data_qvalid_o (snitch_data_qvalid[i] ), + .data_qready_i (snitch_data_qready[i] ), + .data_pdata_i (snitch_data_pdata[i] ), + .data_pwrite_i (snitch_data_pwrite[i] ), + .data_perror_i (snitch_data_perror[i] ), + .data_pid_i (snitch_data_pid[i] ), + .data_pvalid_i (snitch_data_pvalid[i] ), + .data_pready_o (snitch_data_pready[i] ), + .wake_up_sync_i(wake_up_q[i] ), + // Core Events + .core_events_o (/* Unused */ ) + ); + for (genvar j = 0; j < TcdmPorts; j++) begin : gen_tcdm_user + always_comb begin + tcdm_req[TcdmPortsOffs+j].q = tcdm_req_wo_user[j].q; + tcdm_req[TcdmPortsOffs+j].q.user.core_id = i[CoreIDWidth-1:0]; + tcdm_req[TcdmPortsOffs+j].q.user.is_core = 1; + tcdm_req[TcdmPortsOffs+j].q_valid = tcdm_req_wo_user[j].q_valid; + end + end + if (Xdma[i]) begin : gen_dma_connection + assign wide_axi_mst_req[SDMAMst] = axi_dma_req; + assign axi_dma_res = wide_axi_mst_rsp[SDMAMst]; + assign dma_events = dma_core_events; + end else begin + assign axi_dma_res = '0; + end + end + + // ---------------- + // Instruction Cache + // ---------------- + + addr_t [NrCores-1:0] inst_addr; + logic [NrCores-1:0] inst_cacheable; + logic [NrCores-1:0][31:0] inst_data; + logic [NrCores-1:0] inst_valid; + logic [NrCores-1:0] inst_ready; + logic [NrCores-1:0] inst_error; + logic [NrCores-1:0] flush_valid; + logic [NrCores-1:0] flush_ready; + + for (genvar i = 0; i < NrCores; i++) begin : gen_unpack_icache + assign inst_addr[i] = hive_req[i].inst_addr; + assign inst_cacheable[i] = hive_req[i].inst_cacheable; + assign inst_valid[i] = hive_req[i].inst_valid; + assign flush_valid[i] = hive_req[i].flush_i_valid; + assign hive_rsp[i] = '{ + inst_data : inst_data[i], + inst_ready : inst_ready[i], + inst_error : inst_error[i], + flush_i_ready: flush_ready[i], + default : '0 + }; + end + + snitch_icache #( + .NR_FETCH_PORTS ( NrCores ), + .L0_LINE_COUNT ( 8 ), + .LINE_WIDTH ( ICacheLineWidth ), + .LINE_COUNT ( ICacheLineCount ), + .SET_COUNT ( ICacheSets ), + .FETCH_AW ( AxiAddrWidth ), + .FETCH_DW ( 32 ), + .FILL_AW ( AxiAddrWidth ), + .FILL_DW ( AxiDataWidth ), + .EARLY_LATCH ( 0 ), + .L0_EARLY_TAG_WIDTH ( snitch_pkg::PAGE_SHIFT - $clog2(ICacheLineWidth/8) ), + .ISO_CROSSING ( 1'b0 ), + .axi_req_t ( axi_mst_dma_req_t ), + .axi_rsp_t ( axi_mst_dma_resp_t ), + .sram_cfg_data_t ( impl_in_t ), + .sram_cfg_tag_t ( impl_in_t ) + ) i_snitch_icache ( + .clk_i ( clk_i ), + .clk_d2_i ( clk_i ), + .rst_ni ( rst_ni ), + .enable_prefetching_i ( icache_prefetch_enable ), + .icache_events_o ( icache_events ), + .flush_valid_i ( flush_valid ), + .flush_ready_o ( flush_ready ), + .inst_addr_i ( inst_addr ), + .inst_cacheable_i ( inst_cacheable ), + .inst_data_o ( inst_data ), + .inst_valid_i ( inst_valid ), + .inst_ready_o ( inst_ready ), + .inst_error_o ( inst_error ), + .sram_cfg_tag_i ( impl_l1i_tag ), + .sram_cfg_data_i ( impl_l1i_data ), + .axi_req_o ( wide_axi_mst_req[ICache] ), + .axi_rsp_i ( wide_axi_mst_rsp[ICache] ) + ); + + // -------- + // Cores SoC + // -------- + spatz_barrier #( + .AddrWidth (AxiAddrWidth ), + .NrPorts (NrCores ), + .dreq_t (reqrsp_req_t ), + .drsp_t (reqrsp_rsp_t ) + ) i_snitch_barrier ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .in_req_i (core_req ), + .in_rsp_o (core_rsp ), + .out_req_o (filtered_core_req ), + .out_rsp_i (filtered_core_rsp ), + .cluster_periph_start_address_i (cluster_periph_start_address) + ); + + reqrsp_req_t core_to_axi_req; + reqrsp_rsp_t core_to_axi_rsp; + user_t cluster_user; + // Atomic ID, needs to be unique ID of cluster + // cluster_id + HartIdOffset + 1 (because 0 is for non-atomic masters) + assign cluster_user = (hart_base_id_i / NrCores) + (hart_base_id_i % NrCores) + 1'b1; + + reqrsp_mux #( + .NrPorts (NrCores ), + .AddrWidth (AxiAddrWidth ), + .DataWidth (NarrowDataWidth ), + .req_t (reqrsp_req_t ), + .rsp_t (reqrsp_rsp_t ), + .RespDepth (2 ) + ) i_reqrsp_mux_core ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (filtered_core_req), + .slv_rsp_o (filtered_core_rsp), + .mst_req_o (core_to_axi_req ), + .mst_rsp_i (core_to_axi_rsp ), + .idx_o (/*unused*/ ) + ); + + reqrsp_to_axi #( + .DataWidth (NarrowDataWidth), + .UserWidth (NarrowUserWidth), + .reqrsp_req_t (reqrsp_req_t ), + .reqrsp_rsp_t (reqrsp_rsp_t ), + .axi_req_t (axi_mst_req_t ), + .axi_rsp_t (axi_mst_resp_t ) + ) i_reqrsp_to_axi_core ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .user_i (cluster_user ), + .reqrsp_req_i (core_to_axi_req ), + .reqrsp_rsp_o (core_to_axi_rsp ), + .axi_req_o (narrow_axi_mst_req[CoreReq]), + .axi_rsp_i (narrow_axi_mst_rsp[CoreReq]) + ); + + xbar_rule_t [NrNarrowRules-1:0] cluster_xbar_rules; + + assign cluster_xbar_rules = '{ + '{ + idx : TCDM, + start_addr: tcdm_start_address, + end_addr : tcdm_end_address + }, + '{ + idx : ClusterPeripherals, + start_addr: cluster_periph_start_address, + end_addr : cluster_periph_end_address + } + }; + + localparam bit [ClusterXbarCfg.NoSlvPorts-1:0] ClusterEnableDefaultMstPort = '1; + localparam logic [ClusterXbarCfg.NoSlvPorts-1:0][cf_math_pkg::idx_width(ClusterXbarCfg.NoMstPorts)-1:0] ClusterXbarDefaultPort = '{default: SoC}; + + axi_xbar #( + .Cfg (ClusterXbarCfg ), + .slv_aw_chan_t (axi_mst_aw_chan_t), + .mst_aw_chan_t (axi_slv_aw_chan_t), + .w_chan_t (axi_mst_w_chan_t ), + .slv_b_chan_t (axi_mst_b_chan_t ), + .mst_b_chan_t (axi_slv_b_chan_t ), + .slv_ar_chan_t (axi_mst_ar_chan_t), + .mst_ar_chan_t (axi_slv_ar_chan_t), + .slv_r_chan_t (axi_mst_r_chan_t ), + .mst_r_chan_t (axi_slv_r_chan_t ), + .slv_req_t (axi_mst_req_t ), + .slv_resp_t (axi_mst_resp_t ), + .mst_req_t (axi_slv_req_t ), + .mst_resp_t (axi_slv_resp_t ), + .rule_t (xbar_rule_t ) + ) i_cluster_xbar ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .test_i (1'b0 ), + .slv_ports_req_i (narrow_axi_mst_req ), + .slv_ports_resp_o (narrow_axi_mst_rsp ), + .mst_ports_req_o (narrow_axi_slv_req ), + .mst_ports_resp_i (narrow_axi_slv_rsp ), + .addr_map_i (cluster_xbar_rules ), + .en_default_mst_port_i (ClusterEnableDefaultMstPort), + .default_mst_port_i (ClusterXbarDefaultPort ) + ); + + // --------- + // Slaves + // --------- + // 1. TCDM + // Add an adapter that allows access from AXI to the TCDM. + axi_to_tcdm #( + .axi_req_t (axi_slv_req_t ), + .axi_rsp_t (axi_slv_resp_t ), + .tcdm_req_t (spm_req_t ), + .tcdm_rsp_t (spm_rsp_t ), + .AddrWidth (AxiAddrWidth ), + .DataWidth (NarrowDataWidth ), + .IdWidth (NarrowIdWidthOut ), + .BufDepth (MemoryMacroLatency + 1) + ) i_axi_to_tcdm ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .axi_req_i (narrow_axi_slv_req[TCDM]), + .axi_rsp_o (narrow_axi_slv_rsp[TCDM]), + .tcdm_req_o (axi_soc_req ), + .tcdm_rsp_i (axi_soc_rsp ) + ); + + // 2. Peripherals + axi_to_reg #( + .ADDR_WIDTH (AxiAddrWidth ), + .DATA_WIDTH (NarrowDataWidth ), + .AXI_MAX_WRITE_TXNS (1 ), + .AXI_MAX_READ_TXNS (1 ), + .DECOUPLE_W (0 ), + .ID_WIDTH (NarrowIdWidthOut ), + .USER_WIDTH (NarrowUserWidth ), + .axi_req_t (axi_slv_req_t ), + .axi_rsp_t (axi_slv_resp_t ), + .reg_req_t (reg_req_t ), + .reg_rsp_t (reg_rsp_t ) + ) i_axi_to_reg ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .testmode_i (1'b0 ), + .axi_req_i (narrow_axi_slv_req[ClusterPeripherals]), + .axi_rsp_o (narrow_axi_slv_rsp[ClusterPeripherals]), + .reg_req_o (reg_req ), + .reg_rsp_i (reg_rsp ) + ); + + spatz_cluster_peripheral #( + .AddrWidth (AxiAddrWidth ), + .SPMWidth ($clog2(L1NumSet)), + .reg_req_t (reg_req_t ), + .reg_rsp_t (reg_rsp_t ), + .tcdm_events_t (tcdm_events_t ), + .dma_events_t (dma_events_t ), + .NrCores (NrCores ) + ) i_snitch_cluster_peripheral ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .reg_req_i (reg_req ), + .reg_rsp_o (reg_rsp ), + /// The TCDM always starts at the cluster base. + .tcdm_start_address_i (tcdm_start_address ), + .tcdm_end_address_i (tcdm_end_address ), + .icache_prefetch_enable_o (icache_prefetch_enable), + .cl_clint_o (cl_interrupt ), + .cluster_hart_base_id_i (hart_base_id_i ), + .core_events_i (core_events ), + .tcdm_events_i (tcdm_events ), + .dma_events_i (dma_events ), + .icache_events_i (icache_events ), + .cluster_probe_o (cluster_probe_o ), + .l1d_spm_size_o (cfg_spm_size ), + .l1d_insn_o (l1d_insn ), + .l1d_insn_valid_o (l1d_insn_valid ), + .l1d_insn_ready_i (l1d_insn_ready ), + .l1d_busy_o (l1d_busy ) + ); + + // 3. BootROM + axi_to_reg #( + .ADDR_WIDTH (AxiAddrWidth ), + .DATA_WIDTH (AxiDataWidth ), + .AXI_MAX_WRITE_TXNS (1 ), + .AXI_MAX_READ_TXNS (1 ), + .DECOUPLE_W (0 ), + .ID_WIDTH (WideIdWidthOut ), + .USER_WIDTH (AxiUserWidth ), + .axi_req_t (axi_slv_dma_req_t ), + .axi_rsp_t (axi_slv_dma_resp_t), + .reg_req_t (reg_dma_req_t ), + .reg_rsp_t (reg_dma_rsp_t ) + ) i_axi_to_reg_bootrom ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .testmode_i (1'b0 ), + .axi_req_i (wide_axi_slv_req[BootROM]), + .axi_rsp_o (wide_axi_slv_rsp[BootROM]), + .reg_req_o (bootrom_reg_req ), + .reg_rsp_i (bootrom_reg_rsp ) + ); + + bootrom i_bootrom ( + .clk_i (clk_i ), + .req_i (bootrom_reg_req.valid ), + .addr_i (addr_t'(bootrom_reg_req.addr)), + .rdata_o(bootrom_reg_rsp.rdata ) + ); + `FF(bootrom_reg_rsp.ready, bootrom_reg_req.valid, 1'b0) + assign bootrom_reg_rsp.error = 1'b0; + + // Upsize the narrow SoC connection + `AXI_TYPEDEF_ALL(axi_mst_dma_narrow, addr_t, id_dma_mst_t, data_t, strb_t, user_t) + axi_mst_dma_narrow_req_t narrow_axi_slv_req_soc; + axi_mst_dma_narrow_resp_t narrow_axi_slv_resp_soc; + + axi_iw_converter #( + .AxiAddrWidth (AxiAddrWidth ), + .AxiDataWidth (NarrowDataWidth ), + .AxiUserWidth (AxiUserWidth ), + .AxiSlvPortIdWidth (NarrowIdWidthOut ), + .AxiSlvPortMaxUniqIds (1 ), + .AxiSlvPortMaxTxnsPerId(1 ), + .AxiSlvPortMaxTxns (1 ), + .AxiMstPortIdWidth (WideIdWidthIn ), + .AxiMstPortMaxUniqIds (1 ), + .AxiMstPortMaxTxnsPerId(1 ), + .slv_req_t (axi_slv_req_t ), + .slv_resp_t (axi_slv_resp_t ), + .mst_req_t (axi_mst_dma_narrow_req_t ), + .mst_resp_t (axi_mst_dma_narrow_resp_t) + ) i_soc_port_iw_convert ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (narrow_axi_slv_req[SoC] ), + .slv_resp_o (narrow_axi_slv_rsp[SoC] ), + .mst_req_o (narrow_axi_slv_req_soc ), + .mst_resp_i (narrow_axi_slv_resp_soc ) + ); + + axi_dw_converter #( + .AxiAddrWidth (AxiAddrWidth ), + .AxiIdWidth (WideIdWidthIn ), + .AxiMaxReads (2 ), + .AxiSlvPortDataWidth(NarrowDataWidth ), + .AxiMstPortDataWidth(AxiDataWidth ), + .ar_chan_t (axi_mst_dma_ar_chan_t ), + .aw_chan_t (axi_mst_dma_aw_chan_t ), + .b_chan_t (axi_mst_dma_b_chan_t ), + .slv_r_chan_t (axi_mst_dma_narrow_r_chan_t), + .slv_w_chan_t (axi_mst_dma_narrow_b_chan_t), + .axi_slv_req_t (axi_mst_dma_narrow_req_t ), + .axi_slv_resp_t (axi_mst_dma_narrow_resp_t ), + .mst_r_chan_t (axi_mst_dma_r_chan_t ), + .mst_w_chan_t (axi_mst_dma_w_chan_t ), + .axi_mst_req_t (axi_mst_dma_req_t ), + .axi_mst_resp_t (axi_mst_dma_resp_t ) + ) i_soc_port_dw_upsize ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (narrow_axi_slv_req_soc ), + .slv_resp_o (narrow_axi_slv_resp_soc ), + .mst_req_o (wide_axi_mst_req[CoreReqWide]), + .mst_resp_i (wide_axi_mst_rsp[CoreReqWide]) + ); + + // -------------------- + // TCDM event counters + // -------------------- + logic [NrTCDMPortsCores-1:0] flat_acc, flat_con; + for (genvar i = 0; i < NrTCDMPortsCores; i++) begin : gen_event_counter + `FFARN(flat_acc[i], tcdm_req[i].q_valid, '0, clk_i, rst_ni) + `FFARN(flat_con[i], tcdm_req[i].q_valid & ~tcdm_rsp[i].q_ready, '0, clk_i, rst_ni) + end + + popcount #( + .INPUT_WIDTH ( NrTCDMPortsCores ) + ) i_popcount_req ( + .data_i ( flat_acc ), + .popcount_o ( tcdm_events.inc_accessed ) + ); + + popcount #( + .INPUT_WIDTH ( NrTCDMPortsCores ) + ) i_popcount_con ( + .data_i ( flat_con ), + .popcount_o ( tcdm_events.inc_congested ) + ); + + // ------------- + // Sanity Checks + // ------------- + // Sanity check the parameters. Not every configuration makes sense. + `ASSERT_INIT(CheckSuperBankSanity, NrBanks >= BanksPerSuperBank); + `ASSERT_INIT(CheckSuperBankFactor, (NrBanks % BanksPerSuperBank) == 0); + // Check that the cluster base address aligns to the TCDMSize. + `ASSERT(ClusterBaseAddrAlign, ((TCDMSize - 1) & cluster_base_addr_i) == 0) + // Make sure we only have one DMA in the system. + `ASSERT_INIT(NumberDMA, $onehot0(Xdma)) + +endmodule diff --git a/hardware/src/cachepool_cluster_simple.sv b/hardware/src/cachepool_cluster_simple.sv new file mode 100644 index 0000000..4f62f90 --- /dev/null +++ b/hardware/src/cachepool_cluster_simple.sv @@ -0,0 +1,1656 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Author: Diyou Shen + +`include "axi/assign.svh" +`include "axi/typedef.svh" +`include "common_cells/assertions.svh" +`include "common_cells/registers.svh" +`include "mem_interface/assign.svh" +`include "mem_interface/typedef.svh" +`include "register_interface//assign.svh" +`include "register_interface/typedef.svh" +`include "reqrsp_interface/assign.svh" +`include "reqrsp_interface/typedef.svh" +`include "snitch_vm/typedef.svh" +`include "tcdm_interface/assign.svh" +`include "tcdm_interface/typedef.svh" + +/// A single-tile cluster implementation for CachePool +module cachepool_cluster_simple + // import cachepool_pkg::*; + import spatz_pkg::*; + import fpnew_pkg::fpu_implementation_t; + import snitch_pma_pkg::snitch_pma_t; + #( + /// Width of physical address. + parameter int unsigned AxiAddrWidth = 48, + /// Width of AXI port. + parameter int unsigned AxiDataWidth = 512, + /// AXI: id width in. + parameter int unsigned AxiIdWidthIn = 2, + /// AXI: id width out. + parameter int unsigned AxiIdWidthOut = 2, + /// AXI: user width. + parameter int unsigned AxiUserWidth = 1, + /// Address from which to fetch the first instructions. + parameter logic [31:0] BootAddr = 32'h0, + /// Address to indicate start of L2 + parameter logic [AxiAddrWidth-1:0] L2Addr = 48'h0, + parameter logic [AxiAddrWidth-1:0] L2Size = 48'h0, + /// The total amount of cores. + parameter int unsigned NrCores = 8, + /// Data/TCDM memory depth per cut (in words). + parameter int unsigned TCDMDepth = 1024, + /// Cluster peripheral address region size (in kB). + parameter int unsigned ClusterPeriphSize = 64, + /// Number of TCDM Banks. + parameter int unsigned NrBanks = 2 * NrCores, + /// Size of DMA AXI buffer. + parameter int unsigned DMAAxiReqFifoDepth = 3, + /// Size of DMA request fifo. + parameter int unsigned DMAReqFifoDepth = 3, + /// Width of a single icache line. + parameter unsigned ICacheLineWidth = 0, + /// Number of icache lines per set. + parameter int unsigned ICacheLineCount = 0, + /// Number of icache sets. + parameter int unsigned ICacheSets = 0, + // PMA Configuration + parameter snitch_pma_t SnitchPMACfg = '{default: 0}, + /// # Core-global parameters + /// FPU configuration. + parameter fpu_implementation_t FPUImplementation [NrCores] = '{default: fpu_implementation_t'(0)}, + /// Spatz FPU/IPU Configuration + parameter int unsigned NumSpatzFPUs = 4, + parameter int unsigned NumSpatzIPUs = 1, + /// Per-core enabling of the custom `Xdma` ISA extensions. + parameter bit [NrCores-1:0] Xdma = '{default: '0}, + /// # Per-core parameters + /// Per-core integer outstanding loads + parameter int unsigned NumIntOutstandingLoads [NrCores] = '{default: '0}, + /// Per-core integer outstanding memory operations (load and stores) + parameter int unsigned NumIntOutstandingMem [NrCores] = '{default: '0}, + /// Per-core Spatz outstanding loads + parameter int unsigned NumSpatzOutstandingLoads [NrCores] = '{default: '0}, + /// ## Timing Tuning Parameters + /// Insert Pipeline registers into off-loading path (response) + parameter bit RegisterOffloadRsp = 1'b0, + /// Insert Pipeline registers into data memory path (request) + parameter bit RegisterCoreReq = 1'b0, + /// Insert Pipeline registers into data memory path (response) + parameter bit RegisterCoreRsp = 1'b0, + /// Insert Pipeline registers after each memory cut + parameter bit RegisterTCDMCuts = 1'b0, + /// Decouple external AXI plug + parameter bit RegisterExt = 1'b0, + parameter axi_pkg::xbar_latency_e XbarLatency = axi_pkg::CUT_ALL_PORTS, + /// Outstanding transactions on the AXI network + parameter int unsigned MaxMstTrans = 4, + parameter int unsigned MaxSlvTrans = 4, + /// # Interface + /// AXI Ports + parameter type axi_in_req_t = logic, + parameter type axi_in_resp_t = logic, + parameter type axi_out_req_t = logic, + parameter type axi_out_resp_t = logic, + /// SRAM configuration + parameter type impl_in_t = logic, + // Memory latency parameter. Most of the memories have a read latency of 1. In + // case you have memory macros which are pipelined you want to adjust this + // value here. This only applies to the TCDM. The instruction cache macros will break! + // In case you are using the `RegisterTCDMCuts` feature this adds an + // additional cycle latency, which is taken into account here. + parameter int unsigned MemoryMacroLatency = 1 + RegisterTCDMCuts, + /// # SRAM Configuration rules needed: L1D Tag + L1D Data + L1D FIFO + L1I Tag + L1I Data + /*** ATTENTION: `NrSramCfg` should be changed if `L1NumDataBank` and `L1NumTagBank` is changed ***/ + parameter int unsigned NrSramCfg = 1 + ) ( + /// System clock. + input logic clk_i, + /// Asynchronous active high reset. This signal is assumed to be _async_. + input logic rst_ni, + /// Per-core debug request signal. Asserting this signals puts the + /// corresponding core into debug mode. This signal is assumed to be _async_. + input logic [NrCores-1:0] debug_req_i, + /// Machine external interrupt pending. Usually those interrupts come from a + /// platform-level interrupt controller. This signal is assumed to be _async_. + input logic [NrCores-1:0] meip_i, + /// Machine timer interrupt pending. Usually those interrupts come from a + /// core-local interrupt controller such as a timer/RTC. This signal is + /// assumed to be _async_. + input logic [NrCores-1:0] mtip_i, + /// Core software interrupt pending. Usually those interrupts come from + /// another core to facilitate inter-processor-interrupts. This signal is + /// assumed to be _async_. + input logic [NrCores-1:0] msip_i, + /// First hartid of the cluster. Cores of a cluster are monotonically + /// increasing without a gap, i.e., a cluster with 8 cores and a + /// `hart_base_id_i` of 5 get the hartids 5 - 12. + input logic [9:0] hart_base_id_i, + /// Base address of cluster. TCDM and cluster peripheral location are derived from + /// it. This signal is pseudo-static. + input logic [AxiAddrWidth-1:0] cluster_base_addr_i, + /// Per-cluster probe on the cluster status. Can be written by the cores to indicate + /// to the overall system that the cluster is executing something. + output logic cluster_probe_o, + /// AXI Core cluster in-port. + input axi_in_req_t axi_in_req_i, + output axi_in_resp_t axi_in_resp_o, + /// AXI Core cluster out-port to core. + output axi_out_req_t axi_out_req_o, + input axi_out_resp_t axi_out_resp_i, + /// AXI Core cluster out-port to L2 Mem. + output axi_out_req_t axi_out_l2_req_o, + input axi_out_resp_t axi_out_l2_resp_i, + /// SRAM Configuration: L1D Data + L1D Tag + L1D FIFO + L1I Data + L1I Tag + input impl_in_t [NrSramCfg-1:0] impl_i, + /// Indicate the program execution is error + output logic error_o + ); + // --------- + // Imports + // --------- + import snitch_pkg::*; + import snitch_icache_pkg::icache_events_t; + + // --------- + // Constants + // --------- + /// Minimum width to hold the core number. + localparam int unsigned CoreIDWidth = cf_math_pkg::idx_width(NrCores); + localparam int unsigned TCDMMemAddrWidth = $clog2(TCDMDepth); + localparam int unsigned TCDMSize = NrBanks * TCDMDepth * (DataWidth/8); + // The short address for SPM + localparam int unsigned SPMAddrWidth = $clog2(TCDMSize); + // Enlarge the address width for Spatz due to cache + localparam int unsigned TCDMAddrWidth = 32; + localparam int unsigned BanksPerSuperBank = AxiDataWidth / DataWidth; + localparam int unsigned NrSuperBanks = NrBanks / BanksPerSuperBank; + + function automatic int unsigned get_tcdm_ports(int unsigned core); + return spatz_pkg::N_FU + 1; + endfunction + + function automatic int unsigned get_tcdm_port_offs(int unsigned core_idx); + automatic int n = 0; + for (int i = 0; i < core_idx; i++) n += get_tcdm_ports(i); + return n; + endfunction + + localparam int unsigned NrTCDMPortsPerCore = get_tcdm_ports(0); + localparam int unsigned NrTCDMPortsCores = get_tcdm_port_offs(NrCores); + localparam int unsigned NumTCDMIn = NrTCDMPortsCores + 1; + localparam logic [AxiAddrWidth-1:0] TCDMMask = ~(TCDMSize-1); + + // Core Request, SoC Request + localparam int unsigned NrNarrowMasters = 2; + + // Narrow AXI network parameters + localparam int unsigned NarrowIdWidthIn = AxiIdWidthIn; + localparam int unsigned NarrowIdWidthOut = NarrowIdWidthIn + $clog2(NrNarrowMasters); + localparam int unsigned NarrowDataWidth = ELEN; + localparam int unsigned NarrowUserWidth = AxiUserWidth; + + // TCDM, Peripherals, SoC Request + localparam int unsigned NrNarrowSlaves = 3; + localparam int unsigned NrNarrowRules = NrNarrowSlaves - 1; + + // Core Request, DMA, Instruction cache + /// Additional one for L1 DCache + localparam int unsigned NrWideMasters = 3 + 1; + localparam int unsigned WideIdWidthOut = AxiIdWidthOut; + localparam int unsigned WideIdWidthIn = WideIdWidthOut - $clog2(NrWideMasters); + // DMA X-BAR configuration + localparam int unsigned NrWideSlaves = 3 + 1; // one prot for L2, one for L3/LLC (virtual) + + // AXI Configuration + localparam axi_pkg::xbar_cfg_t ClusterXbarCfg = '{ + NoSlvPorts : NrNarrowMasters, + NoMstPorts : NrNarrowSlaves, + MaxMstTrans : MaxMstTrans, + MaxSlvTrans : MaxSlvTrans, + FallThrough : 1'b0, + LatencyMode : XbarLatency, + AxiIdWidthSlvPorts: NarrowIdWidthIn, + AxiIdUsedSlvPorts : NarrowIdWidthIn, + UniqueIds : 1'b0, + AxiAddrWidth : AxiAddrWidth, + AxiDataWidth : NarrowDataWidth, + NoAddrRules : NrNarrowRules, + default : '0 + }; + + // DMA configuration struct + localparam axi_pkg::xbar_cfg_t DmaXbarCfg = '{ + NoSlvPorts : NrWideMasters, + NoMstPorts : NrWideSlaves, + MaxMstTrans : MaxMstTrans, + MaxSlvTrans : MaxSlvTrans, + FallThrough : 1'b0, + LatencyMode : XbarLatency, + AxiIdWidthSlvPorts: WideIdWidthIn, + AxiIdUsedSlvPorts : WideIdWidthIn, + UniqueIds : 1'b0, + AxiAddrWidth : AxiAddrWidth, + AxiDataWidth : AxiDataWidth, + NoAddrRules : NrWideSlaves - 1, + default : '0 + }; + + /*********** TODO: Move into package ***********/ + // Address width of cache + localparam int unsigned L1AddrWidth = 32; + // Cache lane width + localparam int unsigned L1LineWidth = AxiDataWidth; + // Coalecser window + localparam int unsigned L1CoalFactor = 2; + // Total number of Data banks + localparam int unsigned L1NumDataBank = 128; + // Number of bank wraps SPM can see + localparam int unsigned L1NumWrapper = NrBanks; + // SPM view: Number of banks in each bank wrap (Use to mitigate routing complexity of such many banks) + localparam int unsigned L1BankPerWP = L1NumDataBank / NrBanks; + // Pesudo dual bank + localparam int unsigned L1BankFactor = 2; + // Cache ways (total way number across multiple cache controllers) + localparam int unsigned L1Associativity = L1NumDataBank / (L1LineWidth / DataWidth) / L1BankFactor; + // 8 * 1024 * 64 / 512 = 1024) + // Number of entrys of L1 Cache (total number across multiple cache controllers) + localparam int unsigned L1NumEntry = NrBanks * TCDMDepth * DataWidth / L1LineWidth; + // Number of cache entries each cache way has + localparam int unsigned L1CacheWayEntry = L1NumEntry / L1Associativity; + // Number of cache sets each cache way has + localparam int unsigned L1NumSet = L1CacheWayEntry / L1BankFactor; + // Number of Tag banks + localparam int unsigned L1NumTagBank = L1BankFactor * L1Associativity; + // Number of lines per bank unit + localparam int unsigned DepthPerBank = TCDMDepth / L1BankPerWP; + // Cache total size in KB + localparam int unsigned L1Size = NrBanks * TCDMDepth * DataWidth / 8 / 1024; + // Number of cache controller (now is fixde to NrCores (if we change it, we need to change the controller axi output id width too) + localparam int unsigned NumL1CacheCtrl = NrCores; + // Number of data banks assigned to each cache controller + localparam int unsigned NumDataBankPerCtrl = L1NumDataBank / NumL1CacheCtrl; + // Number of tag banks assigned to each cache controller + localparam int unsigned NumTagBankPerCtrl = L1NumTagBank / NumL1CacheCtrl; + // Number of ways per cache controller + localparam int unsigned L1AssoPerCtrl = L1Associativity / NumL1CacheCtrl; + // Number of entries per cache controller + localparam int unsigned L1NumEntryPerCtrl = L1NumEntry / NumL1CacheCtrl; + + // -------- + // Typedefs + // -------- + typedef logic [AxiAddrWidth-1:0] addr_t; + typedef logic [NarrowDataWidth-1:0] data_t; + typedef logic [63:0] tag_data_t; + typedef logic [NarrowDataWidth/8-1:0] strb_t; + typedef logic [AxiDataWidth-1:0] data_dma_t; + typedef logic [AxiDataWidth/8-1:0] strb_dma_t; + typedef logic [NarrowIdWidthIn-1:0] id_mst_t; + typedef logic [NarrowIdWidthOut-1:0] id_slv_t; + typedef logic [WideIdWidthIn-1:0] id_dma_mst_t; + typedef logic [WideIdWidthOut-1:0] id_dma_slv_t; + typedef logic [WideIdWidthIn-$clog2(NumL1CacheCtrl)-1:0] id_dcache_mst_t; + typedef logic [NarrowUserWidth-1:0] user_t; + typedef logic [AxiUserWidth-1:0] user_dma_t; + + typedef logic [TCDMMemAddrWidth-1:0] tcdm_mem_addr_t; + typedef logic [TCDMAddrWidth-1:0] tcdm_addr_t; + typedef logic [SPMAddrWidth-1:0] spm_addr_t; + + typedef logic [$clog2(NumSpatzOutstandingLoads[0])-1:0] reqid_t; + + typedef logic [$clog2(L1NumSet)-1:0] tcdm_bank_addr_t; + + typedef struct packed { + logic [CoreIDWidth-1:0] core_id; + logic is_core; + reqid_t req_id; + } tcdm_user_t; + + // The metadata type used to restore the information from req to rsp + typedef struct packed { + tcdm_user_t user; + logic write; + } tcdm_meta_t; + + + // Regbus peripherals. + `AXI_TYPEDEF_ALL(axi_mst, addr_t, id_mst_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_ALL(axi_slv, addr_t, id_slv_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_ALL(axi_mst_dma, addr_t, id_dma_mst_t, data_dma_t, strb_dma_t, user_dma_t) + `AXI_TYPEDEF_ALL(axi_slv_dma, addr_t, id_dma_slv_t, data_dma_t, strb_dma_t, user_dma_t) + `AXI_TYPEDEF_ALL(axi_dcache, addr_t, id_dcache_mst_t, data_dma_t, strb_dma_t, user_dma_t) + + `REQRSP_TYPEDEF_ALL(reqrsp, addr_t, data_t, strb_t) + + `MEM_TYPEDEF_ALL(mem, tcdm_mem_addr_t, data_t, strb_t, tcdm_user_t) + `MEM_TYPEDEF_ALL(mem_dma, tcdm_mem_addr_t, data_dma_t, strb_dma_t, logic) + + `TCDM_TYPEDEF_ALL(tcdm, tcdm_addr_t, data_t, strb_t, tcdm_user_t) + `TCDM_TYPEDEF_ALL(tcdm_dma, tcdm_addr_t, data_dma_t, strb_dma_t, logic) + `TCDM_TYPEDEF_ALL(spm, spm_addr_t, data_t, strb_t, tcdm_user_t) + + `REG_BUS_TYPEDEF_ALL(reg, addr_t, data_t, strb_t) + `REG_BUS_TYPEDEF_ALL(reg_dma, addr_t, data_dma_t, strb_dma_t) + + // Event counter increments for the TCDM. + typedef struct packed { + /// Number requests going in + logic [$clog2(NrTCDMPortsCores):0] inc_accessed; + /// Number of requests stalled due to congestion + logic [$clog2(NrTCDMPortsCores):0] inc_congested; + } tcdm_events_t; + + // Event counter increments for DMA. + typedef struct packed { + logic aw_stall, ar_stall, r_stall, w_stall, + buf_w_stall, buf_r_stall; + logic aw_valid, aw_ready, aw_done, aw_bw; + logic ar_valid, ar_ready, ar_done, ar_bw; + logic r_valid, r_ready, r_done, r_bw; + logic w_valid, w_ready, w_done, w_bw; + logic b_valid, b_ready, b_done; + logic dma_busy; + axi_pkg::len_t aw_len, ar_len; + axi_pkg::size_t aw_size, ar_size; + logic [$clog2(AxiDataWidth/8):0] num_bytes_written; + } dma_events_t; + + typedef struct packed { + int unsigned idx; + addr_t start_addr; + addr_t end_addr; + } xbar_rule_t; + + typedef struct packed { + acc_addr_e addr; + logic [5:0] id; + logic [31:0] data_op; + data_t data_arga; + data_t data_argb; + addr_t data_argc; + } acc_issue_req_t; + + typedef struct packed { + logic accept; + logic writeback; + logic loadstore; + logic exception; + logic isfloat; + } acc_issue_rsp_t; + + typedef struct packed { + logic [5:0] id; + logic error; + data_t data; + } acc_rsp_t; + + `SNITCH_VM_TYPEDEF(AxiAddrWidth) + + typedef struct packed { + // Slow domain. + logic flush_i_valid; + addr_t inst_addr; + logic inst_cacheable; + logic inst_valid; + // Fast domain. + acc_issue_req_t acc_req; + logic acc_qvalid; + logic acc_pready; + // Slow domain. + logic [1:0] ptw_valid; + va_t [1:0] ptw_va; + pa_t [1:0] ptw_ppn; + } hive_req_t; + + typedef struct packed { + // Slow domain. + logic flush_i_ready; + logic [31:0] inst_data; + logic inst_ready; + logic inst_error; + // Fast domain. + logic acc_qready; + acc_rsp_t acc_resp; + logic acc_pvalid; + // Slow domain. + logic [1:0] ptw_ready; + l0_pte_t [1:0] ptw_pte; + logic [1:0] ptw_is_4mega; + } hive_rsp_t; + + // ----------- + // Assignments + // ----------- + // Calculate start and end address of TCDM based on the `cluster_base_addr_i`. + addr_t tcdm_start_address, tcdm_end_address; + assign tcdm_start_address = (cluster_base_addr_i & TCDMMask); + assign tcdm_end_address = (tcdm_start_address + TCDMSize) & TCDMMask; + + addr_t cluster_periph_start_address, cluster_periph_end_address; + assign cluster_periph_start_address = tcdm_end_address; + assign cluster_periph_end_address = tcdm_end_address + ClusterPeriphSize * 1024; + + localparam int unsigned ClusterReserve = 4096; // 4 MiB + localparam int unsigned ClusterL2Size = 8192; // 8 MiB + addr_t cluster_l2_start_address, cluster_l2_end_address; + assign cluster_l2_start_address = L2Addr; + assign cluster_l2_end_address = L2Addr + L2Size; + + // ---------------- + // Wire Definitions + // ---------------- + // 1. AXI + axi_slv_req_t [NrNarrowSlaves-1:0] narrow_axi_slv_req; + axi_slv_resp_t [NrNarrowSlaves-1:0] narrow_axi_slv_rsp; + axi_mst_req_t [NrNarrowMasters-1:0] narrow_axi_mst_req; + axi_mst_resp_t [NrNarrowMasters-1:0] narrow_axi_mst_rsp; + + // DMA AXI buses + axi_mst_dma_req_t [NrWideMasters-1:0] wide_axi_mst_req; + axi_mst_dma_resp_t [NrWideMasters-1:0] wide_axi_mst_rsp; + axi_slv_dma_req_t [NrWideSlaves-1 :0] wide_axi_slv_req; + axi_slv_dma_resp_t [NrWideSlaves-1 :0] wide_axi_slv_rsp; + + // AXI req/rsp from/to cache controllers + axi_dcache_req_t [NumL1CacheCtrl-1:0] dcache_axi_req; + axi_dcache_resp_t [NumL1CacheCtrl-1:0] dcache_axi_rsp; + + // 2. Memory Subsystem (Banks) + mem_req_t [NrSuperBanks-1:0][BanksPerSuperBank-1:0] ic_req; + mem_rsp_t [NrSuperBanks-1:0][BanksPerSuperBank-1:0] ic_rsp; + + mem_dma_req_t [NrSuperBanks-1:0] sb_dma_req; + mem_dma_rsp_t [NrSuperBanks-1:0] sb_dma_rsp; + + // 3. Memory Subsystem (Interconnect) + tcdm_dma_req_t ext_dma_req; + tcdm_dma_rsp_t ext_dma_rsp; + + // AXI Ports into TCDM (from SoC). + spm_req_t axi_soc_req; + spm_rsp_t axi_soc_rsp; + + tcdm_req_t [NrTCDMPortsCores-1:0] tcdm_req; + tcdm_rsp_t [NrTCDMPortsCores-1:0] tcdm_rsp; + + core_events_t [NrCores-1:0] core_events; + tcdm_events_t tcdm_events; + dma_events_t dma_events; + snitch_icache_pkg::icache_events_t [NrCores-1:0] icache_events; + + // 4. Memory Subsystem (Core side). + reqrsp_req_t [NrCores-1:0] core_req, filtered_core_req; + reqrsp_rsp_t [NrCores-1:0] core_rsp, filtered_core_rsp; + + // 5. Peripheral Subsystem + reg_req_t reg_req; + reg_rsp_t reg_rsp; + + // 6. BootROM + reg_dma_req_t bootrom_reg_req; + reg_dma_rsp_t bootrom_reg_rsp; + + // 7. Misc. Wires. + logic icache_prefetch_enable; + logic [NrCores-1:0] cl_interrupt; + + // 8. L1 D$ + spm_req_t [NrTCDMPortsCores-1:0] spm_req; + spm_rsp_t [NrTCDMPortsCores-1:0] spm_rsp; + + tcdm_req_t [NrTCDMPortsCores-1:0] unmerge_req, strb_hdl_req; + tcdm_rsp_t [NrTCDMPortsCores-1:0] unmerge_rsp, strb_hdl_rsp; + + tcdm_req_t [NrTCDMPortsPerCore-1:0][NumL1CacheCtrl-1:0] cache_req, cache_xbar_req; + tcdm_rsp_t [NrTCDMPortsPerCore-1:0][NumL1CacheCtrl-1:0] cache_rsp, cache_xbar_rsp; + + logic [NumL1CacheCtrl-1:0][NrTCDMPortsPerCore-1:0] cache_req_valid; + logic [NumL1CacheCtrl-1:0][NrTCDMPortsPerCore-1:0] cache_req_ready; + tcdm_addr_t [NumL1CacheCtrl-1:0][NrTCDMPortsPerCore-1:0] cache_req_addr; + tcdm_user_t [NumL1CacheCtrl-1:0][NrTCDMPortsPerCore-1:0] cache_req_meta; + logic [NumL1CacheCtrl-1:0][NrTCDMPortsPerCore-1:0] cache_req_write; + data_t [NumL1CacheCtrl-1:0][NrTCDMPortsPerCore-1:0] cache_req_data; + + logic [NumL1CacheCtrl-1:0][NrTCDMPortsPerCore-1:0] cache_rsp_valid; + logic [NumL1CacheCtrl-1:0][NrTCDMPortsPerCore-1:0] cache_rsp_ready; + logic [NumL1CacheCtrl-1:0][NrTCDMPortsPerCore-1:0] cache_rsp_write; + data_t [NumL1CacheCtrl-1:0][NrTCDMPortsPerCore-1:0] cache_rsp_data; + tcdm_user_t [NumL1CacheCtrl-1:0][NrTCDMPortsPerCore-1:0] cache_rsp_meta; + + logic [NumL1CacheCtrl-1:0][NumTagBankPerCtrl-1:0] l1_tag_bank_req; + logic [NumL1CacheCtrl-1:0][NumTagBankPerCtrl-1:0] l1_tag_bank_we; + tcdm_bank_addr_t [NumL1CacheCtrl-1:0][NumTagBankPerCtrl-1:0] l1_tag_bank_addr; + tag_data_t [NumL1CacheCtrl-1:0][NumTagBankPerCtrl-1:0] l1_tag_bank_wdata; + logic [NumL1CacheCtrl-1:0][NumTagBankPerCtrl-1:0] l1_tag_bank_be; + tag_data_t [NumL1CacheCtrl-1:0][NumTagBankPerCtrl-1:0] l1_tag_bank_rdata; + + logic [NumL1CacheCtrl-1:0][NumDataBankPerCtrl-1:0] l1_data_bank_req; + logic [NumL1CacheCtrl-1:0][NumDataBankPerCtrl-1:0] l1_data_bank_we; + tcdm_bank_addr_t [NumL1CacheCtrl-1:0][NumDataBankPerCtrl-1:0] l1_data_bank_addr; + data_t [NumL1CacheCtrl-1:0][NumDataBankPerCtrl-1:0] l1_data_bank_wdata; + logic [NumL1CacheCtrl-1:0][NumDataBankPerCtrl-1:0] l1_data_bank_be; + data_t [NumL1CacheCtrl-1:0][NumDataBankPerCtrl-1:0] l1_data_bank_rdata; + logic [NumL1CacheCtrl-1:0][NumDataBankPerCtrl-1:0] l1_data_bank_gnt; + + logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_req; + logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_we; + tcdm_bank_addr_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_addr; + data_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_wdata; + strb_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_be; + data_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_rdata; + logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_gnt; + + // Used to bridge `l1_data_bank*` and `l1_cache_wp*` signals + logic [L1NumDataBank-1:0] l1_data_bank_req_flat; + logic [L1NumDataBank-1:0] l1_data_bank_we_flat; + tcdm_bank_addr_t [L1NumDataBank-1:0] l1_data_bank_addr_flat; + data_t [L1NumDataBank-1:0] l1_data_bank_wdata_flat; + logic [L1NumDataBank-1:0] l1_data_bank_be_flat; + data_t [L1NumDataBank-1:0] l1_data_bank_rdata_flat; + logic [L1NumDataBank-1:0] l1_data_bank_gnt_flat; + + // Requests/Response to/from outside DRAM from cache controllers + axi_mst_dma_req_t [NumL1CacheCtrl-1:0] wide_dcache_mst_req; + axi_mst_dma_resp_t [NumL1CacheCtrl-1:0] wide_dcache_mst_rsp; + + logic l1d_insn_valid; + logic [NumL1CacheCtrl-1:0] l1d_insn_ready; + logic [1:0] l1d_insn; + tcdm_bank_addr_t cfg_spm_size; + tcdm_addr_t spm_size; + logic l1d_busy; + + // High if a port access an illegal SPM region (mapped to cache) + logic [NrTCDMPortsCores-1:0] spm_error; + + + // 9. SRAM Configuration + // impl_in_t [L1NumWrapper-1:0][L1BankPerWP-1:0] impl_l1d_data; + // impl_in_t [L1NumTagBank-1:0] impl_l1d_tag; + // impl_in_t [1:0] impl_l1d_fifo; + + // impl_in_t [ICacheSets-1:0] impl_l1i_data; + // impl_in_t [ICacheSets-1:0] impl_l1i_tag; + + // assign {impl_l1d_data, impl_l1d_tag, impl_l1d_fifo, impl_l1i_data, impl_l1i_tag} = impl_i; + assign error_o = |spm_error; + + + // ------------- + // DMA Subsystem + // ------------- + // Optionally decouple the external wide AXI master port. + axi_cut #( + .Bypass (!RegisterExt ), + .aw_chan_t (axi_slv_dma_aw_chan_t), + .w_chan_t (axi_slv_dma_w_chan_t ), + .b_chan_t (axi_slv_dma_b_chan_t ), + .ar_chan_t (axi_slv_dma_ar_chan_t), + .r_chan_t (axi_slv_dma_r_chan_t ), + .axi_req_t (axi_slv_dma_req_t ), + .axi_resp_t (axi_slv_dma_resp_t ) + ) i_cut_ext_wide_out ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (wide_axi_slv_req[SoCDMAOut]), + .slv_resp_o (wide_axi_slv_rsp[SoCDMAOut]), + .mst_req_o (axi_out_req_o ), + .mst_resp_i (axi_out_resp_i ) + ); + + axi_cut #( + .Bypass (!RegisterExt ), + .aw_chan_t (axi_slv_dma_aw_chan_t), + .w_chan_t (axi_slv_dma_w_chan_t ), + .b_chan_t (axi_slv_dma_b_chan_t ), + .ar_chan_t (axi_slv_dma_ar_chan_t), + .r_chan_t (axi_slv_dma_r_chan_t ), + .axi_req_t (axi_slv_dma_req_t ), + .axi_resp_t (axi_slv_dma_resp_t ) + ) i_cut_ext_l2_wide_out ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (wide_axi_slv_req[L2Mem]), + .slv_resp_o (wide_axi_slv_rsp[L2Mem]), + .mst_req_o (axi_out_l2_req_o ), + .mst_resp_i (axi_out_l2_resp_i ) + ); + + axi_cut #( + .Bypass (!RegisterExt ), + .aw_chan_t (axi_mst_aw_chan_t), + .w_chan_t (axi_mst_w_chan_t ), + .b_chan_t (axi_mst_b_chan_t ), + .ar_chan_t (axi_mst_ar_chan_t), + .r_chan_t (axi_mst_r_chan_t ), + .axi_req_t (axi_mst_req_t ), + .axi_resp_t (axi_mst_resp_t ) + ) i_cut_ext_narrow_in ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (axi_in_req_i ), + .slv_resp_o (axi_in_resp_o ), + .mst_req_o (narrow_axi_mst_req[SoCDMAIn]), + .mst_resp_i (narrow_axi_mst_rsp[SoCDMAIn]) + ); + + logic [DmaXbarCfg.NoSlvPorts-1:0][$clog2(DmaXbarCfg.NoMstPorts)-1:0] dma_xbar_default_port; + xbar_rule_t [DmaXbarCfg.NoAddrRules-1:0] dma_xbar_rule; + + assign dma_xbar_default_port = '{default: SoCDMAOut}; + assign dma_xbar_rule = '{ + '{ + idx : TCDMDMA, + start_addr: tcdm_start_address, + end_addr : tcdm_end_address + }, + '{ + idx : BootROM, + start_addr: BootAddr, + end_addr : BootAddr + 'h1000 + }, + '{ + idx : L2Mem, + start_addr: cluster_l2_start_address, + end_addr : cluster_l2_end_address + } + }; + + localparam bit [DmaXbarCfg.NoSlvPorts-1:0] DMAEnableDefaultMstPort = '1; + axi_xbar #( + .Cfg (DmaXbarCfg ), + .ATOPs (0 ), + .slv_aw_chan_t (axi_mst_dma_aw_chan_t), + .mst_aw_chan_t (axi_slv_dma_aw_chan_t), + .w_chan_t (axi_mst_dma_w_chan_t ), + .slv_b_chan_t (axi_mst_dma_b_chan_t ), + .mst_b_chan_t (axi_slv_dma_b_chan_t ), + .slv_ar_chan_t (axi_mst_dma_ar_chan_t), + .mst_ar_chan_t (axi_slv_dma_ar_chan_t), + .slv_r_chan_t (axi_mst_dma_r_chan_t ), + .mst_r_chan_t (axi_slv_dma_r_chan_t ), + .slv_req_t (axi_mst_dma_req_t ), + .slv_resp_t (axi_mst_dma_resp_t ), + .mst_req_t (axi_slv_dma_req_t ), + .mst_resp_t (axi_slv_dma_resp_t ), + .rule_t (xbar_rule_t ) + ) i_axi_dma_xbar ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .test_i (1'b0 ), + .slv_ports_req_i (wide_axi_mst_req ), + .slv_ports_resp_o (wide_axi_mst_rsp ), + .mst_ports_req_o (wide_axi_slv_req ), + .mst_ports_resp_i (wide_axi_slv_rsp ), + .addr_map_i (dma_xbar_rule ), + .en_default_mst_port_i (DMAEnableDefaultMstPort), + .default_mst_port_i (dma_xbar_default_port ) + ); + + addr_t ext_dma_req_q_addr_nontrunc; + + axi_to_mem_interleaved #( + .axi_req_t (axi_slv_dma_req_t ), + .axi_resp_t (axi_slv_dma_resp_t ), + .AddrWidth (AxiAddrWidth ), + .DataWidth (AxiDataWidth ), + .IdWidth (WideIdWidthOut ), + .NumBanks (1 ), + .BufDepth (MemoryMacroLatency + 1) + ) i_axi_to_mem_dma ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .busy_o (/* Unused */ ), + .test_i (1'b0 ), + .axi_req_i (wide_axi_slv_req[TCDMDMA] ), + .axi_resp_o (wide_axi_slv_rsp[TCDMDMA] ), + .mem_req_o (ext_dma_req.q_valid ), + .mem_gnt_i (ext_dma_rsp.q_ready ), + .mem_addr_o (ext_dma_req_q_addr_nontrunc ), + .mem_wdata_o (ext_dma_req.q.data ), + .mem_strb_o (ext_dma_req.q.strb ), + .mem_atop_o (/* The DMA does not support atomics */), + .mem_we_o (ext_dma_req.q.write ), + .mem_rvalid_i (ext_dma_rsp.p_valid ), + .mem_rdata_i (ext_dma_rsp.p.data ) + ); + + assign ext_dma_req.q.addr = tcdm_addr_t'(ext_dma_req_q_addr_nontrunc); + assign ext_dma_req.q.amo = reqrsp_pkg::AMONone; + assign ext_dma_req.q.user = '0; + + spatz_tcdm_interconnect #( + .NumInp (1 ), + .NumOut (NrSuperBanks ), + .tcdm_req_t (tcdm_dma_req_t ), + .tcdm_rsp_t (tcdm_dma_rsp_t ), + .mem_req_t (mem_dma_req_t ), + .mem_rsp_t (mem_dma_rsp_t ), + .user_t (logic ), + .MemAddrWidth (TCDMMemAddrWidth ), + .DataWidth (AxiDataWidth ), + .MemoryResponseLatency (MemoryMacroLatency) + ) i_dma_interconnect ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .req_i (ext_dma_req), + .rsp_o (ext_dma_rsp), + .mem_req_o (sb_dma_req ), + .mem_rsp_i (sb_dma_rsp ) + ); + + // ---------------- + // Memory Subsystem + // ---------------- + for (genvar i = 0; i < NrSuperBanks; i++) begin : gen_tcdm_super_bank + + mem_req_t [BanksPerSuperBank-1:0] amo_req; + mem_rsp_t [BanksPerSuperBank-1:0] amo_rsp; + + logic [BanksPerSuperBank-1:0] mem_cs, mem_wen; + tcdm_mem_addr_t [BanksPerSuperBank-1:0] mem_add; + tcdm_mem_addr_t [BanksPerSuperBank-1:0] mem_add_max; + strb_t [BanksPerSuperBank-1:0] mem_be; + data_t [BanksPerSuperBank-1:0] mem_rdata, mem_wdata; + tcdm_meta_t [BanksPerSuperBank-1:0] bank_req_meta, mem_req_meta, bank_rsp_meta; + + mem_wide_narrow_mux #( + .NarrowDataWidth (NarrowDataWidth), + .WideDataWidth (AxiDataWidth ), + .mem_narrow_req_t (mem_req_t ), + .mem_narrow_rsp_t (mem_rsp_t ), + .mem_wide_req_t (mem_dma_req_t ), + .mem_wide_rsp_t (mem_dma_rsp_t ) + ) i_tcdm_mux ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .in_narrow_req_i (ic_req [i] ), + .in_narrow_rsp_o (ic_rsp [i] ), + .in_wide_req_i (sb_dma_req [i] ), + .in_wide_rsp_o (sb_dma_rsp [i] ), + .out_req_o (amo_req ), + .out_rsp_i (amo_rsp ), + .sel_wide_i (sb_dma_req[i].q_valid) + ); + + // generate banks of the superbank + for (genvar j = 0; j < BanksPerSuperBank; j++) begin : gen_tcdm_bank + tc_sram_impl #( + .NumWords (TCDMDepth), + .DataWidth (DataWidth), + .ByteWidth (8 ), + .NumPorts (1 ), + .Latency (1 ) + ) i_spm_mem ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .impl_i ('0 ), + .impl_o (/* Unused */), + .req_i (mem_cs[j] ), + .we_i (mem_wen[j] ), + .addr_i (mem_add[j] ), + .wdata_i (mem_wdata[j] ), + .be_i (mem_be[j] ), + .rdata_o (mem_rdata[j] ) + ); + + data_t amo_rdata_local; + + // TODO(zarubaf): Share atomic units between mutltiple cuts + snitch_amo_shim #( + .AddrMemWidth ( TCDMMemAddrWidth ), + .DataWidth ( DataWidth ), + .CoreIDWidth ( CoreIDWidth ) + ) i_amo_shim ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .valid_i (amo_req[j].q_valid ), + .ready_o (amo_rsp[j].q_ready ), + .addr_i (amo_req[j].q.addr ), + .write_i (amo_req[j].q.write ), + .wdata_i (amo_req[j].q.data ), + .wstrb_i (amo_req[j].q.strb ), + .core_id_i (amo_req[j].q.user.core_id ), + .is_core_i (amo_req[j].q.user.is_core ), + .rdata_o (amo_rdata_local ), + .amo_i (amo_req[j].q.amo ), + .mem_req_o (mem_cs[j] ), + .mem_add_o (mem_add[j] ), + .mem_wen_o (mem_wen[j] ), + .mem_wdata_o (mem_wdata[j] ), + .mem_be_o (mem_be[j] ), + .mem_rdata_i (mem_rdata[j] ), + .dma_access_i (sb_dma_req[i].q_valid ), + // TODO(zarubaf): Signal AMO conflict somewhere. Socregs? + .amo_conflict_o (/* Unused */ ) + ); + + // Insert a pipeline register at the output of each SRAM. + shift_reg #( + .dtype(data_t ), + .Depth(int'(RegisterTCDMCuts)) + ) i_sram_pipe ( + .clk_i (clk_i ), + .rst_ni(rst_ni ), + .d_i (amo_rdata_local ), + .d_o (amo_rsp[j].p.data) + ); + + // the meta data information + assign bank_req_meta[j] = '{ + user: amo_req[j].q.user, + write: amo_req[j].q.write, + default: '0 + }; + assign amo_rsp[j].p.user = bank_rsp_meta[j].user; + assign amo_rsp[j].p.write = bank_rsp_meta[j].write; + + shift_reg #( + .dtype(tcdm_meta_t ), + .Depth(int'(RegisterTCDMCuts)) + ) i_req_meta_pipe ( + .clk_i (clk_i ), + .rst_ni(rst_ni ), + .d_i (bank_req_meta[j] ), + .d_o (mem_req_meta[j] ) + ); + shift_reg #( + .dtype(tcdm_meta_t ), + .Depth(int'(RegisterTCDMCuts)) + ) i_rsp_meta_pipe ( + .clk_i (clk_i ), + .rst_ni(rst_ni ), + .d_i (mem_req_meta[j] ), + .d_o (bank_rsp_meta[j] ) + ); + end + end + + logic [NrTCDMPortsCores-1:0] unmerge_pready, strb_hdl_pready; + logic [NrTCDMPortsPerCore-1:0][NumL1CacheCtrl-1:0] cache_pready, cache_xbar_pready; + // Currently assume SPM is full 128 KiB + // assign spm_size = 128 * 1024; + // assign spm_size = cfg_spm_size * 1024; + + // split the requests for spm or cache from core side + spatz_addr_mapper #( + .NumIO (NrTCDMPortsCores ), + .AddrWidth (L1AddrWidth ), + .SPMAddrWidth (SPMAddrWidth ), + .DataWidth (DataWidth ), + .mem_req_t (tcdm_req_t ), + .mem_rsp_t (tcdm_rsp_t ), + .mem_rsp_chan_t (tcdm_rsp_chan_t ), + .spm_req_t (spm_req_t ), + .spm_rsp_t (spm_rsp_t ) + ) i_tcdm_mapper ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + // Input + .mem_req_i (tcdm_req ), + .mem_rsp_o (tcdm_rsp ), + .error_o (spm_error ), + // Address + .tcdm_start_address_i (tcdm_start_address[L1AddrWidth-1:0] ), + .tcdm_end_address_i (tcdm_end_address[L1AddrWidth-1:0] ), + .spm_size_i (tcdm_end_address[L1AddrWidth-1:0] - tcdm_start_address[L1AddrWidth-1:0]), + .flush_i (l1d_busy ), + // Output + .spm_req_o (spm_req ), + .spm_rsp_i (spm_rsp ), + .cache_req_o (unmerge_req ), + .cache_pready_o (unmerge_pready ), + .cache_rsp_i (unmerge_rsp ) + ); + + + // spatz_strbreq_merge_tree #( + // .NumIO (NrTCDMPortsCores ), + // .NumOutstandingMem (NumSpatzOutstandingLoads[0] ), + // .MergeNum (NrTCDMPortsCores - NrCores ), + // .DataWidth (DataWidth ), + // .mem_req_t (tcdm_req_t ), + // .mem_rsp_t (tcdm_rsp_t ), + // .req_id_t (reqid_t ), + // .tcdm_user_t (tcdm_user_t ) + // ) i_strbreq_merge_tree ( + // .clk_i (clk_i), + // .rst_ni (rst_ni), + // .unmerge_req_i (unmerge_req ), + // .unmerge_pready_i(unmerge_pready ), + // .merge_rsp_i (strb_hdl_rsp ), + // .merge_req_o (strb_hdl_req ), + // .merge_pready_o (strb_hdl_pready ), + // .unmerge_rsp_o (unmerge_rsp ) + // ); + + + // TODO: Should be NrCore instead of CacheBank here + for (genvar j = 0; j < NrTCDMPortsPerCore; j++) begin: gen_strb_hdlr + for (genvar cb = 0; cb < NumL1CacheCtrl; cb++) begin + // spatz_strbreq_handler #( + // .DataWidth (DataWidth ), + // .mem_req_t (tcdm_req_t ), + // .mem_rsp_t (tcdm_rsp_t ), + // .reqrsp_user_t (tcdm_user_t ) + // ) i_strbreq_handler ( + // .clk_i (clk_i ), + // .rst_ni (rst_ni ), + // .strb_req_i (strb_hdl_req [cb*NrTCDMPortsPerCore+j]), + // .strb_rsp_ready_i (strb_hdl_pready[cb*NrTCDMPortsPerCore+j]), + // .strb_rsp_i (cache_rsp [j][cb] ), + // .strb_req_o (cache_req [j][cb] ), + // .strb_rsp_ready_o (cache_pready [j][cb] ), + // .strb_rsp_o (strb_hdl_rsp [cb*NrTCDMPortsPerCore+j]) + // ); + // end + assign cache_req [j][cb] = unmerge_req [cb*NrTCDMPortsPerCore+j]; + assign cache_pready[j][cb] = unmerge_pready[cb*NrTCDMPortsPerCore+j]; + assign unmerge_rsp [cb*NrTCDMPortsPerCore+j] = cache_rsp [j][cb]; + end + end + + // Used to determine the mapping policy between different cache banks. + // Set through CSR + logic [$clog2(32)-1:0] dynamic_offset; + + /// Wire requests after strb handling to the cache controller + for (genvar j = 0; j < NrTCDMPortsPerCore; j++) begin : gen_cache_xbar + tcdm_cache_interco #( + .NumCore (NrCores ), + .NumCache (NumL1CacheCtrl ), + .tcdm_req_t (tcdm_req_t ), + .tcdm_rsp_t (tcdm_rsp_t ), + .tcdm_req_chan_t (tcdm_req_chan_t ), + .tcdm_rsp_chan_t (tcdm_rsp_chan_t ) + ) i_cache_xbar ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .dynamic_offset_i (dynamic_offset ), + .core_req_i (cache_req[j] ), + .core_rsp_ready_i (cache_pready[j] ), + .core_rsp_o (cache_rsp[j] ), + .mem_req_o (cache_xbar_req[j] ), + .mem_rsp_ready_o (cache_xbar_pready[j] ), + .mem_rsp_i (cache_xbar_rsp[j] ) + ); + end + + // Re-organize the wire for easier connection + for (genvar cb = 0; cb < NumL1CacheCtrl; cb++) begin + for (genvar j = 0; j < NrTCDMPortsPerCore; j++) begin + assign cache_req_valid[cb][j] = cache_xbar_req[j][cb].q_valid; + assign cache_req_addr [cb][j] = cache_xbar_req[j][cb].q.addr; + assign cache_req_meta [cb][j] = cache_xbar_req[j][cb].q.user; + assign cache_req_write[cb][j] = cache_xbar_req[j][cb].q.write; + assign cache_req_data [cb][j] = cache_xbar_req[j][cb].q.data; + + // assign cache_rsp_ready[cb][j] = 1'b1; + assign cache_rsp_ready[cb][j] = cache_xbar_pready[j][cb]; + + assign cache_xbar_rsp[j][cb].p_valid = cache_rsp_valid[cb][j]; + assign cache_xbar_rsp[j][cb].q_ready = cache_req_ready[cb][j]; + assign cache_xbar_rsp[j][cb].p.data = cache_rsp_data [cb][j]; + assign cache_xbar_rsp[j][cb].p.user = cache_rsp_meta [cb][j]; + + assign cache_xbar_rsp[j][cb].p.write = cache_rsp_write[cb][j]; + end + end + + // TODO: remove + tcdm_bank_addr_t num_spm_lines; + assign num_spm_lines = cfg_spm_size * (DepthPerBank / L1Size); + + for (genvar cb = 0; cb < NumL1CacheCtrl; cb++) begin: gen_l1_cache_ctrl + flamingo_spatz_cache_ctrl #( + // Core + .NumPorts (NrTCDMPortsPerCore ), + .CoalExtFactor (L1CoalFactor ), + .AddrWidth (L1AddrWidth ), + .WordWidth (DataWidth ), + // Cache + .NumCacheEntry (L1NumEntryPerCtrl ), + .CacheLineWidth (L1LineWidth ), + .SetAssociativity (L1AssoPerCtrl ), + .BankFactor (L1BankFactor ), + // Type + .core_meta_t (tcdm_user_t ), + .impl_in_t (impl_in_t ), + .axi_req_t (axi_dcache_req_t ), + .axi_resp_t (axi_dcache_resp_t ) + ) i_l1_controller ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .impl_i ('0 ), + // Sync Control + .cache_sync_valid_i (l1d_insn_valid ), + .cache_sync_ready_o (l1d_insn_ready[cb] ), + .cache_sync_insn_i (l1d_insn ), + // SPM Size + // The calculation of spm region in cache is different + // than other modules (needs to times 2) + // Currently assume full cache + .bank_depth_for_SPM_i ('0 ), + // Request + .core_req_valid_i (cache_req_valid[cb] ), + .core_req_ready_o (cache_req_ready[cb] ), + .core_req_addr_i (cache_req_addr[cb] ), + .core_req_meta_i (cache_req_meta[cb] ), + .core_req_write_i (cache_req_write[cb] ), + .core_req_wdata_i (cache_req_data[cb] ), + // Response + .core_resp_valid_o (cache_rsp_valid[cb] ), + .core_resp_ready_i (cache_rsp_ready[cb] ), + .core_resp_write_o (cache_rsp_write[cb] ), + .core_resp_data_o (cache_rsp_data[cb] ), + .core_resp_meta_o (cache_rsp_meta[cb] ), + // AXI refill + .axi_req_o (dcache_axi_req[cb] ), + .axi_resp_i (dcache_axi_rsp[cb] ), + // Tag Banks + .tcdm_tag_bank_req_o (l1_tag_bank_req[cb] ), + .tcdm_tag_bank_we_o (l1_tag_bank_we[cb] ), + .tcdm_tag_bank_addr_o (l1_tag_bank_addr[cb] ), + .tcdm_tag_bank_wdata_o (l1_tag_bank_wdata[cb] ), + .tcdm_tag_bank_be_o (l1_tag_bank_be[cb] ), + .tcdm_tag_bank_rdata_i (l1_tag_bank_rdata[cb] ), + // Data Banks + .tcdm_data_bank_req_o (l1_data_bank_req[cb] ), + .tcdm_data_bank_we_o (l1_data_bank_we[cb] ), + .tcdm_data_bank_addr_o (l1_data_bank_addr[cb] ), + .tcdm_data_bank_wdata_o(l1_data_bank_wdata[cb] ), + .tcdm_data_bank_be_o (l1_data_bank_be[cb] ), + .tcdm_data_bank_rdata_i(l1_data_bank_rdata[cb] ), + .tcdm_data_bank_gnt_i (l1_data_bank_gnt[cb] ) + ); + + for (genvar j = 0; j < NumTagBankPerCtrl; j++) begin + tc_sram_impl #( + .NumWords (L1CacheWayEntry/L1BankFactor), + .DataWidth ($bits(tag_data_t) ), + .ByteWidth ($bits(tag_data_t) ), + .NumPorts (1 ), + .Latency (1 ), + .SimInit ("zeros" ), + .impl_in_t (impl_in_t ) + ) i_meta_bank ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .impl_i ('0 ), + .impl_o (/* unsed */ ), + .req_i (l1_tag_bank_req [cb][j]), + .we_i (l1_tag_bank_we [cb][j]), + .addr_i (l1_tag_bank_addr [cb][j]), + .wdata_i(l1_tag_bank_wdata[cb][j]), + .be_i (l1_tag_bank_be [cb][j]), + .rdata_o(l1_tag_bank_rdata[cb][j]) + ); + end + + for (genvar j = 0; j < NumDataBankPerCtrl; j++) begin : gen_l1_data_banks + tc_sram_impl #( + .NumWords (L1CacheWayEntry/L1BankFactor), + .DataWidth (DataWidth), + .ByteWidth (DataWidth), + .NumPorts (1), + .Latency (1), + .SimInit ("zeros") + ) i_data_bank ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .impl_i ('0 ), + .impl_o (/* unsed */ ), + .req_i (l1_data_bank_req [cb][j]), + .we_i (l1_data_bank_we [cb][j]), + .addr_i (l1_data_bank_addr [cb][j]), + .wdata_i(l1_data_bank_wdata[cb][j]), + .be_i (l1_data_bank_be [cb][j]), + .rdata_o(l1_data_bank_rdata[cb][j]) + ); + + assign l1_data_bank_gnt[cb][j] = 1'b1; + end + end + + // Hong TODO: Now we multiplex axi requests from multiple cache controllers, + // the id width is prepended to the existing id value to tell which + // cache controller request is picked, later we can replace this if + // we have some more appealing mux policy. + axi_mux #( + .SlvAxiIDWidth ( WideIdWidthIn-$clog2(NumL1CacheCtrl) ), // ID width of the slave ports + .slv_aw_chan_t ( axi_dcache_aw_chan_t ), // AW Channel Type, slave ports + .mst_aw_chan_t ( axi_mst_dma_aw_chan_t ), // AW Channel Type, master port + .w_chan_t ( axi_mst_dma_w_chan_t ), // W Channel Type, all ports + .slv_b_chan_t ( axi_dcache_b_chan_t ), // B Channel Type, slave ports + .mst_b_chan_t ( axi_mst_dma_b_chan_t ), // B Channel Type, master port + .slv_ar_chan_t ( axi_dcache_ar_chan_t ), // AR Channel Type, slave ports + .mst_ar_chan_t ( axi_mst_dma_ar_chan_t ), // AR Channel Type, master port + .slv_r_chan_t ( axi_dcache_r_chan_t ), // R Channel Type, slave ports + .mst_r_chan_t ( axi_mst_dma_r_chan_t ), // R Channel Type, master port + .slv_req_t ( axi_dcache_req_t ), + .slv_resp_t ( axi_dcache_resp_t ), + .mst_req_t ( axi_mst_dma_req_t ), + .mst_resp_t ( axi_mst_dma_resp_t ), + .NoSlvPorts ( NumL1CacheCtrl ) // Number of Masters for the module + ) i_dcache_axi_mux ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_i ( 1'b0 ), // Test Mode enable + .slv_reqs_i ( dcache_axi_req ), + .slv_resps_o ( dcache_axi_rsp ), + .mst_req_o ( wide_axi_mst_req[DCache] ), + .mst_resp_i ( wide_axi_mst_rsp[DCache] ) + ); + + + spatz_tcdm_interconnect #( + .NumInp (NumTCDMIn ), + .NumOut (L1NumWrapper ), + .tcdm_req_t (spm_req_t ), + .tcdm_rsp_t (spm_rsp_t ), + .mem_req_t (mem_req_t ), + .mem_rsp_t (mem_rsp_t ), + .MemAddrWidth (TCDMMemAddrWidth ), + .DataWidth (DataWidth ), + .user_t (tcdm_user_t ), + .MemoryResponseLatency (1 + RegisterTCDMCuts) + ) i_tcdm_interconnect ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .req_i ({axi_soc_req, spm_req} ), + .rsp_o ({axi_soc_rsp, spm_rsp} ), + .mem_req_o (ic_req ), + .mem_rsp_i (ic_rsp ) + ); + + hive_req_t [NrCores-1:0] hive_req; + hive_rsp_t [NrCores-1:0] hive_rsp; + + for (genvar i = 0; i < NrCores; i++) begin : gen_core + localparam int unsigned TcdmPorts = get_tcdm_ports(i); + localparam int unsigned TcdmPortsOffs = get_tcdm_port_offs(i); + + axi_mst_dma_req_t axi_dma_req; + axi_mst_dma_resp_t axi_dma_res; + interrupts_t irq; + dma_events_t dma_core_events; + + sync #(.STAGES (2)) + i_sync_debug (.clk_i, .rst_ni, .serial_i (debug_req_i[i]), .serial_o (irq.debug)); + sync #(.STAGES (2)) + i_sync_meip (.clk_i, .rst_ni, .serial_i (meip_i[i]), .serial_o (irq.meip)); + sync #(.STAGES (2)) + i_sync_mtip (.clk_i, .rst_ni, .serial_i (mtip_i[i]), .serial_o (irq.mtip)); + sync #(.STAGES (2)) + i_sync_msip (.clk_i, .rst_ni, .serial_i (msip_i[i]), .serial_o (irq.msip)); + assign irq.mcip = cl_interrupt[i]; + + tcdm_req_t [TcdmPorts-1:0] tcdm_req_wo_user; + + logic [31:0] hart_id; + assign hart_id = hart_base_id_i + i; + + spatz_cc #( + .BootAddr (BootAddr ), + .L2Addr (L2Addr ), + .L2Size (L2Size ), + .RVE (1'b0 ), + .RVF (RVF ), + .RVD (RVD ), + .RVV (RVV ), + .Xdma (Xdma[i] ), + .AddrWidth (AxiAddrWidth ), + .DataWidth (NarrowDataWidth ), + .UserWidth (AxiUserWidth ), + .DMADataWidth (AxiDataWidth ), + .DMAIdWidth (AxiIdWidthIn ), + .SnitchPMACfg (SnitchPMACfg ), + .DMAAxiReqFifoDepth (DMAAxiReqFifoDepth ), + .DMAReqFifoDepth (DMAReqFifoDepth ), + .dreq_t (reqrsp_req_t ), + .drsp_t (reqrsp_rsp_t ), + .tcdm_req_t (tcdm_req_t ), + .tcdm_req_chan_t (tcdm_req_chan_t ), + .tcdm_rsp_t (tcdm_rsp_t ), + .tcdm_rsp_chan_t (tcdm_rsp_chan_t ), + .axi_req_t (axi_mst_dma_req_t ), + .axi_ar_chan_t (axi_mst_dma_ar_chan_t ), + .axi_aw_chan_t (axi_mst_dma_aw_chan_t ), + .axi_rsp_t (axi_mst_dma_resp_t ), + .hive_req_t (hive_req_t ), + .hive_rsp_t (hive_rsp_t ), + .acc_issue_req_t (acc_issue_req_t ), + .acc_issue_rsp_t (acc_issue_rsp_t ), + .acc_rsp_t (acc_rsp_t ), + .dma_events_t (dma_events_t ), + .dma_perf_t (axi_dma_pkg::dma_perf_t ), + .XDivSqrt (1'b0 ), + .XF16 (1'b1 ), + .XF16ALT (1'b1 ), + .XF8 (1'b1 ), + .XF8ALT (1'b1 ), + .IsoCrossing (1'b0 ), + .NumIntOutstandingLoads (NumIntOutstandingLoads[i] ), + .NumIntOutstandingMem (NumIntOutstandingMem[i] ), + .NumSpatzOutstandingLoads(NumSpatzOutstandingLoads[i]), + .FPUImplementation (FPUImplementation[i] ), + .RegisterOffloadRsp (RegisterOffloadRsp ), + .RegisterCoreReq (RegisterCoreReq ), + .RegisterCoreRsp (RegisterCoreRsp ), + .NumSpatzFPUs (NumSpatzFPUs ), + .NumSpatzIPUs (NumSpatzIPUs ), + .TCDMAddrWidth (SPMAddrWidth ) + ) i_spatz_cc ( + .clk_i (clk_i ), + .clk_d2_i (clk_i ), + .rst_ni (rst_ni ), + .testmode_i (1'b0 ), + .hart_id_i (hart_id ), + .hive_req_o (hive_req[i] ), + .hive_rsp_i (hive_rsp[i] ), + .irq_i (irq ), + .data_req_o (core_req[i] ), + .data_rsp_i (core_rsp[i] ), + .tcdm_req_o (tcdm_req_wo_user ), + .tcdm_rsp_i (tcdm_rsp[TcdmPortsOffs +: TcdmPorts]), + .axi_dma_req_o (axi_dma_req ), + .axi_dma_res_i (axi_dma_res ), + .axi_dma_busy_o (/* Unused */ ), + .axi_dma_perf_o (/* Unused */ ), + .axi_dma_events_o (dma_core_events ), + .core_events_o (core_events[i] ), + .tcdm_addr_base_i (tcdm_start_address ) + ); + for (genvar j = 0; j < TcdmPorts; j++) begin : gen_tcdm_user + always_comb begin + tcdm_req[TcdmPortsOffs+j].q = tcdm_req_wo_user[j].q; + tcdm_req[TcdmPortsOffs+j].q.user.core_id = i[CoreIDWidth-1:0]; + tcdm_req[TcdmPortsOffs+j].q.user.is_core = 1; + tcdm_req[TcdmPortsOffs+j].q_valid = tcdm_req_wo_user[j].q_valid; + end + end + if (Xdma[i]) begin : gen_dma_connection + assign wide_axi_mst_req[SDMAMst] = axi_dma_req; + assign axi_dma_res = wide_axi_mst_rsp[SDMAMst]; + assign dma_events = dma_core_events; + end else begin + assign axi_dma_res = '0; + end + end + + // ---------------- + // Instruction Cache + // ---------------- + + addr_t [NrCores-1:0] inst_addr; + logic [NrCores-1:0] inst_cacheable; + logic [NrCores-1:0][31:0] inst_data; + logic [NrCores-1:0] inst_valid; + logic [NrCores-1:0] inst_ready; + logic [NrCores-1:0] inst_error; + logic [NrCores-1:0] flush_valid; + logic [NrCores-1:0] flush_ready; + + for (genvar i = 0; i < NrCores; i++) begin : gen_unpack_icache + assign inst_addr[i] = hive_req[i].inst_addr; + assign inst_cacheable[i] = hive_req[i].inst_cacheable; + assign inst_valid[i] = hive_req[i].inst_valid; + assign flush_valid[i] = hive_req[i].flush_i_valid; + assign hive_rsp[i] = '{ + inst_data : inst_data[i], + inst_ready : inst_ready[i], + inst_error : inst_error[i], + flush_i_ready: flush_ready[i], + default : '0 + }; + end + + snitch_icache #( + .NR_FETCH_PORTS ( NrCores ), + .L0_LINE_COUNT ( 8 ), + .LINE_WIDTH ( ICacheLineWidth ), + .LINE_COUNT ( ICacheLineCount ), + .SET_COUNT ( ICacheSets ), + .FETCH_AW ( AxiAddrWidth ), + .FETCH_DW ( 32 ), + .FILL_AW ( AxiAddrWidth ), + .FILL_DW ( AxiDataWidth ), + .EARLY_LATCH ( 0 ), + .L0_EARLY_TAG_WIDTH ( snitch_pkg::PAGE_SHIFT - $clog2(ICacheLineWidth/8) ), + .ISO_CROSSING ( 1'b0 ), + .axi_req_t ( axi_mst_dma_req_t ), + .axi_rsp_t ( axi_mst_dma_resp_t ), + .sram_cfg_data_t ( impl_in_t ), + .sram_cfg_tag_t ( impl_in_t ) + ) i_snitch_icache ( + .clk_i ( clk_i ), + .clk_d2_i ( clk_i ), + .rst_ni ( rst_ni ), + .enable_prefetching_i ( icache_prefetch_enable ), + .icache_events_o ( icache_events ), + .flush_valid_i ( flush_valid ), + .flush_ready_o ( flush_ready ), + .inst_addr_i ( inst_addr ), + .inst_cacheable_i ( inst_cacheable ), + .inst_data_o ( inst_data ), + .inst_valid_i ( inst_valid ), + .inst_ready_o ( inst_ready ), + .inst_error_o ( inst_error ), + .sram_cfg_tag_i ( '0 ), + .sram_cfg_data_i ( '0 ), + .axi_req_o ( wide_axi_mst_req[ICache] ), + .axi_rsp_i ( wide_axi_mst_rsp[ICache] ) + ); + + // -------- + // Cores SoC + // -------- + spatz_barrier #( + .AddrWidth (AxiAddrWidth ), + .NrPorts (NrCores ), + .dreq_t (reqrsp_req_t ), + .drsp_t (reqrsp_rsp_t ) + ) i_snitch_barrier ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .in_req_i (core_req ), + .in_rsp_o (core_rsp ), + .out_req_o (filtered_core_req ), + .out_rsp_i (filtered_core_rsp ), + .cluster_periph_start_address_i (cluster_periph_start_address) + ); + + reqrsp_req_t core_to_axi_req; + reqrsp_rsp_t core_to_axi_rsp; + user_t cluster_user; + // Atomic ID, needs to be unique ID of cluster + // cluster_id + HartIdOffset + 1 (because 0 is for non-atomic masters) + assign cluster_user = (hart_base_id_i / NrCores) + (hart_base_id_i % NrCores) + 1'b1; + + reqrsp_mux #( + .NrPorts (NrCores ), + .AddrWidth (AxiAddrWidth ), + .DataWidth (NarrowDataWidth ), + .req_t (reqrsp_req_t ), + .rsp_t (reqrsp_rsp_t ), + .RespDepth (2 ) + ) i_reqrsp_mux_core ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (filtered_core_req), + .slv_rsp_o (filtered_core_rsp), + .mst_req_o (core_to_axi_req ), + .mst_rsp_i (core_to_axi_rsp ), + .idx_o (/*unused*/ ) + ); + + reqrsp_to_axi #( + .DataWidth (NarrowDataWidth), + .UserWidth (NarrowUserWidth), + .reqrsp_req_t (reqrsp_req_t ), + .reqrsp_rsp_t (reqrsp_rsp_t ), + .axi_req_t (axi_mst_req_t ), + .axi_rsp_t (axi_mst_resp_t ) + ) i_reqrsp_to_axi_core ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .user_i (cluster_user ), + .reqrsp_req_i (core_to_axi_req ), + .reqrsp_rsp_o (core_to_axi_rsp ), + .axi_req_o (narrow_axi_mst_req[CoreReq]), + .axi_rsp_i (narrow_axi_mst_rsp[CoreReq]) + ); + + xbar_rule_t [NrNarrowRules-1:0] cluster_xbar_rules; + + assign cluster_xbar_rules = '{ + '{ + idx : TCDM, + start_addr: tcdm_start_address, + end_addr : tcdm_end_address + }, + '{ + idx : ClusterPeripherals, + start_addr: cluster_periph_start_address, + end_addr : cluster_periph_end_address + } + }; + + localparam bit [ClusterXbarCfg.NoSlvPorts-1:0] ClusterEnableDefaultMstPort = '1; + localparam logic [ClusterXbarCfg.NoSlvPorts-1:0][cf_math_pkg::idx_width(ClusterXbarCfg.NoMstPorts)-1:0] ClusterXbarDefaultPort = '{default: SoC}; + + axi_xbar #( + .Cfg (ClusterXbarCfg ), + .slv_aw_chan_t (axi_mst_aw_chan_t), + .mst_aw_chan_t (axi_slv_aw_chan_t), + .w_chan_t (axi_mst_w_chan_t ), + .slv_b_chan_t (axi_mst_b_chan_t ), + .mst_b_chan_t (axi_slv_b_chan_t ), + .slv_ar_chan_t (axi_mst_ar_chan_t), + .mst_ar_chan_t (axi_slv_ar_chan_t), + .slv_r_chan_t (axi_mst_r_chan_t ), + .mst_r_chan_t (axi_slv_r_chan_t ), + .slv_req_t (axi_mst_req_t ), + .slv_resp_t (axi_mst_resp_t ), + .mst_req_t (axi_slv_req_t ), + .mst_resp_t (axi_slv_resp_t ), + .rule_t (xbar_rule_t ) + ) i_cluster_xbar ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .test_i (1'b0 ), + .slv_ports_req_i (narrow_axi_mst_req ), + .slv_ports_resp_o (narrow_axi_mst_rsp ), + .mst_ports_req_o (narrow_axi_slv_req ), + .mst_ports_resp_i (narrow_axi_slv_rsp ), + .addr_map_i (cluster_xbar_rules ), + .en_default_mst_port_i (ClusterEnableDefaultMstPort), + .default_mst_port_i (ClusterXbarDefaultPort ) + ); + + // --------- + // Slaves + // --------- + // 1. TCDM + // Add an adapter that allows access from AXI to the TCDM. + axi_to_tcdm #( + .axi_req_t (axi_slv_req_t ), + .axi_rsp_t (axi_slv_resp_t ), + .tcdm_req_t (spm_req_t ), + .tcdm_rsp_t (spm_rsp_t ), + .AddrWidth (AxiAddrWidth ), + .DataWidth (NarrowDataWidth ), + .IdWidth (NarrowIdWidthOut ), + .BufDepth (MemoryMacroLatency + 1) + ) i_axi_to_tcdm ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .axi_req_i (narrow_axi_slv_req[TCDM]), + .axi_rsp_o (narrow_axi_slv_rsp[TCDM]), + .tcdm_req_o (axi_soc_req ), + .tcdm_rsp_i (axi_soc_rsp ) + ); + + // 2. Peripherals + axi_to_reg #( + .ADDR_WIDTH (AxiAddrWidth ), + .DATA_WIDTH (NarrowDataWidth ), + .AXI_MAX_WRITE_TXNS (1 ), + .AXI_MAX_READ_TXNS (1 ), + .DECOUPLE_W (0 ), + .ID_WIDTH (NarrowIdWidthOut ), + .USER_WIDTH (NarrowUserWidth ), + .axi_req_t (axi_slv_req_t ), + .axi_rsp_t (axi_slv_resp_t ), + .reg_req_t (reg_req_t ), + .reg_rsp_t (reg_rsp_t ) + ) i_axi_to_reg ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .testmode_i (1'b0 ), + .axi_req_i (narrow_axi_slv_req[ClusterPeripherals]), + .axi_rsp_o (narrow_axi_slv_rsp[ClusterPeripherals]), + .reg_req_o (reg_req ), + .reg_rsp_i (reg_rsp ) + ); + + spatz_cluster_peripheral #( + .AddrWidth (AxiAddrWidth ), + .SPMWidth ($clog2(L1NumSet)), + .reg_req_t (reg_req_t ), + .reg_rsp_t (reg_rsp_t ), + .tcdm_events_t (tcdm_events_t ), + .dma_events_t (dma_events_t ), + .NrCores (NrCores ) + ) i_snitch_cluster_peripheral ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .reg_req_i (reg_req ), + .reg_rsp_o (reg_rsp ), + /// The TCDM always starts at the cluster base. + .tcdm_start_address_i (tcdm_start_address ), + .tcdm_end_address_i (tcdm_end_address ), + .icache_prefetch_enable_o (icache_prefetch_enable), + .cl_clint_o (cl_interrupt ), + .cluster_hart_base_id_i (hart_base_id_i ), + .core_events_i (core_events ), + .tcdm_events_i (tcdm_events ), + .dma_events_i (dma_events ), + .icache_events_i (icache_events ), + .cluster_probe_o (cluster_probe_o ), + .dynamic_offset_o (dynamic_offset ), + .l1d_spm_size_o (cfg_spm_size ), + .l1d_insn_o (l1d_insn ), + .l1d_insn_valid_o (l1d_insn_valid ), + .l1d_insn_ready_i (&l1d_insn_ready ), + .l1d_busy_o (l1d_busy ) + ); + + // 3. BootROM + axi_to_reg #( + .ADDR_WIDTH (AxiAddrWidth ), + .DATA_WIDTH (AxiDataWidth ), + .AXI_MAX_WRITE_TXNS (1 ), + .AXI_MAX_READ_TXNS (1 ), + .DECOUPLE_W (0 ), + .ID_WIDTH (WideIdWidthOut ), + .USER_WIDTH (AxiUserWidth ), + .axi_req_t (axi_slv_dma_req_t ), + .axi_rsp_t (axi_slv_dma_resp_t), + .reg_req_t (reg_dma_req_t ), + .reg_rsp_t (reg_dma_rsp_t ) + ) i_axi_to_reg_bootrom ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .testmode_i (1'b0 ), + .axi_req_i (wide_axi_slv_req[BootROM]), + .axi_rsp_o (wide_axi_slv_rsp[BootROM]), + .reg_req_o (bootrom_reg_req ), + .reg_rsp_i (bootrom_reg_rsp ) + ); + + bootrom i_bootrom ( + .clk_i (clk_i ), + .req_i (bootrom_reg_req.valid ), + .addr_i (addr_t'(bootrom_reg_req.addr)), + .rdata_o(bootrom_reg_rsp.rdata ) + ); + `FF(bootrom_reg_rsp.ready, bootrom_reg_req.valid, 1'b0) + assign bootrom_reg_rsp.error = 1'b0; + + // Upsize the narrow SoC connection + `AXI_TYPEDEF_ALL(axi_mst_dma_narrow, addr_t, id_dma_mst_t, data_t, strb_t, user_t) + axi_mst_dma_narrow_req_t narrow_axi_slv_req_soc; + axi_mst_dma_narrow_resp_t narrow_axi_slv_resp_soc; + + axi_iw_converter #( + .AxiAddrWidth (AxiAddrWidth ), + .AxiDataWidth (NarrowDataWidth ), + .AxiUserWidth (AxiUserWidth ), + .AxiSlvPortIdWidth (NarrowIdWidthOut ), + .AxiSlvPortMaxUniqIds (1 ), + .AxiSlvPortMaxTxnsPerId(1 ), + .AxiSlvPortMaxTxns (1 ), + .AxiMstPortIdWidth (WideIdWidthIn ), + .AxiMstPortMaxUniqIds (1 ), + .AxiMstPortMaxTxnsPerId(1 ), + .slv_req_t (axi_slv_req_t ), + .slv_resp_t (axi_slv_resp_t ), + .mst_req_t (axi_mst_dma_narrow_req_t ), + .mst_resp_t (axi_mst_dma_narrow_resp_t) + ) i_soc_port_iw_convert ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (narrow_axi_slv_req[SoC] ), + .slv_resp_o (narrow_axi_slv_rsp[SoC] ), + .mst_req_o (narrow_axi_slv_req_soc ), + .mst_resp_i (narrow_axi_slv_resp_soc ) + ); + + axi_dw_converter #( + .AxiAddrWidth (AxiAddrWidth ), + .AxiIdWidth (WideIdWidthIn ), + .AxiMaxReads (2 ), + .AxiSlvPortDataWidth(NarrowDataWidth ), + .AxiMstPortDataWidth(AxiDataWidth ), + .ar_chan_t (axi_mst_dma_ar_chan_t ), + .aw_chan_t (axi_mst_dma_aw_chan_t ), + .b_chan_t (axi_mst_dma_b_chan_t ), + .slv_r_chan_t (axi_mst_dma_narrow_r_chan_t), + .slv_w_chan_t (axi_mst_dma_narrow_b_chan_t), + .axi_slv_req_t (axi_mst_dma_narrow_req_t ), + .axi_slv_resp_t (axi_mst_dma_narrow_resp_t ), + .mst_r_chan_t (axi_mst_dma_r_chan_t ), + .mst_w_chan_t (axi_mst_dma_w_chan_t ), + .axi_mst_req_t (axi_mst_dma_req_t ), + .axi_mst_resp_t (axi_mst_dma_resp_t ) + ) i_soc_port_dw_upsize ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (narrow_axi_slv_req_soc ), + .slv_resp_o (narrow_axi_slv_resp_soc ), + .mst_req_o (wide_axi_mst_req[CoreReqWide]), + .mst_resp_i (wide_axi_mst_rsp[CoreReqWide]) + ); + + // -------------------- + // TCDM event counters + // -------------------- + logic [NrTCDMPortsCores-1:0] flat_acc, flat_con; + for (genvar i = 0; i < NrTCDMPortsCores; i++) begin : gen_event_counter + `FFARN(flat_acc[i], tcdm_req[i].q_valid, '0, clk_i, rst_ni) + `FFARN(flat_con[i], tcdm_req[i].q_valid & ~tcdm_rsp[i].q_ready, '0, clk_i, rst_ni) + end + + popcount #( + .INPUT_WIDTH ( NrTCDMPortsCores ) + ) i_popcount_req ( + .data_i ( flat_acc ), + .popcount_o ( tcdm_events.inc_accessed ) + ); + + popcount #( + .INPUT_WIDTH ( NrTCDMPortsCores ) + ) i_popcount_con ( + .data_i ( flat_con ), + .popcount_o ( tcdm_events.inc_congested ) + ); + + // ------------- + // Sanity Checks + // ------------- + // Sanity check the parameters. Not every configuration makes sense. + `ASSERT_INIT(CheckSuperBankSanity, NrBanks >= BanksPerSuperBank); + `ASSERT_INIT(CheckSuperBankFactor, (NrBanks % BanksPerSuperBank) == 0); + // Check that the cluster base address aligns to the TCDMSize. + `ASSERT(ClusterBaseAddrAlign, ((TCDMSize - 1) & cluster_base_addr_i) == 0) + // Make sure we only have one DMA in the system. + `ASSERT_INIT(NumberDMA, $onehot0(Xdma)) + +endmodule diff --git a/hardware/src/cachepool_pkg.sv b/hardware/src/cachepool_pkg.sv new file mode 100644 index 0000000..a5c9c46 --- /dev/null +++ b/hardware/src/cachepool_pkg.sv @@ -0,0 +1,146 @@ +// Copyright 2021 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +package cachepool_pkg; + import fpnew_pkg::*; + + /********************* + * TILE PARAMETERS * + *********************/ + + `include "axi/assign.svh" + `include "axi/typedef.svh" + + localparam int unsigned NumTiles = 1; + + /////////// + // AXI // + /////////// + + // AXI Data Width + localparam int unsigned SpatzAxiDataWidth = 256; + localparam int unsigned SpatzAxiStrbWidth = SpatzAxiDataWidth / 8; + localparam int unsigned SpatzAxiNarrowDataWidth = 64; + // AXI Address Width + localparam int unsigned SpatzAxiAddrWidth = 32; + // AXI ID Width + localparam int unsigned SpatzAxiIdInWidth = 6; + localparam int unsigned SpatzAxiIdOutWidth = 2; + + // FIXED AxiIdOutWidth + localparam int unsigned IwcAxiIdOutWidth = 3 + $clog2(4); + + // AXI User Width + localparam int unsigned SpatzAxiUserWidth = 10; + + + typedef logic [SpatzAxiDataWidth-1:0] axi_data_t; + typedef logic [SpatzAxiStrbWidth-1:0] axi_strb_t; + typedef logic [SpatzAxiAddrWidth-1:0] axi_addr_t; + typedef logic [SpatzAxiIdInWidth-1:0] axi_id_in_t; + typedef logic [SpatzAxiIdOutWidth-1:0] axi_id_out_t; + typedef logic [SpatzAxiUserWidth-1:0] axi_user_t; + + + `AXI_TYPEDEF_ALL(spatz_axi_in, axi_addr_t, axi_id_in_t, logic [63:0], logic [7:0], axi_user_t) + `AXI_TYPEDEF_ALL(spatz_axi_out, axi_addr_t, axi_id_out_t, axi_data_t, axi_strb_t, axi_user_t) + + typedef logic [IwcAxiIdOutWidth-1:0] axi_id_out_iwc_t; + + `AXI_TYPEDEF_ALL(spatz_axi_iwc_out, axi_addr_t, axi_id_out_iwc_t, axi_data_t, axi_strb_t, axi_user_t) + + //////////////////// + // Spatz Cluster // + //////////////////// + + localparam int unsigned NumCores = 4; + + localparam int unsigned DataWidth = 64; + localparam int unsigned BeWidth = DataWidth / 8; + localparam int unsigned ByteOffset = $clog2(BeWidth); + + localparam int unsigned ICacheLineWidth = 128; + localparam int unsigned ICacheLineCount = 128; + localparam int unsigned ICacheSets = 2; + + localparam int unsigned TCDMStartAddr = 32'h5100_0000; + localparam int unsigned TCDMSize = 32'h2_0000; + + localparam int unsigned PeriStartAddr = TCDMStartAddr + TCDMSize; + + localparam int unsigned BootAddr = 32'h1000; + + // L2 Configuration + localparam int unsigned L2Addr = 48'h5180_0000; + localparam int unsigned L2Size = 48'h0080_0000; + + function automatic snitch_pma_pkg::rule_t [snitch_pma_pkg::NrMaxRules-1:0] get_cached_regions(); + automatic snitch_pma_pkg::rule_t [snitch_pma_pkg::NrMaxRules-1:0] cached_regions; + cached_regions = '{default: '0}; + cached_regions[0] = '{base: 32'h80000000, mask: 32'h80000000}; + cached_regions[1] = '{base: 32'h51800000, mask: 32'hff800000}; + return cached_regions; + endfunction + + localparam snitch_pma_pkg::snitch_pma_t SnitchPMACfg = '{ + NrCachedRegionRules: 2, + CachedRegion: get_cached_regions(), + default: 0 + }; + + ///////////////// + // Spatz Core // + ///////////////// + + localparam int unsigned NFpu = 4; + localparam int unsigned NIpu = 4; + + + localparam fpu_implementation_t FPUImplementation_Core = '{ + // FMA Block + PipeRegs: '{ + // FP32 FP64 FP16 FP8 FP16A FP8A + '{ 1, 2, 1, 0, 1, 0}, // ADDMUL + '{ 1, 1, 1, 1, 1, 1}, // DIVSQRT + '{ 1, 1, 1, 1, 1, 1}, // NONCOMP + '{ 2, 2, 2, 2, 2, 2}, // CONV + '{ 4, 4, 4, 4, 4, 4} // DOTP + }, + UnitTypes: '{ + '{ MERGED, MERGED, MERGED, MERGED, MERGED, MERGED }, // FMA + '{ DISABLED, DISABLED, DISABLED, DISABLED, DISABLED, DISABLED }, // DIVSQRT + '{ PARALLEL, PARALLEL, PARALLEL, PARALLEL, PARALLEL, PARALLEL }, // NONCOMP + '{ MERGED, MERGED, MERGED, MERGED, MERGED, MERGED }, // CONV + '{ MERGED, MERGED, MERGED, MERGED, MERGED, MERGED } // DOTP + }, + PipeConfig: BEFORE + }; + + localparam fpu_implementation_t FPUImplementation [NumCores] = '{default: FPUImplementation_Core}; + + + //////////////////// + // CachePool L1 // + //////////////////// + + // Number of Cache Banks per Tile + // localparam int unsigned L1CacheBank = 1; + + // // L1 Cache + // localparam int unsigned L1AddrWidth = 32; + // localparam int unsigned L1LineWidth = 256; + // localparam int unsigned L1Associativity = 4; + // localparam int unsigned L1BankFactor = 2; + // localparam int unsigned L1CoalFactor = 2; + // // 8 * 1024 * 64 / 512 = 1024) + // localparam int unsigned L1NumEntry = NrBanks * TCDMDepth * DataWidth / L1LineWidth; + // localparam int unsigned L1NumWrapper = L1LineWidth / DataWidth; + // localparam int unsigned L1BankPerWP = L1BankFactor * L1Associativity; + // localparam int unsigned L1BankPerWay = L1BankFactor * L1NumWrapper; + // localparam int unsigned L1CacheWayEntry = L1NumEntry / L1Associativity; + // localparam int unsigned L1NumSet = L1CacheWayEntry / L1BankFactor; + // localparam int unsigned L1NumTagBank = L1BankFactor * L1Associativity; + // localparam int unsigned L1NumDataBank = L1BankFactor * L1NumWrapper * L1Associativity; + +endpackage : cachepool_pkg diff --git a/hardware/src/cachepool_tile.sv b/hardware/src/cachepool_tile.sv new file mode 100644 index 0000000..db35677 --- /dev/null +++ b/hardware/src/cachepool_tile.sv @@ -0,0 +1,369 @@ +// Copyright 2021 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +`include "mempool/mempool.svh" + +/* verilator lint_off DECLFILENAME */ +module cachepool_tile + import cachepool_pkg::*; + import cf_math_pkg::idx_width; +#( + // TCDM + parameter addr_t TCDMBaseAddr = 32'b0, + // Boot address + parameter logic [31:0] BootAddr = 32'h0000_1000, + // Dependent parameters. DO NOT CHANGE. + parameter int unsigned NumICaches = NumCoresPerTile / NumCoresPerCache +) ( + // Clock and reset + input logic clk_i, + input logic rst_ni, + // Scan chain + input logic scan_enable_i, + input logic scan_data_i, + output logic scan_data_o, + // Tile ID + input logic [idx_width(NumTiles)-1:0] tile_id_i, + // TCDM Master interfaces + output `STRUCT_VECT(tcdm_master_req_t, [NumGroups+NumSubGroupsPerGroup-1-1:0]) tcdm_master_req_o, + output logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_master_req_valid_o, + input logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_master_req_ready_i, + input `STRUCT_VECT(tcdm_master_resp_t, [NumGroups+NumSubGroupsPerGroup-1-1:0]) tcdm_master_resp_i, + input logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_master_resp_valid_i, + output logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_master_resp_ready_o, + // TCDM slave interfaces + input `STRUCT_VECT(tcdm_slave_req_t, [NumGroups+NumSubGroupsPerGroup-1-1:0]) tcdm_slave_req_i, + input logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_slave_req_valid_i, + output logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_slave_req_ready_o, + output `STRUCT_VECT(tcdm_slave_resp_t, [NumGroups+NumSubGroupsPerGroup-1-1:0]) tcdm_slave_resp_o, + output logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_slave_resp_valid_o, + input logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_slave_resp_ready_i, + // TCDM DMA interfaces + input `STRUCT_PORT(tcdm_dma_req_t) tcdm_dma_req_i, + input logic tcdm_dma_req_valid_i, + output logic tcdm_dma_req_ready_o, + output `STRUCT_PORT(tcdm_dma_resp_t) tcdm_dma_resp_o, + output logic tcdm_dma_resp_valid_o, + input logic tcdm_dma_resp_ready_i, + // AXI Interface + output `STRUCT_PORT(axi_tile_req_t) axi_mst_req_o, + input `STRUCT_PORT(axi_tile_resp_t) axi_mst_resp_i, + // Wake up interface + input logic [NumCoresPerTile-1:0] wake_up_i +); + + // CachePool Tile will contains several Spatz CC and some cache banks + + /**************** + * Includes * + ****************/ + + `include "common_cells/registers.svh" + + /***************** + * Definitions * + *****************/ + + import snitch_pkg::dreq_t; + import snitch_pkg::dresp_t; + + typedef logic [idx_width(NumGroups)-1:0] group_id_t; + + // Local interconnect address width + typedef logic [idx_width(NumCoresPerTile*NumDataPortsPerCore + NumGroups + NumSubGroupsPerGroup-1)-1:0] local_req_interco_addr_t; + + + // L1 Data Cache Parameters + + /********************* + * Control Signals * + *********************/ + + + /*********** + * Cores * + ***********/ + + // Instruction interfaces + addr_t [NumICaches-1:0][NumCoresPerCache-1:0] snitch_inst_addr; + data_t [NumICaches-1:0][NumCoresPerCache-1:0] snitch_inst_data; + logic [NumICaches-1:0][NumCoresPerCache-1:0] snitch_inst_valid; + logic [NumICaches-1:0][NumCoresPerCache-1:0] snitch_inst_ready; + + // Data interfaces + addr_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qaddr; + logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qwrite; + amo_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qamo; + data_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qdata; + strb_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qstrb; + meta_id_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qid; + logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qvalid; + logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qready; + data_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_pdata; + logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_pwrite; + logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_perror; + meta_id_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_pid; + logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_pvalid; + logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_pready; + + for (genvar c = 0; unsigned'(c) < NumCoresPerTile; c++) begin: gen_cores + logic [31:0] hart_id; + if (NumCoresPerTile == 1) begin + assign hart_id = unsigned'(tile_id_i); + end else begin + assign hart_id = {unsigned'(tile_id_i), c[idx_width(NumCoresPerTile)-1:0]}; + end + + spatz_mempool_cc #( + .BootAddr ( BootAddr ), + .RVE ( 0 ), + .RVM ( 1 ), + .RVV ( RVV ), + .XFVEC ( XFVEC ), + .XFDOTP ( XFDOTP ), + .XFAUX ( XFAUX ), + .RVF ( RVF ), + .RVD ( RVD ), + .XF16 ( XF16 ), + .XF16ALT ( XF16ALT ), + .XF8 ( XF8 ), + .XDivSqrt ( XDivSqrt ), + .NumMemPortsPerSpatz ( NumMemPortsPerSpatz ), + .TCDMPorts ( NumDataPortsPerCore ) + ) + riscv_core ( + .clk_i (clk_i ), + .rst_i (!rst_ni ), + .hart_id_i (hart_id ), + // IMEM Port + .inst_addr_o (snitch_inst_addr[c/NumCoresPerCache][c%NumCoresPerCache] ), + .inst_data_i (snitch_inst_data[c/NumCoresPerCache][c%NumCoresPerCache] ), + .inst_valid_o (snitch_inst_valid[c/NumCoresPerCache][c%NumCoresPerCache]), + .inst_ready_i (snitch_inst_ready[c/NumCoresPerCache][c%NumCoresPerCache]), + // Data Ports + .data_qaddr_o (snitch_data_qaddr[c] ), + .data_qwrite_o (snitch_data_qwrite[c] ), + .data_qamo_o (snitch_data_qamo[c] ), + .data_qdata_o (snitch_data_qdata[c] ), + .data_qstrb_o (snitch_data_qstrb[c] ), + .data_qid_o (snitch_data_qid[c] ), + .data_qvalid_o (snitch_data_qvalid[c] ), + .data_qready_i (snitch_data_qready[c] ), + .data_pdata_i (snitch_data_pdata[c] ), + .data_pwrite_i (snitch_data_pwrite[c] ), + .data_perror_i (snitch_data_perror[c] ), + .data_pid_i (snitch_data_pid[c] ), + .data_pvalid_i (snitch_data_pvalid[c] ), + .data_pready_o (snitch_data_pready[c] ), + .wake_up_sync_i(wake_up_q[c] ), + // Core Events + .core_events_o (/* Unused */ ) + ); + end + + /*********************** + * Instruction Cache * + ***********************/ + // Instruction interface + axi_core_req_t [NumICaches-1:0] axi_cache_req_d, axi_cache_req_q; + axi_core_resp_t [NumICaches-1:0] axi_cache_resp_d, axi_cache_resp_q; + + for (genvar c = 0; unsigned'(c) < NumICaches; c++) begin: gen_icaches + snitch_icache #( + .NR_FETCH_PORTS (NumCoresPerCache ), + /// Cache Line Width + .L0_LINE_COUNT (4 ), + .LINE_WIDTH (ICacheLineWidth ), + .LINE_COUNT (ICacheSizeByte / (ICacheSets * ICacheLineWidth / 8) ), + .SET_COUNT (ICacheSets ), + .FETCH_AW (AddrWidth ), + .FETCH_DW (DataWidth ), + .FILL_AW (AddrWidth ), + .FILL_DW (AxiDataWidth ), + .L1_TAG_SCM (1 ), + /// Make the early cache latch-based. This reduces latency at the cost of + /// increased combinatorial path lengths and the hassle of having latches in + /// the design. + .EARLY_LATCH (1 ), + .L0_EARLY_TAG_WIDTH (11 ), + .ISO_CROSSING (0 ), + .axi_req_t (axi_core_req_t ), + .axi_rsp_t (axi_core_resp_t ) + ) i_snitch_icache ( + .clk_i (clk_i ), + .clk_d2_i (clk_i ), + .rst_ni (rst_ni ), + .enable_prefetching_i (1'b1 ), + .icache_events_o (/* Unused */ ), + .flush_valid_i (1'b0 ), + .flush_ready_o (/* Unused */ ), + .inst_addr_i (snitch_inst_addr[c] ), + .inst_data_o (snitch_inst_data[c] ), + .inst_cacheable_i ({NumCoresPerCache{1'b1}}), + .inst_valid_i (snitch_inst_valid[c] ), + .inst_ready_o (snitch_inst_ready[c] ), + .inst_error_o (/* Unused */ ), + .axi_req_o (axi_cache_req_d[c] ), + .axi_rsp_i (axi_cache_resp_q[c] ) + ); + axi_cut #( + .aw_chan_t (axi_core_aw_t ), + .w_chan_t (axi_core_w_t ), + .b_chan_t (axi_core_b_t ), + .ar_chan_t (axi_core_ar_t ), + .r_chan_t (axi_core_r_t ), + .axi_req_t (axi_core_req_t ), + .axi_resp_t(axi_core_resp_t) + ) axi_cache_slice ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (axi_cache_req_d[c] ), + .slv_resp_o(axi_cache_resp_q[c]), + .mst_req_o (axi_cache_req_q[c] ), + .mst_resp_i(axi_cache_resp_d[c]) + ); + end + + /***************** + * Cache Banks * + *****************/ + + stream_xbar #( + .NumInp (1 ), + .NumOut (NumSuperbanks ), + .payload_t(tcdm_dma_req_t) + ) i_dma_req_interco ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .flush_i(1'b0 ), + // External priority flag + .rr_i ('0 ), + // Master + .data_i (tcdm_dma_req_i_struct ), + .valid_i(tcdm_dma_req_valid_i ), + .ready_o(tcdm_dma_req_ready_o ), + .sel_i (tcdm_dma_req_i_struct.tgt_addr[idx_width(NumBanksPerTile)-1:$clog2(DmaNumWords)]), + // Slave + .data_o (tcdm_dma_req ), + .valid_o(tcdm_dma_req_valid ), + .ready_i(tcdm_dma_req_ready ), + .idx_o (/* Unused */ ) + ); + + + + // TODO: Add a XBar for bank selection + + for (genvar c = 0; unsigned'(c) < NumDCaches; c++) begin: gen_dcaches + flamingo_spatz_cache_ctrl #( + // Core + .NumPorts (L1DNumPorts ), + .CoalExtFactor (L1DCoalFactor ), + .AddrWidth (AddrWidth ), + .WordWidth (DataWidth ), + // Cache + .NumCacheEntry (L1DSizePerBank ), + .CacheLineWidth (L1DCacheLine ), + .SetAssociativity (L1DCacheWay ), + .BankFactor (L1DCacheBF ), + // Type + .core_meta_t ( ), + .impl_in_t ( ), + .axi_req_t ( ), + .axi_resp_t ( ) + ) i_l1_bank ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .impl_i ('0 ), + // Sync Control + .cache_sync_valid_i (l1d_insn_valid ), + .cache_sync_ready_o (l1d_insn_ready ), + .cache_sync_insn_i (l1d_insn ), + // SPM Size, DO WE NEED IT FOR CACHEPOOL? + .bank_depth_for_SPM_i (num_spm_lines ), + // Request + .core_req_valid_i (cache_req_valid[c] ), + .core_req_ready_o (cache_req_ready[c] ), + .core_req_addr_i (cache_req_addr[c] ), + .core_req_meta_i (cache_req_meta[c] ), + .core_req_write_i (cache_req_write[c] ), + .core_req_wdata_i (cache_req_data[c] ), + // Response + .core_resp_valid_o (cache_rsp_valid[c] ), + .core_resp_ready_i (cache_rsp_ready[c] ), + .core_resp_write_o (cache_rsp_write[c] ), + .core_resp_data_o (cache_rsp_data[c] ), + .core_resp_meta_o (cache_rsp_meta[c] ), + // AXI refill + .axi_req_o (l1_axi_mst_req[c] ), + .axi_resp_i (l1_axi_mst_rsp[c] ), + // Tag Banks + .tcdm_tag_bank_req_o (l1_tag_bank_req[c] ), + .tcdm_tag_bank_we_o (l1_tag_bank_we[c] ), + .tcdm_tag_bank_addr_o (l1_tag_bank_addr[c] ), + .tcdm_tag_bank_wdata_o (l1_tag_bank_wdata[c] ), + .tcdm_tag_bank_be_o (l1_tag_bank_be[c] ), + .tcdm_tag_bank_rdata_i (l1_tag_bank_rdata[c] ), + // Data Banks + .tcdm_data_bank_req_o (l1_data_bank_req[c] ), + .tcdm_data_bank_we_o (l1_data_bank_w[c] ), + .tcdm_data_bank_addr_o (l1_data_bank_addr[c] ), + .tcdm_data_bank_wdata_o(l1_data_bank_wdata[c] ), + .tcdm_data_bank_be_o (l1_data_bank_be[c] ), + .tcdm_data_bank_rdata_i(l1_data_bank_rdata[c] ), + .tcdm_data_bank_gnt_i (l1_data_bank_gnt[c] ) + ); + end + + + + /*************** + * Registers * + ***************/ + + + /**************************** + * Remote Interconnects * + ****************************/ + + + + /********************** + * Local Intercos * + **********************/ + + /******************* + * Core De/mux * + *******************/ + + + /**************** + * AXI Plug * + ****************/ + + + /****************** + * Assertions * + ******************/ + + // Check invariants. + if (BootAddr[1:0] != 2'b00) + $fatal(1, "[cachepool_tile] Boot address should be aligned in a 4-byte boundary."); + + if (NumCoresPerTile != 2**$clog2(NumCoresPerTile)) + $fatal(1, "[cachepool_tile] The number of cores per tile must be a power of two."); + + if (NumCores != unsigned'(2**$clog2(NumCores))) + $fatal(1, "[cachepool_tile] The number of cores must be a power of two."); + + if (NumBanksPerTile < 1) + $fatal(1, "[cachepool_tile] The number of banks per tile must be larger than one"); + + if (NumICaches != 1) + $error("NumICaches > 1 is not supported!"); + + if (DataWidth > AxiDataWidth) + $error("AxiDataWidth needs to be larger than DataWidth!"); + +endmodule : cachepool_tile diff --git a/hardware/src/cachepool_tile_simple.sv b/hardware/src/cachepool_tile_simple.sv new file mode 100644 index 0000000..1d1001d --- /dev/null +++ b/hardware/src/cachepool_tile_simple.sv @@ -0,0 +1,1515 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Author: Diyou Shen + +`include "axi/assign.svh" +`include "axi/typedef.svh" +`include "common_cells/assertions.svh" +`include "common_cells/registers.svh" +`include "mem_interface/assign.svh" +`include "mem_interface/typedef.svh" +`include "register_interface//assign.svh" +`include "register_interface/typedef.svh" +`include "reqrsp_interface/assign.svh" +`include "reqrsp_interface/typedef.svh" +`include "snitch_vm/typedef.svh" +`include "tcdm_interface/assign.svh" +`include "tcdm_interface/typedef.svh" + +/// A single-tile implementation for CachePool +module cachepool_tile_simple + import spatz_pkg::*; + import fpnew_pkg::fpu_implementation_t; + import snitch_pma_pkg::snitch_pma_t; + #( + /// Width of physical address. + parameter int unsigned AxiAddrWidth = 48, + /// Width of AXI port. + parameter int unsigned AxiDataWidth = 512, + /// AXI: id width in. + parameter int unsigned AxiIdWidthIn = 2, + /// AXI: id width out. + parameter int unsigned AxiIdWidthOut = 2, + /// AXI: user width. + parameter int unsigned AxiUserWidth = 1, + /// Address from which to fetch the first instructions. + parameter logic [31:0] BootAddr = 32'h0, + /// Address to indicate start of L2 + parameter logic [AxiAddrWidth-1:0] L2Addr = 48'h0, + parameter logic [AxiAddrWidth-1:0] L2Size = 48'h0, + /// The total amount of cores. + parameter int unsigned NrCores = 8, + /// Data/TCDM memory depth per cut (in words). + parameter int unsigned TCDMDepth = 1024, + /// Cluster peripheral address region size (in kB). + parameter int unsigned ClusterPeriphSize = 64, + /// Number of TCDM Banks. + parameter int unsigned NrBanks = 2 * NrCores, + /// Size of DMA AXI buffer. + parameter int unsigned DMAAxiReqFifoDepth = 3, + /// Size of DMA request fifo. + parameter int unsigned DMAReqFifoDepth = 3, + /// Width of a single icache line. + parameter unsigned ICacheLineWidth = 0, + /// Number of icache lines per set. + parameter int unsigned ICacheLineCount = 0, + /// Number of icache sets. + parameter int unsigned ICacheSets = 0, + // PMA Configuration + parameter snitch_pma_t SnitchPMACfg = '{default: 0}, + /// # Core-global parameters + /// FPU configuration. + parameter fpu_implementation_t FPUImplementation [NrCores] = '{default: fpu_implementation_t'(0)}, + /// Spatz FPU/IPU Configuration + parameter int unsigned NumSpatzFPUs = 4, + parameter int unsigned NumSpatzIPUs = 1, + /// Per-core enabling of the custom `Xdma` ISA extensions. + parameter bit [NrCores-1:0] Xdma = '{default: '0}, + /// # Per-core parameters + /// Per-core integer outstanding loads + parameter int unsigned NumIntOutstandingLoads [NrCores] = '{default: '0}, + /// Per-core integer outstanding memory operations (load and stores) + parameter int unsigned NumIntOutstandingMem [NrCores] = '{default: '0}, + /// Per-core Spatz outstanding loads + parameter int unsigned NumSpatzOutstandingLoads [NrCores] = '{default: '0}, + /// ## Timing Tuning Parameters + /// Insert Pipeline registers into off-loading path (response) + parameter bit RegisterOffloadRsp = 1'b0, + /// Insert Pipeline registers into data memory path (request) + parameter bit RegisterCoreReq = 1'b0, + /// Insert Pipeline registers into data memory path (response) + parameter bit RegisterCoreRsp = 1'b0, + /// Insert Pipeline registers after each memory cut + parameter bit RegisterTCDMCuts = 1'b0, + /// Decouple external AXI plug + parameter bit RegisterExt = 1'b0, + parameter axi_pkg::xbar_latency_e XbarLatency = axi_pkg::CUT_ALL_PORTS, + /// Outstanding transactions on the AXI network + parameter int unsigned MaxMstTrans = 4, + parameter int unsigned MaxSlvTrans = 4, + /// # Interface + /// AXI Ports + parameter type axi_in_req_t = logic, + parameter type axi_in_resp_t = logic, + parameter type axi_out_req_t = logic, + parameter type axi_out_resp_t = logic, + /// SRAM configuration + parameter type impl_in_t = logic, + // Memory latency parameter. Most of the memories have a read latency of 1. In + // case you have memory macros which are pipelined you want to adjust this + // value here. This only applies to the TCDM. The instruction cache macros will break! + // In case you are using the `RegisterTCDMCuts` feature this adds an + // additional cycle latency, which is taken into account here. + parameter int unsigned MemoryMacroLatency = 1 + RegisterTCDMCuts, + /// # SRAM Configuration rules needed: L1D Tag + L1D Data + L1D FIFO + L1I Tag + L1I Data + parameter int unsigned NrSramCfg = 64 + 8 + 2 + ICacheSets + ICacheSets + ) ( + /// System clock. + input logic clk_i, + /// Asynchronous active high reset. This signal is assumed to be _async_. + input logic rst_ni, + /// Per-core debug request signal. Asserting this signals puts the + /// corresponding core into debug mode. This signal is assumed to be _async_. + input logic [NrCores-1:0] debug_req_i, + /// Machine external interrupt pending. Usually those interrupts come from a + /// platform-level interrupt controller. This signal is assumed to be _async_. + input logic [NrCores-1:0] meip_i, + /// Machine timer interrupt pending. Usually those interrupts come from a + /// core-local interrupt controller such as a timer/RTC. This signal is + /// assumed to be _async_. + input logic [NrCores-1:0] mtip_i, + /// Core software interrupt pending. Usually those interrupts come from + /// another core to facilitate inter-processor-interrupts. This signal is + /// assumed to be _async_. + input logic [NrCores-1:0] msip_i, + /// First hartid of the cluster. Cores of a cluster are monotonically + /// increasing without a gap, i.e., a cluster with 8 cores and a + /// `hart_base_id_i` of 5 get the hartids 5 - 12. + input logic [9:0] hart_base_id_i, + /// Base address of cluster. TCDM and cluster peripheral location are derived from + /// it. This signal is pseudo-static. + input logic [AxiAddrWidth-1:0] cluster_base_addr_i, + /// Per-cluster probe on the cluster status. Can be written by the cores to indicate + /// to the overall system that the cluster is executing something. + output logic cluster_probe_o, + /// AXI Core cluster in-port. + input axi_in_req_t axi_in_req_i, + output axi_in_resp_t axi_in_resp_o, + /// AXI Core cluster out-port to core. + output axi_out_req_t axi_out_req_o, + input axi_out_resp_t axi_out_resp_i, + /// AXI Core cluster out-port to L2 Mem. + output axi_out_req_t axi_out_l2_req_o, + input axi_out_resp_t axi_out_l2_resp_i, + /// Indicate the program execution is error + output logic error_o + ); + // --------- + // Imports + // --------- + import snitch_pkg::*; + import snitch_icache_pkg::icache_events_t; + + // --------- + // Constants + // --------- + /// Minimum width to hold the core number. + localparam int unsigned CoreIDWidth = cf_math_pkg::idx_width(NrCores); + localparam int unsigned TCDMMemAddrWidth = $clog2(TCDMDepth); + localparam int unsigned TCDMSize = NrBanks * TCDMDepth * (DataWidth/8); + // The short address for SPM + localparam int unsigned SPMAddrWidth = $clog2(TCDMSize); + // Enlarge the address width for Spatz due to cache + localparam int unsigned TCDMAddrWidth = 32; + localparam int unsigned BanksPerSuperBank = AxiDataWidth / DataWidth; + localparam int unsigned NrSuperBanks = NrBanks / BanksPerSuperBank; + + function automatic int unsigned get_tcdm_ports(int unsigned core); + return spatz_pkg::N_FU + 1; + endfunction + + function automatic int unsigned get_tcdm_port_offs(int unsigned core_idx); + automatic int n = 0; + for (int i = 0; i < core_idx; i++) n += get_tcdm_ports(i); + return n; + endfunction + + localparam int unsigned NrTCDMPortsCores = get_tcdm_port_offs(NrCores); + localparam int unsigned NumTCDMIn = NrTCDMPortsCores + 1; + localparam logic [AxiAddrWidth-1:0] TCDMMask = ~(TCDMSize-1); + + // Core Request, SoC Request + localparam int unsigned NrNarrowMasters = 2; + + // Narrow AXI network parameters + localparam int unsigned NarrowIdWidthIn = AxiIdWidthIn; + localparam int unsigned NarrowIdWidthOut = NarrowIdWidthIn + $clog2(NrNarrowMasters); + localparam int unsigned NarrowDataWidth = 64; + localparam int unsigned NarrowUserWidth = AxiUserWidth; + + // TCDM, Peripherals, SoC Request + localparam int unsigned NrNarrowSlaves = 3; + localparam int unsigned NrNarrowRules = NrNarrowSlaves - 1; + + // Core Request, DMA, Instruction cache + /// Additional one for L1 DCache + localparam int unsigned NrWideMasters = 3 + 1; + localparam int unsigned WideIdWidthOut = AxiIdWidthOut; + localparam int unsigned WideIdWidthIn = WideIdWidthOut - $clog2(NrWideMasters); + // DMA X-BAR configuration + localparam int unsigned NrWideSlaves = 3 + 1; // one prot for L2, one for L3/LLC (virtual) + + // AXI Configuration + localparam axi_pkg::xbar_cfg_t ClusterXbarCfg = '{ + NoSlvPorts : NrNarrowMasters, + NoMstPorts : NrNarrowSlaves, + MaxMstTrans : MaxMstTrans, + MaxSlvTrans : MaxSlvTrans, + FallThrough : 1'b0, + LatencyMode : XbarLatency, + AxiIdWidthSlvPorts: NarrowIdWidthIn, + AxiIdUsedSlvPorts : NarrowIdWidthIn, + UniqueIds : 1'b0, + AxiAddrWidth : AxiAddrWidth, + AxiDataWidth : NarrowDataWidth, + NoAddrRules : NrNarrowRules, + default : '0 + }; + + // DMA configuration struct + localparam axi_pkg::xbar_cfg_t DmaXbarCfg = '{ + NoSlvPorts : NrWideMasters, + NoMstPorts : NrWideSlaves, + MaxMstTrans : MaxMstTrans, + MaxSlvTrans : MaxSlvTrans, + FallThrough : 1'b0, + LatencyMode : XbarLatency, + AxiIdWidthSlvPorts: WideIdWidthIn, + AxiIdUsedSlvPorts : WideIdWidthIn, + UniqueIds : 1'b0, + AxiAddrWidth : AxiAddrWidth, + AxiDataWidth : AxiDataWidth, + NoAddrRules : NrWideSlaves - 1, + default : '0 + }; + + // L1 Cache + localparam int unsigned L1AddrWidth = 32; + localparam int unsigned L1LineWidth = 512; + localparam int unsigned L1Associativity = 4; + localparam int unsigned L1BankFactor = 2; + localparam int unsigned L1CoalFactor = 2; + // 8 * 1024 * 64 / 512 = 1024) + localparam int unsigned L1NumEntry = NrBanks * TCDMDepth * DataWidth / L1LineWidth; + localparam int unsigned L1NumWrapper = L1LineWidth / DataWidth; + localparam int unsigned L1BankPerWP = L1BankFactor * L1Associativity; + localparam int unsigned L1BankPerWay = L1BankFactor * L1NumWrapper; + localparam int unsigned L1CacheWayEntry = L1NumEntry / L1Associativity; + localparam int unsigned L1NumSet = L1CacheWayEntry / L1BankFactor; + localparam int unsigned L1NumTagBank = L1BankFactor * L1Associativity; + localparam int unsigned L1NumDataBank = L1BankFactor * L1NumWrapper * L1Associativity; + + // -------- + // Typedefs + // -------- + typedef logic [AxiAddrWidth-1:0] addr_t; + typedef logic [NarrowDataWidth-1:0] data_t; + typedef logic [NarrowDataWidth/8-1:0] strb_t; + typedef logic [AxiDataWidth-1:0] data_dma_t; + typedef logic [AxiDataWidth/8-1:0] strb_dma_t; + typedef logic [NarrowIdWidthIn-1:0] id_mst_t; + typedef logic [NarrowIdWidthOut-1:0] id_slv_t; + typedef logic [WideIdWidthIn-1:0] id_dma_mst_t; + typedef logic [WideIdWidthOut-1:0] id_dma_slv_t; + typedef logic [NarrowUserWidth-1:0] user_t; + typedef logic [AxiUserWidth-1:0] user_dma_t; + + typedef logic [TCDMMemAddrWidth-1:0] tcdm_mem_addr_t; + typedef logic [TCDMAddrWidth-1:0] tcdm_addr_t; + typedef logic [SPMAddrWidth-1:0] spm_addr_t; + + typedef logic [$clog2(NumSpatzOutstandingLoads[0])-1:0] reqid_t; + typedef logic [$clog2(NumSpatzOutstandingLoads[0]):0] tcdm_meta_t; + + typedef logic [$clog2(L1NumSet)-1:0] tcdm_bank_addr_t; + + typedef struct packed { + logic [CoreIDWidth-1:0] core_id; + logic is_core; + reqid_t req_id; + } tcdm_user_t; + + // Regbus peripherals. + `AXI_TYPEDEF_ALL(axi_mst, addr_t, id_mst_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_ALL(axi_slv, addr_t, id_slv_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_ALL(axi_mst_dma, addr_t, id_dma_mst_t, data_dma_t, strb_dma_t, user_dma_t) + `AXI_TYPEDEF_ALL(axi_slv_dma, addr_t, id_dma_slv_t, data_dma_t, strb_dma_t, user_dma_t) + + `REQRSP_TYPEDEF_ALL(reqrsp, addr_t, data_t, strb_t) + + `MEM_TYPEDEF_ALL(mem, tcdm_mem_addr_t, data_t, strb_t, tcdm_user_t) + `MEM_TYPEDEF_ALL(mem_dma, tcdm_mem_addr_t, data_dma_t, strb_dma_t, logic) + + `TCDM_TYPEDEF_ALL(tcdm, tcdm_addr_t, data_t, strb_t, tcdm_user_t) + `TCDM_TYPEDEF_ALL(tcdm_dma, tcdm_addr_t, data_dma_t, strb_dma_t, logic) + `TCDM_TYPEDEF_ALL(spm, spm_addr_t, data_t, strb_t, tcdm_user_t) + + `REG_BUS_TYPEDEF_ALL(reg, addr_t, data_t, strb_t) + `REG_BUS_TYPEDEF_ALL(reg_dma, addr_t, data_dma_t, strb_dma_t) + + // Event counter increments for the TCDM. + typedef struct packed { + /// Number requests going in + logic [$clog2(NrTCDMPortsCores):0] inc_accessed; + /// Number of requests stalled due to congestion + logic [$clog2(NrTCDMPortsCores):0] inc_congested; + } tcdm_events_t; + + // Event counter increments for DMA. + typedef struct packed { + logic aw_stall, ar_stall, r_stall, w_stall, + buf_w_stall, buf_r_stall; + logic aw_valid, aw_ready, aw_done, aw_bw; + logic ar_valid, ar_ready, ar_done, ar_bw; + logic r_valid, r_ready, r_done, r_bw; + logic w_valid, w_ready, w_done, w_bw; + logic b_valid, b_ready, b_done; + logic dma_busy; + axi_pkg::len_t aw_len, ar_len; + axi_pkg::size_t aw_size, ar_size; + logic [$clog2(AxiDataWidth/8):0] num_bytes_written; + } dma_events_t; + + typedef struct packed { + int unsigned idx; + addr_t start_addr; + addr_t end_addr; + } xbar_rule_t; + + typedef struct packed { + acc_addr_e addr; + logic [5:0] id; + logic [31:0] data_op; + data_t data_arga; + data_t data_argb; + addr_t data_argc; + } acc_issue_req_t; + + typedef struct packed { + logic accept; + logic writeback; + logic loadstore; + logic exception; + logic isfloat; + } acc_issue_rsp_t; + + typedef struct packed { + logic [5:0] id; + logic error; + data_t data; + } acc_rsp_t; + + `SNITCH_VM_TYPEDEF(AxiAddrWidth) + + typedef struct packed { + // Slow domain. + logic flush_i_valid; + addr_t inst_addr; + logic inst_cacheable; + logic inst_valid; + // Fast domain. + acc_issue_req_t acc_req; + logic acc_qvalid; + logic acc_pready; + // Slow domain. + logic [1:0] ptw_valid; + va_t [1:0] ptw_va; + pa_t [1:0] ptw_ppn; + } hive_req_t; + + typedef struct packed { + // Slow domain. + logic flush_i_ready; + logic [31:0] inst_data; + logic inst_ready; + logic inst_error; + // Fast domain. + logic acc_qready; + acc_rsp_t acc_resp; + logic acc_pvalid; + // Slow domain. + logic [1:0] ptw_ready; + l0_pte_t [1:0] ptw_pte; + logic [1:0] ptw_is_4mega; + } hive_rsp_t; + + // ----------- + // Assignments + // ----------- + // Calculate start and end address of TCDM based on the `cluster_base_addr_i`. + addr_t tcdm_start_address, tcdm_end_address; + assign tcdm_start_address = (cluster_base_addr_i & TCDMMask); + assign tcdm_end_address = (tcdm_start_address + TCDMSize) & TCDMMask; + + addr_t cluster_periph_start_address, cluster_periph_end_address; + assign cluster_periph_start_address = tcdm_end_address; + assign cluster_periph_end_address = tcdm_end_address + ClusterPeriphSize * 1024; + + localparam int unsigned ClusterReserve = 4096; // 4 MiB + localparam int unsigned ClusterL2Size = 8192; // 8 MiB + addr_t cluster_l2_start_address, cluster_l2_end_address; + assign cluster_l2_start_address = L2Addr; + assign cluster_l2_end_address = L2Addr + L2Size; + + // ---------------- + // Wire Definitions + // ---------------- + // 1. AXI + axi_slv_req_t [NrNarrowSlaves-1:0] narrow_axi_slv_req; + axi_slv_resp_t [NrNarrowSlaves-1:0] narrow_axi_slv_rsp; + axi_mst_req_t [NrNarrowMasters-1:0] narrow_axi_mst_req; + axi_mst_resp_t [NrNarrowMasters-1:0] narrow_axi_mst_rsp; + + // DMA AXI buses + axi_mst_dma_req_t [NrWideMasters-1:0] wide_axi_mst_req; + axi_mst_dma_resp_t [NrWideMasters-1:0] wide_axi_mst_rsp; + axi_slv_dma_req_t [NrWideSlaves-1 :0] wide_axi_slv_req; + axi_slv_dma_resp_t [NrWideSlaves-1 :0] wide_axi_slv_rsp; + + // 2. Memory Subsystem (Banks) + mem_req_t [NrSuperBanks-1:0][BanksPerSuperBank-1:0] ic_req; + mem_rsp_t [NrSuperBanks-1:0][BanksPerSuperBank-1:0] ic_rsp; + + mem_dma_req_t [NrSuperBanks-1:0] sb_dma_req; + mem_dma_rsp_t [NrSuperBanks-1:0] sb_dma_rsp; + + // 3. Memory Subsystem (Interconnect) + tcdm_dma_req_t ext_dma_req; + tcdm_dma_rsp_t ext_dma_rsp; + + // AXI Ports into TCDM (from SoC). + spm_req_t axi_soc_req; + spm_rsp_t axi_soc_rsp; + + tcdm_req_t [NrTCDMPortsCores-1:0] tcdm_req; + tcdm_rsp_t [NrTCDMPortsCores-1:0] tcdm_rsp; + + core_events_t [NrCores-1:0] core_events; + tcdm_events_t tcdm_events; + dma_events_t dma_events; + snitch_icache_pkg::icache_events_t [NrCores-1:0] icache_events; + + // 4. Memory Subsystem (Core side). + reqrsp_req_t [NrCores-1:0] core_req, filtered_core_req; + reqrsp_rsp_t [NrCores-1:0] core_rsp, filtered_core_rsp; + + // 5. Peripheral Subsystem + reg_req_t reg_req; + reg_rsp_t reg_rsp; + + // 6. BootROM + reg_dma_req_t bootrom_reg_req; + reg_dma_rsp_t bootrom_reg_rsp; + + // 7. Misc. Wires. + logic icache_prefetch_enable; + logic [NrCores-1:0] cl_interrupt; + + // 8. L1 D$ + spm_req_t [NrTCDMPortsCores-1:0] spm_req; + spm_rsp_t [NrTCDMPortsCores-1:0] spm_rsp; + + tcdm_req_t [NrTCDMPortsCores-1:0] unmerge_req, strb_hdl_req, cache_req; + tcdm_rsp_t [NrTCDMPortsCores-1:0] unmerge_rsp, strb_hdl_rsp, cache_rsp; + + logic [NrTCDMPortsCores-1:0] cache_req_valid; + logic [NrTCDMPortsCores-1:0] cache_req_ready; + tcdm_addr_t [NrTCDMPortsCores-1:0] cache_req_addr; + tcdm_user_t [NrTCDMPortsCores-1:0] cache_req_meta; + logic [NrTCDMPortsCores-1:0] cache_req_write; + data_t [NrTCDMPortsCores-1:0] cache_req_data; + + logic [NrTCDMPortsCores-1:0] cache_rsp_valid; + logic [NrTCDMPortsCores-1:0] cache_rsp_ready; + logic [NrTCDMPortsCores-1:0] cache_rsp_write; + data_t [NrTCDMPortsCores-1:0] cache_rsp_data; + tcdm_user_t [NrTCDMPortsCores-1:0] cache_rsp_meta; + + logic [L1NumTagBank-1:0] l1_tag_bank_req; + logic [L1NumTagBank-1:0] l1_tag_bank_we; + tcdm_bank_addr_t [L1NumTagBank-1:0] l1_tag_bank_addr; + data_t [L1NumTagBank-1:0] l1_tag_bank_wdata; + logic [L1NumTagBank-1:0] l1_tag_bank_be; + data_t [L1NumTagBank-1:0] l1_tag_bank_rdata; + + logic [L1NumDataBank-1:0] l1_data_bank_req; + logic [L1NumDataBank-1:0] l1_data_bank_we; + tcdm_bank_addr_t [L1NumDataBank-1:0] l1_data_bank_addr; + data_t [L1NumDataBank-1:0] l1_data_bank_wdata; + logic [L1NumDataBank-1:0] l1_data_bank_be; + data_t [L1NumDataBank-1:0] l1_data_bank_rdata; + logic [L1NumDataBank-1:0] l1_data_bank_gnt; + + logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_req; + logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_we; + tcdm_bank_addr_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_addr; + data_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_wdata; + strb_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_be; + data_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_rdata; + logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_gnt; + + logic l1d_insn_valid, l1d_insn_ready; + logic [1:0] l1d_insn; + tcdm_bank_addr_t cfg_spm_size; + tcdm_addr_t spm_size; + logic l1d_busy; + + // High if a port access an illegal SPM region (mapped to cache) + logic [NrTCDMPortsCores-1:0] spm_error; + + + // 9. SRAM Configuration + impl_in_t [L1NumWrapper-1:0][L1BankPerWP-1:0] impl_l1d_data; + impl_in_t [L1NumTagBank-1:0] impl_l1d_tag; + impl_in_t [1:0] impl_l1d_fifo; + + impl_in_t [ICacheSets-1:0] impl_l1i_data; + impl_in_t [ICacheSets-1:0] impl_l1i_tag; + + assign {impl_l1d_data, impl_l1d_tag, impl_l1d_fifo, impl_l1i_data, impl_l1i_tag} = impl_i; + assign error_o = |spm_error; + + + // ------------- + // DMA Subsystem + // ------------- + // Optionally decouple the external wide AXI master port. + axi_cut #( + .Bypass (!RegisterExt ), + .aw_chan_t (axi_slv_dma_aw_chan_t), + .w_chan_t (axi_slv_dma_w_chan_t ), + .b_chan_t (axi_slv_dma_b_chan_t ), + .ar_chan_t (axi_slv_dma_ar_chan_t), + .r_chan_t (axi_slv_dma_r_chan_t ), + .axi_req_t (axi_slv_dma_req_t ), + .axi_resp_t (axi_slv_dma_resp_t ) + ) i_cut_ext_wide_out ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (wide_axi_slv_req[SoCDMAOut]), + .slv_resp_o (wide_axi_slv_rsp[SoCDMAOut]), + .mst_req_o (axi_out_req_o ), + .mst_resp_i (axi_out_resp_i ) + ); + + axi_cut #( + .Bypass (!RegisterExt ), + .aw_chan_t (axi_slv_dma_aw_chan_t), + .w_chan_t (axi_slv_dma_w_chan_t ), + .b_chan_t (axi_slv_dma_b_chan_t ), + .ar_chan_t (axi_slv_dma_ar_chan_t), + .r_chan_t (axi_slv_dma_r_chan_t ), + .axi_req_t (axi_slv_dma_req_t ), + .axi_resp_t (axi_slv_dma_resp_t ) + ) i_cut_ext_l2_wide_out ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (wide_axi_slv_req[L2Mem]), + .slv_resp_o (wide_axi_slv_rsp[L2Mem]), + .mst_req_o (axi_out_l2_req_o ), + .mst_resp_i (axi_out_l2_resp_i ) + ); + + axi_cut #( + .Bypass (!RegisterExt ), + .aw_chan_t (axi_mst_aw_chan_t), + .w_chan_t (axi_mst_w_chan_t ), + .b_chan_t (axi_mst_b_chan_t ), + .ar_chan_t (axi_mst_ar_chan_t), + .r_chan_t (axi_mst_r_chan_t ), + .axi_req_t (axi_mst_req_t ), + .axi_resp_t (axi_mst_resp_t ) + ) i_cut_ext_narrow_in ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (axi_in_req_i ), + .slv_resp_o (axi_in_resp_o ), + .mst_req_o (narrow_axi_mst_req[SoCDMAIn]), + .mst_resp_i (narrow_axi_mst_rsp[SoCDMAIn]) + ); + + logic [DmaXbarCfg.NoSlvPorts-1:0][$clog2(DmaXbarCfg.NoMstPorts)-1:0] dma_xbar_default_port; + xbar_rule_t [DmaXbarCfg.NoAddrRules-1:0] dma_xbar_rule; + + assign dma_xbar_default_port = '{default: SoCDMAOut}; + assign dma_xbar_rule = '{ + '{ + idx : TCDMDMA, + start_addr: tcdm_start_address, + end_addr : tcdm_end_address + }, + '{ + idx : BootROM, + start_addr: BootAddr, + end_addr : BootAddr + 'h1000 + }, + '{ + idx : L2Mem, + start_addr: cluster_l2_start_address, + end_addr : cluster_l2_end_address + } + }; + + localparam bit [DmaXbarCfg.NoSlvPorts-1:0] DMAEnableDefaultMstPort = '1; + axi_xbar #( + .Cfg (DmaXbarCfg ), + .ATOPs (0 ), + .slv_aw_chan_t (axi_mst_dma_aw_chan_t), + .mst_aw_chan_t (axi_slv_dma_aw_chan_t), + .w_chan_t (axi_mst_dma_w_chan_t ), + .slv_b_chan_t (axi_mst_dma_b_chan_t ), + .mst_b_chan_t (axi_slv_dma_b_chan_t ), + .slv_ar_chan_t (axi_mst_dma_ar_chan_t), + .mst_ar_chan_t (axi_slv_dma_ar_chan_t), + .slv_r_chan_t (axi_mst_dma_r_chan_t ), + .mst_r_chan_t (axi_slv_dma_r_chan_t ), + .slv_req_t (axi_mst_dma_req_t ), + .slv_resp_t (axi_mst_dma_resp_t ), + .mst_req_t (axi_slv_dma_req_t ), + .mst_resp_t (axi_slv_dma_resp_t ), + .rule_t (xbar_rule_t ) + ) i_axi_dma_xbar ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .test_i (1'b0 ), + .slv_ports_req_i (wide_axi_mst_req ), + .slv_ports_resp_o (wide_axi_mst_rsp ), + .mst_ports_req_o (wide_axi_slv_req ), + .mst_ports_resp_i (wide_axi_slv_rsp ), + .addr_map_i (dma_xbar_rule ), + .en_default_mst_port_i (DMAEnableDefaultMstPort), + .default_mst_port_i (dma_xbar_default_port ) + ); + + addr_t ext_dma_req_q_addr_nontrunc; + + axi_to_mem_interleaved #( + .axi_req_t (axi_slv_dma_req_t ), + .axi_resp_t (axi_slv_dma_resp_t ), + .AddrWidth (AxiAddrWidth ), + .DataWidth (AxiDataWidth ), + .IdWidth (WideIdWidthOut ), + .NumBanks (1 ), + .BufDepth (MemoryMacroLatency + 1) + ) i_axi_to_mem_dma ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .busy_o (/* Unused */ ), + .test_i (1'b0 ), + .axi_req_i (wide_axi_slv_req[TCDMDMA] ), + .axi_resp_o (wide_axi_slv_rsp[TCDMDMA] ), + .mem_req_o (ext_dma_req.q_valid ), + .mem_gnt_i (ext_dma_rsp.q_ready ), + .mem_addr_o (ext_dma_req_q_addr_nontrunc ), + .mem_wdata_o (ext_dma_req.q.data ), + .mem_strb_o (ext_dma_req.q.strb ), + .mem_atop_o (/* The DMA does not support atomics */), + .mem_we_o (ext_dma_req.q.write ), + .mem_rvalid_i (ext_dma_rsp.p_valid ), + .mem_rdata_i (ext_dma_rsp.p.data ) + ); + + assign ext_dma_req.q.addr = tcdm_addr_t'(ext_dma_req_q_addr_nontrunc); + assign ext_dma_req.q.amo = reqrsp_pkg::AMONone; + assign ext_dma_req.q.user = '0; + + spatz_tcdm_interconnect #( + .NumInp (1 ), + .NumOut (NrSuperBanks ), + .tcdm_req_t (tcdm_dma_req_t ), + .tcdm_rsp_t (tcdm_dma_rsp_t ), + .mem_req_t (mem_dma_req_t ), + .mem_rsp_t (mem_dma_rsp_t ), + .user_t (logic ), + .MemAddrWidth (TCDMMemAddrWidth ), + .DataWidth (AxiDataWidth ), + .MemoryResponseLatency (MemoryMacroLatency) + ) i_dma_interconnect ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .req_i (ext_dma_req), + .rsp_o (ext_dma_rsp), + .mem_req_o (sb_dma_req ), + .mem_rsp_i (sb_dma_rsp ) + ); + + // ---------------- + // Memory Subsystem + // ---------------- + for (genvar i = 0; i < NrSuperBanks; i++) begin : gen_tcdm_super_bank + + mem_req_t [BanksPerSuperBank-1:0] amo_req; + mem_rsp_t [BanksPerSuperBank-1:0] amo_rsp; + + mem_wide_narrow_mux #( + .NarrowDataWidth (NarrowDataWidth), + .WideDataWidth (AxiDataWidth ), + .mem_narrow_req_t (mem_req_t ), + .mem_narrow_rsp_t (mem_rsp_t ), + .mem_wide_req_t (mem_dma_req_t ), + .mem_wide_rsp_t (mem_dma_rsp_t ) + ) i_tcdm_mux ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .in_narrow_req_i (ic_req [i] ), + .in_narrow_rsp_o (ic_rsp [i] ), + .in_wide_req_i (sb_dma_req [i] ), + .in_wide_rsp_o (sb_dma_rsp [i] ), + .out_req_o (amo_req ), + .out_rsp_i (amo_rsp ), + .sel_wide_i (sb_dma_req[i].q_valid) + ); + + // generate banks of the superbank + for (genvar j = 0; j < BanksPerSuperBank; j++) begin : gen_tcdm_bank + + logic mem_cs, mem_wen; + tcdm_mem_addr_t mem_add; + tcdm_mem_addr_t mem_add_max; + strb_t mem_be; + data_t mem_rdata, mem_wdata; + tcdm_meta_t mem_req_meta; + assign mem_add_max = 0 - 1'b1; + + spatz_sram_wrapper #( + .NumBanks (L1BankPerWP ), + .NumWords (TCDMDepth ), + .ByteWidth (8 ), + .DataWidth (DataWidth ), + .MemoryResponseLatency (1 ), + .impl_in_t (impl_in_t ) + ) i_data_mem ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .spm_size_i (cfg_spm_size ), + /// Cache Side TODO: Connect cache + .cache_req_i (l1_cache_wp_req [j] ), + .cache_we_i (l1_cache_wp_we [j] ), + .cache_addr_i (l1_cache_wp_addr [j] ), + .cache_wdata_i(l1_cache_wp_wdata[j] ), + .cache_be_i (l1_cache_wp_be [j] ), + .cache_rdata_o(l1_cache_wp_rdata[j] ), + .cache_ready_o(l1_cache_wp_gnt [j] ), + /// SPM Side + .spm_req_i (mem_cs ), + .spm_we_i (mem_wen ), + .spm_addr_i (mem_add_max - mem_add), // swap the position of stack and data + .spm_wdata_i (mem_wdata ), + .spm_be_i (mem_be ), + .spm_rdata_o (mem_rdata ), + /// SRAM Configuration + .impl_i (impl_l1d_data[j] ) + ); + + data_t amo_rdata_local; + + // TODO(zarubaf): Share atomic units between mutltiple cuts + snitch_amo_shim #( + .AddrMemWidth ( TCDMMemAddrWidth ), + .DataWidth ( DataWidth ), + .CoreIDWidth ( CoreIDWidth ) + ) i_amo_shim ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .valid_i (amo_req[j].q_valid ), + .ready_o (amo_rsp[j].q_ready ), + .addr_i (amo_req[j].q.addr ), + .write_i (amo_req[j].q.write ), + .wdata_i (amo_req[j].q.data ), + .wstrb_i (amo_req[j].q.strb ), + .core_id_i (amo_req[j].q.user.core_id ), + .is_core_i (amo_req[j].q.user.is_core ), + .rdata_o (amo_rdata_local ), + .amo_i (amo_req[j].q.amo ), + .mem_req_o (mem_cs ), + .mem_add_o (mem_add ), + .mem_wen_o (mem_wen ), + .mem_wdata_o (mem_wdata ), + .mem_be_o (mem_be ), + .mem_rdata_i (mem_rdata ), + .dma_access_i (sb_dma_req[i].q_valid ), + // TODO(zarubaf): Signal AMO conflict somewhere. Socregs? + .amo_conflict_o (/* Unused */ ) + ); + + // Insert a pipeline register at the output of each SRAM. + shift_reg #( + .dtype(data_t ), + .Depth(int'(RegisterTCDMCuts)) + ) i_sram_pipe ( + .clk_i (clk_i ), + .rst_ni(rst_ni ), + .d_i (amo_rdata_local ), + .d_o (amo_rsp[j].p.data) + ); + + // delay the req_id two cycles: 1 for bank access, 1 for reg + shift_reg #( + .dtype(tcdm_meta_t ), + .Depth(int'(RegisterTCDMCuts)) + ) i_reqid_pipe1 ( + .clk_i (clk_i ), + .rst_ni(rst_ni ), + .d_i ({amo_req[j].q.user.req_id, amo_req[j].q.write}), + .d_o (mem_req_meta ) + ); + shift_reg #( + .dtype(tcdm_meta_t ), + .Depth(int'(RegisterTCDMCuts)) + ) i_reqid_pipe2 ( + .clk_i (clk_i ), + .rst_ni(rst_ni ), + .d_i (mem_req_meta ), + .d_o ({amo_rsp[j].p.user.req_id, amo_rsp[j].p.write}) + ); + + // tie unused field to 0 + // TODO: remove these fields + assign amo_rsp[j].p.user.core_id = '0; + assign amo_rsp[j].p.user.is_core = '0; + end + end + + logic [NrTCDMPortsCores-1:0] unmerge_pready, strb_hdl_pready, cache_pready; + assign spm_size = cfg_spm_size * L1Associativity * L1LineWidth / 2; + + // split the requests for spm or cache from core side + spatz_addr_mapper #( + .NumIO (NrTCDMPortsCores ), + .AddrWidth (L1AddrWidth ), + .SPMAddrWidth (SPMAddrWidth ), + .DataWidth (DataWidth ), + .mem_req_t (tcdm_req_t ), + .mem_rsp_t (tcdm_rsp_t ), + .mem_rsp_chan_t (tcdm_rsp_chan_t ), + .spm_req_t (spm_req_t ), + .spm_rsp_t (spm_rsp_t ) + ) i_tcdm_mapper ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + // Input + .mem_req_i (tcdm_req ), + .mem_rsp_o (tcdm_rsp ), + .error_o (spm_error ), + // Address + .tcdm_start_address_i (tcdm_start_address[L1AddrWidth-1:0] ), + .tcdm_end_address_i (tcdm_end_address[L1AddrWidth-1:0] ), + .spm_size_i (spm_size ), + .flush_i (l1d_busy ), + // Output + .spm_req_o (spm_req ), + .spm_rsp_i (spm_rsp ), + .cache_req_o (unmerge_req ), + .cache_pready_o (unmerge_pready ), + .cache_rsp_i (unmerge_rsp ) + ); + + localparam int unsigned NumIOPerCore = get_tcdm_ports(0); + logic [NrTCDMPortsCores-1:0] strb_req_ack; + + spatz_strbreq_merge_tree #( + .NumIO (NrTCDMPortsCores ), + .NumOutstandingMem (NumSpatzOutstandingLoads[0] ), + .MergeNum (NrTCDMPortsCores - NrCores ), + .DataWidth (DataWidth ), + .mem_req_t (tcdm_req_t ), + .mem_rsp_t (tcdm_rsp_t ), + .req_id_t (reqid_t ), + .tcdm_user_t (tcdm_user_t ) + ) i_strbreq_merge_tree ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .unmerge_req_i (unmerge_req ), + .unmerge_pready_i(unmerge_pready ), + .merge_rsp_i (strb_hdl_rsp ), + .merge_req_o (strb_hdl_req ), + .merge_pready_o (strb_hdl_pready ), + .unmerge_rsp_o (unmerge_rsp ) + ); + + for (genvar j = 0; j < NrTCDMPortsCores; j++) begin: gen_strb_hdlr + spatz_strbreq_handler #( + .DataWidth (DataWidth ), + .mem_req_t (tcdm_req_t ), + .mem_rsp_t (tcdm_rsp_t ), + .reqrsp_user_t (tcdm_user_t ) + ) i_strbreq_handler ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .strb_req_i (strb_hdl_req[j] ), + .strb_rsp_ready_i (strb_hdl_pready[j] ), + .strb_rsp_i (cache_rsp[j] ), + .strb_req_o (cache_req[j] ), + .strb_rsp_ready_o (cache_pready[j] ), + .strb_rsp_o (strb_hdl_rsp[j] ) + ); + + assign cache_req_valid[j] = cache_req[j].q_valid; + assign cache_rsp_ready[j] = cache_pready[j]; + assign cache_req_addr[j] = cache_req[j].q.addr; + assign cache_req_meta[j] = cache_req[j].q.user; + assign cache_req_write[j] = cache_req[j].q.write; + assign cache_req_data[j] = cache_req[j].q.data; + + assign cache_rsp[j].p_valid = cache_rsp_valid[j]; + assign cache_rsp[j].q_ready = cache_req_ready[j]; + assign cache_rsp[j].p.data = cache_rsp_data[j]; + assign cache_rsp[j].p.user = cache_rsp_meta[j]; + + assign cache_rsp[j].p.write = cache_rsp_write[j]; + end + + flamingo_spatz_cache_ctrl #( + // Core + .NumPorts (NrTCDMPortsCores ), + .CoalExtFactor (L1CoalFactor ), + .AddrWidth (L1AddrWidth ), + .WordWidth (DataWidth ), + // Cache + .NumCacheEntry (L1NumEntry ), + .CacheLineWidth (L1LineWidth ), + .SetAssociativity (L1Associativity ), + .BankFactor (L1BankFactor ), + // Type + .core_meta_t (tcdm_user_t ), + .impl_in_t (impl_in_t ), + .axi_req_t (axi_mst_dma_req_t ), + .axi_resp_t (axi_mst_dma_resp_t) + ) i_l1_controller ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .impl_i (impl_l1d_fifo ), + // Sync Control + .cache_sync_valid_i (l1d_insn_valid ), + .cache_sync_ready_o (l1d_insn_ready ), + .cache_sync_insn_i (l1d_insn ), + // SPM Size + // The calculation of spm region in cache is different + // than other modules (needs to times 2) + .bank_depth_for_SPM_i ((cfg_spm_size<<1) ), + // Request + .core_req_valid_i (cache_req_valid ), + .core_req_ready_o (cache_req_ready ), + .core_req_addr_i (cache_req_addr ), + .core_req_meta_i (cache_req_meta ), + .core_req_write_i (cache_req_write ), + .core_req_wdata_i (cache_req_data ), + // Response + .core_resp_valid_o (cache_rsp_valid ), + .core_resp_ready_i (cache_rsp_ready ), + .core_resp_write_o (cache_rsp_write ), + .core_resp_data_o (cache_rsp_data ), + .core_resp_meta_o (cache_rsp_meta ), + // AXI refill + .axi_req_o (wide_axi_mst_req[DCache] ), + .axi_resp_i (wide_axi_mst_rsp[DCache] ), + // Tag Banks + .tcdm_tag_bank_req_o (l1_tag_bank_req ), + .tcdm_tag_bank_we_o (l1_tag_bank_we ), + .tcdm_tag_bank_addr_o (l1_tag_bank_addr ), + .tcdm_tag_bank_wdata_o (l1_tag_bank_wdata ), + .tcdm_tag_bank_be_o (l1_tag_bank_be ), + .tcdm_tag_bank_rdata_i (l1_tag_bank_rdata ), + // Data Banks + .tcdm_data_bank_req_o (l1_data_bank_req ), + .tcdm_data_bank_we_o (l1_data_bank_we ), + .tcdm_data_bank_addr_o (l1_data_bank_addr ), + .tcdm_data_bank_wdata_o(l1_data_bank_wdata ), + .tcdm_data_bank_be_o (l1_data_bank_be ), + .tcdm_data_bank_rdata_i(l1_data_bank_rdata ), + .tcdm_data_bank_gnt_i (l1_data_bank_gnt ) + ); + + for (genvar j = 0; j < L1NumTagBank; j++) begin: gen_l1_tag_banks + tc_sram_impl #( + .NumWords (L1CacheWayEntry/L1BankFactor), + .DataWidth ($bits(data_t) ), + .ByteWidth ($bits(data_t) ), + .NumPorts (1 ), + .Latency (1 ), + .SimInit ("zeros" ), + .impl_in_t (impl_in_t ) + ) i_meta_bank ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .impl_i (impl_l1d_tag [j]), + .impl_o (/* unsed */ ), + .req_i (l1_tag_bank_req [j]), + .we_i (l1_tag_bank_we [j]), + .addr_i (l1_tag_bank_addr [j]), + .wdata_i(l1_tag_bank_wdata[j]), + .be_i (l1_tag_bank_be [j]), + .rdata_o(l1_tag_bank_rdata[j]) + ); + end + + for (genvar i = 0; i < L1NumWrapper; i++) begin + for (genvar j = 0; j < L1Associativity*L1BankFactor; j++) begin + assign l1_cache_wp_req [i][j] = l1_data_bank_req [i + j*L1NumWrapper]; + assign l1_cache_wp_we [i][j] = l1_data_bank_we [i + j*L1NumWrapper]; + assign l1_cache_wp_addr [i][j] = l1_data_bank_addr [i + j*L1NumWrapper]; + assign l1_cache_wp_wdata[i][j] = l1_data_bank_wdata[i + j*L1NumWrapper]; + assign l1_cache_wp_be [i][j] = (l1_data_bank_be [i + j*L1NumWrapper]) ? {(NarrowDataWidth/8){1'b1}} : '0; + + assign l1_data_bank_rdata[i + j*L1NumWrapper] = l1_cache_wp_rdata[i][j]; + assign l1_data_bank_gnt [i + j*L1NumWrapper] = l1_cache_wp_gnt [i][j]; + end + end + + // We have multiple banks form a pesudo bank (BankWP) + spatz_tcdm_interconnect #( + .NumInp (NumTCDMIn ), + .NumOut (L1NumWrapper ), + .tcdm_req_t (spm_req_t ), + .tcdm_rsp_t (spm_rsp_t ), + .mem_req_t (mem_req_t ), + .mem_rsp_t (mem_rsp_t ), + .MemAddrWidth (TCDMMemAddrWidth ), + .DataWidth (DataWidth ), + .user_t (tcdm_user_t ), + .MemoryResponseLatency (1 + RegisterTCDMCuts) + ) i_tcdm_interconnect ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .req_i ({axi_soc_req, spm_req} ), + .rsp_o ({axi_soc_rsp, spm_rsp} ), + .mem_req_o (ic_req ), + .mem_rsp_i (ic_rsp ) + ); + + hive_req_t [NrCores-1:0] hive_req; + hive_rsp_t [NrCores-1:0] hive_rsp; + + for (genvar i = 0; i < NrCores; i++) begin : gen_core + localparam int unsigned TcdmPorts = get_tcdm_ports(i); + localparam int unsigned TcdmPortsOffs = get_tcdm_port_offs(i); + + axi_mst_dma_req_t axi_dma_req; + axi_mst_dma_resp_t axi_dma_res; + interrupts_t irq; + dma_events_t dma_core_events; + + sync #(.STAGES (2)) + i_sync_debug (.clk_i, .rst_ni, .serial_i (debug_req_i[i]), .serial_o (irq.debug)); + sync #(.STAGES (2)) + i_sync_meip (.clk_i, .rst_ni, .serial_i (meip_i[i]), .serial_o (irq.meip)); + sync #(.STAGES (2)) + i_sync_mtip (.clk_i, .rst_ni, .serial_i (mtip_i[i]), .serial_o (irq.mtip)); + sync #(.STAGES (2)) + i_sync_msip (.clk_i, .rst_ni, .serial_i (msip_i[i]), .serial_o (irq.msip)); + assign irq.mcip = cl_interrupt[i]; + + tcdm_req_t [TcdmPorts-1:0] tcdm_req_wo_user; + + logic [31:0] hart_id; + assign hart_id = hart_base_id_i + i; + + spatz_cc #( + .BootAddr (BootAddr ), + .L2Addr (L2Addr ), + .L2Size (L2Size ), + .RVE (1'b0 ), + .RVF (RVF ), + .RVD (RVD ), + .RVV (RVV ), + .Xdma (Xdma[i] ), + .AddrWidth (AxiAddrWidth ), + .DataWidth (NarrowDataWidth ), + .UserWidth (AxiUserWidth ), + .DMADataWidth (AxiDataWidth ), + .DMAIdWidth (AxiIdWidthIn ), + .SnitchPMACfg (SnitchPMACfg ), + .DMAAxiReqFifoDepth (DMAAxiReqFifoDepth ), + .DMAReqFifoDepth (DMAReqFifoDepth ), + .dreq_t (reqrsp_req_t ), + .drsp_t (reqrsp_rsp_t ), + .tcdm_req_t (tcdm_req_t ), + .tcdm_req_chan_t (tcdm_req_chan_t ), + .tcdm_rsp_t (tcdm_rsp_t ), + .tcdm_rsp_chan_t (tcdm_rsp_chan_t ), + .axi_req_t (axi_mst_dma_req_t ), + .axi_ar_chan_t (axi_mst_dma_ar_chan_t ), + .axi_aw_chan_t (axi_mst_dma_aw_chan_t ), + .axi_rsp_t (axi_mst_dma_resp_t ), + .hive_req_t (hive_req_t ), + .hive_rsp_t (hive_rsp_t ), + .acc_issue_req_t (acc_issue_req_t ), + .acc_issue_rsp_t (acc_issue_rsp_t ), + .acc_rsp_t (acc_rsp_t ), + .dma_events_t (dma_events_t ), + .dma_perf_t (axi_dma_pkg::dma_perf_t ), + .XDivSqrt (1'b0 ), + .XF16 (1'b1 ), + .XF16ALT (1'b1 ), + .XF8 (1'b1 ), + .XF8ALT (1'b1 ), + .IsoCrossing (1'b0 ), + .NumIntOutstandingLoads (NumIntOutstandingLoads[i] ), + .NumIntOutstandingMem (NumIntOutstandingMem[i] ), + .NumSpatzOutstandingLoads(NumSpatzOutstandingLoads[i]), + .FPUImplementation (FPUImplementation[i] ), + .RegisterOffloadRsp (RegisterOffloadRsp ), + .RegisterCoreReq (RegisterCoreReq ), + .RegisterCoreRsp (RegisterCoreRsp ), + .NumSpatzFPUs (NumSpatzFPUs ), + .NumSpatzIPUs (NumSpatzIPUs ), + .TCDMAddrWidth (SPMAddrWidth ) + ) i_spatz_cc ( + .clk_i (clk_i ), + .clk_d2_i (clk_i ), + .rst_ni (rst_ni ), + .testmode_i (1'b0 ), + .hart_id_i (hart_id ), + .hive_req_o (hive_req[i] ), + .hive_rsp_i (hive_rsp[i] ), + .irq_i (irq ), + .data_req_o (core_req[i] ), + .data_rsp_i (core_rsp[i] ), + .tcdm_req_o (tcdm_req_wo_user ), + .tcdm_rsp_i (tcdm_rsp[TcdmPortsOffs +: TcdmPorts]), + .axi_dma_req_o (axi_dma_req ), + .axi_dma_res_i (axi_dma_res ), + .axi_dma_busy_o (/* Unused */ ), + .axi_dma_perf_o (/* Unused */ ), + .axi_dma_events_o (dma_core_events ), + .core_events_o (core_events[i] ), + .tcdm_addr_base_i (tcdm_start_address ) + ); + for (genvar j = 0; j < TcdmPorts; j++) begin : gen_tcdm_user + always_comb begin + tcdm_req[TcdmPortsOffs+j].q = tcdm_req_wo_user[j].q; + tcdm_req[TcdmPortsOffs+j].q.user.core_id = i[CoreIDWidth-1:0]; + tcdm_req[TcdmPortsOffs+j].q.user.is_core = 1; + tcdm_req[TcdmPortsOffs+j].q_valid = tcdm_req_wo_user[j].q_valid; + end + end + if (Xdma[i]) begin : gen_dma_connection + assign wide_axi_mst_req[SDMAMst] = axi_dma_req; + assign axi_dma_res = wide_axi_mst_rsp[SDMAMst]; + assign dma_events = dma_core_events; + end else begin + assign axi_dma_res = '0; + end + end + + // ---------------- + // Instruction Cache + // ---------------- + + addr_t [NrCores-1:0] inst_addr; + logic [NrCores-1:0] inst_cacheable; + logic [NrCores-1:0][31:0] inst_data; + logic [NrCores-1:0] inst_valid; + logic [NrCores-1:0] inst_ready; + logic [NrCores-1:0] inst_error; + logic [NrCores-1:0] flush_valid; + logic [NrCores-1:0] flush_ready; + + for (genvar i = 0; i < NrCores; i++) begin : gen_unpack_icache + assign inst_addr[i] = hive_req[i].inst_addr; + assign inst_cacheable[i] = hive_req[i].inst_cacheable; + assign inst_valid[i] = hive_req[i].inst_valid; + assign flush_valid[i] = hive_req[i].flush_i_valid; + assign hive_rsp[i] = '{ + inst_data : inst_data[i], + inst_ready : inst_ready[i], + inst_error : inst_error[i], + flush_i_ready: flush_ready[i], + default : '0 + }; + end + + snitch_icache #( + .NR_FETCH_PORTS ( NrCores ), + .L0_LINE_COUNT ( 8 ), + .LINE_WIDTH ( ICacheLineWidth ), + .LINE_COUNT ( ICacheLineCount ), + .SET_COUNT ( ICacheSets ), + .FETCH_AW ( AxiAddrWidth ), + .FETCH_DW ( 32 ), + .FILL_AW ( AxiAddrWidth ), + .FILL_DW ( AxiDataWidth ), + .EARLY_LATCH ( 0 ), + .L0_EARLY_TAG_WIDTH ( snitch_pkg::PAGE_SHIFT - $clog2(ICacheLineWidth/8) ), + .ISO_CROSSING ( 1'b0 ), + .axi_req_t ( axi_mst_dma_req_t ), + .axi_rsp_t ( axi_mst_dma_resp_t ), + .sram_cfg_data_t ( impl_in_t ), + .sram_cfg_tag_t ( impl_in_t ) + ) i_snitch_icache ( + .clk_i ( clk_i ), + .clk_d2_i ( clk_i ), + .rst_ni ( rst_ni ), + .enable_prefetching_i ( icache_prefetch_enable ), + .icache_events_o ( icache_events ), + .flush_valid_i ( flush_valid ), + .flush_ready_o ( flush_ready ), + .inst_addr_i ( inst_addr ), + .inst_cacheable_i ( inst_cacheable ), + .inst_data_o ( inst_data ), + .inst_valid_i ( inst_valid ), + .inst_ready_o ( inst_ready ), + .inst_error_o ( inst_error ), + .sram_cfg_tag_i ( impl_l1i_tag ), + .sram_cfg_data_i ( impl_l1i_data ), + .axi_req_o ( wide_axi_mst_req[ICache] ), + .axi_rsp_i ( wide_axi_mst_rsp[ICache] ) + ); + + // -------- + // Cores SoC + // -------- + spatz_barrier #( + .AddrWidth (AxiAddrWidth ), + .NrPorts (NrCores ), + .dreq_t (reqrsp_req_t ), + .drsp_t (reqrsp_rsp_t ) + ) i_snitch_barrier ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .in_req_i (core_req ), + .in_rsp_o (core_rsp ), + .out_req_o (filtered_core_req ), + .out_rsp_i (filtered_core_rsp ), + .cluster_periph_start_address_i (cluster_periph_start_address) + ); + + reqrsp_req_t core_to_axi_req; + reqrsp_rsp_t core_to_axi_rsp; + user_t cluster_user; + // Atomic ID, needs to be unique ID of cluster + // cluster_id + HartIdOffset + 1 (because 0 is for non-atomic masters) + assign cluster_user = (hart_base_id_i / NrCores) + (hart_base_id_i % NrCores) + 1'b1; + + reqrsp_mux #( + .NrPorts (NrCores ), + .AddrWidth (AxiAddrWidth ), + .DataWidth (NarrowDataWidth ), + .req_t (reqrsp_req_t ), + .rsp_t (reqrsp_rsp_t ), + .RespDepth (2 ) + ) i_reqrsp_mux_core ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (filtered_core_req), + .slv_rsp_o (filtered_core_rsp), + .mst_req_o (core_to_axi_req ), + .mst_rsp_i (core_to_axi_rsp ), + .idx_o (/*unused*/ ) + ); + + reqrsp_to_axi #( + .DataWidth (NarrowDataWidth), + .UserWidth (NarrowUserWidth), + .reqrsp_req_t (reqrsp_req_t ), + .reqrsp_rsp_t (reqrsp_rsp_t ), + .axi_req_t (axi_mst_req_t ), + .axi_rsp_t (axi_mst_resp_t ) + ) i_reqrsp_to_axi_core ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .user_i (cluster_user ), + .reqrsp_req_i (core_to_axi_req ), + .reqrsp_rsp_o (core_to_axi_rsp ), + .axi_req_o (narrow_axi_mst_req[CoreReq]), + .axi_rsp_i (narrow_axi_mst_rsp[CoreReq]) + ); + + xbar_rule_t [NrNarrowRules-1:0] cluster_xbar_rules; + + assign cluster_xbar_rules = '{ + '{ + idx : TCDM, + start_addr: tcdm_start_address, + end_addr : tcdm_end_address + }, + '{ + idx : ClusterPeripherals, + start_addr: cluster_periph_start_address, + end_addr : cluster_periph_end_address + } + }; + + localparam bit [ClusterXbarCfg.NoSlvPorts-1:0] ClusterEnableDefaultMstPort = '1; + localparam logic [ClusterXbarCfg.NoSlvPorts-1:0][cf_math_pkg::idx_width(ClusterXbarCfg.NoMstPorts)-1:0] ClusterXbarDefaultPort = '{default: SoC}; + + axi_xbar #( + .Cfg (ClusterXbarCfg ), + .slv_aw_chan_t (axi_mst_aw_chan_t), + .mst_aw_chan_t (axi_slv_aw_chan_t), + .w_chan_t (axi_mst_w_chan_t ), + .slv_b_chan_t (axi_mst_b_chan_t ), + .mst_b_chan_t (axi_slv_b_chan_t ), + .slv_ar_chan_t (axi_mst_ar_chan_t), + .mst_ar_chan_t (axi_slv_ar_chan_t), + .slv_r_chan_t (axi_mst_r_chan_t ), + .mst_r_chan_t (axi_slv_r_chan_t ), + .slv_req_t (axi_mst_req_t ), + .slv_resp_t (axi_mst_resp_t ), + .mst_req_t (axi_slv_req_t ), + .mst_resp_t (axi_slv_resp_t ), + .rule_t (xbar_rule_t ) + ) i_cluster_xbar ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .test_i (1'b0 ), + .slv_ports_req_i (narrow_axi_mst_req ), + .slv_ports_resp_o (narrow_axi_mst_rsp ), + .mst_ports_req_o (narrow_axi_slv_req ), + .mst_ports_resp_i (narrow_axi_slv_rsp ), + .addr_map_i (cluster_xbar_rules ), + .en_default_mst_port_i (ClusterEnableDefaultMstPort), + .default_mst_port_i (ClusterXbarDefaultPort ) + ); + + // --------- + // Slaves + // --------- + // 1. TCDM + // Add an adapter that allows access from AXI to the TCDM. + axi_to_tcdm #( + .axi_req_t (axi_slv_req_t ), + .axi_rsp_t (axi_slv_resp_t ), + .tcdm_req_t (spm_req_t ), + .tcdm_rsp_t (spm_rsp_t ), + .AddrWidth (AxiAddrWidth ), + .DataWidth (NarrowDataWidth ), + .IdWidth (NarrowIdWidthOut ), + .BufDepth (MemoryMacroLatency + 1) + ) i_axi_to_tcdm ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .axi_req_i (narrow_axi_slv_req[TCDM]), + .axi_rsp_o (narrow_axi_slv_rsp[TCDM]), + .tcdm_req_o (axi_soc_req ), + .tcdm_rsp_i (axi_soc_rsp ) + ); + + // 2. Peripherals + axi_to_reg #( + .ADDR_WIDTH (AxiAddrWidth ), + .DATA_WIDTH (NarrowDataWidth ), + .AXI_MAX_WRITE_TXNS (1 ), + .AXI_MAX_READ_TXNS (1 ), + .DECOUPLE_W (0 ), + .ID_WIDTH (NarrowIdWidthOut ), + .USER_WIDTH (NarrowUserWidth ), + .axi_req_t (axi_slv_req_t ), + .axi_rsp_t (axi_slv_resp_t ), + .reg_req_t (reg_req_t ), + .reg_rsp_t (reg_rsp_t ) + ) i_axi_to_reg ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .testmode_i (1'b0 ), + .axi_req_i (narrow_axi_slv_req[ClusterPeripherals]), + .axi_rsp_o (narrow_axi_slv_rsp[ClusterPeripherals]), + .reg_req_o (reg_req ), + .reg_rsp_i (reg_rsp ) + ); + + spatz_cluster_peripheral #( + .AddrWidth (AxiAddrWidth ), + .SPMWidth ($clog2(L1NumSet)), + .reg_req_t (reg_req_t ), + .reg_rsp_t (reg_rsp_t ), + .tcdm_events_t (tcdm_events_t ), + .dma_events_t (dma_events_t ), + .NrCores (NrCores ) + ) i_snitch_cluster_peripheral ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .reg_req_i (reg_req ), + .reg_rsp_o (reg_rsp ), + /// The TCDM always starts at the cluster base. + .tcdm_start_address_i (tcdm_start_address ), + .tcdm_end_address_i (tcdm_end_address ), + .icache_prefetch_enable_o (icache_prefetch_enable), + .cl_clint_o (cl_interrupt ), + .cluster_hart_base_id_i (hart_base_id_i ), + .core_events_i (core_events ), + .tcdm_events_i (tcdm_events ), + .dma_events_i (dma_events ), + .icache_events_i (icache_events ), + .cluster_probe_o (cluster_probe_o ), + .l1d_spm_size_o (cfg_spm_size ), + .l1d_insn_o (l1d_insn ), + .l1d_insn_valid_o (l1d_insn_valid ), + .l1d_insn_ready_i (l1d_insn_ready ), + .l1d_busy_o (l1d_busy ) + ); + + // 3. BootROM + axi_to_reg #( + .ADDR_WIDTH (AxiAddrWidth ), + .DATA_WIDTH (AxiDataWidth ), + .AXI_MAX_WRITE_TXNS (1 ), + .AXI_MAX_READ_TXNS (1 ), + .DECOUPLE_W (0 ), + .ID_WIDTH (WideIdWidthOut ), + .USER_WIDTH (AxiUserWidth ), + .axi_req_t (axi_slv_dma_req_t ), + .axi_rsp_t (axi_slv_dma_resp_t), + .reg_req_t (reg_dma_req_t ), + .reg_rsp_t (reg_dma_rsp_t ) + ) i_axi_to_reg_bootrom ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .testmode_i (1'b0 ), + .axi_req_i (wide_axi_slv_req[BootROM]), + .axi_rsp_o (wide_axi_slv_rsp[BootROM]), + .reg_req_o (bootrom_reg_req ), + .reg_rsp_i (bootrom_reg_rsp ) + ); + + bootrom i_bootrom ( + .clk_i (clk_i ), + .req_i (bootrom_reg_req.valid ), + .addr_i (addr_t'(bootrom_reg_req.addr)), + .rdata_o(bootrom_reg_rsp.rdata ) + ); + `FF(bootrom_reg_rsp.ready, bootrom_reg_req.valid, 1'b0) + assign bootrom_reg_rsp.error = 1'b0; + + // Upsize the narrow SoC connection + `AXI_TYPEDEF_ALL(axi_mst_dma_narrow, addr_t, id_dma_mst_t, data_t, strb_t, user_t) + axi_mst_dma_narrow_req_t narrow_axi_slv_req_soc; + axi_mst_dma_narrow_resp_t narrow_axi_slv_resp_soc; + + axi_iw_converter #( + .AxiAddrWidth (AxiAddrWidth ), + .AxiDataWidth (NarrowDataWidth ), + .AxiUserWidth (AxiUserWidth ), + .AxiSlvPortIdWidth (NarrowIdWidthOut ), + .AxiSlvPortMaxUniqIds (1 ), + .AxiSlvPortMaxTxnsPerId(1 ), + .AxiSlvPortMaxTxns (1 ), + .AxiMstPortIdWidth (WideIdWidthIn ), + .AxiMstPortMaxUniqIds (1 ), + .AxiMstPortMaxTxnsPerId(1 ), + .slv_req_t (axi_slv_req_t ), + .slv_resp_t (axi_slv_resp_t ), + .mst_req_t (axi_mst_dma_narrow_req_t ), + .mst_resp_t (axi_mst_dma_narrow_resp_t) + ) i_soc_port_iw_convert ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (narrow_axi_slv_req[SoC] ), + .slv_resp_o (narrow_axi_slv_rsp[SoC] ), + .mst_req_o (narrow_axi_slv_req_soc ), + .mst_resp_i (narrow_axi_slv_resp_soc ) + ); + + axi_dw_converter #( + .AxiAddrWidth (AxiAddrWidth ), + .AxiIdWidth (WideIdWidthIn ), + .AxiMaxReads (2 ), + .AxiSlvPortDataWidth(NarrowDataWidth ), + .AxiMstPortDataWidth(AxiDataWidth ), + .ar_chan_t (axi_mst_dma_ar_chan_t ), + .aw_chan_t (axi_mst_dma_aw_chan_t ), + .b_chan_t (axi_mst_dma_b_chan_t ), + .slv_r_chan_t (axi_mst_dma_narrow_r_chan_t), + .slv_w_chan_t (axi_mst_dma_narrow_b_chan_t), + .axi_slv_req_t (axi_mst_dma_narrow_req_t ), + .axi_slv_resp_t (axi_mst_dma_narrow_resp_t ), + .mst_r_chan_t (axi_mst_dma_r_chan_t ), + .mst_w_chan_t (axi_mst_dma_w_chan_t ), + .axi_mst_req_t (axi_mst_dma_req_t ), + .axi_mst_resp_t (axi_mst_dma_resp_t ) + ) i_soc_port_dw_upsize ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .slv_req_i (narrow_axi_slv_req_soc ), + .slv_resp_o (narrow_axi_slv_resp_soc ), + .mst_req_o (wide_axi_mst_req[CoreReqWide]), + .mst_resp_i (wide_axi_mst_rsp[CoreReqWide]) + ); + + // -------------------- + // TCDM event counters + // -------------------- + logic [NrTCDMPortsCores-1:0] flat_acc, flat_con; + for (genvar i = 0; i < NrTCDMPortsCores; i++) begin : gen_event_counter + `FFARN(flat_acc[i], tcdm_req[i].q_valid, '0, clk_i, rst_ni) + `FFARN(flat_con[i], tcdm_req[i].q_valid & ~tcdm_rsp[i].q_ready, '0, clk_i, rst_ni) + end + + popcount #( + .INPUT_WIDTH ( NrTCDMPortsCores ) + ) i_popcount_req ( + .data_i ( flat_acc ), + .popcount_o ( tcdm_events.inc_accessed ) + ); + + popcount #( + .INPUT_WIDTH ( NrTCDMPortsCores ) + ) i_popcount_con ( + .data_i ( flat_con ), + .popcount_o ( tcdm_events.inc_congested ) + ); + + // ------------- + // Sanity Checks + // ------------- + // Sanity check the parameters. Not every configuration makes sense. + `ASSERT_INIT(CheckSuperBankSanity, NrBanks >= BanksPerSuperBank); + `ASSERT_INIT(CheckSuperBankFactor, (NrBanks % BanksPerSuperBank) == 0); + // Check that the cluster base address aligns to the TCDMSize. + `ASSERT(ClusterBaseAddrAlign, ((TCDMSize - 1) & cluster_base_addr_i) == 0) + // Make sure we only have one DMA in the system. + `ASSERT_INIT(NumberDMA, $onehot0(Xdma)) + +endmodule diff --git a/hardware/tb/cachepool_cluster_wrapper.sv b/hardware/tb/cachepool_cluster_wrapper.sv new file mode 100644 index 0000000..8fe36ad --- /dev/null +++ b/hardware/tb/cachepool_cluster_wrapper.sv @@ -0,0 +1,176 @@ +// Copyright 2021 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + + + +`include "axi/typedef.svh" + +module cachepool_cluster_wrapper + import cachepool_pkg::*; + import fpnew_pkg::fpu_implementation_t; + import snitch_pma_pkg::snitch_pma_t; + #( + parameter int unsigned AxiAddrWidth = SpatzAxiAddrWidth, + parameter int unsigned AxiDataWidth = SpatzAxiDataWidth, + parameter int unsigned AxiUserWidth = SpatzAxiUserWidth, + parameter int unsigned AxiInIdWidth = SpatzAxiIdInWidth, + parameter int unsigned AxiOutIdWidth = SpatzAxiIdOutWidth, + + parameter type axi_in_resp_t = spatz_axi_in_resp_t, + parameter type axi_in_req_t = spatz_axi_in_req_t, + + parameter type axi_out_resp_t = spatz_axi_out_resp_t, + parameter type axi_out_req_t = spatz_axi_out_req_t +)( + input logic clk_i, + input logic rst_ni, + input logic [NumCores-1:0] debug_req_i, + + input logic [NumCores-1:0] meip_i, + input logic [NumCores-1:0] mtip_i, + input logic [NumCores-1:0] msip_i, + output logic cluster_probe_o, + input axi_in_req_t axi_in_req_i, + output axi_in_resp_t axi_in_resp_o, + output axi_out_req_t axi_out_req_o, + input axi_out_resp_t axi_out_resp_i, + output axi_out_req_t axi_out_l2_req_o, + input axi_out_resp_t axi_out_l2_resp_i +); + + localparam int unsigned NumIntOutstandingLoads [NumCores] = '{default: 4}; + localparam int unsigned NumIntOutstandingMem [NumCores] = '{default: 4}; + localparam int unsigned NumSpatzOutstandingLoads [NumCores] = '{default: 16}; + + spatz_axi_iwc_out_req_t axi_from_cluster_iwc_req; + spatz_axi_iwc_out_resp_t axi_from_cluster_iwc_resp; + spatz_axi_iwc_out_req_t axi_from_cluster_l2_req; + spatz_axi_iwc_out_resp_t axi_from_cluster_l2_resp; + + axi_iw_converter #( + .AxiSlvPortIdWidth ( IwcAxiIdOutWidth ), + .AxiMstPortIdWidth ( AxiOutIdWidth ), + .AxiSlvPortMaxUniqIds ( 2 ), + .AxiSlvPortMaxTxnsPerId ( 2 ), + .AxiSlvPortMaxTxns ( 4 ), + .AxiMstPortMaxUniqIds ( 2 ), + .AxiMstPortMaxTxnsPerId ( 4 ), + .AxiAddrWidth ( AxiAddrWidth ), + .AxiDataWidth ( AxiDataWidth ), + .AxiUserWidth ( AxiUserWidth ), + .slv_req_t ( spatz_axi_iwc_out_req_t ), + .slv_resp_t ( spatz_axi_iwc_out_resp_t), + .mst_req_t ( axi_out_req_t ), + .mst_resp_t ( axi_out_resp_t ) + ) iw_converter( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .slv_req_i ( axi_from_cluster_iwc_req ), + .slv_resp_o ( axi_from_cluster_iwc_resp ), + .mst_req_o ( axi_out_req_o ), + .mst_resp_i ( axi_out_resp_i ) + ); + + axi_iw_converter #( + .AxiSlvPortIdWidth ( IwcAxiIdOutWidth ), + .AxiMstPortIdWidth ( AxiOutIdWidth ), + .AxiSlvPortMaxUniqIds ( 2 ), + .AxiSlvPortMaxTxnsPerId ( 2 ), + .AxiSlvPortMaxTxns ( 4 ), + .AxiMstPortMaxUniqIds ( 2 ), + .AxiMstPortMaxTxnsPerId ( 4 ), + .AxiAddrWidth ( AxiAddrWidth ), + .AxiDataWidth ( AxiDataWidth ), + .AxiUserWidth ( AxiUserWidth ), + .slv_req_t ( spatz_axi_iwc_out_req_t ), + .slv_resp_t ( spatz_axi_iwc_out_resp_t), + .mst_req_t ( axi_out_req_t ), + .mst_resp_t ( axi_out_resp_t ) + ) iw_converter_l2( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .slv_req_i ( axi_from_cluster_l2_req ), + .slv_resp_o ( axi_from_cluster_l2_resp ), + .mst_req_o ( axi_out_l2_req_o ), + .mst_resp_i ( axi_out_l2_resp_i ) + ); + + // Spatz cluster under test. + cachepool_cluster_simple #( + .AxiAddrWidth (AxiAddrWidth ), + .AxiDataWidth (AxiDataWidth ), + .AxiIdWidthIn (AxiInIdWidth ), + .AxiIdWidthOut (IwcAxiIdOutWidth ), + .AxiUserWidth (AxiUserWidth ), + .BootAddr (BootAddr ), + .L2Addr (L2Addr ), + .L2Size (L2Size ), + .ClusterPeriphSize (64 ), + .NrCores (NumCores ), + .TCDMDepth (1024 ), + .NrBanks (16 ), + .ICacheLineWidth (ICacheLineWidth ), + .ICacheLineCount (ICacheLineCount ), + .ICacheSets (ICacheSets ), + .FPUImplementation (FPUImplementation ), + .NumSpatzFPUs (NFpu ), + .NumSpatzIPUs (NIpu ), + .SnitchPMACfg (SnitchPMACfg ), + .NumIntOutstandingLoads (NumIntOutstandingLoads ), + .NumIntOutstandingMem (NumIntOutstandingMem ), + .NumSpatzOutstandingLoads (NumSpatzOutstandingLoads ), + .axi_in_req_t (axi_in_req_t ), + .axi_in_resp_t (axi_in_resp_t ), + .axi_out_req_t (spatz_axi_iwc_out_req_t ), + .axi_out_resp_t (spatz_axi_iwc_out_resp_t ), + .Xdma (4'h1 ), + .DMAAxiReqFifoDepth (3 ), + .DMAReqFifoDepth (3 ), + .RegisterOffloadRsp (1 ), + .RegisterCoreReq (1 ), + .RegisterCoreRsp (1 ), + .RegisterTCDMCuts (1 ), + .RegisterExt (0 ), + .XbarLatency (axi_pkg::CUT_ALL_PORTS ), + .MaxMstTrans (4 ), + .MaxSlvTrans (4 ) + ) i_cluster ( + .clk_i, + .rst_ni, + .impl_i( '0 ), + .error_o(), + .debug_req_i, + .meip_i, + .mtip_i, + .msip_i, + .hart_base_id_i (10'h10), + .cluster_base_addr_i (TCDMStartAddr), + .cluster_probe_o, + .axi_in_req_i, + .axi_in_resp_o, + // AXI Master Port + .axi_out_req_o ( axi_from_cluster_iwc_req ), + .axi_out_resp_i ( axi_from_cluster_iwc_resp ), + .axi_out_l2_req_o ( axi_from_cluster_l2_req ), + .axi_out_l2_resp_i ( axi_from_cluster_l2_resp ) + ); + + // Assertions + + if (AxiAddrWidth != SpatzAxiAddrWidth) + $error("[spatz_cluster_wrapper] AXI Address Width does not match the configuration."); + + if (AxiDataWidth != SpatzAxiDataWidth) + $error("[spatz_cluster_wrapper] AXI Data Width does not match the configuration."); + + if (AxiUserWidth != SpatzAxiUserWidth) + $error("[spatz_cluster_wrapper] AXI User Width does not match the configuration."); + + if (AxiInIdWidth != SpatzAxiIdInWidth) + $error("[spatz_cluster_wrapper] AXI Id Width (In) does not match the configuration."); + + if (AxiOutIdWidth != SpatzAxiIdOutWidth) + $error("[spatz_cluster_wrapper] AXI Id Width (Out) does not match the configuration."); + +endmodule diff --git a/hardware/tb/testharness.sv b/hardware/tb/testharness.sv new file mode 100644 index 0000000..4c174b6 --- /dev/null +++ b/hardware/tb/testharness.sv @@ -0,0 +1,203 @@ +// Copyright 2021 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +`define wait_for(signal) do @(negedge clk_i); while (!signal); + +`include "axi/assign.svh" +`include "axi/typedef.svh" +`include "reqrsp_interface/typedef.svh" + +module testharness ( + input logic clk_i, + input logic rst_ni + ); + + import cachepool_pkg::*; + import spatz_cluster_peripheral_reg_pkg::*; + import axi_pkg::xbar_cfg_t; + import axi_pkg::xbar_rule_32_t; + + import "DPI-C" function int get_entry_point(); + + /********* + * AXI * + *********/ + + localparam NumAXISlaves = 2; + localparam NumRules = NumAXISlaves-1; + + // Spatz wide port to SoC (currently dram) + spatz_axi_out_req_t axi_from_cluster_req; + spatz_axi_out_resp_t axi_from_cluster_resp; + // Spatz wide port to L2 + spatz_axi_out_req_t axi_l2_req; + spatz_axi_out_resp_t axi_l2_resp; + // From SoC to Spatz + spatz_axi_in_req_t axi_to_cluster_req; + spatz_axi_in_resp_t axi_to_cluster_resp; + + + /********* + * DUT * + *********/ + + logic cluster_probe; + logic [NumCores-1:0] debug_req; + + cachepool_cluster_wrapper i_cluster_wrapper ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .meip_i ('0 ), + .msip_i ('0 ), + .mtip_i ('0 ), + .debug_req_i ( debug_req ), + .axi_out_req_o (axi_from_cluster_req ), + .axi_out_resp_i (axi_from_cluster_resp), + .axi_out_l2_req_o ( axi_l2_req ), + .axi_out_l2_resp_i ( axi_l2_resp ), + .axi_in_req_i (axi_to_cluster_req ), + .axi_in_resp_o (axi_to_cluster_resp ), + .cluster_probe_o (cluster_probe ) + ); +/************** + * VCD Dump * + **************/ + +`ifdef VCD_DUMP + initial begin: vcd_dump + // Wait for the reset + wait (rst_ni); + + // Wait until the probe is high + while (!cluster_probe) + @(posedge clk_i); + + // Dump signals of group 0 + $dumpfile(`VCD_DUMP_FILE); + $dumpvars(0, i_cluster_wrapper); + $dumpon; + + // Wait until the probe is low + while (cluster_probe) + @(posedge clk_i); + + $dumpoff; + + // Stop the execution + $finish(0); + end: vcd_dump +`endif + + /************************ + * Simulation control * + ************************/ + + `REQRSP_TYPEDEF_ALL(reqrsp_cluster_in, axi_addr_t, logic [63:0], logic [7:0]) + reqrsp_cluster_in_req_t to_cluster_req; + reqrsp_cluster_in_rsp_t to_cluster_rsp; + + reqrsp_to_axi #( + .DataWidth (DataWidth ), + .UserWidth (SpatzAxiUserWidth ), + .axi_req_t (spatz_axi_in_req_t ), + .axi_rsp_t (spatz_axi_in_resp_t ), + .reqrsp_req_t(reqrsp_cluster_in_req_t), + .reqrsp_rsp_t(reqrsp_cluster_in_rsp_t) + ) i_axi_to_reqrsp ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .user_i ('0 ), + .axi_req_o (axi_to_cluster_req ), + .axi_rsp_i (axi_to_cluster_resp), + .reqrsp_req_i(to_cluster_req ), + .reqrsp_rsp_o(to_cluster_rsp ) + ); + + logic [31:0] entry_point; + initial begin + // Idle + to_cluster_req = '0; + debug_req = '0; + + // Wait for a while + repeat (10) + @(negedge clk_i); + + // Load the entry point + entry_point = get_entry_point(); + $display("Loading entry point: %0x", entry_point); + + // Wait for a while + repeat (1000) + @(negedge clk_i); + + // Store the entry point in the Spatz cluster + to_cluster_req = '{ + q: '{ + addr : PeriStartAddr + SPATZ_CLUSTER_PERIPHERAL_CLUSTER_BOOT_CONTROL_OFFSET, + data : {32'b0, entry_point}, + write : 1'b1, + strb : '1, + amo : reqrsp_pkg::AMONone, + default: '0 + }, + q_valid: 1'b1, + p_ready: 1'b0 + }; + `wait_for(to_cluster_rsp.q_ready); + to_cluster_req = '0; + `wait_for(to_cluster_rsp.p_valid); + to_cluster_req = '{ + p_ready: 1'b1, + q : '{ + amo : reqrsp_pkg::AMONone, + default: '0 + }, + default: '0 + }; + @(negedge clk_i); + to_cluster_req = '0; + + + // Wake up cores + debug_req = '1; + @(negedge clk_i); + debug_req = '0; + end + + /******** + * L2 * + ********/ + + // Wide port into simulation memory. + tb_memory_axi #( + .AxiAddrWidth ( SpatzAxiAddrWidth ), + .AxiDataWidth ( SpatzAxiDataWidth ), + .AxiIdWidth ( SpatzAxiIdOutWidth ), + .AxiUserWidth ( SpatzAxiUserWidth ), + .req_t ( spatz_axi_out_req_t ), + .rsp_t ( spatz_axi_out_resp_t ) + ) i_dma ( + .clk_i (clk_i ), + .rst_ni(rst_ni ), + .req_i (axi_from_cluster_req ), + .rsp_o (axi_from_cluster_resp) + ); + + // Wide port into simulation memory. + tb_memory_axi #( + .AxiAddrWidth ( SpatzAxiAddrWidth ), + .AxiDataWidth ( SpatzAxiDataWidth ), + .AxiIdWidth ( SpatzAxiIdOutWidth ), + .AxiUserWidth ( SpatzAxiUserWidth ), + .req_t ( spatz_axi_out_req_t ), + .rsp_t ( spatz_axi_out_resp_t ) + ) i_l2mem ( + .clk_i (clk_i ), + .rst_ni(rst_ni ), + .req_i (axi_l2_req ), + .rsp_o (axi_l2_resp ) + ); + +endmodule : testharness diff --git a/software/.gitignore b/software/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/software/.gitignore @@ -0,0 +1 @@ +build/ From 99448ede91c85ee327c07af5da3405087ddb8508 Mon Sep 17 00:00:00 2001 From: Diyou Shen Date: Wed, 23 Apr 2025 10:59:44 +0200 Subject: [PATCH 02/17] [Spatz] Update Spatz and add spin-lock tests. --- Makefile | 9 +- hardware/deps/spatz | 2 +- hardware/src/cachepool_cluster_simple.sv | 168 +++++++---------------- hardware/src/cachepool_pkg.sv | 77 +++++++---- hardware/tb/cachepool_cluster_wrapper.sv | 6 +- hardware/tb/testharness.sv | 2 +- software/tests/CMakeLists.txt | 29 ++++ software/tests/spin-lock/main.c | 88 ++++++++++++ 8 files changed, 232 insertions(+), 149 deletions(-) create mode 100644 software/tests/CMakeLists.txt create mode 100644 software/tests/spin-lock/main.c diff --git a/Makefile b/Makefile index 10bdc49..90515ed 100644 --- a/Makefile +++ b/Makefile @@ -93,6 +93,7 @@ VLOG_FLAGS += -64 USE_CACHE ?= 1 USE_PRINT ?= 1 +ENABLE_CACHEPOOL_TESTS ?= 1 ############ @@ -101,7 +102,9 @@ USE_PRINT ?= 1 # Currently highjack the simulation flow from spatz .PHONY: sw sw: - make -BC $(SPATZ_DIR)/hw/system/spatz_cluster sw DEFS="-t cachepool" USE_CACHE=$(USE_CACHE) ENABLE_PRINT=$(USE_PRINT) + make -BC $(SPATZ_DIR)/hw/system/spatz_cluster sw DEFS="-t cachepool" \ + USE_CACHE=$(USE_CACHE) ENABLE_PRINT=$(USE_PRINT) \ + ENABLE_CACHEPOOL_TESTS=$(ENABLE_CACHEPOOL_TESTS) CACHEPOOL_DIR=$(CACHEPOOL_DIR) rm -rf ${ROOT_DIR}/${SOFTWARE_DIR}/build mkdir -p ${ROOT_DIR}/${SOFTWARE_DIR}/build cp -r $(SPATZ_DIR)/hw/system/spatz_cluster/sw/build ${ROOT_DIR}/${SOFTWARE_DIR}/ @@ -109,7 +112,9 @@ sw: .PHONY: vsim vsim: - make -BC $(SPATZ_DIR)/hw/system/spatz_cluster sw.vsim DEFS="-t cachepool" USE_CACHE=$(USE_CACHE) ENABLE_PRINT=$(USE_PRINT) + make -BC $(SPATZ_DIR)/hw/system/spatz_cluster sw.vsim DEFS="-t cachepool" \ + USE_CACHE=$(USE_CACHE) ENABLE_PRINT=$(USE_PRINT) \ + ENABLE_CACHEPOOL_TESTS=$(ENABLE_CACHEPOOL_TESTS) CACHEPOOL_DIR=$(CACHEPOOL_DIR) rm -rf bin mkdir -p bin cp -r $(SPATZ_DIR)/hw/system/spatz_cluster/bin/* bin/ diff --git a/hardware/deps/spatz b/hardware/deps/spatz index 42b9d42..a2c3e83 160000 --- a/hardware/deps/spatz +++ b/hardware/deps/spatz @@ -1 +1 @@ -Subproject commit 42b9d423234629fccee981418f2b12f86df96b52 +Subproject commit a2c3e8329992f8264f7507fe0f3aa5b5350e772f diff --git a/hardware/src/cachepool_cluster_simple.sv b/hardware/src/cachepool_cluster_simple.sv index 4f62f90..274186a 100644 --- a/hardware/src/cachepool_cluster_simple.sv +++ b/hardware/src/cachepool_cluster_simple.sv @@ -20,7 +20,7 @@ /// A single-tile cluster implementation for CachePool module cachepool_cluster_simple - // import cachepool_pkg::*; + import cachepool_pkg::*; import spatz_pkg::*; import fpnew_pkg::fpu_implementation_t; import snitch_pma_pkg::snitch_pma_t; @@ -162,7 +162,7 @@ module cachepool_cluster_simple /// Minimum width to hold the core number. localparam int unsigned CoreIDWidth = cf_math_pkg::idx_width(NrCores); localparam int unsigned TCDMMemAddrWidth = $clog2(TCDMDepth); - localparam int unsigned TCDMSize = NrBanks * TCDMDepth * (DataWidth/8); + localparam int unsigned TCDMSize = NrBanks * TCDMDepth * BeWidth; // The short address for SPM localparam int unsigned SPMAddrWidth = $clog2(TCDMSize); // Enlarge the address width for Spatz due to cache @@ -240,47 +240,6 @@ module cachepool_cluster_simple default : '0 }; - /*********** TODO: Move into package ***********/ - // Address width of cache - localparam int unsigned L1AddrWidth = 32; - // Cache lane width - localparam int unsigned L1LineWidth = AxiDataWidth; - // Coalecser window - localparam int unsigned L1CoalFactor = 2; - // Total number of Data banks - localparam int unsigned L1NumDataBank = 128; - // Number of bank wraps SPM can see - localparam int unsigned L1NumWrapper = NrBanks; - // SPM view: Number of banks in each bank wrap (Use to mitigate routing complexity of such many banks) - localparam int unsigned L1BankPerWP = L1NumDataBank / NrBanks; - // Pesudo dual bank - localparam int unsigned L1BankFactor = 2; - // Cache ways (total way number across multiple cache controllers) - localparam int unsigned L1Associativity = L1NumDataBank / (L1LineWidth / DataWidth) / L1BankFactor; - // 8 * 1024 * 64 / 512 = 1024) - // Number of entrys of L1 Cache (total number across multiple cache controllers) - localparam int unsigned L1NumEntry = NrBanks * TCDMDepth * DataWidth / L1LineWidth; - // Number of cache entries each cache way has - localparam int unsigned L1CacheWayEntry = L1NumEntry / L1Associativity; - // Number of cache sets each cache way has - localparam int unsigned L1NumSet = L1CacheWayEntry / L1BankFactor; - // Number of Tag banks - localparam int unsigned L1NumTagBank = L1BankFactor * L1Associativity; - // Number of lines per bank unit - localparam int unsigned DepthPerBank = TCDMDepth / L1BankPerWP; - // Cache total size in KB - localparam int unsigned L1Size = NrBanks * TCDMDepth * DataWidth / 8 / 1024; - // Number of cache controller (now is fixde to NrCores (if we change it, we need to change the controller axi output id width too) - localparam int unsigned NumL1CacheCtrl = NrCores; - // Number of data banks assigned to each cache controller - localparam int unsigned NumDataBankPerCtrl = L1NumDataBank / NumL1CacheCtrl; - // Number of tag banks assigned to each cache controller - localparam int unsigned NumTagBankPerCtrl = L1NumTagBank / NumL1CacheCtrl; - // Number of ways per cache controller - localparam int unsigned L1AssoPerCtrl = L1Associativity / NumL1CacheCtrl; - // Number of entries per cache controller - localparam int unsigned L1NumEntryPerCtrl = L1NumEntry / NumL1CacheCtrl; - // -------- // Typedefs // -------- @@ -309,6 +268,7 @@ module cachepool_cluster_simple typedef struct packed { logic [CoreIDWidth-1:0] core_id; logic is_core; + logic is_amo; reqid_t req_id; } tcdm_user_t; @@ -507,8 +467,8 @@ module cachepool_cluster_simple tcdm_req_t [NrTCDMPortsCores-1:0] unmerge_req, strb_hdl_req; tcdm_rsp_t [NrTCDMPortsCores-1:0] unmerge_rsp, strb_hdl_rsp; - tcdm_req_t [NrTCDMPortsPerCore-1:0][NumL1CacheCtrl-1:0] cache_req, cache_xbar_req; - tcdm_rsp_t [NrTCDMPortsPerCore-1:0][NumL1CacheCtrl-1:0] cache_rsp, cache_xbar_rsp; + tcdm_req_t [NrTCDMPortsPerCore-1:0][NumL1CacheCtrl-1:0] cache_req, cache_xbar_req, cache_amo_req; + tcdm_rsp_t [NrTCDMPortsPerCore-1:0][NumL1CacheCtrl-1:0] cache_rsp, cache_xbar_rsp, cache_amo_rsp; logic [NumL1CacheCtrl-1:0][NrTCDMPortsPerCore-1:0] cache_req_valid; logic [NumL1CacheCtrl-1:0][NrTCDMPortsPerCore-1:0] cache_req_ready; @@ -873,10 +833,7 @@ module cachepool_cluster_simple end logic [NrTCDMPortsCores-1:0] unmerge_pready, strb_hdl_pready; - logic [NrTCDMPortsPerCore-1:0][NumL1CacheCtrl-1:0] cache_pready, cache_xbar_pready; - // Currently assume SPM is full 128 KiB - // assign spm_size = 128 * 1024; - // assign spm_size = cfg_spm_size * 1024; + logic [NrTCDMPortsPerCore-1:0][NumL1CacheCtrl-1:0] cache_pready, cache_xbar_pready, cache_amo_pready; // split the requests for spm or cache from core side spatz_addr_mapper #( @@ -909,47 +866,8 @@ module cachepool_cluster_simple .cache_rsp_i (unmerge_rsp ) ); - - // spatz_strbreq_merge_tree #( - // .NumIO (NrTCDMPortsCores ), - // .NumOutstandingMem (NumSpatzOutstandingLoads[0] ), - // .MergeNum (NrTCDMPortsCores - NrCores ), - // .DataWidth (DataWidth ), - // .mem_req_t (tcdm_req_t ), - // .mem_rsp_t (tcdm_rsp_t ), - // .req_id_t (reqid_t ), - // .tcdm_user_t (tcdm_user_t ) - // ) i_strbreq_merge_tree ( - // .clk_i (clk_i), - // .rst_ni (rst_ni), - // .unmerge_req_i (unmerge_req ), - // .unmerge_pready_i(unmerge_pready ), - // .merge_rsp_i (strb_hdl_rsp ), - // .merge_req_o (strb_hdl_req ), - // .merge_pready_o (strb_hdl_pready ), - // .unmerge_rsp_o (unmerge_rsp ) - // ); - - - // TODO: Should be NrCore instead of CacheBank here - for (genvar j = 0; j < NrTCDMPortsPerCore; j++) begin: gen_strb_hdlr + for (genvar j = 0; j < NrTCDMPortsPerCore; j++) begin for (genvar cb = 0; cb < NumL1CacheCtrl; cb++) begin - // spatz_strbreq_handler #( - // .DataWidth (DataWidth ), - // .mem_req_t (tcdm_req_t ), - // .mem_rsp_t (tcdm_rsp_t ), - // .reqrsp_user_t (tcdm_user_t ) - // ) i_strbreq_handler ( - // .clk_i (clk_i ), - // .rst_ni (rst_ni ), - // .strb_req_i (strb_hdl_req [cb*NrTCDMPortsPerCore+j]), - // .strb_rsp_ready_i (strb_hdl_pready[cb*NrTCDMPortsPerCore+j]), - // .strb_rsp_i (cache_rsp [j][cb] ), - // .strb_req_o (cache_req [j][cb] ), - // .strb_rsp_ready_o (cache_pready [j][cb] ), - // .strb_rsp_o (strb_hdl_rsp [cb*NrTCDMPortsPerCore+j]) - // ); - // end assign cache_req [j][cb] = unmerge_req [cb*NrTCDMPortsPerCore+j]; assign cache_pready[j][cb] = unmerge_pready[cb*NrTCDMPortsPerCore+j]; assign unmerge_rsp [cb*NrTCDMPortsPerCore+j] = cache_rsp [j][cb]; @@ -965,6 +883,7 @@ module cachepool_cluster_simple tcdm_cache_interco #( .NumCore (NrCores ), .NumCache (NumL1CacheCtrl ), + .AddrWidth (32'd32 ), .tcdm_req_t (tcdm_req_t ), .tcdm_rsp_t (tcdm_rsp_t ), .tcdm_req_chan_t (tcdm_req_chan_t ), @@ -973,33 +892,50 @@ module cachepool_cluster_simple .clk_i (clk_i ), .rst_ni (rst_ni ), .dynamic_offset_i (dynamic_offset ), - .core_req_i (cache_req[j] ), - .core_rsp_ready_i (cache_pready[j] ), - .core_rsp_o (cache_rsp[j] ), - .mem_req_o (cache_xbar_req[j] ), + .core_req_i (cache_req [j] ), + .core_rsp_ready_i (cache_pready [j] ), + .core_rsp_o (cache_rsp [j] ), + .mem_req_o (cache_xbar_req [j] ), .mem_rsp_ready_o (cache_xbar_pready[j] ), - .mem_rsp_i (cache_xbar_rsp[j] ) + .mem_rsp_i (cache_xbar_rsp [j] ) ); end - // Re-organize the wire for easier connection - for (genvar cb = 0; cb < NumL1CacheCtrl; cb++) begin - for (genvar j = 0; j < NrTCDMPortsPerCore; j++) begin - assign cache_req_valid[cb][j] = cache_xbar_req[j][cb].q_valid; - assign cache_req_addr [cb][j] = cache_xbar_req[j][cb].q.addr; - assign cache_req_meta [cb][j] = cache_xbar_req[j][cb].q.user; - assign cache_req_write[cb][j] = cache_xbar_req[j][cb].q.write; - assign cache_req_data [cb][j] = cache_xbar_req[j][cb].q.data; + for (genvar cb = 0; cb < NumL1CacheCtrl; cb++) begin : gen_cache_connect + for (genvar j = 0; j < NrTCDMPortsPerCore; j++) begin : gen_cache_amo + spatz_cache_amo #( + .DataWidth ( DataWidth ), + .CoreIDWidth ( CoreIDWidth ), + .tcdm_req_t ( tcdm_req_t ), + .tcdm_rsp_t ( tcdm_rsp_t ), + .tcdm_req_chan_t ( tcdm_req_chan_t ), + .tcdm_rsp_chan_t ( tcdm_rsp_chan_t ), + .tcdm_user_t ( tcdm_user_t ) + ) i_cache_amo ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .core_req_i (cache_xbar_req [j][cb] ), + .core_rsp_ready_i (cache_xbar_pready[j][cb] ), + .core_rsp_o (cache_xbar_rsp [j][cb] ), + .mem_req_o (cache_amo_req [j][cb] ), + .mem_rsp_ready_o (cache_amo_pready [j][cb] ), + .mem_rsp_i (cache_amo_rsp [j][cb] ) + ); + assign cache_req_valid[cb][j] = cache_amo_req[j][cb].q_valid; + assign cache_req_addr [cb][j] = cache_amo_req[j][cb].q.addr; + assign cache_req_meta [cb][j] = cache_amo_req[j][cb].q.user; + assign cache_req_write[cb][j] = cache_amo_req[j][cb].q.write; + assign cache_req_data [cb][j] = cache_amo_req[j][cb].q.data; // assign cache_rsp_ready[cb][j] = 1'b1; - assign cache_rsp_ready[cb][j] = cache_xbar_pready[j][cb]; + assign cache_rsp_ready[cb][j] = cache_amo_pready[j][cb]; - assign cache_xbar_rsp[j][cb].p_valid = cache_rsp_valid[cb][j]; - assign cache_xbar_rsp[j][cb].q_ready = cache_req_ready[cb][j]; - assign cache_xbar_rsp[j][cb].p.data = cache_rsp_data [cb][j]; - assign cache_xbar_rsp[j][cb].p.user = cache_rsp_meta [cb][j]; + assign cache_amo_rsp[j][cb].p_valid = cache_rsp_valid[cb][j]; + assign cache_amo_rsp[j][cb].q_ready = cache_req_ready[cb][j]; + assign cache_amo_rsp[j][cb].p.data = cache_rsp_data [cb][j]; + assign cache_amo_rsp[j][cb].p.user = cache_rsp_meta [cb][j]; - assign cache_xbar_rsp[j][cb].p.write = cache_rsp_write[cb][j]; + assign cache_amo_rsp[j][cb].p.write = cache_rsp_write[cb][j]; end end @@ -1080,10 +1016,10 @@ module cachepool_cluster_simple .SimInit ("zeros" ), .impl_in_t (impl_in_t ) ) i_meta_bank ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .impl_i ('0 ), - .impl_o (/* unsed */ ), + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .impl_i ('0 ), + .impl_o (/* unsed */ ), .req_i (l1_tag_bank_req [cb][j]), .we_i (l1_tag_bank_we [cb][j]), .addr_i (l1_tag_bank_addr [cb][j]), @@ -1102,10 +1038,10 @@ module cachepool_cluster_simple .Latency (1), .SimInit ("zeros") ) i_data_bank ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .impl_i ('0 ), - .impl_o (/* unsed */ ), + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .impl_i ('0 ), + .impl_o (/* unsed */ ), .req_i (l1_data_bank_req [cb][j]), .we_i (l1_data_bank_we [cb][j]), .addr_i (l1_data_bank_addr [cb][j]), diff --git a/hardware/src/cachepool_pkg.sv b/hardware/src/cachepool_pkg.sv index a5c9c46..47863ce 100644 --- a/hardware/src/cachepool_pkg.sv +++ b/hardware/src/cachepool_pkg.sv @@ -19,13 +19,13 @@ package cachepool_pkg; /////////// // AXI Data Width - localparam int unsigned SpatzAxiDataWidth = 256; - localparam int unsigned SpatzAxiStrbWidth = SpatzAxiDataWidth / 8; + localparam int unsigned SpatzAxiDataWidth = 256; + localparam int unsigned SpatzAxiStrbWidth = SpatzAxiDataWidth / 8; localparam int unsigned SpatzAxiNarrowDataWidth = 64; // AXI Address Width - localparam int unsigned SpatzAxiAddrWidth = 32; + localparam int unsigned SpatzAxiAddrWidth = 32; // AXI ID Width - localparam int unsigned SpatzAxiIdInWidth = 6; + localparam int unsigned SpatzAxiIdInWidth = 6; localparam int unsigned SpatzAxiIdOutWidth = 2; // FIXED AxiIdOutWidth @@ -55,10 +55,13 @@ package cachepool_pkg; //////////////////// localparam int unsigned NumCores = 4; + // TODO: read from CFG + localparam int unsigned NumBank = 16; + localparam int unsigned TCDMDepth = 1024; - localparam int unsigned DataWidth = 64; - localparam int unsigned BeWidth = DataWidth / 8; - localparam int unsigned ByteOffset = $clog2(BeWidth); + localparam int unsigned SpatzDataWidth = 64; + localparam int unsigned BeWidth = SpatzDataWidth / 8; + localparam int unsigned ByteOffset = $clog2(BeWidth); localparam int unsigned ICacheLineWidth = 128; localparam int unsigned ICacheLineCount = 128; @@ -119,28 +122,50 @@ package cachepool_pkg; localparam fpu_implementation_t FPUImplementation [NumCores] = '{default: FPUImplementation_Core}; - //////////////////// // CachePool L1 // //////////////////// - // Number of Cache Banks per Tile - // localparam int unsigned L1CacheBank = 1; - - // // L1 Cache - // localparam int unsigned L1AddrWidth = 32; - // localparam int unsigned L1LineWidth = 256; - // localparam int unsigned L1Associativity = 4; - // localparam int unsigned L1BankFactor = 2; - // localparam int unsigned L1CoalFactor = 2; - // // 8 * 1024 * 64 / 512 = 1024) - // localparam int unsigned L1NumEntry = NrBanks * TCDMDepth * DataWidth / L1LineWidth; - // localparam int unsigned L1NumWrapper = L1LineWidth / DataWidth; - // localparam int unsigned L1BankPerWP = L1BankFactor * L1Associativity; - // localparam int unsigned L1BankPerWay = L1BankFactor * L1NumWrapper; - // localparam int unsigned L1CacheWayEntry = L1NumEntry / L1Associativity; - // localparam int unsigned L1NumSet = L1CacheWayEntry / L1BankFactor; - // localparam int unsigned L1NumTagBank = L1BankFactor * L1Associativity; - // localparam int unsigned L1NumDataBank = L1BankFactor * L1NumWrapper * L1Associativity; + // Address width of cache + localparam int unsigned L1AddrWidth = 32; + // Cache lane width + localparam int unsigned L1LineWidth = SpatzAxiDataWidth; + // Coalecser window + localparam int unsigned L1CoalFactor = 2; + // Total number of Data banks + localparam int unsigned L1NumDataBank = 128; + // Number of bank wraps SPM can see + localparam int unsigned L1NumWrapper = NumBank; + // SPM view: Number of banks in each bank wrap (Use to mitigate routing complexity of such many banks) + localparam int unsigned L1BankPerWP = L1NumDataBank / NumBank; + // Pesudo dual bank + localparam int unsigned L1BankFactor = 2; + // Cache ways (total way number across multiple cache controllers) + localparam int unsigned L1Associativity = L1NumDataBank / (L1LineWidth / SpatzDataWidth) / L1BankFactor; + // 8 * 1024 * 64 / 512 = 1024) + // Number of entrys of L1 Cache (total number across multiple cache controllers) + localparam int unsigned L1NumEntry = NumBank * TCDMDepth * SpatzDataWidth / L1LineWidth; + // Number of cache entries each cache way has + localparam int unsigned L1CacheWayEntry = L1NumEntry / L1Associativity; + // Number of cache sets each cache way has + localparam int unsigned L1NumSet = L1CacheWayEntry / L1BankFactor; + // Number of Tag banks + localparam int unsigned L1NumTagBank = L1BankFactor * L1Associativity; + // Number of lines per bank unit + localparam int unsigned DepthPerBank = TCDMDepth / L1BankPerWP; + // Cache total size in KB + localparam int unsigned L1Size = NumBank * TCDMDepth * BeWidth / 1024; + + // Number of cache controller (now is fixde to NrCores (if we change it, we need to change the controller axi output id width too) + localparam int unsigned NumL1CacheCtrl = NumCores; + // Number of data banks assigned to each cache controller + localparam int unsigned NumDataBankPerCtrl = L1NumDataBank / NumL1CacheCtrl; + // Number of tag banks assigned to each cache controller + localparam int unsigned NumTagBankPerCtrl = L1NumTagBank / NumL1CacheCtrl; + // Number of ways per cache controller + localparam int unsigned L1AssoPerCtrl = L1Associativity / NumL1CacheCtrl; + // Number of entries per cache controller + localparam int unsigned L1NumEntryPerCtrl = L1NumEntry / NumL1CacheCtrl; + endpackage : cachepool_pkg diff --git a/hardware/tb/cachepool_cluster_wrapper.sv b/hardware/tb/cachepool_cluster_wrapper.sv index 8fe36ad..32cffb9 100644 --- a/hardware/tb/cachepool_cluster_wrapper.sv +++ b/hardware/tb/cachepool_cluster_wrapper.sv @@ -70,7 +70,7 @@ module cachepool_cluster_wrapper .slv_resp_o ( axi_from_cluster_iwc_resp ), .mst_req_o ( axi_out_req_o ), .mst_resp_i ( axi_out_resp_i ) - ); + ); axi_iw_converter #( .AxiSlvPortIdWidth ( IwcAxiIdOutWidth ), @@ -108,8 +108,8 @@ module cachepool_cluster_wrapper .L2Size (L2Size ), .ClusterPeriphSize (64 ), .NrCores (NumCores ), - .TCDMDepth (1024 ), - .NrBanks (16 ), + .TCDMDepth (TCDMDepth ), + .NrBanks (NumBank ), .ICacheLineWidth (ICacheLineWidth ), .ICacheLineCount (ICacheLineCount ), .ICacheSets (ICacheSets ), diff --git a/hardware/tb/testharness.sv b/hardware/tb/testharness.sv index 4c174b6..1c3b8d8 100644 --- a/hardware/tb/testharness.sv +++ b/hardware/tb/testharness.sv @@ -98,7 +98,7 @@ module testharness ( reqrsp_cluster_in_rsp_t to_cluster_rsp; reqrsp_to_axi #( - .DataWidth (DataWidth ), + .DataWidth (SpatzDataWidth ), .UserWidth (SpatzAxiUserWidth ), .axi_req_t (spatz_axi_in_req_t ), .axi_rsp_t (spatz_axi_in_resp_t ), diff --git a/software/tests/CMakeLists.txt b/software/tests/CMakeLists.txt new file mode 100644 index 0000000..2e31f38 --- /dev/null +++ b/software/tests/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright 2020 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.13) + +# Allow spatzBenchmarks to be built as a standalone library. +if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) + set(CMAKE_TOOLCHAIN_FILE toolchain-gcc CACHE STRING "Toolchain to use") + + project(Benchmarks LANGUAGES C ASM) + include(SnitchUtilities) + + # Build the runtime. + add_subdirectory(${SPATZ_DIR}/sw/snRuntime snRuntime) +endif() + +add_compile_options(-O3 -g -ffunction-sections) +add_compile_options(-DELEN=64) + +include_directories(include) +include_directories(${SNRUNTIME_INCLUDE_DIRS}) + +# Tests +enable_testing() +set(SNITCH_TEST_PREFIX cachepool-) + +add_snitch_test(spin-lock spin-lock/main.c) diff --git a/software/tests/spin-lock/main.c b/software/tests/spin-lock/main.c new file mode 100644 index 0000000..a304720 --- /dev/null +++ b/software/tests/spin-lock/main.c @@ -0,0 +1,88 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// +// SPDX-License-Identifier: Apache-2.0 +// +// 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: Diyou Shen + +#include +#include +#include +#include +#include "printf.h" + +static double result __attribute__((section(".data"))); + +static inline int fp_check(const double a, const double b) { + const double threshold = 0.00001; + + // Absolute value + double comp = a - b; + if (comp < 0) + comp = -comp; + + return comp > threshold; +} + +typedef volatile int spinlock_t __attribute__((aligned(8))); +spinlock_t lock; + +static inline void spin_lock (spinlock_t *lock) { + while (__sync_lock_test_and_set(lock, 1)) { } +} + +static inline void spin_unlock(spinlock_t *lock) { + __sync_lock_release(lock); +} + +int main() { + const unsigned int num_cores = snrt_cluster_core_num(); + const unsigned int cid = snrt_cluster_core_idx(); + + uint32_t spm_size = 0; + + if (cid == 0) { + // Set xbar policy to default interleave (cacheline width) + l1d_xbar_config(256, num_cores); + // Init the cache + l1d_init(spm_size); + } + + // Wait for all cores to finish + snrt_cluster_hw_barrier(); + + // Fetch lock + spin_lock (&lock); + + // Each core print its core id + printf("Core%d:hello\n", cid); + + // Add cid to the result + result += cid; + + // Release the lock + spin_unlock(&lock); + + snrt_cluster_hw_barrier(); + + if (cid == 0) { + printf("result: %f\n", result); + } + + // Wait for core 0 to finish displaying results + snrt_cluster_hw_barrier(); + set_eoc(); + + return 0; +} From 26d6015b863dafaa92b82743e95dcc0d40f584df Mon Sep 17 00:00:00 2001 From: Diyou Shen Date: Wed, 23 Apr 2025 14:21:33 +0200 Subject: [PATCH 03/17] [Spatz] Update spatz wave script. Fix a missing config in Makefile --- Makefile | 4 ++-- hardware/deps/spatz | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 90515ed..8e84e90 100644 --- a/Makefile +++ b/Makefile @@ -10,8 +10,8 @@ ROOT_DIR := $(patsubst %/,%, $(dir $(abspath $(lastword $(MAKEFILE_LIST))))) CACHEPOOL_DIR := $(shell git rev-parse --show-toplevel 2>/dev/null || echo $$CACHEPOOL_DIR) # Include configuration -config_mk = $(abspath $(ROOT_DIR)/config/config.mk) -include $(config_mk) +# config_mk = $(abspath $(ROOT_DIR)/config/config.mk) +# include $(config_mk) # Directories INSTALL_PREFIX ?= install diff --git a/hardware/deps/spatz b/hardware/deps/spatz index a2c3e83..03ab785 160000 --- a/hardware/deps/spatz +++ b/hardware/deps/spatz @@ -1 +1 @@ -Subproject commit a2c3e8329992f8264f7507fe0f3aa5b5350e772f +Subproject commit 03ab78561a42ba5865d1ab6d08554ce4ef5436ab From 13841e61b98b382c6032bec16c81478ba2650545 Mon Sep 17 00:00:00 2001 From: Diyou Shen Date: Wed, 23 Apr 2025 14:47:47 +0200 Subject: [PATCH 04/17] Update README --- README.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8c5dc54..3bb5a21 100644 --- a/README.md +++ b/README.md @@ -10,4 +10,28 @@ Make sure you clone this repository recursively to get all the necessary submodu ```bash git submodule update --init --recursive ``` ->>>>>>> 0d74201... [Spatz] Add Spatz dependency and some simple setup for CachePool + +Then, initialize and generated the needed hardware with: + +```bash +make init +make generate +``` + +You can build the software only with: + +```bash +make sw +``` + +Or, build the software and hardware together with (only support QuestaSim for now): + +```bash +make vsim +``` + +The QuestaSim simulation can be run with: + +```bash +./bin/spatz_cluster.vsim.gui ./software/build/TESTNAME +``` From 4d90e77f23926a5cefd5cedfc9c58f1cf35d41ed Mon Sep 17 00:00:00 2001 From: Diyou Shen Date: Wed, 23 Apr 2025 14:52:56 +0200 Subject: [PATCH 05/17] [SRC] Remove unused source files. --- hardware/src/cachepool_cluster.sv | 1495 ------------------------ hardware/src/cachepool_tile.sv | 369 ------ hardware/src/cachepool_tile_simple.sv | 1515 ------------------------- 3 files changed, 3379 deletions(-) delete mode 100644 hardware/src/cachepool_cluster.sv delete mode 100644 hardware/src/cachepool_tile.sv delete mode 100644 hardware/src/cachepool_tile_simple.sv diff --git a/hardware/src/cachepool_cluster.sv b/hardware/src/cachepool_cluster.sv deleted file mode 100644 index bc1303a..0000000 --- a/hardware/src/cachepool_cluster.sv +++ /dev/null @@ -1,1495 +0,0 @@ -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Author: Matheus Cavalcante - -`include "axi/assign.svh" -`include "axi/typedef.svh" -`include "common_cells/assertions.svh" -`include "common_cells/registers.svh" -`include "mem_interface/assign.svh" -`include "mem_interface/typedef.svh" -`include "register_interface//assign.svh" -`include "register_interface/typedef.svh" -`include "reqrsp_interface/assign.svh" -`include "reqrsp_interface/typedef.svh" -`include "snitch_vm/typedef.svh" -`include "tcdm_interface/assign.svh" -`include "tcdm_interface/typedef.svh" - -/// Spatz many-core cluster with improved TCDM interconnect. -/// Spatz Cluster Top-Level. -module spatz_cluster - import spatz_pkg::*; - import fpnew_pkg::fpu_implementation_t; - import snitch_pma_pkg::snitch_pma_t; - #( - /// Width of physical address. - parameter int unsigned AxiAddrWidth = 48, - /// Width of AXI port. - parameter int unsigned AxiDataWidth = 512, - /// AXI: id width in. - parameter int unsigned AxiIdWidthIn = 2, - /// AXI: id width out. - parameter int unsigned AxiIdWidthOut = 2, - /// AXI: user width. - parameter int unsigned AxiUserWidth = 1, - /// Address from which to fetch the first instructions. - parameter logic [31:0] BootAddr = 32'h0, - /// Address to indicate start of L2 - parameter logic [AxiAddrWidth-1:0] L2Addr = 48'h0, - parameter logic [AxiAddrWidth-1:0] L2Size = 48'h0, - /// The total amount of cores. - parameter int unsigned NrCores = 8, - /// Data/TCDM memory depth per cut (in words). - parameter int unsigned TCDMDepth = 1024, - /// Cluster peripheral address region size (in kB). - parameter int unsigned ClusterPeriphSize = 64, - /// Number of TCDM Banks. - parameter int unsigned NrBanks = 2 * NrCores, - /// Size of DMA AXI buffer. - parameter int unsigned DMAAxiReqFifoDepth = 3, - /// Size of DMA request fifo. - parameter int unsigned DMAReqFifoDepth = 3, - /// Width of a single icache line. - parameter unsigned ICacheLineWidth = 0, - /// Number of icache lines per set. - parameter int unsigned ICacheLineCount = 0, - /// Number of icache sets. - parameter int unsigned ICacheSets = 0, - // PMA Configuration - parameter snitch_pma_t SnitchPMACfg = '{default: 0}, - /// # Core-global parameters - /// FPU configuration. - parameter fpu_implementation_t FPUImplementation [NrCores] = '{default: fpu_implementation_t'(0)}, - /// Spatz FPU/IPU Configuration - parameter int unsigned NumSpatzFPUs = 4, - parameter int unsigned NumSpatzIPUs = 1, - /// Per-core enabling of the custom `Xdma` ISA extensions. - parameter bit [NrCores-1:0] Xdma = '{default: '0}, - /// # Per-core parameters - /// Per-core integer outstanding loads - parameter int unsigned NumIntOutstandingLoads [NrCores] = '{default: '0}, - /// Per-core integer outstanding memory operations (load and stores) - parameter int unsigned NumIntOutstandingMem [NrCores] = '{default: '0}, - /// Per-core Spatz outstanding loads - parameter int unsigned NumSpatzOutstandingLoads [NrCores] = '{default: '0}, - /// ## Timing Tuning Parameters - /// Insert Pipeline registers into off-loading path (response) - parameter bit RegisterOffloadRsp = 1'b0, - /// Insert Pipeline registers into data memory path (request) - parameter bit RegisterCoreReq = 1'b0, - /// Insert Pipeline registers into data memory path (response) - parameter bit RegisterCoreRsp = 1'b0, - /// Insert Pipeline registers after each memory cut - parameter bit RegisterTCDMCuts = 1'b0, - /// Decouple external AXI plug - parameter bit RegisterExt = 1'b0, - parameter axi_pkg::xbar_latency_e XbarLatency = axi_pkg::CUT_ALL_PORTS, - /// Outstanding transactions on the AXI network - parameter int unsigned MaxMstTrans = 4, - parameter int unsigned MaxSlvTrans = 4, - /// # Interface - /// AXI Ports - parameter type axi_in_req_t = logic, - parameter type axi_in_resp_t = logic, - parameter type axi_out_req_t = logic, - parameter type axi_out_resp_t = logic, - /// SRAM configuration - parameter type impl_in_t = logic, - // Memory latency parameter. Most of the memories have a read latency of 1. In - // case you have memory macros which are pipelined you want to adjust this - // value here. This only applies to the TCDM. The instruction cache macros will break! - // In case you are using the `RegisterTCDMCuts` feature this adds an - // additional cycle latency, which is taken into account here. - parameter int unsigned MemoryMacroLatency = 1 + RegisterTCDMCuts, - /// # SRAM Configuration rules needed: L1D Tag + L1D Data + L1D FIFO + L1I Tag + L1I Data - parameter int unsigned NrSramCfg = 64 + 8 + 2 + ICacheSets + ICacheSets - ) ( - /// System clock. - input logic clk_i, - /// Asynchronous active high reset. This signal is assumed to be _async_. - input logic rst_ni, - /// Per-core debug request signal. Asserting this signals puts the - /// corresponding core into debug mode. This signal is assumed to be _async_. - input logic [NrCores-1:0] debug_req_i, - /// Machine external interrupt pending. Usually those interrupts come from a - /// platform-level interrupt controller. This signal is assumed to be _async_. - input logic [NrCores-1:0] meip_i, - /// Machine timer interrupt pending. Usually those interrupts come from a - /// core-local interrupt controller such as a timer/RTC. This signal is - /// assumed to be _async_. - input logic [NrCores-1:0] mtip_i, - /// Core software interrupt pending. Usually those interrupts come from - /// another core to facilitate inter-processor-interrupts. This signal is - /// assumed to be _async_. - input logic [NrCores-1:0] msip_i, - /// First hartid of the cluster. Cores of a cluster are monotonically - /// increasing without a gap, i.e., a cluster with 8 cores and a - /// `hart_base_id_i` of 5 get the hartids 5 - 12. - input logic [9:0] hart_base_id_i, - /// Base address of cluster. TCDM and cluster peripheral location are derived from - /// it. This signal is pseudo-static. - input logic [AxiAddrWidth-1:0] cluster_base_addr_i, - /// Per-cluster probe on the cluster status. Can be written by the cores to indicate - /// to the overall system that the cluster is executing something. - output logic cluster_probe_o, - /// AXI Core cluster in-port. - input axi_in_req_t axi_in_req_i, - output axi_in_resp_t axi_in_resp_o, - /// AXI Core cluster out-port to core. - output axi_out_req_t axi_out_req_o, - input axi_out_resp_t axi_out_resp_i, - /// AXI Core cluster out-port to L2 Mem. - output axi_out_req_t axi_out_l2_req_o, - input axi_out_resp_t axi_out_l2_resp_i, - /// SRAM Configuration: L1D Data + L1D Tag + L1D FIFO + L1I Data + L1I Tag - input impl_in_t [NrSramCfg-1:0] impl_i, - /// Indicate the program execution is error - output logic error_o - ); - // --------- - // Imports - // --------- - import snitch_pkg::*; - import snitch_icache_pkg::icache_events_t; - - // --------- - // Constants - // --------- - /// Minimum width to hold the core number. - localparam int unsigned CoreIDWidth = cf_math_pkg::idx_width(NrCores); - localparam int unsigned TCDMMemAddrWidth = $clog2(TCDMDepth); - localparam int unsigned TCDMSize = NrBanks * TCDMDepth * (DataWidth/8); - // The short address for SPM - localparam int unsigned SPMAddrWidth = $clog2(TCDMSize); - // Enlarge the address width for Spatz due to cache - localparam int unsigned TCDMAddrWidth = 32; - localparam int unsigned BanksPerSuperBank = AxiDataWidth / DataWidth; - localparam int unsigned NrSuperBanks = NrBanks / BanksPerSuperBank; - - function automatic int unsigned get_tcdm_ports(int unsigned core); - return spatz_pkg::N_FU + 1; - endfunction - - function automatic int unsigned get_tcdm_port_offs(int unsigned core_idx); - automatic int n = 0; - for (int i = 0; i < core_idx; i++) n += get_tcdm_ports(i); - return n; - endfunction - - localparam int unsigned NrTCDMPortsCores = get_tcdm_port_offs(NrCores); - localparam int unsigned NumTCDMIn = NrTCDMPortsCores + 1; - localparam logic [AxiAddrWidth-1:0] TCDMMask = ~(TCDMSize-1); - - // Core Request, SoC Request - localparam int unsigned NrNarrowMasters = 2; - - // Narrow AXI network parameters - localparam int unsigned NarrowIdWidthIn = AxiIdWidthIn; - localparam int unsigned NarrowIdWidthOut = NarrowIdWidthIn + $clog2(NrNarrowMasters); - localparam int unsigned NarrowDataWidth = 64; - localparam int unsigned NarrowUserWidth = AxiUserWidth; - - // TCDM, Peripherals, SoC Request - localparam int unsigned NrNarrowSlaves = 3; - localparam int unsigned NrNarrowRules = NrNarrowSlaves - 1; - - // Core Request, DMA, Instruction cache - /// Additional one for L1 DCache - localparam int unsigned NrWideMasters = 3 + 1; - localparam int unsigned WideIdWidthOut = AxiIdWidthOut; - localparam int unsigned WideIdWidthIn = WideIdWidthOut - $clog2(NrWideMasters); - // DMA X-BAR configuration - localparam int unsigned NrWideSlaves = 3 + 1; // one prot for L2, one for L3/LLC (virtual) - - // AXI Configuration - localparam axi_pkg::xbar_cfg_t ClusterXbarCfg = '{ - NoSlvPorts : NrNarrowMasters, - NoMstPorts : NrNarrowSlaves, - MaxMstTrans : MaxMstTrans, - MaxSlvTrans : MaxSlvTrans, - FallThrough : 1'b0, - LatencyMode : XbarLatency, - AxiIdWidthSlvPorts: NarrowIdWidthIn, - AxiIdUsedSlvPorts : NarrowIdWidthIn, - UniqueIds : 1'b0, - AxiAddrWidth : AxiAddrWidth, - AxiDataWidth : NarrowDataWidth, - NoAddrRules : NrNarrowRules, - default : '0 - }; - - // DMA configuration struct - localparam axi_pkg::xbar_cfg_t DmaXbarCfg = '{ - NoSlvPorts : NrWideMasters, - NoMstPorts : NrWideSlaves, - MaxMstTrans : MaxMstTrans, - MaxSlvTrans : MaxSlvTrans, - FallThrough : 1'b0, - LatencyMode : XbarLatency, - AxiIdWidthSlvPorts: WideIdWidthIn, - AxiIdUsedSlvPorts : WideIdWidthIn, - UniqueIds : 1'b0, - AxiAddrWidth : AxiAddrWidth, - AxiDataWidth : AxiDataWidth, - NoAddrRules : NrWideSlaves - 1, - default : '0 - }; - - // L1 Cache - localparam int unsigned L1AddrWidth = 32; - localparam int unsigned L1LineWidth = 512; - localparam int unsigned L1Associativity = 4; - localparam int unsigned L1BankFactor = 2; - localparam int unsigned L1CoalFactor = 2; - // 8 * 1024 * 64 / 512 = 1024) - localparam int unsigned L1NumEntry = NrBanks * TCDMDepth * DataWidth / L1LineWidth; - localparam int unsigned L1NumWrapper = L1LineWidth / DataWidth; - localparam int unsigned L1BankPerWP = L1BankFactor * L1Associativity; - localparam int unsigned L1BankPerWay = L1BankFactor * L1NumWrapper; - localparam int unsigned L1CacheWayEntry = L1NumEntry / L1Associativity; - localparam int unsigned L1NumSet = L1CacheWayEntry / L1BankFactor; - localparam int unsigned L1NumTagBank = L1BankFactor * L1Associativity; - localparam int unsigned L1NumDataBank = L1BankFactor * L1NumWrapper * L1Associativity; - - // -------- - // Typedefs - // -------- - typedef logic [AxiAddrWidth-1:0] addr_t; - typedef logic [NarrowDataWidth-1:0] data_t; - typedef logic [NarrowDataWidth/8-1:0] strb_t; - typedef logic [AxiDataWidth-1:0] data_dma_t; - typedef logic [AxiDataWidth/8-1:0] strb_dma_t; - typedef logic [NarrowIdWidthIn-1:0] id_mst_t; - typedef logic [NarrowIdWidthOut-1:0] id_slv_t; - typedef logic [WideIdWidthIn-1:0] id_dma_mst_t; - typedef logic [WideIdWidthOut-1:0] id_dma_slv_t; - typedef logic [NarrowUserWidth-1:0] user_t; - typedef logic [AxiUserWidth-1:0] user_dma_t; - - typedef logic [TCDMMemAddrWidth-1:0] tcdm_mem_addr_t; - typedef logic [TCDMAddrWidth-1:0] tcdm_addr_t; - typedef logic [SPMAddrWidth-1:0] spm_addr_t; - - typedef logic [$clog2(NumSpatzOutstandingLoads[0])-1:0] reqid_t; - typedef logic [$clog2(NumSpatzOutstandingLoads[0]):0] tcdm_meta_t; - - typedef logic [$clog2(L1NumSet)-1:0] tcdm_bank_addr_t; - - typedef struct packed { - logic [CoreIDWidth-1:0] core_id; - logic is_core; - reqid_t req_id; - } tcdm_user_t; - - // Regbus peripherals. - `AXI_TYPEDEF_ALL(axi_mst, addr_t, id_mst_t, data_t, strb_t, user_t) - `AXI_TYPEDEF_ALL(axi_slv, addr_t, id_slv_t, data_t, strb_t, user_t) - `AXI_TYPEDEF_ALL(axi_mst_dma, addr_t, id_dma_mst_t, data_dma_t, strb_dma_t, user_dma_t) - `AXI_TYPEDEF_ALL(axi_slv_dma, addr_t, id_dma_slv_t, data_dma_t, strb_dma_t, user_dma_t) - - `REQRSP_TYPEDEF_ALL(reqrsp, addr_t, data_t, strb_t) - - `MEM_TYPEDEF_ALL(mem, tcdm_mem_addr_t, data_t, strb_t, tcdm_user_t) - `MEM_TYPEDEF_ALL(mem_dma, tcdm_mem_addr_t, data_dma_t, strb_dma_t, logic) - - `TCDM_TYPEDEF_ALL(tcdm, tcdm_addr_t, data_t, strb_t, tcdm_user_t) - `TCDM_TYPEDEF_ALL(tcdm_dma, tcdm_addr_t, data_dma_t, strb_dma_t, logic) - `TCDM_TYPEDEF_ALL(spm, spm_addr_t, data_t, strb_t, tcdm_user_t) - - `REG_BUS_TYPEDEF_ALL(reg, addr_t, data_t, strb_t) - `REG_BUS_TYPEDEF_ALL(reg_dma, addr_t, data_dma_t, strb_dma_t) - - // Event counter increments for the TCDM. - typedef struct packed { - /// Number requests going in - logic [$clog2(NrTCDMPortsCores):0] inc_accessed; - /// Number of requests stalled due to congestion - logic [$clog2(NrTCDMPortsCores):0] inc_congested; - } tcdm_events_t; - - // Event counter increments for DMA. - typedef struct packed { - logic aw_stall, ar_stall, r_stall, w_stall, - buf_w_stall, buf_r_stall; - logic aw_valid, aw_ready, aw_done, aw_bw; - logic ar_valid, ar_ready, ar_done, ar_bw; - logic r_valid, r_ready, r_done, r_bw; - logic w_valid, w_ready, w_done, w_bw; - logic b_valid, b_ready, b_done; - logic dma_busy; - axi_pkg::len_t aw_len, ar_len; - axi_pkg::size_t aw_size, ar_size; - logic [$clog2(AxiDataWidth/8):0] num_bytes_written; - } dma_events_t; - - typedef struct packed { - int unsigned idx; - addr_t start_addr; - addr_t end_addr; - } xbar_rule_t; - - typedef struct packed { - acc_addr_e addr; - logic [5:0] id; - logic [31:0] data_op; - data_t data_arga; - data_t data_argb; - addr_t data_argc; - } acc_issue_req_t; - - typedef struct packed { - logic accept; - logic writeback; - logic loadstore; - logic exception; - logic isfloat; - } acc_issue_rsp_t; - - typedef struct packed { - logic [5:0] id; - logic error; - data_t data; - } acc_rsp_t; - - `SNITCH_VM_TYPEDEF(AxiAddrWidth) - - typedef struct packed { - // Slow domain. - logic flush_i_valid; - addr_t inst_addr; - logic inst_cacheable; - logic inst_valid; - // Fast domain. - acc_issue_req_t acc_req; - logic acc_qvalid; - logic acc_pready; - // Slow domain. - logic [1:0] ptw_valid; - va_t [1:0] ptw_va; - pa_t [1:0] ptw_ppn; - } hive_req_t; - - typedef struct packed { - // Slow domain. - logic flush_i_ready; - logic [31:0] inst_data; - logic inst_ready; - logic inst_error; - // Fast domain. - logic acc_qready; - acc_rsp_t acc_resp; - logic acc_pvalid; - // Slow domain. - logic [1:0] ptw_ready; - l0_pte_t [1:0] ptw_pte; - logic [1:0] ptw_is_4mega; - } hive_rsp_t; - - // ----------- - // Assignments - // ----------- - // Calculate start and end address of TCDM based on the `cluster_base_addr_i`. - addr_t tcdm_start_address, tcdm_end_address; - assign tcdm_start_address = (cluster_base_addr_i & TCDMMask); - assign tcdm_end_address = (tcdm_start_address + TCDMSize) & TCDMMask; - - addr_t cluster_periph_start_address, cluster_periph_end_address; - assign cluster_periph_start_address = tcdm_end_address; - assign cluster_periph_end_address = tcdm_end_address + ClusterPeriphSize * 1024; - - localparam int unsigned ClusterReserve = 4096; // 4 MiB - localparam int unsigned ClusterL2Size = 8192; // 8 MiB - addr_t cluster_l2_start_address, cluster_l2_end_address; - assign cluster_l2_start_address = L2Addr; - assign cluster_l2_end_address = L2Addr + L2Size; - - // ---------------- - // Wire Definitions - // ---------------- - // 1. AXI - axi_slv_req_t [NrNarrowSlaves-1:0] narrow_axi_slv_req; - axi_slv_resp_t [NrNarrowSlaves-1:0] narrow_axi_slv_rsp; - axi_mst_req_t [NrNarrowMasters-1:0] narrow_axi_mst_req; - axi_mst_resp_t [NrNarrowMasters-1:0] narrow_axi_mst_rsp; - - // DMA AXI buses - axi_mst_dma_req_t [NrWideMasters-1:0] wide_axi_mst_req; - axi_mst_dma_resp_t [NrWideMasters-1:0] wide_axi_mst_rsp; - axi_slv_dma_req_t [NrWideSlaves-1 :0] wide_axi_slv_req; - axi_slv_dma_resp_t [NrWideSlaves-1 :0] wide_axi_slv_rsp; - - // 2. Memory Subsystem (Banks) - mem_req_t [NrSuperBanks-1:0][BanksPerSuperBank-1:0] ic_req; - mem_rsp_t [NrSuperBanks-1:0][BanksPerSuperBank-1:0] ic_rsp; - - mem_dma_req_t [NrSuperBanks-1:0] sb_dma_req; - mem_dma_rsp_t [NrSuperBanks-1:0] sb_dma_rsp; - - // 3. Memory Subsystem (Interconnect) - tcdm_dma_req_t ext_dma_req; - tcdm_dma_rsp_t ext_dma_rsp; - - // AXI Ports into TCDM (from SoC). - spm_req_t axi_soc_req; - spm_rsp_t axi_soc_rsp; - - tcdm_req_t [NrTCDMPortsCores-1:0] tcdm_req; - tcdm_rsp_t [NrTCDMPortsCores-1:0] tcdm_rsp; - - core_events_t [NrCores-1:0] core_events; - tcdm_events_t tcdm_events; - dma_events_t dma_events; - snitch_icache_pkg::icache_events_t [NrCores-1:0] icache_events; - - // 4. Memory Subsystem (Core side). - reqrsp_req_t [NrCores-1:0] core_req, filtered_core_req; - reqrsp_rsp_t [NrCores-1:0] core_rsp, filtered_core_rsp; - - // 5. Peripheral Subsystem - reg_req_t reg_req; - reg_rsp_t reg_rsp; - - // 6. BootROM - reg_dma_req_t bootrom_reg_req; - reg_dma_rsp_t bootrom_reg_rsp; - - // 7. Misc. Wires. - logic icache_prefetch_enable; - logic [NrCores-1:0] cl_interrupt; - - // 8. L1 D$ - spm_req_t [NrTCDMPortsCores-1:0] spm_req; - spm_rsp_t [NrTCDMPortsCores-1:0] spm_rsp; - - tcdm_req_t [NrTCDMPortsCores-1:0] unmerge_req, strb_hdl_req, cache_req; - tcdm_rsp_t [NrTCDMPortsCores-1:0] unmerge_rsp, strb_hdl_rsp, cache_rsp; - - logic [NrTCDMPortsCores-1:0] cache_req_valid; - logic [NrTCDMPortsCores-1:0] cache_req_ready; - tcdm_addr_t [NrTCDMPortsCores-1:0] cache_req_addr; - tcdm_user_t [NrTCDMPortsCores-1:0] cache_req_meta; - logic [NrTCDMPortsCores-1:0] cache_req_write; - data_t [NrTCDMPortsCores-1:0] cache_req_data; - - logic [NrTCDMPortsCores-1:0] cache_rsp_valid; - logic [NrTCDMPortsCores-1:0] cache_rsp_ready; - logic [NrTCDMPortsCores-1:0] cache_rsp_write; - data_t [NrTCDMPortsCores-1:0] cache_rsp_data; - tcdm_user_t [NrTCDMPortsCores-1:0] cache_rsp_meta; - - logic [L1NumTagBank-1:0] l1_tag_bank_req; - logic [L1NumTagBank-1:0] l1_tag_bank_we; - tcdm_bank_addr_t [L1NumTagBank-1:0] l1_tag_bank_addr; - data_t [L1NumTagBank-1:0] l1_tag_bank_wdata; - logic [L1NumTagBank-1:0] l1_tag_bank_be; - data_t [L1NumTagBank-1:0] l1_tag_bank_rdata; - - logic [L1NumDataBank-1:0] l1_data_bank_req; - logic [L1NumDataBank-1:0] l1_data_bank_we; - tcdm_bank_addr_t [L1NumDataBank-1:0] l1_data_bank_addr; - data_t [L1NumDataBank-1:0] l1_data_bank_wdata; - logic [L1NumDataBank-1:0] l1_data_bank_be; - data_t [L1NumDataBank-1:0] l1_data_bank_rdata; - logic [L1NumDataBank-1:0] l1_data_bank_gnt; - - logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_req; - logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_we; - tcdm_bank_addr_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_addr; - data_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_wdata; - strb_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_be; - data_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_rdata; - logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_gnt; - - logic l1d_insn_valid, l1d_insn_ready; - logic [1:0] l1d_insn; - tcdm_bank_addr_t cfg_spm_size; - tcdm_addr_t spm_size; - logic l1d_busy; - - // High if a port access an illegal SPM region (mapped to cache) - logic [NrTCDMPortsCores-1:0] spm_error; - - - // 9. SRAM Configuration - impl_in_t [L1NumWrapper-1:0][L1BankPerWP-1:0] impl_l1d_data; - impl_in_t [L1NumTagBank-1:0] impl_l1d_tag; - impl_in_t [1:0] impl_l1d_fifo; - - impl_in_t [ICacheSets-1:0] impl_l1i_data; - impl_in_t [ICacheSets-1:0] impl_l1i_tag; - - assign {impl_l1d_data, impl_l1d_tag, impl_l1d_fifo, impl_l1i_data, impl_l1i_tag} = impl_i; - assign error_o = |spm_error; - - - // ------------- - // DMA Subsystem - // ------------- - // Optionally decouple the external wide AXI master port. - axi_cut #( - .Bypass (!RegisterExt ), - .aw_chan_t (axi_slv_dma_aw_chan_t), - .w_chan_t (axi_slv_dma_w_chan_t ), - .b_chan_t (axi_slv_dma_b_chan_t ), - .ar_chan_t (axi_slv_dma_ar_chan_t), - .r_chan_t (axi_slv_dma_r_chan_t ), - .axi_req_t (axi_slv_dma_req_t ), - .axi_resp_t (axi_slv_dma_resp_t ) - ) i_cut_ext_wide_out ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .slv_req_i (wide_axi_slv_req[SoCDMAOut]), - .slv_resp_o (wide_axi_slv_rsp[SoCDMAOut]), - .mst_req_o (axi_out_req_o ), - .mst_resp_i (axi_out_resp_i ) - ); - - axi_cut #( - .Bypass (!RegisterExt ), - .aw_chan_t (axi_slv_dma_aw_chan_t), - .w_chan_t (axi_slv_dma_w_chan_t ), - .b_chan_t (axi_slv_dma_b_chan_t ), - .ar_chan_t (axi_slv_dma_ar_chan_t), - .r_chan_t (axi_slv_dma_r_chan_t ), - .axi_req_t (axi_slv_dma_req_t ), - .axi_resp_t (axi_slv_dma_resp_t ) - ) i_cut_ext_l2_wide_out ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .slv_req_i (wide_axi_slv_req[L2Mem]), - .slv_resp_o (wide_axi_slv_rsp[L2Mem]), - .mst_req_o (axi_out_l2_req_o ), - .mst_resp_i (axi_out_l2_resp_i ) - ); - - axi_cut #( - .Bypass (!RegisterExt ), - .aw_chan_t (axi_mst_aw_chan_t), - .w_chan_t (axi_mst_w_chan_t ), - .b_chan_t (axi_mst_b_chan_t ), - .ar_chan_t (axi_mst_ar_chan_t), - .r_chan_t (axi_mst_r_chan_t ), - .axi_req_t (axi_mst_req_t ), - .axi_resp_t (axi_mst_resp_t ) - ) i_cut_ext_narrow_in ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .slv_req_i (axi_in_req_i ), - .slv_resp_o (axi_in_resp_o ), - .mst_req_o (narrow_axi_mst_req[SoCDMAIn]), - .mst_resp_i (narrow_axi_mst_rsp[SoCDMAIn]) - ); - - logic [DmaXbarCfg.NoSlvPorts-1:0][$clog2(DmaXbarCfg.NoMstPorts)-1:0] dma_xbar_default_port; - xbar_rule_t [DmaXbarCfg.NoAddrRules-1:0] dma_xbar_rule; - - assign dma_xbar_default_port = '{default: SoCDMAOut}; - assign dma_xbar_rule = '{ - '{ - idx : TCDMDMA, - start_addr: tcdm_start_address, - end_addr : tcdm_end_address - }, - '{ - idx : BootROM, - start_addr: BootAddr, - end_addr : BootAddr + 'h1000 - }, - '{ - idx : L2Mem, - start_addr: cluster_l2_start_address, - end_addr : cluster_l2_end_address - } - }; - - localparam bit [DmaXbarCfg.NoSlvPorts-1:0] DMAEnableDefaultMstPort = '1; - axi_xbar #( - .Cfg (DmaXbarCfg ), - .ATOPs (0 ), - .slv_aw_chan_t (axi_mst_dma_aw_chan_t), - .mst_aw_chan_t (axi_slv_dma_aw_chan_t), - .w_chan_t (axi_mst_dma_w_chan_t ), - .slv_b_chan_t (axi_mst_dma_b_chan_t ), - .mst_b_chan_t (axi_slv_dma_b_chan_t ), - .slv_ar_chan_t (axi_mst_dma_ar_chan_t), - .mst_ar_chan_t (axi_slv_dma_ar_chan_t), - .slv_r_chan_t (axi_mst_dma_r_chan_t ), - .mst_r_chan_t (axi_slv_dma_r_chan_t ), - .slv_req_t (axi_mst_dma_req_t ), - .slv_resp_t (axi_mst_dma_resp_t ), - .mst_req_t (axi_slv_dma_req_t ), - .mst_resp_t (axi_slv_dma_resp_t ), - .rule_t (xbar_rule_t ) - ) i_axi_dma_xbar ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .test_i (1'b0 ), - .slv_ports_req_i (wide_axi_mst_req ), - .slv_ports_resp_o (wide_axi_mst_rsp ), - .mst_ports_req_o (wide_axi_slv_req ), - .mst_ports_resp_i (wide_axi_slv_rsp ), - .addr_map_i (dma_xbar_rule ), - .en_default_mst_port_i (DMAEnableDefaultMstPort), - .default_mst_port_i (dma_xbar_default_port ) - ); - - addr_t ext_dma_req_q_addr_nontrunc; - - axi_to_mem_interleaved #( - .axi_req_t (axi_slv_dma_req_t ), - .axi_resp_t (axi_slv_dma_resp_t ), - .AddrWidth (AxiAddrWidth ), - .DataWidth (AxiDataWidth ), - .IdWidth (WideIdWidthOut ), - .NumBanks (1 ), - .BufDepth (MemoryMacroLatency + 1) - ) i_axi_to_mem_dma ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .busy_o (/* Unused */ ), - .test_i (1'b0 ), - .axi_req_i (wide_axi_slv_req[TCDMDMA] ), - .axi_resp_o (wide_axi_slv_rsp[TCDMDMA] ), - .mem_req_o (ext_dma_req.q_valid ), - .mem_gnt_i (ext_dma_rsp.q_ready ), - .mem_addr_o (ext_dma_req_q_addr_nontrunc ), - .mem_wdata_o (ext_dma_req.q.data ), - .mem_strb_o (ext_dma_req.q.strb ), - .mem_atop_o (/* The DMA does not support atomics */), - .mem_we_o (ext_dma_req.q.write ), - .mem_rvalid_i (ext_dma_rsp.p_valid ), - .mem_rdata_i (ext_dma_rsp.p.data ) - ); - - assign ext_dma_req.q.addr = tcdm_addr_t'(ext_dma_req_q_addr_nontrunc); - assign ext_dma_req.q.amo = reqrsp_pkg::AMONone; - assign ext_dma_req.q.user = '0; - - spatz_tcdm_interconnect #( - .NumInp (1 ), - .NumOut (NrSuperBanks ), - .tcdm_req_t (tcdm_dma_req_t ), - .tcdm_rsp_t (tcdm_dma_rsp_t ), - .mem_req_t (mem_dma_req_t ), - .mem_rsp_t (mem_dma_rsp_t ), - .user_t (logic ), - .MemAddrWidth (TCDMMemAddrWidth ), - .DataWidth (AxiDataWidth ), - .MemoryResponseLatency (MemoryMacroLatency) - ) i_dma_interconnect ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .req_i (ext_dma_req), - .rsp_o (ext_dma_rsp), - .mem_req_o (sb_dma_req ), - .mem_rsp_i (sb_dma_rsp ) - ); - - // ---------------- - // Memory Subsystem - // ---------------- - for (genvar i = 0; i < NrSuperBanks; i++) begin : gen_tcdm_super_bank - - mem_req_t [BanksPerSuperBank-1:0] amo_req; - mem_rsp_t [BanksPerSuperBank-1:0] amo_rsp; - - mem_wide_narrow_mux #( - .NarrowDataWidth (NarrowDataWidth), - .WideDataWidth (AxiDataWidth ), - .mem_narrow_req_t (mem_req_t ), - .mem_narrow_rsp_t (mem_rsp_t ), - .mem_wide_req_t (mem_dma_req_t ), - .mem_wide_rsp_t (mem_dma_rsp_t ) - ) i_tcdm_mux ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .in_narrow_req_i (ic_req [i] ), - .in_narrow_rsp_o (ic_rsp [i] ), - .in_wide_req_i (sb_dma_req [i] ), - .in_wide_rsp_o (sb_dma_rsp [i] ), - .out_req_o (amo_req ), - .out_rsp_i (amo_rsp ), - .sel_wide_i (sb_dma_req[i].q_valid) - ); - - // generate banks of the superbank - for (genvar j = 0; j < BanksPerSuperBank; j++) begin : gen_tcdm_bank - - logic mem_cs, mem_wen; - tcdm_mem_addr_t mem_add; - tcdm_mem_addr_t mem_add_max; - strb_t mem_be; - data_t mem_rdata, mem_wdata; - tcdm_meta_t mem_req_meta; - assign mem_add_max = 0 - 1'b1; - - spatz_sram_wrapper #( - .NumBanks (L1BankPerWP ), - .NumWords (TCDMDepth ), - .ByteWidth (8 ), - .DataWidth (DataWidth ), - .MemoryResponseLatency (1 ), - .impl_in_t (impl_in_t ) - ) i_data_mem ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .spm_size_i (cfg_spm_size ), - /// Cache Side TODO: Connect cache - .cache_req_i (l1_cache_wp_req [j] ), - .cache_we_i (l1_cache_wp_we [j] ), - .cache_addr_i (l1_cache_wp_addr [j] ), - .cache_wdata_i(l1_cache_wp_wdata[j] ), - .cache_be_i (l1_cache_wp_be [j] ), - .cache_rdata_o(l1_cache_wp_rdata[j] ), - .cache_ready_o(l1_cache_wp_gnt [j] ), - /// SPM Side - .spm_req_i (mem_cs ), - .spm_we_i (mem_wen ), - .spm_addr_i (mem_add_max - mem_add), // swap the position of stack and data - .spm_wdata_i (mem_wdata ), - .spm_be_i (mem_be ), - .spm_rdata_o (mem_rdata ), - /// SRAM Configuration - .impl_i (impl_l1d_data[j] ) - ); - - data_t amo_rdata_local; - - // TODO(zarubaf): Share atomic units between mutltiple cuts - snitch_amo_shim #( - .AddrMemWidth ( TCDMMemAddrWidth ), - .DataWidth ( DataWidth ), - .CoreIDWidth ( CoreIDWidth ) - ) i_amo_shim ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .valid_i (amo_req[j].q_valid ), - .ready_o (amo_rsp[j].q_ready ), - .addr_i (amo_req[j].q.addr ), - .write_i (amo_req[j].q.write ), - .wdata_i (amo_req[j].q.data ), - .wstrb_i (amo_req[j].q.strb ), - .core_id_i (amo_req[j].q.user.core_id ), - .is_core_i (amo_req[j].q.user.is_core ), - .rdata_o (amo_rdata_local ), - .amo_i (amo_req[j].q.amo ), - .mem_req_o (mem_cs ), - .mem_add_o (mem_add ), - .mem_wen_o (mem_wen ), - .mem_wdata_o (mem_wdata ), - .mem_be_o (mem_be ), - .mem_rdata_i (mem_rdata ), - .dma_access_i (sb_dma_req[i].q_valid ), - // TODO(zarubaf): Signal AMO conflict somewhere. Socregs? - .amo_conflict_o (/* Unused */ ) - ); - - // Insert a pipeline register at the output of each SRAM. - shift_reg #( - .dtype(data_t ), - .Depth(int'(RegisterTCDMCuts)) - ) i_sram_pipe ( - .clk_i (clk_i ), - .rst_ni(rst_ni ), - .d_i (amo_rdata_local ), - .d_o (amo_rsp[j].p.data) - ); - - // delay the req_id two cycles: 1 for bank access, 1 for reg - shift_reg #( - .dtype(tcdm_meta_t ), - .Depth(int'(RegisterTCDMCuts)) - ) i_reqid_pipe1 ( - .clk_i (clk_i ), - .rst_ni(rst_ni ), - .d_i ({amo_req[j].q.user.req_id, amo_req[j].q.write}), - .d_o (mem_req_meta ) - ); - shift_reg #( - .dtype(tcdm_meta_t ), - .Depth(int'(RegisterTCDMCuts)) - ) i_reqid_pipe2 ( - .clk_i (clk_i ), - .rst_ni(rst_ni ), - .d_i (mem_req_meta ), - .d_o ({amo_rsp[j].p.user.req_id, amo_rsp[j].p.write}) - ); - - // tie unused field to 0 - // TODO: remove these fields - assign amo_rsp[j].p.user.core_id = '0; - assign amo_rsp[j].p.user.is_core = '0; - end - end - - logic [NrTCDMPortsCores-1:0] unmerge_pready, strb_hdl_pready, cache_pready; - assign spm_size = cfg_spm_size * L1Associativity * L1LineWidth / 2; - - // split the requests for spm or cache from core side - spatz_addr_mapper #( - .NumIO (NrTCDMPortsCores ), - .AddrWidth (L1AddrWidth ), - .SPMAddrWidth (SPMAddrWidth ), - .DataWidth (DataWidth ), - .mem_req_t (tcdm_req_t ), - .mem_rsp_t (tcdm_rsp_t ), - .mem_rsp_chan_t (tcdm_rsp_chan_t ), - .spm_req_t (spm_req_t ), - .spm_rsp_t (spm_rsp_t ) - ) i_tcdm_mapper ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - // Input - .mem_req_i (tcdm_req ), - .mem_rsp_o (tcdm_rsp ), - .error_o (spm_error ), - // Address - .tcdm_start_address_i (tcdm_start_address[L1AddrWidth-1:0] ), - .tcdm_end_address_i (tcdm_end_address[L1AddrWidth-1:0] ), - .spm_size_i (spm_size ), - .flush_i (l1d_busy ), - // Output - .spm_req_o (spm_req ), - .spm_rsp_i (spm_rsp ), - .cache_req_o (unmerge_req ), - .cache_pready_o (unmerge_pready ), - .cache_rsp_i (unmerge_rsp ) - ); - - localparam int unsigned NumIOPerCore = get_tcdm_ports(0); - logic [NrTCDMPortsCores-1:0] strb_req_ack; - - spatz_strbreq_merge_tree #( - .NumIO (NrTCDMPortsCores ), - .NumOutstandingMem (NumSpatzOutstandingLoads[0] ), - .MergeNum (NrTCDMPortsCores - NrCores ), - .DataWidth (DataWidth ), - .mem_req_t (tcdm_req_t ), - .mem_rsp_t (tcdm_rsp_t ), - .req_id_t (reqid_t ), - .tcdm_user_t (tcdm_user_t ) - ) i_strbreq_merge_tree ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .unmerge_req_i (unmerge_req ), - .unmerge_pready_i(unmerge_pready ), - .merge_rsp_i (strb_hdl_rsp ), - .merge_req_o (strb_hdl_req ), - .merge_pready_o (strb_hdl_pready ), - .unmerge_rsp_o (unmerge_rsp ) - ); - - for (genvar j = 0; j < NrTCDMPortsCores; j++) begin: gen_strb_hdlr - spatz_strbreq_handler #( - .DataWidth (DataWidth ), - .mem_req_t (tcdm_req_t ), - .mem_rsp_t (tcdm_rsp_t ), - .reqrsp_user_t (tcdm_user_t ) - ) i_strbreq_handler ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .strb_req_i (strb_hdl_req[j] ), - .strb_rsp_ready_i (strb_hdl_pready[j] ), - .strb_rsp_i (cache_rsp[j] ), - .strb_req_o (cache_req[j] ), - .strb_rsp_ready_o (cache_pready[j] ), - .strb_rsp_o (strb_hdl_rsp[j] ) - ); - - assign cache_req_valid[j] = cache_req[j].q_valid; - assign cache_rsp_ready[j] = cache_pready[j]; - assign cache_req_addr[j] = cache_req[j].q.addr; - assign cache_req_meta[j] = cache_req[j].q.user; - assign cache_req_write[j] = cache_req[j].q.write; - assign cache_req_data[j] = cache_req[j].q.data; - - assign cache_rsp[j].p_valid = cache_rsp_valid[j]; - assign cache_rsp[j].q_ready = cache_req_ready[j]; - assign cache_rsp[j].p.data = cache_rsp_data[j]; - assign cache_rsp[j].p.user = cache_rsp_meta[j]; - - assign cache_rsp[j].p.write = cache_rsp_write[j]; - end - - flamingo_spatz_cache_ctrl #( - // Core - .NumPorts (NrTCDMPortsCores ), - .CoalExtFactor (L1CoalFactor ), - .AddrWidth (L1AddrWidth ), - .WordWidth (DataWidth ), - // Cache - .NumCacheEntry (L1NumEntry ), - .CacheLineWidth (L1LineWidth ), - .SetAssociativity (L1Associativity ), - .BankFactor (L1BankFactor ), - // Type - .core_meta_t (tcdm_user_t ), - .impl_in_t (impl_in_t ), - .axi_req_t (axi_mst_dma_req_t ), - .axi_resp_t (axi_mst_dma_resp_t) - ) i_l1_controller ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .impl_i (impl_l1d_fifo ), - // Sync Control - .cache_sync_valid_i (l1d_insn_valid ), - .cache_sync_ready_o (l1d_insn_ready ), - .cache_sync_insn_i (l1d_insn ), - // SPM Size - // The calculation of spm region in cache is different - // than other modules (needs to times 2) - .bank_depth_for_SPM_i ((cfg_spm_size<<1) ), - // Request - .core_req_valid_i (cache_req_valid ), - .core_req_ready_o (cache_req_ready ), - .core_req_addr_i (cache_req_addr ), - .core_req_meta_i (cache_req_meta ), - .core_req_write_i (cache_req_write ), - .core_req_wdata_i (cache_req_data ), - // Response - .core_resp_valid_o (cache_rsp_valid ), - .core_resp_ready_i (cache_rsp_ready ), - .core_resp_write_o (cache_rsp_write ), - .core_resp_data_o (cache_rsp_data ), - .core_resp_meta_o (cache_rsp_meta ), - // AXI refill - .axi_req_o (wide_axi_mst_req[DCache] ), - .axi_resp_i (wide_axi_mst_rsp[DCache] ), - // Tag Banks - .tcdm_tag_bank_req_o (l1_tag_bank_req ), - .tcdm_tag_bank_we_o (l1_tag_bank_we ), - .tcdm_tag_bank_addr_o (l1_tag_bank_addr ), - .tcdm_tag_bank_wdata_o (l1_tag_bank_wdata ), - .tcdm_tag_bank_be_o (l1_tag_bank_be ), - .tcdm_tag_bank_rdata_i (l1_tag_bank_rdata ), - // Data Banks - .tcdm_data_bank_req_o (l1_data_bank_req ), - .tcdm_data_bank_we_o (l1_data_bank_we ), - .tcdm_data_bank_addr_o (l1_data_bank_addr ), - .tcdm_data_bank_wdata_o(l1_data_bank_wdata ), - .tcdm_data_bank_be_o (l1_data_bank_be ), - .tcdm_data_bank_rdata_i(l1_data_bank_rdata ), - .tcdm_data_bank_gnt_i (l1_data_bank_gnt ) - ); - - for (genvar j = 0; j < L1NumTagBank; j++) begin: gen_l1_tag_banks - tc_sram_impl #( - .NumWords (L1CacheWayEntry/L1BankFactor), - .DataWidth ($bits(data_t) ), - .ByteWidth ($bits(data_t) ), - .NumPorts (1 ), - .Latency (1 ), - .SimInit ("zeros" ), - .impl_in_t (impl_in_t ) - ) i_meta_bank ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .impl_i (impl_l1d_tag [j]), - .impl_o (/* unsed */ ), - .req_i (l1_tag_bank_req [j]), - .we_i (l1_tag_bank_we [j]), - .addr_i (l1_tag_bank_addr [j]), - .wdata_i(l1_tag_bank_wdata[j]), - .be_i (l1_tag_bank_be [j]), - .rdata_o(l1_tag_bank_rdata[j]) - ); - end - - for (genvar i = 0; i < L1NumWrapper; i++) begin - for (genvar j = 0; j < L1Associativity*L1BankFactor; j++) begin - assign l1_cache_wp_req [i][j] = l1_data_bank_req [i + j*L1NumWrapper]; - assign l1_cache_wp_we [i][j] = l1_data_bank_we [i + j*L1NumWrapper]; - assign l1_cache_wp_addr [i][j] = l1_data_bank_addr [i + j*L1NumWrapper]; - assign l1_cache_wp_wdata[i][j] = l1_data_bank_wdata[i + j*L1NumWrapper]; - assign l1_cache_wp_be [i][j] = (l1_data_bank_be [i + j*L1NumWrapper]) ? {(NarrowDataWidth/8){1'b1}} : '0; - - assign l1_data_bank_rdata[i + j*L1NumWrapper] = l1_cache_wp_rdata[i][j]; - assign l1_data_bank_gnt [i + j*L1NumWrapper] = l1_cache_wp_gnt [i][j]; - end - end - - // We have multiple banks form a pesudo bank (BankWP) - spatz_tcdm_interconnect #( - .NumInp (NumTCDMIn ), - .NumOut (L1NumWrapper ), - .tcdm_req_t (spm_req_t ), - .tcdm_rsp_t (spm_rsp_t ), - .mem_req_t (mem_req_t ), - .mem_rsp_t (mem_rsp_t ), - .MemAddrWidth (TCDMMemAddrWidth ), - .DataWidth (DataWidth ), - .user_t (tcdm_user_t ), - .MemoryResponseLatency (1 + RegisterTCDMCuts) - ) i_tcdm_interconnect ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .req_i ({axi_soc_req, spm_req} ), - .rsp_o ({axi_soc_rsp, spm_rsp} ), - .mem_req_o (ic_req ), - .mem_rsp_i (ic_rsp ) - ); - - hive_req_t [NrCores-1:0] hive_req; - hive_rsp_t [NrCores-1:0] hive_rsp; - - for (genvar i = 0; i < NrCores; i++) begin : gen_core - localparam int unsigned TcdmPorts = get_tcdm_ports(i); - localparam int unsigned TcdmPortsOffs = get_tcdm_port_offs(i); - - axi_mst_dma_req_t axi_dma_req; - axi_mst_dma_resp_t axi_dma_res; - interrupts_t irq; - dma_events_t dma_core_events; - - sync #(.STAGES (2)) - i_sync_debug (.clk_i, .rst_ni, .serial_i (debug_req_i[i]), .serial_o (irq.debug)); - sync #(.STAGES (2)) - i_sync_meip (.clk_i, .rst_ni, .serial_i (meip_i[i]), .serial_o (irq.meip)); - sync #(.STAGES (2)) - i_sync_mtip (.clk_i, .rst_ni, .serial_i (mtip_i[i]), .serial_o (irq.mtip)); - sync #(.STAGES (2)) - i_sync_msip (.clk_i, .rst_ni, .serial_i (msip_i[i]), .serial_o (irq.msip)); - assign irq.mcip = cl_interrupt[i]; - - tcdm_req_t [TcdmPorts-1:0] tcdm_req_wo_user; - - logic [31:0] hart_id; - assign hart_id = hart_base_id_i + i; - - spatz_mempool_cc #( - .BootAddr ( BootAddr ), - .RVE ( 0 ), - .RVM ( 1 ), - .RVV ( RVV ), - .XFVEC ( XFVEC ), - .XFDOTP ( XFDOTP ), - .XFAUX ( XFAUX ), - .RVF ( RVF ), - .RVD ( RVD ), - .XF16 ( XF16 ), - .XF16ALT ( XF16ALT ), - .XF8 ( XF8 ), - .XDivSqrt ( XDivSqrt ), - .NumMemPortsPerSpatz ( NumMemPortsPerSpatz ), - .TCDMPorts ( NumDataPortsPerCore ), - .BankOffset ( ByteOffset+$clog2(NumBanksPerTile)), - .NumCoresPerTile ( NumCoresPerTile ), - .TileLen ( $clog2(NumTiles) ), - .NumBanks ( NumBanks ) - ) i_spatz_cc ( - .clk_i (clk_i ), - .rst_i (!rst_ni ), - .hart_id_i (hart_id ), - // IMEM Port - .inst_addr_o (snitch_inst_addr[c/NumCoresPerCache][c%NumCoresPerCache] ), - .inst_data_i (snitch_inst_data[c/NumCoresPerCache][c%NumCoresPerCache] ), - .inst_valid_o (snitch_inst_valid[c/NumCoresPerCache][c%NumCoresPerCache]), - .inst_ready_i (snitch_inst_ready[c/NumCoresPerCache][c%NumCoresPerCache]), - // Data Ports - .data_qaddr_o (snitch_data_qaddr[i] ), - .data_qwrite_o (snitch_data_qwrite[i] ), - .data_qamo_o (snitch_data_qamo[i] ), - .data_qdata_o (snitch_data_qdata[i] ), - .data_qstrb_o (snitch_data_qstrb[i] ), - .data_qid_o (snitch_data_qid[i] ), - .data_qvalid_o (snitch_data_qvalid[i] ), - .data_qready_i (snitch_data_qready[i] ), - .data_pdata_i (snitch_data_pdata[i] ), - .data_pwrite_i (snitch_data_pwrite[i] ), - .data_perror_i (snitch_data_perror[i] ), - .data_pid_i (snitch_data_pid[i] ), - .data_pvalid_i (snitch_data_pvalid[i] ), - .data_pready_o (snitch_data_pready[i] ), - .wake_up_sync_i(wake_up_q[i] ), - // Core Events - .core_events_o (/* Unused */ ) - ); - for (genvar j = 0; j < TcdmPorts; j++) begin : gen_tcdm_user - always_comb begin - tcdm_req[TcdmPortsOffs+j].q = tcdm_req_wo_user[j].q; - tcdm_req[TcdmPortsOffs+j].q.user.core_id = i[CoreIDWidth-1:0]; - tcdm_req[TcdmPortsOffs+j].q.user.is_core = 1; - tcdm_req[TcdmPortsOffs+j].q_valid = tcdm_req_wo_user[j].q_valid; - end - end - if (Xdma[i]) begin : gen_dma_connection - assign wide_axi_mst_req[SDMAMst] = axi_dma_req; - assign axi_dma_res = wide_axi_mst_rsp[SDMAMst]; - assign dma_events = dma_core_events; - end else begin - assign axi_dma_res = '0; - end - end - - // ---------------- - // Instruction Cache - // ---------------- - - addr_t [NrCores-1:0] inst_addr; - logic [NrCores-1:0] inst_cacheable; - logic [NrCores-1:0][31:0] inst_data; - logic [NrCores-1:0] inst_valid; - logic [NrCores-1:0] inst_ready; - logic [NrCores-1:0] inst_error; - logic [NrCores-1:0] flush_valid; - logic [NrCores-1:0] flush_ready; - - for (genvar i = 0; i < NrCores; i++) begin : gen_unpack_icache - assign inst_addr[i] = hive_req[i].inst_addr; - assign inst_cacheable[i] = hive_req[i].inst_cacheable; - assign inst_valid[i] = hive_req[i].inst_valid; - assign flush_valid[i] = hive_req[i].flush_i_valid; - assign hive_rsp[i] = '{ - inst_data : inst_data[i], - inst_ready : inst_ready[i], - inst_error : inst_error[i], - flush_i_ready: flush_ready[i], - default : '0 - }; - end - - snitch_icache #( - .NR_FETCH_PORTS ( NrCores ), - .L0_LINE_COUNT ( 8 ), - .LINE_WIDTH ( ICacheLineWidth ), - .LINE_COUNT ( ICacheLineCount ), - .SET_COUNT ( ICacheSets ), - .FETCH_AW ( AxiAddrWidth ), - .FETCH_DW ( 32 ), - .FILL_AW ( AxiAddrWidth ), - .FILL_DW ( AxiDataWidth ), - .EARLY_LATCH ( 0 ), - .L0_EARLY_TAG_WIDTH ( snitch_pkg::PAGE_SHIFT - $clog2(ICacheLineWidth/8) ), - .ISO_CROSSING ( 1'b0 ), - .axi_req_t ( axi_mst_dma_req_t ), - .axi_rsp_t ( axi_mst_dma_resp_t ), - .sram_cfg_data_t ( impl_in_t ), - .sram_cfg_tag_t ( impl_in_t ) - ) i_snitch_icache ( - .clk_i ( clk_i ), - .clk_d2_i ( clk_i ), - .rst_ni ( rst_ni ), - .enable_prefetching_i ( icache_prefetch_enable ), - .icache_events_o ( icache_events ), - .flush_valid_i ( flush_valid ), - .flush_ready_o ( flush_ready ), - .inst_addr_i ( inst_addr ), - .inst_cacheable_i ( inst_cacheable ), - .inst_data_o ( inst_data ), - .inst_valid_i ( inst_valid ), - .inst_ready_o ( inst_ready ), - .inst_error_o ( inst_error ), - .sram_cfg_tag_i ( impl_l1i_tag ), - .sram_cfg_data_i ( impl_l1i_data ), - .axi_req_o ( wide_axi_mst_req[ICache] ), - .axi_rsp_i ( wide_axi_mst_rsp[ICache] ) - ); - - // -------- - // Cores SoC - // -------- - spatz_barrier #( - .AddrWidth (AxiAddrWidth ), - .NrPorts (NrCores ), - .dreq_t (reqrsp_req_t ), - .drsp_t (reqrsp_rsp_t ) - ) i_snitch_barrier ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .in_req_i (core_req ), - .in_rsp_o (core_rsp ), - .out_req_o (filtered_core_req ), - .out_rsp_i (filtered_core_rsp ), - .cluster_periph_start_address_i (cluster_periph_start_address) - ); - - reqrsp_req_t core_to_axi_req; - reqrsp_rsp_t core_to_axi_rsp; - user_t cluster_user; - // Atomic ID, needs to be unique ID of cluster - // cluster_id + HartIdOffset + 1 (because 0 is for non-atomic masters) - assign cluster_user = (hart_base_id_i / NrCores) + (hart_base_id_i % NrCores) + 1'b1; - - reqrsp_mux #( - .NrPorts (NrCores ), - .AddrWidth (AxiAddrWidth ), - .DataWidth (NarrowDataWidth ), - .req_t (reqrsp_req_t ), - .rsp_t (reqrsp_rsp_t ), - .RespDepth (2 ) - ) i_reqrsp_mux_core ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .slv_req_i (filtered_core_req), - .slv_rsp_o (filtered_core_rsp), - .mst_req_o (core_to_axi_req ), - .mst_rsp_i (core_to_axi_rsp ), - .idx_o (/*unused*/ ) - ); - - reqrsp_to_axi #( - .DataWidth (NarrowDataWidth), - .UserWidth (NarrowUserWidth), - .reqrsp_req_t (reqrsp_req_t ), - .reqrsp_rsp_t (reqrsp_rsp_t ), - .axi_req_t (axi_mst_req_t ), - .axi_rsp_t (axi_mst_resp_t ) - ) i_reqrsp_to_axi_core ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .user_i (cluster_user ), - .reqrsp_req_i (core_to_axi_req ), - .reqrsp_rsp_o (core_to_axi_rsp ), - .axi_req_o (narrow_axi_mst_req[CoreReq]), - .axi_rsp_i (narrow_axi_mst_rsp[CoreReq]) - ); - - xbar_rule_t [NrNarrowRules-1:0] cluster_xbar_rules; - - assign cluster_xbar_rules = '{ - '{ - idx : TCDM, - start_addr: tcdm_start_address, - end_addr : tcdm_end_address - }, - '{ - idx : ClusterPeripherals, - start_addr: cluster_periph_start_address, - end_addr : cluster_periph_end_address - } - }; - - localparam bit [ClusterXbarCfg.NoSlvPorts-1:0] ClusterEnableDefaultMstPort = '1; - localparam logic [ClusterXbarCfg.NoSlvPorts-1:0][cf_math_pkg::idx_width(ClusterXbarCfg.NoMstPorts)-1:0] ClusterXbarDefaultPort = '{default: SoC}; - - axi_xbar #( - .Cfg (ClusterXbarCfg ), - .slv_aw_chan_t (axi_mst_aw_chan_t), - .mst_aw_chan_t (axi_slv_aw_chan_t), - .w_chan_t (axi_mst_w_chan_t ), - .slv_b_chan_t (axi_mst_b_chan_t ), - .mst_b_chan_t (axi_slv_b_chan_t ), - .slv_ar_chan_t (axi_mst_ar_chan_t), - .mst_ar_chan_t (axi_slv_ar_chan_t), - .slv_r_chan_t (axi_mst_r_chan_t ), - .mst_r_chan_t (axi_slv_r_chan_t ), - .slv_req_t (axi_mst_req_t ), - .slv_resp_t (axi_mst_resp_t ), - .mst_req_t (axi_slv_req_t ), - .mst_resp_t (axi_slv_resp_t ), - .rule_t (xbar_rule_t ) - ) i_cluster_xbar ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .test_i (1'b0 ), - .slv_ports_req_i (narrow_axi_mst_req ), - .slv_ports_resp_o (narrow_axi_mst_rsp ), - .mst_ports_req_o (narrow_axi_slv_req ), - .mst_ports_resp_i (narrow_axi_slv_rsp ), - .addr_map_i (cluster_xbar_rules ), - .en_default_mst_port_i (ClusterEnableDefaultMstPort), - .default_mst_port_i (ClusterXbarDefaultPort ) - ); - - // --------- - // Slaves - // --------- - // 1. TCDM - // Add an adapter that allows access from AXI to the TCDM. - axi_to_tcdm #( - .axi_req_t (axi_slv_req_t ), - .axi_rsp_t (axi_slv_resp_t ), - .tcdm_req_t (spm_req_t ), - .tcdm_rsp_t (spm_rsp_t ), - .AddrWidth (AxiAddrWidth ), - .DataWidth (NarrowDataWidth ), - .IdWidth (NarrowIdWidthOut ), - .BufDepth (MemoryMacroLatency + 1) - ) i_axi_to_tcdm ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .axi_req_i (narrow_axi_slv_req[TCDM]), - .axi_rsp_o (narrow_axi_slv_rsp[TCDM]), - .tcdm_req_o (axi_soc_req ), - .tcdm_rsp_i (axi_soc_rsp ) - ); - - // 2. Peripherals - axi_to_reg #( - .ADDR_WIDTH (AxiAddrWidth ), - .DATA_WIDTH (NarrowDataWidth ), - .AXI_MAX_WRITE_TXNS (1 ), - .AXI_MAX_READ_TXNS (1 ), - .DECOUPLE_W (0 ), - .ID_WIDTH (NarrowIdWidthOut ), - .USER_WIDTH (NarrowUserWidth ), - .axi_req_t (axi_slv_req_t ), - .axi_rsp_t (axi_slv_resp_t ), - .reg_req_t (reg_req_t ), - .reg_rsp_t (reg_rsp_t ) - ) i_axi_to_reg ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .testmode_i (1'b0 ), - .axi_req_i (narrow_axi_slv_req[ClusterPeripherals]), - .axi_rsp_o (narrow_axi_slv_rsp[ClusterPeripherals]), - .reg_req_o (reg_req ), - .reg_rsp_i (reg_rsp ) - ); - - spatz_cluster_peripheral #( - .AddrWidth (AxiAddrWidth ), - .SPMWidth ($clog2(L1NumSet)), - .reg_req_t (reg_req_t ), - .reg_rsp_t (reg_rsp_t ), - .tcdm_events_t (tcdm_events_t ), - .dma_events_t (dma_events_t ), - .NrCores (NrCores ) - ) i_snitch_cluster_peripheral ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .reg_req_i (reg_req ), - .reg_rsp_o (reg_rsp ), - /// The TCDM always starts at the cluster base. - .tcdm_start_address_i (tcdm_start_address ), - .tcdm_end_address_i (tcdm_end_address ), - .icache_prefetch_enable_o (icache_prefetch_enable), - .cl_clint_o (cl_interrupt ), - .cluster_hart_base_id_i (hart_base_id_i ), - .core_events_i (core_events ), - .tcdm_events_i (tcdm_events ), - .dma_events_i (dma_events ), - .icache_events_i (icache_events ), - .cluster_probe_o (cluster_probe_o ), - .l1d_spm_size_o (cfg_spm_size ), - .l1d_insn_o (l1d_insn ), - .l1d_insn_valid_o (l1d_insn_valid ), - .l1d_insn_ready_i (l1d_insn_ready ), - .l1d_busy_o (l1d_busy ) - ); - - // 3. BootROM - axi_to_reg #( - .ADDR_WIDTH (AxiAddrWidth ), - .DATA_WIDTH (AxiDataWidth ), - .AXI_MAX_WRITE_TXNS (1 ), - .AXI_MAX_READ_TXNS (1 ), - .DECOUPLE_W (0 ), - .ID_WIDTH (WideIdWidthOut ), - .USER_WIDTH (AxiUserWidth ), - .axi_req_t (axi_slv_dma_req_t ), - .axi_rsp_t (axi_slv_dma_resp_t), - .reg_req_t (reg_dma_req_t ), - .reg_rsp_t (reg_dma_rsp_t ) - ) i_axi_to_reg_bootrom ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .testmode_i (1'b0 ), - .axi_req_i (wide_axi_slv_req[BootROM]), - .axi_rsp_o (wide_axi_slv_rsp[BootROM]), - .reg_req_o (bootrom_reg_req ), - .reg_rsp_i (bootrom_reg_rsp ) - ); - - bootrom i_bootrom ( - .clk_i (clk_i ), - .req_i (bootrom_reg_req.valid ), - .addr_i (addr_t'(bootrom_reg_req.addr)), - .rdata_o(bootrom_reg_rsp.rdata ) - ); - `FF(bootrom_reg_rsp.ready, bootrom_reg_req.valid, 1'b0) - assign bootrom_reg_rsp.error = 1'b0; - - // Upsize the narrow SoC connection - `AXI_TYPEDEF_ALL(axi_mst_dma_narrow, addr_t, id_dma_mst_t, data_t, strb_t, user_t) - axi_mst_dma_narrow_req_t narrow_axi_slv_req_soc; - axi_mst_dma_narrow_resp_t narrow_axi_slv_resp_soc; - - axi_iw_converter #( - .AxiAddrWidth (AxiAddrWidth ), - .AxiDataWidth (NarrowDataWidth ), - .AxiUserWidth (AxiUserWidth ), - .AxiSlvPortIdWidth (NarrowIdWidthOut ), - .AxiSlvPortMaxUniqIds (1 ), - .AxiSlvPortMaxTxnsPerId(1 ), - .AxiSlvPortMaxTxns (1 ), - .AxiMstPortIdWidth (WideIdWidthIn ), - .AxiMstPortMaxUniqIds (1 ), - .AxiMstPortMaxTxnsPerId(1 ), - .slv_req_t (axi_slv_req_t ), - .slv_resp_t (axi_slv_resp_t ), - .mst_req_t (axi_mst_dma_narrow_req_t ), - .mst_resp_t (axi_mst_dma_narrow_resp_t) - ) i_soc_port_iw_convert ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .slv_req_i (narrow_axi_slv_req[SoC] ), - .slv_resp_o (narrow_axi_slv_rsp[SoC] ), - .mst_req_o (narrow_axi_slv_req_soc ), - .mst_resp_i (narrow_axi_slv_resp_soc ) - ); - - axi_dw_converter #( - .AxiAddrWidth (AxiAddrWidth ), - .AxiIdWidth (WideIdWidthIn ), - .AxiMaxReads (2 ), - .AxiSlvPortDataWidth(NarrowDataWidth ), - .AxiMstPortDataWidth(AxiDataWidth ), - .ar_chan_t (axi_mst_dma_ar_chan_t ), - .aw_chan_t (axi_mst_dma_aw_chan_t ), - .b_chan_t (axi_mst_dma_b_chan_t ), - .slv_r_chan_t (axi_mst_dma_narrow_r_chan_t), - .slv_w_chan_t (axi_mst_dma_narrow_b_chan_t), - .axi_slv_req_t (axi_mst_dma_narrow_req_t ), - .axi_slv_resp_t (axi_mst_dma_narrow_resp_t ), - .mst_r_chan_t (axi_mst_dma_r_chan_t ), - .mst_w_chan_t (axi_mst_dma_w_chan_t ), - .axi_mst_req_t (axi_mst_dma_req_t ), - .axi_mst_resp_t (axi_mst_dma_resp_t ) - ) i_soc_port_dw_upsize ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .slv_req_i (narrow_axi_slv_req_soc ), - .slv_resp_o (narrow_axi_slv_resp_soc ), - .mst_req_o (wide_axi_mst_req[CoreReqWide]), - .mst_resp_i (wide_axi_mst_rsp[CoreReqWide]) - ); - - // -------------------- - // TCDM event counters - // -------------------- - logic [NrTCDMPortsCores-1:0] flat_acc, flat_con; - for (genvar i = 0; i < NrTCDMPortsCores; i++) begin : gen_event_counter - `FFARN(flat_acc[i], tcdm_req[i].q_valid, '0, clk_i, rst_ni) - `FFARN(flat_con[i], tcdm_req[i].q_valid & ~tcdm_rsp[i].q_ready, '0, clk_i, rst_ni) - end - - popcount #( - .INPUT_WIDTH ( NrTCDMPortsCores ) - ) i_popcount_req ( - .data_i ( flat_acc ), - .popcount_o ( tcdm_events.inc_accessed ) - ); - - popcount #( - .INPUT_WIDTH ( NrTCDMPortsCores ) - ) i_popcount_con ( - .data_i ( flat_con ), - .popcount_o ( tcdm_events.inc_congested ) - ); - - // ------------- - // Sanity Checks - // ------------- - // Sanity check the parameters. Not every configuration makes sense. - `ASSERT_INIT(CheckSuperBankSanity, NrBanks >= BanksPerSuperBank); - `ASSERT_INIT(CheckSuperBankFactor, (NrBanks % BanksPerSuperBank) == 0); - // Check that the cluster base address aligns to the TCDMSize. - `ASSERT(ClusterBaseAddrAlign, ((TCDMSize - 1) & cluster_base_addr_i) == 0) - // Make sure we only have one DMA in the system. - `ASSERT_INIT(NumberDMA, $onehot0(Xdma)) - -endmodule diff --git a/hardware/src/cachepool_tile.sv b/hardware/src/cachepool_tile.sv deleted file mode 100644 index db35677..0000000 --- a/hardware/src/cachepool_tile.sv +++ /dev/null @@ -1,369 +0,0 @@ -// Copyright 2021 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -`include "mempool/mempool.svh" - -/* verilator lint_off DECLFILENAME */ -module cachepool_tile - import cachepool_pkg::*; - import cf_math_pkg::idx_width; -#( - // TCDM - parameter addr_t TCDMBaseAddr = 32'b0, - // Boot address - parameter logic [31:0] BootAddr = 32'h0000_1000, - // Dependent parameters. DO NOT CHANGE. - parameter int unsigned NumICaches = NumCoresPerTile / NumCoresPerCache -) ( - // Clock and reset - input logic clk_i, - input logic rst_ni, - // Scan chain - input logic scan_enable_i, - input logic scan_data_i, - output logic scan_data_o, - // Tile ID - input logic [idx_width(NumTiles)-1:0] tile_id_i, - // TCDM Master interfaces - output `STRUCT_VECT(tcdm_master_req_t, [NumGroups+NumSubGroupsPerGroup-1-1:0]) tcdm_master_req_o, - output logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_master_req_valid_o, - input logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_master_req_ready_i, - input `STRUCT_VECT(tcdm_master_resp_t, [NumGroups+NumSubGroupsPerGroup-1-1:0]) tcdm_master_resp_i, - input logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_master_resp_valid_i, - output logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_master_resp_ready_o, - // TCDM slave interfaces - input `STRUCT_VECT(tcdm_slave_req_t, [NumGroups+NumSubGroupsPerGroup-1-1:0]) tcdm_slave_req_i, - input logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_slave_req_valid_i, - output logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_slave_req_ready_o, - output `STRUCT_VECT(tcdm_slave_resp_t, [NumGroups+NumSubGroupsPerGroup-1-1:0]) tcdm_slave_resp_o, - output logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_slave_resp_valid_o, - input logic [NumGroups+NumSubGroupsPerGroup-1-1:0] tcdm_slave_resp_ready_i, - // TCDM DMA interfaces - input `STRUCT_PORT(tcdm_dma_req_t) tcdm_dma_req_i, - input logic tcdm_dma_req_valid_i, - output logic tcdm_dma_req_ready_o, - output `STRUCT_PORT(tcdm_dma_resp_t) tcdm_dma_resp_o, - output logic tcdm_dma_resp_valid_o, - input logic tcdm_dma_resp_ready_i, - // AXI Interface - output `STRUCT_PORT(axi_tile_req_t) axi_mst_req_o, - input `STRUCT_PORT(axi_tile_resp_t) axi_mst_resp_i, - // Wake up interface - input logic [NumCoresPerTile-1:0] wake_up_i -); - - // CachePool Tile will contains several Spatz CC and some cache banks - - /**************** - * Includes * - ****************/ - - `include "common_cells/registers.svh" - - /***************** - * Definitions * - *****************/ - - import snitch_pkg::dreq_t; - import snitch_pkg::dresp_t; - - typedef logic [idx_width(NumGroups)-1:0] group_id_t; - - // Local interconnect address width - typedef logic [idx_width(NumCoresPerTile*NumDataPortsPerCore + NumGroups + NumSubGroupsPerGroup-1)-1:0] local_req_interco_addr_t; - - - // L1 Data Cache Parameters - - /********************* - * Control Signals * - *********************/ - - - /*********** - * Cores * - ***********/ - - // Instruction interfaces - addr_t [NumICaches-1:0][NumCoresPerCache-1:0] snitch_inst_addr; - data_t [NumICaches-1:0][NumCoresPerCache-1:0] snitch_inst_data; - logic [NumICaches-1:0][NumCoresPerCache-1:0] snitch_inst_valid; - logic [NumICaches-1:0][NumCoresPerCache-1:0] snitch_inst_ready; - - // Data interfaces - addr_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qaddr; - logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qwrite; - amo_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qamo; - data_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qdata; - strb_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qstrb; - meta_id_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qid; - logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qvalid; - logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_qready; - data_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_pdata; - logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_pwrite; - logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_perror; - meta_id_t [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_pid; - logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_pvalid; - logic [NumCoresPerTile-1:0][NumDataPortsPerCore-1:0] snitch_data_pready; - - for (genvar c = 0; unsigned'(c) < NumCoresPerTile; c++) begin: gen_cores - logic [31:0] hart_id; - if (NumCoresPerTile == 1) begin - assign hart_id = unsigned'(tile_id_i); - end else begin - assign hart_id = {unsigned'(tile_id_i), c[idx_width(NumCoresPerTile)-1:0]}; - end - - spatz_mempool_cc #( - .BootAddr ( BootAddr ), - .RVE ( 0 ), - .RVM ( 1 ), - .RVV ( RVV ), - .XFVEC ( XFVEC ), - .XFDOTP ( XFDOTP ), - .XFAUX ( XFAUX ), - .RVF ( RVF ), - .RVD ( RVD ), - .XF16 ( XF16 ), - .XF16ALT ( XF16ALT ), - .XF8 ( XF8 ), - .XDivSqrt ( XDivSqrt ), - .NumMemPortsPerSpatz ( NumMemPortsPerSpatz ), - .TCDMPorts ( NumDataPortsPerCore ) - ) - riscv_core ( - .clk_i (clk_i ), - .rst_i (!rst_ni ), - .hart_id_i (hart_id ), - // IMEM Port - .inst_addr_o (snitch_inst_addr[c/NumCoresPerCache][c%NumCoresPerCache] ), - .inst_data_i (snitch_inst_data[c/NumCoresPerCache][c%NumCoresPerCache] ), - .inst_valid_o (snitch_inst_valid[c/NumCoresPerCache][c%NumCoresPerCache]), - .inst_ready_i (snitch_inst_ready[c/NumCoresPerCache][c%NumCoresPerCache]), - // Data Ports - .data_qaddr_o (snitch_data_qaddr[c] ), - .data_qwrite_o (snitch_data_qwrite[c] ), - .data_qamo_o (snitch_data_qamo[c] ), - .data_qdata_o (snitch_data_qdata[c] ), - .data_qstrb_o (snitch_data_qstrb[c] ), - .data_qid_o (snitch_data_qid[c] ), - .data_qvalid_o (snitch_data_qvalid[c] ), - .data_qready_i (snitch_data_qready[c] ), - .data_pdata_i (snitch_data_pdata[c] ), - .data_pwrite_i (snitch_data_pwrite[c] ), - .data_perror_i (snitch_data_perror[c] ), - .data_pid_i (snitch_data_pid[c] ), - .data_pvalid_i (snitch_data_pvalid[c] ), - .data_pready_o (snitch_data_pready[c] ), - .wake_up_sync_i(wake_up_q[c] ), - // Core Events - .core_events_o (/* Unused */ ) - ); - end - - /*********************** - * Instruction Cache * - ***********************/ - // Instruction interface - axi_core_req_t [NumICaches-1:0] axi_cache_req_d, axi_cache_req_q; - axi_core_resp_t [NumICaches-1:0] axi_cache_resp_d, axi_cache_resp_q; - - for (genvar c = 0; unsigned'(c) < NumICaches; c++) begin: gen_icaches - snitch_icache #( - .NR_FETCH_PORTS (NumCoresPerCache ), - /// Cache Line Width - .L0_LINE_COUNT (4 ), - .LINE_WIDTH (ICacheLineWidth ), - .LINE_COUNT (ICacheSizeByte / (ICacheSets * ICacheLineWidth / 8) ), - .SET_COUNT (ICacheSets ), - .FETCH_AW (AddrWidth ), - .FETCH_DW (DataWidth ), - .FILL_AW (AddrWidth ), - .FILL_DW (AxiDataWidth ), - .L1_TAG_SCM (1 ), - /// Make the early cache latch-based. This reduces latency at the cost of - /// increased combinatorial path lengths and the hassle of having latches in - /// the design. - .EARLY_LATCH (1 ), - .L0_EARLY_TAG_WIDTH (11 ), - .ISO_CROSSING (0 ), - .axi_req_t (axi_core_req_t ), - .axi_rsp_t (axi_core_resp_t ) - ) i_snitch_icache ( - .clk_i (clk_i ), - .clk_d2_i (clk_i ), - .rst_ni (rst_ni ), - .enable_prefetching_i (1'b1 ), - .icache_events_o (/* Unused */ ), - .flush_valid_i (1'b0 ), - .flush_ready_o (/* Unused */ ), - .inst_addr_i (snitch_inst_addr[c] ), - .inst_data_o (snitch_inst_data[c] ), - .inst_cacheable_i ({NumCoresPerCache{1'b1}}), - .inst_valid_i (snitch_inst_valid[c] ), - .inst_ready_o (snitch_inst_ready[c] ), - .inst_error_o (/* Unused */ ), - .axi_req_o (axi_cache_req_d[c] ), - .axi_rsp_i (axi_cache_resp_q[c] ) - ); - axi_cut #( - .aw_chan_t (axi_core_aw_t ), - .w_chan_t (axi_core_w_t ), - .b_chan_t (axi_core_b_t ), - .ar_chan_t (axi_core_ar_t ), - .r_chan_t (axi_core_r_t ), - .axi_req_t (axi_core_req_t ), - .axi_resp_t(axi_core_resp_t) - ) axi_cache_slice ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .slv_req_i (axi_cache_req_d[c] ), - .slv_resp_o(axi_cache_resp_q[c]), - .mst_req_o (axi_cache_req_q[c] ), - .mst_resp_i(axi_cache_resp_d[c]) - ); - end - - /***************** - * Cache Banks * - *****************/ - - stream_xbar #( - .NumInp (1 ), - .NumOut (NumSuperbanks ), - .payload_t(tcdm_dma_req_t) - ) i_dma_req_interco ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .flush_i(1'b0 ), - // External priority flag - .rr_i ('0 ), - // Master - .data_i (tcdm_dma_req_i_struct ), - .valid_i(tcdm_dma_req_valid_i ), - .ready_o(tcdm_dma_req_ready_o ), - .sel_i (tcdm_dma_req_i_struct.tgt_addr[idx_width(NumBanksPerTile)-1:$clog2(DmaNumWords)]), - // Slave - .data_o (tcdm_dma_req ), - .valid_o(tcdm_dma_req_valid ), - .ready_i(tcdm_dma_req_ready ), - .idx_o (/* Unused */ ) - ); - - - - // TODO: Add a XBar for bank selection - - for (genvar c = 0; unsigned'(c) < NumDCaches; c++) begin: gen_dcaches - flamingo_spatz_cache_ctrl #( - // Core - .NumPorts (L1DNumPorts ), - .CoalExtFactor (L1DCoalFactor ), - .AddrWidth (AddrWidth ), - .WordWidth (DataWidth ), - // Cache - .NumCacheEntry (L1DSizePerBank ), - .CacheLineWidth (L1DCacheLine ), - .SetAssociativity (L1DCacheWay ), - .BankFactor (L1DCacheBF ), - // Type - .core_meta_t ( ), - .impl_in_t ( ), - .axi_req_t ( ), - .axi_resp_t ( ) - ) i_l1_bank ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .impl_i ('0 ), - // Sync Control - .cache_sync_valid_i (l1d_insn_valid ), - .cache_sync_ready_o (l1d_insn_ready ), - .cache_sync_insn_i (l1d_insn ), - // SPM Size, DO WE NEED IT FOR CACHEPOOL? - .bank_depth_for_SPM_i (num_spm_lines ), - // Request - .core_req_valid_i (cache_req_valid[c] ), - .core_req_ready_o (cache_req_ready[c] ), - .core_req_addr_i (cache_req_addr[c] ), - .core_req_meta_i (cache_req_meta[c] ), - .core_req_write_i (cache_req_write[c] ), - .core_req_wdata_i (cache_req_data[c] ), - // Response - .core_resp_valid_o (cache_rsp_valid[c] ), - .core_resp_ready_i (cache_rsp_ready[c] ), - .core_resp_write_o (cache_rsp_write[c] ), - .core_resp_data_o (cache_rsp_data[c] ), - .core_resp_meta_o (cache_rsp_meta[c] ), - // AXI refill - .axi_req_o (l1_axi_mst_req[c] ), - .axi_resp_i (l1_axi_mst_rsp[c] ), - // Tag Banks - .tcdm_tag_bank_req_o (l1_tag_bank_req[c] ), - .tcdm_tag_bank_we_o (l1_tag_bank_we[c] ), - .tcdm_tag_bank_addr_o (l1_tag_bank_addr[c] ), - .tcdm_tag_bank_wdata_o (l1_tag_bank_wdata[c] ), - .tcdm_tag_bank_be_o (l1_tag_bank_be[c] ), - .tcdm_tag_bank_rdata_i (l1_tag_bank_rdata[c] ), - // Data Banks - .tcdm_data_bank_req_o (l1_data_bank_req[c] ), - .tcdm_data_bank_we_o (l1_data_bank_w[c] ), - .tcdm_data_bank_addr_o (l1_data_bank_addr[c] ), - .tcdm_data_bank_wdata_o(l1_data_bank_wdata[c] ), - .tcdm_data_bank_be_o (l1_data_bank_be[c] ), - .tcdm_data_bank_rdata_i(l1_data_bank_rdata[c] ), - .tcdm_data_bank_gnt_i (l1_data_bank_gnt[c] ) - ); - end - - - - /*************** - * Registers * - ***************/ - - - /**************************** - * Remote Interconnects * - ****************************/ - - - - /********************** - * Local Intercos * - **********************/ - - /******************* - * Core De/mux * - *******************/ - - - /**************** - * AXI Plug * - ****************/ - - - /****************** - * Assertions * - ******************/ - - // Check invariants. - if (BootAddr[1:0] != 2'b00) - $fatal(1, "[cachepool_tile] Boot address should be aligned in a 4-byte boundary."); - - if (NumCoresPerTile != 2**$clog2(NumCoresPerTile)) - $fatal(1, "[cachepool_tile] The number of cores per tile must be a power of two."); - - if (NumCores != unsigned'(2**$clog2(NumCores))) - $fatal(1, "[cachepool_tile] The number of cores must be a power of two."); - - if (NumBanksPerTile < 1) - $fatal(1, "[cachepool_tile] The number of banks per tile must be larger than one"); - - if (NumICaches != 1) - $error("NumICaches > 1 is not supported!"); - - if (DataWidth > AxiDataWidth) - $error("AxiDataWidth needs to be larger than DataWidth!"); - -endmodule : cachepool_tile diff --git a/hardware/src/cachepool_tile_simple.sv b/hardware/src/cachepool_tile_simple.sv deleted file mode 100644 index 1d1001d..0000000 --- a/hardware/src/cachepool_tile_simple.sv +++ /dev/null @@ -1,1515 +0,0 @@ -// Copyright 2025 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Author: Diyou Shen - -`include "axi/assign.svh" -`include "axi/typedef.svh" -`include "common_cells/assertions.svh" -`include "common_cells/registers.svh" -`include "mem_interface/assign.svh" -`include "mem_interface/typedef.svh" -`include "register_interface//assign.svh" -`include "register_interface/typedef.svh" -`include "reqrsp_interface/assign.svh" -`include "reqrsp_interface/typedef.svh" -`include "snitch_vm/typedef.svh" -`include "tcdm_interface/assign.svh" -`include "tcdm_interface/typedef.svh" - -/// A single-tile implementation for CachePool -module cachepool_tile_simple - import spatz_pkg::*; - import fpnew_pkg::fpu_implementation_t; - import snitch_pma_pkg::snitch_pma_t; - #( - /// Width of physical address. - parameter int unsigned AxiAddrWidth = 48, - /// Width of AXI port. - parameter int unsigned AxiDataWidth = 512, - /// AXI: id width in. - parameter int unsigned AxiIdWidthIn = 2, - /// AXI: id width out. - parameter int unsigned AxiIdWidthOut = 2, - /// AXI: user width. - parameter int unsigned AxiUserWidth = 1, - /// Address from which to fetch the first instructions. - parameter logic [31:0] BootAddr = 32'h0, - /// Address to indicate start of L2 - parameter logic [AxiAddrWidth-1:0] L2Addr = 48'h0, - parameter logic [AxiAddrWidth-1:0] L2Size = 48'h0, - /// The total amount of cores. - parameter int unsigned NrCores = 8, - /// Data/TCDM memory depth per cut (in words). - parameter int unsigned TCDMDepth = 1024, - /// Cluster peripheral address region size (in kB). - parameter int unsigned ClusterPeriphSize = 64, - /// Number of TCDM Banks. - parameter int unsigned NrBanks = 2 * NrCores, - /// Size of DMA AXI buffer. - parameter int unsigned DMAAxiReqFifoDepth = 3, - /// Size of DMA request fifo. - parameter int unsigned DMAReqFifoDepth = 3, - /// Width of a single icache line. - parameter unsigned ICacheLineWidth = 0, - /// Number of icache lines per set. - parameter int unsigned ICacheLineCount = 0, - /// Number of icache sets. - parameter int unsigned ICacheSets = 0, - // PMA Configuration - parameter snitch_pma_t SnitchPMACfg = '{default: 0}, - /// # Core-global parameters - /// FPU configuration. - parameter fpu_implementation_t FPUImplementation [NrCores] = '{default: fpu_implementation_t'(0)}, - /// Spatz FPU/IPU Configuration - parameter int unsigned NumSpatzFPUs = 4, - parameter int unsigned NumSpatzIPUs = 1, - /// Per-core enabling of the custom `Xdma` ISA extensions. - parameter bit [NrCores-1:0] Xdma = '{default: '0}, - /// # Per-core parameters - /// Per-core integer outstanding loads - parameter int unsigned NumIntOutstandingLoads [NrCores] = '{default: '0}, - /// Per-core integer outstanding memory operations (load and stores) - parameter int unsigned NumIntOutstandingMem [NrCores] = '{default: '0}, - /// Per-core Spatz outstanding loads - parameter int unsigned NumSpatzOutstandingLoads [NrCores] = '{default: '0}, - /// ## Timing Tuning Parameters - /// Insert Pipeline registers into off-loading path (response) - parameter bit RegisterOffloadRsp = 1'b0, - /// Insert Pipeline registers into data memory path (request) - parameter bit RegisterCoreReq = 1'b0, - /// Insert Pipeline registers into data memory path (response) - parameter bit RegisterCoreRsp = 1'b0, - /// Insert Pipeline registers after each memory cut - parameter bit RegisterTCDMCuts = 1'b0, - /// Decouple external AXI plug - parameter bit RegisterExt = 1'b0, - parameter axi_pkg::xbar_latency_e XbarLatency = axi_pkg::CUT_ALL_PORTS, - /// Outstanding transactions on the AXI network - parameter int unsigned MaxMstTrans = 4, - parameter int unsigned MaxSlvTrans = 4, - /// # Interface - /// AXI Ports - parameter type axi_in_req_t = logic, - parameter type axi_in_resp_t = logic, - parameter type axi_out_req_t = logic, - parameter type axi_out_resp_t = logic, - /// SRAM configuration - parameter type impl_in_t = logic, - // Memory latency parameter. Most of the memories have a read latency of 1. In - // case you have memory macros which are pipelined you want to adjust this - // value here. This only applies to the TCDM. The instruction cache macros will break! - // In case you are using the `RegisterTCDMCuts` feature this adds an - // additional cycle latency, which is taken into account here. - parameter int unsigned MemoryMacroLatency = 1 + RegisterTCDMCuts, - /// # SRAM Configuration rules needed: L1D Tag + L1D Data + L1D FIFO + L1I Tag + L1I Data - parameter int unsigned NrSramCfg = 64 + 8 + 2 + ICacheSets + ICacheSets - ) ( - /// System clock. - input logic clk_i, - /// Asynchronous active high reset. This signal is assumed to be _async_. - input logic rst_ni, - /// Per-core debug request signal. Asserting this signals puts the - /// corresponding core into debug mode. This signal is assumed to be _async_. - input logic [NrCores-1:0] debug_req_i, - /// Machine external interrupt pending. Usually those interrupts come from a - /// platform-level interrupt controller. This signal is assumed to be _async_. - input logic [NrCores-1:0] meip_i, - /// Machine timer interrupt pending. Usually those interrupts come from a - /// core-local interrupt controller such as a timer/RTC. This signal is - /// assumed to be _async_. - input logic [NrCores-1:0] mtip_i, - /// Core software interrupt pending. Usually those interrupts come from - /// another core to facilitate inter-processor-interrupts. This signal is - /// assumed to be _async_. - input logic [NrCores-1:0] msip_i, - /// First hartid of the cluster. Cores of a cluster are monotonically - /// increasing without a gap, i.e., a cluster with 8 cores and a - /// `hart_base_id_i` of 5 get the hartids 5 - 12. - input logic [9:0] hart_base_id_i, - /// Base address of cluster. TCDM and cluster peripheral location are derived from - /// it. This signal is pseudo-static. - input logic [AxiAddrWidth-1:0] cluster_base_addr_i, - /// Per-cluster probe on the cluster status. Can be written by the cores to indicate - /// to the overall system that the cluster is executing something. - output logic cluster_probe_o, - /// AXI Core cluster in-port. - input axi_in_req_t axi_in_req_i, - output axi_in_resp_t axi_in_resp_o, - /// AXI Core cluster out-port to core. - output axi_out_req_t axi_out_req_o, - input axi_out_resp_t axi_out_resp_i, - /// AXI Core cluster out-port to L2 Mem. - output axi_out_req_t axi_out_l2_req_o, - input axi_out_resp_t axi_out_l2_resp_i, - /// Indicate the program execution is error - output logic error_o - ); - // --------- - // Imports - // --------- - import snitch_pkg::*; - import snitch_icache_pkg::icache_events_t; - - // --------- - // Constants - // --------- - /// Minimum width to hold the core number. - localparam int unsigned CoreIDWidth = cf_math_pkg::idx_width(NrCores); - localparam int unsigned TCDMMemAddrWidth = $clog2(TCDMDepth); - localparam int unsigned TCDMSize = NrBanks * TCDMDepth * (DataWidth/8); - // The short address for SPM - localparam int unsigned SPMAddrWidth = $clog2(TCDMSize); - // Enlarge the address width for Spatz due to cache - localparam int unsigned TCDMAddrWidth = 32; - localparam int unsigned BanksPerSuperBank = AxiDataWidth / DataWidth; - localparam int unsigned NrSuperBanks = NrBanks / BanksPerSuperBank; - - function automatic int unsigned get_tcdm_ports(int unsigned core); - return spatz_pkg::N_FU + 1; - endfunction - - function automatic int unsigned get_tcdm_port_offs(int unsigned core_idx); - automatic int n = 0; - for (int i = 0; i < core_idx; i++) n += get_tcdm_ports(i); - return n; - endfunction - - localparam int unsigned NrTCDMPortsCores = get_tcdm_port_offs(NrCores); - localparam int unsigned NumTCDMIn = NrTCDMPortsCores + 1; - localparam logic [AxiAddrWidth-1:0] TCDMMask = ~(TCDMSize-1); - - // Core Request, SoC Request - localparam int unsigned NrNarrowMasters = 2; - - // Narrow AXI network parameters - localparam int unsigned NarrowIdWidthIn = AxiIdWidthIn; - localparam int unsigned NarrowIdWidthOut = NarrowIdWidthIn + $clog2(NrNarrowMasters); - localparam int unsigned NarrowDataWidth = 64; - localparam int unsigned NarrowUserWidth = AxiUserWidth; - - // TCDM, Peripherals, SoC Request - localparam int unsigned NrNarrowSlaves = 3; - localparam int unsigned NrNarrowRules = NrNarrowSlaves - 1; - - // Core Request, DMA, Instruction cache - /// Additional one for L1 DCache - localparam int unsigned NrWideMasters = 3 + 1; - localparam int unsigned WideIdWidthOut = AxiIdWidthOut; - localparam int unsigned WideIdWidthIn = WideIdWidthOut - $clog2(NrWideMasters); - // DMA X-BAR configuration - localparam int unsigned NrWideSlaves = 3 + 1; // one prot for L2, one for L3/LLC (virtual) - - // AXI Configuration - localparam axi_pkg::xbar_cfg_t ClusterXbarCfg = '{ - NoSlvPorts : NrNarrowMasters, - NoMstPorts : NrNarrowSlaves, - MaxMstTrans : MaxMstTrans, - MaxSlvTrans : MaxSlvTrans, - FallThrough : 1'b0, - LatencyMode : XbarLatency, - AxiIdWidthSlvPorts: NarrowIdWidthIn, - AxiIdUsedSlvPorts : NarrowIdWidthIn, - UniqueIds : 1'b0, - AxiAddrWidth : AxiAddrWidth, - AxiDataWidth : NarrowDataWidth, - NoAddrRules : NrNarrowRules, - default : '0 - }; - - // DMA configuration struct - localparam axi_pkg::xbar_cfg_t DmaXbarCfg = '{ - NoSlvPorts : NrWideMasters, - NoMstPorts : NrWideSlaves, - MaxMstTrans : MaxMstTrans, - MaxSlvTrans : MaxSlvTrans, - FallThrough : 1'b0, - LatencyMode : XbarLatency, - AxiIdWidthSlvPorts: WideIdWidthIn, - AxiIdUsedSlvPorts : WideIdWidthIn, - UniqueIds : 1'b0, - AxiAddrWidth : AxiAddrWidth, - AxiDataWidth : AxiDataWidth, - NoAddrRules : NrWideSlaves - 1, - default : '0 - }; - - // L1 Cache - localparam int unsigned L1AddrWidth = 32; - localparam int unsigned L1LineWidth = 512; - localparam int unsigned L1Associativity = 4; - localparam int unsigned L1BankFactor = 2; - localparam int unsigned L1CoalFactor = 2; - // 8 * 1024 * 64 / 512 = 1024) - localparam int unsigned L1NumEntry = NrBanks * TCDMDepth * DataWidth / L1LineWidth; - localparam int unsigned L1NumWrapper = L1LineWidth / DataWidth; - localparam int unsigned L1BankPerWP = L1BankFactor * L1Associativity; - localparam int unsigned L1BankPerWay = L1BankFactor * L1NumWrapper; - localparam int unsigned L1CacheWayEntry = L1NumEntry / L1Associativity; - localparam int unsigned L1NumSet = L1CacheWayEntry / L1BankFactor; - localparam int unsigned L1NumTagBank = L1BankFactor * L1Associativity; - localparam int unsigned L1NumDataBank = L1BankFactor * L1NumWrapper * L1Associativity; - - // -------- - // Typedefs - // -------- - typedef logic [AxiAddrWidth-1:0] addr_t; - typedef logic [NarrowDataWidth-1:0] data_t; - typedef logic [NarrowDataWidth/8-1:0] strb_t; - typedef logic [AxiDataWidth-1:0] data_dma_t; - typedef logic [AxiDataWidth/8-1:0] strb_dma_t; - typedef logic [NarrowIdWidthIn-1:0] id_mst_t; - typedef logic [NarrowIdWidthOut-1:0] id_slv_t; - typedef logic [WideIdWidthIn-1:0] id_dma_mst_t; - typedef logic [WideIdWidthOut-1:0] id_dma_slv_t; - typedef logic [NarrowUserWidth-1:0] user_t; - typedef logic [AxiUserWidth-1:0] user_dma_t; - - typedef logic [TCDMMemAddrWidth-1:0] tcdm_mem_addr_t; - typedef logic [TCDMAddrWidth-1:0] tcdm_addr_t; - typedef logic [SPMAddrWidth-1:0] spm_addr_t; - - typedef logic [$clog2(NumSpatzOutstandingLoads[0])-1:0] reqid_t; - typedef logic [$clog2(NumSpatzOutstandingLoads[0]):0] tcdm_meta_t; - - typedef logic [$clog2(L1NumSet)-1:0] tcdm_bank_addr_t; - - typedef struct packed { - logic [CoreIDWidth-1:0] core_id; - logic is_core; - reqid_t req_id; - } tcdm_user_t; - - // Regbus peripherals. - `AXI_TYPEDEF_ALL(axi_mst, addr_t, id_mst_t, data_t, strb_t, user_t) - `AXI_TYPEDEF_ALL(axi_slv, addr_t, id_slv_t, data_t, strb_t, user_t) - `AXI_TYPEDEF_ALL(axi_mst_dma, addr_t, id_dma_mst_t, data_dma_t, strb_dma_t, user_dma_t) - `AXI_TYPEDEF_ALL(axi_slv_dma, addr_t, id_dma_slv_t, data_dma_t, strb_dma_t, user_dma_t) - - `REQRSP_TYPEDEF_ALL(reqrsp, addr_t, data_t, strb_t) - - `MEM_TYPEDEF_ALL(mem, tcdm_mem_addr_t, data_t, strb_t, tcdm_user_t) - `MEM_TYPEDEF_ALL(mem_dma, tcdm_mem_addr_t, data_dma_t, strb_dma_t, logic) - - `TCDM_TYPEDEF_ALL(tcdm, tcdm_addr_t, data_t, strb_t, tcdm_user_t) - `TCDM_TYPEDEF_ALL(tcdm_dma, tcdm_addr_t, data_dma_t, strb_dma_t, logic) - `TCDM_TYPEDEF_ALL(spm, spm_addr_t, data_t, strb_t, tcdm_user_t) - - `REG_BUS_TYPEDEF_ALL(reg, addr_t, data_t, strb_t) - `REG_BUS_TYPEDEF_ALL(reg_dma, addr_t, data_dma_t, strb_dma_t) - - // Event counter increments for the TCDM. - typedef struct packed { - /// Number requests going in - logic [$clog2(NrTCDMPortsCores):0] inc_accessed; - /// Number of requests stalled due to congestion - logic [$clog2(NrTCDMPortsCores):0] inc_congested; - } tcdm_events_t; - - // Event counter increments for DMA. - typedef struct packed { - logic aw_stall, ar_stall, r_stall, w_stall, - buf_w_stall, buf_r_stall; - logic aw_valid, aw_ready, aw_done, aw_bw; - logic ar_valid, ar_ready, ar_done, ar_bw; - logic r_valid, r_ready, r_done, r_bw; - logic w_valid, w_ready, w_done, w_bw; - logic b_valid, b_ready, b_done; - logic dma_busy; - axi_pkg::len_t aw_len, ar_len; - axi_pkg::size_t aw_size, ar_size; - logic [$clog2(AxiDataWidth/8):0] num_bytes_written; - } dma_events_t; - - typedef struct packed { - int unsigned idx; - addr_t start_addr; - addr_t end_addr; - } xbar_rule_t; - - typedef struct packed { - acc_addr_e addr; - logic [5:0] id; - logic [31:0] data_op; - data_t data_arga; - data_t data_argb; - addr_t data_argc; - } acc_issue_req_t; - - typedef struct packed { - logic accept; - logic writeback; - logic loadstore; - logic exception; - logic isfloat; - } acc_issue_rsp_t; - - typedef struct packed { - logic [5:0] id; - logic error; - data_t data; - } acc_rsp_t; - - `SNITCH_VM_TYPEDEF(AxiAddrWidth) - - typedef struct packed { - // Slow domain. - logic flush_i_valid; - addr_t inst_addr; - logic inst_cacheable; - logic inst_valid; - // Fast domain. - acc_issue_req_t acc_req; - logic acc_qvalid; - logic acc_pready; - // Slow domain. - logic [1:0] ptw_valid; - va_t [1:0] ptw_va; - pa_t [1:0] ptw_ppn; - } hive_req_t; - - typedef struct packed { - // Slow domain. - logic flush_i_ready; - logic [31:0] inst_data; - logic inst_ready; - logic inst_error; - // Fast domain. - logic acc_qready; - acc_rsp_t acc_resp; - logic acc_pvalid; - // Slow domain. - logic [1:0] ptw_ready; - l0_pte_t [1:0] ptw_pte; - logic [1:0] ptw_is_4mega; - } hive_rsp_t; - - // ----------- - // Assignments - // ----------- - // Calculate start and end address of TCDM based on the `cluster_base_addr_i`. - addr_t tcdm_start_address, tcdm_end_address; - assign tcdm_start_address = (cluster_base_addr_i & TCDMMask); - assign tcdm_end_address = (tcdm_start_address + TCDMSize) & TCDMMask; - - addr_t cluster_periph_start_address, cluster_periph_end_address; - assign cluster_periph_start_address = tcdm_end_address; - assign cluster_periph_end_address = tcdm_end_address + ClusterPeriphSize * 1024; - - localparam int unsigned ClusterReserve = 4096; // 4 MiB - localparam int unsigned ClusterL2Size = 8192; // 8 MiB - addr_t cluster_l2_start_address, cluster_l2_end_address; - assign cluster_l2_start_address = L2Addr; - assign cluster_l2_end_address = L2Addr + L2Size; - - // ---------------- - // Wire Definitions - // ---------------- - // 1. AXI - axi_slv_req_t [NrNarrowSlaves-1:0] narrow_axi_slv_req; - axi_slv_resp_t [NrNarrowSlaves-1:0] narrow_axi_slv_rsp; - axi_mst_req_t [NrNarrowMasters-1:0] narrow_axi_mst_req; - axi_mst_resp_t [NrNarrowMasters-1:0] narrow_axi_mst_rsp; - - // DMA AXI buses - axi_mst_dma_req_t [NrWideMasters-1:0] wide_axi_mst_req; - axi_mst_dma_resp_t [NrWideMasters-1:0] wide_axi_mst_rsp; - axi_slv_dma_req_t [NrWideSlaves-1 :0] wide_axi_slv_req; - axi_slv_dma_resp_t [NrWideSlaves-1 :0] wide_axi_slv_rsp; - - // 2. Memory Subsystem (Banks) - mem_req_t [NrSuperBanks-1:0][BanksPerSuperBank-1:0] ic_req; - mem_rsp_t [NrSuperBanks-1:0][BanksPerSuperBank-1:0] ic_rsp; - - mem_dma_req_t [NrSuperBanks-1:0] sb_dma_req; - mem_dma_rsp_t [NrSuperBanks-1:0] sb_dma_rsp; - - // 3. Memory Subsystem (Interconnect) - tcdm_dma_req_t ext_dma_req; - tcdm_dma_rsp_t ext_dma_rsp; - - // AXI Ports into TCDM (from SoC). - spm_req_t axi_soc_req; - spm_rsp_t axi_soc_rsp; - - tcdm_req_t [NrTCDMPortsCores-1:0] tcdm_req; - tcdm_rsp_t [NrTCDMPortsCores-1:0] tcdm_rsp; - - core_events_t [NrCores-1:0] core_events; - tcdm_events_t tcdm_events; - dma_events_t dma_events; - snitch_icache_pkg::icache_events_t [NrCores-1:0] icache_events; - - // 4. Memory Subsystem (Core side). - reqrsp_req_t [NrCores-1:0] core_req, filtered_core_req; - reqrsp_rsp_t [NrCores-1:0] core_rsp, filtered_core_rsp; - - // 5. Peripheral Subsystem - reg_req_t reg_req; - reg_rsp_t reg_rsp; - - // 6. BootROM - reg_dma_req_t bootrom_reg_req; - reg_dma_rsp_t bootrom_reg_rsp; - - // 7. Misc. Wires. - logic icache_prefetch_enable; - logic [NrCores-1:0] cl_interrupt; - - // 8. L1 D$ - spm_req_t [NrTCDMPortsCores-1:0] spm_req; - spm_rsp_t [NrTCDMPortsCores-1:0] spm_rsp; - - tcdm_req_t [NrTCDMPortsCores-1:0] unmerge_req, strb_hdl_req, cache_req; - tcdm_rsp_t [NrTCDMPortsCores-1:0] unmerge_rsp, strb_hdl_rsp, cache_rsp; - - logic [NrTCDMPortsCores-1:0] cache_req_valid; - logic [NrTCDMPortsCores-1:0] cache_req_ready; - tcdm_addr_t [NrTCDMPortsCores-1:0] cache_req_addr; - tcdm_user_t [NrTCDMPortsCores-1:0] cache_req_meta; - logic [NrTCDMPortsCores-1:0] cache_req_write; - data_t [NrTCDMPortsCores-1:0] cache_req_data; - - logic [NrTCDMPortsCores-1:0] cache_rsp_valid; - logic [NrTCDMPortsCores-1:0] cache_rsp_ready; - logic [NrTCDMPortsCores-1:0] cache_rsp_write; - data_t [NrTCDMPortsCores-1:0] cache_rsp_data; - tcdm_user_t [NrTCDMPortsCores-1:0] cache_rsp_meta; - - logic [L1NumTagBank-1:0] l1_tag_bank_req; - logic [L1NumTagBank-1:0] l1_tag_bank_we; - tcdm_bank_addr_t [L1NumTagBank-1:0] l1_tag_bank_addr; - data_t [L1NumTagBank-1:0] l1_tag_bank_wdata; - logic [L1NumTagBank-1:0] l1_tag_bank_be; - data_t [L1NumTagBank-1:0] l1_tag_bank_rdata; - - logic [L1NumDataBank-1:0] l1_data_bank_req; - logic [L1NumDataBank-1:0] l1_data_bank_we; - tcdm_bank_addr_t [L1NumDataBank-1:0] l1_data_bank_addr; - data_t [L1NumDataBank-1:0] l1_data_bank_wdata; - logic [L1NumDataBank-1:0] l1_data_bank_be; - data_t [L1NumDataBank-1:0] l1_data_bank_rdata; - logic [L1NumDataBank-1:0] l1_data_bank_gnt; - - logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_req; - logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_we; - tcdm_bank_addr_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_addr; - data_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_wdata; - strb_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_be; - data_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_rdata; - logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_gnt; - - logic l1d_insn_valid, l1d_insn_ready; - logic [1:0] l1d_insn; - tcdm_bank_addr_t cfg_spm_size; - tcdm_addr_t spm_size; - logic l1d_busy; - - // High if a port access an illegal SPM region (mapped to cache) - logic [NrTCDMPortsCores-1:0] spm_error; - - - // 9. SRAM Configuration - impl_in_t [L1NumWrapper-1:0][L1BankPerWP-1:0] impl_l1d_data; - impl_in_t [L1NumTagBank-1:0] impl_l1d_tag; - impl_in_t [1:0] impl_l1d_fifo; - - impl_in_t [ICacheSets-1:0] impl_l1i_data; - impl_in_t [ICacheSets-1:0] impl_l1i_tag; - - assign {impl_l1d_data, impl_l1d_tag, impl_l1d_fifo, impl_l1i_data, impl_l1i_tag} = impl_i; - assign error_o = |spm_error; - - - // ------------- - // DMA Subsystem - // ------------- - // Optionally decouple the external wide AXI master port. - axi_cut #( - .Bypass (!RegisterExt ), - .aw_chan_t (axi_slv_dma_aw_chan_t), - .w_chan_t (axi_slv_dma_w_chan_t ), - .b_chan_t (axi_slv_dma_b_chan_t ), - .ar_chan_t (axi_slv_dma_ar_chan_t), - .r_chan_t (axi_slv_dma_r_chan_t ), - .axi_req_t (axi_slv_dma_req_t ), - .axi_resp_t (axi_slv_dma_resp_t ) - ) i_cut_ext_wide_out ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .slv_req_i (wide_axi_slv_req[SoCDMAOut]), - .slv_resp_o (wide_axi_slv_rsp[SoCDMAOut]), - .mst_req_o (axi_out_req_o ), - .mst_resp_i (axi_out_resp_i ) - ); - - axi_cut #( - .Bypass (!RegisterExt ), - .aw_chan_t (axi_slv_dma_aw_chan_t), - .w_chan_t (axi_slv_dma_w_chan_t ), - .b_chan_t (axi_slv_dma_b_chan_t ), - .ar_chan_t (axi_slv_dma_ar_chan_t), - .r_chan_t (axi_slv_dma_r_chan_t ), - .axi_req_t (axi_slv_dma_req_t ), - .axi_resp_t (axi_slv_dma_resp_t ) - ) i_cut_ext_l2_wide_out ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .slv_req_i (wide_axi_slv_req[L2Mem]), - .slv_resp_o (wide_axi_slv_rsp[L2Mem]), - .mst_req_o (axi_out_l2_req_o ), - .mst_resp_i (axi_out_l2_resp_i ) - ); - - axi_cut #( - .Bypass (!RegisterExt ), - .aw_chan_t (axi_mst_aw_chan_t), - .w_chan_t (axi_mst_w_chan_t ), - .b_chan_t (axi_mst_b_chan_t ), - .ar_chan_t (axi_mst_ar_chan_t), - .r_chan_t (axi_mst_r_chan_t ), - .axi_req_t (axi_mst_req_t ), - .axi_resp_t (axi_mst_resp_t ) - ) i_cut_ext_narrow_in ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .slv_req_i (axi_in_req_i ), - .slv_resp_o (axi_in_resp_o ), - .mst_req_o (narrow_axi_mst_req[SoCDMAIn]), - .mst_resp_i (narrow_axi_mst_rsp[SoCDMAIn]) - ); - - logic [DmaXbarCfg.NoSlvPorts-1:0][$clog2(DmaXbarCfg.NoMstPorts)-1:0] dma_xbar_default_port; - xbar_rule_t [DmaXbarCfg.NoAddrRules-1:0] dma_xbar_rule; - - assign dma_xbar_default_port = '{default: SoCDMAOut}; - assign dma_xbar_rule = '{ - '{ - idx : TCDMDMA, - start_addr: tcdm_start_address, - end_addr : tcdm_end_address - }, - '{ - idx : BootROM, - start_addr: BootAddr, - end_addr : BootAddr + 'h1000 - }, - '{ - idx : L2Mem, - start_addr: cluster_l2_start_address, - end_addr : cluster_l2_end_address - } - }; - - localparam bit [DmaXbarCfg.NoSlvPorts-1:0] DMAEnableDefaultMstPort = '1; - axi_xbar #( - .Cfg (DmaXbarCfg ), - .ATOPs (0 ), - .slv_aw_chan_t (axi_mst_dma_aw_chan_t), - .mst_aw_chan_t (axi_slv_dma_aw_chan_t), - .w_chan_t (axi_mst_dma_w_chan_t ), - .slv_b_chan_t (axi_mst_dma_b_chan_t ), - .mst_b_chan_t (axi_slv_dma_b_chan_t ), - .slv_ar_chan_t (axi_mst_dma_ar_chan_t), - .mst_ar_chan_t (axi_slv_dma_ar_chan_t), - .slv_r_chan_t (axi_mst_dma_r_chan_t ), - .mst_r_chan_t (axi_slv_dma_r_chan_t ), - .slv_req_t (axi_mst_dma_req_t ), - .slv_resp_t (axi_mst_dma_resp_t ), - .mst_req_t (axi_slv_dma_req_t ), - .mst_resp_t (axi_slv_dma_resp_t ), - .rule_t (xbar_rule_t ) - ) i_axi_dma_xbar ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .test_i (1'b0 ), - .slv_ports_req_i (wide_axi_mst_req ), - .slv_ports_resp_o (wide_axi_mst_rsp ), - .mst_ports_req_o (wide_axi_slv_req ), - .mst_ports_resp_i (wide_axi_slv_rsp ), - .addr_map_i (dma_xbar_rule ), - .en_default_mst_port_i (DMAEnableDefaultMstPort), - .default_mst_port_i (dma_xbar_default_port ) - ); - - addr_t ext_dma_req_q_addr_nontrunc; - - axi_to_mem_interleaved #( - .axi_req_t (axi_slv_dma_req_t ), - .axi_resp_t (axi_slv_dma_resp_t ), - .AddrWidth (AxiAddrWidth ), - .DataWidth (AxiDataWidth ), - .IdWidth (WideIdWidthOut ), - .NumBanks (1 ), - .BufDepth (MemoryMacroLatency + 1) - ) i_axi_to_mem_dma ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .busy_o (/* Unused */ ), - .test_i (1'b0 ), - .axi_req_i (wide_axi_slv_req[TCDMDMA] ), - .axi_resp_o (wide_axi_slv_rsp[TCDMDMA] ), - .mem_req_o (ext_dma_req.q_valid ), - .mem_gnt_i (ext_dma_rsp.q_ready ), - .mem_addr_o (ext_dma_req_q_addr_nontrunc ), - .mem_wdata_o (ext_dma_req.q.data ), - .mem_strb_o (ext_dma_req.q.strb ), - .mem_atop_o (/* The DMA does not support atomics */), - .mem_we_o (ext_dma_req.q.write ), - .mem_rvalid_i (ext_dma_rsp.p_valid ), - .mem_rdata_i (ext_dma_rsp.p.data ) - ); - - assign ext_dma_req.q.addr = tcdm_addr_t'(ext_dma_req_q_addr_nontrunc); - assign ext_dma_req.q.amo = reqrsp_pkg::AMONone; - assign ext_dma_req.q.user = '0; - - spatz_tcdm_interconnect #( - .NumInp (1 ), - .NumOut (NrSuperBanks ), - .tcdm_req_t (tcdm_dma_req_t ), - .tcdm_rsp_t (tcdm_dma_rsp_t ), - .mem_req_t (mem_dma_req_t ), - .mem_rsp_t (mem_dma_rsp_t ), - .user_t (logic ), - .MemAddrWidth (TCDMMemAddrWidth ), - .DataWidth (AxiDataWidth ), - .MemoryResponseLatency (MemoryMacroLatency) - ) i_dma_interconnect ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .req_i (ext_dma_req), - .rsp_o (ext_dma_rsp), - .mem_req_o (sb_dma_req ), - .mem_rsp_i (sb_dma_rsp ) - ); - - // ---------------- - // Memory Subsystem - // ---------------- - for (genvar i = 0; i < NrSuperBanks; i++) begin : gen_tcdm_super_bank - - mem_req_t [BanksPerSuperBank-1:0] amo_req; - mem_rsp_t [BanksPerSuperBank-1:0] amo_rsp; - - mem_wide_narrow_mux #( - .NarrowDataWidth (NarrowDataWidth), - .WideDataWidth (AxiDataWidth ), - .mem_narrow_req_t (mem_req_t ), - .mem_narrow_rsp_t (mem_rsp_t ), - .mem_wide_req_t (mem_dma_req_t ), - .mem_wide_rsp_t (mem_dma_rsp_t ) - ) i_tcdm_mux ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .in_narrow_req_i (ic_req [i] ), - .in_narrow_rsp_o (ic_rsp [i] ), - .in_wide_req_i (sb_dma_req [i] ), - .in_wide_rsp_o (sb_dma_rsp [i] ), - .out_req_o (amo_req ), - .out_rsp_i (amo_rsp ), - .sel_wide_i (sb_dma_req[i].q_valid) - ); - - // generate banks of the superbank - for (genvar j = 0; j < BanksPerSuperBank; j++) begin : gen_tcdm_bank - - logic mem_cs, mem_wen; - tcdm_mem_addr_t mem_add; - tcdm_mem_addr_t mem_add_max; - strb_t mem_be; - data_t mem_rdata, mem_wdata; - tcdm_meta_t mem_req_meta; - assign mem_add_max = 0 - 1'b1; - - spatz_sram_wrapper #( - .NumBanks (L1BankPerWP ), - .NumWords (TCDMDepth ), - .ByteWidth (8 ), - .DataWidth (DataWidth ), - .MemoryResponseLatency (1 ), - .impl_in_t (impl_in_t ) - ) i_data_mem ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .spm_size_i (cfg_spm_size ), - /// Cache Side TODO: Connect cache - .cache_req_i (l1_cache_wp_req [j] ), - .cache_we_i (l1_cache_wp_we [j] ), - .cache_addr_i (l1_cache_wp_addr [j] ), - .cache_wdata_i(l1_cache_wp_wdata[j] ), - .cache_be_i (l1_cache_wp_be [j] ), - .cache_rdata_o(l1_cache_wp_rdata[j] ), - .cache_ready_o(l1_cache_wp_gnt [j] ), - /// SPM Side - .spm_req_i (mem_cs ), - .spm_we_i (mem_wen ), - .spm_addr_i (mem_add_max - mem_add), // swap the position of stack and data - .spm_wdata_i (mem_wdata ), - .spm_be_i (mem_be ), - .spm_rdata_o (mem_rdata ), - /// SRAM Configuration - .impl_i (impl_l1d_data[j] ) - ); - - data_t amo_rdata_local; - - // TODO(zarubaf): Share atomic units between mutltiple cuts - snitch_amo_shim #( - .AddrMemWidth ( TCDMMemAddrWidth ), - .DataWidth ( DataWidth ), - .CoreIDWidth ( CoreIDWidth ) - ) i_amo_shim ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .valid_i (amo_req[j].q_valid ), - .ready_o (amo_rsp[j].q_ready ), - .addr_i (amo_req[j].q.addr ), - .write_i (amo_req[j].q.write ), - .wdata_i (amo_req[j].q.data ), - .wstrb_i (amo_req[j].q.strb ), - .core_id_i (amo_req[j].q.user.core_id ), - .is_core_i (amo_req[j].q.user.is_core ), - .rdata_o (amo_rdata_local ), - .amo_i (amo_req[j].q.amo ), - .mem_req_o (mem_cs ), - .mem_add_o (mem_add ), - .mem_wen_o (mem_wen ), - .mem_wdata_o (mem_wdata ), - .mem_be_o (mem_be ), - .mem_rdata_i (mem_rdata ), - .dma_access_i (sb_dma_req[i].q_valid ), - // TODO(zarubaf): Signal AMO conflict somewhere. Socregs? - .amo_conflict_o (/* Unused */ ) - ); - - // Insert a pipeline register at the output of each SRAM. - shift_reg #( - .dtype(data_t ), - .Depth(int'(RegisterTCDMCuts)) - ) i_sram_pipe ( - .clk_i (clk_i ), - .rst_ni(rst_ni ), - .d_i (amo_rdata_local ), - .d_o (amo_rsp[j].p.data) - ); - - // delay the req_id two cycles: 1 for bank access, 1 for reg - shift_reg #( - .dtype(tcdm_meta_t ), - .Depth(int'(RegisterTCDMCuts)) - ) i_reqid_pipe1 ( - .clk_i (clk_i ), - .rst_ni(rst_ni ), - .d_i ({amo_req[j].q.user.req_id, amo_req[j].q.write}), - .d_o (mem_req_meta ) - ); - shift_reg #( - .dtype(tcdm_meta_t ), - .Depth(int'(RegisterTCDMCuts)) - ) i_reqid_pipe2 ( - .clk_i (clk_i ), - .rst_ni(rst_ni ), - .d_i (mem_req_meta ), - .d_o ({amo_rsp[j].p.user.req_id, amo_rsp[j].p.write}) - ); - - // tie unused field to 0 - // TODO: remove these fields - assign amo_rsp[j].p.user.core_id = '0; - assign amo_rsp[j].p.user.is_core = '0; - end - end - - logic [NrTCDMPortsCores-1:0] unmerge_pready, strb_hdl_pready, cache_pready; - assign spm_size = cfg_spm_size * L1Associativity * L1LineWidth / 2; - - // split the requests for spm or cache from core side - spatz_addr_mapper #( - .NumIO (NrTCDMPortsCores ), - .AddrWidth (L1AddrWidth ), - .SPMAddrWidth (SPMAddrWidth ), - .DataWidth (DataWidth ), - .mem_req_t (tcdm_req_t ), - .mem_rsp_t (tcdm_rsp_t ), - .mem_rsp_chan_t (tcdm_rsp_chan_t ), - .spm_req_t (spm_req_t ), - .spm_rsp_t (spm_rsp_t ) - ) i_tcdm_mapper ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - // Input - .mem_req_i (tcdm_req ), - .mem_rsp_o (tcdm_rsp ), - .error_o (spm_error ), - // Address - .tcdm_start_address_i (tcdm_start_address[L1AddrWidth-1:0] ), - .tcdm_end_address_i (tcdm_end_address[L1AddrWidth-1:0] ), - .spm_size_i (spm_size ), - .flush_i (l1d_busy ), - // Output - .spm_req_o (spm_req ), - .spm_rsp_i (spm_rsp ), - .cache_req_o (unmerge_req ), - .cache_pready_o (unmerge_pready ), - .cache_rsp_i (unmerge_rsp ) - ); - - localparam int unsigned NumIOPerCore = get_tcdm_ports(0); - logic [NrTCDMPortsCores-1:0] strb_req_ack; - - spatz_strbreq_merge_tree #( - .NumIO (NrTCDMPortsCores ), - .NumOutstandingMem (NumSpatzOutstandingLoads[0] ), - .MergeNum (NrTCDMPortsCores - NrCores ), - .DataWidth (DataWidth ), - .mem_req_t (tcdm_req_t ), - .mem_rsp_t (tcdm_rsp_t ), - .req_id_t (reqid_t ), - .tcdm_user_t (tcdm_user_t ) - ) i_strbreq_merge_tree ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .unmerge_req_i (unmerge_req ), - .unmerge_pready_i(unmerge_pready ), - .merge_rsp_i (strb_hdl_rsp ), - .merge_req_o (strb_hdl_req ), - .merge_pready_o (strb_hdl_pready ), - .unmerge_rsp_o (unmerge_rsp ) - ); - - for (genvar j = 0; j < NrTCDMPortsCores; j++) begin: gen_strb_hdlr - spatz_strbreq_handler #( - .DataWidth (DataWidth ), - .mem_req_t (tcdm_req_t ), - .mem_rsp_t (tcdm_rsp_t ), - .reqrsp_user_t (tcdm_user_t ) - ) i_strbreq_handler ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .strb_req_i (strb_hdl_req[j] ), - .strb_rsp_ready_i (strb_hdl_pready[j] ), - .strb_rsp_i (cache_rsp[j] ), - .strb_req_o (cache_req[j] ), - .strb_rsp_ready_o (cache_pready[j] ), - .strb_rsp_o (strb_hdl_rsp[j] ) - ); - - assign cache_req_valid[j] = cache_req[j].q_valid; - assign cache_rsp_ready[j] = cache_pready[j]; - assign cache_req_addr[j] = cache_req[j].q.addr; - assign cache_req_meta[j] = cache_req[j].q.user; - assign cache_req_write[j] = cache_req[j].q.write; - assign cache_req_data[j] = cache_req[j].q.data; - - assign cache_rsp[j].p_valid = cache_rsp_valid[j]; - assign cache_rsp[j].q_ready = cache_req_ready[j]; - assign cache_rsp[j].p.data = cache_rsp_data[j]; - assign cache_rsp[j].p.user = cache_rsp_meta[j]; - - assign cache_rsp[j].p.write = cache_rsp_write[j]; - end - - flamingo_spatz_cache_ctrl #( - // Core - .NumPorts (NrTCDMPortsCores ), - .CoalExtFactor (L1CoalFactor ), - .AddrWidth (L1AddrWidth ), - .WordWidth (DataWidth ), - // Cache - .NumCacheEntry (L1NumEntry ), - .CacheLineWidth (L1LineWidth ), - .SetAssociativity (L1Associativity ), - .BankFactor (L1BankFactor ), - // Type - .core_meta_t (tcdm_user_t ), - .impl_in_t (impl_in_t ), - .axi_req_t (axi_mst_dma_req_t ), - .axi_resp_t (axi_mst_dma_resp_t) - ) i_l1_controller ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .impl_i (impl_l1d_fifo ), - // Sync Control - .cache_sync_valid_i (l1d_insn_valid ), - .cache_sync_ready_o (l1d_insn_ready ), - .cache_sync_insn_i (l1d_insn ), - // SPM Size - // The calculation of spm region in cache is different - // than other modules (needs to times 2) - .bank_depth_for_SPM_i ((cfg_spm_size<<1) ), - // Request - .core_req_valid_i (cache_req_valid ), - .core_req_ready_o (cache_req_ready ), - .core_req_addr_i (cache_req_addr ), - .core_req_meta_i (cache_req_meta ), - .core_req_write_i (cache_req_write ), - .core_req_wdata_i (cache_req_data ), - // Response - .core_resp_valid_o (cache_rsp_valid ), - .core_resp_ready_i (cache_rsp_ready ), - .core_resp_write_o (cache_rsp_write ), - .core_resp_data_o (cache_rsp_data ), - .core_resp_meta_o (cache_rsp_meta ), - // AXI refill - .axi_req_o (wide_axi_mst_req[DCache] ), - .axi_resp_i (wide_axi_mst_rsp[DCache] ), - // Tag Banks - .tcdm_tag_bank_req_o (l1_tag_bank_req ), - .tcdm_tag_bank_we_o (l1_tag_bank_we ), - .tcdm_tag_bank_addr_o (l1_tag_bank_addr ), - .tcdm_tag_bank_wdata_o (l1_tag_bank_wdata ), - .tcdm_tag_bank_be_o (l1_tag_bank_be ), - .tcdm_tag_bank_rdata_i (l1_tag_bank_rdata ), - // Data Banks - .tcdm_data_bank_req_o (l1_data_bank_req ), - .tcdm_data_bank_we_o (l1_data_bank_we ), - .tcdm_data_bank_addr_o (l1_data_bank_addr ), - .tcdm_data_bank_wdata_o(l1_data_bank_wdata ), - .tcdm_data_bank_be_o (l1_data_bank_be ), - .tcdm_data_bank_rdata_i(l1_data_bank_rdata ), - .tcdm_data_bank_gnt_i (l1_data_bank_gnt ) - ); - - for (genvar j = 0; j < L1NumTagBank; j++) begin: gen_l1_tag_banks - tc_sram_impl #( - .NumWords (L1CacheWayEntry/L1BankFactor), - .DataWidth ($bits(data_t) ), - .ByteWidth ($bits(data_t) ), - .NumPorts (1 ), - .Latency (1 ), - .SimInit ("zeros" ), - .impl_in_t (impl_in_t ) - ) i_meta_bank ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .impl_i (impl_l1d_tag [j]), - .impl_o (/* unsed */ ), - .req_i (l1_tag_bank_req [j]), - .we_i (l1_tag_bank_we [j]), - .addr_i (l1_tag_bank_addr [j]), - .wdata_i(l1_tag_bank_wdata[j]), - .be_i (l1_tag_bank_be [j]), - .rdata_o(l1_tag_bank_rdata[j]) - ); - end - - for (genvar i = 0; i < L1NumWrapper; i++) begin - for (genvar j = 0; j < L1Associativity*L1BankFactor; j++) begin - assign l1_cache_wp_req [i][j] = l1_data_bank_req [i + j*L1NumWrapper]; - assign l1_cache_wp_we [i][j] = l1_data_bank_we [i + j*L1NumWrapper]; - assign l1_cache_wp_addr [i][j] = l1_data_bank_addr [i + j*L1NumWrapper]; - assign l1_cache_wp_wdata[i][j] = l1_data_bank_wdata[i + j*L1NumWrapper]; - assign l1_cache_wp_be [i][j] = (l1_data_bank_be [i + j*L1NumWrapper]) ? {(NarrowDataWidth/8){1'b1}} : '0; - - assign l1_data_bank_rdata[i + j*L1NumWrapper] = l1_cache_wp_rdata[i][j]; - assign l1_data_bank_gnt [i + j*L1NumWrapper] = l1_cache_wp_gnt [i][j]; - end - end - - // We have multiple banks form a pesudo bank (BankWP) - spatz_tcdm_interconnect #( - .NumInp (NumTCDMIn ), - .NumOut (L1NumWrapper ), - .tcdm_req_t (spm_req_t ), - .tcdm_rsp_t (spm_rsp_t ), - .mem_req_t (mem_req_t ), - .mem_rsp_t (mem_rsp_t ), - .MemAddrWidth (TCDMMemAddrWidth ), - .DataWidth (DataWidth ), - .user_t (tcdm_user_t ), - .MemoryResponseLatency (1 + RegisterTCDMCuts) - ) i_tcdm_interconnect ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .req_i ({axi_soc_req, spm_req} ), - .rsp_o ({axi_soc_rsp, spm_rsp} ), - .mem_req_o (ic_req ), - .mem_rsp_i (ic_rsp ) - ); - - hive_req_t [NrCores-1:0] hive_req; - hive_rsp_t [NrCores-1:0] hive_rsp; - - for (genvar i = 0; i < NrCores; i++) begin : gen_core - localparam int unsigned TcdmPorts = get_tcdm_ports(i); - localparam int unsigned TcdmPortsOffs = get_tcdm_port_offs(i); - - axi_mst_dma_req_t axi_dma_req; - axi_mst_dma_resp_t axi_dma_res; - interrupts_t irq; - dma_events_t dma_core_events; - - sync #(.STAGES (2)) - i_sync_debug (.clk_i, .rst_ni, .serial_i (debug_req_i[i]), .serial_o (irq.debug)); - sync #(.STAGES (2)) - i_sync_meip (.clk_i, .rst_ni, .serial_i (meip_i[i]), .serial_o (irq.meip)); - sync #(.STAGES (2)) - i_sync_mtip (.clk_i, .rst_ni, .serial_i (mtip_i[i]), .serial_o (irq.mtip)); - sync #(.STAGES (2)) - i_sync_msip (.clk_i, .rst_ni, .serial_i (msip_i[i]), .serial_o (irq.msip)); - assign irq.mcip = cl_interrupt[i]; - - tcdm_req_t [TcdmPorts-1:0] tcdm_req_wo_user; - - logic [31:0] hart_id; - assign hart_id = hart_base_id_i + i; - - spatz_cc #( - .BootAddr (BootAddr ), - .L2Addr (L2Addr ), - .L2Size (L2Size ), - .RVE (1'b0 ), - .RVF (RVF ), - .RVD (RVD ), - .RVV (RVV ), - .Xdma (Xdma[i] ), - .AddrWidth (AxiAddrWidth ), - .DataWidth (NarrowDataWidth ), - .UserWidth (AxiUserWidth ), - .DMADataWidth (AxiDataWidth ), - .DMAIdWidth (AxiIdWidthIn ), - .SnitchPMACfg (SnitchPMACfg ), - .DMAAxiReqFifoDepth (DMAAxiReqFifoDepth ), - .DMAReqFifoDepth (DMAReqFifoDepth ), - .dreq_t (reqrsp_req_t ), - .drsp_t (reqrsp_rsp_t ), - .tcdm_req_t (tcdm_req_t ), - .tcdm_req_chan_t (tcdm_req_chan_t ), - .tcdm_rsp_t (tcdm_rsp_t ), - .tcdm_rsp_chan_t (tcdm_rsp_chan_t ), - .axi_req_t (axi_mst_dma_req_t ), - .axi_ar_chan_t (axi_mst_dma_ar_chan_t ), - .axi_aw_chan_t (axi_mst_dma_aw_chan_t ), - .axi_rsp_t (axi_mst_dma_resp_t ), - .hive_req_t (hive_req_t ), - .hive_rsp_t (hive_rsp_t ), - .acc_issue_req_t (acc_issue_req_t ), - .acc_issue_rsp_t (acc_issue_rsp_t ), - .acc_rsp_t (acc_rsp_t ), - .dma_events_t (dma_events_t ), - .dma_perf_t (axi_dma_pkg::dma_perf_t ), - .XDivSqrt (1'b0 ), - .XF16 (1'b1 ), - .XF16ALT (1'b1 ), - .XF8 (1'b1 ), - .XF8ALT (1'b1 ), - .IsoCrossing (1'b0 ), - .NumIntOutstandingLoads (NumIntOutstandingLoads[i] ), - .NumIntOutstandingMem (NumIntOutstandingMem[i] ), - .NumSpatzOutstandingLoads(NumSpatzOutstandingLoads[i]), - .FPUImplementation (FPUImplementation[i] ), - .RegisterOffloadRsp (RegisterOffloadRsp ), - .RegisterCoreReq (RegisterCoreReq ), - .RegisterCoreRsp (RegisterCoreRsp ), - .NumSpatzFPUs (NumSpatzFPUs ), - .NumSpatzIPUs (NumSpatzIPUs ), - .TCDMAddrWidth (SPMAddrWidth ) - ) i_spatz_cc ( - .clk_i (clk_i ), - .clk_d2_i (clk_i ), - .rst_ni (rst_ni ), - .testmode_i (1'b0 ), - .hart_id_i (hart_id ), - .hive_req_o (hive_req[i] ), - .hive_rsp_i (hive_rsp[i] ), - .irq_i (irq ), - .data_req_o (core_req[i] ), - .data_rsp_i (core_rsp[i] ), - .tcdm_req_o (tcdm_req_wo_user ), - .tcdm_rsp_i (tcdm_rsp[TcdmPortsOffs +: TcdmPorts]), - .axi_dma_req_o (axi_dma_req ), - .axi_dma_res_i (axi_dma_res ), - .axi_dma_busy_o (/* Unused */ ), - .axi_dma_perf_o (/* Unused */ ), - .axi_dma_events_o (dma_core_events ), - .core_events_o (core_events[i] ), - .tcdm_addr_base_i (tcdm_start_address ) - ); - for (genvar j = 0; j < TcdmPorts; j++) begin : gen_tcdm_user - always_comb begin - tcdm_req[TcdmPortsOffs+j].q = tcdm_req_wo_user[j].q; - tcdm_req[TcdmPortsOffs+j].q.user.core_id = i[CoreIDWidth-1:0]; - tcdm_req[TcdmPortsOffs+j].q.user.is_core = 1; - tcdm_req[TcdmPortsOffs+j].q_valid = tcdm_req_wo_user[j].q_valid; - end - end - if (Xdma[i]) begin : gen_dma_connection - assign wide_axi_mst_req[SDMAMst] = axi_dma_req; - assign axi_dma_res = wide_axi_mst_rsp[SDMAMst]; - assign dma_events = dma_core_events; - end else begin - assign axi_dma_res = '0; - end - end - - // ---------------- - // Instruction Cache - // ---------------- - - addr_t [NrCores-1:0] inst_addr; - logic [NrCores-1:0] inst_cacheable; - logic [NrCores-1:0][31:0] inst_data; - logic [NrCores-1:0] inst_valid; - logic [NrCores-1:0] inst_ready; - logic [NrCores-1:0] inst_error; - logic [NrCores-1:0] flush_valid; - logic [NrCores-1:0] flush_ready; - - for (genvar i = 0; i < NrCores; i++) begin : gen_unpack_icache - assign inst_addr[i] = hive_req[i].inst_addr; - assign inst_cacheable[i] = hive_req[i].inst_cacheable; - assign inst_valid[i] = hive_req[i].inst_valid; - assign flush_valid[i] = hive_req[i].flush_i_valid; - assign hive_rsp[i] = '{ - inst_data : inst_data[i], - inst_ready : inst_ready[i], - inst_error : inst_error[i], - flush_i_ready: flush_ready[i], - default : '0 - }; - end - - snitch_icache #( - .NR_FETCH_PORTS ( NrCores ), - .L0_LINE_COUNT ( 8 ), - .LINE_WIDTH ( ICacheLineWidth ), - .LINE_COUNT ( ICacheLineCount ), - .SET_COUNT ( ICacheSets ), - .FETCH_AW ( AxiAddrWidth ), - .FETCH_DW ( 32 ), - .FILL_AW ( AxiAddrWidth ), - .FILL_DW ( AxiDataWidth ), - .EARLY_LATCH ( 0 ), - .L0_EARLY_TAG_WIDTH ( snitch_pkg::PAGE_SHIFT - $clog2(ICacheLineWidth/8) ), - .ISO_CROSSING ( 1'b0 ), - .axi_req_t ( axi_mst_dma_req_t ), - .axi_rsp_t ( axi_mst_dma_resp_t ), - .sram_cfg_data_t ( impl_in_t ), - .sram_cfg_tag_t ( impl_in_t ) - ) i_snitch_icache ( - .clk_i ( clk_i ), - .clk_d2_i ( clk_i ), - .rst_ni ( rst_ni ), - .enable_prefetching_i ( icache_prefetch_enable ), - .icache_events_o ( icache_events ), - .flush_valid_i ( flush_valid ), - .flush_ready_o ( flush_ready ), - .inst_addr_i ( inst_addr ), - .inst_cacheable_i ( inst_cacheable ), - .inst_data_o ( inst_data ), - .inst_valid_i ( inst_valid ), - .inst_ready_o ( inst_ready ), - .inst_error_o ( inst_error ), - .sram_cfg_tag_i ( impl_l1i_tag ), - .sram_cfg_data_i ( impl_l1i_data ), - .axi_req_o ( wide_axi_mst_req[ICache] ), - .axi_rsp_i ( wide_axi_mst_rsp[ICache] ) - ); - - // -------- - // Cores SoC - // -------- - spatz_barrier #( - .AddrWidth (AxiAddrWidth ), - .NrPorts (NrCores ), - .dreq_t (reqrsp_req_t ), - .drsp_t (reqrsp_rsp_t ) - ) i_snitch_barrier ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .in_req_i (core_req ), - .in_rsp_o (core_rsp ), - .out_req_o (filtered_core_req ), - .out_rsp_i (filtered_core_rsp ), - .cluster_periph_start_address_i (cluster_periph_start_address) - ); - - reqrsp_req_t core_to_axi_req; - reqrsp_rsp_t core_to_axi_rsp; - user_t cluster_user; - // Atomic ID, needs to be unique ID of cluster - // cluster_id + HartIdOffset + 1 (because 0 is for non-atomic masters) - assign cluster_user = (hart_base_id_i / NrCores) + (hart_base_id_i % NrCores) + 1'b1; - - reqrsp_mux #( - .NrPorts (NrCores ), - .AddrWidth (AxiAddrWidth ), - .DataWidth (NarrowDataWidth ), - .req_t (reqrsp_req_t ), - .rsp_t (reqrsp_rsp_t ), - .RespDepth (2 ) - ) i_reqrsp_mux_core ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .slv_req_i (filtered_core_req), - .slv_rsp_o (filtered_core_rsp), - .mst_req_o (core_to_axi_req ), - .mst_rsp_i (core_to_axi_rsp ), - .idx_o (/*unused*/ ) - ); - - reqrsp_to_axi #( - .DataWidth (NarrowDataWidth), - .UserWidth (NarrowUserWidth), - .reqrsp_req_t (reqrsp_req_t ), - .reqrsp_rsp_t (reqrsp_rsp_t ), - .axi_req_t (axi_mst_req_t ), - .axi_rsp_t (axi_mst_resp_t ) - ) i_reqrsp_to_axi_core ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .user_i (cluster_user ), - .reqrsp_req_i (core_to_axi_req ), - .reqrsp_rsp_o (core_to_axi_rsp ), - .axi_req_o (narrow_axi_mst_req[CoreReq]), - .axi_rsp_i (narrow_axi_mst_rsp[CoreReq]) - ); - - xbar_rule_t [NrNarrowRules-1:0] cluster_xbar_rules; - - assign cluster_xbar_rules = '{ - '{ - idx : TCDM, - start_addr: tcdm_start_address, - end_addr : tcdm_end_address - }, - '{ - idx : ClusterPeripherals, - start_addr: cluster_periph_start_address, - end_addr : cluster_periph_end_address - } - }; - - localparam bit [ClusterXbarCfg.NoSlvPorts-1:0] ClusterEnableDefaultMstPort = '1; - localparam logic [ClusterXbarCfg.NoSlvPorts-1:0][cf_math_pkg::idx_width(ClusterXbarCfg.NoMstPorts)-1:0] ClusterXbarDefaultPort = '{default: SoC}; - - axi_xbar #( - .Cfg (ClusterXbarCfg ), - .slv_aw_chan_t (axi_mst_aw_chan_t), - .mst_aw_chan_t (axi_slv_aw_chan_t), - .w_chan_t (axi_mst_w_chan_t ), - .slv_b_chan_t (axi_mst_b_chan_t ), - .mst_b_chan_t (axi_slv_b_chan_t ), - .slv_ar_chan_t (axi_mst_ar_chan_t), - .mst_ar_chan_t (axi_slv_ar_chan_t), - .slv_r_chan_t (axi_mst_r_chan_t ), - .mst_r_chan_t (axi_slv_r_chan_t ), - .slv_req_t (axi_mst_req_t ), - .slv_resp_t (axi_mst_resp_t ), - .mst_req_t (axi_slv_req_t ), - .mst_resp_t (axi_slv_resp_t ), - .rule_t (xbar_rule_t ) - ) i_cluster_xbar ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .test_i (1'b0 ), - .slv_ports_req_i (narrow_axi_mst_req ), - .slv_ports_resp_o (narrow_axi_mst_rsp ), - .mst_ports_req_o (narrow_axi_slv_req ), - .mst_ports_resp_i (narrow_axi_slv_rsp ), - .addr_map_i (cluster_xbar_rules ), - .en_default_mst_port_i (ClusterEnableDefaultMstPort), - .default_mst_port_i (ClusterXbarDefaultPort ) - ); - - // --------- - // Slaves - // --------- - // 1. TCDM - // Add an adapter that allows access from AXI to the TCDM. - axi_to_tcdm #( - .axi_req_t (axi_slv_req_t ), - .axi_rsp_t (axi_slv_resp_t ), - .tcdm_req_t (spm_req_t ), - .tcdm_rsp_t (spm_rsp_t ), - .AddrWidth (AxiAddrWidth ), - .DataWidth (NarrowDataWidth ), - .IdWidth (NarrowIdWidthOut ), - .BufDepth (MemoryMacroLatency + 1) - ) i_axi_to_tcdm ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .axi_req_i (narrow_axi_slv_req[TCDM]), - .axi_rsp_o (narrow_axi_slv_rsp[TCDM]), - .tcdm_req_o (axi_soc_req ), - .tcdm_rsp_i (axi_soc_rsp ) - ); - - // 2. Peripherals - axi_to_reg #( - .ADDR_WIDTH (AxiAddrWidth ), - .DATA_WIDTH (NarrowDataWidth ), - .AXI_MAX_WRITE_TXNS (1 ), - .AXI_MAX_READ_TXNS (1 ), - .DECOUPLE_W (0 ), - .ID_WIDTH (NarrowIdWidthOut ), - .USER_WIDTH (NarrowUserWidth ), - .axi_req_t (axi_slv_req_t ), - .axi_rsp_t (axi_slv_resp_t ), - .reg_req_t (reg_req_t ), - .reg_rsp_t (reg_rsp_t ) - ) i_axi_to_reg ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .testmode_i (1'b0 ), - .axi_req_i (narrow_axi_slv_req[ClusterPeripherals]), - .axi_rsp_o (narrow_axi_slv_rsp[ClusterPeripherals]), - .reg_req_o (reg_req ), - .reg_rsp_i (reg_rsp ) - ); - - spatz_cluster_peripheral #( - .AddrWidth (AxiAddrWidth ), - .SPMWidth ($clog2(L1NumSet)), - .reg_req_t (reg_req_t ), - .reg_rsp_t (reg_rsp_t ), - .tcdm_events_t (tcdm_events_t ), - .dma_events_t (dma_events_t ), - .NrCores (NrCores ) - ) i_snitch_cluster_peripheral ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .reg_req_i (reg_req ), - .reg_rsp_o (reg_rsp ), - /// The TCDM always starts at the cluster base. - .tcdm_start_address_i (tcdm_start_address ), - .tcdm_end_address_i (tcdm_end_address ), - .icache_prefetch_enable_o (icache_prefetch_enable), - .cl_clint_o (cl_interrupt ), - .cluster_hart_base_id_i (hart_base_id_i ), - .core_events_i (core_events ), - .tcdm_events_i (tcdm_events ), - .dma_events_i (dma_events ), - .icache_events_i (icache_events ), - .cluster_probe_o (cluster_probe_o ), - .l1d_spm_size_o (cfg_spm_size ), - .l1d_insn_o (l1d_insn ), - .l1d_insn_valid_o (l1d_insn_valid ), - .l1d_insn_ready_i (l1d_insn_ready ), - .l1d_busy_o (l1d_busy ) - ); - - // 3. BootROM - axi_to_reg #( - .ADDR_WIDTH (AxiAddrWidth ), - .DATA_WIDTH (AxiDataWidth ), - .AXI_MAX_WRITE_TXNS (1 ), - .AXI_MAX_READ_TXNS (1 ), - .DECOUPLE_W (0 ), - .ID_WIDTH (WideIdWidthOut ), - .USER_WIDTH (AxiUserWidth ), - .axi_req_t (axi_slv_dma_req_t ), - .axi_rsp_t (axi_slv_dma_resp_t), - .reg_req_t (reg_dma_req_t ), - .reg_rsp_t (reg_dma_rsp_t ) - ) i_axi_to_reg_bootrom ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .testmode_i (1'b0 ), - .axi_req_i (wide_axi_slv_req[BootROM]), - .axi_rsp_o (wide_axi_slv_rsp[BootROM]), - .reg_req_o (bootrom_reg_req ), - .reg_rsp_i (bootrom_reg_rsp ) - ); - - bootrom i_bootrom ( - .clk_i (clk_i ), - .req_i (bootrom_reg_req.valid ), - .addr_i (addr_t'(bootrom_reg_req.addr)), - .rdata_o(bootrom_reg_rsp.rdata ) - ); - `FF(bootrom_reg_rsp.ready, bootrom_reg_req.valid, 1'b0) - assign bootrom_reg_rsp.error = 1'b0; - - // Upsize the narrow SoC connection - `AXI_TYPEDEF_ALL(axi_mst_dma_narrow, addr_t, id_dma_mst_t, data_t, strb_t, user_t) - axi_mst_dma_narrow_req_t narrow_axi_slv_req_soc; - axi_mst_dma_narrow_resp_t narrow_axi_slv_resp_soc; - - axi_iw_converter #( - .AxiAddrWidth (AxiAddrWidth ), - .AxiDataWidth (NarrowDataWidth ), - .AxiUserWidth (AxiUserWidth ), - .AxiSlvPortIdWidth (NarrowIdWidthOut ), - .AxiSlvPortMaxUniqIds (1 ), - .AxiSlvPortMaxTxnsPerId(1 ), - .AxiSlvPortMaxTxns (1 ), - .AxiMstPortIdWidth (WideIdWidthIn ), - .AxiMstPortMaxUniqIds (1 ), - .AxiMstPortMaxTxnsPerId(1 ), - .slv_req_t (axi_slv_req_t ), - .slv_resp_t (axi_slv_resp_t ), - .mst_req_t (axi_mst_dma_narrow_req_t ), - .mst_resp_t (axi_mst_dma_narrow_resp_t) - ) i_soc_port_iw_convert ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .slv_req_i (narrow_axi_slv_req[SoC] ), - .slv_resp_o (narrow_axi_slv_rsp[SoC] ), - .mst_req_o (narrow_axi_slv_req_soc ), - .mst_resp_i (narrow_axi_slv_resp_soc ) - ); - - axi_dw_converter #( - .AxiAddrWidth (AxiAddrWidth ), - .AxiIdWidth (WideIdWidthIn ), - .AxiMaxReads (2 ), - .AxiSlvPortDataWidth(NarrowDataWidth ), - .AxiMstPortDataWidth(AxiDataWidth ), - .ar_chan_t (axi_mst_dma_ar_chan_t ), - .aw_chan_t (axi_mst_dma_aw_chan_t ), - .b_chan_t (axi_mst_dma_b_chan_t ), - .slv_r_chan_t (axi_mst_dma_narrow_r_chan_t), - .slv_w_chan_t (axi_mst_dma_narrow_b_chan_t), - .axi_slv_req_t (axi_mst_dma_narrow_req_t ), - .axi_slv_resp_t (axi_mst_dma_narrow_resp_t ), - .mst_r_chan_t (axi_mst_dma_r_chan_t ), - .mst_w_chan_t (axi_mst_dma_w_chan_t ), - .axi_mst_req_t (axi_mst_dma_req_t ), - .axi_mst_resp_t (axi_mst_dma_resp_t ) - ) i_soc_port_dw_upsize ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .slv_req_i (narrow_axi_slv_req_soc ), - .slv_resp_o (narrow_axi_slv_resp_soc ), - .mst_req_o (wide_axi_mst_req[CoreReqWide]), - .mst_resp_i (wide_axi_mst_rsp[CoreReqWide]) - ); - - // -------------------- - // TCDM event counters - // -------------------- - logic [NrTCDMPortsCores-1:0] flat_acc, flat_con; - for (genvar i = 0; i < NrTCDMPortsCores; i++) begin : gen_event_counter - `FFARN(flat_acc[i], tcdm_req[i].q_valid, '0, clk_i, rst_ni) - `FFARN(flat_con[i], tcdm_req[i].q_valid & ~tcdm_rsp[i].q_ready, '0, clk_i, rst_ni) - end - - popcount #( - .INPUT_WIDTH ( NrTCDMPortsCores ) - ) i_popcount_req ( - .data_i ( flat_acc ), - .popcount_o ( tcdm_events.inc_accessed ) - ); - - popcount #( - .INPUT_WIDTH ( NrTCDMPortsCores ) - ) i_popcount_con ( - .data_i ( flat_con ), - .popcount_o ( tcdm_events.inc_congested ) - ); - - // ------------- - // Sanity Checks - // ------------- - // Sanity check the parameters. Not every configuration makes sense. - `ASSERT_INIT(CheckSuperBankSanity, NrBanks >= BanksPerSuperBank); - `ASSERT_INIT(CheckSuperBankFactor, (NrBanks % BanksPerSuperBank) == 0); - // Check that the cluster base address aligns to the TCDMSize. - `ASSERT(ClusterBaseAddrAlign, ((TCDMSize - 1) & cluster_base_addr_i) == 0) - // Make sure we only have one DMA in the system. - `ASSERT_INIT(NumberDMA, $onehot0(Xdma)) - -endmodule From 5dba4f23bfae73b870ed1721b9f2306597d061e1 Mon Sep 17 00:00:00 2001 From: Zexin Fu Date: Fri, 25 Apr 2025 03:50:31 +0200 Subject: [PATCH 06/17] [SW] Add multi_producer_single_consumer_double_linked_list kernel and its runtimes, the spin lock is still under debugging. --- hardware/deps/spatz | 2 +- software/tests/CMakeLists.txt | 7 + .../data/data_256_16.h | 4175 +++++++++++++++++ .../data/data_64_8.h | 559 +++ .../data/layer.h | 160 + .../kernel/debug.c | 33 + .../kernel/debug.h | 21 + .../kernel/llist.c | 80 + .../kernel/llist.h | 68 + .../kernel/mm.c | 90 + .../kernel/mm.h | 49 + .../kernel/rlc.c | 84 + .../kernel/rlc.h | 29 + .../main.c | 35 + 14 files changed, 5391 insertions(+), 1 deletion(-) create mode 100644 software/tests/multi_producer_single_consumer_double_linked_list/data/data_256_16.h create mode 100644 software/tests/multi_producer_single_consumer_double_linked_list/data/data_64_8.h create mode 100644 software/tests/multi_producer_single_consumer_double_linked_list/data/layer.h create mode 100644 software/tests/multi_producer_single_consumer_double_linked_list/kernel/debug.c create mode 100644 software/tests/multi_producer_single_consumer_double_linked_list/kernel/debug.h create mode 100644 software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.c create mode 100644 software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.h create mode 100644 software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.c create mode 100644 software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.h create mode 100644 software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.c create mode 100644 software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.h create mode 100644 software/tests/multi_producer_single_consumer_double_linked_list/main.c diff --git a/hardware/deps/spatz b/hardware/deps/spatz index 03ab785..1a8b23e 160000 --- a/hardware/deps/spatz +++ b/hardware/deps/spatz @@ -1 +1 @@ -Subproject commit 03ab78561a42ba5865d1ab6d08554ce4ef5436ab +Subproject commit 1a8b23e52468c132f2a47abccb4502326803ad76 diff --git a/software/tests/CMakeLists.txt b/software/tests/CMakeLists.txt index 2e31f38..6c591f1 100644 --- a/software/tests/CMakeLists.txt +++ b/software/tests/CMakeLists.txt @@ -22,8 +22,15 @@ add_compile_options(-DELEN=64) include_directories(include) include_directories(${SNRUNTIME_INCLUDE_DIRS}) +add_library(debug_print multi_producer_single_consumer_double_linked_list/kernel/debug.c) +add_library(llist multi_producer_single_consumer_double_linked_list/kernel/llist.c) +add_library(mm multi_producer_single_consumer_double_linked_list/kernel/mm.c) +add_library(rlc multi_producer_single_consumer_double_linked_list/kernel/rlc.c) + # Tests enable_testing() set(SNITCH_TEST_PREFIX cachepool-) add_snitch_test(spin-lock spin-lock/main.c) + +add_snitch_test(multi_producer_single_consumer_double_linked_list multi_producer_single_consumer_double_linked_list/main.c) \ No newline at end of file diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/data/data_256_16.h b/software/tests/multi_producer_single_consumer_double_linked_list/data/data_256_16.h new file mode 100644 index 0000000..c8cd531 --- /dev/null +++ b/software/tests/multi_producer_single_consumer_double_linked_list/data/data_256_16.h @@ -0,0 +1,4175 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This file was generated automatically. + +#include "layer.h" + +int N = 256; + +int N_list = 16; + +node_t nodes0[] = { + {.next = &nodes0[3], .payload = {.id = 130, .data = (double)-38.497175}}, + {.next = &nodes0[224], .payload = {.id = 223, .data = (double)49.595112}}, + {.next = &nodes0[159], .payload = {.id = 59, .data = (double)-24.108912}}, + {.next = &nodes0[7], .payload = {.id = 131, .data = (double)-88.414967}}, + {.next = &nodes0[75], .payload = {.id = 198, .data = (double)99.856494}}, + {.next = &nodes0[70], .payload = {.id = 121, .data = (double)7.875806}}, + {.next = &nodes0[238], .payload = {.id = 138, .data = (double)53.166886}}, + {.next = &nodes0[131], .payload = {.id = 132, .data = (double)75.60192}}, + {.next = &nodes0[69], .payload = {.id = 81, .data = (double)-47.451678}}, + {.next = &nodes0[119], .payload = {.id = 3, .data = (double)-55.357852}}, + {.next = &nodes0[21], .payload = {.id = 253, .data = (double)-8.342895}}, + {.next = &nodes0[34], .payload = {.id = 145, .data = (double)-57.640359}}, + {.next = &nodes0[73], .payload = {.id = 151, .data = (double)29.975612}}, + {.next = &nodes0[227], .payload = {.id = 75, .data = (double)-20.87362}}, + {.next = &nodes0[147], .payload = {.id = 96, .data = (double)99.224276}}, + {.next = &nodes0[77], .payload = {.id = 193, .data = (double)84.65312}}, + {.next = &nodes0[145], .payload = {.id = 119, .data = (double)-69.432146}}, + {.next = &nodes0[84], .payload = {.id = 127, .data = (double)85.819723}}, + {.next = &nodes0[118], .payload = {.id = 202, .data = (double)69.739147}}, + {.next = &nodes0[60], .payload = {.id = 98, .data = (double)94.215676}}, + {.next = &nodes0[65], .payload = {.id = 35, .data = (double)10.408126}}, + {.next = &nodes0[175], .payload = {.id = 254, .data = (double)99.690888}}, + {.next = &nodes0[24], .payload = {.id = 214, .data = (double)91.463528}}, + {.next = &nodes0[191], .payload = {.id = 188, .data = (double)-61.958218}}, + {.next = &nodes0[66], .payload = {.id = 215, .data = (double)99.084538}}, + {.next = &nodes0[23], .payload = {.id = 187, .data = (double)-50.268733}}, + {.next = &nodes0[111], .payload = {.id = 115, .data = (double)74.103714}}, + {.next = &nodes0[43], .payload = {.id = 106, .data = (double)-77.689565}}, + {.next = &nodes0[177], .payload = {.id = 148, .data = (double)-59.769787}}, + {.next = &nodes0[244], .payload = {.id = 61, .data = (double)27.999952}}, + {.next = &nodes0[173], .payload = {.id = 31, .data = (double)45.946357}}, + {.next = &nodes0[80], .payload = {.id = 159, .data = (double)-55.956523}}, + {.next = &nodes0[163], .payload = {.id = 185, .data = (double)-32.139479}}, + {.next = &nodes0[231], .payload = {.id = 1, .data = (double)-94.997849}}, + {.next = &nodes0[47], .payload = {.id = 146, .data = (double)7.859218}}, + {.next = &nodes0[203], .payload = {.id = 12, .data = (double)-94.692806}}, + {.next = &nodes0[52], .payload = {.id = 200, .data = (double)93.799251}}, + {.next = &nodes0[239], .payload = {.id = 212, .data = (double)-8.998327}}, + {.next = &nodes0[134], .payload = {.id = 83, .data = (double)79.564577}}, + {.next = &nodes0[226], .payload = {.id = 168, .data = (double)-57.152639}}, + {.next = &nodes0[122], .payload = {.id = 21, .data = (double)39.627879}}, + {.next = &nodes0[8], .payload = {.id = 80, .data = (double)12.273627}}, + {.next = &nodes0[248], .payload = {.id = 88, .data = (double)-81.818118}}, + {.next = &nodes0[200], .payload = {.id = 107, .data = (double)-13.04695}}, + {.next = &nodes0[211], .payload = {.id = 86, .data = (double)99.507521}}, + {.next = &nodes0[183], .payload = {.id = 18, .data = (double)61.886091}}, + {.next = &nodes0[162], .payload = {.id = 103, .data = (double)7.394066}}, + {.next = &nodes0[28], .payload = {.id = 147, .data = (double)45.986214}}, + {.next = &nodes0[117], .payload = {.id = 226, .data = (double)0.570077}}, + {.next = &nodes0[71], .payload = {.id = 47, .data = (double)-44.405279}}, + {.next = &nodes0[165], .payload = {.id = 244, .data = (double)-59.14816}}, + {.next = &nodes0[30], .payload = {.id = 30, .data = (double)61.425655}}, + {.next = &nodes0[18], .payload = {.id = 201, .data = (double)85.273397}}, + {.next = &nodes0[16], .payload = {.id = 118, .data = (double)21.794042}}, + {.next = &nodes0[115], .payload = {.id = 43, .data = (double)-42.122407}}, + {.next = &nodes0[11], .payload = {.id = 144, .data = (double)-15.372412}}, + {.next = &nodes0[32], .payload = {.id = 184, .data = (double)-19.475744}}, + {.next = &nodes0[207], .payload = {.id = 221, .data = (double)15.836058}}, + {.next = &nodes0[40], .payload = {.id = 20, .data = (double)61.16385}}, + {.next = &nodes0[228], .payload = {.id = 140, .data = (double)-4.943524}}, + {.next = &nodes0[113], .payload = {.id = 99, .data = (double)72.15594}}, + {.next = &nodes0[186], .payload = {.id = 142, .data = (double)-46.988674}}, + {.next = &nodes0[143], .payload = {.id = 50, .data = (double)-25.963807}}, + {.next = &nodes0[152], .payload = {.id = 234, .data = (double)-52.959221}}, + {.next = &nodes0[151], .payload = {.id = 165, .data = (double)-85.82853}}, + {.next = &nodes0[255], .payload = {.id = 36, .data = (double)65.880933}}, + {.next = &nodes0[160], .payload = {.id = 216, .data = (double)11.153665}}, + {.next = &nodes0[148], .payload = {.id = 219, .data = (double)-40.658435}}, + {.next = &nodes0[209], .payload = {.id = 174, .data = (double)61.4994}}, + {.next = &nodes0[38], .payload = {.id = 82, .data = (double)16.917198}}, + {.next = &nodes0[120], .payload = {.id = 122, .data = (double)55.725296}}, + {.next = &nodes0[136], .payload = {.id = 48, .data = (double)27.136889}}, + {.next = &nodes0[63], .payload = {.id = 233, .data = (double)35.042511}}, + {.next = &nodes0[93], .payload = {.id = 152, .data = (double)-12.379983}}, + {.next = &nodes0[246], .payload = {.id = 16, .data = (double)-55.911876}}, + {.next = &nodes0[36], .payload = {.id = 199, .data = (double)67.205517}}, + {.next = &nodes0[114], .payload = {.id = 229, .data = (double)92.155781}}, + {.next = &nodes0[123], .payload = {.id = 194, .data = (double)-11.373851}}, + {.next = &nodes0[208], .payload = {.id = 161, .data = (double)26.220591}}, + {.next = &nodes0[97], .payload = {.id = 210, .data = (double)-46.959388}}, + {.next = &nodes0[78], .payload = {.id = 160, .data = (double)-85.801383}}, + {.next = &nodes0[85], .payload = {.id = 204, .data = (double)-2.871775}}, + {.next = &nodes0[130], .payload = {.id = 181, .data = (double)34.672909}}, + {.next = &nodes0[74], .payload = {.id = 15, .data = (double)8.988296}}, + {.next = &nodes0[252], .payload = {.id = 128, .data = (double)75.744376}}, + {.next = &nodes0[234], .payload = {.id = 205, .data = (double)-57.25054}}, + {.next = &nodes0[41], .payload = {.id = 79, .data = (double)-50.674498}}, + {.next = &nodes0[54], .payload = {.id = 42, .data = (double)-54.420345}}, + {.next = &nodes0[26], .payload = {.id = 114, .data = (double)82.525568}}, + {.next = &nodes0[179], .payload = {.id = 8, .data = (double)-15.615636}}, + {.next = &nodes0[135], .payload = {.id = 101, .data = (double)44.144364}}, + {.next = &nodes0[49], .payload = {.id = 46, .data = (double)-79.799714}}, + {.next = &nodes0[225], .payload = {.id = 25, .data = (double)-32.681091}}, + {.next = &nodes0[214], .payload = {.id = 153, .data = (double)3.515168}}, + {.next = &nodes0[14], .payload = {.id = 95, .data = (double)-23.676143}}, + {.next = &nodes0[146], .payload = {.id = 178, .data = (double)-15.284275}}, + {.next = &nodes0[170], .payload = {.id = 92, .data = (double)58.415873}}, + {.next = &nodes0[37], .payload = {.id = 211, .data = (double)56.81412}}, + {.next = &nodes0[12], .payload = {.id = 150, .data = (double)99.029871}}, + {.next = &nodes0[251], .payload = {.id = 66, .data = (double)-54.190386}}, + {.next = &nodes0[4], .payload = {.id = 197, .data = (double)-89.882334}}, + {.next = &nodes0[240], .payload = {.id = 111, .data = (double)-47.32219}}, + {.next = &nodes0[64], .payload = {.id = 164, .data = (double)71.92708}}, + {.next = &nodes0[155], .payload = {.id = 5, .data = (double)35.339897}}, + {.next = &nodes0[68], .payload = {.id = 173, .data = (double)56.923885}}, + {.next = &nodes0[92], .payload = {.id = 24, .data = (double)91.442614}}, + {.next = &nodes0[121], .payload = {.id = 73, .data = (double)-37.064424}}, + {.next = &nodes0[254], .payload = {.id = 136, .data = (double)-86.157496}}, + {.next = &nodes0[17], .payload = {.id = 126, .data = (double)-96.104652}}, + {.next = &nodes0[99], .payload = {.id = 65, .data = (double)55.199982}}, + {.next = &nodes0[188], .payload = {.id = 236, .data = (double)78.057463}}, + {.next = &nodes0[142], .payload = {.id = 116, .data = (double)-40.311042}}, + {.next = &nodes0[95], .payload = {.id = 177, .data = (double)-13.789764}}, + {.next = &nodes0[90], .payload = {.id = 100, .data = (double)-97.703796}}, + {.next = &nodes0[185], .payload = {.id = 230, .data = (double)-83.977707}}, + {.next = &nodes0[157], .payload = {.id = 44, .data = (double)-84.041605}}, + {.next = &nodes0[144], .payload = {.id = 55, .data = (double)21.826201}}, + {.next = &nodes0[218], .payload = {.id = 227, .data = (double)70.543978}}, + {.next = &nodes0[81], .payload = {.id = 203, .data = (double)-66.737778}}, + {.next = &nodes0[103], .payload = {.id = 4, .data = (double)47.294243}}, + {.next = &nodes0[124], .payload = {.id = 123, .data = (double)6.070734}}, + {.next = &nodes0[13], .payload = {.id = 74, .data = (double)31.087733}}, + {.next = &nodes0[202], .payload = {.id = 22, .data = (double)-31.949897}}, + {.next = &nodes0[153], .payload = {.id = 195, .data = (double)72.269821}}, + {.next = &nodes0[205], .payload = {.id = 124, .data = (double)-99.885621}}, + {.next = &nodes0[149], .payload = {.id = 240, .data = (double)-16.155017}}, + {.next = &nodes0[83], .payload = {.id = 14, .data = (double)29.976888}}, + {.next = &nodes0[89], .payload = {.id = 7, .data = (double)-82.612233}}, + {.next = &nodes0[232], .payload = {.id = 134, .data = (double)-82.86931}}, + {.next = &nodes0[72], .payload = {.id = 232, .data = (double)19.007021}}, + {.next = &nodes0[212], .payload = {.id = 182, .data = (double)96.833042}}, + {.next = &nodes0[128], .payload = {.id = 133, .data = (double)89.389889}}, + {.next = &nodes0[245], .payload = {.id = 246, .data = (double)-52.262809}}, + {.next = &nodes0[242], .payload = {.id = 71, .data = (double)88.581943}}, + {.next = &nodes0[196], .payload = {.id = 84, .data = (double)-20.119899}}, + {.next = &nodes0[46], .payload = {.id = 102, .data = (double)36.342074}}, + {.next = &nodes0[62], .payload = {.id = 49, .data = (double)-27.033564}}, + {.next = &nodes0[235], .payload = {.id = 155, .data = (double)-55.060533}}, + {.next = &nodes0[139], .payload = {.id = 57, .data = (double)45.82536}}, + {.next = &nodes0[2], .payload = {.id = 58, .data = (double)-67.319501}}, + {.next = &nodes0[169], .payload = {.id = 171, .data = (double)14.208619}}, + {.next = &nodes0[180], .payload = {.id = 248, .data = (double)34.338045}}, + {.next = &nodes0[53], .payload = {.id = 117, .data = (double)27.789899}}, + {.next = &nodes0[210], .payload = {.id = 51, .data = (double)-58.098594}}, + {.next = &nodes0[138], .payload = {.id = 56, .data = (double)-65.77227}}, + {.next = &nodes0[5], .payload = {.id = 120, .data = (double)52.50216}}, + {.next = &nodes0[237], .payload = {.id = 179, .data = (double)-6.595066}}, + {.next = &nodes0[19], .payload = {.id = 97, .data = (double)5.822869}}, + {.next = &nodes0[57], .payload = {.id = 220, .data = (double)93.741873}}, + {.next = &nodes0[215], .payload = {.id = 241, .data = (double)16.734458}}, + {.next = &nodes0[216], .payload = {.id = 68, .data = (double)-36.90939}}, + {.next = &nodes0[233], .payload = {.id = 166, .data = (double)-52.399073}}, + {.next = &nodes0[110], .payload = {.id = 235, .data = (double)-76.022677}}, + {.next = &nodes0[100], .payload = {.id = 196, .data = (double)10.065062}}, + {.next = &nodes0[161], .payload = {.id = 157, .data = (double)17.661744}}, + {.next = &nodes0[127], .payload = {.id = 6, .data = (double)78.435914}}, + {.next = &nodes0[27], .payload = {.id = 105, .data = (double)28.19236}}, + {.next = &nodes0[91], .payload = {.id = 45, .data = (double)-53.441823}}, + {.next = &nodes0[15], .payload = {.id = 192, .data = (double)-50.03871}}, + {.next = &nodes0[29], .payload = {.id = 60, .data = (double)97.90467}}, + {.next = &nodes0[189], .payload = {.id = 217, .data = (double)43.681655}}, + {.next = &nodes0[31], .payload = {.id = 158, .data = (double)-53.977053}}, + {.next = &nodes0[156], .payload = {.id = 104, .data = (double)-46.634962}}, + {.next = &nodes0[25], .payload = {.id = 186, .data = (double)72.334507}}, + {.next = &nodes0[168], .payload = {.id = 90, .data = (double)-78.070174}}, + {.next = &nodes0[132], .payload = {.id = 245, .data = (double)43.23836}}, + {.next = &nodes0[204], .payload = {.id = 63, .data = (double)36.92285}}, + {.next = &nodes0[125], .payload = {.id = 239, .data = (double)23.876302}}, + {.next = &nodes0[96], .payload = {.id = 91, .data = (double)25.489208}}, + {.next = &nodes0[104], .payload = {.id = 172, .data = (double)-5.465795}}, + {.next = &nodes0[243], .payload = {.id = 93, .data = (double)-15.568007}}, + {.next = &nodes0[86], .payload = {.id = 78, .data = (double)-47.023967}}, + {.next = &nodes0[198], .payload = {.id = 10, .data = (double)-56.272405}}, + {.next = &nodes0[250], .payload = {.id = 32, .data = (double)7.245618}}, + {.next = &nodes0[101], .payload = {.id = 110, .data = (double)75.170588}}, + {.next = NULL, .payload = {.id = 255, .data = (double)99.21929}}, + {.next = &nodes0[158], .payload = {.id = 191, .data = (double)-44.290971}}, + {.next = &nodes0[98], .payload = {.id = 149, .data = (double)-37.656742}}, + {.next = &nodes0[50], .payload = {.id = 243, .data = (double)86.941252}}, + {.next = &nodes0[172], .payload = {.id = 9, .data = (double)-94.040556}}, + {.next = &nodes0[195], .payload = {.id = 249, .data = (double)-40.000584}}, + {.next = &nodes0[217], .payload = {.id = 38, .data = (double)72.34138}}, + {.next = &nodes0[112], .payload = {.id = 176, .data = (double)-80.613837}}, + {.next = &nodes0[58], .payload = {.id = 19, .data = (double)-98.700248}}, + {.next = &nodes0[221], .payload = {.id = 28, .data = (double)69.498873}}, + {.next = &nodes0[129], .payload = {.id = 231, .data = (double)-62.835008}}, + {.next = &nodes0[55], .payload = {.id = 143, .data = (double)74.486608}}, + {.next = &nodes0[174], .payload = {.id = 109, .data = (double)90.763186}}, + {.next = &nodes0[249], .payload = {.id = 237, .data = (double)-50.75693}}, + {.next = &nodes0[67], .payload = {.id = 218, .data = (double)-69.040635}}, + {.next = &nodes0[88], .payload = {.id = 113, .data = (double)-64.269624}}, + {.next = &nodes0[219], .payload = {.id = 189, .data = (double)-10.27729}}, + {.next = &nodes0[87], .payload = {.id = 41, .data = (double)-90.835123}}, + {.next = &nodes0[201], .payload = {.id = 207, .data = (double)-88.27292}}, + {.next = &nodes0[102], .payload = {.id = 163, .data = (double)81.084003}}, + {.next = &nodes0[222], .payload = {.id = 250, .data = (double)-36.764561}}, + {.next = &nodes0[44], .payload = {.id = 85, .data = (double)-56.135848}}, + {.next = &nodes0[33], .payload = {.id = 0, .data = (double)27.88536}}, + {.next = &nodes0[35], .payload = {.id = 11, .data = (double)1.071058}}, + {.next = &nodes0[133], .payload = {.id = 70, .data = (double)-57.803431}}, + {.next = &nodes0[187], .payload = {.id = 108, .data = (double)-9.255259}}, + {.next = &nodes0[229], .payload = {.id = 208, .data = (double)-24.205376}}, + {.next = &nodes0[105], .payload = {.id = 23, .data = (double)-68.9041}}, + {.next = &nodes0[126], .payload = {.id = 13, .data = (double)-60.23247}}, + {.next = &nodes0[109], .payload = {.id = 64, .data = (double)68.570384}}, + {.next = &nodes0[108], .payload = {.id = 125, .data = (double)-35.168789}}, + {.next = &nodes0[10], .payload = {.id = 252, .data = (double)-85.491377}}, + {.next = &nodes0[1], .payload = {.id = 222, .data = (double)8.43904}}, + {.next = &nodes0[194], .payload = {.id = 162, .data = (double)-54.211643}}, + {.next = &nodes0[182], .payload = {.id = 175, .data = (double)-61.918017}}, + {.next = &nodes0[213], .payload = {.id = 52, .data = (double)-46.604436}}, + {.next = &nodes0[42], .payload = {.id = 87, .data = (double)1.905259}}, + {.next = &nodes0[56], .payload = {.id = 183, .data = (double)-80.316426}}, + {.next = &nodes0[253], .payload = {.id = 53, .data = (double)87.330918}}, + {.next = &nodes0[137], .payload = {.id = 154, .data = (double)-75.799161}}, + {.next = &nodes0[178], .payload = {.id = 242, .data = (double)4.556543}}, + {.next = &nodes0[199], .payload = {.id = 69, .data = (double)-46.451825}}, + {.next = &nodes0[241], .payload = {.id = 39, .data = (double)15.470429}}, + {.next = &nodes0[76], .payload = {.id = 228, .data = (double)-68.513454}}, + {.next = &nodes0[176], .payload = {.id = 190, .data = (double)-15.623672}}, + {.next = &nodes0[184], .payload = {.id = 27, .data = (double)-80.656725}}, + {.next = &nodes0[51], .payload = {.id = 29, .data = (double)20.745206}}, + {.next = &nodes0[206], .payload = {.id = 251, .data = (double)50.372898}}, + {.next = &nodes0[20], .payload = {.id = 34, .data = (double)-24.293125}}, + {.next = &nodes0[247], .payload = {.id = 224, .data = (double)-88.566945}}, + {.next = &nodes0[220], .payload = {.id = 26, .data = (double)-81.450831}}, + {.next = &nodes0[230], .payload = {.id = 169, .data = (double)-73.53763}}, + {.next = &nodes0[236], .payload = {.id = 76, .data = (double)82.909518}}, + {.next = &nodes0[61], .payload = {.id = 141, .data = (double)9.960719}}, + {.next = &nodes0[79], .payload = {.id = 209, .data = (double)97.061769}}, + {.next = &nodes0[140], .payload = {.id = 170, .data = (double)87.102848}}, + {.next = &nodes0[9], .payload = {.id = 2, .data = (double)-44.994136}}, + {.next = &nodes0[107], .payload = {.id = 135, .data = (double)-2.801907}}, + {.next = &nodes0[39], .payload = {.id = 167, .data = (double)33.795556}}, + {.next = &nodes0[193], .payload = {.id = 206, .data = (double)-19.791941}}, + {.next = &nodes0[154], .payload = {.id = 156, .data = (double)-32.382888}}, + {.next = &nodes0[171], .payload = {.id = 77, .data = (double)-8.229629}}, + {.next = &nodes0[82], .payload = {.id = 180, .data = (double)45.81517}}, + {.next = &nodes0[59], .payload = {.id = 139, .data = (double)-74.321707}}, + {.next = &nodes0[22], .payload = {.id = 213, .data = (double)-15.398503}}, + {.next = &nodes0[190], .payload = {.id = 112, .data = (double)0.117223}}, + {.next = &nodes0[192], .payload = {.id = 40, .data = (double)40.914367}}, + {.next = &nodes0[106], .payload = {.id = 72, .data = (double)75.273525}}, + {.next = &nodes0[94], .payload = {.id = 94, .data = (double)-87.294459}}, + {.next = &nodes0[166], .payload = {.id = 62, .data = (double)11.389949}}, + {.next = &nodes0[141], .payload = {.id = 247, .data = (double)-20.842831}}, + {.next = &nodes0[45], .payload = {.id = 17, .data = (double)17.853137}}, + {.next = &nodes0[48], .payload = {.id = 225, .data = (double)16.835519}}, + {.next = &nodes0[164], .payload = {.id = 89, .data = (double)-90.576725}}, + {.next = &nodes0[167], .payload = {.id = 238, .data = (double)18.903831}}, + {.next = &nodes0[223], .payload = {.id = 33, .data = (double)94.623153}}, + {.next = &nodes0[150], .payload = {.id = 67, .data = (double)-93.579951}}, + {.next = &nodes0[0], .payload = {.id = 129, .data = (double)66.333106}}, + {.next = &nodes0[116], .payload = {.id = 54, .data = (double)29.607077}}, + {.next = &nodes0[6], .payload = {.id = 137, .data = (double)52.120433}}, + {.next = &nodes0[181], .payload = {.id = 37, .data = (double)23.70395}}, +}; + +node_t nodes1[] = { + {.next = &nodes1[234], .payload = {.id = 72, .data = (double)-34.630839}}, + {.next = &nodes1[200], .payload = {.id = 192, .data = (double)4.927374}}, + {.next = &nodes1[124], .payload = {.id = 143, .data = (double)66.146204}}, + {.next = &nodes1[134], .payload = {.id = 159, .data = (double)-97.969777}}, + {.next = &nodes1[108], .payload = {.id = 254, .data = (double)84.782209}}, + {.next = &nodes1[193], .payload = {.id = 45, .data = (double)70.68959}}, + {.next = &nodes1[105], .payload = {.id = 99, .data = (double)49.58513}}, + {.next = &nodes1[21], .payload = {.id = 114, .data = (double)54.496177}}, + {.next = &nodes1[15], .payload = {.id = 239, .data = (double)-58.442419}}, + {.next = &nodes1[41], .payload = {.id = 220, .data = (double)-70.160483}}, + {.next = &nodes1[109], .payload = {.id = 97, .data = (double)-66.442171}}, + {.next = &nodes1[8], .payload = {.id = 238, .data = (double)89.51804}}, + {.next = &nodes1[125], .payload = {.id = 59, .data = (double)-6.52197}}, + {.next = &nodes1[249], .payload = {.id = 37, .data = (double)16.815883}}, + {.next = &nodes1[167], .payload = {.id = 213, .data = (double)88.212719}}, + {.next = &nodes1[19], .payload = {.id = 240, .data = (double)-57.794961}}, + {.next = &nodes1[66], .payload = {.id = 11, .data = (double)79.441621}}, + {.next = &nodes1[224], .payload = {.id = 137, .data = (double)7.634581}}, + {.next = &nodes1[253], .payload = {.id = 28, .data = (double)38.789962}}, + {.next = &nodes1[89], .payload = {.id = 241, .data = (double)32.085627}}, + {.next = &nodes1[37], .payload = {.id = 1, .data = (double)33.515547}}, + {.next = &nodes1[170], .payload = {.id = 115, .data = (double)70.058648}}, + {.next = &nodes1[182], .payload = {.id = 170, .data = (double)-55.68072}}, + {.next = &nodes1[254], .payload = {.id = 107, .data = (double)91.634568}}, + {.next = &nodes1[148], .payload = {.id = 32, .data = (double)8.522228}}, + {.next = &nodes1[192], .payload = {.id = 148, .data = (double)22.066341}}, + {.next = &nodes1[58], .payload = {.id = 54, .data = (double)-94.195036}}, + {.next = &nodes1[147], .payload = {.id = 174, .data = (double)-5.347902}}, + {.next = &nodes1[157], .payload = {.id = 47, .data = (double)-16.195743}}, + {.next = &nodes1[247], .payload = {.id = 67, .data = (double)-72.860103}}, + {.next = &nodes1[165], .payload = {.id = 252, .data = (double)-9.193735}}, + {.next = &nodes1[18], .payload = {.id = 27, .data = (double)-53.747704}}, + {.next = &nodes1[155], .payload = {.id = 91, .data = (double)-74.755805}}, + {.next = &nodes1[243], .payload = {.id = 14, .data = (double)-48.16169}}, + {.next = &nodes1[88], .payload = {.id = 121, .data = (double)-14.324397}}, + {.next = &nodes1[121], .payload = {.id = 243, .data = (double)-65.23729}}, + {.next = &nodes1[206], .payload = {.id = 194, .data = (double)-79.894778}}, + {.next = &nodes1[139], .payload = {.id = 2, .data = (double)97.578491}}, + {.next = &nodes1[216], .payload = {.id = 81, .data = (double)99.981566}}, + {.next = &nodes1[123], .payload = {.id = 236, .data = (double)21.926182}}, + {.next = &nodes1[79], .payload = {.id = 134, .data = (double)93.094746}}, + {.next = &nodes1[146], .payload = {.id = 221, .data = (double)12.567919}}, + {.next = &nodes1[179], .payload = {.id = 83, .data = (double)30.028819}}, + {.next = &nodes1[250], .payload = {.id = 164, .data = (double)51.632931}}, + {.next = &nodes1[129], .payload = {.id = 225, .data = (double)52.888689}}, + {.next = &nodes1[151], .payload = {.id = 51, .data = (double)-55.892261}}, + {.next = &nodes1[75], .payload = {.id = 229, .data = (double)4.514507}}, + {.next = &nodes1[72], .payload = {.id = 93, .data = (double)12.793916}}, + {.next = &nodes1[181], .payload = {.id = 25, .data = (double)8.030445}}, + {.next = &nodes1[32], .payload = {.id = 90, .data = (double)-69.523531}}, + {.next = &nodes1[86], .payload = {.id = 156, .data = (double)76.063996}}, + {.next = &nodes1[169], .payload = {.id = 21, .data = (double)-84.503329}}, + {.next = &nodes1[55], .payload = {.id = 87, .data = (double)89.922347}}, + {.next = &nodes1[45], .payload = {.id = 50, .data = (double)20.650518}}, + {.next = &nodes1[156], .payload = {.id = 196, .data = (double)-54.503367}}, + {.next = &nodes1[186], .payload = {.id = 88, .data = (double)-60.127864}}, + {.next = &nodes1[218], .payload = {.id = 109, .data = (double)43.002941}}, + {.next = &nodes1[10], .payload = {.id = 96, .data = (double)53.37962}}, + {.next = &nodes1[65], .payload = {.id = 55, .data = (double)-32.774091}}, + {.next = &nodes1[60], .payload = {.id = 181, .data = (double)-49.719265}}, + {.next = &nodes1[166], .payload = {.id = 182, .data = (double)-75.868823}}, + {.next = &nodes1[153], .payload = {.id = 200, .data = (double)-45.137735}}, + {.next = &nodes1[27], .payload = {.id = 173, .data = (double)16.311117}}, + {.next = &nodes1[138], .payload = {.id = 184, .data = (double)-76.089052}}, + {.next = &nodes1[29], .payload = {.id = 66, .data = (double)28.54993}}, + {.next = &nodes1[251], .payload = {.id = 56, .data = (double)35.828377}}, + {.next = &nodes1[158], .payload = {.id = 12, .data = (double)48.731088}}, + {.next = &nodes1[80], .payload = {.id = 186, .data = (double)52.437922}}, + {.next = &nodes1[190], .payload = {.id = 161, .data = (double)-82.877408}}, + {.next = &nodes1[113], .payload = {.id = 16, .data = (double)27.532287}}, + {.next = &nodes1[207], .payload = {.id = 4, .data = (double)90.007922}}, + {.next = &nodes1[214], .payload = {.id = 63, .data = (double)-21.195949}}, + {.next = &nodes1[115], .payload = {.id = 94, .data = (double)-56.407092}}, + {.next = &nodes1[174], .payload = {.id = 168, .data = (double)58.586574}}, + {.next = &nodes1[52], .payload = {.id = 86, .data = (double)50.846641}}, + {.next = &nodes1[83], .payload = {.id = 230, .data = (double)-9.897107}}, + {.next = &nodes1[91], .payload = {.id = 141, .data = (double)-46.320892}}, + {.next = &nodes1[92], .payload = {.id = 207, .data = (double)74.543947}}, + {.next = &nodes1[239], .payload = {.id = 151, .data = (double)70.190567}}, + {.next = &nodes1[93], .payload = {.id = 135, .data = (double)-45.983521}}, + {.next = &nodes1[217], .payload = {.id = 187, .data = (double)-62.970032}}, + {.next = &nodes1[150], .payload = {.id = 203, .data = (double)39.483479}}, + {.next = &nodes1[40], .payload = {.id = 133, .data = (double)46.759061}}, + {.next = &nodes1[248], .payload = {.id = 231, .data = (double)-11.455799}}, + {.next = &nodes1[59], .payload = {.id = 180, .data = (double)-45.816715}}, + {.next = &nodes1[43], .payload = {.id = 163, .data = (double)-2.284431}}, + {.next = &nodes1[152], .payload = {.id = 157, .data = (double)40.23675}}, + {.next = &nodes1[97], .payload = {.id = 129, .data = (double)27.117021}}, + {.next = &nodes1[127], .payload = {.id = 122, .data = (double)-25.885825}}, + {.next = &nodes1[35], .payload = {.id = 242, .data = (double)-68.588581}}, + {.next = &nodes1[61], .payload = {.id = 199, .data = (double)6.827018}}, + {.next = &nodes1[2], .payload = {.id = 142, .data = (double)70.342632}}, + {.next = &nodes1[203], .payload = {.id = 208, .data = (double)14.812844}}, + {.next = &nodes1[17], .payload = {.id = 136, .data = (double)61.639844}}, + {.next = &nodes1[221], .payload = {.id = 19, .data = (double)25.349687}}, + {.next = &nodes1[71], .payload = {.id = 62, .data = (double)-94.60671}}, + {.next = &nodes1[46], .payload = {.id = 228, .data = (double)-54.862573}}, + {.next = &nodes1[163], .payload = {.id = 130, .data = (double)65.741462}}, + {.next = &nodes1[117], .payload = {.id = 75, .data = (double)50.401965}}, + {.next = &nodes1[135], .payload = {.id = 249, .data = (double)-53.704753}}, + {.next = &nodes1[50], .payload = {.id = 155, .data = (double)-31.932231}}, + {.next = &nodes1[237], .payload = {.id = 245, .data = (double)-99.464855}}, + {.next = &nodes1[238], .payload = {.id = 190, .data = (double)44.917}}, + {.next = &nodes1[110], .payload = {.id = 34, .data = (double)-58.633122}}, + {.next = &nodes1[73], .payload = {.id = 167, .data = (double)-1.835733}}, + {.next = &nodes1[255], .payload = {.id = 100, .data = (double)-77.093426}}, + {.next = &nodes1[199], .payload = {.id = 43, .data = (double)-29.648239}}, + {.next = &nodes1[26], .payload = {.id = 53, .data = (double)-12.832805}}, + {.next = NULL, .payload = {.id = 255, .data = (double)57.565605}}, + {.next = &nodes1[6], .payload = {.id = 98, .data = (double)21.449499}}, + {.next = &nodes1[245], .payload = {.id = 35, .data = (double)-15.971296}}, + {.next = &nodes1[171], .payload = {.id = 8, .data = (double)0.955633}}, + {.next = &nodes1[202], .payload = {.id = 218, .data = (double)25.889141}}, + {.next = &nodes1[244], .payload = {.id = 17, .data = (double)53.162737}}, + {.next = &nodes1[209], .payload = {.id = 146, .data = (double)-51.227312}}, + {.next = &nodes1[57], .payload = {.id = 95, .data = (double)39.892994}}, + {.next = &nodes1[64], .payload = {.id = 65, .data = (double)-94.579591}}, + {.next = &nodes1[229], .payload = {.id = 76, .data = (double)66.384857}}, + {.next = &nodes1[160], .payload = {.id = 117, .data = (double)-75.788987}}, + {.next = &nodes1[48], .payload = {.id = 24, .data = (double)-36.058086}}, + {.next = &nodes1[53], .payload = {.id = 49, .data = (double)9.226462}}, + {.next = &nodes1[101], .payload = {.id = 244, .data = (double)-84.987026}}, + {.next = &nodes1[194], .payload = {.id = 70, .data = (double)-24.179227}}, + {.next = &nodes1[11], .payload = {.id = 237, .data = (double)48.017861}}, + {.next = &nodes1[236], .payload = {.id = 144, .data = (double)-82.66742}}, + {.next = &nodes1[142], .payload = {.id = 60, .data = (double)-74.474441}}, + {.next = &nodes1[102], .payload = {.id = 189, .data = (double)-3.160283}}, + {.next = &nodes1[145], .payload = {.id = 123, .data = (double)1.192158}}, + {.next = &nodes1[23], .payload = {.id = 106, .data = (double)35.469457}}, + {.next = &nodes1[164], .payload = {.id = 226, .data = (double)21.26353}}, + {.next = &nodes1[98], .payload = {.id = 74, .data = (double)-24.174757}}, + {.next = &nodes1[183], .payload = {.id = 215, .data = (double)64.423129}}, + {.next = &nodes1[141], .payload = {.id = 39, .data = (double)71.346406}}, + {.next = &nodes1[232], .payload = {.id = 30, .data = (double)-87.15423}}, + {.next = &nodes1[68], .payload = {.id = 160, .data = (double)89.612516}}, + {.next = &nodes1[136], .payload = {.id = 250, .data = (double)41.391166}}, + {.next = &nodes1[30], .payload = {.id = 251, .data = (double)40.597512}}, + {.next = &nodes1[112], .payload = {.id = 217, .data = (double)-85.183566}}, + {.next = &nodes1[67], .payload = {.id = 185, .data = (double)7.172793}}, + {.next = &nodes1[70], .payload = {.id = 3, .data = (double)19.090464}}, + {.next = &nodes1[168], .payload = {.id = 79, .data = (double)-96.123343}}, + {.next = &nodes1[180], .payload = {.id = 40, .data = (double)53.118915}}, + {.next = &nodes1[95], .payload = {.id = 61, .data = (double)24.451392}}, + {.next = &nodes1[111], .payload = {.id = 7, .data = (double)43.854792}}, + {.next = &nodes1[99], .payload = {.id = 248, .data = (double)-41.748142}}, + {.next = &nodes1[189], .payload = {.id = 124, .data = (double)-31.753765}}, + {.next = &nodes1[176], .payload = {.id = 222, .data = (double)-39.232898}}, + {.next = &nodes1[230], .payload = {.id = 175, .data = (double)6.184386}}, + {.next = &nodes1[103], .payload = {.id = 33, .data = (double)-16.845153}}, + {.next = &nodes1[201], .payload = {.id = 205, .data = (double)73.692239}}, + {.next = &nodes1[149], .payload = {.id = 204, .data = (double)-74.744101}}, + {.next = &nodes1[107], .payload = {.id = 52, .data = (double)-56.115673}}, + {.next = &nodes1[3], .payload = {.id = 158, .data = (double)-44.746285}}, + {.next = &nodes1[241], .payload = {.id = 201, .data = (double)94.858986}}, + {.next = &nodes1[225], .payload = {.id = 127, .data = (double)-78.892226}}, + {.next = &nodes1[47], .payload = {.id = 92, .data = (double)33.891769}}, + {.next = &nodes1[187], .payload = {.id = 197, .data = (double)-64.111691}}, + {.next = &nodes1[120], .payload = {.id = 48, .data = (double)49.503134}}, + {.next = &nodes1[33], .payload = {.id = 13, .data = (double)-5.065113}}, + {.next = &nodes1[228], .payload = {.id = 178, .data = (double)-33.841741}}, + {.next = &nodes1[231], .payload = {.id = 118, .data = (double)96.76887}}, + {.next = &nodes1[44], .payload = {.id = 224, .data = (double)-76.309688}}, + {.next = &nodes1[20], .payload = {.id = 0, .data = (double)60.28332}}, + {.next = &nodes1[197], .payload = {.id = 131, .data = (double)41.461729}}, + {.next = &nodes1[96], .payload = {.id = 227, .data = (double)58.148166}}, + {.next = &nodes1[4], .payload = {.id = 253, .data = (double)37.476984}}, + {.next = &nodes1[63], .payload = {.id = 183, .data = (double)-61.483141}}, + {.next = &nodes1[131], .payload = {.id = 214, .data = (double)-4.454163}}, + {.next = &nodes1[38], .payload = {.id = 80, .data = (double)7.88381}}, + {.next = &nodes1[212], .payload = {.id = 22, .data = (double)-42.85437}}, + {.next = &nodes1[118], .payload = {.id = 116, .data = (double)20.082323}}, + {.next = &nodes1[219], .payload = {.id = 9, .data = (double)66.113834}}, + {.next = &nodes1[76], .payload = {.id = 140, .data = (double)46.205243}}, + {.next = &nodes1[227], .payload = {.id = 102, .data = (double)92.944155}}, + {.next = &nodes1[22], .payload = {.id = 169, .data = (double)-81.38933}}, + {.next = &nodes1[235], .payload = {.id = 234, .data = (double)-38.923951}}, + {.next = &nodes1[161], .payload = {.id = 223, .data = (double)98.783625}}, + {.next = &nodes1[159], .payload = {.id = 177, .data = (double)49.187087}}, + {.next = &nodes1[128], .payload = {.id = 105, .data = (double)-37.608551}}, + {.next = &nodes1[184], .payload = {.id = 84, .data = (double)56.24661}}, + {.next = &nodes1[242], .payload = {.id = 41, .data = (double)-23.923794}}, + {.next = &nodes1[31], .payload = {.id = 26, .data = (double)-72.325188}}, + {.next = &nodes1[210], .payload = {.id = 171, .data = (double)38.357431}}, + {.next = &nodes1[137], .payload = {.id = 216, .data = (double)-19.858512}}, + {.next = &nodes1[74], .payload = {.id = 85, .data = (double)30.350931}}, + {.next = &nodes1[178], .payload = {.id = 104, .data = (double)-94.864315}}, + {.next = &nodes1[49], .payload = {.id = 89, .data = (double)-95.923997}}, + {.next = &nodes1[90], .payload = {.id = 198, .data = (double)-97.170327}}, + {.next = &nodes1[14], .payload = {.id = 212, .data = (double)-89.724657}}, + {.next = &nodes1[223], .payload = {.id = 125, .data = (double)69.915125}}, + {.next = &nodes1[85], .payload = {.id = 162, .data = (double)44.014933}}, + {.next = &nodes1[233], .payload = {.id = 111, .data = (double)38.122883}}, + {.next = &nodes1[208], .payload = {.id = 149, .data = (double)-24.202139}}, + {.next = &nodes1[28], .payload = {.id = 46, .data = (double)90.686068}}, + {.next = &nodes1[0], .payload = {.id = 71, .data = (double)-57.667943}}, + {.next = &nodes1[7], .payload = {.id = 113, .data = (double)-79.619739}}, + {.next = &nodes1[104], .payload = {.id = 166, .data = (double)29.18058}}, + {.next = &nodes1[82], .payload = {.id = 132, .data = (double)-12.902571}}, + {.next = &nodes1[34], .payload = {.id = 120, .data = (double)-30.559247}}, + {.next = &nodes1[5], .payload = {.id = 44, .data = (double)50.695025}}, + {.next = &nodes1[36], .payload = {.id = 193, .data = (double)-43.400259}}, + {.next = &nodes1[77], .payload = {.id = 206, .data = (double)-1.824261}}, + {.next = &nodes1[9], .payload = {.id = 219, .data = (double)-89.278185}}, + {.next = &nodes1[205], .payload = {.id = 209, .data = (double)-6.120611}}, + {.next = &nodes1[144], .payload = {.id = 247, .data = (double)18.762239}}, + {.next = &nodes1[246], .payload = {.id = 210, .data = (double)-11.90624}}, + {.next = &nodes1[54], .payload = {.id = 195, .data = (double)-61.176484}}, + {.next = &nodes1[213], .payload = {.id = 5, .data = (double)78.285185}}, + {.next = &nodes1[78], .payload = {.id = 150, .data = (double)-94.26}}, + {.next = &nodes1[25], .payload = {.id = 147, .data = (double)-7.058307}}, + {.next = &nodes1[62], .payload = {.id = 172, .data = (double)-38.758794}}, + {.next = &nodes1[12], .payload = {.id = 58, .data = (double)-66.991054}}, + {.next = &nodes1[119], .payload = {.id = 23, .data = (double)-45.656979}}, + {.next = &nodes1[143], .payload = {.id = 6, .data = (double)22.530465}}, + {.next = &nodes1[116], .payload = {.id = 64, .data = (double)12.878397}}, + {.next = &nodes1[100], .payload = {.id = 154, .data = (double)59.566471}}, + {.next = &nodes1[42], .payload = {.id = 82, .data = (double)-30.007931}}, + {.next = &nodes1[126], .payload = {.id = 188, .data = (double)-56.723072}}, + {.next = &nodes1[191], .payload = {.id = 110, .data = (double)-84.800704}}, + {.next = &nodes1[16], .payload = {.id = 10, .data = (double)9.57439}}, + {.next = &nodes1[215], .payload = {.id = 153, .data = (double)-57.57603}}, + {.next = &nodes1[51], .payload = {.id = 20, .data = (double)-45.080511}}, + {.next = &nodes1[175], .payload = {.id = 233, .data = (double)98.006252}}, + {.next = &nodes1[154], .payload = {.id = 126, .data = (double)64.466184}}, + {.next = &nodes1[252], .payload = {.id = 138, .data = (double)-3.300499}}, + {.next = &nodes1[87], .payload = {.id = 128, .data = (double)92.157513}}, + {.next = &nodes1[122], .payload = {.id = 69, .data = (double)-89.943073}}, + {.next = &nodes1[185], .payload = {.id = 103, .data = (double)-78.38025}}, + {.next = &nodes1[84], .payload = {.id = 179, .data = (double)40.570988}}, + {.next = &nodes1[240], .payload = {.id = 77, .data = (double)-49.545694}}, + {.next = &nodes1[177], .payload = {.id = 176, .data = (double)-14.899237}}, + {.next = &nodes1[198], .payload = {.id = 119, .data = (double)56.527069}}, + {.next = &nodes1[24], .payload = {.id = 31, .data = (double)-18.480126}}, + {.next = &nodes1[195], .payload = {.id = 112, .data = (double)25.448479}}, + {.next = &nodes1[130], .payload = {.id = 73, .data = (double)52.245942}}, + {.next = &nodes1[39], .payload = {.id = 235, .data = (double)24.205464}}, + {.next = &nodes1[114], .payload = {.id = 145, .data = (double)76.326237}}, + {.next = &nodes1[204], .payload = {.id = 246, .data = (double)-9.899259}}, + {.next = &nodes1[1], .payload = {.id = 191, .data = (double)95.321405}}, + {.next = &nodes1[220], .payload = {.id = 152, .data = (double)-63.632029}}, + {.next = &nodes1[140], .payload = {.id = 78, .data = (double)-83.618753}}, + {.next = &nodes1[81], .payload = {.id = 202, .data = (double)10.671793}}, + {.next = &nodes1[106], .payload = {.id = 42, .data = (double)-98.820783}}, + {.next = &nodes1[69], .payload = {.id = 15, .data = (double)-50.552052}}, + {.next = &nodes1[94], .payload = {.id = 18, .data = (double)4.259963}}, + {.next = &nodes1[13], .payload = {.id = 36, .data = (double)80.967696}}, + {.next = &nodes1[188], .payload = {.id = 211, .data = (double)-63.127266}}, + {.next = &nodes1[226], .payload = {.id = 68, .data = (double)-7.660311}}, + {.next = &nodes1[222], .payload = {.id = 232, .data = (double)72.033333}}, + {.next = &nodes1[132], .payload = {.id = 38, .data = (double)39.104597}}, + {.next = &nodes1[196], .payload = {.id = 165, .data = (double)38.121868}}, + {.next = &nodes1[211], .payload = {.id = 57, .data = (double)-19.136666}}, + {.next = &nodes1[172], .payload = {.id = 139, .data = (double)-12.885101}}, + {.next = &nodes1[133], .payload = {.id = 29, .data = (double)41.283828}}, + {.next = &nodes1[56], .payload = {.id = 108, .data = (double)-20.669112}}, + {.next = &nodes1[173], .payload = {.id = 101, .data = (double)63.860235}}, +}; + +node_t nodes2[] = { + {.next = &nodes2[54], .payload = {.id = 50, .data = (double)-93.327094}}, + {.next = &nodes2[254], .payload = {.id = 0, .data = (double)-0.46655}}, + {.next = &nodes2[60], .payload = {.id = 119, .data = (double)38.056133}}, + {.next = &nodes2[84], .payload = {.id = 37, .data = (double)-53.976322}}, + {.next = &nodes2[18], .payload = {.id = 236, .data = (double)-3.562121}}, + {.next = &nodes2[97], .payload = {.id = 141, .data = (double)-58.958885}}, + {.next = &nodes2[182], .payload = {.id = 73, .data = (double)35.264745}}, + {.next = &nodes2[110], .payload = {.id = 228, .data = (double)-15.412629}}, + {.next = NULL, .payload = {.id = 255, .data = (double)84.307504}}, + {.next = &nodes2[114], .payload = {.id = 185, .data = (double)79.853353}}, + {.next = &nodes2[201], .payload = {.id = 71, .data = (double)50.830299}}, + {.next = &nodes2[47], .payload = {.id = 208, .data = (double)45.922502}}, + {.next = &nodes2[71], .payload = {.id = 245, .data = (double)53.486506}}, + {.next = &nodes2[247], .payload = {.id = 16, .data = (double)-8.632837}}, + {.next = &nodes2[21], .payload = {.id = 214, .data = (double)-5.146423}}, + {.next = &nodes2[86], .payload = {.id = 177, .data = (double)28.668137}}, + {.next = &nodes2[62], .payload = {.id = 139, .data = (double)97.764181}}, + {.next = &nodes2[246], .payload = {.id = 250, .data = (double)31.566246}}, + {.next = &nodes2[103], .payload = {.id = 237, .data = (double)69.45497}}, + {.next = &nodes2[69], .payload = {.id = 206, .data = (double)65.483845}}, + {.next = &nodes2[191], .payload = {.id = 100, .data = (double)-90.930638}}, + {.next = &nodes2[211], .payload = {.id = 215, .data = (double)-81.755042}}, + {.next = &nodes2[184], .payload = {.id = 34, .data = (double)66.56778}}, + {.next = &nodes2[154], .payload = {.id = 204, .data = (double)77.618204}}, + {.next = &nodes2[25], .payload = {.id = 219, .data = (double)-25.470628}}, + {.next = &nodes2[143], .payload = {.id = 220, .data = (double)-73.976909}}, + {.next = &nodes2[117], .payload = {.id = 31, .data = (double)94.720563}}, + {.next = &nodes2[142], .payload = {.id = 247, .data = (double)34.995342}}, + {.next = &nodes2[32], .payload = {.id = 67, .data = (double)74.079392}}, + {.next = &nodes2[148], .payload = {.id = 91, .data = (double)88.633827}}, + {.next = &nodes2[188], .payload = {.id = 253, .data = (double)-45.345922}}, + {.next = &nodes2[129], .payload = {.id = 48, .data = (double)-92.115485}}, + {.next = &nodes2[217], .payload = {.id = 68, .data = (double)60.846508}}, + {.next = &nodes2[179], .payload = {.id = 187, .data = (double)-70.333235}}, + {.next = &nodes2[145], .payload = {.id = 26, .data = (double)66.007512}}, + {.next = &nodes2[210], .payload = {.id = 105, .data = (double)7.509321}}, + {.next = &nodes2[2], .payload = {.id = 118, .data = (double)-44.051972}}, + {.next = &nodes2[144], .payload = {.id = 61, .data = (double)-45.49453}}, + {.next = &nodes2[81], .payload = {.id = 242, .data = (double)-54.768181}}, + {.next = &nodes2[139], .payload = {.id = 166, .data = (double)-87.288392}}, + {.next = &nodes2[108], .payload = {.id = 114, .data = (double)30.984379}}, + {.next = &nodes2[150], .payload = {.id = 42, .data = (double)51.115465}}, + {.next = &nodes2[43], .payload = {.id = 175, .data = (double)31.780615}}, + {.next = &nodes2[15], .payload = {.id = 176, .data = (double)-39.673934}}, + {.next = &nodes2[94], .payload = {.id = 137, .data = (double)-89.884298}}, + {.next = &nodes2[13], .payload = {.id = 15, .data = (double)38.062702}}, + {.next = &nodes2[57], .payload = {.id = 2, .data = (double)-53.562311}}, + {.next = &nodes2[156], .payload = {.id = 209, .data = (double)-37.49033}}, + {.next = &nodes2[178], .payload = {.id = 126, .data = (double)80.339242}}, + {.next = &nodes2[28], .payload = {.id = 66, .data = (double)-40.97171}}, + {.next = &nodes2[231], .payload = {.id = 183, .data = (double)42.480263}}, + {.next = &nodes2[167], .payload = {.id = 240, .data = (double)-77.022937}}, + {.next = &nodes2[65], .payload = {.id = 226, .data = (double)74.721474}}, + {.next = &nodes2[185], .payload = {.id = 53, .data = (double)81.925562}}, + {.next = &nodes2[187], .payload = {.id = 51, .data = (double)-27.027753}}, + {.next = &nodes2[243], .payload = {.id = 6, .data = (double)79.781706}}, + {.next = &nodes2[177], .payload = {.id = 202, .data = (double)73.098463}}, + {.next = &nodes2[164], .payload = {.id = 3, .data = (double)27.580926}}, + {.next = &nodes2[10], .payload = {.id = 70, .data = (double)-84.940128}}, + {.next = &nodes2[134], .payload = {.id = 149, .data = (double)19.196327}}, + {.next = &nodes2[118], .payload = {.id = 120, .data = (double)-56.546063}}, + {.next = &nodes2[135], .payload = {.id = 84, .data = (double)-47.567718}}, + {.next = &nodes2[5], .payload = {.id = 140, .data = (double)57.39562}}, + {.next = &nodes2[116], .payload = {.id = 24, .data = (double)39.855816}}, + {.next = &nodes2[241], .payload = {.id = 190, .data = (double)17.072938}}, + {.next = &nodes2[7], .payload = {.id = 227, .data = (double)88.225974}}, + {.next = &nodes2[186], .payload = {.id = 76, .data = (double)69.148896}}, + {.next = &nodes2[132], .payload = {.id = 129, .data = (double)-44.823712}}, + {.next = &nodes2[223], .payload = {.id = 233, .data = (double)-79.279887}}, + {.next = &nodes2[11], .payload = {.id = 207, .data = (double)-20.253963}}, + {.next = &nodes2[101], .payload = {.id = 194, .data = (double)-41.020451}}, + {.next = &nodes2[27], .payload = {.id = 246, .data = (double)24.344761}}, + {.next = &nodes2[31], .payload = {.id = 47, .data = (double)25.491622}}, + {.next = &nodes2[238], .payload = {.id = 95, .data = (double)27.080784}}, + {.next = &nodes2[146], .payload = {.id = 164, .data = (double)-15.807889}}, + {.next = &nodes2[20], .payload = {.id = 99, .data = (double)-76.664813}}, + {.next = &nodes2[48], .payload = {.id = 125, .data = (double)-26.533008}}, + {.next = &nodes2[119], .payload = {.id = 224, .data = (double)34.002653}}, + {.next = &nodes2[115], .payload = {.id = 159, .data = (double)57.686307}}, + {.next = &nodes2[183], .payload = {.id = 64, .data = (double)88.837563}}, + {.next = &nodes2[253], .payload = {.id = 45, .data = (double)-72.644152}}, + {.next = &nodes2[133], .payload = {.id = 243, .data = (double)-14.177518}}, + {.next = &nodes2[66], .payload = {.id = 75, .data = (double)-20.517701}}, + {.next = &nodes2[138], .payload = {.id = 231, .data = (double)-42.474118}}, + {.next = &nodes2[224], .payload = {.id = 38, .data = (double)60.386392}}, + {.next = &nodes2[59], .payload = {.id = 148, .data = (double)57.728751}}, + {.next = &nodes2[255], .payload = {.id = 178, .data = (double)-93.769872}}, + {.next = &nodes2[37], .payload = {.id = 60, .data = (double)0.358952}}, + {.next = &nodes2[109], .payload = {.id = 8, .data = (double)-42.473667}}, + {.next = &nodes2[199], .payload = {.id = 199, .data = (double)30.942592}}, + {.next = &nodes2[100], .payload = {.id = 211, .data = (double)-49.022041}}, + {.next = &nodes2[77], .payload = {.id = 223, .data = (double)12.336676}}, + {.next = &nodes2[153], .payload = {.id = 156, .data = (double)73.289578}}, + {.next = &nodes2[41], .payload = {.id = 41, .data = (double)-49.87464}}, + {.next = &nodes2[16], .payload = {.id = 138, .data = (double)-33.298169}}, + {.next = &nodes2[123], .payload = {.id = 81, .data = (double)-75.282253}}, + {.next = &nodes2[213], .payload = {.id = 123, .data = (double)-27.462792}}, + {.next = &nodes2[170], .payload = {.id = 142, .data = (double)65.963567}}, + {.next = &nodes2[4], .payload = {.id = 235, .data = (double)-69.053965}}, + {.next = &nodes2[172], .payload = {.id = 57, .data = (double)57.302562}}, + {.next = &nodes2[197], .payload = {.id = 212, .data = (double)90.718504}}, + {.next = &nodes2[141], .payload = {.id = 195, .data = (double)1.110215}}, + {.next = &nodes2[56], .payload = {.id = 201, .data = (double)10.267046}}, + {.next = &nodes2[208], .payload = {.id = 238, .data = (double)-29.977201}}, + {.next = &nodes2[87], .payload = {.id = 59, .data = (double)-26.828494}}, + {.next = &nodes2[79], .payload = {.id = 63, .data = (double)82.809791}}, + {.next = &nodes2[244], .payload = {.id = 161, .data = (double)-96.843783}}, + {.next = &nodes2[75], .payload = {.id = 98, .data = (double)29.847889}}, + {.next = &nodes2[236], .payload = {.id = 115, .data = (double)66.738617}}, + {.next = &nodes2[166], .payload = {.id = 9, .data = (double)9.319628}}, + {.next = &nodes2[181], .payload = {.id = 229, .data = (double)83.168734}}, + {.next = &nodes2[216], .payload = {.id = 112, .data = (double)45.31983}}, + {.next = &nodes2[42], .payload = {.id = 174, .data = (double)81.750338}}, + {.next = &nodes2[196], .payload = {.id = 133, .data = (double)-81.665315}}, + {.next = &nodes2[33], .payload = {.id = 186, .data = (double)-35.577636}}, + {.next = &nodes2[106], .payload = {.id = 160, .data = (double)17.770584}}, + {.next = &nodes2[34], .payload = {.id = 25, .data = (double)-95.61208}}, + {.next = &nodes2[175], .payload = {.id = 32, .data = (double)82.123391}}, + {.next = &nodes2[125], .payload = {.id = 121, .data = (double)-11.060828}}, + {.next = &nodes2[52], .payload = {.id = 225, .data = (double)-17.838273}}, + {.next = &nodes2[151], .payload = {.id = 180, .data = (double)69.459709}}, + {.next = &nodes2[17], .payload = {.id = 249, .data = (double)21.798983}}, + {.next = &nodes2[229], .payload = {.id = 197, .data = (double)58.619219}}, + {.next = &nodes2[230], .payload = {.id = 82, .data = (double)-26.282868}}, + {.next = &nodes2[35], .payload = {.id = 104, .data = (double)-53.039994}}, + {.next = &nodes2[96], .payload = {.id = 122, .data = (double)-52.777472}}, + {.next = &nodes2[233], .payload = {.id = 93, .data = (double)22.016439}}, + {.next = &nodes2[219], .payload = {.id = 171, .data = (double)-55.690049}}, + {.next = &nodes2[169], .payload = {.id = 89, .data = (double)-5.704626}}, + {.next = &nodes2[0], .payload = {.id = 49, .data = (double)57.722097}}, + {.next = &nodes2[113], .payload = {.id = 132, .data = (double)64.838216}}, + {.next = &nodes2[212], .payload = {.id = 154, .data = (double)59.702765}}, + {.next = &nodes2[206], .payload = {.id = 130, .data = (double)93.641375}}, + {.next = &nodes2[12], .payload = {.id = 244, .data = (double)12.19314}}, + {.next = &nodes2[198], .payload = {.id = 150, .data = (double)-44.545031}}, + {.next = &nodes2[137], .payload = {.id = 85, .data = (double)-23.7949}}, + {.next = &nodes2[222], .payload = {.id = 192, .data = (double)-23.81912}}, + {.next = &nodes2[235], .payload = {.id = 86, .data = (double)27.709854}}, + {.next = &nodes2[68], .payload = {.id = 232, .data = (double)-37.51022}}, + {.next = &nodes2[249], .payload = {.id = 167, .data = (double)-10.344957}}, + {.next = &nodes2[24], .payload = {.id = 218, .data = (double)48.917794}}, + {.next = &nodes2[122], .payload = {.id = 196, .data = (double)-13.960135}}, + {.next = &nodes2[121], .payload = {.id = 248, .data = (double)11.347951}}, + {.next = &nodes2[252], .payload = {.id = 221, .data = (double)-88.003804}}, + {.next = &nodes2[105], .payload = {.id = 62, .data = (double)-67.091116}}, + {.next = &nodes2[202], .payload = {.id = 27, .data = (double)-20.838852}}, + {.next = &nodes2[39], .payload = {.id = 165, .data = (double)-77.270139}}, + {.next = &nodes2[242], .payload = {.id = 22, .data = (double)-28.208168}}, + {.next = &nodes2[126], .payload = {.id = 92, .data = (double)-34.398744}}, + {.next = &nodes2[74], .payload = {.id = 163, .data = (double)-74.648291}}, + {.next = &nodes2[176], .payload = {.id = 43, .data = (double)53.494155}}, + {.next = &nodes2[155], .payload = {.id = 181, .data = (double)-14.745276}}, + {.next = &nodes2[55], .payload = {.id = 5, .data = (double)33.368143}}, + {.next = &nodes2[221], .payload = {.id = 157, .data = (double)-73.639354}}, + {.next = &nodes2[19], .payload = {.id = 205, .data = (double)-17.237286}}, + {.next = &nodes2[50], .payload = {.id = 182, .data = (double)-78.407634}}, + {.next = &nodes2[90], .payload = {.id = 210, .data = (double)-37.495286}}, + {.next = &nodes2[124], .payload = {.id = 103, .data = (double)-76.775904}}, + {.next = &nodes2[160], .payload = {.id = 146, .data = (double)-53.400264}}, + {.next = &nodes2[203], .payload = {.id = 109, .data = (double)39.296798}}, + {.next = &nodes2[85], .payload = {.id = 147, .data = (double)54.873716}}, + {.next = &nodes2[95], .payload = {.id = 80, .data = (double)-47.108284}}, + {.next = &nodes2[218], .payload = {.id = 19, .data = (double)70.667092}}, + {.next = &nodes2[36], .payload = {.id = 117, .data = (double)87.810613}}, + {.next = &nodes2[152], .payload = {.id = 4, .data = (double)-8.0859}}, + {.next = &nodes2[111], .payload = {.id = 111, .data = (double)17.468069}}, + {.next = &nodes2[193], .payload = {.id = 10, .data = (double)-85.22762}}, + {.next = &nodes2[38], .payload = {.id = 241, .data = (double)-44.286358}}, + {.next = &nodes2[162], .payload = {.id = 18, .data = (double)99.874713}}, + {.next = &nodes2[29], .payload = {.id = 90, .data = (double)23.909373}}, + {.next = &nodes2[250], .payload = {.id = 143, .data = (double)10.841558}}, + {.next = &nodes2[67], .payload = {.id = 128, .data = (double)-87.889982}}, + {.next = &nodes2[104], .payload = {.id = 58, .data = (double)75.292119}}, + {.next = &nodes2[44], .payload = {.id = 136, .data = (double)94.218662}}, + {.next = &nodes2[107], .payload = {.id = 97, .data = (double)40.215433}}, + {.next = &nodes2[22], .payload = {.id = 33, .data = (double)49.034431}}, + {.next = &nodes2[80], .payload = {.id = 44, .data = (double)36.171019}}, + {.next = &nodes2[23], .payload = {.id = 203, .data = (double)-13.986012}}, + {.next = &nodes2[171], .payload = {.id = 127, .data = (double)28.965362}}, + {.next = &nodes2[245], .payload = {.id = 188, .data = (double)-74.761682}}, + {.next = &nodes2[26], .payload = {.id = 30, .data = (double)55.662323}}, + {.next = &nodes2[83], .payload = {.id = 230, .data = (double)-89.710784}}, + {.next = &nodes2[82], .payload = {.id = 74, .data = (double)34.881246}}, + {.next = &nodes2[49], .payload = {.id = 65, .data = (double)93.476815}}, + {.next = &nodes2[251], .payload = {.id = 35, .data = (double)80.586984}}, + {.next = &nodes2[239], .payload = {.id = 54, .data = (double)-34.656175}}, + {.next = &nodes2[194], .payload = {.id = 77, .data = (double)11.462524}}, + {.next = &nodes2[53], .payload = {.id = 52, .data = (double)-73.717639}}, + {.next = &nodes2[8], .payload = {.id = 254, .data = (double)52.481904}}, + {.next = &nodes2[45], .payload = {.id = 14, .data = (double)92.405815}}, + {.next = &nodes2[131], .payload = {.id = 153, .data = (double)8.043091}}, + {.next = &nodes2[248], .payload = {.id = 101, .data = (double)-92.557574}}, + {.next = &nodes2[99], .payload = {.id = 56, .data = (double)-59.841041}}, + {.next = &nodes2[220], .payload = {.id = 11, .data = (double)89.047127}}, + {.next = &nodes2[232], .payload = {.id = 78, .data = (double)-81.939425}}, + {.next = &nodes2[127], .payload = {.id = 170, .data = (double)-9.598916}}, + {.next = &nodes2[240], .payload = {.id = 134, .data = (double)-57.578837}}, + {.next = &nodes2[14], .payload = {.id = 213, .data = (double)37.364207}}, + {.next = &nodes2[227], .payload = {.id = 151, .data = (double)96.805626}}, + {.next = &nodes2[102], .payload = {.id = 200, .data = (double)75.541243}}, + {.next = &nodes2[112], .payload = {.id = 173, .data = (double)45.448599}}, + {.next = &nodes2[6], .payload = {.id = 72, .data = (double)-54.877061}}, + {.next = &nodes2[205], .payload = {.id = 28, .data = (double)-98.380407}}, + {.next = &nodes2[165], .payload = {.id = 110, .data = (double)8.038499}}, + {.next = &nodes2[128], .payload = {.id = 88, .data = (double)34.967311}}, + {.next = &nodes2[180], .payload = {.id = 29, .data = (double)73.01348}}, + {.next = &nodes2[130], .payload = {.id = 131, .data = (double)89.802158}}, + {.next = &nodes2[30], .payload = {.id = 252, .data = (double)-94.209364}}, + {.next = &nodes2[51], .payload = {.id = 239, .data = (double)11.253095}}, + {.next = &nodes2[140], .payload = {.id = 217, .data = (double)-13.624696}}, + {.next = &nodes2[237], .payload = {.id = 106, .data = (double)-22.270834}}, + {.next = &nodes2[209], .payload = {.id = 216, .data = (double)-82.927129}}, + {.next = &nodes2[92], .payload = {.id = 155, .data = (double)-78.01473}}, + {.next = &nodes2[76], .payload = {.id = 124, .data = (double)96.185544}}, + {.next = &nodes2[159], .payload = {.id = 108, .data = (double)89.876154}}, + {.next = &nodes2[195], .payload = {.id = 169, .data = (double)18.733204}}, + {.next = &nodes2[40], .payload = {.id = 113, .data = (double)77.082757}}, + {.next = &nodes2[58], .payload = {.id = 69, .data = (double)-6.333722}}, + {.next = &nodes2[226], .payload = {.id = 20, .data = (double)-78.669347}}, + {.next = &nodes2[200], .payload = {.id = 172, .data = (double)23.021367}}, + {.next = &nodes2[225], .payload = {.id = 12, .data = (double)97.530339}}, + {.next = &nodes2[78], .payload = {.id = 158, .data = (double)-28.351544}}, + {.next = &nodes2[70], .payload = {.id = 193, .data = (double)19.478371}}, + {.next = &nodes2[98], .payload = {.id = 234, .data = (double)1.482509}}, + {.next = &nodes2[234], .payload = {.id = 39, .data = (double)-56.199092}}, + {.next = &nodes2[189], .payload = {.id = 13, .data = (double)-40.16915}}, + {.next = &nodes2[147], .payload = {.id = 21, .data = (double)-23.72714}}, + {.next = &nodes2[190], .payload = {.id = 152, .data = (double)97.505461}}, + {.next = &nodes2[158], .payload = {.id = 145, .data = (double)62.610596}}, + {.next = &nodes2[89], .payload = {.id = 198, .data = (double)-77.117186}}, + {.next = &nodes2[61], .payload = {.id = 83, .data = (double)49.802321}}, + {.next = &nodes2[9], .payload = {.id = 184, .data = (double)-11.287534}}, + {.next = &nodes2[161], .payload = {.id = 79, .data = (double)-21.085088}}, + {.next = &nodes2[73], .payload = {.id = 94, .data = (double)29.530476}}, + {.next = &nodes2[93], .payload = {.id = 40, .data = (double)-61.973602}}, + {.next = &nodes2[204], .payload = {.id = 87, .data = (double)-25.705272}}, + {.next = &nodes2[163], .payload = {.id = 116, .data = (double)23.130443}}, + {.next = &nodes2[214], .payload = {.id = 107, .data = (double)-25.797697}}, + {.next = &nodes2[174], .payload = {.id = 96, .data = (double)-7.146493}}, + {.next = &nodes2[192], .payload = {.id = 55, .data = (double)-16.899381}}, + {.next = &nodes2[173], .payload = {.id = 135, .data = (double)27.898584}}, + {.next = &nodes2[136], .payload = {.id = 191, .data = (double)42.430559}}, + {.next = &nodes2[63], .payload = {.id = 23, .data = (double)-40.825522}}, + {.next = &nodes2[88], .payload = {.id = 7, .data = (double)-6.949349}}, + {.next = &nodes2[149], .payload = {.id = 162, .data = (double)-46.926498}}, + {.next = &nodes2[64], .payload = {.id = 189, .data = (double)24.863499}}, + {.next = &nodes2[207], .payload = {.id = 251, .data = (double)38.694238}}, + {.next = &nodes2[168], .payload = {.id = 17, .data = (double)-39.575666}}, + {.next = &nodes2[157], .payload = {.id = 102, .data = (double)99.185475}}, + {.next = &nodes2[215], .payload = {.id = 168, .data = (double)-27.592205}}, + {.next = &nodes2[228], .payload = {.id = 144, .data = (double)17.276617}}, + {.next = &nodes2[3], .payload = {.id = 36, .data = (double)55.148196}}, + {.next = &nodes2[91], .payload = {.id = 222, .data = (double)91.324925}}, + {.next = &nodes2[72], .payload = {.id = 46, .data = (double)-80.567214}}, + {.next = &nodes2[46], .payload = {.id = 1, .data = (double)16.631426}}, + {.next = &nodes2[120], .payload = {.id = 179, .data = (double)99.717351}}, +}; + +node_t nodes3[] = { + {.next = &nodes3[23], .payload = {.id = 169, .data = (double)60.229617}}, + {.next = &nodes3[56], .payload = {.id = 47, .data = (double)63.378248}}, + {.next = &nodes3[252], .payload = {.id = 100, .data = (double)81.029377}}, + {.next = &nodes3[64], .payload = {.id = 253, .data = (double)60.732345}}, + {.next = &nodes3[226], .payload = {.id = 149, .data = (double)97.82454}}, + {.next = &nodes3[53], .payload = {.id = 37, .data = (double)-6.196879}}, + {.next = &nodes3[85], .payload = {.id = 54, .data = (double)-79.482054}}, + {.next = &nodes3[198], .payload = {.id = 214, .data = (double)-50.077669}}, + {.next = &nodes3[2], .payload = {.id = 99, .data = (double)-77.828421}}, + {.next = &nodes3[251], .payload = {.id = 182, .data = (double)-29.690603}}, + {.next = &nodes3[194], .payload = {.id = 220, .data = (double)-47.644665}}, + {.next = &nodes3[107], .payload = {.id = 108, .data = (double)-51.887152}}, + {.next = &nodes3[79], .payload = {.id = 4, .data = (double)-63.947415}}, + {.next = &nodes3[28], .payload = {.id = 187, .data = (double)-45.088928}}, + {.next = &nodes3[41], .payload = {.id = 28, .data = (double)35.272584}}, + {.next = &nodes3[167], .payload = {.id = 126, .data = (double)46.588204}}, + {.next = &nodes3[73], .payload = {.id = 175, .data = (double)-35.757714}}, + {.next = &nodes3[117], .payload = {.id = 91, .data = (double)5.554301}}, + {.next = &nodes3[12], .payload = {.id = 3, .data = (double)-27.480466}}, + {.next = &nodes3[66], .payload = {.id = 34, .data = (double)6.80223}}, + {.next = &nodes3[123], .payload = {.id = 247, .data = (double)-59.803926}}, + {.next = &nodes3[87], .payload = {.id = 0, .data = (double)29.204964}}, + {.next = &nodes3[60], .payload = {.id = 120, .data = (double)27.134158}}, + {.next = &nodes3[153], .payload = {.id = 170, .data = (double)45.416265}}, + {.next = &nodes3[163], .payload = {.id = 197, .data = (double)21.514581}}, + {.next = &nodes3[195], .payload = {.id = 22, .data = (double)66.269011}}, + {.next = &nodes3[154], .payload = {.id = 111, .data = (double)-82.877209}}, + {.next = &nodes3[40], .payload = {.id = 84, .data = (double)-10.279705}}, + {.next = &nodes3[108], .payload = {.id = 188, .data = (double)96.005456}}, + {.next = &nodes3[140], .payload = {.id = 26, .data = (double)-12.465319}}, + {.next = &nodes3[172], .payload = {.id = 145, .data = (double)-60.106033}}, + {.next = NULL, .payload = {.id = 255, .data = (double)22.389673}}, + {.next = &nodes3[206], .payload = {.id = 19, .data = (double)-73.790192}}, + {.next = &nodes3[253], .payload = {.id = 78, .data = (double)-72.480082}}, + {.next = &nodes3[230], .payload = {.id = 211, .data = (double)5.891976}}, + {.next = &nodes3[159], .payload = {.id = 75, .data = (double)67.835258}}, + {.next = &nodes3[96], .payload = {.id = 113, .data = (double)-86.464135}}, + {.next = &nodes3[188], .payload = {.id = 191, .data = (double)27.502508}}, + {.next = &nodes3[17], .payload = {.id = 90, .data = (double)45.446957}}, + {.next = &nodes3[235], .payload = {.id = 173, .data = (double)64.468256}}, + {.next = &nodes3[183], .payload = {.id = 85, .data = (double)-98.94976}}, + {.next = &nodes3[101], .payload = {.id = 29, .data = (double)-52.49396}}, + {.next = &nodes3[151], .payload = {.id = 117, .data = (double)10.83039}}, + {.next = &nodes3[3], .payload = {.id = 252, .data = (double)-26.217767}}, + {.next = &nodes3[74], .payload = {.id = 124, .data = (double)57.704003}}, + {.next = &nodes3[61], .payload = {.id = 194, .data = (double)35.882122}}, + {.next = &nodes3[70], .payload = {.id = 8, .data = (double)-54.691391}}, + {.next = &nodes3[210], .payload = {.id = 56, .data = (double)70.23321}}, + {.next = &nodes3[201], .payload = {.id = 69, .data = (double)0.401423}}, + {.next = &nodes3[184], .payload = {.id = 153, .data = (double)-61.779314}}, + {.next = &nodes3[169], .payload = {.id = 226, .data = (double)-1.759961}}, + {.next = &nodes3[203], .payload = {.id = 161, .data = (double)48.661541}}, + {.next = &nodes3[72], .payload = {.id = 200, .data = (double)-86.553327}}, + {.next = &nodes3[216], .payload = {.id = 38, .data = (double)67.022679}}, + {.next = &nodes3[83], .payload = {.id = 142, .data = (double)-8.464085}}, + {.next = &nodes3[142], .payload = {.id = 93, .data = (double)-42.379684}}, + {.next = &nodes3[69], .payload = {.id = 48, .data = (double)60.251845}}, + {.next = &nodes3[165], .payload = {.id = 138, .data = (double)26.34717}}, + {.next = &nodes3[175], .payload = {.id = 66, .data = (double)-30.082984}}, + {.next = &nodes3[25], .payload = {.id = 21, .data = (double)-67.550558}}, + {.next = &nodes3[249], .payload = {.id = 121, .data = (double)96.207885}}, + {.next = &nodes3[246], .payload = {.id = 195, .data = (double)90.557879}}, + {.next = &nodes3[29], .payload = {.id = 25, .data = (double)-66.892167}}, + {.next = &nodes3[141], .payload = {.id = 130, .data = (double)-33.496278}}, + {.next = &nodes3[31], .payload = {.id = 254, .data = (double)10.329387}}, + {.next = &nodes3[197], .payload = {.id = 156, .data = (double)73.159655}}, + {.next = &nodes3[148], .payload = {.id = 35, .data = (double)-38.106421}}, + {.next = &nodes3[121], .payload = {.id = 244, .data = (double)58.739277}}, + {.next = &nodes3[137], .payload = {.id = 235, .data = (double)-36.082446}}, + {.next = &nodes3[204], .payload = {.id = 49, .data = (double)-72.320293}}, + {.next = &nodes3[181], .payload = {.id = 9, .data = (double)-72.486929}}, + {.next = &nodes3[38], .payload = {.id = 89, .data = (double)9.760849}}, + {.next = &nodes3[115], .payload = {.id = 201, .data = (double)55.703075}}, + {.next = &nodes3[129], .payload = {.id = 176, .data = (double)-83.986218}}, + {.next = &nodes3[15], .payload = {.id = 125, .data = (double)-31.039501}}, + {.next = &nodes3[207], .payload = {.id = 71, .data = (double)98.90507}}, + {.next = &nodes3[95], .payload = {.id = 207, .data = (double)89.764706}}, + {.next = &nodes3[114], .payload = {.id = 96, .data = (double)-16.034891}}, + {.next = &nodes3[174], .payload = {.id = 165, .data = (double)-0.759355}}, + {.next = &nodes3[97], .payload = {.id = 5, .data = (double)-57.161468}}, + {.next = &nodes3[10], .payload = {.id = 219, .data = (double)12.334542}}, + {.next = &nodes3[150], .payload = {.id = 51, .data = (double)28.235807}}, + {.next = &nodes3[50], .payload = {.id = 225, .data = (double)83.295782}}, + {.next = &nodes3[182], .payload = {.id = 143, .data = (double)-41.311486}}, + {.next = &nodes3[242], .payload = {.id = 17, .data = (double)-32.647126}}, + {.next = &nodes3[47], .payload = {.id = 55, .data = (double)69.178455}}, + {.next = &nodes3[220], .payload = {.id = 13, .data = (double)54.174944}}, + {.next = &nodes3[106], .payload = {.id = 1, .data = (double)-15.318727}}, + {.next = &nodes3[196], .payload = {.id = 135, .data = (double)55.828519}}, + {.next = &nodes3[77], .payload = {.id = 95, .data = (double)-90.450111}}, + {.next = &nodes3[138], .payload = {.id = 60, .data = (double)81.061242}}, + {.next = &nodes3[43], .payload = {.id = 251, .data = (double)10.804287}}, + {.next = &nodes3[27], .payload = {.id = 83, .data = (double)41.107235}}, + {.next = &nodes3[13], .payload = {.id = 186, .data = (double)99.63012}}, + {.next = &nodes3[187], .payload = {.id = 167, .data = (double)84.862093}}, + {.next = &nodes3[145], .payload = {.id = 208, .data = (double)-25.597324}}, + {.next = &nodes3[237], .payload = {.id = 114, .data = (double)5.211889}}, + {.next = &nodes3[180], .payload = {.id = 6, .data = (double)89.533654}}, + {.next = &nodes3[225], .payload = {.id = 45, .data = (double)5.491958}}, + {.next = &nodes3[63], .payload = {.id = 129, .data = (double)47.037397}}, + {.next = &nodes3[228], .payload = {.id = 140, .data = (double)-87.379893}}, + {.next = &nodes3[218], .payload = {.id = 30, .data = (double)-11.160258}}, + {.next = &nodes3[110], .payload = {.id = 58, .data = (double)52.623366}}, + {.next = &nodes3[179], .payload = {.id = 205, .data = (double)21.018966}}, + {.next = &nodes3[103], .payload = {.id = 204, .data = (double)13.448928}}, + {.next = &nodes3[122], .payload = {.id = 178, .data = (double)-38.700829}}, + {.next = &nodes3[18], .payload = {.id = 2, .data = (double)-27.634381}}, + {.next = &nodes3[222], .payload = {.id = 109, .data = (double)-16.686481}}, + {.next = &nodes3[132], .payload = {.id = 189, .data = (double)89.580876}}, + {.next = &nodes3[93], .payload = {.id = 185, .data = (double)-29.488138}}, + {.next = &nodes3[90], .payload = {.id = 59, .data = (double)-45.44174}}, + {.next = &nodes3[58], .payload = {.id = 65, .data = (double)-9.774402}}, + {.next = &nodes3[248], .payload = {.id = 133, .data = (double)62.701773}}, + {.next = &nodes3[185], .payload = {.id = 249, .data = (double)58.074612}}, + {.next = &nodes3[128], .payload = {.id = 97, .data = (double)58.779822}}, + {.next = &nodes3[152], .payload = {.id = 202, .data = (double)-26.734305}}, + {.next = &nodes3[65], .payload = {.id = 155, .data = (double)56.168313}}, + {.next = &nodes3[55], .payload = {.id = 92, .data = (double)-77.762628}}, + {.next = &nodes3[164], .payload = {.id = 73, .data = (double)-94.362491}}, + {.next = &nodes3[57], .payload = {.id = 137, .data = (double)39.07785}}, + {.next = &nodes3[7], .payload = {.id = 213, .data = (double)29.912147}}, + {.next = &nodes3[224], .payload = {.id = 245, .data = (double)1.751149}}, + {.next = &nodes3[168], .payload = {.id = 179, .data = (double)20.524326}}, + {.next = &nodes3[113], .payload = {.id = 248, .data = (double)-72.224626}}, + {.next = &nodes3[143], .payload = {.id = 222, .data = (double)-10.745378}}, + {.next = &nodes3[49], .payload = {.id = 152, .data = (double)50.658184}}, + {.next = &nodes3[200], .payload = {.id = 231, .data = (double)-10.977761}}, + {.next = &nodes3[11], .payload = {.id = 107, .data = (double)22.961917}}, + {.next = &nodes3[8], .payload = {.id = 98, .data = (double)-8.577277}}, + {.next = &nodes3[105], .payload = {.id = 177, .data = (double)32.183844}}, + {.next = &nodes3[86], .payload = {.id = 12, .data = (double)-79.771847}}, + {.next = &nodes3[62], .payload = {.id = 24, .data = (double)61.808744}}, + {.next = &nodes3[37], .payload = {.id = 190, .data = (double)-84.991767}}, + {.next = &nodes3[205], .payload = {.id = 63, .data = (double)89.282653}}, + {.next = &nodes3[157], .payload = {.id = 237, .data = (double)-87.012184}}, + {.next = &nodes3[48], .payload = {.id = 68, .data = (double)-89.348623}}, + {.next = &nodes3[80], .payload = {.id = 218, .data = (double)-22.602524}}, + {.next = &nodes3[134], .payload = {.id = 236, .data = (double)-30.514941}}, + {.next = &nodes3[161], .payload = {.id = 61, .data = (double)-70.530269}}, + {.next = &nodes3[39], .payload = {.id = 172, .data = (double)20.49066}}, + {.next = &nodes3[14], .payload = {.id = 27, .data = (double)-17.828278}}, + {.next = &nodes3[234], .payload = {.id = 131, .data = (double)-91.132862}}, + {.next = &nodes3[89], .payload = {.id = 94, .data = (double)-39.769761}}, + {.next = &nodes3[231], .payload = {.id = 223, .data = (double)99.273022}}, + {.next = &nodes3[160], .payload = {.id = 102, .data = (double)-96.71293}}, + {.next = &nodes3[244], .payload = {.id = 209, .data = (double)52.616894}}, + {.next = &nodes3[232], .payload = {.id = 240, .data = (double)70.27241}}, + {.next = &nodes3[240], .payload = {.id = 80, .data = (double)65.952317}}, + {.next = &nodes3[5], .payload = {.id = 36, .data = (double)61.724774}}, + {.next = &nodes3[233], .payload = {.id = 87, .data = (double)-48.815214}}, + {.next = &nodes3[173], .payload = {.id = 52, .data = (double)74.823389}}, + {.next = &nodes3[236], .payload = {.id = 118, .data = (double)-21.909253}}, + {.next = &nodes3[104], .payload = {.id = 203, .data = (double)-23.42912}}, + {.next = &nodes3[139], .payload = {.id = 171, .data = (double)-84.214599}}, + {.next = &nodes3[36], .payload = {.id = 112, .data = (double)94.930898}}, + {.next = &nodes3[213], .payload = {.id = 40, .data = (double)89.426034}}, + {.next = &nodes3[254], .payload = {.id = 15, .data = (double)76.736433}}, + {.next = &nodes3[193], .payload = {.id = 238, .data = (double)8.434272}}, + {.next = &nodes3[42], .payload = {.id = 116, .data = (double)97.666297}}, + {.next = &nodes3[215], .payload = {.id = 76, .data = (double)29.992137}}, + {.next = &nodes3[245], .payload = {.id = 103, .data = (double)3.075146}}, + {.next = &nodes3[133], .payload = {.id = 62, .data = (double)-12.505488}}, + {.next = &nodes3[44], .payload = {.id = 123, .data = (double)-96.751554}}, + {.next = &nodes3[229], .payload = {.id = 198, .data = (double)56.262394}}, + {.next = &nodes3[35], .payload = {.id = 74, .data = (double)86.165181}}, + {.next = &nodes3[100], .payload = {.id = 139, .data = (double)62.299536}}, + {.next = &nodes3[219], .payload = {.id = 229, .data = (double)-9.591463}}, + {.next = &nodes3[221], .payload = {.id = 127, .data = (double)25.651392}}, + {.next = &nodes3[211], .payload = {.id = 180, .data = (double)-14.776785}}, + {.next = &nodes3[202], .payload = {.id = 227, .data = (double)-75.472516}}, + {.next = &nodes3[186], .payload = {.id = 158, .data = (double)-75.104998}}, + {.next = &nodes3[127], .payload = {.id = 106, .data = (double)-14.152221}}, + {.next = &nodes3[243], .payload = {.id = 146, .data = (double)-91.618812}}, + {.next = &nodes3[6], .payload = {.id = 53, .data = (double)10.908149}}, + {.next = &nodes3[94], .payload = {.id = 166, .data = (double)-0.495322}}, + {.next = &nodes3[135], .payload = {.id = 67, .data = (double)-94.665962}}, + {.next = &nodes3[67], .payload = {.id = 243, .data = (double)27.540005}}, + {.next = &nodes3[45], .payload = {.id = 193, .data = (double)60.219195}}, + {.next = &nodes3[130], .payload = {.id = 11, .data = (double)68.885678}}, + {.next = &nodes3[76], .payload = {.id = 206, .data = (double)35.812411}}, + {.next = &nodes3[46], .payload = {.id = 7, .data = (double)-2.745816}}, + {.next = &nodes3[178], .payload = {.id = 10, .data = (double)-84.566983}}, + {.next = &nodes3[30], .payload = {.id = 144, .data = (double)-91.238745}}, + {.next = &nodes3[149], .payload = {.id = 86, .data = (double)-84.154846}}, + {.next = &nodes3[116], .payload = {.id = 154, .data = (double)-28.605165}}, + {.next = &nodes3[91], .payload = {.id = 250, .data = (double)-94.743195}}, + {.next = &nodes3[199], .payload = {.id = 159, .data = (double)-26.396165}}, + {.next = &nodes3[0], .payload = {.id = 168, .data = (double)3.855171}}, + {.next = &nodes3[177], .payload = {.id = 192, .data = (double)-27.337774}}, + {.next = &nodes3[208], .payload = {.id = 216, .data = (double)47.134972}}, + {.next = &nodes3[4], .payload = {.id = 148, .data = (double)3.076718}}, + {.next = &nodes3[125], .payload = {.id = 151, .data = (double)-49.337247}}, + {.next = &nodes3[255], .payload = {.id = 43, .data = (double)-43.645653}}, + {.next = &nodes3[146], .payload = {.id = 239, .data = (double)78.266336}}, + {.next = &nodes3[124], .payload = {.id = 221, .data = (double)-47.942046}}, + {.next = &nodes3[131], .payload = {.id = 23, .data = (double)54.219563}}, + {.next = &nodes3[119], .payload = {.id = 136, .data = (double)-7.07542}}, + {.next = &nodes3[170], .payload = {.id = 157, .data = (double)-33.615063}}, + {.next = &nodes3[189], .payload = {.id = 215, .data = (double)-77.310277}}, + {.next = &nodes3[51], .payload = {.id = 160, .data = (double)77.897303}}, + {.next = &nodes3[209], .payload = {.id = 232, .data = (double)-82.441852}}, + {.next = &nodes3[75], .payload = {.id = 70, .data = (double)-52.844385}}, + {.next = &nodes3[166], .payload = {.id = 228, .data = (double)70.565258}}, + {.next = &nodes3[227], .payload = {.id = 162, .data = (double)78.927499}}, + {.next = &nodes3[81], .payload = {.id = 50, .data = (double)-49.999358}}, + {.next = &nodes3[111], .payload = {.id = 64, .data = (double)-55.592399}}, + {.next = &nodes3[59], .payload = {.id = 20, .data = (double)-24.656026}}, + {.next = &nodes3[118], .payload = {.id = 72, .data = (double)-25.017465}}, + {.next = &nodes3[136], .payload = {.id = 217, .data = (double)-0.191208}}, + {.next = &nodes3[217], .payload = {.id = 233, .data = (double)36.385852}}, + {.next = &nodes3[102], .payload = {.id = 57, .data = (double)-42.987397}}, + {.next = &nodes3[9], .payload = {.id = 181, .data = (double)37.952962}}, + {.next = &nodes3[92], .payload = {.id = 82, .data = (double)-72.241462}}, + {.next = &nodes3[214], .payload = {.id = 41, .data = (double)96.887959}}, + {.next = &nodes3[192], .payload = {.id = 42, .data = (double)-7.664004}}, + {.next = &nodes3[33], .payload = {.id = 77, .data = (double)58.276127}}, + {.next = &nodes3[155], .payload = {.id = 39, .data = (double)-26.431808}}, + {.next = &nodes3[68], .payload = {.id = 234, .data = (double)69.104244}}, + {.next = &nodes3[241], .payload = {.id = 31, .data = (double)-43.014413}}, + {.next = &nodes3[126], .payload = {.id = 230, .data = (double)79.735806}}, + {.next = &nodes3[156], .payload = {.id = 14, .data = (double)67.023965}}, + {.next = &nodes3[99], .payload = {.id = 128, .data = (double)54.300275}}, + {.next = &nodes3[26], .payload = {.id = 110, .data = (double)32.87426}}, + {.next = &nodes3[19], .payload = {.id = 33, .data = (double)-10.214407}}, + {.next = &nodes3[20], .payload = {.id = 246, .data = (double)-75.727509}}, + {.next = &nodes3[1], .payload = {.id = 46, .data = (double)93.253631}}, + {.next = &nodes3[191], .payload = {.id = 150, .data = (double)8.60614}}, + {.next = &nodes3[239], .payload = {.id = 163, .data = (double)-22.671046}}, + {.next = &nodes3[54], .payload = {.id = 141, .data = (double)55.23808}}, + {.next = &nodes3[52], .payload = {.id = 199, .data = (double)-93.040207}}, + {.next = &nodes3[120], .payload = {.id = 212, .data = (double)-20.393191}}, + {.next = &nodes3[82], .payload = {.id = 224, .data = (double)-42.884624}}, + {.next = &nodes3[238], .payload = {.id = 241, .data = (double)42.361821}}, + {.next = &nodes3[71], .payload = {.id = 88, .data = (double)66.99262}}, + {.next = &nodes3[112], .payload = {.id = 132, .data = (double)9.202749}}, + {.next = &nodes3[16], .payload = {.id = 174, .data = (double)9.094879}}, + {.next = &nodes3[22], .payload = {.id = 119, .data = (double)-5.972984}}, + {.next = &nodes3[158], .payload = {.id = 115, .data = (double)1.465539}}, + {.next = &nodes3[176], .payload = {.id = 242, .data = (double)85.464891}}, + {.next = &nodes3[78], .payload = {.id = 164, .data = (double)94.744717}}, + {.next = &nodes3[212], .payload = {.id = 81, .data = (double)39.214398}}, + {.next = &nodes3[223], .payload = {.id = 32, .data = (double)49.707304}}, + {.next = &nodes3[32], .payload = {.id = 18, .data = (double)53.261521}}, + {.next = &nodes3[190], .payload = {.id = 147, .data = (double)86.674196}}, + {.next = &nodes3[34], .payload = {.id = 210, .data = (double)14.784356}}, + {.next = &nodes3[247], .payload = {.id = 104, .data = (double)-51.612373}}, + {.next = &nodes3[24], .payload = {.id = 196, .data = (double)-71.444106}}, + {.next = &nodes3[171], .payload = {.id = 105, .data = (double)-71.284632}}, + {.next = &nodes3[88], .payload = {.id = 134, .data = (double)-64.982175}}, + {.next = &nodes3[162], .payload = {.id = 122, .data = (double)-49.269948}}, + {.next = &nodes3[109], .payload = {.id = 184, .data = (double)74.007435}}, + {.next = &nodes3[250], .payload = {.id = 183, .data = (double)-91.528967}}, + {.next = &nodes3[144], .payload = {.id = 101, .data = (double)19.347809}}, + {.next = &nodes3[147], .payload = {.id = 79, .data = (double)-42.624121}}, + {.next = &nodes3[84], .payload = {.id = 16, .data = (double)-92.450502}}, + {.next = &nodes3[98], .payload = {.id = 44, .data = (double)-23.625513}}, +}; + +node_t nodes4[] = { + {.next = &nodes4[67], .payload = {.id = 185, .data = (double)61.738417}}, + {.next = &nodes4[87], .payload = {.id = 218, .data = (double)7.860053}}, + {.next = &nodes4[149], .payload = {.id = 216, .data = (double)36.546071}}, + {.next = &nodes4[61], .payload = {.id = 111, .data = (double)-6.395846}}, + {.next = &nodes4[180], .payload = {.id = 204, .data = (double)-93.653026}}, + {.next = &nodes4[32], .payload = {.id = 190, .data = (double)-7.524339}}, + {.next = &nodes4[123], .payload = {.id = 41, .data = (double)-45.308493}}, + {.next = &nodes4[63], .payload = {.id = 198, .data = (double)-31.094227}}, + {.next = &nodes4[139], .payload = {.id = 24, .data = (double)44.184912}}, + {.next = &nodes4[60], .payload = {.id = 89, .data = (double)82.645945}}, + {.next = &nodes4[21], .payload = {.id = 73, .data = (double)10.070513}}, + {.next = &nodes4[74], .payload = {.id = 206, .data = (double)53.794413}}, + {.next = &nodes4[108], .payload = {.id = 167, .data = (double)74.627012}}, + {.next = &nodes4[75], .payload = {.id = 210, .data = (double)-15.927612}}, + {.next = &nodes4[122], .payload = {.id = 28, .data = (double)-61.547166}}, + {.next = &nodes4[77], .payload = {.id = 26, .data = (double)38.662662}}, + {.next = &nodes4[207], .payload = {.id = 46, .data = (double)63.675492}}, + {.next = &nodes4[57], .payload = {.id = 162, .data = (double)7.503538}}, + {.next = &nodes4[93], .payload = {.id = 175, .data = (double)1.097411}}, + {.next = &nodes4[137], .payload = {.id = 213, .data = (double)73.924057}}, + {.next = &nodes4[153], .payload = {.id = 202, .data = (double)-86.196171}}, + {.next = &nodes4[40], .payload = {.id = 74, .data = (double)85.819936}}, + {.next = &nodes4[124], .payload = {.id = 138, .data = (double)44.576506}}, + {.next = &nodes4[154], .payload = {.id = 100, .data = (double)75.348634}}, + {.next = &nodes4[99], .payload = {.id = 102, .data = (double)13.592374}}, + {.next = &nodes4[0], .payload = {.id = 184, .data = (double)2.075071}}, + {.next = &nodes4[150], .payload = {.id = 71, .data = (double)54.153212}}, + {.next = &nodes4[193], .payload = {.id = 222, .data = (double)7.451697}}, + {.next = &nodes4[140], .payload = {.id = 254, .data = (double)72.746049}}, + {.next = &nodes4[226], .payload = {.id = 159, .data = (double)-16.830877}}, + {.next = &nodes4[37], .payload = {.id = 49, .data = (double)-41.90947}}, + {.next = &nodes4[6], .payload = {.id = 40, .data = (double)59.081071}}, + {.next = &nodes4[106], .payload = {.id = 191, .data = (double)61.383071}}, + {.next = &nodes4[156], .payload = {.id = 228, .data = (double)-40.327402}}, + {.next = &nodes4[43], .payload = {.id = 123, .data = (double)71.229301}}, + {.next = &nodes4[134], .payload = {.id = 79, .data = (double)-60.108805}}, + {.next = &nodes4[72], .payload = {.id = 246, .data = (double)-93.284745}}, + {.next = &nodes4[56], .payload = {.id = 50, .data = (double)-42.473932}}, + {.next = &nodes4[198], .payload = {.id = 117, .data = (double)-62.760186}}, + {.next = &nodes4[200], .payload = {.id = 180, .data = (double)-76.751996}}, + {.next = &nodes4[234], .payload = {.id = 75, .data = (double)-18.61851}}, + {.next = &nodes4[152], .payload = {.id = 140, .data = (double)30.736673}}, + {.next = &nodes4[86], .payload = {.id = 5, .data = (double)-69.713748}}, + {.next = &nodes4[79], .payload = {.id = 124, .data = (double)79.408552}}, + {.next = &nodes4[25], .payload = {.id = 183, .data = (double)-81.811671}}, + {.next = &nodes4[181], .payload = {.id = 22, .data = (double)-29.142602}}, + {.next = &nodes4[98], .payload = {.id = 16, .data = (double)32.44536}}, + {.next = &nodes4[151], .payload = {.id = 242, .data = (double)76.751324}}, + {.next = &nodes4[31], .payload = {.id = 39, .data = (double)86.740075}}, + {.next = &nodes4[27], .payload = {.id = 221, .data = (double)-64.305274}}, + {.next = &nodes4[116], .payload = {.id = 232, .data = (double)64.672087}}, + {.next = &nodes4[49], .payload = {.id = 220, .data = (double)-30.446023}}, + {.next = &nodes4[191], .payload = {.id = 33, .data = (double)-40.477087}}, + {.next = &nodes4[17], .payload = {.id = 161, .data = (double)-5.834385}}, + {.next = &nodes4[114], .payload = {.id = 86, .data = (double)7.030455}}, + {.next = &nodes4[237], .payload = {.id = 132, .data = (double)-50.390583}}, + {.next = &nodes4[187], .payload = {.id = 51, .data = (double)42.828257}}, + {.next = &nodes4[219], .payload = {.id = 163, .data = (double)32.818888}}, + {.next = &nodes4[69], .payload = {.id = 113, .data = (double)-77.470648}}, + {.next = &nodes4[33], .payload = {.id = 227, .data = (double)-95.452935}}, + {.next = &nodes4[146], .payload = {.id = 90, .data = (double)-64.987045}}, + {.next = &nodes4[58], .payload = {.id = 112, .data = (double)-61.43772}}, + {.next = &nodes4[89], .payload = {.id = 128, .data = (double)33.851171}}, + {.next = &nodes4[94], .payload = {.id = 199, .data = (double)-87.248018}}, + {.next = &nodes4[239], .payload = {.id = 35, .data = (double)-58.544441}}, + {.next = &nodes4[38], .payload = {.id = 116, .data = (double)-48.547024}}, + {.next = &nodes4[73], .payload = {.id = 145, .data = (double)-18.916677}}, + {.next = &nodes4[251], .payload = {.id = 186, .data = (double)-9.31354}}, + {.next = &nodes4[213], .payload = {.id = 177, .data = (double)-70.029524}}, + {.next = &nodes4[183], .payload = {.id = 114, .data = (double)-67.501147}}, + {.next = &nodes4[162], .payload = {.id = 2, .data = (double)-78.020896}}, + {.next = &nodes4[208], .payload = {.id = 95, .data = (double)-20.601085}}, + {.next = &nodes4[84], .payload = {.id = 247, .data = (double)19.556979}}, + {.next = &nodes4[250], .payload = {.id = 146, .data = (double)0.504094}}, + {.next = &nodes4[253], .payload = {.id = 207, .data = (double)53.165537}}, + {.next = &nodes4[194], .payload = {.id = 211, .data = (double)98.57132}}, + {.next = &nodes4[188], .payload = {.id = 64, .data = (double)33.966793}}, + {.next = &nodes4[14], .payload = {.id = 27, .data = (double)22.015316}}, + {.next = &nodes4[70], .payload = {.id = 1, .data = (double)89.641034}}, + {.next = &nodes4[222], .payload = {.id = 125, .data = (double)65.397965}}, + {.next = &nodes4[88], .payload = {.id = 8, .data = (double)54.99446}}, + {.next = &nodes4[29], .payload = {.id = 158, .data = (double)21.14779}}, + {.next = &nodes4[2], .payload = {.id = 215, .data = (double)-24.870893}}, + {.next = &nodes4[190], .payload = {.id = 98, .data = (double)92.426276}}, + {.next = &nodes4[214], .payload = {.id = 248, .data = (double)40.657253}}, + {.next = &nodes4[78], .payload = {.id = 0, .data = (double)-93.685897}}, + {.next = &nodes4[91], .payload = {.id = 6, .data = (double)38.100052}}, + {.next = &nodes4[51], .payload = {.id = 219, .data = (double)30.70682}}, + {.next = &nodes4[172], .payload = {.id = 9, .data = (double)84.10419}}, + {.next = &nodes4[126], .payload = {.id = 129, .data = (double)-63.04376}}, + {.next = &nodes4[177], .payload = {.id = 67, .data = (double)-89.501779}}, + {.next = &nodes4[80], .payload = {.id = 7, .data = (double)-17.924518}}, + {.next = &nodes4[97], .payload = {.id = 107, .data = (double)8.660097}}, + {.next = &nodes4[68], .payload = {.id = 176, .data = (double)14.540335}}, + {.next = &nodes4[216], .payload = {.id = 200, .data = (double)98.824732}}, + {.next = &nodes4[3], .payload = {.id = 110, .data = (double)70.211948}}, + {.next = &nodes4[233], .payload = {.id = 69, .data = (double)43.471611}}, + {.next = &nodes4[224], .payload = {.id = 108, .data = (double)-1.217516}}, + {.next = &nodes4[171], .payload = {.id = 17, .data = (double)5.09543}}, + {.next = &nodes4[211], .payload = {.id = 103, .data = (double)-78.539862}}, + {.next = &nodes4[16], .payload = {.id = 45, .data = (double)96.032107}}, + {.next = &nodes4[109], .payload = {.id = 156, .data = (double)-69.362887}}, + {.next = &nodes4[182], .payload = {.id = 93, .data = (double)83.926962}}, + {.next = &nodes4[45], .payload = {.id = 21, .data = (double)-31.534596}}, + {.next = &nodes4[254], .payload = {.id = 58, .data = (double)86.604787}}, + {.next = &nodes4[163], .payload = {.id = 240, .data = (double)-16.15188}}, + {.next = &nodes4[206], .payload = {.id = 192, .data = (double)44.656016}}, + {.next = &nodes4[223], .payload = {.id = 230, .data = (double)8.889068}}, + {.next = &nodes4[238], .payload = {.id = 168, .data = (double)-83.625939}}, + {.next = &nodes4[81], .payload = {.id = 157, .data = (double)49.546967}}, + {.next = &nodes4[120], .payload = {.id = 237, .data = (double)45.004789}}, + {.next = &nodes4[169], .payload = {.id = 149, .data = (double)-37.80441}}, + {.next = &nodes4[52], .payload = {.id = 32, .data = (double)94.582126}}, + {.next = &nodes4[227], .payload = {.id = 43, .data = (double)35.324449}}, + {.next = &nodes4[220], .payload = {.id = 87, .data = (double)44.623536}}, + {.next = &nodes4[186], .payload = {.id = 83, .data = (double)81.587392}}, + {.next = &nodes4[252], .payload = {.id = 233, .data = (double)-50.497592}}, + {.next = &nodes4[76], .payload = {.id = 63, .data = (double)-51.508392}}, + {.next = &nodes4[112], .payload = {.id = 31, .data = (double)-55.026592}}, + {.next = &nodes4[247], .payload = {.id = 152, .data = (double)-40.99248}}, + {.next = &nodes4[199], .payload = {.id = 238, .data = (double)-77.431072}}, + {.next = &nodes4[59], .payload = {.id = 226, .data = (double)-99.305341}}, + {.next = &nodes4[159], .payload = {.id = 29, .data = (double)-50.696173}}, + {.next = &nodes4[113], .payload = {.id = 42, .data = (double)-75.625179}}, + {.next = &nodes4[41], .payload = {.id = 139, .data = (double)-97.712853}}, + {.next = &nodes4[184], .payload = {.id = 19, .data = (double)-65.363515}}, + {.next = &nodes4[142], .payload = {.id = 130, .data = (double)-71.877625}}, + {.next = &nodes4[133], .payload = {.id = 194, .data = (double)63.290645}}, + {.next = &nodes4[66], .payload = {.id = 144, .data = (double)-38.638732}}, + {.next = &nodes4[42], .payload = {.id = 4, .data = (double)-37.261503}}, + {.next = &nodes4[210], .payload = {.id = 37, .data = (double)-36.591851}}, + {.next = &nodes4[110], .payload = {.id = 236, .data = (double)87.482072}}, + {.next = &nodes4[221], .payload = {.id = 11, .data = (double)47.167454}}, + {.next = &nodes4[168], .payload = {.id = 195, .data = (double)49.160897}}, + {.next = &nodes4[249], .payload = {.id = 80, .data = (double)92.782808}}, + {.next = &nodes4[44], .payload = {.id = 182, .data = (double)16.629536}}, + {.next = &nodes4[101], .payload = {.id = 155, .data = (double)-73.286244}}, + {.next = &nodes4[82], .payload = {.id = 214, .data = (double)81.353462}}, + {.next = &nodes4[204], .payload = {.id = 120, .data = (double)13.556244}}, + {.next = &nodes4[15], .payload = {.id = 25, .data = (double)28.66182}}, + {.next = NULL, .payload = {.id = 255, .data = (double)-88.711193}}, + {.next = &nodes4[62], .payload = {.id = 127, .data = (double)-82.652446}}, + {.next = &nodes4[55], .payload = {.id = 131, .data = (double)-35.279666}}, + {.next = &nodes4[102], .payload = {.id = 92, .data = (double)-64.842258}}, + {.next = &nodes4[90], .payload = {.id = 66, .data = (double)27.588915}}, + {.next = &nodes4[35], .payload = {.id = 78, .data = (double)-4.510296}}, + {.next = &nodes4[143], .payload = {.id = 91, .data = (double)76.448995}}, + {.next = &nodes4[205], .payload = {.id = 136, .data = (double)90.806965}}, + {.next = &nodes4[138], .payload = {.id = 119, .data = (double)58.153533}}, + {.next = &nodes4[1], .payload = {.id = 217, .data = (double)32.358508}}, + {.next = &nodes4[10], .payload = {.id = 72, .data = (double)-98.963711}}, + {.next = &nodes4[201], .payload = {.id = 243, .data = (double)-96.870841}}, + {.next = &nodes4[231], .payload = {.id = 141, .data = (double)38.553718}}, + {.next = &nodes4[4], .payload = {.id = 203, .data = (double)86.755113}}, + {.next = &nodes4[24], .payload = {.id = 101, .data = (double)-98.146566}}, + {.next = &nodes4[209], .payload = {.id = 251, .data = (double)-19.54693}}, + {.next = &nodes4[107], .payload = {.id = 229, .data = (double)34.699972}}, + {.next = &nodes4[5], .payload = {.id = 189, .data = (double)-88.452644}}, + {.next = &nodes4[12], .payload = {.id = 166, .data = (double)50.94791}}, + {.next = &nodes4[118], .payload = {.id = 30, .data = (double)11.61733}}, + {.next = &nodes4[218], .payload = {.id = 170, .data = (double)40.753225}}, + {.next = &nodes4[167], .payload = {.id = 54, .data = (double)-48.711205}}, + {.next = &nodes4[129], .payload = {.id = 3, .data = (double)-96.212526}}, + {.next = &nodes4[47], .payload = {.id = 241, .data = (double)53.210694}}, + {.next = &nodes4[54], .payload = {.id = 85, .data = (double)14.826671}}, + {.next = &nodes4[161], .payload = {.id = 53, .data = (double)-11.524778}}, + {.next = &nodes4[34], .payload = {.id = 122, .data = (double)-64.901017}}, + {.next = &nodes4[236], .payload = {.id = 55, .data = (double)-4.184147}}, + {.next = &nodes4[246], .payload = {.id = 196, .data = (double)15.662253}}, + {.next = &nodes4[230], .payload = {.id = 150, .data = (double)-76.516851}}, + {.next = &nodes4[39], .payload = {.id = 179, .data = (double)4.068308}}, + {.next = &nodes4[125], .payload = {.id = 18, .data = (double)-37.24948}}, + {.next = &nodes4[132], .payload = {.id = 10, .data = (double)74.563542}}, + {.next = &nodes4[18], .payload = {.id = 174, .data = (double)9.52985}}, + {.next = &nodes4[136], .payload = {.id = 154, .data = (double)-56.17428}}, + {.next = &nodes4[36], .payload = {.id = 245, .data = (double)-79.820657}}, + {.next = &nodes4[28], .payload = {.id = 253, .data = (double)-56.546158}}, + {.next = &nodes4[96], .payload = {.id = 68, .data = (double)-17.339727}}, + {.next = &nodes4[197], .payload = {.id = 13, .data = (double)-72.383503}}, + {.next = &nodes4[30], .payload = {.id = 48, .data = (double)60.923167}}, + {.next = &nodes4[11], .payload = {.id = 205, .data = (double)-18.226613}}, + {.next = &nodes4[8], .payload = {.id = 23, .data = (double)54.397957}}, + {.next = &nodes4[71], .payload = {.id = 94, .data = (double)99.434361}}, + {.next = &nodes4[65], .payload = {.id = 115, .data = (double)-8.217106}}, + {.next = &nodes4[103], .payload = {.id = 20, .data = (double)82.424832}}, + {.next = &nodes4[158], .payload = {.id = 165, .data = (double)-50.506914}}, + {.next = &nodes4[164], .payload = {.id = 84, .data = (double)-82.107856}}, + {.next = &nodes4[165], .payload = {.id = 52, .data = (double)-30.727297}}, + {.next = &nodes4[144], .payload = {.id = 65, .data = (double)6.208298}}, + {.next = &nodes4[117], .payload = {.id = 62, .data = (double)17.3661}}, + {.next = &nodes4[23], .payload = {.id = 99, .data = (double)85.20794}}, + {.next = &nodes4[64], .payload = {.id = 34, .data = (double)-42.199173}}, + {.next = &nodes4[147], .payload = {.id = 135, .data = (double)50.75133}}, + {.next = &nodes4[240], .payload = {.id = 223, .data = (double)5.768508}}, + {.next = &nodes4[19], .payload = {.id = 212, .data = (double)-23.504076}}, + {.next = &nodes4[131], .payload = {.id = 235, .data = (double)-44.870054}}, + {.next = &nodes4[128], .payload = {.id = 143, .data = (double)-76.35503}}, + {.next = &nodes4[232], .payload = {.id = 14, .data = (double)-58.531659}}, + {.next = &nodes4[148], .payload = {.id = 118, .data = (double)47.323579}}, + {.next = &nodes4[105], .payload = {.id = 239, .data = (double)61.895637}}, + {.next = &nodes4[135], .payload = {.id = 181, .data = (double)-58.919703}}, + {.next = &nodes4[175], .payload = {.id = 244, .data = (double)-58.783676}}, + {.next = &nodes4[104], .payload = {.id = 57, .data = (double)7.715585}}, + {.next = &nodes4[189], .payload = {.id = 61, .data = (double)23.135407}}, + {.next = &nodes4[166], .payload = {.id = 121, .data = (double)51.45655}}, + {.next = &nodes4[22], .payload = {.id = 137, .data = (double)-39.610832}}, + {.next = &nodes4[127], .payload = {.id = 193, .data = (double)-20.810258}}, + {.next = &nodes4[179], .payload = {.id = 47, .data = (double)90.921773}}, + {.next = &nodes4[217], .payload = {.id = 96, .data = (double)-0.923221}}, + {.next = &nodes4[176], .payload = {.id = 252, .data = (double)-53.132144}}, + {.next = &nodes4[48], .payload = {.id = 38, .data = (double)-30.239365}}, + {.next = &nodes4[235], .payload = {.id = 104, .data = (double)96.598778}}, + {.next = &nodes4[92], .payload = {.id = 106, .data = (double)97.819894}}, + {.next = &nodes4[170], .payload = {.id = 178, .data = (double)-34.376472}}, + {.next = &nodes4[248], .payload = {.id = 249, .data = (double)-90.264736}}, + {.next = &nodes4[192], .payload = {.id = 134, .data = (double)-52.895749}}, + {.next = &nodes4[20], .payload = {.id = 201, .data = (double)86.91656}}, + {.next = &nodes4[83], .payload = {.id = 97, .data = (double)87.321749}}, + {.next = &nodes4[245], .payload = {.id = 171, .data = (double)-84.379456}}, + {.next = &nodes4[185], .payload = {.id = 164, .data = (double)-56.317675}}, + {.next = &nodes4[9], .payload = {.id = 88, .data = (double)87.333876}}, + {.next = &nodes4[178], .payload = {.id = 12, .data = (double)-87.543743}}, + {.next = &nodes4[141], .payload = {.id = 126, .data = (double)3.056132}}, + {.next = &nodes4[50], .payload = {.id = 231, .data = (double)6.386722}}, + {.next = &nodes4[95], .payload = {.id = 109, .data = (double)87.7121}}, + {.next = &nodes4[173], .payload = {.id = 173, .data = (double)-87.64839}}, + {.next = &nodes4[53], .payload = {.id = 160, .data = (double)9.846902}}, + {.next = &nodes4[100], .payload = {.id = 44, .data = (double)-24.061163}}, + {.next = &nodes4[157], .payload = {.id = 188, .data = (double)-8.640305}}, + {.next = &nodes4[121], .payload = {.id = 225, .data = (double)-55.461957}}, + {.next = &nodes4[119], .payload = {.id = 151, .data = (double)83.226077}}, + {.next = &nodes4[196], .payload = {.id = 142, .data = (double)-87.575134}}, + {.next = &nodes4[46], .payload = {.id = 15, .data = (double)-34.990093}}, + {.next = &nodes4[26], .payload = {.id = 70, .data = (double)-79.891019}}, + {.next = &nodes4[241], .payload = {.id = 76, .data = (double)87.00642}}, + {.next = &nodes4[212], .payload = {.id = 105, .data = (double)-43.08767}}, + {.next = &nodes4[202], .payload = {.id = 56, .data = (double)-59.586399}}, + {.next = &nodes4[215], .payload = {.id = 133, .data = (double)-47.842945}}, + {.next = &nodes4[160], .payload = {.id = 169, .data = (double)-10.650405}}, + {.next = &nodes4[130], .payload = {.id = 36, .data = (double)40.997652}}, + {.next = &nodes4[229], .payload = {.id = 224, .data = (double)45.571628}}, + {.next = &nodes4[145], .payload = {.id = 77, .data = (double)75.679924}}, + {.next = &nodes4[203], .payload = {.id = 60, .data = (double)-72.545409}}, + {.next = &nodes4[115], .payload = {.id = 82, .data = (double)29.179584}}, + {.next = &nodes4[13], .payload = {.id = 209, .data = (double)29.176164}}, + {.next = &nodes4[225], .payload = {.id = 172, .data = (double)12.833744}}, + {.next = &nodes4[7], .payload = {.id = 197, .data = (double)-90.942039}}, + {.next = &nodes4[174], .payload = {.id = 153, .data = (double)22.92509}}, + {.next = &nodes4[155], .payload = {.id = 250, .data = (double)48.108216}}, + {.next = &nodes4[243], .payload = {.id = 81, .data = (double)-35.76646}}, + {.next = &nodes4[255], .payload = {.id = 147, .data = (double)79.023674}}, + {.next = &nodes4[228], .payload = {.id = 187, .data = (double)2.649569}}, + {.next = &nodes4[195], .payload = {.id = 234, .data = (double)-30.768053}}, + {.next = &nodes4[244], .payload = {.id = 208, .data = (double)95.666657}}, + {.next = &nodes4[242], .payload = {.id = 59, .data = (double)39.23426}}, + {.next = &nodes4[111], .payload = {.id = 148, .data = (double)40.711407}}, +}; + +node_t nodes5[] = { + {.next = &nodes5[81], .payload = {.id = 49, .data = (double)52.269298}}, + {.next = &nodes5[45], .payload = {.id = 228, .data = (double)83.736516}}, + {.next = &nodes5[187], .payload = {.id = 226, .data = (double)34.717772}}, + {.next = &nodes5[31], .payload = {.id = 78, .data = (double)-27.775018}}, + {.next = &nodes5[3], .payload = {.id = 77, .data = (double)56.533325}}, + {.next = &nodes5[23], .payload = {.id = 17, .data = (double)49.091312}}, + {.next = &nodes5[68], .payload = {.id = 65, .data = (double)11.907309}}, + {.next = &nodes5[37], .payload = {.id = 85, .data = (double)-98.646526}}, + {.next = &nodes5[214], .payload = {.id = 216, .data = (double)34.140286}}, + {.next = &nodes5[0], .payload = {.id = 48, .data = (double)-11.052827}}, + {.next = &nodes5[7], .payload = {.id = 84, .data = (double)-72.902095}}, + {.next = &nodes5[30], .payload = {.id = 132, .data = (double)19.586771}}, + {.next = &nodes5[124], .payload = {.id = 40, .data = (double)-46.405594}}, + {.next = &nodes5[113], .payload = {.id = 120, .data = (double)66.256362}}, + {.next = &nodes5[209], .payload = {.id = 111, .data = (double)-60.03999}}, + {.next = &nodes5[158], .payload = {.id = 31, .data = (double)10.607545}}, + {.next = &nodes5[242], .payload = {.id = 202, .data = (double)76.619475}}, + {.next = &nodes5[230], .payload = {.id = 243, .data = (double)86.138988}}, + {.next = &nodes5[86], .payload = {.id = 211, .data = (double)59.900471}}, + {.next = &nodes5[185], .payload = {.id = 155, .data = (double)-78.81109}}, + {.next = &nodes5[172], .payload = {.id = 151, .data = (double)29.348721}}, + {.next = &nodes5[156], .payload = {.id = 200, .data = (double)-20.883524}}, + {.next = &nodes5[200], .payload = {.id = 75, .data = (double)-44.807626}}, + {.next = &nodes5[144], .payload = {.id = 18, .data = (double)-30.8281}}, + {.next = &nodes5[137], .payload = {.id = 123, .data = (double)59.009125}}, + {.next = &nodes5[88], .payload = {.id = 45, .data = (double)-27.859954}}, + {.next = &nodes5[6], .payload = {.id = 64, .data = (double)44.968769}}, + {.next = &nodes5[57], .payload = {.id = 3, .data = (double)64.138148}}, + {.next = &nodes5[84], .payload = {.id = 254, .data = (double)-23.211165}}, + {.next = &nodes5[169], .payload = {.id = 81, .data = (double)-0.839513}}, + {.next = &nodes5[48], .payload = {.id = 133, .data = (double)16.448804}}, + {.next = &nodes5[107], .payload = {.id = 79, .data = (double)88.844459}}, + {.next = &nodes5[75], .payload = {.id = 205, .data = (double)-99.109991}}, + {.next = &nodes5[128], .payload = {.id = 182, .data = (double)-86.565132}}, + {.next = &nodes5[56], .payload = {.id = 13, .data = (double)47.949034}}, + {.next = &nodes5[227], .payload = {.id = 195, .data = (double)-7.589169}}, + {.next = &nodes5[237], .payload = {.id = 69, .data = (double)37.063198}}, + {.next = &nodes5[112], .payload = {.id = 86, .data = (double)-20.861604}}, + {.next = &nodes5[17], .payload = {.id = 242, .data = (double)83.832199}}, + {.next = &nodes5[24], .payload = {.id = 122, .data = (double)69.557586}}, + {.next = &nodes5[175], .payload = {.id = 186, .data = (double)-31.38441}}, + {.next = &nodes5[159], .payload = {.id = 236, .data = (double)-22.307346}}, + {.next = &nodes5[2], .payload = {.id = 225, .data = (double)-65.494497}}, + {.next = &nodes5[114], .payload = {.id = 171, .data = (double)-82.82904}}, + {.next = &nodes5[202], .payload = {.id = 191, .data = (double)3.19878}}, + {.next = &nodes5[47], .payload = {.id = 229, .data = (double)18.033673}}, + {.next = &nodes5[192], .payload = {.id = 59, .data = (double)56.887745}}, + {.next = &nodes5[133], .payload = {.id = 230, .data = (double)34.422016}}, + {.next = &nodes5[99], .payload = {.id = 134, .data = (double)6.87348}}, + {.next = &nodes5[216], .payload = {.id = 92, .data = (double)64.707048}}, + {.next = &nodes5[178], .payload = {.id = 178, .data = (double)-30.339941}}, + {.next = &nodes5[19], .payload = {.id = 154, .data = (double)59.246213}}, + {.next = &nodes5[179], .payload = {.id = 51, .data = (double)-82.540554}}, + {.next = &nodes5[203], .payload = {.id = 166, .data = (double)-69.851014}}, + {.next = &nodes5[186], .payload = {.id = 249, .data = (double)23.881996}}, + {.next = &nodes5[141], .payload = {.id = 163, .data = (double)-7.387358}}, + {.next = &nodes5[177], .payload = {.id = 14, .data = (double)58.099617}}, + {.next = &nodes5[109], .payload = {.id = 4, .data = (double)64.180478}}, + {.next = &nodes5[100], .payload = {.id = 213, .data = (double)-26.841394}}, + {.next = &nodes5[170], .payload = {.id = 232, .data = (double)-52.285455}}, + {.next = &nodes5[25], .payload = {.id = 44, .data = (double)-22.075605}}, + {.next = &nodes5[13], .payload = {.id = 119, .data = (double)59.537104}}, + {.next = &nodes5[224], .payload = {.id = 129, .data = (double)-15.374409}}, + {.next = &nodes5[134], .payload = {.id = 142, .data = (double)18.763989}}, + {.next = &nodes5[54], .payload = {.id = 248, .data = (double)68.397043}}, + {.next = &nodes5[123], .payload = {.id = 148, .data = (double)22.53558}}, + {.next = &nodes5[104], .payload = {.id = 1, .data = (double)-58.568377}}, + {.next = &nodes5[42], .payload = {.id = 224, .data = (double)-8.427883}}, + {.next = &nodes5[197], .payload = {.id = 66, .data = (double)98.54604}}, + {.next = &nodes5[67], .payload = {.id = 223, .data = (double)-29.603015}}, + {.next = &nodes5[146], .payload = {.id = 95, .data = (double)-39.912943}}, + {.next = &nodes5[212], .payload = {.id = 9, .data = (double)69.888485}}, + {.next = &nodes5[115], .payload = {.id = 61, .data = (double)-97.531877}}, + {.next = &nodes5[223], .payload = {.id = 27, .data = (double)26.824589}}, + {.next = &nodes5[152], .payload = {.id = 99, .data = (double)-64.472546}}, + {.next = &nodes5[129], .payload = {.id = 206, .data = (double)-57.040779}}, + {.next = &nodes5[132], .payload = {.id = 90, .data = (double)-11.955416}}, + {.next = &nodes5[74], .payload = {.id = 98, .data = (double)-4.198052}}, + {.next = &nodes5[166], .payload = {.id = 221, .data = (double)-21.491199}}, + {.next = &nodes5[12], .payload = {.id = 39, .data = (double)-85.298663}}, + {.next = &nodes5[206], .payload = {.id = 107, .data = (double)-43.939971}}, + {.next = &nodes5[52], .payload = {.id = 50, .data = (double)-79.553717}}, + {.next = &nodes5[14], .payload = {.id = 110, .data = (double)86.413431}}, + {.next = &nodes5[182], .payload = {.id = 245, .data = (double)-66.626895}}, + {.next = NULL, .payload = {.id = 255, .data = (double)12.316415}}, + {.next = &nodes5[9], .payload = {.id = 47, .data = (double)88.592045}}, + {.next = &nodes5[58], .payload = {.id = 212, .data = (double)7.377802}}, + {.next = &nodes5[120], .payload = {.id = 158, .data = (double)49.370606}}, + {.next = &nodes5[85], .payload = {.id = 46, .data = (double)-81.695914}}, + {.next = &nodes5[194], .payload = {.id = 208, .data = (double)40.751949}}, + {.next = &nodes5[108], .payload = {.id = 11, .data = (double)8.112486}}, + {.next = &nodes5[250], .payload = {.id = 180, .data = (double)44.398789}}, + {.next = &nodes5[142], .payload = {.id = 102, .data = (double)46.974873}}, + {.next = &nodes5[79], .payload = {.id = 38, .data = (double)-50.710044}}, + {.next = &nodes5[253], .payload = {.id = 174, .data = (double)-30.33427}}, + {.next = &nodes5[61], .payload = {.id = 118, .data = (double)-58.070321}}, + {.next = &nodes5[196], .payload = {.id = 88, .data = (double)-24.022009}}, + {.next = &nodes5[205], .payload = {.id = 25, .data = (double)93.784105}}, + {.next = &nodes5[116], .payload = {.id = 127, .data = (double)-49.463663}}, + {.next = &nodes5[174], .payload = {.id = 135, .data = (double)84.699151}}, + {.next = &nodes5[249], .payload = {.id = 214, .data = (double)-60.585145}}, + {.next = &nodes5[211], .payload = {.id = 240, .data = (double)-2.665957}}, + {.next = &nodes5[245], .payload = {.id = 20, .data = (double)-53.571199}}, + {.next = &nodes5[184], .payload = {.id = 160, .data = (double)37.532882}}, + {.next = &nodes5[27], .payload = {.id = 2, .data = (double)-71.161688}}, + {.next = &nodes5[46], .payload = {.id = 58, .data = (double)19.384911}}, + {.next = &nodes5[198], .payload = {.id = 114, .data = (double)53.523582}}, + {.next = &nodes5[29], .payload = {.id = 80, .data = (double)44.17989}}, + {.next = &nodes5[34], .payload = {.id = 12, .data = (double)-23.230757}}, + {.next = &nodes5[110], .payload = {.id = 5, .data = (double)85.774988}}, + {.next = &nodes5[243], .payload = {.id = 6, .data = (double)-40.144622}}, + {.next = &nodes5[77], .payload = {.id = 97, .data = (double)39.058459}}, + {.next = &nodes5[96], .payload = {.id = 87, .data = (double)68.322677}}, + {.next = &nodes5[39], .payload = {.id = 121, .data = (double)-86.168266}}, + {.next = &nodes5[140], .payload = {.id = 172, .data = (double)66.263549}}, + {.next = &nodes5[201], .payload = {.id = 62, .data = (double)-17.237986}}, + {.next = &nodes5[62], .payload = {.id = 128, .data = (double)-69.171353}}, + {.next = &nodes5[234], .payload = {.id = 72, .data = (double)-46.318641}}, + {.next = &nodes5[63], .payload = {.id = 141, .data = (double)62.459395}}, + {.next = &nodes5[171], .payload = {.id = 234, .data = (double)-25.338786}}, + {.next = &nodes5[103], .payload = {.id = 159, .data = (double)11.598683}}, + {.next = &nodes5[43], .payload = {.id = 170, .data = (double)84.109509}}, + {.next = &nodes5[229], .payload = {.id = 189, .data = (double)85.984489}}, + {.next = &nodes5[189], .payload = {.id = 149, .data = (double)12.644058}}, + {.next = &nodes5[246], .payload = {.id = 41, .data = (double)-24.000001}}, + {.next = &nodes5[55], .payload = {.id = 162, .data = (double)-25.176086}}, + {.next = &nodes5[51], .payload = {.id = 153, .data = (double)-33.68066}}, + {.next = &nodes5[207], .payload = {.id = 54, .data = (double)2.48817}}, + {.next = &nodes5[210], .payload = {.id = 183, .data = (double)-91.063389}}, + {.next = &nodes5[89], .payload = {.id = 207, .data = (double)-44.331034}}, + {.next = &nodes5[92], .payload = {.id = 101, .data = (double)-36.172467}}, + {.next = &nodes5[5], .payload = {.id = 16, .data = (double)-84.314462}}, + {.next = &nodes5[49], .payload = {.id = 91, .data = (double)-13.876756}}, + {.next = &nodes5[59], .payload = {.id = 231, .data = (double)-37.362851}}, + {.next = &nodes5[244], .payload = {.id = 143, .data = (double)82.88025}}, + {.next = &nodes5[66], .payload = {.id = 0, .data = (double)-96.868381}}, + {.next = &nodes5[10], .payload = {.id = 83, .data = (double)-8.427673}}, + {.next = &nodes5[252], .payload = {.id = 124, .data = (double)34.59553}}, + {.next = &nodes5[231], .payload = {.id = 116, .data = (double)45.442673}}, + {.next = &nodes5[70], .payload = {.id = 94, .data = (double)18.878584}}, + {.next = &nodes5[94], .payload = {.id = 173, .data = (double)46.030145}}, + {.next = &nodes5[148], .payload = {.id = 164, .data = (double)35.911098}}, + {.next = &nodes5[254], .payload = {.id = 103, .data = (double)26.580492}}, + {.next = &nodes5[163], .payload = {.id = 23, .data = (double)22.773047}}, + {.next = &nodes5[102], .payload = {.id = 19, .data = (double)-80.462843}}, + {.next = &nodes5[165], .payload = {.id = 219, .data = (double)-37.319178}}, + {.next = &nodes5[111], .payload = {.id = 96, .data = (double)20.642254}}, + {.next = &nodes5[247], .payload = {.id = 251, .data = (double)90.36839}}, + {.next = &nodes5[53], .payload = {.id = 165, .data = (double)38.087461}}, + {.next = &nodes5[65], .payload = {.id = 147, .data = (double)-66.732301}}, + {.next = &nodes5[155], .payload = {.id = 36, .data = (double)54.433481}}, + {.next = &nodes5[64], .payload = {.id = 247, .data = (double)-62.580284}}, + {.next = &nodes5[130], .payload = {.id = 100, .data = (double)-20.352083}}, + {.next = &nodes5[40], .payload = {.id = 185, .data = (double)-95.482977}}, + {.next = &nodes5[121], .payload = {.id = 169, .data = (double)-40.913556}}, + {.next = &nodes5[93], .payload = {.id = 37, .data = (double)-40.924104}}, + {.next = &nodes5[16], .payload = {.id = 201, .data = (double)47.477674}}, + {.next = &nodes5[162], .payload = {.id = 33, .data = (double)-62.852431}}, + {.next = &nodes5[157], .payload = {.id = 32, .data = (double)-24.914601}}, + {.next = &nodes5[199], .payload = {.id = 237, .data = (double)19.285163}}, + {.next = &nodes5[50], .payload = {.id = 177, .data = (double)4.222966}}, + {.next = &nodes5[251], .payload = {.id = 105, .data = (double)56.394874}}, + {.next = &nodes5[180], .payload = {.id = 34, .data = (double)17.175024}}, + {.next = &nodes5[97], .payload = {.id = 24, .data = (double)19.121732}}, + {.next = &nodes5[11], .payload = {.id = 131, .data = (double)-10.186656}}, + {.next = &nodes5[78], .payload = {.id = 220, .data = (double)-22.272148}}, + {.next = &nodes5[69], .payload = {.id = 222, .data = (double)-77.153585}}, + {.next = &nodes5[154], .payload = {.id = 168, .data = (double)-3.445783}}, + {.next = &nodes5[101], .payload = {.id = 239, .data = (double)-15.392244}}, + {.next = &nodes5[136], .payload = {.id = 82, .data = (double)23.333758}}, + {.next = &nodes5[119], .payload = {.id = 233, .data = (double)-76.610219}}, + {.next = &nodes5[41], .payload = {.id = 235, .data = (double)-71.728291}}, + {.next = &nodes5[126], .payload = {.id = 152, .data = (double)93.362227}}, + {.next = &nodes5[117], .payload = {.id = 71, .data = (double)-46.216207}}, + {.next = &nodes5[235], .payload = {.id = 136, .data = (double)73.926745}}, + {.next = &nodes5[204], .payload = {.id = 187, .data = (double)-78.127464}}, + {.next = &nodes5[222], .payload = {.id = 145, .data = (double)-50.353806}}, + {.next = &nodes5[131], .payload = {.id = 15, .data = (double)37.862108}}, + {.next = &nodes5[91], .payload = {.id = 179, .data = (double)-80.475394}}, + {.next = &nodes5[191], .payload = {.id = 52, .data = (double)-13.804097}}, + {.next = &nodes5[150], .payload = {.id = 35, .data = (double)-23.985457}}, + {.next = &nodes5[87], .payload = {.id = 157, .data = (double)-55.599784}}, + {.next = &nodes5[151], .payload = {.id = 246, .data = (double)-42.233045}}, + {.next = &nodes5[82], .payload = {.id = 109, .data = (double)-26.996893}}, + {.next = &nodes5[125], .payload = {.id = 161, .data = (double)-55.793653}}, + {.next = &nodes5[181], .payload = {.id = 156, .data = (double)-80.278688}}, + {.next = &nodes5[147], .payload = {.id = 250, .data = (double)73.104446}}, + {.next = &nodes5[1], .payload = {.id = 227, .data = (double)60.122677}}, + {.next = &nodes5[160], .payload = {.id = 176, .data = (double)56.854}}, + {.next = &nodes5[20], .payload = {.id = 150, .data = (double)29.006241}}, + {.next = &nodes5[32], .payload = {.id = 204, .data = (double)-14.089432}}, + {.next = &nodes5[127], .payload = {.id = 53, .data = (double)11.397006}}, + {.next = &nodes5[72], .payload = {.id = 60, .data = (double)72.743635}}, + {.next = &nodes5[15], .payload = {.id = 30, .data = (double)-54.372322}}, + {.next = &nodes5[217], .payload = {.id = 209, .data = (double)59.20161}}, + {.next = &nodes5[143], .payload = {.id = 22, .data = (double)21.033749}}, + {.next = &nodes5[76], .payload = {.id = 89, .data = (double)72.439662}}, + {.next = &nodes5[220], .payload = {.id = 67, .data = (double)-51.451496}}, + {.next = &nodes5[138], .payload = {.id = 115, .data = (double)-94.616778}}, + {.next = &nodes5[168], .payload = {.id = 238, .data = (double)14.961209}}, + {.next = &nodes5[4], .payload = {.id = 76, .data = (double)-40.049549}}, + {.next = &nodes5[26], .payload = {.id = 63, .data = (double)55.833821}}, + {.next = &nodes5[213], .payload = {.id = 192, .data = (double)10.382058}}, + {.next = &nodes5[167], .payload = {.id = 167, .data = (double)99.540545}}, + {.next = &nodes5[122], .payload = {.id = 188, .data = (double)60.010025}}, + {.next = &nodes5[73], .payload = {.id = 26, .data = (double)-34.724671}}, + {.next = &nodes5[183], .payload = {.id = 108, .data = (double)57.173306}}, + {.next = &nodes5[240], .payload = {.id = 55, .data = (double)-79.341415}}, + {.next = &nodes5[145], .payload = {.id = 218, .data = (double)93.18328}}, + {.next = &nodes5[248], .payload = {.id = 112, .data = (double)99.452985}}, + {.next = &nodes5[153], .payload = {.id = 184, .data = (double)42.155798}}, + {.next = &nodes5[38], .payload = {.id = 241, .data = (double)7.475854}}, + {.next = &nodes5[90], .payload = {.id = 10, .data = (double)35.406993}}, + {.next = &nodes5[241], .payload = {.id = 193, .data = (double)-33.802069}}, + {.next = &nodes5[208], .payload = {.id = 217, .data = (double)-2.103204}}, + {.next = &nodes5[218], .payload = {.id = 138, .data = (double)-92.646967}}, + {.next = &nodes5[139], .payload = {.id = 93, .data = (double)30.207372}}, + {.next = &nodes5[18], .payload = {.id = 210, .data = (double)15.469581}}, + {.next = &nodes5[225], .payload = {.id = 139, .data = (double)93.685608}}, + {.next = &nodes5[232], .payload = {.id = 198, .data = (double)-62.722615}}, + {.next = &nodes5[36], .payload = {.id = 68, .data = (double)4.220906}}, + {.next = &nodes5[193], .payload = {.id = 29, .data = (double)-9.889961}}, + {.next = &nodes5[149], .payload = {.id = 146, .data = (double)32.938777}}, + {.next = &nodes5[221], .payload = {.id = 28, .data = (double)56.709628}}, + {.next = &nodes5[164], .payload = {.id = 130, .data = (double)-24.601836}}, + {.next = &nodes5[118], .payload = {.id = 140, .data = (double)40.326857}}, + {.next = &nodes5[98], .payload = {.id = 126, .data = (double)-39.433471}}, + {.next = &nodes5[228], .payload = {.id = 196, .data = (double)59.551158}}, + {.next = &nodes5[219], .payload = {.id = 197, .data = (double)25.952064}}, + {.next = &nodes5[44], .payload = {.id = 190, .data = (double)48.097897}}, + {.next = &nodes5[83], .payload = {.id = 244, .data = (double)-65.35304}}, + {.next = &nodes5[95], .payload = {.id = 117, .data = (double)88.594983}}, + {.next = &nodes5[21], .payload = {.id = 199, .data = (double)31.461582}}, + {.next = &nodes5[60], .payload = {.id = 43, .data = (double)-69.144622}}, + {.next = &nodes5[239], .payload = {.id = 73, .data = (double)-70.813036}}, + {.next = &nodes5[215], .payload = {.id = 137, .data = (double)-16.339862}}, + {.next = &nodes5[105], .payload = {.id = 57, .data = (double)10.843961}}, + {.next = &nodes5[173], .payload = {.id = 70, .data = (double)-66.099651}}, + {.next = &nodes5[71], .payload = {.id = 8, .data = (double)13.339184}}, + {.next = &nodes5[22], .payload = {.id = 74, .data = (double)-66.55852}}, + {.next = &nodes5[236], .payload = {.id = 56, .data = (double)-82.076232}}, + {.next = &nodes5[35], .payload = {.id = 194, .data = (double)-14.726123}}, + {.next = &nodes5[190], .payload = {.id = 203, .data = (double)-10.084998}}, + {.next = &nodes5[238], .payload = {.id = 7, .data = (double)12.79164}}, + {.next = &nodes5[176], .payload = {.id = 144, .data = (double)-78.126115}}, + {.next = &nodes5[195], .payload = {.id = 21, .data = (double)-84.796351}}, + {.next = &nodes5[233], .payload = {.id = 42, .data = (double)56.778056}}, + {.next = &nodes5[255], .payload = {.id = 252, .data = (double)-3.078216}}, + {.next = &nodes5[106], .payload = {.id = 113, .data = (double)-64.014557}}, + {.next = &nodes5[8], .payload = {.id = 215, .data = (double)-77.209006}}, + {.next = &nodes5[33], .payload = {.id = 181, .data = (double)-9.510561}}, + {.next = &nodes5[80], .payload = {.id = 106, .data = (double)-34.822753}}, + {.next = &nodes5[226], .payload = {.id = 125, .data = (double)-72.164175}}, + {.next = &nodes5[188], .payload = {.id = 175, .data = (double)-31.386664}}, + {.next = &nodes5[161], .payload = {.id = 104, .data = (double)93.552617}}, + {.next = &nodes5[28], .payload = {.id = 253, .data = (double)-60.974302}}, +}; + +node_t nodes6[] = { + {.next = &nodes6[184], .payload = {.id = 22, .data = (double)-47.562945}}, + {.next = &nodes6[12], .payload = {.id = 173, .data = (double)-59.457475}}, + {.next = &nodes6[226], .payload = {.id = 58, .data = (double)40.299922}}, + {.next = &nodes6[224], .payload = {.id = 24, .data = (double)-87.906228}}, + {.next = &nodes6[70], .payload = {.id = 106, .data = (double)0.408189}}, + {.next = &nodes6[160], .payload = {.id = 17, .data = (double)52.545188}}, + {.next = &nodes6[19], .payload = {.id = 189, .data = (double)39.375597}}, + {.next = &nodes6[220], .payload = {.id = 67, .data = (double)-46.247103}}, + {.next = &nodes6[245], .payload = {.id = 98, .data = (double)48.133166}}, + {.next = NULL, .payload = {.id = 255, .data = (double)97.880723}}, + {.next = &nodes6[7], .payload = {.id = 66, .data = (double)56.224796}}, + {.next = &nodes6[211], .payload = {.id = 203, .data = (double)49.615689}}, + {.next = &nodes6[128], .payload = {.id = 174, .data = (double)55.987396}}, + {.next = &nodes6[126], .payload = {.id = 29, .data = (double)-16.913601}}, + {.next = &nodes6[232], .payload = {.id = 235, .data = (double)-65.438558}}, + {.next = &nodes6[194], .payload = {.id = 247, .data = (double)-44.044803}}, + {.next = &nodes6[68], .payload = {.id = 116, .data = (double)-34.539816}}, + {.next = &nodes6[222], .payload = {.id = 167, .data = (double)60.163364}}, + {.next = &nodes6[29], .payload = {.id = 141, .data = (double)45.443008}}, + {.next = &nodes6[91], .payload = {.id = 190, .data = (double)-91.934038}}, + {.next = &nodes6[119], .payload = {.id = 104, .data = (double)-84.422586}}, + {.next = &nodes6[225], .payload = {.id = 39, .data = (double)7.278035}}, + {.next = &nodes6[154], .payload = {.id = 76, .data = (double)-84.585994}}, + {.next = &nodes6[10], .payload = {.id = 65, .data = (double)-74.613879}}, + {.next = &nodes6[209], .payload = {.id = 89, .data = (double)72.585699}}, + {.next = &nodes6[42], .payload = {.id = 159, .data = (double)63.992578}}, + {.next = &nodes6[173], .payload = {.id = 50, .data = (double)-13.103282}}, + {.next = &nodes6[18], .payload = {.id = 140, .data = (double)69.801198}}, + {.next = &nodes6[32], .payload = {.id = 181, .data = (double)92.926944}}, + {.next = &nodes6[146], .payload = {.id = 142, .data = (double)-79.210196}}, + {.next = &nodes6[20], .payload = {.id = 103, .data = (double)-45.748408}}, + {.next = &nodes6[80], .payload = {.id = 184, .data = (double)-46.998415}}, + {.next = &nodes6[255], .payload = {.id = 182, .data = (double)-58.472755}}, + {.next = &nodes6[86], .payload = {.id = 220, .data = (double)-87.105593}}, + {.next = &nodes6[50], .payload = {.id = 108, .data = (double)-64.13113}}, + {.next = &nodes6[234], .payload = {.id = 70, .data = (double)-94.12875}}, + {.next = &nodes6[41], .payload = {.id = 129, .data = (double)52.096444}}, + {.next = &nodes6[174], .payload = {.id = 156, .data = (double)-83.019516}}, + {.next = &nodes6[25], .payload = {.id = 158, .data = (double)-73.29723}}, + {.next = &nodes6[63], .payload = {.id = 54, .data = (double)48.338702}}, + {.next = &nodes6[92], .payload = {.id = 222, .data = (double)-11.313735}}, + {.next = &nodes6[109], .payload = {.id = 130, .data = (double)-50.974625}}, + {.next = &nodes6[115], .payload = {.id = 160, .data = (double)-85.033903}}, + {.next = &nodes6[96], .payload = {.id = 114, .data = (double)-43.538626}}, + {.next = &nodes6[5], .payload = {.id = 16, .data = (double)36.58841}}, + {.next = &nodes6[204], .payload = {.id = 240, .data = (double)-93.070111}}, + {.next = &nodes6[191], .payload = {.id = 47, .data = (double)69.293623}}, + {.next = &nodes6[83], .payload = {.id = 162, .data = (double)-13.003424}}, + {.next = &nodes6[193], .payload = {.id = 35, .data = (double)-38.018623}}, + {.next = &nodes6[90], .payload = {.id = 118, .data = (double)-98.406165}}, + {.next = &nodes6[75], .payload = {.id = 109, .data = (double)60.867604}}, + {.next = &nodes6[110], .payload = {.id = 171, .data = (double)-45.608826}}, + {.next = &nodes6[140], .payload = {.id = 74, .data = (double)42.46465}}, + {.next = &nodes6[14], .payload = {.id = 234, .data = (double)36.642583}}, + {.next = &nodes6[148], .payload = {.id = 210, .data = (double)96.513447}}, + {.next = &nodes6[23], .payload = {.id = 64, .data = (double)-66.607409}}, + {.next = &nodes6[223], .payload = {.id = 62, .data = (double)56.59742}}, + {.next = &nodes6[163], .payload = {.id = 27, .data = (double)25.714139}}, + {.next = &nodes6[8], .payload = {.id = 97, .data = (double)82.789534}}, + {.next = &nodes6[21], .payload = {.id = 38, .data = (double)61.612016}}, + {.next = &nodes6[120], .payload = {.id = 10, .data = (double)97.376507}}, + {.next = &nodes6[113], .payload = {.id = 41, .data = (double)26.858849}}, + {.next = &nodes6[236], .payload = {.id = 206, .data = (double)60.779351}}, + {.next = &nodes6[239], .payload = {.id = 55, .data = (double)48.131636}}, + {.next = &nodes6[79], .payload = {.id = 3, .data = (double)90.934302}}, + {.next = &nodes6[37], .payload = {.id = 155, .data = (double)94.910958}}, + {.next = &nodes6[85], .payload = {.id = 72, .data = (double)-45.603881}}, + {.next = &nodes6[170], .payload = {.id = 231, .data = (double)64.33708}}, + {.next = &nodes6[49], .payload = {.id = 117, .data = (double)10.618279}}, + {.next = &nodes6[181], .payload = {.id = 153, .data = (double)40.169382}}, + {.next = &nodes6[34], .payload = {.id = 107, .data = (double)80.388202}}, + {.next = &nodes6[159], .payload = {.id = 94, .data = (double)86.232015}}, + {.next = &nodes6[208], .payload = {.id = 43, .data = (double)36.211137}}, + {.next = &nodes6[241], .payload = {.id = 80, .data = (double)13.377226}}, + {.next = &nodes6[30], .payload = {.id = 102, .data = (double)44.057584}}, + {.next = &nodes6[150], .payload = {.id = 110, .data = (double)96.282773}}, + {.next = &nodes6[118], .payload = {.id = 227, .data = (double)-91.460736}}, + {.next = &nodes6[64], .payload = {.id = 2, .data = (double)79.582512}}, + {.next = &nodes6[17], .payload = {.id = 166, .data = (double)-36.998217}}, + {.next = &nodes6[179], .payload = {.id = 4, .data = (double)-1.022456}}, + {.next = &nodes6[105], .payload = {.id = 185, .data = (double)-76.017289}}, + {.next = &nodes6[121], .payload = {.id = 112, .data = (double)-86.214712}}, + {.next = &nodes6[123], .payload = {.id = 20, .data = (double)-96.66212}}, + {.next = &nodes6[129], .payload = {.id = 163, .data = (double)92.843655}}, + {.next = &nodes6[175], .payload = {.id = 83, .data = (double)-79.419017}}, + {.next = &nodes6[52], .payload = {.id = 73, .data = (double)-87.225602}}, + {.next = &nodes6[40], .payload = {.id = 221, .data = (double)80.499216}}, + {.next = &nodes6[102], .payload = {.id = 12, .data = (double)-73.603424}}, + {.next = &nodes6[183], .payload = {.id = 214, .data = (double)26.05951}}, + {.next = &nodes6[210], .payload = {.id = 244, .data = (double)-17.601559}}, + {.next = &nodes6[231], .payload = {.id = 119, .data = (double)-59.865769}}, + {.next = &nodes6[112], .payload = {.id = 191, .data = (double)67.18495}}, + {.next = &nodes6[156], .payload = {.id = 223, .data = (double)-74.24169}}, + {.next = &nodes6[95], .payload = {.id = 52, .data = (double)21.766481}}, + {.next = &nodes6[251], .payload = {.id = 123, .data = (double)-7.214662}}, + {.next = &nodes6[39], .payload = {.id = 53, .data = (double)-38.141987}}, + {.next = &nodes6[16], .payload = {.id = 115, .data = (double)68.969301}}, + {.next = &nodes6[122], .payload = {.id = 132, .data = (double)-17.992778}}, + {.next = &nodes6[26], .payload = {.id = 49, .data = (double)-82.75744}}, + {.next = &nodes6[134], .payload = {.id = 242, .data = (double)-50.843044}}, + {.next = &nodes6[189], .payload = {.id = 137, .data = (double)90.198052}}, + {.next = &nodes6[161], .payload = {.id = 92, .data = (double)-23.404105}}, + {.next = &nodes6[233], .payload = {.id = 13, .data = (double)72.162801}}, + {.next = &nodes6[33], .payload = {.id = 219, .data = (double)-95.639963}}, + {.next = &nodes6[177], .payload = {.id = 253, .data = (double)60.433617}}, + {.next = &nodes6[147], .payload = {.id = 186, .data = (double)-68.476925}}, + {.next = &nodes6[67], .payload = {.id = 230, .data = (double)14.77684}}, + {.next = &nodes6[149], .payload = {.id = 250, .data = (double)76.930503}}, + {.next = &nodes6[139], .payload = {.id = 31, .data = (double)-83.514438}}, + {.next = &nodes6[97], .payload = {.id = 131, .data = (double)-98.724423}}, + {.next = &nodes6[1], .payload = {.id = 172, .data = (double)-85.062513}}, + {.next = &nodes6[77], .payload = {.id = 1, .data = (double)-89.086174}}, + {.next = &nodes6[164], .payload = {.id = 192, .data = (double)-34.441268}}, + {.next = &nodes6[72], .payload = {.id = 42, .data = (double)66.905294}}, + {.next = &nodes6[254], .payload = {.id = 121, .data = (double)-39.218139}}, + {.next = &nodes6[47], .payload = {.id = 161, .data = (double)13.564146}}, + {.next = &nodes6[202], .payload = {.id = 177, .data = (double)-67.125004}}, + {.next = &nodes6[155], .payload = {.id = 85, .data = (double)44.555675}}, + {.next = &nodes6[237], .payload = {.id = 228, .data = (double)-7.801016}}, + {.next = &nodes6[4], .payload = {.id = 105, .data = (double)-25.438367}}, + {.next = &nodes6[87], .payload = {.id = 11, .data = (double)86.78488}}, + {.next = &nodes6[43], .payload = {.id = 113, .data = (double)-6.981164}}, + {.next = &nodes6[178], .payload = {.id = 133, .data = (double)-53.400452}}, + {.next = &nodes6[0], .payload = {.id = 21, .data = (double)-86.493486}}, + {.next = &nodes6[104], .payload = {.id = 252, .data = (double)26.150878}}, + {.next = &nodes6[212], .payload = {.id = 146, .data = (double)-88.020985}}, + {.next = &nodes6[108], .payload = {.id = 30, .data = (double)40.362128}}, + {.next = &nodes6[82], .payload = {.id = 19, .data = (double)54.07341}}, + {.next = &nodes6[137], .payload = {.id = 175, .data = (double)16.941607}}, + {.next = &nodes6[157], .payload = {.id = 164, .data = (double)-52.645653}}, + {.next = &nodes6[247], .payload = {.id = 127, .data = (double)-60.915515}}, + {.next = &nodes6[57], .payload = {.id = 26, .data = (double)1.322121}}, + {.next = &nodes6[235], .payload = {.id = 198, .data = (double)-47.966641}}, + {.next = &nodes6[227], .payload = {.id = 148, .data = (double)42.330495}}, + {.next = &nodes6[89], .payload = {.id = 243, .data = (double)-40.978967}}, + {.next = &nodes6[185], .payload = {.id = 8, .data = (double)5.6573}}, + {.next = &nodes6[158], .payload = {.id = 100, .data = (double)-35.639597}}, + {.next = &nodes6[116], .payload = {.id = 176, .data = (double)-68.91789}}, + {.next = &nodes6[51], .payload = {.id = 170, .data = (double)-36.388456}}, + {.next = &nodes6[172], .payload = {.id = 32, .data = (double)7.312963}}, + {.next = &nodes6[22], .payload = {.id = 75, .data = (double)15.330335}}, + {.next = &nodes6[188], .payload = {.id = 78, .data = (double)-27.975221}}, + {.next = &nodes6[58], .payload = {.id = 96, .data = (double)10.572958}}, + {.next = &nodes6[180], .payload = {.id = 212, .data = (double)64.734683}}, + {.next = &nodes6[2], .payload = {.id = 57, .data = (double)41.580121}}, + {.next = &nodes6[217], .payload = {.id = 201, .data = (double)-19.121555}}, + {.next = &nodes6[248], .payload = {.id = 143, .data = (double)5.962898}}, + {.next = &nodes6[216], .payload = {.id = 187, .data = (double)37.210969}}, + {.next = &nodes6[143], .payload = {.id = 211, .data = (double)-73.856952}}, + {.next = &nodes6[124], .payload = {.id = 251, .data = (double)5.162812}}, + {.next = &nodes6[81], .payload = {.id = 111, .data = (double)90.815881}}, + {.next = &nodes6[182], .payload = {.id = 225, .data = (double)65.871235}}, + {.next = &nodes6[48], .payload = {.id = 34, .data = (double)-44.506453}}, + {.next = &nodes6[138], .payload = {.id = 169, .data = (double)47.070574}}, + {.next = &nodes6[141], .payload = {.id = 77, .data = (double)-8.960444}}, + {.next = &nodes6[171], .payload = {.id = 86, .data = (double)-54.319115}}, + {.next = &nodes6[151], .payload = {.id = 224, .data = (double)81.015594}}, + {.next = &nodes6[78], .payload = {.id = 165, .data = (double)-47.801812}}, + {.next = &nodes6[74], .payload = {.id = 101, .data = (double)-16.74868}}, + {.next = &nodes6[142], .payload = {.id = 95, .data = (double)71.49704}}, + {.next = &nodes6[127], .payload = {.id = 18, .data = (double)90.890597}}, + {.next = &nodes6[71], .payload = {.id = 93, .data = (double)-69.983066}}, + {.next = &nodes6[187], .payload = {.id = 217, .data = (double)-48.23587}}, + {.next = &nodes6[13], .payload = {.id = 28, .data = (double)0.209793}}, + {.next = &nodes6[192], .payload = {.id = 193, .data = (double)-81.757419}}, + {.next = &nodes6[205], .payload = {.id = 150, .data = (double)84.254881}}, + {.next = &nodes6[59], .payload = {.id = 37, .data = (double)-59.360501}}, + {.next = &nodes6[132], .payload = {.id = 197, .data = (double)35.436675}}, + {.next = &nodes6[44], .payload = {.id = 15, .data = (double)-26.917507}}, + {.next = &nodes6[15], .payload = {.id = 246, .data = (double)-87.804186}}, + {.next = &nodes6[249], .payload = {.id = 232, .data = (double)-21.000262}}, + {.next = &nodes6[250], .payload = {.id = 87, .data = (double)1.764977}}, + {.next = &nodes6[152], .payload = {.id = 33, .data = (double)23.209411}}, + {.next = &nodes6[93], .payload = {.id = 51, .data = (double)-9.325632}}, + {.next = &nodes6[38], .payload = {.id = 157, .data = (double)-80.884599}}, + {.next = &nodes6[117], .payload = {.id = 84, .data = (double)14.782461}}, + {.next = &nodes6[111], .payload = {.id = 0, .data = (double)-40.89159}}, + {.next = &nodes6[9], .payload = {.id = 254, .data = (double)58.969249}}, + {.next = &nodes6[230], .payload = {.id = 134, .data = (double)-30.71526}}, + {.next = &nodes6[242], .payload = {.id = 5, .data = (double)-77.451267}}, + {.next = &nodes6[88], .payload = {.id = 213, .data = (double)-25.552051}}, + {.next = &nodes6[65], .payload = {.id = 154, .data = (double)-25.501605}}, + {.next = &nodes6[76], .payload = {.id = 226, .data = (double)-33.690022}}, + {.next = &nodes6[203], .payload = {.id = 215, .data = (double)28.937003}}, + {.next = &nodes6[3], .payload = {.id = 23, .data = (double)-92.034628}}, + {.next = &nodes6[60], .payload = {.id = 9, .data = (double)95.53939}}, + {.next = &nodes6[190], .payload = {.id = 125, .data = (double)-1.327865}}, + {.next = &nodes6[103], .payload = {.id = 218, .data = (double)62.549418}}, + {.next = &nodes6[73], .payload = {.id = 79, .data = (double)-0.077999}}, + {.next = &nodes6[253], .payload = {.id = 138, .data = (double)-99.707592}}, + {.next = &nodes6[130], .payload = {.id = 126, .data = (double)54.522653}}, + {.next = &nodes6[98], .payload = {.id = 48, .data = (double)-88.418811}}, + {.next = &nodes6[214], .payload = {.id = 194, .data = (double)-50.356242}}, + {.next = &nodes6[166], .payload = {.id = 36, .data = (double)2.26094}}, + {.next = &nodes6[215], .payload = {.id = 248, .data = (double)-72.552797}}, + {.next = &nodes6[125], .payload = {.id = 145, .data = (double)-1.594225}}, + {.next = &nodes6[54], .payload = {.id = 209, .data = (double)66.074466}}, + {.next = &nodes6[198], .payload = {.id = 179, .data = (double)-18.69749}}, + {.next = &nodes6[28], .payload = {.id = 180, .data = (double)7.18491}}, + {.next = &nodes6[213], .payload = {.id = 238, .data = (double)-44.029089}}, + {.next = &nodes6[62], .payload = {.id = 205, .data = (double)-7.59135}}, + {.next = &nodes6[199], .payload = {.id = 237, .data = (double)-62.569777}}, + {.next = &nodes6[197], .payload = {.id = 178, .data = (double)-6.788978}}, + {.next = &nodes6[162], .payload = {.id = 216, .data = (double)16.46476}}, + {.next = &nodes6[99], .payload = {.id = 241, .data = (double)23.83531}}, + {.next = &nodes6[240], .payload = {.id = 151, .data = (double)79.457494}}, + {.next = &nodes6[221], .payload = {.id = 60, .data = (double)90.60324}}, + {.next = &nodes6[243], .payload = {.id = 45, .data = (double)39.735176}}, + {.next = &nodes6[207], .payload = {.id = 44, .data = (double)-86.776983}}, + {.next = &nodes6[229], .payload = {.id = 90, .data = (double)-51.08971}}, + {.next = &nodes6[169], .payload = {.id = 245, .data = (double)10.137733}}, + {.next = &nodes6[200], .payload = {.id = 204, .data = (double)-50.029474}}, + {.next = &nodes6[133], .payload = {.id = 147, .data = (double)99.391854}}, + {.next = &nodes6[45], .payload = {.id = 239, .data = (double)76.68476}}, + {.next = &nodes6[228], .payload = {.id = 195, .data = (double)-28.851449}}, + {.next = &nodes6[107], .payload = {.id = 249, .data = (double)-60.108439}}, + {.next = &nodes6[6], .payload = {.id = 188, .data = (double)65.277338}}, + {.next = &nodes6[11], .payload = {.id = 202, .data = (double)-9.559766}}, + {.next = &nodes6[196], .payload = {.id = 208, .data = (double)-97.608615}}, + {.next = &nodes6[100], .payload = {.id = 136, .data = (double)75.439723}}, + {.next = &nodes6[244], .payload = {.id = 68, .data = (double)77.282952}}, + {.next = &nodes6[56], .payload = {.id = 61, .data = (double)4.601073}}, + {.next = &nodes6[153], .payload = {.id = 168, .data = (double)40.145121}}, + {.next = &nodes6[55], .payload = {.id = 63, .data = (double)44.153104}}, + {.next = &nodes6[131], .payload = {.id = 25, .data = (double)57.858}}, + {.next = &nodes6[61], .payload = {.id = 40, .data = (double)-21.853699}}, + {.next = &nodes6[206], .payload = {.id = 59, .data = (double)-67.233474}}, + {.next = &nodes6[165], .payload = {.id = 149, .data = (double)-81.394672}}, + {.next = &nodes6[167], .payload = {.id = 196, .data = (double)2.691935}}, + {.next = &nodes6[101], .payload = {.id = 91, .data = (double)-5.647082}}, + {.next = &nodes6[219], .payload = {.id = 135, .data = (double)67.914801}}, + {.next = &nodes6[114], .payload = {.id = 120, .data = (double)12.761348}}, + {.next = &nodes6[201], .payload = {.id = 236, .data = (double)-57.056779}}, + {.next = &nodes6[168], .payload = {.id = 14, .data = (double)13.676078}}, + {.next = &nodes6[66], .payload = {.id = 71, .data = (double)61.421569}}, + {.next = &nodes6[252], .payload = {.id = 199, .data = (double)98.135324}}, + {.next = &nodes6[218], .payload = {.id = 207, .data = (double)-72.041392}}, + {.next = &nodes6[106], .payload = {.id = 229, .data = (double)-66.402158}}, + {.next = &nodes6[135], .payload = {.id = 7, .data = (double)18.785954}}, + {.next = &nodes6[144], .payload = {.id = 56, .data = (double)-76.111399}}, + {.next = &nodes6[69], .payload = {.id = 152, .data = (double)3.951844}}, + {.next = &nodes6[246], .payload = {.id = 81, .data = (double)-26.462444}}, + {.next = &nodes6[238], .payload = {.id = 6, .data = (double)-0.083492}}, + {.next = &nodes6[46], .payload = {.id = 46, .data = (double)45.991675}}, + {.next = &nodes6[35], .payload = {.id = 69, .data = (double)54.286058}}, + {.next = &nodes6[136], .payload = {.id = 99, .data = (double)-16.126139}}, + {.next = &nodes6[84], .payload = {.id = 82, .data = (double)-48.976784}}, + {.next = &nodes6[36], .payload = {.id = 128, .data = (double)80.088659}}, + {.next = &nodes6[195], .payload = {.id = 144, .data = (double)-52.366481}}, + {.next = &nodes6[53], .payload = {.id = 233, .data = (double)-94.103541}}, + {.next = &nodes6[24], .payload = {.id = 88, .data = (double)-91.192419}}, + {.next = &nodes6[186], .payload = {.id = 124, .data = (double)18.338187}}, + {.next = &nodes6[145], .payload = {.id = 200, .data = (double)-93.783581}}, + {.next = &nodes6[27], .payload = {.id = 139, .data = (double)31.46077}}, + {.next = &nodes6[94], .payload = {.id = 122, .data = (double)24.543505}}, + {.next = &nodes6[31], .payload = {.id = 183, .data = (double)-38.338456}}, +}; + +node_t nodes7[] = { + {.next = &nodes7[151], .payload = {.id = 169, .data = (double)-20.569492}}, + {.next = &nodes7[252], .payload = {.id = 13, .data = (double)94.141107}}, + {.next = &nodes7[116], .payload = {.id = 206, .data = (double)-55.527361}}, + {.next = &nodes7[147], .payload = {.id = 38, .data = (double)-74.7628}}, + {.next = &nodes7[70], .payload = {.id = 101, .data = (double)-62.412862}}, + {.next = &nodes7[10], .payload = {.id = 179, .data = (double)-87.232589}}, + {.next = &nodes7[192], .payload = {.id = 132, .data = (double)74.096154}}, + {.next = &nodes7[222], .payload = {.id = 94, .data = (double)-73.122896}}, + {.next = &nodes7[134], .payload = {.id = 71, .data = (double)-23.391305}}, + {.next = &nodes7[240], .payload = {.id = 200, .data = (double)-22.345016}}, + {.next = &nodes7[114], .payload = {.id = 180, .data = (double)97.672193}}, + {.next = &nodes7[198], .payload = {.id = 15, .data = (double)10.720381}}, + {.next = &nodes7[171], .payload = {.id = 244, .data = (double)70.847954}}, + {.next = &nodes7[210], .payload = {.id = 62, .data = (double)51.675478}}, + {.next = &nodes7[27], .payload = {.id = 138, .data = (double)37.770108}}, + {.next = &nodes7[179], .payload = {.id = 214, .data = (double)75.298957}}, + {.next = &nodes7[97], .payload = {.id = 202, .data = (double)41.613792}}, + {.next = &nodes7[138], .payload = {.id = 142, .data = (double)14.451612}}, + {.next = &nodes7[211], .payload = {.id = 222, .data = (double)35.942474}}, + {.next = &nodes7[79], .payload = {.id = 184, .data = (double)42.218755}}, + {.next = &nodes7[103], .payload = {.id = 18, .data = (double)-16.273585}}, + {.next = &nodes7[118], .payload = {.id = 246, .data = (double)-59.940682}}, + {.next = &nodes7[196], .payload = {.id = 75, .data = (double)-44.917172}}, + {.next = &nodes7[140], .payload = {.id = 68, .data = (double)7.126696}}, + {.next = &nodes7[153], .payload = {.id = 112, .data = (double)-72.870036}}, + {.next = &nodes7[84], .payload = {.id = 182, .data = (double)72.29832}}, + {.next = &nodes7[102], .payload = {.id = 229, .data = (double)-33.736573}}, + {.next = &nodes7[150], .payload = {.id = 139, .data = (double)-42.986125}}, + {.next = &nodes7[124], .payload = {.id = 145, .data = (double)29.475978}}, + {.next = &nodes7[78], .payload = {.id = 104, .data = (double)48.18896}}, + {.next = &nodes7[128], .payload = {.id = 66, .data = (double)-79.801911}}, + {.next = &nodes7[130], .payload = {.id = 49, .data = (double)-22.380169}}, + {.next = &nodes7[227], .payload = {.id = 250, .data = (double)-8.485713}}, + {.next = &nodes7[191], .payload = {.id = 151, .data = (double)53.514546}}, + {.next = &nodes7[173], .payload = {.id = 239, .data = (double)0.095475}}, + {.next = &nodes7[168], .payload = {.id = 165, .data = (double)-49.600258}}, + {.next = &nodes7[28], .payload = {.id = 144, .data = (double)71.422237}}, + {.next = &nodes7[53], .payload = {.id = 189, .data = (double)79.937409}}, + {.next = &nodes7[115], .payload = {.id = 60, .data = (double)-70.360052}}, + {.next = &nodes7[148], .payload = {.id = 120, .data = (double)-8.710267}}, + {.next = &nodes7[155], .payload = {.id = 28, .data = (double)80.091012}}, + {.next = &nodes7[123], .payload = {.id = 36, .data = (double)94.432976}}, + {.next = &nodes7[177], .payload = {.id = 208, .data = (double)56.979411}}, + {.next = &nodes7[110], .payload = {.id = 84, .data = (double)84.166997}}, + {.next = &nodes7[72], .payload = {.id = 55, .data = (double)57.310128}}, + {.next = &nodes7[104], .payload = {.id = 118, .data = (double)67.395336}}, + {.next = &nodes7[241], .payload = {.id = 124, .data = (double)64.701258}}, + {.next = &nodes7[18], .payload = {.id = 221, .data = (double)-63.386329}}, + {.next = &nodes7[43], .payload = {.id = 83, .data = (double)49.149964}}, + {.next = &nodes7[255], .payload = {.id = 89, .data = (double)-43.930669}}, + {.next = &nodes7[226], .payload = {.id = 8, .data = (double)50.447028}}, + {.next = &nodes7[50], .payload = {.id = 7, .data = (double)-87.672126}}, + {.next = &nodes7[197], .payload = {.id = 10, .data = (double)-82.858538}}, + {.next = &nodes7[160], .payload = {.id = 190, .data = (double)61.085965}}, + {.next = &nodes7[199], .payload = {.id = 41, .data = (double)-12.921351}}, + {.next = &nodes7[45], .payload = {.id = 117, .data = (double)66.585987}}, + {.next = &nodes7[201], .payload = {.id = 149, .data = (double)-95.989529}}, + {.next = &nodes7[107], .payload = {.id = 153, .data = (double)82.303088}}, + {.next = &nodes7[220], .payload = {.id = 81, .data = (double)-33.701185}}, + {.next = &nodes7[126], .payload = {.id = 44, .data = (double)66.821624}}, + {.next = &nodes7[142], .payload = {.id = 24, .data = (double)-84.20899}}, + {.next = &nodes7[120], .payload = {.id = 248, .data = (double)13.880718}}, + {.next = &nodes7[109], .payload = {.id = 196, .data = (double)31.080114}}, + {.next = &nodes7[218], .payload = {.id = 212, .data = (double)69.083849}}, + {.next = &nodes7[4], .payload = {.id = 100, .data = (double)29.110962}}, + {.next = &nodes7[6], .payload = {.id = 131, .data = (double)-64.483261}}, + {.next = &nodes7[125], .payload = {.id = 254, .data = (double)-2.483831}}, + {.next = &nodes7[60], .payload = {.id = 23, .data = (double)-4.747544}}, + {.next = &nodes7[127], .payload = {.id = 171, .data = (double)2.302743}}, + {.next = &nodes7[216], .payload = {.id = 47, .data = (double)82.834787}}, + {.next = &nodes7[231], .payload = {.id = 102, .data = (double)-57.7219}}, + {.next = &nodes7[94], .payload = {.id = 219, .data = (double)61.668774}}, + {.next = &nodes7[209], .payload = {.id = 56, .data = (double)24.611586}}, + {.next = &nodes7[131], .payload = {.id = 126, .data = (double)27.081962}}, + {.next = &nodes7[250], .payload = {.id = 114, .data = (double)75.866518}}, + {.next = &nodes7[237], .payload = {.id = 21, .data = (double)-5.035122}}, + {.next = &nodes7[20], .payload = {.id = 17, .data = (double)63.681043}}, + {.next = &nodes7[37], .payload = {.id = 188, .data = (double)53.094878}}, + {.next = &nodes7[154], .payload = {.id = 105, .data = (double)51.898659}}, + {.next = &nodes7[193], .payload = {.id = 185, .data = (double)78.47476}}, + {.next = &nodes7[232], .payload = {.id = 108, .data = (double)3.053941}}, + {.next = &nodes7[63], .payload = {.id = 211, .data = (double)1.462971}}, + {.next = &nodes7[239], .payload = {.id = 242, .data = (double)-40.328849}}, + {.next = &nodes7[69], .payload = {.id = 46, .data = (double)82.160897}}, + {.next = &nodes7[19], .payload = {.id = 183, .data = (double)-47.770618}}, + {.next = &nodes7[56], .payload = {.id = 148, .data = (double)-18.098561}}, + {.next = &nodes7[181], .payload = {.id = 237, .data = (double)-85.756853}}, + {.next = &nodes7[0], .payload = {.id = 168, .data = (double)64.862164}}, + {.next = &nodes7[51], .payload = {.id = 6, .data = (double)-46.287601}}, + {.next = &nodes7[38], .payload = {.id = 59, .data = (double)-17.11152}}, + {.next = &nodes7[208], .payload = {.id = 176, .data = (double)21.810021}}, + {.next = &nodes7[46], .payload = {.id = 123, .data = (double)-45.2045}}, + {.next = &nodes7[5], .payload = {.id = 178, .data = (double)-78.379094}}, + {.next = &nodes7[17], .payload = {.id = 141, .data = (double)-67.418519}}, + {.next = &nodes7[47], .payload = {.id = 220, .data = (double)52.583644}}, + {.next = &nodes7[236], .payload = {.id = 32, .data = (double)-75.943625}}, + {.next = &nodes7[235], .payload = {.id = 156, .data = (double)-98.307255}}, + {.next = &nodes7[137], .payload = {.id = 203, .data = (double)14.408487}}, + {.next = &nodes7[169], .payload = {.id = 92, .data = (double)-80.356522}}, + {.next = &nodes7[87], .payload = {.id = 167, .data = (double)35.439231}}, + {.next = &nodes7[35], .payload = {.id = 164, .data = (double)-30.25816}}, + {.next = &nodes7[64], .payload = {.id = 99, .data = (double)-16.645454}}, + {.next = &nodes7[180], .payload = {.id = 230, .data = (double)-47.888153}}, + {.next = &nodes7[122], .payload = {.id = 19, .data = (double)7.102882}}, + {.next = &nodes7[39], .payload = {.id = 119, .data = (double)-50.101948}}, + {.next = &nodes7[234], .payload = {.id = 110, .data = (double)-37.775381}}, + {.next = &nodes7[195], .payload = {.id = 73, .data = (double)21.79243}}, + {.next = &nodes7[133], .payload = {.id = 154, .data = (double)29.474311}}, + {.next = &nodes7[233], .payload = {.id = 252, .data = (double)43.133691}}, + {.next = &nodes7[246], .payload = {.id = 197, .data = (double)99.49382}}, + {.next = &nodes7[189], .payload = {.id = 85, .data = (double)79.406272}}, + {.next = &nodes7[71], .payload = {.id = 218, .data = (double)-48.26963}}, + {.next = &nodes7[251], .payload = {.id = 0, .data = (double)77.098539}}, + {.next = &nodes7[111], .payload = {.id = 217, .data = (double)-74.411172}}, + {.next = &nodes7[25], .payload = {.id = 181, .data = (double)28.118949}}, + {.next = &nodes7[13], .payload = {.id = 61, .data = (double)17.586827}}, + {.next = &nodes7[42], .payload = {.id = 207, .data = (double)6.92702}}, + {.next = &nodes7[14], .payload = {.id = 137, .data = (double)49.792227}}, + {.next = &nodes7[61], .payload = {.id = 247, .data = (double)-18.161631}}, + {.next = &nodes7[81], .payload = {.id = 210, .data = (double)34.373695}}, + {.next = &nodes7[32], .payload = {.id = 249, .data = (double)81.324187}}, + {.next = &nodes7[205], .payload = {.id = 235, .data = (double)16.714924}}, + {.next = &nodes7[75], .payload = {.id = 20, .data = (double)73.378803}}, + {.next = &nodes7[3], .payload = {.id = 37, .data = (double)61.692144}}, + {.next = &nodes7[244], .payload = {.id = 146, .data = (double)35.539049}}, + {.next = NULL, .payload = {.id = 255, .data = (double)26.206554}}, + {.next = &nodes7[83], .payload = {.id = 45, .data = (double)-48.422728}}, + {.next = &nodes7[214], .payload = {.id = 172, .data = (double)32.471091}}, + {.next = &nodes7[23], .payload = {.id = 67, .data = (double)-42.781429}}, + {.next = &nodes7[163], .payload = {.id = 224, .data = (double)-82.140036}}, + {.next = &nodes7[224], .payload = {.id = 50, .data = (double)-20.529001}}, + {.next = &nodes7[202], .payload = {.id = 127, .data = (double)-75.225428}}, + {.next = &nodes7[162], .payload = {.id = 158, .data = (double)61.017114}}, + {.next = &nodes7[96], .payload = {.id = 155, .data = (double)20.22839}}, + {.next = &nodes7[106], .payload = {.id = 72, .data = (double)-2.883042}}, + {.next = &nodes7[170], .payload = {.id = 30, .data = (double)35.506977}}, + {.next = &nodes7[65], .payload = {.id = 130, .data = (double)18.808719}}, + {.next = &nodes7[176], .payload = {.id = 204, .data = (double)-62.016968}}, + {.next = &nodes7[36], .payload = {.id = 143, .data = (double)92.983522}}, + {.next = &nodes7[41], .payload = {.id = 35, .data = (double)96.873598}}, + {.next = &nodes7[249], .payload = {.id = 69, .data = (double)-31.226164}}, + {.next = &nodes7[219], .payload = {.id = 192, .data = (double)20.00666}}, + {.next = &nodes7[204], .payload = {.id = 25, .data = (double)80.55544}}, + {.next = &nodes7[80], .payload = {.id = 107, .data = (double)64.203478}}, + {.next = &nodes7[200], .payload = {.id = 77, .data = (double)21.731053}}, + {.next = &nodes7[221], .payload = {.id = 2, .data = (double)-10.844946}}, + {.next = &nodes7[248], .payload = {.id = 52, .data = (double)-44.759836}}, + {.next = &nodes7[242], .payload = {.id = 39, .data = (double)-15.32502}}, + {.next = &nodes7[229], .payload = {.id = 121, .data = (double)83.606214}}, + {.next = &nodes7[164], .payload = {.id = 64, .data = (double)84.985633}}, + {.next = &nodes7[93], .payload = {.id = 140, .data = (double)-22.686866}}, + {.next = &nodes7[68], .payload = {.id = 170, .data = (double)-79.537579}}, + {.next = &nodes7[228], .payload = {.id = 97, .data = (double)65.164666}}, + {.next = &nodes7[74], .payload = {.id = 113, .data = (double)70.259068}}, + {.next = &nodes7[143], .payload = {.id = 106, .data = (double)73.437794}}, + {.next = &nodes7[135], .payload = {.id = 29, .data = (double)60.090067}}, + {.next = &nodes7[188], .payload = {.id = 233, .data = (double)-5.892686}}, + {.next = &nodes7[187], .payload = {.id = 174, .data = (double)-25.154047}}, + {.next = &nodes7[40], .payload = {.id = 27, .data = (double)0.420294}}, + {.next = &nodes7[253], .payload = {.id = 161, .data = (double)28.548062}}, + {.next = &nodes7[141], .payload = {.id = 191, .data = (double)60.472749}}, + {.next = &nodes7[1], .payload = {.id = 12, .data = (double)8.289801}}, + {.next = &nodes7[212], .payload = {.id = 159, .data = (double)-38.90806}}, + {.next = &nodes7[167], .payload = {.id = 225, .data = (double)-28.943321}}, + {.next = &nodes7[30], .payload = {.id = 65, .data = (double)12.536752}}, + {.next = &nodes7[100], .payload = {.id = 163, .data = (double)-24.70491}}, + {.next = &nodes7[152], .payload = {.id = 96, .data = (double)-11.377877}}, + {.next = &nodes7[213], .payload = {.id = 226, .data = (double)48.841986}}, + {.next = &nodes7[99], .payload = {.id = 166, .data = (double)-6.660397}}, + {.next = &nodes7[7], .payload = {.id = 93, .data = (double)73.780005}}, + {.next = &nodes7[95], .payload = {.id = 31, .data = (double)24.054623}}, + {.next = &nodes7[21], .payload = {.id = 245, .data = (double)-72.526948}}, + {.next = &nodes7[136], .payload = {.id = 129, .data = (double)-25.506648}}, + {.next = &nodes7[184], .payload = {.id = 240, .data = (double)73.499551}}, + {.next = &nodes7[88], .payload = {.id = 5, .data = (double)-54.751544}}, + {.next = &nodes7[44], .payload = {.id = 54, .data = (double)74.693251}}, + {.next = &nodes7[2], .payload = {.id = 205, .data = (double)45.309975}}, + {.next = &nodes7[119], .payload = {.id = 209, .data = (double)81.305301}}, + {.next = &nodes7[89], .payload = {.id = 58, .data = (double)-16.081233}}, + {.next = &nodes7[182], .payload = {.id = 215, .data = (double)-63.772828}}, + {.next = &nodes7[230], .payload = {.id = 231, .data = (double)-41.189776}}, + {.next = &nodes7[34], .payload = {.id = 238, .data = (double)77.885212}}, + {.next = &nodes7[113], .payload = {.id = 216, .data = (double)-80.479387}}, + {.next = &nodes7[98], .payload = {.id = 91, .data = (double)39.236569}}, + {.next = &nodes7[82], .payload = {.id = 241, .data = (double)-23.666156}}, + {.next = &nodes7[207], .payload = {.id = 87, .data = (double)63.477185}}, + {.next = &nodes7[139], .payload = {.id = 34, .data = (double)-65.424205}}, + {.next = &nodes7[90], .payload = {.id = 175, .data = (double)29.468424}}, + {.next = &nodes7[121], .payload = {.id = 234, .data = (double)73.278674}}, + {.next = &nodes7[185], .payload = {.id = 86, .data = (double)-95.953422}}, + {.next = &nodes7[217], .payload = {.id = 134, .data = (double)-30.04802}}, + {.next = &nodes7[57], .payload = {.id = 152, .data = (double)-98.220403}}, + {.next = &nodes7[190], .payload = {.id = 133, .data = (double)17.37605}}, + {.next = &nodes7[223], .payload = {.id = 186, .data = (double)-40.241778}}, + {.next = &nodes7[55], .payload = {.id = 116, .data = (double)-61.447311}}, + {.next = &nodes7[22], .payload = {.id = 74, .data = (double)-92.506866}}, + {.next = &nodes7[144], .payload = {.id = 76, .data = (double)-71.229466}}, + {.next = &nodes7[161], .payload = {.id = 11, .data = (double)-31.241723}}, + {.next = &nodes7[76], .payload = {.id = 16, .data = (double)68.159433}}, + {.next = &nodes7[245], .payload = {.id = 42, .data = (double)99.453845}}, + {.next = &nodes7[206], .payload = {.id = 78, .data = (double)38.732251}}, + {.next = &nodes7[33], .payload = {.id = 150, .data = (double)56.060733}}, + {.next = &nodes7[172], .payload = {.id = 128, .data = (double)-93.887362}}, + {.next = &nodes7[26], .payload = {.id = 228, .data = (double)57.618087}}, + {.next = &nodes7[158], .payload = {.id = 26, .data = (double)42.86114}}, + {.next = &nodes7[86], .payload = {.id = 236, .data = (double)88.860197}}, + {.next = &nodes7[254], .payload = {.id = 79, .data = (double)-92.243494}}, + {.next = &nodes7[49], .payload = {.id = 88, .data = (double)-39.389009}}, + {.next = &nodes7[92], .payload = {.id = 177, .data = (double)-40.304815}}, + {.next = &nodes7[178], .payload = {.id = 57, .data = (double)4.512402}}, + {.next = &nodes7[149], .payload = {.id = 63, .data = (double)87.929997}}, + {.next = &nodes7[129], .payload = {.id = 223, .data = (double)-32.873507}}, + {.next = &nodes7[159], .payload = {.id = 160, .data = (double)93.404889}}, + {.next = &nodes7[203], .payload = {.id = 227, .data = (double)-38.582946}}, + {.next = &nodes7[157], .payload = {.id = 173, .data = (double)68.65679}}, + {.next = &nodes7[174], .payload = {.id = 4, .data = (double)-6.988409}}, + {.next = &nodes7[31], .payload = {.id = 48, .data = (double)-86.597609}}, + {.next = &nodes7[225], .payload = {.id = 135, .data = (double)-67.297277}}, + {.next = &nodes7[15], .payload = {.id = 213, .data = (double)68.127739}}, + {.next = &nodes7[247], .payload = {.id = 193, .data = (double)32.106065}}, + {.next = &nodes7[48], .payload = {.id = 82, .data = (double)-52.484141}}, + {.next = &nodes7[215], .payload = {.id = 3, .data = (double)-47.340807}}, + {.next = &nodes7[166], .payload = {.id = 95, .data = (double)94.843885}}, + {.next = &nodes7[77], .payload = {.id = 187, .data = (double)-70.014141}}, + {.next = &nodes7[146], .payload = {.id = 51, .data = (double)-34.774639}}, + {.next = &nodes7[117], .payload = {.id = 136, .data = (double)78.898384}}, + {.next = &nodes7[52], .payload = {.id = 9, .data = (double)33.493692}}, + {.next = &nodes7[108], .payload = {.id = 251, .data = (double)-36.723308}}, + {.next = &nodes7[101], .payload = {.id = 98, .data = (double)-46.116004}}, + {.next = &nodes7[91], .payload = {.id = 122, .data = (double)40.926789}}, + {.next = &nodes7[156], .payload = {.id = 232, .data = (double)70.242778}}, + {.next = &nodes7[29], .payload = {.id = 103, .data = (double)64.793887}}, + {.next = &nodes7[105], .payload = {.id = 109, .data = (double)-68.205511}}, + {.next = &nodes7[66], .payload = {.id = 253, .data = (double)55.788235}}, + {.next = &nodes7[24], .payload = {.id = 111, .data = (double)1.359055}}, + {.next = &nodes7[132], .payload = {.id = 157, .data = (double)-49.521912}}, + {.next = &nodes7[186], .payload = {.id = 33, .data = (double)51.437751}}, + {.next = &nodes7[67], .payload = {.id = 22, .data = (double)76.330774}}, + {.next = &nodes7[9], .payload = {.id = 199, .data = (double)-16.286863}}, + {.next = &nodes7[12], .payload = {.id = 243, .data = (double)-89.187606}}, + {.next = &nodes7[16], .payload = {.id = 201, .data = (double)-92.936199}}, + {.next = &nodes7[73], .payload = {.id = 125, .data = (double)1.025275}}, + {.next = &nodes7[54], .payload = {.id = 40, .data = (double)97.655987}}, + {.next = &nodes7[62], .payload = {.id = 195, .data = (double)44.25664}}, + {.next = &nodes7[85], .payload = {.id = 147, .data = (double)-46.183284}}, + {.next = &nodes7[59], .payload = {.id = 43, .data = (double)25.445242}}, + {.next = &nodes7[238], .payload = {.id = 198, .data = (double)-48.114745}}, + {.next = &nodes7[243], .payload = {.id = 194, .data = (double)36.15115}}, + {.next = &nodes7[175], .payload = {.id = 53, .data = (double)-8.368564}}, + {.next = &nodes7[8], .payload = {.id = 70, .data = (double)-17.821993}}, + {.next = &nodes7[194], .payload = {.id = 115, .data = (double)-94.210368}}, + {.next = &nodes7[145], .payload = {.id = 1, .data = (double)-26.119667}}, + {.next = &nodes7[11], .payload = {.id = 14, .data = (double)17.945288}}, + {.next = &nodes7[165], .payload = {.id = 162, .data = (double)-15.23864}}, + {.next = &nodes7[58], .payload = {.id = 80, .data = (double)77.914843}}, + {.next = &nodes7[183], .payload = {.id = 90, .data = (double)-1.676157}}, +}; + +node_t nodes8[] = { + {.next = &nodes8[231], .payload = {.id = 65, .data = (double)-90.699928}}, + {.next = &nodes8[84], .payload = {.id = 67, .data = (double)34.428354}}, + {.next = &nodes8[197], .payload = {.id = 194, .data = (double)25.073333}}, + {.next = &nodes8[137], .payload = {.id = 206, .data = (double)8.616031}}, + {.next = &nodes8[118], .payload = {.id = 150, .data = (double)-22.222668}}, + {.next = &nodes8[101], .payload = {.id = 85, .data = (double)-79.289208}}, + {.next = &nodes8[43], .payload = {.id = 232, .data = (double)-95.058854}}, + {.next = &nodes8[119], .payload = {.id = 119, .data = (double)52.155005}}, + {.next = &nodes8[237], .payload = {.id = 63, .data = (double)-32.41329}}, + {.next = &nodes8[209], .payload = {.id = 178, .data = (double)-85.106201}}, + {.next = &nodes8[248], .payload = {.id = 38, .data = (double)19.99023}}, + {.next = &nodes8[55], .payload = {.id = 196, .data = (double)-39.769036}}, + {.next = &nodes8[92], .payload = {.id = 69, .data = (double)78.350871}}, + {.next = &nodes8[141], .payload = {.id = 24, .data = (double)65.181752}}, + {.next = &nodes8[64], .payload = {.id = 108, .data = (double)-58.057461}}, + {.next = &nodes8[6], .payload = {.id = 231, .data = (double)44.795122}}, + {.next = &nodes8[205], .payload = {.id = 26, .data = (double)92.63425}}, + {.next = &nodes8[174], .payload = {.id = 181, .data = (double)-76.129238}}, + {.next = &nodes8[239], .payload = {.id = 44, .data = (double)-99.56061}}, + {.next = &nodes8[165], .payload = {.id = 20, .data = (double)-96.446174}}, + {.next = &nodes8[229], .payload = {.id = 98, .data = (double)-72.363999}}, + {.next = &nodes8[155], .payload = {.id = 187, .data = (double)-98.870973}}, + {.next = &nodes8[163], .payload = {.id = 52, .data = (double)-1.515572}}, + {.next = &nodes8[240], .payload = {.id = 12, .data = (double)-84.233881}}, + {.next = &nodes8[47], .payload = {.id = 159, .data = (double)37.029753}}, + {.next = &nodes8[195], .payload = {.id = 96, .data = (double)-41.165292}}, + {.next = &nodes8[34], .payload = {.id = 156, .data = (double)-23.683474}}, + {.next = &nodes8[124], .payload = {.id = 247, .data = (double)-57.843705}}, + {.next = &nodes8[228], .payload = {.id = 114, .data = (double)95.035899}}, + {.next = &nodes8[221], .payload = {.id = 171, .data = (double)17.677068}}, + {.next = &nodes8[213], .payload = {.id = 192, .data = (double)19.376066}}, + {.next = &nodes8[203], .payload = {.id = 200, .data = (double)41.536312}}, + {.next = &nodes8[42], .payload = {.id = 214, .data = (double)23.65612}}, + {.next = &nodes8[198], .payload = {.id = 71, .data = (double)17.863233}}, + {.next = &nodes8[215], .payload = {.id = 157, .data = (double)-16.686753}}, + {.next = &nodes8[196], .payload = {.id = 111, .data = (double)84.238353}}, + {.next = &nodes8[52], .payload = {.id = 14, .data = (double)14.606986}}, + {.next = &nodes8[125], .payload = {.id = 126, .data = (double)6.780561}}, + {.next = &nodes8[207], .payload = {.id = 90, .data = (double)-16.267051}}, + {.next = &nodes8[87], .payload = {.id = 220, .data = (double)-30.798542}}, + {.next = &nodes8[224], .payload = {.id = 79, .data = (double)84.874175}}, + {.next = &nodes8[217], .payload = {.id = 163, .data = (double)-59.382555}}, + {.next = &nodes8[74], .payload = {.id = 215, .data = (double)-5.028562}}, + {.next = &nodes8[103], .payload = {.id = 233, .data = (double)3.373565}}, + {.next = &nodes8[153], .payload = {.id = 48, .data = (double)9.538116}}, + {.next = &nodes8[139], .payload = {.id = 123, .data = (double)42.024726}}, + {.next = &nodes8[117], .payload = {.id = 225, .data = (double)-92.02455}}, + {.next = &nodes8[227], .payload = {.id = 160, .data = (double)93.166643}}, + {.next = &nodes8[162], .payload = {.id = 87, .data = (double)21.232155}}, + {.next = &nodes8[18], .payload = {.id = 43, .data = (double)31.782051}}, + {.next = &nodes8[14], .payload = {.id = 107, .data = (double)-56.531489}}, + {.next = &nodes8[204], .payload = {.id = 73, .data = (double)92.770951}}, + {.next = &nodes8[214], .payload = {.id = 15, .data = (double)-82.396028}}, + {.next = NULL, .payload = {.id = 255, .data = (double)48.275007}}, + {.next = &nodes8[28], .payload = {.id = 113, .data = (double)42.079289}}, + {.next = &nodes8[133], .payload = {.id = 197, .data = (double)57.981636}}, + {.next = &nodes8[13], .payload = {.id = 23, .data = (double)9.819758}}, + {.next = &nodes8[244], .payload = {.id = 83, .data = (double)-65.269946}}, + {.next = &nodes8[247], .payload = {.id = 5, .data = (double)-35.873237}}, + {.next = &nodes8[37], .payload = {.id = 125, .data = (double)78.7732}}, + {.next = &nodes8[212], .payload = {.id = 189, .data = (double)87.49889}}, + {.next = &nodes8[32], .payload = {.id = 213, .data = (double)90.061655}}, + {.next = &nodes8[243], .payload = {.id = 8, .data = (double)1.385866}}, + {.next = &nodes8[10], .payload = {.id = 37, .data = (double)53.48328}}, + {.next = &nodes8[225], .payload = {.id = 109, .data = (double)42.876907}}, + {.next = &nodes8[29], .payload = {.id = 170, .data = (double)-26.451776}}, + {.next = &nodes8[27], .payload = {.id = 246, .data = (double)25.386615}}, + {.next = &nodes8[241], .payload = {.id = 250, .data = (double)37.081037}}, + {.next = &nodes8[219], .payload = {.id = 135, .data = (double)57.106439}}, + {.next = &nodes8[38], .payload = {.id = 89, .data = (double)76.278113}}, + {.next = &nodes8[100], .payload = {.id = 92, .data = (double)38.503107}}, + {.next = &nodes8[81], .payload = {.id = 223, .data = (double)83.72146}}, + {.next = &nodes8[3], .payload = {.id = 205, .data = (double)-68.125901}}, + {.next = &nodes8[22], .payload = {.id = 51, .data = (double)79.375424}}, + {.next = &nodes8[126], .payload = {.id = 216, .data = (double)12.266937}}, + {.next = &nodes8[45], .payload = {.id = 122, .data = (double)88.53473}}, + {.next = &nodes8[223], .payload = {.id = 3, .data = (double)-66.919225}}, + {.next = &nodes8[238], .payload = {.id = 202, .data = (double)91.397544}}, + {.next = &nodes8[9], .payload = {.id = 177, .data = (double)96.690665}}, + {.next = &nodes8[159], .payload = {.id = 130, .data = (double)-78.705907}}, + {.next = &nodes8[138], .payload = {.id = 243, .data = (double)94.325754}}, + {.next = &nodes8[46], .payload = {.id = 224, .data = (double)-51.234567}}, + {.next = &nodes8[187], .payload = {.id = 33, .data = (double)65.062198}}, + {.next = &nodes8[68], .payload = {.id = 134, .data = (double)-46.604346}}, + {.next = &nodes8[12], .payload = {.id = 68, .data = (double)-75.356162}}, + {.next = &nodes8[226], .payload = {.id = 102, .data = (double)68.614886}}, + {.next = &nodes8[15], .payload = {.id = 230, .data = (double)-48.681889}}, + {.next = &nodes8[255], .payload = {.id = 221, .data = (double)-51.930425}}, + {.next = &nodes8[95], .payload = {.id = 238, .data = (double)-40.713206}}, + {.next = &nodes8[50], .payload = {.id = 106, .data = (double)10.716313}}, + {.next = &nodes8[31], .payload = {.id = 199, .data = (double)-85.423841}}, + {.next = &nodes8[116], .payload = {.id = 211, .data = (double)-33.786693}}, + {.next = &nodes8[33], .payload = {.id = 70, .data = (double)-8.522425}}, + {.next = &nodes8[8], .payload = {.id = 62, .data = (double)-61.884247}}, + {.next = &nodes8[79], .payload = {.id = 129, .data = (double)-97.445897}}, + {.next = &nodes8[252], .payload = {.id = 239, .data = (double)30.305639}}, + {.next = &nodes8[232], .payload = {.id = 57, .data = (double)-60.815707}}, + {.next = &nodes8[135], .payload = {.id = 59, .data = (double)70.438874}}, + {.next = &nodes8[93], .payload = {.id = 61, .data = (double)64.910829}}, + {.next = &nodes8[49], .payload = {.id = 42, .data = (double)-80.512596}}, + {.next = &nodes8[107], .payload = {.id = 93, .data = (double)-50.352242}}, + {.next = &nodes8[48], .payload = {.id = 86, .data = (double)31.504362}}, + {.next = &nodes8[120], .payload = {.id = 132, .data = (double)-89.387}}, + {.next = &nodes8[208], .payload = {.id = 234, .data = (double)54.098864}}, + {.next = &nodes8[182], .payload = {.id = 35, .data = (double)68.863488}}, + {.next = &nodes8[188], .payload = {.id = 55, .data = (double)-18.157849}}, + {.next = &nodes8[57], .payload = {.id = 82, .data = (double)38.363543}}, + {.next = &nodes8[178], .payload = {.id = 94, .data = (double)-20.426001}}, + {.next = &nodes8[110], .payload = {.id = 167, .data = (double)-54.8903}}, + {.next = &nodes8[152], .payload = {.id = 28, .data = (double)78.02218}}, + {.next = &nodes8[193], .payload = {.id = 168, .data = (double)26.757699}}, + {.next = &nodes8[17], .payload = {.id = 180, .data = (double)47.015897}}, + {.next = &nodes8[246], .payload = {.id = 116, .data = (double)8.498296}}, + {.next = &nodes8[218], .payload = {.id = 0, .data = (double)1.113514}}, + {.next = &nodes8[179], .payload = {.id = 253, .data = (double)65.749734}}, + {.next = &nodes8[128], .payload = {.id = 227, .data = (double)-23.725478}}, + {.next = &nodes8[61], .payload = {.id = 212, .data = (double)-41.285129}}, + {.next = &nodes8[115], .payload = {.id = 226, .data = (double)77.132032}}, + {.next = &nodes8[169], .payload = {.id = 151, .data = (double)2.184461}}, + {.next = &nodes8[191], .payload = {.id = 120, .data = (double)12.456042}}, + {.next = &nodes8[83], .payload = {.id = 133, .data = (double)-88.679045}}, + {.next = &nodes8[19], .payload = {.id = 19, .data = (double)49.047793}}, + {.next = &nodes8[150], .payload = {.id = 144, .data = (double)-9.481099}}, + {.next = &nodes8[66], .payload = {.id = 245, .data = (double)6.641164}}, + {.next = &nodes8[202], .payload = {.id = 248, .data = (double)25.902897}}, + {.next = &nodes8[206], .payload = {.id = 127, .data = (double)75.495447}}, + {.next = &nodes8[171], .payload = {.id = 217, .data = (double)50.426751}}, + {.next = &nodes8[185], .payload = {.id = 138, .data = (double)-70.714322}}, + {.next = &nodes8[222], .payload = {.id = 228, .data = (double)59.241317}}, + {.next = &nodes8[168], .payload = {.id = 185, .data = (double)-67.81423}}, + {.next = &nodes8[106], .payload = {.id = 81, .data = (double)82.036297}}, + {.next = &nodes8[142], .payload = {.id = 153, .data = (double)39.225699}}, + {.next = &nodes8[122], .payload = {.id = 143, .data = (double)-28.263513}}, + {.next = &nodes8[90], .payload = {.id = 198, .data = (double)10.032036}}, + {.next = &nodes8[78], .payload = {.id = 176, .data = (double)-10.237016}}, + {.next = &nodes8[98], .payload = {.id = 60, .data = (double)-56.882099}}, + {.next = &nodes8[82], .payload = {.id = 32, .data = (double)-31.82916}}, + {.next = &nodes8[145], .payload = {.id = 207, .data = (double)-19.316587}}, + {.next = &nodes8[123], .payload = {.id = 244, .data = (double)54.663704}}, + {.next = &nodes8[59], .payload = {.id = 124, .data = (double)34.848697}}, + {.next = &nodes8[73], .payload = {.id = 50, .data = (double)-78.735554}}, + {.next = &nodes8[16], .payload = {.id = 25, .data = (double)58.356657}}, + {.next = &nodes8[200], .payload = {.id = 154, .data = (double)38.587215}}, + {.next = &nodes8[251], .payload = {.id = 17, .data = (double)-36.787695}}, + {.next = &nodes8[72], .payload = {.id = 204, .data = (double)57.251648}}, + {.next = &nodes8[253], .payload = {.id = 208, .data = (double)-30.11941}}, + {.next = &nodes8[211], .payload = {.id = 148, .data = (double)-55.138523}}, + {.next = &nodes8[7], .payload = {.id = 118, .data = (double)42.070545}}, + {.next = &nodes8[108], .payload = {.id = 166, .data = (double)-11.387229}}, + {.next = &nodes8[114], .payload = {.id = 252, .data = (double)-58.884086}}, + {.next = &nodes8[170], .payload = {.id = 145, .data = (double)23.221767}}, + {.next = &nodes8[156], .payload = {.id = 46, .data = (double)26.732236}}, + {.next = &nodes8[220], .payload = {.id = 29, .data = (double)12.466514}}, + {.next = &nodes8[140], .payload = {.id = 49, .data = (double)-25.221928}}, + {.next = &nodes8[88], .payload = {.id = 237, .data = (double)-2.639058}}, + {.next = &nodes8[60], .payload = {.id = 188, .data = (double)-6.733732}}, + {.next = &nodes8[44], .payload = {.id = 47, .data = (double)59.982543}}, + {.next = &nodes8[99], .payload = {.id = 41, .data = (double)-9.493509}}, + {.next = &nodes8[249], .payload = {.id = 174, .data = (double)44.982904}}, + {.next = &nodes8[102], .payload = {.id = 131, .data = (double)-23.825937}}, + {.next = &nodes8[89], .payload = {.id = 105, .data = (double)47.36373}}, + {.next = &nodes8[105], .payload = {.id = 54, .data = (double)48.502178}}, + {.next = &nodes8[69], .payload = {.id = 88, .data = (double)-35.631248}}, + {.next = &nodes8[161], .payload = {.id = 53, .data = (double)64.367732}}, + {.next = &nodes8[40], .payload = {.id = 78, .data = (double)17.024142}}, + {.next = &nodes8[242], .payload = {.id = 21, .data = (double)-19.312068}}, + {.next = &nodes8[176], .payload = {.id = 140, .data = (double)56.87148}}, + {.next = &nodes8[127], .payload = {.id = 137, .data = (double)36.678066}}, + {.next = &nodes8[21], .payload = {.id = 186, .data = (double)69.202839}}, + {.next = &nodes8[131], .payload = {.id = 152, .data = (double)59.36673}}, + {.next = &nodes8[234], .payload = {.id = 146, .data = (double)35.105203}}, + {.next = &nodes8[189], .payload = {.id = 218, .data = (double)29.860023}}, + {.next = &nodes8[210], .payload = {.id = 10, .data = (double)-24.272481}}, + {.next = &nodes8[136], .payload = {.id = 31, .data = (double)-8.758415}}, + {.next = &nodes8[245], .payload = {.id = 182, .data = (double)-91.873153}}, + {.next = &nodes8[154], .payload = {.id = 236, .data = (double)1.747119}}, + {.next = &nodes8[236], .payload = {.id = 141, .data = (double)-59.199819}}, + {.next = &nodes8[76], .payload = {.id = 2, .data = (double)-0.833014}}, + {.next = &nodes8[25], .payload = {.id = 95, .data = (double)-31.428239}}, + {.next = &nodes8[53], .payload = {.id = 254, .data = (double)75.727446}}, + {.next = &nodes8[158], .payload = {.id = 173, .data = (double)-60.706184}}, + {.next = &nodes8[201], .payload = {.id = 76, .data = (double)10.645266}}, + {.next = &nodes8[63], .payload = {.id = 36, .data = (double)-33.605475}}, + {.next = &nodes8[41], .payload = {.id = 162, .data = (double)48.733993}}, + {.next = &nodes8[181], .payload = {.id = 75, .data = (double)47.242786}}, + {.next = &nodes8[166], .payload = {.id = 139, .data = (double)-87.593435}}, + {.next = &nodes8[194], .payload = {.id = 100, .data = (double)77.287371}}, + {.next = &nodes8[104], .payload = {.id = 34, .data = (double)63.317737}}, + {.next = &nodes8[96], .payload = {.id = 56, .data = (double)-49.142138}}, + {.next = &nodes8[39], .payload = {.id = 219, .data = (double)-77.05561}}, + {.next = &nodes8[157], .payload = {.id = 40, .data = (double)-27.341091}}, + {.next = &nodes8[75], .payload = {.id = 121, .data = (double)16.561254}}, + {.next = &nodes8[62], .payload = {.id = 7, .data = (double)-44.368574}}, + {.next = &nodes8[65], .payload = {.id = 169, .data = (double)41.909091}}, + {.next = &nodes8[85], .payload = {.id = 101, .data = (double)2.458925}}, + {.next = &nodes8[20], .payload = {.id = 97, .data = (double)60.959366}}, + {.next = &nodes8[54], .payload = {.id = 112, .data = (double)-73.465654}}, + {.next = &nodes8[11], .payload = {.id = 195, .data = (double)68.627996}}, + {.next = &nodes8[51], .payload = {.id = 72, .data = (double)0.839515}}, + {.next = &nodes8[80], .payload = {.id = 242, .data = (double)-80.808714}}, + {.next = &nodes8[26], .payload = {.id = 155, .data = (double)-90.604024}}, + {.next = &nodes8[164], .payload = {.id = 77, .data = (double)-13.437924}}, + {.next = &nodes8[67], .payload = {.id = 249, .data = (double)-57.364974}}, + {.next = &nodes8[77], .payload = {.id = 201, .data = (double)5.079013}}, + {.next = &nodes8[184], .payload = {.id = 74, .data = (double)-99.132474}}, + {.next = &nodes8[109], .payload = {.id = 27, .data = (double)27.507624}}, + {.next = &nodes8[94], .payload = {.id = 128, .data = (double)-15.522726}}, + {.next = &nodes8[70], .payload = {.id = 91, .data = (double)21.798739}}, + {.next = &nodes8[175], .payload = {.id = 235, .data = (double)2.861812}}, + {.next = &nodes8[111], .payload = {.id = 179, .data = (double)92.49505}}, + {.next = &nodes8[23], .payload = {.id = 11, .data = (double)63.420661}}, + {.next = &nodes8[4], .payload = {.id = 149, .data = (double)29.423889}}, + {.next = &nodes8[250], .payload = {.id = 190, .data = (double)-92.011882}}, + {.next = &nodes8[2], .payload = {.id = 193, .data = (double)54.73219}}, + {.next = &nodes8[143], .payload = {.id = 16, .data = (double)-0.308771}}, + {.next = &nodes8[24], .payload = {.id = 158, .data = (double)57.622306}}, + {.next = &nodes8[129], .payload = {.id = 184, .data = (double)-47.152081}}, + {.next = &nodes8[254], .payload = {.id = 164, .data = (double)73.769992}}, + {.next = &nodes8[177], .payload = {.id = 1, .data = (double)-6.142213}}, + {.next = &nodes8[167], .payload = {.id = 136, .data = (double)96.706479}}, + {.next = &nodes8[173], .payload = {.id = 30, .data = (double)30.919197}}, + {.next = &nodes8[180], .payload = {.id = 172, .data = (double)47.690006}}, + {.next = &nodes8[86], .payload = {.id = 229, .data = (double)-77.325194}}, + {.next = &nodes8[58], .payload = {.id = 4, .data = (double)50.286}}, + {.next = &nodes8[130], .payload = {.id = 80, .data = (double)56.216299}}, + {.next = &nodes8[35], .payload = {.id = 110, .data = (double)37.322259}}, + {.next = &nodes8[230], .payload = {.id = 103, .data = (double)9.561194}}, + {.next = &nodes8[183], .payload = {.id = 161, .data = (double)-89.239562}}, + {.next = &nodes8[112], .payload = {.id = 115, .data = (double)-64.43746}}, + {.next = &nodes8[186], .payload = {.id = 99, .data = (double)20.50489}}, + {.next = &nodes8[160], .payload = {.id = 104, .data = (double)-37.217841}}, + {.next = &nodes8[1], .payload = {.id = 66, .data = (double)26.648094}}, + {.next = &nodes8[97], .payload = {.id = 58, .data = (double)-75.850839}}, + {.next = &nodes8[91], .payload = {.id = 210, .data = (double)32.666895}}, + {.next = &nodes8[146], .payload = {.id = 147, .data = (double)12.376997}}, + {.next = &nodes8[199], .payload = {.id = 241, .data = (double)-83.53091}}, + {.next = &nodes8[132], .payload = {.id = 142, .data = (double)8.234417}}, + {.next = &nodes8[0], .payload = {.id = 64, .data = (double)51.429868}}, + {.next = &nodes8[144], .payload = {.id = 203, .data = (double)4.121257}}, + {.next = &nodes8[151], .payload = {.id = 45, .data = (double)-28.972204}}, + {.next = &nodes8[36], .payload = {.id = 13, .data = (double)-11.162225}}, + {.next = &nodes8[149], .payload = {.id = 251, .data = (double)67.133016}}, + {.next = &nodes8[56], .payload = {.id = 22, .data = (double)-92.833614}}, + {.next = &nodes8[172], .payload = {.id = 9, .data = (double)10.099114}}, + {.next = &nodes8[5], .payload = {.id = 84, .data = (double)63.048831}}, + {.next = &nodes8[216], .payload = {.id = 183, .data = (double)-44.177551}}, + {.next = &nodes8[147], .payload = {.id = 117, .data = (double)27.375487}}, + {.next = &nodes8[192], .payload = {.id = 6, .data = (double)-33.821031}}, + {.next = &nodes8[190], .payload = {.id = 39, .data = (double)43.331614}}, + {.next = &nodes8[134], .payload = {.id = 175, .data = (double)-61.300458}}, + {.next = &nodes8[30], .payload = {.id = 191, .data = (double)85.725648}}, + {.next = &nodes8[121], .payload = {.id = 18, .data = (double)96.134148}}, + {.next = &nodes8[235], .payload = {.id = 240, .data = (double)-35.937449}}, + {.next = &nodes8[233], .payload = {.id = 209, .data = (double)76.679348}}, + {.next = &nodes8[148], .payload = {.id = 165, .data = (double)72.088948}}, + {.next = &nodes8[71], .payload = {.id = 222, .data = (double)28.452871}}, +}; + +node_t nodes9[] = { + {.next = &nodes9[201], .payload = {.id = 155, .data = (double)22.793118}}, + {.next = &nodes9[49], .payload = {.id = 27, .data = (double)-91.371134}}, + {.next = &nodes9[160], .payload = {.id = 188, .data = (double)-30.38095}}, + {.next = &nodes9[65], .payload = {.id = 208, .data = (double)12.633721}}, + {.next = &nodes9[238], .payload = {.id = 129, .data = (double)47.156486}}, + {.next = &nodes9[122], .payload = {.id = 98, .data = (double)-43.346666}}, + {.next = &nodes9[247], .payload = {.id = 224, .data = (double)3.300843}}, + {.next = &nodes9[78], .payload = {.id = 162, .data = (double)-12.20559}}, + {.next = &nodes9[43], .payload = {.id = 0, .data = (double)-24.734244}}, + {.next = &nodes9[184], .payload = {.id = 251, .data = (double)35.162425}}, + {.next = &nodes9[168], .payload = {.id = 205, .data = (double)14.978776}}, + {.next = &nodes9[145], .payload = {.id = 54, .data = (double)-47.09586}}, + {.next = &nodes9[213], .payload = {.id = 253, .data = (double)22.765395}}, + {.next = &nodes9[220], .payload = {.id = 174, .data = (double)-99.942546}}, + {.next = &nodes9[134], .payload = {.id = 4, .data = (double)73.543884}}, + {.next = &nodes9[186], .payload = {.id = 106, .data = (double)-98.56119}}, + {.next = &nodes9[107], .payload = {.id = 42, .data = (double)-43.309075}}, + {.next = &nodes9[225], .payload = {.id = 7, .data = (double)20.842196}}, + {.next = &nodes9[214], .payload = {.id = 131, .data = (double)31.85657}}, + {.next = &nodes9[169], .payload = {.id = 109, .data = (double)-36.819657}}, + {.next = &nodes9[140], .payload = {.id = 84, .data = (double)5.963304}}, + {.next = &nodes9[180], .payload = {.id = 114, .data = (double)70.995385}}, + {.next = &nodes9[170], .payload = {.id = 141, .data = (double)41.357987}}, + {.next = &nodes9[62], .payload = {.id = 151, .data = (double)-83.992053}}, + {.next = &nodes9[48], .payload = {.id = 183, .data = (double)-86.276566}}, + {.next = &nodes9[123], .payload = {.id = 61, .data = (double)-78.285977}}, + {.next = &nodes9[74], .payload = {.id = 243, .data = (double)74.5485}}, + {.next = &nodes9[39], .payload = {.id = 153, .data = (double)-23.134798}}, + {.next = &nodes9[219], .payload = {.id = 197, .data = (double)-78.707009}}, + {.next = &nodes9[250], .payload = {.id = 79, .data = (double)54.974085}}, + {.next = &nodes9[158], .payload = {.id = 213, .data = (double)-7.855912}}, + {.next = &nodes9[93], .payload = {.id = 165, .data = (double)60.781982}}, + {.next = &nodes9[150], .payload = {.id = 11, .data = (double)-84.582355}}, + {.next = &nodes9[221], .payload = {.id = 219, .data = (double)98.839607}}, + {.next = &nodes9[167], .payload = {.id = 49, .data = (double)20.167743}}, + {.next = &nodes9[115], .payload = {.id = 35, .data = (double)-63.992492}}, + {.next = &nodes9[112], .payload = {.id = 17, .data = (double)-76.333955}}, + {.next = &nodes9[47], .payload = {.id = 239, .data = (double)81.985492}}, + {.next = &nodes9[80], .payload = {.id = 168, .data = (double)19.902983}}, + {.next = &nodes9[0], .payload = {.id = 154, .data = (double)96.88962}}, + {.next = &nodes9[188], .payload = {.id = 227, .data = (double)-50.348478}}, + {.next = &nodes9[79], .payload = {.id = 22, .data = (double)-4.237071}}, + {.next = &nodes9[133], .payload = {.id = 104, .data = (double)15.597429}}, + {.next = &nodes9[210], .payload = {.id = 1, .data = (double)81.448485}}, + {.next = &nodes9[153], .payload = {.id = 63, .data = (double)71.918338}}, + {.next = &nodes9[215], .payload = {.id = 177, .data = (double)55.934576}}, + {.next = &nodes9[24], .payload = {.id = 182, .data = (double)47.385108}}, + {.next = &nodes9[179], .payload = {.id = 240, .data = (double)-0.200132}}, + {.next = &nodes9[85], .payload = {.id = 184, .data = (double)-81.966828}}, + {.next = &nodes9[97], .payload = {.id = 28, .data = (double)14.697302}}, + {.next = &nodes9[119], .payload = {.id = 112, .data = (double)30.315187}}, + {.next = &nodes9[183], .payload = {.id = 190, .data = (double)-44.69843}}, + {.next = &nodes9[76], .payload = {.id = 215, .data = (double)-94.52986}}, + {.next = &nodes9[146], .payload = {.id = 14, .data = (double)-62.618865}}, + {.next = &nodes9[99], .payload = {.id = 19, .data = (double)62.234526}}, + {.next = &nodes9[67], .payload = {.id = 170, .data = (double)-53.665805}}, + {.next = &nodes9[26], .payload = {.id = 242, .data = (double)47.085813}}, + {.next = &nodes9[212], .payload = {.id = 249, .data = (double)-78.662142}}, + {.next = &nodes9[70], .payload = {.id = 230, .data = (double)64.214938}}, + {.next = &nodes9[69], .payload = {.id = 149, .data = (double)-87.183909}}, + {.next = &nodes9[96], .payload = {.id = 39, .data = (double)-96.275993}}, + {.next = &nodes9[226], .payload = {.id = 137, .data = (double)-19.887819}}, + {.next = &nodes9[27], .payload = {.id = 152, .data = (double)-92.448932}}, + {.next = &nodes9[84], .payload = {.id = 74, .data = (double)-3.551813}}, + {.next = &nodes9[46], .payload = {.id = 181, .data = (double)3.54854}}, + {.next = &nodes9[163], .payload = {.id = 209, .data = (double)53.993439}}, + {.next = &nodes9[17], .payload = {.id = 6, .data = (double)-3.577982}}, + {.next = &nodes9[208], .payload = {.id = 171, .data = (double)-66.103422}}, + {.next = &nodes9[246], .payload = {.id = 247, .data = (double)23.71938}}, + {.next = &nodes9[23], .payload = {.id = 150, .data = (double)-55.645951}}, + {.next = &nodes9[75], .payload = {.id = 231, .data = (double)-84.794236}}, + {.next = &nodes9[157], .payload = {.id = 135, .data = (double)-67.640976}}, + {.next = &nodes9[230], .payload = {.id = 133, .data = (double)-10.681025}}, + {.next = &nodes9[1], .payload = {.id = 26, .data = (double)-95.510792}}, + {.next = &nodes9[233], .payload = {.id = 244, .data = (double)-58.644274}}, + {.next = &nodes9[176], .payload = {.id = 232, .data = (double)86.279248}}, + {.next = &nodes9[254], .payload = {.id = 216, .data = (double)-76.74634}}, + {.next = &nodes9[36], .payload = {.id = 16, .data = (double)43.460542}}, + {.next = &nodes9[143], .payload = {.id = 163, .data = (double)-59.658551}}, + {.next = &nodes9[142], .payload = {.id = 23, .data = (double)-57.85921}}, + {.next = &nodes9[55], .payload = {.id = 169, .data = (double)3.162726}}, + {.next = &nodes9[207], .payload = {.id = 52, .data = (double)-63.62317}}, + {.next = &nodes9[240], .payload = {.id = 194, .data = (double)14.981344}}, + {.next = &nodes9[198], .payload = {.id = 139, .data = (double)10.115243}}, + {.next = &nodes9[154], .payload = {.id = 75, .data = (double)-73.934232}}, + {.next = &nodes9[161], .payload = {.id = 185, .data = (double)-43.101243}}, + {.next = &nodes9[149], .payload = {.id = 235, .data = (double)78.863251}}, + {.next = &nodes9[202], .payload = {.id = 91, .data = (double)52.307845}}, + {.next = &nodes9[37], .payload = {.id = 238, .data = (double)36.621462}}, + {.next = &nodes9[203], .payload = {.id = 82, .data = (double)-25.92451}}, + {.next = &nodes9[116], .payload = {.id = 77, .data = (double)65.504356}}, + {.next = &nodes9[92], .payload = {.id = 159, .data = (double)89.143172}}, + {.next = &nodes9[98], .payload = {.id = 160, .data = (double)64.045747}}, + {.next = &nodes9[130], .payload = {.id = 166, .data = (double)-42.798698}}, + {.next = &nodes9[229], .payload = {.id = 203, .data = (double)75.222609}}, + {.next = &nodes9[206], .payload = {.id = 96, .data = (double)-53.497422}}, + {.next = &nodes9[147], .payload = {.id = 40, .data = (double)43.90946}}, + {.next = &nodes9[216], .payload = {.id = 29, .data = (double)-67.774172}}, + {.next = &nodes9[7], .payload = {.id = 161, .data = (double)28.058263}}, + {.next = &nodes9[255], .payload = {.id = 20, .data = (double)44.051132}}, + {.next = &nodes9[105], .payload = {.id = 118, .data = (double)36.121141}}, + {.next = &nodes9[118], .payload = {.id = 9, .data = (double)-72.206339}}, + {.next = &nodes9[81], .payload = {.id = 51, .data = (double)64.090636}}, + {.next = &nodes9[63], .payload = {.id = 73, .data = (double)-76.496719}}, + {.next = &nodes9[217], .payload = {.id = 116, .data = (double)-26.871181}}, + {.next = &nodes9[194], .payload = {.id = 119, .data = (double)50.99438}}, + {.next = &nodes9[2], .payload = {.id = 187, .data = (double)83.001795}}, + {.next = &nodes9[218], .payload = {.id = 43, .data = (double)-82.850299}}, + {.next = &nodes9[42], .payload = {.id = 103, .data = (double)57.884496}}, + {.next = &nodes9[89], .payload = {.id = 81, .data = (double)4.408846}}, + {.next = NULL, .payload = {.id = 255, .data = (double)8.294791}}, + {.next = &nodes9[50], .payload = {.id = 111, .data = (double)-69.044284}}, + {.next = &nodes9[54], .payload = {.id = 18, .data = (double)-53.930733}}, + {.next = &nodes9[82], .payload = {.id = 193, .data = (double)85.942768}}, + {.next = &nodes9[196], .payload = {.id = 59, .data = (double)-54.037243}}, + {.next = &nodes9[166], .payload = {.id = 36, .data = (double)91.647667}}, + {.next = &nodes9[29], .payload = {.id = 78, .data = (double)79.393791}}, + {.next = &nodes9[34], .payload = {.id = 48, .data = (double)66.072715}}, + {.next = &nodes9[32], .payload = {.id = 10, .data = (double)-66.878836}}, + {.next = &nodes9[21], .payload = {.id = 113, .data = (double)-49.273455}}, + {.next = &nodes9[174], .payload = {.id = 57, .data = (double)-9.305971}}, + {.next = &nodes9[252], .payload = {.id = 94, .data = (double)-73.223379}}, + {.next = &nodes9[222], .payload = {.id = 99, .data = (double)75.353263}}, + {.next = &nodes9[44], .payload = {.id = 62, .data = (double)-59.53029}}, + {.next = &nodes9[251], .payload = {.id = 157, .data = (double)42.321166}}, + {.next = &nodes9[192], .payload = {.id = 86, .data = (double)60.460039}}, + {.next = &nodes9[156], .payload = {.id = 211, .data = (double)92.247745}}, + {.next = &nodes9[87], .payload = {.id = 90, .data = (double)48.278808}}, + {.next = &nodes9[103], .payload = {.id = 72, .data = (double)0.665842}}, + {.next = &nodes9[33], .payload = {.id = 218, .data = (double)26.73236}}, + {.next = &nodes9[38], .payload = {.id = 167, .data = (double)-93.27813}}, + {.next = &nodes9[127], .payload = {.id = 89, .data = (double)17.809617}}, + {.next = &nodes9[232], .payload = {.id = 31, .data = (double)-92.161827}}, + {.next = &nodes9[15], .payload = {.id = 105, .data = (double)-76.434279}}, + {.next = &nodes9[66], .payload = {.id = 5, .data = (double)-2.627687}}, + {.next = &nodes9[6], .payload = {.id = 223, .data = (double)91.089137}}, + {.next = &nodes9[151], .payload = {.id = 144, .data = (double)-98.941873}}, + {.next = &nodes9[40], .payload = {.id = 226, .data = (double)66.435409}}, + {.next = &nodes9[94], .payload = {.id = 202, .data = (double)91.34187}}, + {.next = &nodes9[193], .payload = {.id = 200, .data = (double)89.403093}}, + {.next = &nodes9[125], .payload = {.id = 85, .data = (double)-54.102749}}, + {.next = &nodes9[64], .payload = {.id = 180, .data = (double)17.216033}}, + {.next = &nodes9[204], .payload = {.id = 24, .data = (double)-67.750748}}, + {.next = &nodes9[31], .payload = {.id = 164, .data = (double)31.376845}}, + {.next = &nodes9[200], .payload = {.id = 65, .data = (double)-16.040997}}, + {.next = &nodes9[235], .payload = {.id = 55, .data = (double)44.83736}}, + {.next = &nodes9[77], .payload = {.id = 15, .data = (double)-27.555411}}, + {.next = &nodes9[16], .payload = {.id = 41, .data = (double)32.349013}}, + {.next = &nodes9[13], .payload = {.id = 173, .data = (double)-52.148675}}, + {.next = &nodes9[181], .payload = {.id = 236, .data = (double)-46.184844}}, + {.next = &nodes9[231], .payload = {.id = 12, .data = (double)28.6954}}, + {.next = &nodes9[178], .payload = {.id = 145, .data = (double)-81.782283}}, + {.next = &nodes9[136], .payload = {.id = 143, .data = (double)92.91405}}, + {.next = &nodes9[144], .payload = {.id = 64, .data = (double)0.871905}}, + {.next = &nodes9[90], .payload = {.id = 76, .data = (double)20.69493}}, + {.next = &nodes9[242], .payload = {.id = 124, .data = (double)10.982271}}, + {.next = &nodes9[30], .payload = {.id = 212, .data = (double)-8.230314}}, + {.next = &nodes9[61], .payload = {.id = 136, .data = (double)-57.108372}}, + {.next = &nodes9[52], .payload = {.id = 214, .data = (double)17.365303}}, + {.next = &nodes9[35], .payload = {.id = 34, .data = (double)-48.348071}}, + {.next = &nodes9[51], .payload = {.id = 189, .data = (double)92.657533}}, + {.next = &nodes9[106], .payload = {.id = 186, .data = (double)65.95296}}, + {.next = &nodes9[241], .payload = {.id = 45, .data = (double)98.555165}}, + {.next = &nodes9[126], .payload = {.id = 210, .data = (double)51.494657}}, + {.next = &nodes9[227], .payload = {.id = 121, .data = (double)56.757683}}, + {.next = &nodes9[60], .payload = {.id = 38, .data = (double)12.72094}}, + {.next = &nodes9[165], .payload = {.id = 37, .data = (double)19.871505}}, + {.next = &nodes9[102], .payload = {.id = 50, .data = (double)58.923214}}, + {.next = &nodes9[187], .payload = {.id = 206, .data = (double)38.838372}}, + {.next = &nodes9[111], .payload = {.id = 110, .data = (double)-27.546042}}, + {.next = &nodes9[152], .payload = {.id = 142, .data = (double)-67.852398}}, + {.next = &nodes9[28], .payload = {.id = 196, .data = (double)-18.573075}}, + {.next = &nodes9[243], .payload = {.id = 69, .data = (double)22.949634}}, + {.next = &nodes9[68], .payload = {.id = 246, .data = (double)-50.060913}}, + {.next = &nodes9[114], .payload = {.id = 58, .data = (double)18.119198}}, + {.next = &nodes9[244], .payload = {.id = 221, .data = (double)-54.013972}}, + {.next = &nodes9[239], .payload = {.id = 233, .data = (double)-4.688909}}, + {.next = &nodes9[159], .payload = {.id = 33, .data = (double)-88.817599}}, + {.next = &nodes9[245], .payload = {.id = 146, .data = (double)-70.934313}}, + {.next = &nodes9[56], .payload = {.id = 241, .data = (double)-60.066692}}, + {.next = &nodes9[104], .payload = {.id = 115, .data = (double)-15.287691}}, + {.next = &nodes9[88], .payload = {.id = 237, .data = (double)89.423622}}, + {.next = &nodes9[108], .payload = {.id = 102, .data = (double)41.829767}}, + {.next = &nodes9[234], .payload = {.id = 191, .data = (double)21.272682}}, + {.next = &nodes9[12], .payload = {.id = 252, .data = (double)32.684816}}, + {.next = &nodes9[141], .payload = {.id = 179, .data = (double)-20.971377}}, + {.next = &nodes9[228], .payload = {.id = 107, .data = (double)30.909224}}, + {.next = &nodes9[3], .payload = {.id = 207, .data = (double)93.211091}}, + {.next = &nodes9[248], .payload = {.id = 228, .data = (double)-81.398114}}, + {.next = &nodes9[224], .payload = {.id = 127, .data = (double)-31.128739}}, + {.next = &nodes9[139], .payload = {.id = 199, .data = (double)-41.149635}}, + {.next = &nodes9[121], .payload = {.id = 93, .data = (double)-80.456618}}, + {.next = &nodes9[223], .payload = {.id = 87, .data = (double)57.911117}}, + {.next = &nodes9[138], .payload = {.id = 201, .data = (double)60.588449}}, + {.next = &nodes9[164], .payload = {.id = 120, .data = (double)-17.354368}}, + {.next = &nodes9[172], .payload = {.id = 68, .data = (double)-4.826163}}, + {.next = &nodes9[25], .payload = {.id = 60, .data = (double)-22.907623}}, + {.next = &nodes9[195], .payload = {.id = 67, .data = (double)-80.740285}}, + {.next = &nodes9[22], .payload = {.id = 140, .data = (double)39.411482}}, + {.next = &nodes9[117], .payload = {.id = 47, .data = (double)-65.886643}}, + {.next = &nodes9[197], .payload = {.id = 66, .data = (double)-70.087761}}, + {.next = &nodes9[124], .payload = {.id = 156, .data = (double)4.201109}}, + {.next = &nodes9[191], .payload = {.id = 92, .data = (double)39.341521}}, + {.next = &nodes9[20], .payload = {.id = 83, .data = (double)-91.312343}}, + {.next = &nodes9[73], .payload = {.id = 25, .data = (double)66.672999}}, + {.next = &nodes9[59], .payload = {.id = 148, .data = (double)-12.924513}}, + {.next = &nodes9[5], .payload = {.id = 97, .data = (double)71.810649}}, + {.next = &nodes9[11], .payload = {.id = 53, .data = (double)31.92975}}, + {.next = &nodes9[148], .payload = {.id = 172, .data = (double)-92.787773}}, + {.next = &nodes9[14], .payload = {.id = 3, .data = (double)-29.420398}}, + {.next = &nodes9[209], .payload = {.id = 2, .data = (double)3.274356}}, + {.next = &nodes9[45], .payload = {.id = 176, .data = (double)99.363429}}, + {.next = &nodes9[9], .payload = {.id = 250, .data = (double)84.037626}}, + {.next = &nodes9[110], .payload = {.id = 254, .data = (double)52.848843}}, + {.next = &nodes9[72], .payload = {.id = 132, .data = (double)49.562839}}, + {.next = &nodes9[185], .payload = {.id = 178, .data = (double)-29.374467}}, + {.next = &nodes9[132], .payload = {.id = 30, .data = (double)25.908085}}, + {.next = &nodes9[100], .payload = {.id = 117, .data = (double)-44.887891}}, + {.next = &nodes9[162], .payload = {.id = 44, .data = (double)-10.159328}}, + {.next = &nodes9[190], .payload = {.id = 198, .data = (double)-85.522806}}, + {.next = &nodes9[211], .payload = {.id = 175, .data = (double)-68.511048}}, + {.next = &nodes9[175], .payload = {.id = 220, .data = (double)35.382595}}, + {.next = &nodes9[236], .payload = {.id = 100, .data = (double)-18.270659}}, + {.next = &nodes9[131], .payload = {.id = 88, .data = (double)-23.752701}}, + {.next = &nodes9[4], .payload = {.id = 128, .data = (double)41.098922}}, + {.next = &nodes9[101], .payload = {.id = 8, .data = (double)0.367397}}, + {.next = &nodes9[83], .payload = {.id = 138, .data = (double)-32.312431}}, + {.next = &nodes9[253], .payload = {.id = 122, .data = (double)-3.506449}}, + {.next = &nodes9[19], .payload = {.id = 108, .data = (double)37.553347}}, + {.next = &nodes9[10], .payload = {.id = 204, .data = (double)62.62947}}, + {.next = &nodes9[71], .payload = {.id = 134, .data = (double)39.862288}}, + {.next = &nodes9[53], .payload = {.id = 13, .data = (double)-57.696579}}, + {.next = &nodes9[177], .payload = {.id = 32, .data = (double)14.45386}}, + {.next = &nodes9[173], .payload = {.id = 245, .data = (double)-59.446688}}, + {.next = &nodes9[113], .payload = {.id = 192, .data = (double)-61.094961}}, + {.next = &nodes9[120], .payload = {.id = 56, .data = (double)-31.465745}}, + {.next = &nodes9[182], .payload = {.id = 101, .data = (double)-62.195797}}, + {.next = &nodes9[128], .payload = {.id = 71, .data = (double)56.773647}}, + {.next = &nodes9[18], .payload = {.id = 130, .data = (double)70.999785}}, + {.next = &nodes9[86], .payload = {.id = 234, .data = (double)-29.292415}}, + {.next = &nodes9[171], .payload = {.id = 195, .data = (double)-47.778499}}, + {.next = &nodes9[199], .payload = {.id = 46, .data = (double)73.46048}}, + {.next = &nodes9[249], .payload = {.id = 125, .data = (double)-49.244471}}, + {.next = &nodes9[237], .payload = {.id = 70, .data = (double)-92.192687}}, + {.next = &nodes9[135], .payload = {.id = 222, .data = (double)-36.853861}}, + {.next = &nodes9[205], .payload = {.id = 147, .data = (double)85.172358}}, + {.next = &nodes9[57], .payload = {.id = 248, .data = (double)-68.800886}}, + {.next = &nodes9[137], .payload = {.id = 225, .data = (double)-98.055362}}, + {.next = &nodes9[58], .payload = {.id = 229, .data = (double)34.739583}}, + {.next = &nodes9[189], .payload = {.id = 126, .data = (double)-38.669383}}, + {.next = &nodes9[109], .payload = {.id = 80, .data = (double)29.846347}}, + {.next = &nodes9[91], .payload = {.id = 158, .data = (double)19.494513}}, + {.next = &nodes9[95], .payload = {.id = 95, .data = (double)-4.571753}}, + {.next = &nodes9[155], .payload = {.id = 123, .data = (double)-25.957406}}, + {.next = &nodes9[129], .payload = {.id = 217, .data = (double)-86.489148}}, + {.next = &nodes9[41], .payload = {.id = 21, .data = (double)-3.69667}}, +}; + +node_t nodes10[] = { + {.next = &nodes10[187], .payload = {.id = 177, .data = (double)-97.382778}}, + {.next = &nodes10[252], .payload = {.id = 148, .data = (double)24.039463}}, + {.next = &nodes10[225], .payload = {.id = 151, .data = (double)93.432631}}, + {.next = &nodes10[11], .payload = {.id = 116, .data = (double)28.929196}}, + {.next = &nodes10[254], .payload = {.id = 92, .data = (double)58.878079}}, + {.next = &nodes10[37], .payload = {.id = 51, .data = (double)39.386961}}, + {.next = &nodes10[81], .payload = {.id = 173, .data = (double)18.060182}}, + {.next = &nodes10[16], .payload = {.id = 3, .data = (double)-40.077896}}, + {.next = &nodes10[213], .payload = {.id = 84, .data = (double)-40.237383}}, + {.next = &nodes10[71], .payload = {.id = 249, .data = (double)83.822417}}, + {.next = &nodes10[182], .payload = {.id = 99, .data = (double)37.681308}}, + {.next = &nodes10[124], .payload = {.id = 117, .data = (double)-30.536452}}, + {.next = &nodes10[10], .payload = {.id = 98, .data = (double)38.150283}}, + {.next = &nodes10[241], .payload = {.id = 54, .data = (double)50.113916}}, + {.next = &nodes10[31], .payload = {.id = 220, .data = (double)80.496994}}, + {.next = &nodes10[108], .payload = {.id = 242, .data = (double)-98.686234}}, + {.next = &nodes10[125], .payload = {.id = 4, .data = (double)53.173841}}, + {.next = &nodes10[47], .payload = {.id = 165, .data = (double)-93.745249}}, + {.next = &nodes10[231], .payload = {.id = 229, .data = (double)9.125248}}, + {.next = &nodes10[145], .payload = {.id = 17, .data = (double)-84.158053}}, + {.next = &nodes10[104], .payload = {.id = 0, .data = (double)37.553993}}, + {.next = &nodes10[43], .payload = {.id = 119, .data = (double)46.637766}}, + {.next = &nodes10[4], .payload = {.id = 91, .data = (double)-96.986459}}, + {.next = &nodes10[227], .payload = {.id = 208, .data = (double)15.312732}}, + {.next = &nodes10[2], .payload = {.id = 150, .data = (double)-87.331649}}, + {.next = &nodes10[247], .payload = {.id = 75, .data = (double)-22.175408}}, + {.next = &nodes10[22], .payload = {.id = 90, .data = (double)-13.16767}}, + {.next = &nodes10[19], .payload = {.id = 16, .data = (double)-55.881515}}, + {.next = &nodes10[161], .payload = {.id = 223, .data = (double)68.970803}}, + {.next = &nodes10[28], .payload = {.id = 222, .data = (double)99.370063}}, + {.next = &nodes10[13], .payload = {.id = 53, .data = (double)-83.955381}}, + {.next = &nodes10[29], .payload = {.id = 221, .data = (double)10.016268}}, + {.next = &nodes10[60], .payload = {.id = 40, .data = (double)-43.577092}}, + {.next = &nodes10[134], .payload = {.id = 141, .data = (double)-9.184204}}, + {.next = &nodes10[123], .payload = {.id = 103, .data = (double)-0.016159}}, + {.next = &nodes10[173], .payload = {.id = 181, .data = (double)66.41554}}, + {.next = &nodes10[114], .payload = {.id = 193, .data = (double)66.8913}}, + {.next = &nodes10[30], .payload = {.id = 52, .data = (double)-93.652576}}, + {.next = &nodes10[196], .payload = {.id = 77, .data = (double)87.243049}}, + {.next = &nodes10[203], .payload = {.id = 153, .data = (double)-62.02611}}, + {.next = &nodes10[77], .payload = {.id = 200, .data = (double)-61.37611}}, + {.next = &nodes10[27], .payload = {.id = 15, .data = (double)65.685371}}, + {.next = &nodes10[249], .payload = {.id = 64, .data = (double)94.919701}}, + {.next = &nodes10[168], .payload = {.id = 120, .data = (double)-95.729433}}, + {.next = &nodes10[105], .payload = {.id = 35, .data = (double)-35.871255}}, + {.next = &nodes10[235], .payload = {.id = 122, .data = (double)44.879832}}, + {.next = &nodes10[158], .payload = {.id = 170, .data = (double)-22.280236}}, + {.next = &nodes10[204], .payload = {.id = 166, .data = (double)-78.588966}}, + {.next = &nodes10[184], .payload = {.id = 11, .data = (double)-12.578727}}, + {.next = &nodes10[207], .payload = {.id = 213, .data = (double)58.49232}}, + {.next = &nodes10[193], .payload = {.id = 80, .data = (double)48.944916}}, + {.next = &nodes10[205], .payload = {.id = 190, .data = (double)23.386665}}, + {.next = &nodes10[211], .payload = {.id = 252, .data = (double)14.322366}}, + {.next = &nodes10[198], .payload = {.id = 217, .data = (double)6.780095}}, + {.next = &nodes10[67], .payload = {.id = 72, .data = (double)-81.207939}}, + {.next = &nodes10[66], .payload = {.id = 45, .data = (double)-97.055031}}, + {.next = &nodes10[111], .payload = {.id = 131, .data = (double)-35.263825}}, + {.next = &nodes10[54], .payload = {.id = 71, .data = (double)47.064556}}, + {.next = &nodes10[35], .payload = {.id = 180, .data = (double)85.680744}}, + {.next = &nodes10[253], .payload = {.id = 226, .data = (double)65.230995}}, + {.next = &nodes10[96], .payload = {.id = 41, .data = (double)-74.992159}}, + {.next = &nodes10[63], .payload = {.id = 126, .data = (double)11.804958}}, + {.next = &nodes10[15], .payload = {.id = 241, .data = (double)78.064912}}, + {.next = &nodes10[188], .payload = {.id = 127, .data = (double)8.546815}}, + {.next = &nodes10[51], .payload = {.id = 189, .data = (double)-88.339995}}, + {.next = &nodes10[9], .payload = {.id = 248, .data = (double)64.467492}}, + {.next = &nodes10[119], .payload = {.id = 46, .data = (double)-56.562383}}, + {.next = &nodes10[174], .payload = {.id = 73, .data = (double)33.201577}}, + {.next = &nodes10[154], .payload = {.id = 49, .data = (double)-0.320849}}, + {.next = &nodes10[222], .payload = {.id = 8, .data = (double)9.642439}}, + {.next = &nodes10[138], .payload = {.id = 107, .data = (double)51.912033}}, + {.next = &nodes10[147], .payload = {.id = 250, .data = (double)2.254298}}, + {.next = &nodes10[101], .payload = {.id = 159, .data = (double)-35.595189}}, + {.next = &nodes10[88], .payload = {.id = 157, .data = (double)-43.374183}}, + {.next = &nodes10[162], .payload = {.id = 168, .data = (double)-93.63657}}, + {.next = &nodes10[165], .payload = {.id = 139, .data = (double)63.88371}}, + {.next = &nodes10[69], .payload = {.id = 7, .data = (double)59.353477}}, + {.next = &nodes10[236], .payload = {.id = 201, .data = (double)31.375303}}, + {.next = &nodes10[171], .payload = {.id = 32, .data = (double)-9.446553}}, + {.next = &nodes10[61], .payload = {.id = 125, .data = (double)41.325196}}, + {.next = &nodes10[224], .payload = {.id = 163, .data = (double)87.559907}}, + {.next = &nodes10[143], .payload = {.id = 174, .data = (double)-90.182875}}, + {.next = NULL, .payload = {.id = 255, .data = (double)-68.778579}}, + {.next = &nodes10[216], .payload = {.id = 198, .data = (double)-53.796399}}, + {.next = &nodes10[36], .payload = {.id = 192, .data = (double)46.860068}}, + {.next = &nodes10[3], .payload = {.id = 115, .data = (double)11.670088}}, + {.next = &nodes10[146], .payload = {.id = 61, .data = (double)-49.984107}}, + {.next = &nodes10[57], .payload = {.id = 70, .data = (double)-60.164025}}, + {.next = &nodes10[72], .payload = {.id = 158, .data = (double)-18.039094}}, + {.next = &nodes10[163], .payload = {.id = 66, .data = (double)-23.04042}}, + {.next = &nodes10[87], .payload = {.id = 69, .data = (double)98.907082}}, + {.next = &nodes10[117], .payload = {.id = 95, .data = (double)-51.382133}}, + {.next = &nodes10[140], .payload = {.id = 27, .data = (double)-62.399875}}, + {.next = &nodes10[220], .payload = {.id = 205, .data = (double)11.628321}}, + {.next = &nodes10[128], .payload = {.id = 112, .data = (double)-78.521669}}, + {.next = &nodes10[92], .payload = {.id = 26, .data = (double)-46.235595}}, + {.next = &nodes10[130], .payload = {.id = 42, .data = (double)-12.316673}}, + {.next = &nodes10[189], .payload = {.id = 236, .data = (double)-99.960874}}, + {.next = &nodes10[86], .payload = {.id = 60, .data = (double)79.139796}}, + {.next = &nodes10[206], .payload = {.id = 57, .data = (double)-21.515645}}, + {.next = &nodes10[118], .payload = {.id = 238, .data = (double)-43.103566}}, + {.next = &nodes10[199], .payload = {.id = 160, .data = (double)-80.748741}}, + {.next = &nodes10[195], .payload = {.id = 133, .data = (double)73.532368}}, + {.next = &nodes10[56], .payload = {.id = 130, .data = (double)8.724109}}, + {.next = &nodes10[202], .payload = {.id = 1, .data = (double)-1.613669}}, + {.next = &nodes10[172], .payload = {.id = 36, .data = (double)-69.570139}}, + {.next = &nodes10[73], .payload = {.id = 156, .data = (double)-69.173697}}, + {.next = &nodes10[153], .payload = {.id = 232, .data = (double)48.91567}}, + {.next = &nodes10[164], .payload = {.id = 243, .data = (double)96.878885}}, + {.next = &nodes10[50], .payload = {.id = 79, .data = (double)45.647416}}, + {.next = &nodes10[78], .payload = {.id = 31, .data = (double)-8.931397}}, + {.next = &nodes10[102], .payload = {.id = 132, .data = (double)-6.321056}}, + {.next = &nodes10[91], .payload = {.id = 94, .data = (double)-20.83834}}, + {.next = &nodes10[200], .payload = {.id = 215, .data = (double)0.938556}}, + {.next = &nodes10[148], .payload = {.id = 194, .data = (double)-84.412925}}, + {.next = &nodes10[175], .payload = {.id = 109, .data = (double)-28.896465}}, + {.next = &nodes10[192], .payload = {.id = 137, .data = (double)6.227486}}, + {.next = &nodes10[218], .payload = {.id = 96, .data = (double)93.766986}}, + {.next = &nodes10[221], .payload = {.id = 239, .data = (double)-96.73951}}, + {.next = &nodes10[135], .payload = {.id = 47, .data = (double)-15.951395}}, + {.next = &nodes10[133], .payload = {.id = 87, .data = (double)33.338957}}, + {.next = &nodes10[95], .payload = {.id = 25, .data = (double)6.388853}}, + {.next = &nodes10[208], .payload = {.id = 29, .data = (double)-72.675193}}, + {.next = &nodes10[139], .payload = {.id = 104, .data = (double)37.188929}}, + {.next = &nodes10[21], .payload = {.id = 118, .data = (double)78.35919}}, + {.next = &nodes10[132], .payload = {.id = 5, .data = (double)59.592955}}, + {.next = &nodes10[107], .payload = {.id = 231, .data = (double)10.047741}}, + {.next = &nodes10[166], .payload = {.id = 183, .data = (double)27.783343}}, + {.next = &nodes10[181], .payload = {.id = 113, .data = (double)-2.431424}}, + {.next = &nodes10[116], .payload = {.id = 136, .data = (double)-67.931318}}, + {.next = &nodes10[234], .payload = {.id = 43, .data = (double)-98.359182}}, + {.next = &nodes10[214], .payload = {.id = 196, .data = (double)3.897055}}, + {.next = &nodes10[76], .payload = {.id = 6, .data = (double)19.40075}}, + {.next = &nodes10[212], .payload = {.id = 88, .data = (double)94.654812}}, + {.next = &nodes10[155], .payload = {.id = 142, .data = (double)55.183581}}, + {.next = &nodes10[68], .payload = {.id = 48, .data = (double)57.145068}}, + {.next = &nodes10[49], .payload = {.id = 212, .data = (double)-79.179521}}, + {.next = &nodes10[82], .payload = {.id = 254, .data = (double)-7.926039}}, + {.next = &nodes10[115], .payload = {.id = 108, .data = (double)-87.989533}}, + {.next = &nodes10[209], .payload = {.id = 105, .data = (double)-32.315581}}, + {.next = &nodes10[122], .payload = {.id = 28, .data = (double)-86.307209}}, + {.next = &nodes10[246], .payload = {.id = 22, .data = (double)38.784912}}, + {.next = &nodes10[237], .payload = {.id = 82, .data = (double)-75.571698}}, + {.next = &nodes10[230], .payload = {.id = 175, .data = (double)-55.855443}}, + {.next = &nodes10[90], .payload = {.id = 68, .data = (double)-50.567562}}, + {.next = &nodes10[239], .payload = {.id = 18, .data = (double)25.064603}}, + {.next = &nodes10[251], .payload = {.id = 62, .data = (double)-23.684518}}, + {.next = &nodes10[52], .payload = {.id = 251, .data = (double)14.133641}}, + {.next = &nodes10[131], .payload = {.id = 195, .data = (double)-56.819987}}, + {.next = &nodes10[106], .payload = {.id = 155, .data = (double)53.146819}}, + {.next = &nodes10[151], .payload = {.id = 203, .data = (double)89.500669}}, + {.next = &nodes10[93], .payload = {.id = 204, .data = (double)11.684696}}, + {.next = &nodes10[244], .payload = {.id = 101, .data = (double)54.1594}}, + {.next = &nodes10[242], .payload = {.id = 233, .data = (double)-27.998291}}, + {.next = &nodes10[5], .payload = {.id = 50, .data = (double)-25.720584}}, + {.next = &nodes10[191], .payload = {.id = 143, .data = (double)1.191547}}, + {.next = &nodes10[97], .payload = {.id = 235, .data = (double)91.964886}}, + {.next = &nodes10[44], .payload = {.id = 34, .data = (double)-1.600797}}, + {.next = &nodes10[183], .payload = {.id = 171, .data = (double)-2.018072}}, + {.next = &nodes10[232], .payload = {.id = 210, .data = (double)40.510083}}, + {.next = &nodes10[64], .payload = {.id = 188, .data = (double)58.849915}}, + {.next = &nodes10[180], .payload = {.id = 224, .data = (double)-17.531342}}, + {.next = &nodes10[46], .payload = {.id = 169, .data = (double)28.350334}}, + {.next = &nodes10[144], .payload = {.id = 67, .data = (double)94.994443}}, + {.next = &nodes10[167], .payload = {.id = 244, .data = (double)-57.035437}}, + {.next = &nodes10[33], .payload = {.id = 140, .data = (double)8.32119}}, + {.next = &nodes10[238], .payload = {.id = 184, .data = (double)-27.81479}}, + {.next = &nodes10[177], .payload = {.id = 245, .data = (double)-37.019065}}, + {.next = &nodes10[45], .payload = {.id = 121, .data = (double)-24.446213}}, + {.next = &nodes10[141], .payload = {.id = 21, .data = (double)22.643244}}, + {.next = &nodes10[120], .payload = {.id = 86, .data = (double)-89.582497}}, + {.next = &nodes10[157], .payload = {.id = 33, .data = (double)40.09452}}, + {.next = &nodes10[190], .payload = {.id = 37, .data = (double)93.943244}}, + {.next = &nodes10[127], .payload = {.id = 182, .data = (double)-6.388171}}, + {.next = &nodes10[25], .payload = {.id = 74, .data = (double)-58.310574}}, + {.next = &nodes10[210], .payload = {.id = 110, .data = (double)-69.216313}}, + {.next = &nodes10[240], .payload = {.id = 186, .data = (double)78.086122}}, + {.next = &nodes10[223], .payload = {.id = 246, .data = (double)54.304614}}, + {.next = &nodes10[103], .payload = {.id = 129, .data = (double)13.340347}}, + {.next = &nodes10[14], .payload = {.id = 219, .data = (double)86.703994}}, + {.next = &nodes10[59], .payload = {.id = 225, .data = (double)26.648164}}, + {.next = &nodes10[85], .payload = {.id = 114, .data = (double)-36.652088}}, + {.next = &nodes10[152], .payload = {.id = 100, .data = (double)-69.001612}}, + {.next = &nodes10[6], .payload = {.id = 172, .data = (double)24.794097}}, + {.next = &nodes10[197], .payload = {.id = 12, .data = (double)-50.020776}}, + {.next = &nodes10[32], .payload = {.id = 39, .data = (double)94.466521}}, + {.next = &nodes10[99], .payload = {.id = 56, .data = (double)-46.699284}}, + {.next = &nodes10[229], .payload = {.id = 178, .data = (double)84.207042}}, + {.next = &nodes10[178], .payload = {.id = 128, .data = (double)-1.981601}}, + {.next = &nodes10[100], .payload = {.id = 237, .data = (double)-93.06742}}, + {.next = &nodes10[185], .payload = {.id = 38, .data = (double)-95.573823}}, + {.next = &nodes10[243], .payload = {.id = 144, .data = (double)46.731548}}, + {.next = &nodes10[75], .payload = {.id = 138, .data = (double)-10.12316}}, + {.next = &nodes10[142], .payload = {.id = 81, .data = (double)9.915989}}, + {.next = &nodes10[48], .payload = {.id = 10, .data = (double)76.432414}}, + {.next = &nodes10[255], .payload = {.id = 134, .data = (double)19.735989}}, + {.next = &nodes10[109], .payload = {.id = 78, .data = (double)-68.277713}}, + {.next = &nodes10[215], .payload = {.id = 13, .data = (double)42.987597}}, + {.next = &nodes10[179], .payload = {.id = 218, .data = (double)19.983146}}, + {.next = &nodes10[201], .payload = {.id = 161, .data = (double)31.778206}}, + {.next = &nodes10[53], .payload = {.id = 216, .data = (double)31.506376}}, + {.next = &nodes10[80], .payload = {.id = 162, .data = (double)-91.244547}}, + {.next = &nodes10[7], .payload = {.id = 2, .data = (double)51.09454}}, + {.next = &nodes10[149], .payload = {.id = 154, .data = (double)36.644837}}, + {.next = &nodes10[74], .payload = {.id = 167, .data = (double)-61.676672}}, + {.next = &nodes10[84], .payload = {.id = 191, .data = (double)5.804166}}, + {.next = &nodes10[250], .payload = {.id = 58, .data = (double)8.63839}}, + {.next = &nodes10[113], .payload = {.id = 214, .data = (double)9.993093}}, + {.next = &nodes10[110], .payload = {.id = 30, .data = (double)-77.92873}}, + {.next = &nodes10[70], .payload = {.id = 106, .data = (double)93.930341}}, + {.next = &nodes10[94], .payload = {.id = 111, .data = (double)7.270665}}, + {.next = &nodes10[137], .payload = {.id = 253, .data = (double)-81.142574}}, + {.next = &nodes10[26], .payload = {.id = 89, .data = (double)-52.806832}}, + {.next = &nodes10[170], .payload = {.id = 85, .data = (double)-27.914669}}, + {.next = &nodes10[83], .payload = {.id = 197, .data = (double)-79.754976}}, + {.next = &nodes10[41], .payload = {.id = 14, .data = (double)29.19816}}, + {.next = &nodes10[40], .payload = {.id = 199, .data = (double)-22.933782}}, + {.next = &nodes10[169], .payload = {.id = 20, .data = (double)59.991814}}, + {.next = &nodes10[12], .payload = {.id = 97, .data = (double)16.215405}}, + {.next = &nodes10[18], .payload = {.id = 228, .data = (double)-51.855489}}, + {.next = &nodes10[248], .payload = {.id = 206, .data = (double)49.221675}}, + {.next = &nodes10[62], .payload = {.id = 240, .data = (double)-72.982858}}, + {.next = &nodes10[194], .payload = {.id = 9, .data = (double)-62.285804}}, + {.next = &nodes10[65], .payload = {.id = 247, .data = (double)88.669581}}, + {.next = &nodes10[17], .payload = {.id = 164, .data = (double)-64.27224}}, + {.next = &nodes10[39], .payload = {.id = 152, .data = (double)63.809947}}, + {.next = &nodes10[121], .payload = {.id = 24, .data = (double)29.691408}}, + {.next = &nodes10[159], .payload = {.id = 209, .data = (double)34.898513}}, + {.next = &nodes10[1], .payload = {.id = 147, .data = (double)-27.184961}}, + {.next = &nodes10[58], .payload = {.id = 179, .data = (double)31.149872}}, + {.next = &nodes10[0], .payload = {.id = 176, .data = (double)43.569039}}, + {.next = &nodes10[126], .payload = {.id = 230, .data = (double)-24.987385}}, + {.next = &nodes10[136], .payload = {.id = 211, .data = (double)-14.585002}}, + {.next = &nodes10[79], .payload = {.id = 124, .data = (double)-92.102291}}, + {.next = &nodes10[55], .payload = {.id = 44, .data = (double)-81.960603}}, + {.next = &nodes10[233], .payload = {.id = 123, .data = (double)-49.860752}}, + {.next = &nodes10[150], .payload = {.id = 202, .data = (double)14.005534}}, + {.next = &nodes10[8], .payload = {.id = 83, .data = (double)-3.754081}}, + {.next = &nodes10[176], .payload = {.id = 185, .data = (double)48.695488}}, + {.next = &nodes10[217], .payload = {.id = 19, .data = (double)3.322012}}, + {.next = &nodes10[160], .payload = {.id = 187, .data = (double)64.405303}}, + {.next = &nodes10[186], .payload = {.id = 55, .data = (double)-70.782435}}, + {.next = &nodes10[156], .payload = {.id = 234, .data = (double)-9.519305}}, + {.next = &nodes10[245], .payload = {.id = 145, .data = (double)76.586475}}, + {.next = &nodes10[34], .payload = {.id = 102, .data = (double)-50.255549}}, + {.next = &nodes10[228], .payload = {.id = 146, .data = (double)23.946921}}, + {.next = &nodes10[226], .payload = {.id = 23, .data = (double)-45.626977}}, + {.next = &nodes10[38], .payload = {.id = 76, .data = (double)92.242779}}, + {.next = &nodes10[23], .payload = {.id = 207, .data = (double)53.256684}}, + {.next = &nodes10[89], .payload = {.id = 65, .data = (double)42.936504}}, + {.next = &nodes10[98], .payload = {.id = 59, .data = (double)-63.679252}}, + {.next = &nodes10[42], .payload = {.id = 63, .data = (double)-97.476902}}, + {.next = &nodes10[24], .payload = {.id = 149, .data = (double)-35.861181}}, + {.next = &nodes10[219], .payload = {.id = 227, .data = (double)-35.309816}}, + {.next = &nodes10[112], .payload = {.id = 93, .data = (double)16.939372}}, + {.next = &nodes10[129], .payload = {.id = 135, .data = (double)72.112172}}, +}; + +node_t nodes11[] = { + {.next = &nodes11[160], .payload = {.id = 206, .data = (double)25.79572}}, + {.next = &nodes11[109], .payload = {.id = 125, .data = (double)-10.120316}}, + {.next = &nodes11[87], .payload = {.id = 110, .data = (double)-72.938665}}, + {.next = &nodes11[134], .payload = {.id = 195, .data = (double)10.094217}}, + {.next = &nodes11[157], .payload = {.id = 0, .data = (double)81.947079}}, + {.next = &nodes11[218], .payload = {.id = 37, .data = (double)22.39632}}, + {.next = &nodes11[166], .payload = {.id = 24, .data = (double)53.087003}}, + {.next = &nodes11[228], .payload = {.id = 245, .data = (double)-98.773748}}, + {.next = &nodes11[82], .payload = {.id = 67, .data = (double)-35.020875}}, + {.next = &nodes11[231], .payload = {.id = 172, .data = (double)70.765857}}, + {.next = &nodes11[200], .payload = {.id = 179, .data = (double)-64.350322}}, + {.next = &nodes11[170], .payload = {.id = 186, .data = (double)-8.932434}}, + {.next = &nodes11[133], .payload = {.id = 217, .data = (double)-29.229331}}, + {.next = &nodes11[195], .payload = {.id = 239, .data = (double)-59.762572}}, + {.next = &nodes11[2], .payload = {.id = 109, .data = (double)39.222828}}, + {.next = &nodes11[184], .payload = {.id = 27, .data = (double)-17.749647}}, + {.next = &nodes11[8], .payload = {.id = 66, .data = (double)-2.01142}}, + {.next = &nodes11[62], .payload = {.id = 64, .data = (double)97.125528}}, + {.next = &nodes11[190], .payload = {.id = 114, .data = (double)18.063095}}, + {.next = &nodes11[249], .payload = {.id = 116, .data = (double)-59.613599}}, + {.next = &nodes11[118], .payload = {.id = 101, .data = (double)3.39393}}, + {.next = &nodes11[125], .payload = {.id = 231, .data = (double)69.613958}}, + {.next = &nodes11[9], .payload = {.id = 171, .data = (double)-92.65579}}, + {.next = &nodes11[20], .payload = {.id = 100, .data = (double)-89.090667}}, + {.next = &nodes11[129], .payload = {.id = 2, .data = (double)8.44675}}, + {.next = &nodes11[72], .payload = {.id = 92, .data = (double)-90.14091}}, + {.next = &nodes11[191], .payload = {.id = 94, .data = (double)-20.392022}}, + {.next = &nodes11[84], .payload = {.id = 209, .data = (double)37.730856}}, + {.next = &nodes11[255], .payload = {.id = 17, .data = (double)-36.500758}}, + {.next = &nodes11[93], .payload = {.id = 233, .data = (double)99.797401}}, + {.next = &nodes11[71], .payload = {.id = 103, .data = (double)65.978701}}, + {.next = &nodes11[219], .payload = {.id = 15, .data = (double)86.605989}}, + {.next = &nodes11[145], .payload = {.id = 224, .data = (double)21.881152}}, + {.next = &nodes11[210], .payload = {.id = 41, .data = (double)-53.563493}}, + {.next = &nodes11[40], .payload = {.id = 62, .data = (double)-86.772735}}, + {.next = &nodes11[252], .payload = {.id = 122, .data = (double)43.674944}}, + {.next = &nodes11[59], .payload = {.id = 19, .data = (double)89.720313}}, + {.next = &nodes11[34], .payload = {.id = 61, .data = (double)51.555318}}, + {.next = &nodes11[167], .payload = {.id = 35, .data = (double)-63.050701}}, + {.next = &nodes11[209], .payload = {.id = 145, .data = (double)-10.748353}}, + {.next = &nodes11[17], .payload = {.id = 63, .data = (double)85.420641}}, + {.next = &nodes11[156], .payload = {.id = 168, .data = (double)-90.21624}}, + {.next = &nodes11[236], .payload = {.id = 212, .data = (double)-42.562539}}, + {.next = &nodes11[164], .payload = {.id = 32, .data = (double)-45.240767}}, + {.next = &nodes11[142], .payload = {.id = 197, .data = (double)-73.090842}}, + {.next = &nodes11[113], .payload = {.id = 161, .data = (double)-84.119017}}, + {.next = &nodes11[128], .payload = {.id = 148, .data = (double)-73.685794}}, + {.next = &nodes11[153], .payload = {.id = 193, .data = (double)-86.466664}}, + {.next = &nodes11[233], .payload = {.id = 143, .data = (double)-38.096339}}, + {.next = &nodes11[161], .payload = {.id = 248, .data = (double)44.879329}}, + {.next = &nodes11[92], .payload = {.id = 74, .data = (double)-37.420502}}, + {.next = &nodes11[77], .payload = {.id = 97, .data = (double)-7.730567}}, + {.next = &nodes11[69], .payload = {.id = 183, .data = (double)18.993797}}, + {.next = &nodes11[12], .payload = {.id = 216, .data = (double)99.004867}}, + {.next = &nodes11[211], .payload = {.id = 135, .data = (double)82.450556}}, + {.next = &nodes11[248], .payload = {.id = 227, .data = (double)-99.683817}}, + {.next = &nodes11[130], .payload = {.id = 157, .data = (double)-52.424329}}, + {.next = &nodes11[13], .payload = {.id = 238, .data = (double)-97.740546}}, + {.next = &nodes11[1], .payload = {.id = 124, .data = (double)-77.167012}}, + {.next = &nodes11[114], .payload = {.id = 20, .data = (double)-76.322542}}, + {.next = &nodes11[14], .payload = {.id = 108, .data = (double)87.568492}}, + {.next = &nodes11[186], .payload = {.id = 188, .data = (double)86.295964}}, + {.next = &nodes11[16], .payload = {.id = 65, .data = (double)73.425801}}, + {.next = &nodes11[32], .payload = {.id = 223, .data = (double)-64.018554}}, + {.next = &nodes11[49], .payload = {.id = 247, .data = (double)-31.727683}}, + {.next = &nodes11[239], .payload = {.id = 236, .data = (double)12.083101}}, + {.next = &nodes11[206], .payload = {.id = 46, .data = (double)0.464917}}, + {.next = &nodes11[254], .payload = {.id = 164, .data = (double)9.468322}}, + {.next = &nodes11[35], .payload = {.id = 121, .data = (double)59.297244}}, + {.next = &nodes11[232], .payload = {.id = 184, .data = (double)57.461516}}, + {.next = &nodes11[124], .payload = {.id = 130, .data = (double)2.33329}}, + {.next = &nodes11[240], .payload = {.id = 104, .data = (double)-9.660382}}, + {.next = &nodes11[26], .payload = {.id = 93, .data = (double)-41.764128}}, + {.next = &nodes11[208], .payload = {.id = 154, .data = (double)8.700232}}, + {.next = &nodes11[80], .payload = {.id = 58, .data = (double)-17.391196}}, + {.next = &nodes11[101], .payload = {.id = 12, .data = (double)99.13716}}, + {.next = &nodes11[25], .payload = {.id = 91, .data = (double)26.129711}}, + {.next = &nodes11[207], .payload = {.id = 98, .data = (double)-15.507564}}, + {.next = &nodes11[102], .payload = {.id = 106, .data = (double)-77.365683}}, + {.next = &nodes11[140], .payload = {.id = 72, .data = (double)47.066356}}, + {.next = &nodes11[192], .payload = {.id = 59, .data = (double)48.473332}}, + {.next = &nodes11[155], .payload = {.id = 10, .data = (double)4.761097}}, + {.next = &nodes11[196], .payload = {.id = 68, .data = (double)-8.491014}}, + {.next = &nodes11[117], .payload = {.id = 166, .data = (double)11.50973}}, + {.next = &nodes11[138], .payload = {.id = 210, .data = (double)86.778335}}, + {.next = &nodes11[131], .payload = {.id = 138, .data = (double)-69.982053}}, + {.next = &nodes11[66], .payload = {.id = 45, .data = (double)-4.679556}}, + {.next = &nodes11[136], .payload = {.id = 111, .data = (double)-17.288139}}, + {.next = &nodes11[74], .payload = {.id = 57, .data = (double)-46.028259}}, + {.next = &nodes11[220], .payload = {.id = 89, .data = (double)11.54019}}, + {.next = &nodes11[89], .payload = {.id = 88, .data = (double)47.034016}}, + {.next = &nodes11[242], .payload = {.id = 199, .data = (double)-45.116291}}, + {.next = &nodes11[234], .payload = {.id = 75, .data = (double)22.300975}}, + {.next = &nodes11[159], .payload = {.id = 234, .data = (double)-17.191772}}, + {.next = &nodes11[205], .payload = {.id = 151, .data = (double)-49.377805}}, + {.next = &nodes11[73], .payload = {.id = 153, .data = (double)71.082211}}, + {.next = &nodes11[181], .payload = {.id = 50, .data = (double)70.425886}}, + {.next = &nodes11[188], .payload = {.id = 54, .data = (double)-93.554089}}, + {.next = &nodes11[94], .payload = {.id = 150, .data = (double)24.512066}}, + {.next = &nodes11[152], .payload = {.id = 243, .data = (double)1.337925}}, + {.next = &nodes11[229], .payload = {.id = 141, .data = (double)42.409498}}, + {.next = &nodes11[237], .payload = {.id = 13, .data = (double)95.155382}}, + {.next = &nodes11[60], .payload = {.id = 107, .data = (double)55.746228}}, + {.next = &nodes11[216], .payload = {.id = 214, .data = (double)-36.702288}}, + {.next = &nodes11[221], .payload = {.id = 202, .data = (double)39.165899}}, + {.next = &nodes11[10], .payload = {.id = 178, .data = (double)-16.608615}}, + {.next = &nodes11[119], .payload = {.id = 219, .data = (double)12.526868}}, + {.next = &nodes11[105], .payload = {.id = 177, .data = (double)-90.193727}}, + {.next = &nodes11[88], .payload = {.id = 56, .data = (double)-96.997148}}, + {.next = &nodes11[193], .payload = {.id = 126, .data = (double)-27.411322}}, + {.next = &nodes11[185], .payload = {.id = 43, .data = (double)-28.147733}}, + {.next = &nodes11[104], .payload = {.id = 201, .data = (double)4.929242}}, + {.next = &nodes11[224], .payload = {.id = 174, .data = (double)67.602887}}, + {.next = &nodes11[127], .payload = {.id = 162, .data = (double)20.020421}}, + {.next = &nodes11[194], .payload = {.id = 21, .data = (double)-36.480482}}, + {.next = &nodes11[43], .payload = {.id = 31, .data = (double)86.650006}}, + {.next = &nodes11[100], .payload = {.id = 140, .data = (double)-64.226647}}, + {.next = &nodes11[41], .payload = {.id = 167, .data = (double)65.050501}}, + {.next = &nodes11[30], .payload = {.id = 102, .data = (double)-71.552076}}, + {.next = &nodes11[247], .payload = {.id = 220, .data = (double)3.94116}}, + {.next = &nodes11[68], .payload = {.id = 120, .data = (double)81.432493}}, + {.next = NULL, .payload = {.id = 255, .data = (double)83.232611}}, + {.next = &nodes11[123], .payload = {.id = 253, .data = (double)-32.412629}}, + {.next = &nodes11[121], .payload = {.id = 254, .data = (double)34.494591}}, + {.next = &nodes11[165], .payload = {.id = 131, .data = (double)89.950778}}, + {.next = &nodes11[29], .payload = {.id = 232, .data = (double)59.91287}}, + {.next = &nodes11[22], .payload = {.id = 170, .data = (double)30.655376}}, + {.next = &nodes11[67], .payload = {.id = 163, .data = (double)-51.057366}}, + {.next = &nodes11[98], .payload = {.id = 149, .data = (double)-59.429659}}, + {.next = &nodes11[227], .payload = {.id = 3, .data = (double)-58.648545}}, + {.next = &nodes11[148], .payload = {.id = 158, .data = (double)17.772465}}, + {.next = &nodes11[116], .payload = {.id = 139, .data = (double)73.763707}}, + {.next = &nodes11[33], .payload = {.id = 40, .data = (double)-53.81773}}, + {.next = &nodes11[106], .payload = {.id = 218, .data = (double)-74.057372}}, + {.next = &nodes11[44], .payload = {.id = 196, .data = (double)-41.433457}}, + {.next = &nodes11[115], .payload = {.id = 30, .data = (double)78.826019}}, + {.next = &nodes11[179], .payload = {.id = 112, .data = (double)-9.822829}}, + {.next = &nodes11[143], .payload = {.id = 81, .data = (double)4.129818}}, + {.next = &nodes11[42], .payload = {.id = 211, .data = (double)97.255688}}, + {.next = &nodes11[217], .payload = {.id = 70, .data = (double)-19.026646}}, + {.next = &nodes11[50], .payload = {.id = 73, .data = (double)-23.925166}}, + {.next = &nodes11[96], .payload = {.id = 49, .data = (double)-25.20812}}, + {.next = &nodes11[91], .payload = {.id = 198, .data = (double)38.923888}}, + {.next = &nodes11[168], .payload = {.id = 82, .data = (double)-9.678081}}, + {.next = &nodes11[55], .payload = {.id = 226, .data = (double)95.851532}}, + {.next = &nodes11[144], .payload = {.id = 225, .data = (double)41.717414}}, + {.next = &nodes11[177], .payload = {.id = 5, .data = (double)8.270765}}, + {.next = &nodes11[56], .payload = {.id = 156, .data = (double)76.540584}}, + {.next = &nodes11[250], .payload = {.id = 159, .data = (double)-4.857602}}, + {.next = &nodes11[15], .payload = {.id = 26, .data = (double)-17.191969}}, + {.next = &nodes11[203], .payload = {.id = 241, .data = (double)58.039101}}, + {.next = &nodes11[120], .payload = {.id = 119, .data = (double)38.343486}}, + {.next = &nodes11[7], .payload = {.id = 244, .data = (double)-35.215232}}, + {.next = &nodes11[3], .payload = {.id = 194, .data = (double)-14.535232}}, + {.next = &nodes11[0], .payload = {.id = 205, .data = (double)45.945704}}, + {.next = &nodes11[75], .payload = {.id = 11, .data = (double)-72.949501}}, + {.next = &nodes11[126], .payload = {.id = 169, .data = (double)-70.348766}}, + {.next = &nodes11[24], .payload = {.id = 1, .data = (double)-34.143052}}, + {.next = &nodes11[63], .payload = {.id = 222, .data = (double)-1.499109}}, + {.next = &nodes11[65], .payload = {.id = 235, .data = (double)-33.241549}}, + {.next = &nodes11[241], .payload = {.id = 207, .data = (double)97.437853}}, + {.next = &nodes11[212], .payload = {.id = 249, .data = (double)23.198669}}, + {.next = &nodes11[52], .payload = {.id = 182, .data = (double)38.302724}}, + {.next = &nodes11[226], .payload = {.id = 52, .data = (double)-72.497456}}, + {.next = &nodes11[253], .payload = {.id = 33, .data = (double)55.821577}}, + {.next = &nodes11[235], .payload = {.id = 132, .data = (double)-24.264274}}, + {.next = &nodes11[149], .payload = {.id = 25, .data = (double)76.02638}}, + {.next = &nodes11[5], .payload = {.id = 36, .data = (double)52.489497}}, + {.next = &nodes11[223], .payload = {.id = 83, .data = (double)65.40202}}, + {.next = &nodes11[230], .payload = {.id = 79, .data = (double)75.156594}}, + {.next = &nodes11[61], .payload = {.id = 187, .data = (double)15.793258}}, + {.next = &nodes11[107], .payload = {.id = 176, .data = (double)84.07694}}, + {.next = &nodes11[90], .payload = {.id = 87, .data = (double)-20.877761}}, + {.next = &nodes11[141], .payload = {.id = 48, .data = (double)42.403826}}, + {.next = &nodes11[176], .payload = {.id = 251, .data = (double)-64.874182}}, + {.next = &nodes11[178], .payload = {.id = 128, .data = (double)-23.182525}}, + {.next = &nodes11[122], .payload = {.id = 252, .data = (double)-33.897034}}, + {.next = &nodes11[215], .payload = {.id = 6, .data = (double)60.021012}}, + {.next = &nodes11[70], .payload = {.id = 129, .data = (double)58.213319}}, + {.next = &nodes11[18], .payload = {.id = 113, .data = (double)-64.224284}}, + {.next = &nodes11[6], .payload = {.id = 23, .data = (double)45.415907}}, + {.next = &nodes11[163], .payload = {.id = 51, .data = (double)-1.710881}}, + {.next = &nodes11[81], .payload = {.id = 9, .data = (double)41.027278}}, + {.next = &nodes11[202], .payload = {.id = 191, .data = (double)-26.286115}}, + {.next = &nodes11[204], .payload = {.id = 28, .data = (double)-11.399103}}, + {.next = &nodes11[86], .payload = {.id = 44, .data = (double)37.628257}}, + {.next = &nodes11[238], .payload = {.id = 189, .data = (double)-81.374742}}, + {.next = &nodes11[54], .payload = {.id = 134, .data = (double)53.652065}}, + {.next = &nodes11[108], .payload = {.id = 55, .data = (double)52.907771}}, + {.next = &nodes11[201], .payload = {.id = 77, .data = (double)18.76116}}, + {.next = &nodes11[19], .payload = {.id = 115, .data = (double)42.526878}}, + {.next = &nodes11[213], .payload = {.id = 95, .data = (double)-39.08917}}, + {.next = &nodes11[37], .payload = {.id = 60, .data = (double)97.648683}}, + {.next = &nodes11[175], .payload = {.id = 127, .data = (double)4.763461}}, + {.next = &nodes11[180], .payload = {.id = 22, .data = (double)75.927624}}, + {.next = &nodes11[150], .payload = {.id = 240, .data = (double)-43.674659}}, + {.next = &nodes11[139], .payload = {.id = 69, .data = (double)-50.643232}}, + {.next = &nodes11[182], .payload = {.id = 8, .data = (double)-38.200321}}, + {.next = &nodes11[162], .payload = {.id = 181, .data = (double)22.217951}}, + {.next = &nodes11[21], .payload = {.id = 230, .data = (double)-76.414855}}, + {.next = &nodes11[198], .payload = {.id = 180, .data = (double)34.418099}}, + {.next = &nodes11[169], .payload = {.id = 78, .data = (double)5.046106}}, + {.next = &nodes11[47], .payload = {.id = 192, .data = (double)-24.21213}}, + {.next = &nodes11[99], .payload = {.id = 242, .data = (double)-38.44549}}, + {.next = &nodes11[135], .payload = {.id = 29, .data = (double)86.753705}}, + {.next = &nodes11[95], .payload = {.id = 152, .data = (double)-8.271468}}, + {.next = &nodes11[173], .payload = {.id = 47, .data = (double)20.942352}}, + {.next = &nodes11[23], .payload = {.id = 99, .data = (double)22.626856}}, + {.next = &nodes11[147], .payload = {.id = 155, .data = (double)-98.84989}}, + {.next = &nodes11[225], .payload = {.id = 146, .data = (double)25.29057}}, + {.next = &nodes11[110], .payload = {.id = 42, .data = (double)37.475577}}, + {.next = &nodes11[246], .payload = {.id = 136, .data = (double)13.098316}}, + {.next = &nodes11[174], .payload = {.id = 250, .data = (double)-94.176524}}, + {.next = &nodes11[51], .payload = {.id = 96, .data = (double)65.524202}}, + {.next = &nodes11[172], .payload = {.id = 86, .data = (double)3.740531}}, + {.next = &nodes11[197], .payload = {.id = 7, .data = (double)72.517532}}, + {.next = &nodes11[53], .payload = {.id = 215, .data = (double)5.078245}}, + {.next = &nodes11[79], .payload = {.id = 71, .data = (double)-91.634745}}, + {.next = &nodes11[251], .payload = {.id = 38, .data = (double)-46.627477}}, + {.next = &nodes11[28], .payload = {.id = 16, .data = (double)83.422424}}, + {.next = &nodes11[76], .payload = {.id = 90, .data = (double)3.225337}}, + {.next = &nodes11[222], .payload = {.id = 203, .data = (double)22.410749}}, + {.next = &nodes11[154], .payload = {.id = 204, .data = (double)-78.139553}}, + {.next = &nodes11[244], .payload = {.id = 84, .data = (double)-91.516817}}, + {.next = &nodes11[171], .payload = {.id = 175, .data = (double)-40.311691}}, + {.next = &nodes11[46], .payload = {.id = 147, .data = (double)-76.489204}}, + {.next = &nodes11[97], .payload = {.id = 53, .data = (double)-61.348034}}, + {.next = &nodes11[146], .payload = {.id = 4, .data = (double)-72.284695}}, + {.next = &nodes11[64], .payload = {.id = 246, .data = (double)37.167158}}, + {.next = &nodes11[48], .payload = {.id = 142, .data = (double)-16.083662}}, + {.next = &nodes11[137], .payload = {.id = 80, .data = (double)57.383972}}, + {.next = &nodes11[112], .payload = {.id = 173, .data = (double)33.399309}}, + {.next = &nodes11[11], .payload = {.id = 185, .data = (double)-64.516147}}, + {.next = &nodes11[39], .payload = {.id = 144, .data = (double)53.726084}}, + {.next = &nodes11[189], .payload = {.id = 76, .data = (double)48.493571}}, + {.next = &nodes11[187], .payload = {.id = 133, .data = (double)-23.878598}}, + {.next = &nodes11[103], .payload = {.id = 213, .data = (double)21.768921}}, + {.next = &nodes11[31], .payload = {.id = 14, .data = (double)-70.969521}}, + {.next = &nodes11[183], .payload = {.id = 190, .data = (double)-40.141104}}, + {.next = &nodes11[57], .payload = {.id = 237, .data = (double)27.500709}}, + {.next = &nodes11[78], .payload = {.id = 105, .data = (double)44.529358}}, + {.next = &nodes11[27], .payload = {.id = 208, .data = (double)-3.267403}}, + {.next = &nodes11[111], .payload = {.id = 200, .data = (double)5.410547}}, + {.next = &nodes11[151], .payload = {.id = 118, .data = (double)-49.983541}}, + {.next = &nodes11[214], .payload = {.id = 85, .data = (double)99.167274}}, + {.next = &nodes11[199], .payload = {.id = 229, .data = (double)25.092148}}, + {.next = &nodes11[85], .payload = {.id = 137, .data = (double)31.906068}}, + {.next = &nodes11[158], .payload = {.id = 221, .data = (double)26.371521}}, + {.next = &nodes11[245], .payload = {.id = 228, .data = (double)-95.20264}}, + {.next = &nodes11[243], .payload = {.id = 117, .data = (double)-9.063358}}, + {.next = &nodes11[45], .payload = {.id = 160, .data = (double)-17.969727}}, + {.next = &nodes11[132], .payload = {.id = 39, .data = (double)13.408619}}, + {.next = &nodes11[58], .payload = {.id = 123, .data = (double)-75.291157}}, + {.next = &nodes11[38], .payload = {.id = 34, .data = (double)-78.645713}}, + {.next = &nodes11[83], .payload = {.id = 165, .data = (double)23.953208}}, + {.next = &nodes11[36], .payload = {.id = 18, .data = (double)11.46806}}, +}; + +node_t nodes12[] = { + {.next = &nodes12[90], .payload = {.id = 242, .data = (double)-35.319174}}, + {.next = &nodes12[161], .payload = {.id = 34, .data = (double)-41.163067}}, + {.next = &nodes12[63], .payload = {.id = 149, .data = (double)-3.016297}}, + {.next = &nodes12[215], .payload = {.id = 130, .data = (double)61.779156}}, + {.next = &nodes12[242], .payload = {.id = 65, .data = (double)98.043528}}, + {.next = &nodes12[7], .payload = {.id = 71, .data = (double)20.885903}}, + {.next = &nodes12[222], .payload = {.id = 67, .data = (double)28.44858}}, + {.next = &nodes12[89], .payload = {.id = 72, .data = (double)-14.859166}}, + {.next = &nodes12[214], .payload = {.id = 180, .data = (double)-97.627392}}, + {.next = &nodes12[201], .payload = {.id = 97, .data = (double)55.773963}}, + {.next = &nodes12[94], .payload = {.id = 142, .data = (double)-65.07723}}, + {.next = &nodes12[138], .payload = {.id = 132, .data = (double)-42.636869}}, + {.next = &nodes12[36], .payload = {.id = 234, .data = (double)-6.608885}}, + {.next = &nodes12[141], .payload = {.id = 208, .data = (double)66.3379}}, + {.next = &nodes12[140], .payload = {.id = 29, .data = (double)-82.142519}}, + {.next = &nodes12[74], .payload = {.id = 46, .data = (double)-36.374538}}, + {.next = &nodes12[67], .payload = {.id = 118, .data = (double)59.644644}}, + {.next = &nodes12[251], .payload = {.id = 195, .data = (double)-80.344642}}, + {.next = &nodes12[167], .payload = {.id = 193, .data = (double)-33.006519}}, + {.next = &nodes12[98], .payload = {.id = 24, .data = (double)-39.089973}}, + {.next = &nodes12[9], .payload = {.id = 96, .data = (double)96.733676}}, + {.next = &nodes12[181], .payload = {.id = 116, .data = (double)-15.796779}}, + {.next = &nodes12[41], .payload = {.id = 32, .data = (double)-19.160517}}, + {.next = &nodes12[18], .payload = {.id = 192, .data = (double)71.671135}}, + {.next = &nodes12[228], .payload = {.id = 166, .data = (double)28.452219}}, + {.next = &nodes12[232], .payload = {.id = 3, .data = (double)62.813344}}, + {.next = &nodes12[3], .payload = {.id = 129, .data = (double)98.072966}}, + {.next = &nodes12[240], .payload = {.id = 7, .data = (double)32.032952}}, + {.next = &nodes12[31], .payload = {.id = 81, .data = (double)69.360777}}, + {.next = &nodes12[156], .payload = {.id = 60, .data = (double)-85.650801}}, + {.next = &nodes12[152], .payload = {.id = 203, .data = (double)-32.518679}}, + {.next = &nodes12[125], .payload = {.id = 82, .data = (double)-52.650007}}, + {.next = &nodes12[182], .payload = {.id = 19, .data = (double)-60.866676}}, + {.next = &nodes12[169], .payload = {.id = 245, .data = (double)55.42119}}, + {.next = &nodes12[230], .payload = {.id = 126, .data = (double)-5.367894}}, + {.next = &nodes12[83], .payload = {.id = 249, .data = (double)91.12114}}, + {.next = &nodes12[208], .payload = {.id = 235, .data = (double)87.236412}}, + {.next = &nodes12[184], .payload = {.id = 135, .data = (double)70.289051}}, + {.next = &nodes12[121], .payload = {.id = 79, .data = (double)20.914651}}, + {.next = &nodes12[206], .payload = {.id = 200, .data = (double)46.862691}}, + {.next = &nodes12[69], .payload = {.id = 218, .data = (double)87.701094}}, + {.next = &nodes12[1], .payload = {.id = 33, .data = (double)-74.488861}}, + {.next = &nodes12[170], .payload = {.id = 222, .data = (double)27.616577}}, + {.next = &nodes12[92], .payload = {.id = 40, .data = (double)-28.151074}}, + {.next = &nodes12[124], .payload = {.id = 152, .data = (double)-31.430401}}, + {.next = &nodes12[82], .payload = {.id = 210, .data = (double)-80.460248}}, + {.next = &nodes12[211], .payload = {.id = 121, .data = (double)84.572903}}, + {.next = &nodes12[76], .payload = {.id = 52, .data = (double)-62.354632}}, + {.next = &nodes12[176], .payload = {.id = 140, .data = (double)-97.159398}}, + {.next = &nodes12[146], .payload = {.id = 159, .data = (double)54.073558}}, + {.next = &nodes12[178], .payload = {.id = 50, .data = (double)32.497512}}, + {.next = &nodes12[236], .payload = {.id = 185, .data = (double)36.575262}}, + {.next = &nodes12[177], .payload = {.id = 44, .data = (double)40.444376}}, + {.next = &nodes12[0], .payload = {.id = 241, .data = (double)53.976102}}, + {.next = &nodes12[23], .payload = {.id = 191, .data = (double)83.608403}}, + {.next = &nodes12[229], .payload = {.id = 37, .data = (double)-89.374538}}, + {.next = &nodes12[20], .payload = {.id = 95, .data = (double)96.71582}}, + {.next = &nodes12[93], .payload = {.id = 177, .data = (double)-5.082084}}, + {.next = &nodes12[107], .payload = {.id = 107, .data = (double)59.619648}}, + {.next = &nodes12[26], .payload = {.id = 128, .data = (double)-89.676023}}, + {.next = &nodes12[248], .payload = {.id = 156, .data = (double)-69.16994}}, + {.next = &nodes12[30], .payload = {.id = 202, .data = (double)-61.014863}}, + {.next = &nodes12[126], .payload = {.id = 88, .data = (double)13.629916}}, + {.next = &nodes12[157], .payload = {.id = 150, .data = (double)59.874401}}, + {.next = &nodes12[25], .payload = {.id = 2, .data = (double)-78.251073}}, + {.next = &nodes12[243], .payload = {.id = 182, .data = (double)-10.235875}}, + {.next = &nodes12[227], .payload = {.id = 162, .data = (double)27.514933}}, + {.next = &nodes12[129], .payload = {.id = 119, .data = (double)-42.158311}}, + {.next = &nodes12[194], .payload = {.id = 90, .data = (double)-77.367126}}, + {.next = &nodes12[112], .payload = {.id = 219, .data = (double)31.321104}}, + {.next = &nodes12[137], .payload = {.id = 213, .data = (double)-56.116735}}, + {.next = &nodes12[203], .payload = {.id = 56, .data = (double)-69.146542}}, + {.next = &nodes12[202], .payload = {.id = 215, .data = (double)-61.384094}}, + {.next = &nodes12[5], .payload = {.id = 70, .data = (double)57.785685}}, + {.next = &nodes12[172], .payload = {.id = 47, .data = (double)-23.442077}}, + {.next = &nodes12[79], .payload = {.id = 227, .data = (double)31.278926}}, + {.next = &nodes12[139], .payload = {.id = 53, .data = (double)-23.080988}}, + {.next = &nodes12[37], .payload = {.id = 134, .data = (double)1.119222}}, + {.next = &nodes12[113], .payload = {.id = 247, .data = (double)-33.469053}}, + {.next = &nodes12[231], .payload = {.id = 228, .data = (double)79.979443}}, + {.next = &nodes12[131], .payload = {.id = 154, .data = (double)-70.98595}}, + {.next = &nodes12[96], .payload = {.id = 42, .data = (double)73.135927}}, + {.next = &nodes12[155], .payload = {.id = 211, .data = (double)-79.218543}}, + {.next = &nodes12[255], .payload = {.id = 250, .data = (double)-47.06703}}, + {.next = &nodes12[158], .payload = {.id = 5, .data = (double)-24.217797}}, + {.next = &nodes12[192], .payload = {.id = 173, .data = (double)50.485571}}, + {.next = &nodes12[185], .payload = {.id = 92, .data = (double)38.099453}}, + {.next = &nodes12[174], .payload = {.id = 205, .data = (double)-64.01667}}, + {.next = &nodes12[73], .payload = {.id = 69, .data = (double)-8.794269}}, + {.next = &nodes12[180], .payload = {.id = 73, .data = (double)-64.040525}}, + {.next = &nodes12[101], .payload = {.id = 243, .data = (double)-67.606794}}, + {.next = &nodes12[153], .payload = {.id = 15, .data = (double)-70.156714}}, + {.next = &nodes12[81], .payload = {.id = 41, .data = (double)72.249568}}, + {.next = &nodes12[220], .payload = {.id = 178, .data = (double)-70.970034}}, + {.next = &nodes12[105], .payload = {.id = 143, .data = (double)18.354025}}, + {.next = &nodes12[56], .payload = {.id = 94, .data = (double)46.258637}}, + {.next = &nodes12[52], .payload = {.id = 43, .data = (double)-52.951766}}, + {.next = &nodes12[48], .payload = {.id = 139, .data = (double)71.571677}}, + {.next = &nodes12[241], .payload = {.id = 25, .data = (double)88.666659}}, + {.next = &nodes12[250], .payload = {.id = 109, .data = (double)-89.445146}}, + {.next = &nodes12[14], .payload = {.id = 28, .data = (double)-31.147075}}, + {.next = &nodes12[33], .payload = {.id = 244, .data = (double)-85.200588}}, + {.next = &nodes12[54], .payload = {.id = 190, .data = (double)-13.642824}}, + {.next = &nodes12[162], .payload = {.id = 171, .data = (double)-39.726574}}, + {.next = &nodes12[235], .payload = {.id = 63, .data = (double)-2.659733}}, + {.next = &nodes12[196], .payload = {.id = 144, .data = (double)-69.772877}}, + {.next = &nodes12[189], .payload = {.id = 13, .data = (double)-99.963132}}, + {.next = &nodes12[99], .payload = {.id = 108, .data = (double)-37.500056}}, + {.next = &nodes12[117], .payload = {.id = 104, .data = (double)92.082209}}, + {.next = &nodes12[53], .payload = {.id = 240, .data = (double)80.678299}}, + {.next = &nodes12[171], .payload = {.id = 75, .data = (double)10.410006}}, + {.next = &nodes12[58], .payload = {.id = 106, .data = (double)26.737533}}, + {.next = &nodes12[136], .payload = {.id = 220, .data = (double)67.091827}}, + {.next = &nodes12[35], .payload = {.id = 248, .data = (double)-87.98827}}, + {.next = &nodes12[135], .payload = {.id = 58, .data = (double)34.013216}}, + {.next = &nodes12[106], .payload = {.id = 12, .data = (double)27.226564}}, + {.next = &nodes12[190], .payload = {.id = 101, .data = (double)-82.31073}}, + {.next = &nodes12[111], .payload = {.id = 105, .data = (double)-84.383616}}, + {.next = &nodes12[43], .payload = {.id = 39, .data = (double)64.150657}}, + {.next = &nodes12[2], .payload = {.id = 148, .data = (double)40.154975}}, + {.next = &nodes12[49], .payload = {.id = 158, .data = (double)98.717115}}, + {.next = &nodes12[28], .payload = {.id = 80, .data = (double)15.5877}}, + {.next = &nodes12[186], .payload = {.id = 22, .data = (double)14.055282}}, + {.next = &nodes12[64], .payload = {.id = 1, .data = (double)-86.078473}}, + {.next = &nodes12[80], .payload = {.id = 153, .data = (double)-83.119707}}, + {.next = &nodes12[219], .payload = {.id = 83, .data = (double)0.345761}}, + {.next = &nodes12[68], .payload = {.id = 89, .data = (double)40.976509}}, + {.next = &nodes12[104], .payload = {.id = 62, .data = (double)44.267846}}, + {.next = &nodes12[115], .payload = {.id = 11, .data = (double)80.651201}}, + {.next = &nodes12[46], .payload = {.id = 120, .data = (double)-92.934752}}, + {.next = &nodes12[40], .payload = {.id = 217, .data = (double)-81.611743}}, + {.next = &nodes12[60], .payload = {.id = 155, .data = (double)86.788371}}, + {.next = &nodes12[246], .payload = {.id = 253, .data = (double)85.71726}}, + {.next = &nodes12[134], .payload = {.id = 237, .data = (double)84.539078}}, + {.next = &nodes12[238], .payload = {.id = 238, .data = (double)-44.723288}}, + {.next = &nodes12[29], .payload = {.id = 59, .data = (double)-73.14451}}, + {.next = &nodes12[42], .payload = {.id = 221, .data = (double)90.097792}}, + {.next = &nodes12[72], .payload = {.id = 214, .data = (double)-43.340596}}, + {.next = &nodes12[77], .payload = {.id = 133, .data = (double)-83.497967}}, + {.next = &nodes12[249], .payload = {.id = 54, .data = (double)84.896409}}, + {.next = &nodes12[197], .payload = {.id = 30, .data = (double)-98.37615}}, + {.next = &nodes12[45], .payload = {.id = 209, .data = (double)-97.607718}}, + {.next = &nodes12[200], .payload = {.id = 175, .data = (double)-24.039841}}, + {.next = NULL, .payload = {.id = 255, .data = (double)-64.311566}}, + {.next = &nodes12[102], .payload = {.id = 189, .data = (double)91.236731}}, + {.next = &nodes12[183], .payload = {.id = 86, .data = (double)-26.605995}}, + {.next = &nodes12[188], .payload = {.id = 160, .data = (double)-52.410512}}, + {.next = &nodes12[245], .payload = {.id = 232, .data = (double)39.130727}}, + {.next = &nodes12[21], .payload = {.id = 115, .data = (double)46.762909}}, + {.next = &nodes12[51], .payload = {.id = 184, .data = (double)92.352545}}, + {.next = &nodes12[221], .payload = {.id = 230, .data = (double)93.433102}}, + {.next = &nodes12[38], .payload = {.id = 78, .data = (double)-62.841793}}, + {.next = &nodes12[87], .payload = {.id = 204, .data = (double)38.055666}}, + {.next = &nodes12[205], .payload = {.id = 16, .data = (double)6.251164}}, + {.next = &nodes12[160], .payload = {.id = 224, .data = (double)-76.004578}}, + {.next = &nodes12[70], .payload = {.id = 212, .data = (double)-10.811559}}, + {.next = &nodes12[127], .payload = {.id = 61, .data = (double)-96.85844}}, + {.next = &nodes12[44], .payload = {.id = 151, .data = (double)72.402886}}, + {.next = &nodes12[27], .payload = {.id = 6, .data = (double)-1.140971}}, + {.next = &nodes12[50], .payload = {.id = 49, .data = (double)9.023758}}, + {.next = &nodes12[216], .payload = {.id = 225, .data = (double)71.288165}}, + {.next = &nodes12[253], .payload = {.id = 35, .data = (double)-26.155421}}, + {.next = &nodes12[85], .payload = {.id = 172, .data = (double)49.230109}}, + {.next = &nodes12[244], .payload = {.id = 112, .data = (double)-6.226238}}, + {.next = &nodes12[173], .payload = {.id = 168, .data = (double)-76.801127}}, + {.next = &nodes12[122], .payload = {.id = 21, .data = (double)-36.680457}}, + {.next = &nodes12[212], .payload = {.id = 124, .data = (double)12.741255}}, + {.next = &nodes12[17], .payload = {.id = 194, .data = (double)-46.582437}}, + {.next = &nodes12[144], .payload = {.id = 188, .data = (double)27.48483}}, + {.next = &nodes12[78], .payload = {.id = 246, .data = (double)-23.4402}}, + {.next = &nodes12[154], .payload = {.id = 223, .data = (double)41.615021}}, + {.next = &nodes12[191], .payload = {.id = 76, .data = (double)-9.990847}}, + {.next = &nodes12[159], .payload = {.id = 48, .data = (double)-23.686991}}, + {.next = &nodes12[224], .payload = {.id = 169, .data = (double)-66.479921}}, + {.next = &nodes12[199], .payload = {.id = 206, .data = (double)9.522511}}, + {.next = &nodes12[128], .payload = {.id = 10, .data = (double)77.452307}}, + {.next = &nodes12[10], .payload = {.id = 141, .data = (double)-77.690119}}, + {.next = &nodes12[15], .payload = {.id = 45, .data = (double)-21.146335}}, + {.next = &nodes12[47], .payload = {.id = 51, .data = (double)-5.025717}}, + {.next = &nodes12[168], .payload = {.id = 187, .data = (double)83.542428}}, + {.next = &nodes12[110], .payload = {.id = 74, .data = (double)1.882983}}, + {.next = &nodes12[16], .payload = {.id = 117, .data = (double)92.11626}}, + {.next = &nodes12[165], .payload = {.id = 20, .data = (double)36.303358}}, + {.next = &nodes12[62], .payload = {.id = 87, .data = (double)95.64669}}, + {.next = &nodes12[195], .payload = {.id = 136, .data = (double)-44.430241}}, + {.next = &nodes12[95], .payload = {.id = 93, .data = (double)-71.582504}}, + {.next = &nodes12[19], .payload = {.id = 23, .data = (double)82.640853}}, + {.next = &nodes12[24], .payload = {.id = 165, .data = (double)-30.984856}}, + {.next = &nodes12[66], .payload = {.id = 161, .data = (double)-11.962998}}, + {.next = &nodes12[91], .payload = {.id = 14, .data = (double)-70.654929}}, + {.next = &nodes12[209], .payload = {.id = 102, .data = (double)-5.509686}}, + {.next = &nodes12[151], .payload = {.id = 77, .data = (double)-28.938554}}, + {.next = &nodes12[142], .payload = {.id = 174, .data = (double)6.504166}}, + {.next = &nodes12[145], .payload = {.id = 85, .data = (double)9.233252}}, + {.next = &nodes12[86], .payload = {.id = 91, .data = (double)-3.693418}}, + {.next = &nodes12[252], .payload = {.id = 137, .data = (double)-73.492247}}, + {.next = &nodes12[237], .payload = {.id = 145, .data = (double)-10.669366}}, + {.next = &nodes12[22], .payload = {.id = 31, .data = (double)97.28433}}, + {.next = &nodes12[166], .payload = {.id = 123, .data = (double)45.394343}}, + {.next = &nodes12[13], .payload = {.id = 207, .data = (double)34.560372}}, + {.next = &nodes12[57], .payload = {.id = 176, .data = (double)41.121561}}, + {.next = &nodes12[223], .payload = {.id = 98, .data = (double)-7.012735}}, + {.next = &nodes12[130], .payload = {.id = 216, .data = (double)-95.259905}}, + {.next = &nodes12[114], .payload = {.id = 57, .data = (double)99.491209}}, + {.next = &nodes12[132], .payload = {.id = 252, .data = (double)-1.655643}}, + {.next = &nodes12[239], .payload = {.id = 17, .data = (double)-22.003468}}, + {.next = &nodes12[61], .payload = {.id = 201, .data = (double)17.744858}}, + {.next = &nodes12[39], .payload = {.id = 199, .data = (double)49.818182}}, + {.next = &nodes12[133], .payload = {.id = 236, .data = (double)27.756102}}, + {.next = &nodes12[108], .payload = {.id = 103, .data = (double)48.337222}}, + {.next = &nodes12[163], .payload = {.id = 111, .data = (double)55.705427}}, + {.next = &nodes12[198], .payload = {.id = 122, .data = (double)49.885056}}, + {.next = &nodes12[34], .payload = {.id = 125, .data = (double)-87.716447}}, + {.next = &nodes12[234], .payload = {.id = 197, .data = (double)-21.769247}}, + {.next = &nodes12[65], .payload = {.id = 181, .data = (double)85.444505}}, + {.next = &nodes12[11], .payload = {.id = 131, .data = (double)24.863401}}, + {.next = &nodes12[75], .payload = {.id = 226, .data = (double)-74.018549}}, + {.next = &nodes12[119], .payload = {.id = 147, .data = (double)-47.749482}}, + {.next = &nodes12[116], .payload = {.id = 100, .data = (double)77.983096}}, + {.next = &nodes12[193], .payload = {.id = 84, .data = (double)-17.832437}}, + {.next = &nodes12[8], .payload = {.id = 179, .data = (double)74.055547}}, + {.next = &nodes12[147], .payload = {.id = 231, .data = (double)79.200326}}, + {.next = &nodes12[88], .payload = {.id = 68, .data = (double)-16.828907}}, + {.next = &nodes12[218], .payload = {.id = 99, .data = (double)-84.35308}}, + {.next = &nodes12[103], .payload = {.id = 170, .data = (double)-20.251039}}, + {.next = &nodes12[175], .payload = {.id = 9, .data = (double)63.406718}}, + {.next = &nodes12[123], .payload = {.id = 0, .data = (double)91.176689}}, + {.next = &nodes12[247], .payload = {.id = 163, .data = (double)-57.828651}}, + {.next = &nodes12[164], .payload = {.id = 167, .data = (double)51.096786}}, + {.next = &nodes12[118], .payload = {.id = 38, .data = (double)40.670825}}, + {.next = &nodes12[59], .payload = {.id = 127, .data = (double)-66.184152}}, + {.next = &nodes12[150], .payload = {.id = 229, .data = (double)13.213761}}, + {.next = &nodes12[84], .payload = {.id = 4, .data = (double)54.268676}}, + {.next = &nodes12[148], .payload = {.id = 114, .data = (double)-6.153522}}, + {.next = &nodes12[207], .payload = {.id = 198, .data = (double)54.630203}}, + {.next = &nodes12[4], .payload = {.id = 64, .data = (double)-12.652977}}, + {.next = &nodes12[179], .payload = {.id = 186, .data = (double)-91.796477}}, + {.next = &nodes12[217], .payload = {.id = 146, .data = (double)61.568138}}, + {.next = &nodes12[109], .payload = {.id = 239, .data = (double)-14.60332}}, + {.next = &nodes12[32], .payload = {.id = 18, .data = (double)15.586283}}, + {.next = &nodes12[225], .payload = {.id = 8, .data = (double)-81.893399}}, + {.next = &nodes12[254], .payload = {.id = 26, .data = (double)-13.054593}}, + {.next = &nodes12[6], .payload = {.id = 66, .data = (double)-83.067311}}, + {.next = &nodes12[149], .payload = {.id = 183, .data = (double)35.698681}}, + {.next = &nodes12[233], .payload = {.id = 113, .data = (double)2.532622}}, + {.next = &nodes12[12], .payload = {.id = 233, .data = (double)-49.332852}}, + {.next = &nodes12[143], .payload = {.id = 254, .data = (double)22.060377}}, + {.next = &nodes12[187], .payload = {.id = 164, .data = (double)46.872222}}, + {.next = &nodes12[120], .payload = {.id = 157, .data = (double)-0.810345}}, + {.next = &nodes12[71], .payload = {.id = 55, .data = (double)67.992537}}, + {.next = &nodes12[210], .payload = {.id = 110, .data = (double)-31.290766}}, + {.next = &nodes12[213], .payload = {.id = 196, .data = (double)30.868656}}, + {.next = &nodes12[97], .payload = {.id = 138, .data = (double)-43.805614}}, + {.next = &nodes12[55], .payload = {.id = 36, .data = (double)9.777027}}, + {.next = &nodes12[100], .payload = {.id = 27, .data = (double)96.516061}}, + {.next = &nodes12[204], .payload = {.id = 251, .data = (double)-11.885033}}, +}; + +node_t nodes13[] = { + {.next = &nodes13[7], .payload = {.id = 147, .data = (double)-2.754619}}, + {.next = &nodes13[160], .payload = {.id = 161, .data = (double)-8.425176}}, + {.next = &nodes13[254], .payload = {.id = 90, .data = (double)-4.04341}}, + {.next = &nodes13[112], .payload = {.id = 156, .data = (double)89.073064}}, + {.next = &nodes13[86], .payload = {.id = 229, .data = (double)-19.087534}}, + {.next = &nodes13[178], .payload = {.id = 103, .data = (double)26.680461}}, + {.next = &nodes13[93], .payload = {.id = 86, .data = (double)-73.4576}}, + {.next = &nodes13[247], .payload = {.id = 148, .data = (double)5.33652}}, + {.next = &nodes13[113], .payload = {.id = 191, .data = (double)39.372716}}, + {.next = &nodes13[21], .payload = {.id = 25, .data = (double)-55.867448}}, + {.next = &nodes13[32], .payload = {.id = 240, .data = (double)-42.034563}}, + {.next = &nodes13[43], .payload = {.id = 177, .data = (double)-30.659951}}, + {.next = &nodes13[29], .payload = {.id = 224, .data = (double)-25.417013}}, + {.next = &nodes13[136], .payload = {.id = 110, .data = (double)-46.042124}}, + {.next = &nodes13[142], .payload = {.id = 29, .data = (double)-71.011746}}, + {.next = &nodes13[164], .payload = {.id = 254, .data = (double)-19.674016}}, + {.next = &nodes13[185], .payload = {.id = 245, .data = (double)13.046303}}, + {.next = &nodes13[49], .payload = {.id = 32, .data = (double)-22.533939}}, + {.next = &nodes13[1], .payload = {.id = 160, .data = (double)78.380643}}, + {.next = &nodes13[252], .payload = {.id = 82, .data = (double)11.697393}}, + {.next = &nodes13[111], .payload = {.id = 218, .data = (double)-47.918561}}, + {.next = &nodes13[71], .payload = {.id = 26, .data = (double)-5.801948}}, + {.next = &nodes13[132], .payload = {.id = 213, .data = (double)-69.30304}}, + {.next = &nodes13[97], .payload = {.id = 237, .data = (double)-33.743871}}, + {.next = &nodes13[184], .payload = {.id = 84, .data = (double)46.357257}}, + {.next = &nodes13[127], .payload = {.id = 222, .data = (double)-36.611247}}, + {.next = &nodes13[222], .payload = {.id = 169, .data = (double)-0.734253}}, + {.next = &nodes13[183], .payload = {.id = 15, .data = (double)-34.805537}}, + {.next = &nodes13[23], .payload = {.id = 236, .data = (double)95.120207}}, + {.next = &nodes13[225], .payload = {.id = 225, .data = (double)7.973319}}, + {.next = &nodes13[213], .payload = {.id = 2, .data = (double)-33.141074}}, + {.next = &nodes13[74], .payload = {.id = 42, .data = (double)70.330273}}, + {.next = &nodes13[58], .payload = {.id = 241, .data = (double)88.801905}}, + {.next = &nodes13[83], .payload = {.id = 243, .data = (double)14.745517}}, + {.next = &nodes13[89], .payload = {.id = 209, .data = (double)94.641218}}, + {.next = &nodes13[22], .payload = {.id = 212, .data = (double)33.271193}}, + {.next = &nodes13[236], .payload = {.id = 216, .data = (double)-36.674832}}, + {.next = &nodes13[205], .payload = {.id = 54, .data = (double)-82.705134}}, + {.next = &nodes13[57], .payload = {.id = 132, .data = (double)-52.273459}}, + {.next = &nodes13[69], .payload = {.id = 63, .data = (double)-50.669165}}, + {.next = &nodes13[144], .payload = {.id = 61, .data = (double)46.003551}}, + {.next = &nodes13[103], .payload = {.id = 79, .data = (double)64.258264}}, + {.next = &nodes13[230], .payload = {.id = 99, .data = (double)-18.927926}}, + {.next = &nodes13[81], .payload = {.id = 178, .data = (double)-11.22799}}, + {.next = &nodes13[190], .payload = {.id = 205, .data = (double)-66.727385}}, + {.next = &nodes13[102], .payload = {.id = 252, .data = (double)10.191998}}, + {.next = &nodes13[100], .payload = {.id = 11, .data = (double)-76.786983}}, + {.next = &nodes13[138], .payload = {.id = 220, .data = (double)12.497448}}, + {.next = &nodes13[248], .payload = {.id = 48, .data = (double)57.909393}}, + {.next = &nodes13[117], .payload = {.id = 33, .data = (double)-72.719077}}, + {.next = &nodes13[121], .payload = {.id = 138, .data = (double)-58.041205}}, + {.next = &nodes13[80], .payload = {.id = 184, .data = (double)89.489742}}, + {.next = &nodes13[40], .payload = {.id = 60, .data = (double)-44.165824}}, + {.next = &nodes13[5], .payload = {.id = 102, .data = (double)-7.140843}}, + {.next = &nodes13[147], .payload = {.id = 174, .data = (double)93.914921}}, + {.next = &nodes13[84], .payload = {.id = 165, .data = (double)91.325386}}, + {.next = &nodes13[98], .payload = {.id = 180, .data = (double)-41.696641}}, + {.next = &nodes13[246], .payload = {.id = 133, .data = (double)-77.288464}}, + {.next = &nodes13[33], .payload = {.id = 242, .data = (double)96.137956}}, + {.next = &nodes13[228], .payload = {.id = 124, .data = (double)23.82669}}, + {.next = &nodes13[107], .payload = {.id = 8, .data = (double)-64.822478}}, + {.next = &nodes13[151], .payload = {.id = 75, .data = (double)-93.275889}}, + {.next = &nodes13[140], .payload = {.id = 158, .data = (double)88.175177}}, + {.next = &nodes13[196], .payload = {.id = 107, .data = (double)-33.418772}}, + {.next = &nodes13[124], .payload = {.id = 58, .data = (double)18.316174}}, + {.next = &nodes13[87], .payload = {.id = 115, .data = (double)-83.808192}}, + {.next = &nodes13[95], .payload = {.id = 127, .data = (double)11.758092}}, + {.next = &nodes13[201], .payload = {.id = 105, .data = (double)-85.860282}}, + {.next = &nodes13[14], .payload = {.id = 28, .data = (double)78.097769}}, + {.next = &nodes13[106], .payload = {.id = 64, .data = (double)-34.540811}}, + {.next = &nodes13[119], .payload = {.id = 19, .data = (double)55.795056}}, + {.next = &nodes13[68], .payload = {.id = 27, .data = (double)-3.118457}}, + {.next = &nodes13[251], .payload = {.id = 13, .data = (double)44.280616}}, + {.next = &nodes13[150], .payload = {.id = 119, .data = (double)89.064446}}, + {.next = &nodes13[174], .payload = {.id = 43, .data = (double)-8.284215}}, + {.next = &nodes13[188], .payload = {.id = 52, .data = (double)94.027168}}, + {.next = &nodes13[171], .payload = {.id = 144, .data = (double)-44.570933}}, + {.next = &nodes13[26], .payload = {.id = 168, .data = (double)39.416422}}, + {.next = &nodes13[200], .payload = {.id = 202, .data = (double)-90.536213}}, + {.next = &nodes13[224], .payload = {.id = 129, .data = (double)41.867427}}, + {.next = &nodes13[204], .payload = {.id = 185, .data = (double)28.934406}}, + {.next = &nodes13[56], .payload = {.id = 179, .data = (double)28.936888}}, + {.next = &nodes13[165], .payload = {.id = 140, .data = (double)-54.912555}}, + {.next = &nodes13[16], .payload = {.id = 244, .data = (double)-70.583305}}, + {.next = &nodes13[101], .payload = {.id = 166, .data = (double)-78.127016}}, + {.next = &nodes13[176], .payload = {.id = 68, .data = (double)-70.20606}}, + {.next = &nodes13[131], .payload = {.id = 230, .data = (double)-0.116617}}, + {.next = &nodes13[91], .payload = {.id = 116, .data = (double)76.16945}}, + {.next = &nodes13[137], .payload = {.id = 122, .data = (double)-77.806691}}, + {.next = &nodes13[122], .payload = {.id = 210, .data = (double)67.866335}}, + {.next = &nodes13[216], .payload = {.id = 93, .data = (double)71.584422}}, + {.next = &nodes13[172], .payload = {.id = 117, .data = (double)47.152157}}, + {.next = &nodes13[153], .payload = {.id = 38, .data = (double)-74.557647}}, + {.next = &nodes13[211], .payload = {.id = 87, .data = (double)-40.841914}}, + {.next = &nodes13[133], .payload = {.id = 233, .data = (double)-35.956414}}, + {.next = &nodes13[79], .payload = {.id = 128, .data = (double)-86.598817}}, + {.next = &nodes13[11], .payload = {.id = 176, .data = (double)-73.594526}}, + {.next = &nodes13[243], .payload = {.id = 238, .data = (double)41.090271}}, + {.next = &nodes13[99], .payload = {.id = 181, .data = (double)-87.410098}}, + {.next = &nodes13[218], .payload = {.id = 182, .data = (double)74.35874}}, + {.next = &nodes13[72], .payload = {.id = 12, .data = (double)79.015835}}, + {.next = &nodes13[77], .payload = {.id = 167, .data = (double)-44.811453}}, + {.next = &nodes13[15], .payload = {.id = 253, .data = (double)-38.38356}}, + {.next = &nodes13[227], .payload = {.id = 80, .data = (double)-9.511726}}, + {.next = &nodes13[36], .payload = {.id = 215, .data = (double)-91.769709}}, + {.next = &nodes13[9], .payload = {.id = 24, .data = (double)-24.893522}}, + {.next = &nodes13[135], .payload = {.id = 65, .data = (double)15.893406}}, + {.next = &nodes13[163], .payload = {.id = 9, .data = (double)57.098404}}, + {.next = &nodes13[34], .payload = {.id = 208, .data = (double)-42.950684}}, + {.next = &nodes13[191], .payload = {.id = 152, .data = (double)6.571093}}, + {.next = &nodes13[237], .payload = {.id = 136, .data = (double)16.023877}}, + {.next = &nodes13[47], .payload = {.id = 219, .data = (double)-63.100683}}, + {.next = &nodes13[62], .payload = {.id = 157, .data = (double)61.759175}}, + {.next = &nodes13[170], .payload = {.id = 192, .data = (double)68.381574}}, + {.next = &nodes13[255], .payload = {.id = 227, .data = (double)-39.688046}}, + {.next = &nodes13[202], .payload = {.id = 188, .data = (double)29.210245}}, + {.next = &nodes13[168], .payload = {.id = 46, .data = (double)77.281794}}, + {.next = &nodes13[193], .payload = {.id = 34, .data = (double)43.964243}}, + {.next = &nodes13[223], .payload = {.id = 250, .data = (double)80.034894}}, + {.next = &nodes13[238], .payload = {.id = 20, .data = (double)-34.773555}}, + {.next = &nodes13[0], .payload = {.id = 146, .data = (double)-30.954684}}, + {.next = &nodes13[82], .payload = {.id = 139, .data = (double)49.003343}}, + {.next = &nodes13[35], .payload = {.id = 211, .data = (double)38.571854}}, + {.next = &nodes13[203], .payload = {.id = 112, .data = (double)8.487021}}, + {.next = &nodes13[52], .payload = {.id = 59, .data = (double)67.397805}}, + {.next = &nodes13[198], .payload = {.id = 40, .data = (double)-88.069656}}, + {.next = &nodes13[70], .payload = {.id = 18, .data = (double)-34.863008}}, + {.next = &nodes13[12], .payload = {.id = 223, .data = (double)-31.230597}}, + {.next = &nodes13[148], .payload = {.id = 198, .data = (double)-47.998508}}, + {.next = &nodes13[110], .payload = {.id = 135, .data = (double)87.829586}}, + {.next = &nodes13[239], .payload = {.id = 4, .data = (double)51.681604}}, + {.next = &nodes13[206], .payload = {.id = 231, .data = (double)-70.923223}}, + {.next = &nodes13[104], .payload = {.id = 214, .data = (double)-52.418935}}, + {.next = &nodes13[208], .payload = {.id = 234, .data = (double)-99.141139}}, + {.next = &nodes13[242], .payload = {.id = 195, .data = (double)-73.60915}}, + {.next = &nodes13[152], .payload = {.id = 66, .data = (double)78.364526}}, + {.next = &nodes13[123], .payload = {.id = 111, .data = (double)89.219099}}, + {.next = &nodes13[59], .payload = {.id = 123, .data = (double)-26.881828}}, + {.next = &nodes13[25], .payload = {.id = 221, .data = (double)-93.062182}}, + {.next = &nodes13[126], .payload = {.id = 17, .data = (double)35.370509}}, + {.next = &nodes13[18], .payload = {.id = 159, .data = (double)-86.874482}}, + {.next = &nodes13[241], .payload = {.id = 70, .data = (double)-98.984484}}, + {.next = &nodes13[149], .payload = {.id = 30, .data = (double)85.577423}}, + {.next = &nodes13[60], .payload = {.id = 7, .data = (double)84.972269}}, + {.next = &nodes13[39], .payload = {.id = 62, .data = (double)47.235772}}, + {.next = &nodes13[118], .payload = {.id = 249, .data = (double)46.328104}}, + {.next = &nodes13[116], .payload = {.id = 45, .data = (double)-31.284798}}, + {.next = &nodes13[96], .payload = {.id = 175, .data = (double)8.286992}}, + {.next = &nodes13[244], .payload = {.id = 199, .data = (double)-3.151377}}, + {.next = &nodes13[17], .payload = {.id = 31, .data = (double)-9.001825}}, + {.next = &nodes13[186], .payload = {.id = 120, .data = (double)34.930593}}, + {.next = &nodes13[187], .payload = {.id = 76, .data = (double)6.224345}}, + {.next = &nodes13[85], .payload = {.id = 67, .data = (double)18.354326}}, + {.next = &nodes13[125], .payload = {.id = 39, .data = (double)38.442106}}, + {.next = &nodes13[179], .payload = {.id = 0, .data = (double)-42.987096}}, + {.next = &nodes13[143], .payload = {.id = 6, .data = (double)48.083377}}, + {.next = &nodes13[64], .payload = {.id = 57, .data = (double)99.132867}}, + {.next = &nodes13[234], .payload = {.id = 172, .data = (double)25.455239}}, + {.next = &nodes13[108], .payload = {.id = 207, .data = (double)42.362434}}, + {.next = &nodes13[66], .payload = {.id = 126, .data = (double)-64.946519}}, + {.next = &nodes13[177], .payload = {.id = 162, .data = (double)-83.965919}}, + {.next = &nodes13[229], .payload = {.id = 247, .data = (double)-11.578893}}, + {.next = &nodes13[115], .payload = {.id = 187, .data = (double)-31.441504}}, + {.next = &nodes13[46], .payload = {.id = 10, .data = (double)-2.987721}}, + {.next = NULL, .payload = {.id = 255, .data = (double)68.175383}}, + {.next = &nodes13[173], .payload = {.id = 141, .data = (double)-29.457666}}, + {.next = &nodes13[61], .payload = {.id = 74, .data = (double)53.721278}}, + {.next = &nodes13[215], .payload = {.id = 97, .data = (double)54.367002}}, + {.next = &nodes13[48], .payload = {.id = 47, .data = (double)20.727197}}, + {.next = &nodes13[75], .payload = {.id = 51, .data = (double)-66.012903}}, + {.next = &nodes13[175], .payload = {.id = 193, .data = (double)-10.948739}}, + {.next = &nodes13[120], .payload = {.id = 145, .data = (double)-87.326164}}, + {.next = &nodes13[73], .payload = {.id = 118, .data = (double)-89.037665}}, + {.next = &nodes13[207], .payload = {.id = 142, .data = (double)-46.52843}}, + {.next = &nodes13[146], .payload = {.id = 44, .data = (double)-65.759737}}, + {.next = &nodes13[134], .payload = {.id = 194, .data = (double)-39.183532}}, + {.next = &nodes13[141], .payload = {.id = 69, .data = (double)14.740157}}, + {.next = &nodes13[249], .payload = {.id = 163, .data = (double)79.589172}}, + {.next = &nodes13[67], .payload = {.id = 104, .data = (double)72.07653}}, + {.next = &nodes13[30], .payload = {.id = 1, .data = (double)-13.065672}}, + {.next = &nodes13[8], .payload = {.id = 190, .data = (double)18.671451}}, + {.next = &nodes13[167], .payload = {.id = 96, .data = (double)-9.03184}}, + {.next = &nodes13[109], .payload = {.id = 151, .data = (double)35.661658}}, + {.next = &nodes13[139], .payload = {.id = 16, .data = (double)-60.249721}}, + {.next = &nodes13[6], .payload = {.id = 85, .data = (double)89.986779}}, + {.next = &nodes13[161], .payload = {.id = 246, .data = (double)81.376158}}, + {.next = &nodes13[88], .payload = {.id = 121, .data = (double)77.595581}}, + {.next = &nodes13[209], .payload = {.id = 77, .data = (double)-4.146132}}, + {.next = &nodes13[37], .payload = {.id = 53, .data = (double)71.000804}}, + {.next = &nodes13[219], .payload = {.id = 36, .data = (double)95.111178}}, + {.next = &nodes13[158], .payload = {.id = 206, .data = (double)84.826328}}, + {.next = &nodes13[226], .payload = {.id = 153, .data = (double)-41.547129}}, + {.next = &nodes13[182], .payload = {.id = 150, .data = (double)41.965058}}, + {.next = &nodes13[189], .payload = {.id = 35, .data = (double)26.404223}}, + {.next = &nodes13[78], .payload = {.id = 201, .data = (double)53.949947}}, + {.next = &nodes13[128], .payload = {.id = 197, .data = (double)-65.652575}}, + {.next = &nodes13[217], .payload = {.id = 108, .data = (double)-93.457165}}, + {.next = &nodes13[44], .payload = {.id = 204, .data = (double)-8.814693}}, + {.next = &nodes13[31], .payload = {.id = 41, .data = (double)-72.6997}}, + {.next = &nodes13[166], .payload = {.id = 73, .data = (double)-5.869474}}, + {.next = &nodes13[197], .payload = {.id = 203, .data = (double)-29.375821}}, + {.next = &nodes13[63], .payload = {.id = 106, .data = (double)78.686888}}, + {.next = &nodes13[180], .payload = {.id = 189, .data = (double)-34.738717}}, + {.next = &nodes13[235], .payload = {.id = 113, .data = (double)58.895751}}, + {.next = &nodes13[162], .payload = {.id = 186, .data = (double)-17.661654}}, + {.next = &nodes13[245], .payload = {.id = 55, .data = (double)71.394753}}, + {.next = &nodes13[94], .payload = {.id = 232, .data = (double)-8.391853}}, + {.next = &nodes13[76], .payload = {.id = 143, .data = (double)36.045348}}, + {.next = &nodes13[28], .payload = {.id = 235, .data = (double)47.698996}}, + {.next = &nodes13[41], .payload = {.id = 78, .data = (double)59.603503}}, + {.next = &nodes13[2], .payload = {.id = 89, .data = (double)-81.854099}}, + {.next = &nodes13[210], .payload = {.id = 88, .data = (double)29.52804}}, + {.next = &nodes13[199], .payload = {.id = 72, .data = (double)-91.988264}}, + {.next = &nodes13[130], .payload = {.id = 3, .data = (double)61.030735}}, + {.next = &nodes13[181], .payload = {.id = 95, .data = (double)-95.117305}}, + {.next = &nodes13[42], .payload = {.id = 98, .data = (double)74.839808}}, + {.next = &nodes13[214], .payload = {.id = 94, .data = (double)49.457339}}, + {.next = &nodes13[13], .payload = {.id = 109, .data = (double)-14.819549}}, + {.next = &nodes13[51], .payload = {.id = 183, .data = (double)-53.534387}}, + {.next = &nodes13[92], .payload = {.id = 37, .data = (double)-59.557822}}, + {.next = &nodes13[53], .payload = {.id = 101, .data = (double)-25.915908}}, + {.next = &nodes13[90], .payload = {.id = 92, .data = (double)40.660898}}, + {.next = &nodes13[233], .payload = {.id = 170, .data = (double)74.998628}}, + {.next = &nodes13[45], .payload = {.id = 251, .data = (double)-72.115341}}, + {.next = &nodes13[231], .payload = {.id = 130, .data = (double)-59.057481}}, + {.next = &nodes13[114], .payload = {.id = 226, .data = (double)-67.480478}}, + {.next = &nodes13[250], .payload = {.id = 154, .data = (double)24.190254}}, + {.next = &nodes13[19], .payload = {.id = 81, .data = (double)-51.897701}}, + {.next = &nodes13[159], .payload = {.id = 125, .data = (double)-26.885771}}, + {.next = &nodes13[145], .payload = {.id = 248, .data = (double)37.829396}}, + {.next = &nodes13[220], .payload = {.id = 100, .data = (double)57.971743}}, + {.next = &nodes13[38], .payload = {.id = 131, .data = (double)96.250324}}, + {.next = &nodes13[253], .payload = {.id = 22, .data = (double)47.549573}}, + {.next = &nodes13[157], .payload = {.id = 171, .data = (double)4.137528}}, + {.next = &nodes13[54], .payload = {.id = 173, .data = (double)-41.366112}}, + {.next = &nodes13[65], .payload = {.id = 114, .data = (double)57.538369}}, + {.next = &nodes13[20], .payload = {.id = 217, .data = (double)-74.705298}}, + {.next = &nodes13[50], .payload = {.id = 137, .data = (double)91.820746}}, + {.next = &nodes13[232], .payload = {.id = 21, .data = (double)-80.387173}}, + {.next = &nodes13[155], .payload = {.id = 5, .data = (double)-91.336503}}, + {.next = &nodes13[169], .payload = {.id = 50, .data = (double)22.305618}}, + {.next = &nodes13[212], .payload = {.id = 71, .data = (double)96.036808}}, + {.next = &nodes13[195], .payload = {.id = 196, .data = (double)57.869652}}, + {.next = &nodes13[10], .payload = {.id = 239, .data = (double)-5.217865}}, + {.next = &nodes13[194], .payload = {.id = 200, .data = (double)94.14481}}, + {.next = &nodes13[156], .payload = {.id = 56, .data = (double)-2.15732}}, + {.next = &nodes13[129], .payload = {.id = 134, .data = (double)-4.301307}}, + {.next = &nodes13[192], .payload = {.id = 149, .data = (double)-75.458113}}, + {.next = &nodes13[240], .payload = {.id = 49, .data = (double)27.599843}}, + {.next = &nodes13[55], .payload = {.id = 164, .data = (double)-42.325462}}, + {.next = &nodes13[3], .payload = {.id = 155, .data = (double)59.980773}}, + {.next = &nodes13[27], .payload = {.id = 14, .data = (double)18.541332}}, + {.next = &nodes13[24], .payload = {.id = 83, .data = (double)-97.515402}}, + {.next = &nodes13[105], .payload = {.id = 23, .data = (double)73.977261}}, + {.next = &nodes13[221], .payload = {.id = 91, .data = (double)-39.03268}}, + {.next = &nodes13[4], .payload = {.id = 228, .data = (double)84.086795}}, +}; + +node_t nodes14[] = { + {.next = &nodes14[56], .payload = {.id = 160, .data = (double)-51.154223}}, + {.next = &nodes14[94], .payload = {.id = 24, .data = (double)-62.974844}}, + {.next = &nodes14[184], .payload = {.id = 43, .data = (double)-8.610847}}, + {.next = &nodes14[123], .payload = {.id = 11, .data = (double)52.648807}}, + {.next = &nodes14[146], .payload = {.id = 1, .data = (double)49.239603}}, + {.next = &nodes14[51], .payload = {.id = 166, .data = (double)-77.105741}}, + {.next = &nodes14[93], .payload = {.id = 144, .data = (double)35.297557}}, + {.next = &nodes14[42], .payload = {.id = 67, .data = (double)78.485526}}, + {.next = &nodes14[70], .payload = {.id = 114, .data = (double)8.105797}}, + {.next = &nodes14[83], .payload = {.id = 225, .data = (double)-0.159274}}, + {.next = &nodes14[69], .payload = {.id = 46, .data = (double)68.218035}}, + {.next = &nodes14[119], .payload = {.id = 32, .data = (double)52.281889}}, + {.next = &nodes14[222], .payload = {.id = 75, .data = (double)-15.059159}}, + {.next = &nodes14[125], .payload = {.id = 116, .data = (double)52.792981}}, + {.next = &nodes14[115], .payload = {.id = 216, .data = (double)-17.13715}}, + {.next = &nodes14[107], .payload = {.id = 87, .data = (double)2.282903}}, + {.next = &nodes14[18], .payload = {.id = 18, .data = (double)45.06987}}, + {.next = &nodes14[110], .payload = {.id = 162, .data = (double)-37.580094}}, + {.next = &nodes14[132], .payload = {.id = 19, .data = (double)84.846419}}, + {.next = &nodes14[33], .payload = {.id = 206, .data = (double)13.285659}}, + {.next = &nodes14[36], .payload = {.id = 243, .data = (double)-17.947948}}, + {.next = &nodes14[228], .payload = {.id = 4, .data = (double)-29.559345}}, + {.next = &nodes14[231], .payload = {.id = 183, .data = (double)-58.818337}}, + {.next = &nodes14[220], .payload = {.id = 15, .data = (double)-65.645307}}, + {.next = &nodes14[2], .payload = {.id = 42, .data = (double)-23.043777}}, + {.next = &nodes14[144], .payload = {.id = 178, .data = (double)14.070708}}, + {.next = &nodes14[121], .payload = {.id = 131, .data = (double)-22.183902}}, + {.next = &nodes14[67], .payload = {.id = 49, .data = (double)96.992466}}, + {.next = &nodes14[185], .payload = {.id = 26, .data = (double)-78.535099}}, + {.next = &nodes14[229], .payload = {.id = 199, .data = (double)60.920604}}, + {.next = &nodes14[199], .payload = {.id = 126, .data = (double)55.876494}}, + {.next = NULL, .payload = {.id = 255, .data = (double)-94.459165}}, + {.next = &nodes14[189], .payload = {.id = 196, .data = (double)-46.96898}}, + {.next = &nodes14[191], .payload = {.id = 207, .data = (double)6.212731}}, + {.next = &nodes14[15], .payload = {.id = 86, .data = (double)97.50464}}, + {.next = &nodes14[208], .payload = {.id = 187, .data = (double)-66.674556}}, + {.next = &nodes14[91], .payload = {.id = 244, .data = (double)72.03719}}, + {.next = &nodes14[194], .payload = {.id = 223, .data = (double)3.244823}}, + {.next = &nodes14[105], .payload = {.id = 96, .data = (double)66.062494}}, + {.next = &nodes14[20], .payload = {.id = 242, .data = (double)68.824399}}, + {.next = &nodes14[80], .payload = {.id = 90, .data = (double)-75.561988}}, + {.next = &nodes14[150], .payload = {.id = 174, .data = (double)-95.919545}}, + {.next = &nodes14[244], .payload = {.id = 68, .data = (double)-66.255358}}, + {.next = &nodes14[203], .payload = {.id = 147, .data = (double)-87.715206}}, + {.next = &nodes14[52], .payload = {.id = 247, .data = (double)69.193397}}, + {.next = &nodes14[114], .payload = {.id = 251, .data = (double)37.370981}}, + {.next = &nodes14[92], .payload = {.id = 38, .data = (double)-42.345748}}, + {.next = &nodes14[68], .payload = {.id = 213, .data = (double)-40.018196}}, + {.next = &nodes14[168], .payload = {.id = 62, .data = (double)-76.156431}}, + {.next = &nodes14[90], .payload = {.id = 72, .data = (double)68.8059}}, + {.next = &nodes14[57], .payload = {.id = 106, .data = (double)3.989783}}, + {.next = &nodes14[237], .payload = {.id = 167, .data = (double)-66.044152}}, + {.next = &nodes14[152], .payload = {.id = 248, .data = (double)-46.613048}}, + {.next = &nodes14[100], .payload = {.id = 193, .data = (double)-84.935764}}, + {.next = &nodes14[253], .payload = {.id = 123, .data = (double)-92.803776}}, + {.next = &nodes14[206], .payload = {.id = 29, .data = (double)-15.181631}}, + {.next = &nodes14[17], .payload = {.id = 161, .data = (double)-53.075582}}, + {.next = &nodes14[250], .payload = {.id = 107, .data = (double)-1.562497}}, + {.next = &nodes14[127], .payload = {.id = 203, .data = (double)15.63865}}, + {.next = &nodes14[196], .payload = {.id = 152, .data = (double)16.793396}}, + {.next = &nodes14[12], .payload = {.id = 74, .data = (double)-53.426072}}, + {.next = &nodes14[47], .payload = {.id = 212, .data = (double)0.927907}}, + {.next = &nodes14[211], .payload = {.id = 59, .data = (double)-20.726048}}, + {.next = &nodes14[31], .payload = {.id = 254, .data = (double)-70.00755}}, + {.next = &nodes14[173], .payload = {.id = 209, .data = (double)-30.536703}}, + {.next = &nodes14[41], .payload = {.id = 173, .data = (double)-15.765474}}, + {.next = &nodes14[27], .payload = {.id = 48, .data = (double)-18.543556}}, + {.next = &nodes14[246], .payload = {.id = 50, .data = (double)-14.407667}}, + {.next = &nodes14[198], .payload = {.id = 214, .data = (double)32.691339}}, + {.next = &nodes14[66], .payload = {.id = 47, .data = (double)-54.825314}}, + {.next = &nodes14[13], .payload = {.id = 115, .data = (double)-96.465921}}, + {.next = &nodes14[26], .payload = {.id = 130, .data = (double)-37.508065}}, + {.next = &nodes14[251], .payload = {.id = 110, .data = (double)-0.420191}}, + {.next = &nodes14[35], .payload = {.id = 186, .data = (double)33.477511}}, + {.next = &nodes14[72], .payload = {.id = 109, .data = (double)-41.287414}}, + {.next = &nodes14[215], .payload = {.id = 22, .data = (double)-5.056899}}, + {.next = &nodes14[130], .payload = {.id = 119, .data = (double)-76.173178}}, + {.next = &nodes14[54], .payload = {.id = 122, .data = (double)-11.488771}}, + {.next = &nodes14[255], .payload = {.id = 157, .data = (double)98.389105}}, + {.next = &nodes14[108], .payload = {.id = 57, .data = (double)34.831782}}, + {.next = &nodes14[165], .payload = {.id = 91, .data = (double)-2.131724}}, + {.next = &nodes14[139], .payload = {.id = 52, .data = (double)78.950929}}, + {.next = &nodes14[216], .payload = {.id = 236, .data = (double)-88.023668}}, + {.next = &nodes14[177], .payload = {.id = 226, .data = (double)32.161243}}, + {.next = &nodes14[193], .payload = {.id = 83, .data = (double)-28.780539}}, + {.next = &nodes14[39], .payload = {.id = 241, .data = (double)53.106016}}, + {.next = &nodes14[59], .payload = {.id = 151, .data = (double)61.910686}}, + {.next = &nodes14[116], .payload = {.id = 234, .data = (double)86.927187}}, + {.next = &nodes14[25], .payload = {.id = 177, .data = (double)-36.697134}}, + {.next = &nodes14[113], .payload = {.id = 232, .data = (double)70.55493}}, + {.next = &nodes14[60], .payload = {.id = 73, .data = (double)-19.142194}}, + {.next = &nodes14[95], .payload = {.id = 245, .data = (double)82.227559}}, + {.next = &nodes14[245], .payload = {.id = 39, .data = (double)44.427314}}, + {.next = &nodes14[209], .payload = {.id = 145, .data = (double)53.294153}}, + {.next = &nodes14[28], .payload = {.id = 25, .data = (double)34.70514}}, + {.next = &nodes14[44], .payload = {.id = 246, .data = (double)26.785498}}, + {.next = &nodes14[4], .payload = {.id = 0, .data = (double)-70.888604}}, + {.next = &nodes14[16], .payload = {.id = 17, .data = (double)-99.134214}}, + {.next = &nodes14[102], .payload = {.id = 102, .data = (double)-39.449478}}, + {.next = &nodes14[79], .payload = {.id = 56, .data = (double)-97.442831}}, + {.next = &nodes14[151], .payload = {.id = 194, .data = (double)70.06686}}, + {.next = &nodes14[252], .payload = {.id = 142, .data = (double)18.209024}}, + {.next = &nodes14[219], .payload = {.id = 103, .data = (double)24.646524}}, + {.next = &nodes14[84], .payload = {.id = 82, .data = (double)88.645012}}, + {.next = &nodes14[242], .payload = {.id = 6, .data = (double)56.160427}}, + {.next = &nodes14[154], .payload = {.id = 97, .data = (double)-0.373018}}, + {.next = &nodes14[21], .payload = {.id = 3, .data = (double)15.950271}}, + {.next = &nodes14[120], .payload = {.id = 88, .data = (double)-70.52518}}, + {.next = &nodes14[62], .payload = {.id = 58, .data = (double)34.419096}}, + {.next = &nodes14[171], .payload = {.id = 138, .data = (double)12.451082}}, + {.next = &nodes14[234], .payload = {.id = 163, .data = (double)-83.011653}}, + {.next = &nodes14[142], .payload = {.id = 239, .data = (double)-51.92521}}, + {.next = &nodes14[248], .payload = {.id = 230, .data = (double)27.585272}}, + {.next = &nodes14[87], .payload = {.id = 233, .data = (double)81.367165}}, + {.next = &nodes14[230], .payload = {.id = 252, .data = (double)-52.774034}}, + {.next = &nodes14[233], .payload = {.id = 217, .data = (double)-49.747041}}, + {.next = &nodes14[82], .payload = {.id = 235, .data = (double)45.323014}}, + {.next = &nodes14[240], .payload = {.id = 201, .data = (double)91.588213}}, + {.next = &nodes14[78], .payload = {.id = 156, .data = (double)-14.370362}}, + {.next = &nodes14[243], .payload = {.id = 33, .data = (double)-37.143946}}, + {.next = &nodes14[40], .payload = {.id = 89, .data = (double)-9.073052}}, + {.next = &nodes14[205], .payload = {.id = 132, .data = (double)52.802228}}, + {.next = &nodes14[71], .payload = {.id = 129, .data = (double)-13.863776}}, + {.next = &nodes14[158], .payload = {.id = 12, .data = (double)5.767748}}, + {.next = &nodes14[175], .payload = {.id = 135, .data = (double)10.75678}}, + {.next = &nodes14[254], .payload = {.id = 117, .data = (double)98.142313}}, + {.next = &nodes14[109], .payload = {.id = 137, .data = (double)-6.036324}}, + {.next = &nodes14[239], .payload = {.id = 204, .data = (double)18.372931}}, + {.next = &nodes14[34], .payload = {.id = 85, .data = (double)90.027764}}, + {.next = &nodes14[50], .payload = {.id = 105, .data = (double)32.216121}}, + {.next = &nodes14[169], .payload = {.id = 120, .data = (double)-9.976896}}, + {.next = &nodes14[88], .payload = {.id = 176, .data = (double)-95.55271}}, + {.next = &nodes14[225], .payload = {.id = 20, .data = (double)84.095436}}, + {.next = &nodes14[22], .payload = {.id = 182, .data = (double)38.172793}}, + {.next = &nodes14[0], .payload = {.id = 159, .data = (double)-88.710151}}, + {.next = &nodes14[137], .payload = {.id = 180, .data = (double)-80.454865}}, + {.next = &nodes14[65], .payload = {.id = 172, .data = (double)2.951965}}, + {.next = &nodes14[133], .payload = {.id = 181, .data = (double)-2.328276}}, + {.next = &nodes14[24], .payload = {.id = 41, .data = (double)-1.25744}}, + {.next = &nodes14[183], .payload = {.id = 53, .data = (double)60.48728}}, + {.next = &nodes14[37], .payload = {.id = 222, .data = (double)25.568787}}, + {.next = &nodes14[53], .payload = {.id = 192, .data = (double)94.821453}}, + {.next = &nodes14[85], .payload = {.id = 240, .data = (double)49.286703}}, + {.next = &nodes14[162], .payload = {.id = 77, .data = (double)52.963402}}, + {.next = &nodes14[135], .payload = {.id = 179, .data = (double)-35.515726}}, + {.next = &nodes14[214], .payload = {.id = 100, .data = (double)20.916785}}, + {.next = &nodes14[106], .payload = {.id = 2, .data = (double)-44.524868}}, + {.next = &nodes14[170], .payload = {.id = 190, .data = (double)-59.648275}}, + {.next = &nodes14[8], .payload = {.id = 113, .data = (double)61.896319}}, + {.next = &nodes14[147], .payload = {.id = 189, .data = (double)93.885551}}, + {.next = &nodes14[131], .payload = {.id = 175, .data = (double)-6.06002}}, + {.next = &nodes14[32], .payload = {.id = 195, .data = (double)-57.183979}}, + {.next = &nodes14[188], .payload = {.id = 249, .data = (double)-42.591081}}, + {.next = &nodes14[224], .payload = {.id = 79, .data = (double)18.729994}}, + {.next = &nodes14[190], .payload = {.id = 98, .data = (double)-94.650222}}, + {.next = &nodes14[101], .payload = {.id = 141, .data = (double)-47.321803}}, + {.next = &nodes14[112], .payload = {.id = 229, .data = (double)-46.412809}}, + {.next = &nodes14[48], .payload = {.id = 61, .data = (double)35.303733}}, + {.next = &nodes14[227], .payload = {.id = 13, .data = (double)43.162327}}, + {.next = &nodes14[247], .payload = {.id = 8, .data = (double)0.981846}}, + {.next = &nodes14[118], .payload = {.id = 155, .data = (double)-23.885324}}, + {.next = &nodes14[156], .payload = {.id = 228, .data = (double)87.620599}}, + {.next = &nodes14[153], .payload = {.id = 78, .data = (double)53.194433}}, + {.next = &nodes14[174], .payload = {.id = 94, .data = (double)-94.055296}}, + {.next = &nodes14[204], .payload = {.id = 169, .data = (double)-92.524476}}, + {.next = &nodes14[218], .payload = {.id = 92, .data = (double)-53.835641}}, + {.next = &nodes14[46], .payload = {.id = 37, .data = (double)-27.749908}}, + {.next = &nodes14[111], .payload = {.id = 238, .data = (double)-7.502663}}, + {.next = &nodes14[200], .payload = {.id = 63, .data = (double)-21.037708}}, + {.next = &nodes14[77], .payload = {.id = 121, .data = (double)70.574858}}, + {.next = &nodes14[141], .payload = {.id = 191, .data = (double)27.08884}}, + {.next = &nodes14[236], .payload = {.id = 139, .data = (double)-68.737809}}, + {.next = &nodes14[103], .payload = {.id = 81, .data = (double)60.196846}}, + {.next = &nodes14[197], .payload = {.id = 210, .data = (double)-84.667682}}, + {.next = &nodes14[38], .payload = {.id = 95, .data = (double)47.559671}}, + {.next = &nodes14[126], .payload = {.id = 136, .data = (double)7.878477}}, + {.next = &nodes14[30], .payload = {.id = 125, .data = (double)31.882205}}, + {.next = &nodes14[161], .payload = {.id = 227, .data = (double)64.7816}}, + {.next = &nodes14[86], .payload = {.id = 150, .data = (double)-26.717981}}, + {.next = &nodes14[241], .payload = {.id = 65, .data = (double)95.514171}}, + {.next = &nodes14[226], .payload = {.id = 219, .data = (double)34.31205}}, + {.next = &nodes14[148], .payload = {.id = 112, .data = (double)8.487623}}, + {.next = &nodes14[238], .payload = {.id = 70, .data = (double)-60.182723}}, + {.next = &nodes14[187], .payload = {.id = 54, .data = (double)87.8164}}, + {.next = &nodes14[235], .payload = {.id = 44, .data = (double)47.234884}}, + {.next = &nodes14[210], .payload = {.id = 27, .data = (double)66.948431}}, + {.next = &nodes14[166], .payload = {.id = 36, .data = (double)-0.836796}}, + {.next = &nodes14[99], .payload = {.id = 55, .data = (double)-26.511721}}, + {.next = &nodes14[45], .payload = {.id = 250, .data = (double)-67.883138}}, + {.next = &nodes14[202], .payload = {.id = 197, .data = (double)-40.535946}}, + {.next = &nodes14[145], .payload = {.id = 99, .data = (double)-64.180862}}, + {.next = &nodes14[64], .payload = {.id = 208, .data = (double)-14.578822}}, + {.next = &nodes14[178], .payload = {.id = 149, .data = (double)-74.360387}}, + {.next = &nodes14[128], .payload = {.id = 84, .data = (double)33.335402}}, + {.next = &nodes14[9], .payload = {.id = 224, .data = (double)-62.692212}}, + {.next = &nodes14[11], .payload = {.id = 31, .data = (double)-18.484406}}, + {.next = &nodes14[223], .payload = {.id = 153, .data = (double)53.038804}}, + {.next = &nodes14[61], .payload = {.id = 211, .data = (double)64.74779}}, + {.next = &nodes14[14], .payload = {.id = 215, .data = (double)-37.329407}}, + {.next = &nodes14[207], .payload = {.id = 127, .data = (double)76.940046}}, + {.next = &nodes14[179], .payload = {.id = 64, .data = (double)39.007423}}, + {.next = &nodes14[124], .payload = {.id = 134, .data = (double)-1.889258}}, + {.next = &nodes14[29], .payload = {.id = 198, .data = (double)14.704139}}, + {.next = &nodes14[192], .payload = {.id = 148, .data = (double)18.092683}}, + {.next = &nodes14[217], .payload = {.id = 170, .data = (double)31.553557}}, + {.next = &nodes14[201], .payload = {.id = 133, .data = (double)13.771045}}, + {.next = &nodes14[195], .payload = {.id = 30, .data = (double)2.850201}}, + {.next = &nodes14[122], .payload = {.id = 128, .data = (double)-67.171151}}, + {.next = &nodes14[149], .payload = {.id = 188, .data = (double)-40.09582}}, + {.next = &nodes14[43], .payload = {.id = 146, .data = (double)-43.112492}}, + {.next = &nodes14[55], .payload = {.id = 28, .data = (double)96.260225}}, + {.next = &nodes14[157], .payload = {.id = 60, .data = (double)4.532475}}, + {.next = &nodes14[186], .payload = {.id = 35, .data = (double)3.945516}}, + {.next = &nodes14[73], .payload = {.id = 185, .data = (double)62.291436}}, + {.next = &nodes14[98], .payload = {.id = 101, .data = (double)-34.608823}}, + {.next = &nodes14[1], .payload = {.id = 23, .data = (double)39.626581}}, + {.next = &nodes14[167], .payload = {.id = 237, .data = (double)-59.870395}}, + {.next = &nodes14[136], .payload = {.id = 171, .data = (double)-15.505392}}, + {.next = &nodes14[163], .payload = {.id = 93, .data = (double)88.480601}}, + {.next = &nodes14[129], .payload = {.id = 104, .data = (double)52.034289}}, + {.next = &nodes14[97], .payload = {.id = 16, .data = (double)50.803574}}, + {.next = &nodes14[140], .payload = {.id = 221, .data = (double)76.179314}}, + {.next = &nodes14[143], .payload = {.id = 76, .data = (double)-0.177978}}, + {.next = &nodes14[160], .payload = {.id = 154, .data = (double)25.0306}}, + {.next = &nodes14[172], .payload = {.id = 80, .data = (double)51.260589}}, + {.next = &nodes14[75], .payload = {.id = 21, .data = (double)70.259362}}, + {.next = &nodes14[221], .payload = {.id = 220, .data = (double)9.512498}}, + {.next = &nodes14[23], .payload = {.id = 14, .data = (double)92.85276}}, + {.next = &nodes14[104], .payload = {.id = 5, .data = (double)71.027616}}, + {.next = &nodes14[117], .payload = {.id = 200, .data = (double)24.914458}}, + {.next = &nodes14[63], .payload = {.id = 253, .data = (double)-52.303316}}, + {.next = &nodes14[213], .payload = {.id = 184, .data = (double)-0.653721}}, + {.next = &nodes14[3], .payload = {.id = 10, .data = (double)63.917301}}, + {.next = &nodes14[180], .payload = {.id = 218, .data = (double)3.073846}}, + {.next = &nodes14[249], .payload = {.id = 164, .data = (double)37.598252}}, + {.next = &nodes14[10], .payload = {.id = 45, .data = (double)37.409311}}, + {.next = &nodes14[155], .payload = {.id = 140, .data = (double)-88.852575}}, + {.next = &nodes14[164], .payload = {.id = 168, .data = (double)7.683363}}, + {.next = &nodes14[49], .payload = {.id = 71, .data = (double)-59.947301}}, + {.next = &nodes14[19], .payload = {.id = 205, .data = (double)-45.327014}}, + {.next = &nodes14[58], .payload = {.id = 202, .data = (double)43.541369}}, + {.next = &nodes14[7], .payload = {.id = 66, .data = (double)48.286432}}, + {.next = &nodes14[159], .payload = {.id = 7, .data = (double)22.591286}}, + {.next = &nodes14[212], .payload = {.id = 34, .data = (double)-6.819661}}, + {.next = &nodes14[182], .payload = {.id = 69, .data = (double)-27.258001}}, + {.next = &nodes14[138], .payload = {.id = 40, .data = (double)-83.550411}}, + {.next = &nodes14[81], .payload = {.id = 51, .data = (double)71.35475}}, + {.next = &nodes14[232], .payload = {.id = 9, .data = (double)-86.332592}}, + {.next = &nodes14[89], .payload = {.id = 231, .data = (double)61.786696}}, + {.next = &nodes14[5], .payload = {.id = 165, .data = (double)73.787992}}, + {.next = &nodes14[74], .payload = {.id = 108, .data = (double)-6.795634}}, + {.next = &nodes14[181], .payload = {.id = 111, .data = (double)0.958951}}, + {.next = &nodes14[6], .payload = {.id = 143, .data = (double)-24.440459}}, + {.next = &nodes14[176], .payload = {.id = 124, .data = (double)-64.626165}}, + {.next = &nodes14[76], .payload = {.id = 118, .data = (double)76.025134}}, + {.next = &nodes14[134], .payload = {.id = 158, .data = (double)-17.614079}}, +}; + +node_t nodes15[] = { + {.next = &nodes15[193], .payload = {.id = 171, .data = (double)-14.453639}}, + {.next = &nodes15[117], .payload = {.id = 139, .data = (double)20.702721}}, + {.next = &nodes15[70], .payload = {.id = 95, .data = (double)-25.288338}}, + {.next = &nodes15[238], .payload = {.id = 14, .data = (double)-29.139663}}, + {.next = &nodes15[164], .payload = {.id = 65, .data = (double)79.035044}}, + {.next = &nodes15[234], .payload = {.id = 146, .data = (double)-46.304119}}, + {.next = &nodes15[189], .payload = {.id = 211, .data = (double)-18.98168}}, + {.next = &nodes15[31], .payload = {.id = 197, .data = (double)-31.733124}}, + {.next = &nodes15[214], .payload = {.id = 247, .data = (double)-41.033719}}, + {.next = &nodes15[87], .payload = {.id = 115, .data = (double)72.655769}}, + {.next = &nodes15[123], .payload = {.id = 206, .data = (double)-96.416956}}, + {.next = &nodes15[30], .payload = {.id = 23, .data = (double)95.504775}}, + {.next = &nodes15[199], .payload = {.id = 32, .data = (double)-6.383027}}, + {.next = &nodes15[118], .payload = {.id = 217, .data = (double)23.348965}}, + {.next = &nodes15[185], .payload = {.id = 71, .data = (double)-77.501823}}, + {.next = &nodes15[197], .payload = {.id = 213, .data = (double)48.849366}}, + {.next = &nodes15[120], .payload = {.id = 62, .data = (double)-67.289009}}, + {.next = &nodes15[89], .payload = {.id = 84, .data = (double)-99.174855}}, + {.next = &nodes15[35], .payload = {.id = 136, .data = (double)47.177857}}, + {.next = &nodes15[250], .payload = {.id = 130, .data = (double)-19.520753}}, + {.next = &nodes15[223], .payload = {.id = 158, .data = (double)42.727097}}, + {.next = &nodes15[192], .payload = {.id = 166, .data = (double)-39.921349}}, + {.next = &nodes15[1], .payload = {.id = 138, .data = (double)80.746854}}, + {.next = &nodes15[14], .payload = {.id = 70, .data = (double)-8.448059}}, + {.next = &nodes15[177], .payload = {.id = 39, .data = (double)-0.157877}}, + {.next = &nodes15[188], .payload = {.id = 215, .data = (double)-39.440004}}, + {.next = &nodes15[16], .payload = {.id = 61, .data = (double)-5.950494}}, + {.next = &nodes15[10], .payload = {.id = 205, .data = (double)-13.240216}}, + {.next = &nodes15[130], .payload = {.id = 152, .data = (double)26.137251}}, + {.next = &nodes15[64], .payload = {.id = 6, .data = (double)-23.300909}}, + {.next = &nodes15[174], .payload = {.id = 24, .data = (double)34.252404}}, + {.next = &nodes15[180], .payload = {.id = 198, .data = (double)83.622385}}, + {.next = &nodes15[233], .payload = {.id = 79, .data = (double)64.514351}}, + {.next = &nodes15[147], .payload = {.id = 89, .data = (double)-0.377845}}, + {.next = &nodes15[3], .payload = {.id = 13, .data = (double)-5.813515}}, + {.next = &nodes15[22], .payload = {.id = 137, .data = (double)84.339962}}, + {.next = &nodes15[2], .payload = {.id = 94, .data = (double)-75.601811}}, + {.next = &nodes15[142], .payload = {.id = 249, .data = (double)-21.653321}}, + {.next = &nodes15[128], .payload = {.id = 189, .data = (double)-90.948257}}, + {.next = &nodes15[17], .payload = {.id = 83, .data = (double)99.600911}}, + {.next = &nodes15[112], .payload = {.id = 103, .data = (double)25.671348}}, + {.next = &nodes15[79], .payload = {.id = 202, .data = (double)96.437238}}, + {.next = &nodes15[97], .payload = {.id = 20, .data = (double)-98.927803}}, + {.next = NULL, .payload = {.id = 255, .data = (double)-0.859358}}, + {.next = &nodes15[99], .payload = {.id = 35, .data = (double)-13.414068}}, + {.next = &nodes15[127], .payload = {.id = 161, .data = (double)29.445078}}, + {.next = &nodes15[23], .payload = {.id = 69, .data = (double)12.170904}}, + {.next = &nodes15[156], .payload = {.id = 109, .data = (double)-9.379601}}, + {.next = &nodes15[81], .payload = {.id = 132, .data = (double)90.886491}}, + {.next = &nodes15[198], .payload = {.id = 74, .data = (double)-30.07914}}, + {.next = &nodes15[107], .payload = {.id = 180, .data = (double)62.564952}}, + {.next = &nodes15[252], .payload = {.id = 101, .data = (double)41.54133}}, + {.next = &nodes15[20], .payload = {.id = 157, .data = (double)29.522123}}, + {.next = &nodes15[114], .payload = {.id = 45, .data = (double)-47.356722}}, + {.next = &nodes15[113], .payload = {.id = 144, .data = (double)-10.911517}}, + {.next = &nodes15[171], .payload = {.id = 76, .data = (double)-43.17671}}, + {.next = &nodes15[101], .payload = {.id = 195, .data = (double)-10.010419}}, + {.next = &nodes15[43], .payload = {.id = 254, .data = (double)-16.862819}}, + {.next = &nodes15[140], .payload = {.id = 191, .data = (double)40.875711}}, + {.next = &nodes15[158], .payload = {.id = 243, .data = (double)-2.990633}}, + {.next = &nodes15[220], .payload = {.id = 113, .data = (double)59.406693}}, + {.next = &nodes15[76], .payload = {.id = 2, .data = (double)74.288695}}, + {.next = &nodes15[213], .payload = {.id = 48, .data = (double)3.394537}}, + {.next = &nodes15[178], .payload = {.id = 50, .data = (double)-67.003236}}, + {.next = &nodes15[159], .payload = {.id = 7, .data = (double)-15.34181}}, + {.next = &nodes15[207], .payload = {.id = 55, .data = (double)84.570561}}, + {.next = &nodes15[181], .payload = {.id = 122, .data = (double)-81.489798}}, + {.next = &nodes15[91], .payload = {.id = 219, .data = (double)92.628322}}, + {.next = &nodes15[160], .payload = {.id = 127, .data = (double)-95.897593}}, + {.next = &nodes15[51], .payload = {.id = 100, .data = (double)-7.953364}}, + {.next = &nodes15[122], .payload = {.id = 96, .data = (double)85.829689}}, + {.next = &nodes15[191], .payload = {.id = 187, .data = (double)57.235419}}, + {.next = &nodes15[32], .payload = {.id = 78, .data = (double)49.98733}}, + {.next = &nodes15[61], .payload = {.id = 1, .data = (double)-6.223678}}, + {.next = &nodes15[116], .payload = {.id = 18, .data = (double)41.913193}}, + {.next = &nodes15[235], .payload = {.id = 107, .data = (double)-91.2306}}, + {.next = &nodes15[236], .payload = {.id = 3, .data = (double)94.879835}}, + {.next = &nodes15[145], .payload = {.id = 200, .data = (double)-57.786326}}, + {.next = &nodes15[206], .payload = {.id = 149, .data = (double)-15.49273}}, + {.next = &nodes15[157], .payload = {.id = 203, .data = (double)-48.136465}}, + {.next = &nodes15[115], .payload = {.id = 81, .data = (double)32.627536}}, + {.next = &nodes15[96], .payload = {.id = 133, .data = (double)-69.173068}}, + {.next = &nodes15[65], .payload = {.id = 54, .data = (double)11.134942}}, + {.next = &nodes15[200], .payload = {.id = 118, .data = (double)59.629394}}, + {.next = &nodes15[248], .payload = {.id = 184, .data = (double)-96.746261}}, + {.next = &nodes15[45], .payload = {.id = 160, .data = (double)5.455742}}, + {.next = &nodes15[230], .payload = {.id = 67, .data = (double)-11.696062}}, + {.next = &nodes15[138], .payload = {.id = 116, .data = (double)60.311593}}, + {.next = &nodes15[251], .payload = {.id = 252, .data = (double)69.525906}}, + {.next = &nodes15[204], .payload = {.id = 85, .data = (double)53.369526}}, + {.next = &nodes15[124], .payload = {.id = 233, .data = (double)71.637872}}, + {.next = &nodes15[211], .payload = {.id = 220, .data = (double)35.020458}}, + {.next = &nodes15[196], .payload = {.id = 245, .data = (double)-10.096744}}, + {.next = &nodes15[149], .payload = {.id = 163, .data = (double)-6.356166}}, + {.next = &nodes15[62], .payload = {.id = 47, .data = (double)85.343376}}, + {.next = &nodes15[44], .payload = {.id = 34, .data = (double)42.051115}}, + {.next = &nodes15[237], .payload = {.id = 134, .data = (double)-40.290668}}, + {.next = &nodes15[183], .payload = {.id = 21, .data = (double)0.9084}}, + {.next = &nodes15[194], .payload = {.id = 226, .data = (double)39.206488}}, + {.next = &nodes15[125], .payload = {.id = 36, .data = (double)-47.918798}}, + {.next = &nodes15[179], .payload = {.id = 43, .data = (double)-13.982796}}, + {.next = &nodes15[7], .payload = {.id = 196, .data = (double)61.566814}}, + {.next = &nodes15[12], .payload = {.id = 31, .data = (double)-32.164653}}, + {.next = &nodes15[73], .payload = {.id = 0, .data = (double)-82.852265}}, + {.next = &nodes15[227], .payload = {.id = 105, .data = (double)31.601261}}, + {.next = &nodes15[195], .payload = {.id = 98, .data = (double)-35.292333}}, + {.next = &nodes15[182], .payload = {.id = 169, .data = (double)-39.918269}}, + {.next = &nodes15[239], .payload = {.id = 181, .data = (double)-28.908473}}, + {.next = &nodes15[205], .payload = {.id = 174, .data = (double)83.460403}}, + {.next = &nodes15[166], .payload = {.id = 235, .data = (double)-82.781291}}, + {.next = &nodes15[246], .payload = {.id = 238, .data = (double)-15.624155}}, + {.next = &nodes15[74], .payload = {.id = 17, .data = (double)60.449701}}, + {.next = &nodes15[104], .payload = {.id = 104, .data = (double)-46.136313}}, + {.next = &nodes15[5], .payload = {.id = 145, .data = (double)-22.382095}}, + {.next = &nodes15[94], .payload = {.id = 46, .data = (double)65.917836}}, + {.next = &nodes15[39], .payload = {.id = 82, .data = (double)-57.520769}}, + {.next = &nodes15[42], .payload = {.id = 19, .data = (double)61.97059}}, + {.next = &nodes15[232], .payload = {.id = 140, .data = (double)-28.191148}}, + {.next = &nodes15[67], .payload = {.id = 218, .data = (double)38.132458}}, + {.next = &nodes15[173], .payload = {.id = 193, .data = (double)44.818937}}, + {.next = &nodes15[121], .payload = {.id = 63, .data = (double)-6.573432}}, + {.next = &nodes15[4], .payload = {.id = 64, .data = (double)-76.795191}}, + {.next = &nodes15[105], .payload = {.id = 97, .data = (double)-78.786016}}, + {.next = &nodes15[133], .payload = {.id = 207, .data = (double)-21.013231}}, + {.next = &nodes15[109], .payload = {.id = 234, .data = (double)7.716507}}, + {.next = &nodes15[143], .payload = {.id = 37, .data = (double)-37.346078}}, + {.next = &nodes15[36], .payload = {.id = 93, .data = (double)96.266895}}, + {.next = &nodes15[93], .payload = {.id = 162, .data = (double)-83.20598}}, + {.next = &nodes15[58], .payload = {.id = 190, .data = (double)-16.749688}}, + {.next = &nodes15[186], .payload = {.id = 52, .data = (double)-1.745044}}, + {.next = &nodes15[203], .payload = {.id = 153, .data = (double)-81.410508}}, + {.next = &nodes15[100], .payload = {.id = 42, .data = (double)-27.881558}}, + {.next = &nodes15[110], .payload = {.id = 237, .data = (double)-70.366871}}, + {.next = &nodes15[243], .payload = {.id = 208, .data = (double)-97.33908}}, + {.next = &nodes15[146], .payload = {.id = 10, .data = (double)11.399995}}, + {.next = &nodes15[90], .payload = {.id = 232, .data = (double)68.417942}}, + {.next = &nodes15[137], .payload = {.id = 27, .data = (double)-91.775002}}, + {.next = &nodes15[225], .payload = {.id = 28, .data = (double)-64.125555}}, + {.next = &nodes15[83], .payload = {.id = 117, .data = (double)-43.409198}}, + {.next = &nodes15[6], .payload = {.id = 210, .data = (double)-7.967397}}, + {.next = &nodes15[119], .payload = {.id = 192, .data = (double)-37.210729}}, + {.next = &nodes15[136], .payload = {.id = 26, .data = (double)78.44519}}, + {.next = &nodes15[241], .payload = {.id = 250, .data = (double)-33.229989}}, + {.next = &nodes15[24], .payload = {.id = 38, .data = (double)95.70332}}, + {.next = &nodes15[244], .payload = {.id = 230, .data = (double)-70.969162}}, + {.next = &nodes15[41], .payload = {.id = 201, .data = (double)-84.355894}}, + {.next = &nodes15[167], .payload = {.id = 11, .data = (double)-89.577478}}, + {.next = &nodes15[165], .payload = {.id = 90, .data = (double)-81.138955}}, + {.next = &nodes15[221], .payload = {.id = 87, .data = (double)84.082639}}, + {.next = &nodes15[228], .payload = {.id = 164, .data = (double)-84.163374}}, + {.next = &nodes15[163], .payload = {.id = 241, .data = (double)47.756236}}, + {.next = &nodes15[154], .payload = {.id = 57, .data = (double)-12.002081}}, + {.next = &nodes15[54], .payload = {.id = 143, .data = (double)-60.025748}}, + {.next = &nodes15[102], .payload = {.id = 30, .data = (double)-1.432034}}, + {.next = &nodes15[240], .payload = {.id = 58, .data = (double)-62.216009}}, + {.next = &nodes15[98], .payload = {.id = 225, .data = (double)63.193645}}, + {.next = &nodes15[218], .payload = {.id = 110, .data = (double)89.483679}}, + {.next = &nodes15[27], .payload = {.id = 204, .data = (double)34.681752}}, + {.next = &nodes15[92], .payload = {.id = 244, .data = (double)-96.074444}}, + {.next = &nodes15[254], .payload = {.id = 8, .data = (double)19.439188}}, + {.next = &nodes15[208], .payload = {.id = 128, .data = (double)-58.355452}}, + {.next = &nodes15[50], .payload = {.id = 179, .data = (double)44.062}}, + {.next = &nodes15[219], .payload = {.id = 177, .data = (double)-17.396119}}, + {.next = &nodes15[59], .payload = {.id = 242, .data = (double)-10.94681}}, + {.next = &nodes15[86], .payload = {.id = 66, .data = (double)-1.017845}}, + {.next = &nodes15[190], .payload = {.id = 91, .data = (double)-34.268445}}, + {.next = &nodes15[132], .payload = {.id = 236, .data = (double)53.944229}}, + {.next = &nodes15[34], .payload = {.id = 12, .data = (double)86.212921}}, + {.next = &nodes15[152], .payload = {.id = 142, .data = (double)-26.508635}}, + {.next = &nodes15[71], .payload = {.id = 186, .data = (double)-7.424211}}, + {.next = &nodes15[26], .payload = {.id = 60, .data = (double)-63.371736}}, + {.next = &nodes15[72], .payload = {.id = 77, .data = (double)66.990732}}, + {.next = &nodes15[155], .payload = {.id = 224, .data = (double)-61.839583}}, + {.next = &nodes15[56], .payload = {.id = 194, .data = (double)51.470853}}, + {.next = &nodes15[141], .payload = {.id = 25, .data = (double)-73.552349}}, + {.next = &nodes15[224], .payload = {.id = 125, .data = (double)54.175497}}, + {.next = &nodes15[247], .payload = {.id = 155, .data = (double)94.654358}}, + {.next = &nodes15[216], .payload = {.id = 40, .data = (double)94.674298}}, + {.next = &nodes15[129], .payload = {.id = 51, .data = (double)47.373848}}, + {.next = &nodes15[53], .payload = {.id = 44, .data = (double)80.558535}}, + {.next = &nodes15[77], .payload = {.id = 199, .data = (double)62.001202}}, + {.next = &nodes15[253], .payload = {.id = 123, .data = (double)-48.96722}}, + {.next = &nodes15[0], .payload = {.id = 170, .data = (double)-50.269299}}, + {.next = &nodes15[11], .payload = {.id = 22, .data = (double)-23.812465}}, + {.next = &nodes15[162], .payload = {.id = 176, .data = (double)2.130317}}, + {.next = &nodes15[215], .payload = {.id = 72, .data = (double)43.952793}}, + {.next = &nodes15[82], .payload = {.id = 53, .data = (double)90.01014}}, + {.next = &nodes15[172], .payload = {.id = 223, .data = (double)-72.977211}}, + {.next = &nodes15[13], .payload = {.id = 216, .data = (double)62.626496}}, + {.next = &nodes15[15], .payload = {.id = 212, .data = (double)31.543419}}, + {.next = &nodes15[126], .payload = {.id = 92, .data = (double)-43.14375}}, + {.next = &nodes15[38], .payload = {.id = 188, .data = (double)68.581965}}, + {.next = &nodes15[201], .payload = {.id = 167, .data = (double)96.837247}}, + {.next = &nodes15[245], .payload = {.id = 172, .data = (double)13.707137}}, + {.next = &nodes15[229], .payload = {.id = 227, .data = (double)-62.355779}}, + {.next = &nodes15[69], .payload = {.id = 99, .data = (double)-94.2251}}, + {.next = &nodes15[8], .payload = {.id = 246, .data = (double)-51.47407}}, + {.next = &nodes15[25], .payload = {.id = 214, .data = (double)45.182281}}, + {.next = &nodes15[55], .payload = {.id = 75, .data = (double)-59.253258}}, + {.next = &nodes15[95], .payload = {.id = 33, .data = (double)-82.070404}}, + {.next = &nodes15[212], .payload = {.id = 119, .data = (double)48.759998}}, + {.next = &nodes15[106], .payload = {.id = 168, .data = (double)36.862787}}, + {.next = &nodes15[84], .payload = {.id = 183, .data = (double)53.729355}}, + {.next = &nodes15[176], .payload = {.id = 154, .data = (double)2.668292}}, + {.next = &nodes15[148], .payload = {.id = 86, .data = (double)-63.886231}}, + {.next = &nodes15[184], .payload = {.id = 175, .data = (double)2.682904}}, + {.next = &nodes15[249], .payload = {.id = 150, .data = (double)-26.352794}}, + {.next = &nodes15[151], .payload = {.id = 56, .data = (double)27.330438}}, + {.next = &nodes15[19], .payload = {.id = 129, .data = (double)-22.29942}}, + {.next = &nodes15[150], .payload = {.id = 240, .data = (double)80.483067}}, + {.next = &nodes15[60], .payload = {.id = 112, .data = (double)81.375673}}, + {.next = &nodes15[242], .payload = {.id = 221, .data = (double)60.928147}}, + {.next = &nodes15[226], .payload = {.id = 120, .data = (double)9.431244}}, + {.next = &nodes15[63], .payload = {.id = 49, .data = (double)-12.844926}}, + {.next = &nodes15[37], .payload = {.id = 248, .data = (double)65.890153}}, + {.next = &nodes15[49], .payload = {.id = 73, .data = (double)-70.389259}}, + {.next = &nodes15[131], .payload = {.id = 41, .data = (double)-43.79987}}, + {.next = &nodes15[29], .payload = {.id = 5, .data = (double)-57.556467}}, + {.next = &nodes15[210], .payload = {.id = 111, .data = (double)99.964222}}, + {.next = &nodes15[161], .payload = {.id = 178, .data = (double)-7.068702}}, + {.next = &nodes15[9], .payload = {.id = 114, .data = (double)-74.13596}}, + {.next = &nodes15[33], .payload = {.id = 88, .data = (double)-50.768513}}, + {.next = &nodes15[144], .payload = {.id = 229, .data = (double)-3.776561}}, + {.next = &nodes15[85], .payload = {.id = 159, .data = (double)86.133523}}, + {.next = &nodes15[68], .payload = {.id = 126, .data = (double)-20.216548}}, + {.next = &nodes15[153], .payload = {.id = 29, .data = (double)-66.0267}}, + {.next = &nodes15[66], .payload = {.id = 121, .data = (double)20.458305}}, + {.next = &nodes15[75], .payload = {.id = 106, .data = (double)-34.114616}}, + {.next = &nodes15[21], .payload = {.id = 165, .data = (double)60.308938}}, + {.next = &nodes15[222], .payload = {.id = 228, .data = (double)-94.636941}}, + {.next = &nodes15[46], .payload = {.id = 68, .data = (double)97.763717}}, + {.next = &nodes15[111], .payload = {.id = 16, .data = (double)34.158309}}, + {.next = &nodes15[168], .payload = {.id = 141, .data = (double)-80.7777}}, + {.next = &nodes15[80], .payload = {.id = 80, .data = (double)12.649478}}, + {.next = &nodes15[255], .payload = {.id = 147, .data = (double)20.06815}}, + {.next = &nodes15[47], .payload = {.id = 108, .data = (double)24.472971}}, + {.next = &nodes15[217], .payload = {.id = 4, .data = (double)-20.489057}}, + {.next = &nodes15[18], .payload = {.id = 135, .data = (double)60.220084}}, + {.next = &nodes15[231], .payload = {.id = 15, .data = (double)21.274893}}, + {.next = &nodes15[202], .payload = {.id = 182, .data = (double)17.113577}}, + {.next = &nodes15[170], .payload = {.id = 59, .data = (double)-89.086567}}, + {.next = &nodes15[88], .payload = {.id = 251, .data = (double)-79.467296}}, + {.next = &nodes15[187], .payload = {.id = 222, .data = (double)-82.472974}}, + {.next = &nodes15[139], .payload = {.id = 209, .data = (double)31.160194}}, + {.next = &nodes15[135], .payload = {.id = 231, .data = (double)-51.643957}}, + {.next = &nodes15[108], .payload = {.id = 173, .data = (double)10.198866}}, + {.next = &nodes15[209], .payload = {.id = 239, .data = (double)-76.708236}}, + {.next = &nodes15[52], .payload = {.id = 156, .data = (double)35.288006}}, + {.next = &nodes15[169], .payload = {.id = 185, .data = (double)48.103234}}, + {.next = &nodes15[28], .payload = {.id = 151, .data = (double)-62.728834}}, + {.next = &nodes15[48], .payload = {.id = 131, .data = (double)29.4336}}, + {.next = &nodes15[57], .payload = {.id = 253, .data = (double)-13.642409}}, + {.next = &nodes15[40], .payload = {.id = 102, .data = (double)-4.028981}}, + {.next = &nodes15[175], .payload = {.id = 124, .data = (double)-51.983973}}, + {.next = &nodes15[134], .payload = {.id = 9, .data = (double)-85.388876}}, + {.next = &nodes15[78], .payload = {.id = 148, .data = (double)-81.95553}}, +}; + +node_t* head[16] = { + &nodes0[197], + &nodes1[162], + &nodes2[1], + &nodes3[21], + &nodes4[85], + &nodes5[135], + &nodes6[176], + &nodes7[112], + &nodes8[113], + &nodes9[8], + &nodes10[20], + &nodes11[4], + &nodes12[226], + &nodes13[154], + &nodes14[96], + &nodes15[103], +}; + diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/data/data_64_8.h b/software/tests/multi_producer_single_consumer_double_linked_list/data/data_64_8.h new file mode 100644 index 0000000..a75f2b8 --- /dev/null +++ b/software/tests/multi_producer_single_consumer_double_linked_list/data/data_64_8.h @@ -0,0 +1,559 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This file was generated automatically. + +#include "layer.h" + +int N = 64; + +int N_list = 8; + +node_t nodes0[] = { + {.next = NULL, .payload = {.id = 63, .data = (double)36.92285}}, + {.next = &nodes0[63], .payload = {.id = 6, .data = (double)78.435914}}, + {.next = &nodes0[52], .payload = {.id = 44, .data = (double)-84.041605}}, + {.next = &nodes0[18], .payload = {.id = 11, .data = (double)1.071058}}, + {.next = &nodes0[36], .payload = {.id = 26, .data = (double)-81.450831}}, + {.next = &nodes0[33], .payload = {.id = 61, .data = (double)27.999952}}, + {.next = &nodes0[47], .payload = {.id = 56, .data = (double)-65.77227}}, + {.next = &nodes0[8], .payload = {.id = 39, .data = (double)15.470429}}, + {.next = &nodes0[49], .payload = {.id = 40, .data = (double)40.914367}}, + {.next = &nodes0[7], .payload = {.id = 38, .data = (double)72.34138}}, + {.next = &nodes0[45], .payload = {.id = 28, .data = (double)69.498873}}, + {.next = &nodes0[3], .payload = {.id = 10, .data = (double)-56.272405}}, + {.next = &nodes0[28], .payload = {.id = 0, .data = (double)27.88536}}, + {.next = &nodes0[34], .payload = {.id = 22, .data = (double)-31.949897}}, + {.next = &nodes0[35], .payload = {.id = 46, .data = (double)-79.799714}}, + {.next = &nodes0[16], .payload = {.id = 32, .data = (double)7.245618}}, + {.next = &nodes0[39], .payload = {.id = 33, .data = (double)94.623153}}, + {.next = &nodes0[20], .payload = {.id = 18, .data = (double)61.886091}}, + {.next = &nodes0[54], .payload = {.id = 12, .data = (double)-94.692806}}, + {.next = &nodes0[48], .payload = {.id = 30, .data = (double)61.425655}}, + {.next = &nodes0[58], .payload = {.id = 19, .data = (double)-98.700248}}, + {.next = &nodes0[59], .payload = {.id = 50, .data = (double)-25.963807}}, + {.next = &nodes0[13], .payload = {.id = 21, .data = (double)39.627879}}, + {.next = &nodes0[1], .payload = {.id = 5, .data = (double)35.339897}}, + {.next = &nodes0[30], .payload = {.id = 59, .data = (double)-24.108912}}, + {.next = &nodes0[6], .payload = {.id = 55, .data = (double)21.826201}}, + {.next = &nodes0[55], .payload = {.id = 3, .data = (double)-55.357852}}, + {.next = &nodes0[50], .payload = {.id = 53, .data = (double)87.330918}}, + {.next = &nodes0[60], .payload = {.id = 1, .data = (double)-94.997849}}, + {.next = &nodes0[57], .payload = {.id = 24, .data = (double)91.442614}}, + {.next = &nodes0[5], .payload = {.id = 60, .data = (double)97.90467}}, + {.next = &nodes0[46], .payload = {.id = 48, .data = (double)27.136889}}, + {.next = &nodes0[38], .payload = {.id = 42, .data = (double)-54.420345}}, + {.next = &nodes0[0], .payload = {.id = 62, .data = (double)11.389949}}, + {.next = &nodes0[29], .payload = {.id = 23, .data = (double)-68.9041}}, + {.next = &nodes0[31], .payload = {.id = 47, .data = (double)-44.405279}}, + {.next = &nodes0[10], .payload = {.id = 27, .data = (double)-80.656725}}, + {.next = &nodes0[9], .payload = {.id = 37, .data = (double)23.70395}}, + {.next = &nodes0[2], .payload = {.id = 43, .data = (double)-42.122407}}, + {.next = &nodes0[40], .payload = {.id = 34, .data = (double)-24.293125}}, + {.next = &nodes0[53], .payload = {.id = 35, .data = (double)10.408126}}, + {.next = &nodes0[43], .payload = {.id = 15, .data = (double)8.988296}}, + {.next = &nodes0[44], .payload = {.id = 8, .data = (double)-15.615636}}, + {.next = &nodes0[56], .payload = {.id = 16, .data = (double)-55.911876}}, + {.next = &nodes0[11], .payload = {.id = 9, .data = (double)-94.040556}}, + {.next = &nodes0[19], .payload = {.id = 29, .data = (double)20.745206}}, + {.next = &nodes0[21], .payload = {.id = 49, .data = (double)-27.033564}}, + {.next = &nodes0[51], .payload = {.id = 57, .data = (double)45.82536}}, + {.next = &nodes0[15], .payload = {.id = 31, .data = (double)45.946357}}, + {.next = &nodes0[32], .payload = {.id = 41, .data = (double)-90.835123}}, + {.next = &nodes0[25], .payload = {.id = 54, .data = (double)29.607077}}, + {.next = &nodes0[24], .payload = {.id = 58, .data = (double)-67.319501}}, + {.next = &nodes0[14], .payload = {.id = 45, .data = (double)-53.441823}}, + {.next = &nodes0[37], .payload = {.id = 36, .data = (double)65.880933}}, + {.next = &nodes0[62], .payload = {.id = 13, .data = (double)-60.23247}}, + {.next = &nodes0[23], .payload = {.id = 4, .data = (double)47.294243}}, + {.next = &nodes0[17], .payload = {.id = 17, .data = (double)17.853137}}, + {.next = &nodes0[4], .payload = {.id = 25, .data = (double)-32.681091}}, + {.next = &nodes0[22], .payload = {.id = 20, .data = (double)61.16385}}, + {.next = &nodes0[61], .payload = {.id = 51, .data = (double)-58.098594}}, + {.next = &nodes0[26], .payload = {.id = 2, .data = (double)-44.994136}}, + {.next = &nodes0[27], .payload = {.id = 52, .data = (double)-46.604436}}, + {.next = &nodes0[41], .payload = {.id = 14, .data = (double)29.976888}}, + {.next = &nodes0[42], .payload = {.id = 7, .data = (double)-82.612233}}, +}; + +node_t nodes1[] = { + {.next = &nodes1[19], .payload = {.id = 36, .data = (double)-57.640359}}, + {.next = &nodes1[13], .payload = {.id = 23, .data = (double)75.60192}}, + {.next = &nodes1[17], .payload = {.id = 4, .data = (double)-64.269624}}, + {.next = &nodes1[45], .payload = {.id = 49, .data = (double)-53.977053}}, + {.next = &nodes1[15], .payload = {.id = 30, .data = (double)-74.321707}}, + {.next = &nodes1[33], .payload = {.id = 16, .data = (double)-35.168789}}, + {.next = &nodes1[34], .payload = {.id = 10, .data = (double)-69.432146}}, + {.next = &nodes1[6], .payload = {.id = 9, .data = (double)21.794042}}, + {.next = &nodes1[9], .payload = {.id = 38, .data = (double)45.986214}}, + {.next = &nodes1[39], .payload = {.id = 39, .data = (double)-59.769787}}, + {.next = &nodes1[22], .payload = {.id = 19, .data = (double)75.744376}}, + {.next = &nodes1[54], .payload = {.id = 55, .data = (double)71.92708}}, + {.next = &nodes1[46], .payload = {.id = 57, .data = (double)-52.399073}}, + {.next = &nodes1[44], .payload = {.id = 24, .data = (double)89.389889}}, + {.next = &nodes1[10], .payload = {.id = 18, .data = (double)85.819723}}, + {.next = &nodes1[29], .payload = {.id = 31, .data = (double)-4.943524}}, + {.next = &nodes1[27], .payload = {.id = 13, .data = (double)55.725296}}, + {.next = &nodes1[59], .payload = {.id = 5, .data = (double)82.525568}}, + {.next = &nodes1[36], .payload = {.id = 7, .data = (double)-40.311042}}, + {.next = &nodes1[8], .payload = {.id = 37, .data = (double)7.859218}}, + {.next = &nodes1[23], .payload = {.id = 0, .data = (double)90.763186}}, + {.next = &nodes1[35], .payload = {.id = 53, .data = (double)-54.211643}}, + {.next = &nodes1[43], .payload = {.id = 20, .data = (double)66.333106}}, + {.next = &nodes1[28], .payload = {.id = 1, .data = (double)75.170588}}, + {.next = &nodes1[51], .payload = {.id = 45, .data = (double)-75.799161}}, + {.next = &nodes1[38], .payload = {.id = 33, .data = (double)-46.988674}}, + {.next = &nodes1[24], .payload = {.id = 44, .data = (double)3.515168}}, + {.next = &nodes1[41], .payload = {.id = 14, .data = (double)6.070734}}, + {.next = &nodes1[50], .payload = {.id = 2, .data = (double)-47.32219}}, + {.next = &nodes1[25], .payload = {.id = 32, .data = (double)9.960719}}, + {.next = &nodes1[0], .payload = {.id = 35, .data = (double)-15.372412}}, + {.next = &nodes1[47], .payload = {.id = 47, .data = (double)-32.382888}}, + {.next = &nodes1[21], .payload = {.id = 52, .data = (double)26.220591}}, + {.next = &nodes1[14], .payload = {.id = 17, .data = (double)-96.104652}}, + {.next = &nodes1[60], .payload = {.id = 11, .data = (double)52.50216}}, + {.next = &nodes1[11], .payload = {.id = 54, .data = (double)81.084003}}, + {.next = &nodes1[7], .payload = {.id = 8, .data = (double)27.789899}}, + {.next = &nodes1[52], .payload = {.id = 28, .data = (double)52.120433}}, + {.next = &nodes1[30], .payload = {.id = 34, .data = (double)74.486608}}, + {.next = &nodes1[48], .payload = {.id = 40, .data = (double)-37.656742}}, + {.next = NULL, .payload = {.id = 63, .data = (double)-5.465795}}, + {.next = &nodes1[5], .payload = {.id = 15, .data = (double)-99.885621}}, + {.next = &nodes1[40], .payload = {.id = 62, .data = (double)14.208619}}, + {.next = &nodes1[55], .payload = {.id = 21, .data = (double)-38.497175}}, + {.next = &nodes1[61], .payload = {.id = 25, .data = (double)-82.86931}}, + {.next = &nodes1[62], .payload = {.id = 50, .data = (double)-55.956523}}, + {.next = &nodes1[58], .payload = {.id = 58, .data = (double)33.795556}}, + {.next = &nodes1[3], .payload = {.id = 48, .data = (double)17.661744}}, + {.next = &nodes1[57], .payload = {.id = 41, .data = (double)99.029871}}, + {.next = &nodes1[26], .payload = {.id = 43, .data = (double)-12.379983}}, + {.next = &nodes1[2], .payload = {.id = 3, .data = (double)0.117223}}, + {.next = &nodes1[31], .payload = {.id = 46, .data = (double)-55.060533}}, + {.next = &nodes1[4], .payload = {.id = 29, .data = (double)53.166886}}, + {.next = &nodes1[42], .payload = {.id = 61, .data = (double)87.102848}}, + {.next = &nodes1[12], .payload = {.id = 56, .data = (double)-85.82853}}, + {.next = &nodes1[1], .payload = {.id = 22, .data = (double)-88.414967}}, + {.next = &nodes1[37], .payload = {.id = 27, .data = (double)-86.157496}}, + {.next = &nodes1[49], .payload = {.id = 42, .data = (double)29.975612}}, + {.next = &nodes1[63], .payload = {.id = 59, .data = (double)-57.152639}}, + {.next = &nodes1[18], .payload = {.id = 6, .data = (double)74.103714}}, + {.next = &nodes1[16], .payload = {.id = 12, .data = (double)7.875806}}, + {.next = &nodes1[56], .payload = {.id = 26, .data = (double)-2.801907}}, + {.next = &nodes1[32], .payload = {.id = 51, .data = (double)-85.801383}}, + {.next = &nodes1[53], .payload = {.id = 60, .data = (double)-73.53763}}, +}; + +node_t nodes2[] = { + {.next = &nodes2[9], .payload = {.id = 46, .data = (double)66.748991}}, + {.next = &nodes2[60], .payload = {.id = 15, .data = (double)35.042511}}, + {.next = &nodes2[26], .payload = {.id = 29, .data = (double)-20.842831}}, + {.next = &nodes2[19], .payload = {.id = 61, .data = (double)20.965965}}, + {.next = &nodes2[53], .payload = {.id = 26, .data = (double)-59.14816}}, + {.next = &nodes2[49], .payload = {.id = 20, .data = (double)18.903831}}, + {.next = &nodes2[0], .payload = {.id = 45, .data = (double)-68.450634}}, + {.next = &nodes2[20], .payload = {.id = 55, .data = (double)87.786001}}, + {.next = &nodes2[5], .payload = {.id = 19, .data = (double)-50.75693}}, + {.next = &nodes2[31], .payload = {.id = 47, .data = (double)40.707985}}, + {.next = &nodes2[27], .payload = {.id = 24, .data = (double)4.556543}}, + {.next = &nodes2[1], .payload = {.id = 14, .data = (double)19.007021}}, + {.next = &nodes2[17], .payload = {.id = 12, .data = (double)-83.977707}}, + {.next = &nodes2[32], .payload = {.id = 41, .data = (double)86.651876}}, + {.next = &nodes2[8], .payload = {.id = 18, .data = (double)78.057463}}, + {.next = &nodes2[34], .payload = {.id = 22, .data = (double)-16.155017}}, + {.next = &nodes2[22], .payload = {.id = 38, .data = (double)-85.347856}}, + {.next = &nodes2[11], .payload = {.id = 13, .data = (double)-62.835008}}, + {.next = &nodes2[42], .payload = {.id = 52, .data = (double)63.420827}}, + {.next = &nodes2[29], .payload = {.id = 62, .data = (double)43.522437}}, + {.next = &nodes2[59], .payload = {.id = 56, .data = (double)-73.141777}}, + {.next = &nodes2[33], .payload = {.id = 36, .data = (double)99.690888}}, + {.next = &nodes2[54], .payload = {.id = 39, .data = (double)-57.369138}}, + {.next = &nodes2[40], .payload = {.id = 49, .data = (double)97.446613}}, + {.next = &nodes2[39], .payload = {.id = 6, .data = (double)-88.566945}}, + {.next = &nodes2[6], .payload = {.id = 44, .data = (double)-26.094582}}, + {.next = &nodes2[61], .payload = {.id = 30, .data = (double)34.338045}}, + {.next = &nodes2[4], .payload = {.id = 25, .data = (double)86.941252}}, + {.next = &nodes2[12], .payload = {.id = 11, .data = (double)92.155781}}, + {.next = NULL, .payload = {.id = 63, .data = (double)-59.280538}}, + {.next = &nodes2[51], .payload = {.id = 1, .data = (double)-40.658435}}, + {.next = &nodes2[23], .payload = {.id = 48, .data = (double)22.335553}}, + {.next = &nodes2[41], .payload = {.id = 42, .data = (double)76.172835}}, + {.next = &nodes2[16], .payload = {.id = 37, .data = (double)99.21929}}, + {.next = &nodes2[10], .payload = {.id = 23, .data = (double)16.734458}}, + {.next = &nodes2[18], .payload = {.id = 51, .data = (double)-98.435379}}, + {.next = &nodes2[43], .payload = {.id = 34, .data = (double)-85.491377}}, + {.next = &nodes2[45], .payload = {.id = 9, .data = (double)70.543978}}, + {.next = &nodes2[55], .payload = {.id = 4, .data = (double)8.43904}}, + {.next = &nodes2[48], .payload = {.id = 7, .data = (double)16.835519}}, + {.next = &nodes2[35], .payload = {.id = 50, .data = (double)30.795264}}, + {.next = &nodes2[25], .payload = {.id = 43, .data = (double)75.854048}}, + {.next = &nodes2[57], .payload = {.id = 53, .data = (double)-40.12425}}, + {.next = &nodes2[21], .payload = {.id = 35, .data = (double)-8.342895}}, + {.next = &nodes2[2], .payload = {.id = 28, .data = (double)-52.262809}}, + {.next = &nodes2[28], .payload = {.id = 10, .data = (double)-68.513454}}, + {.next = &nodes2[3], .payload = {.id = 60, .data = (double)-45.530358}}, + {.next = &nodes2[46], .payload = {.id = 59, .data = (double)10.644728}}, + {.next = &nodes2[37], .payload = {.id = 8, .data = (double)0.570077}}, + {.next = &nodes2[15], .payload = {.id = 21, .data = (double)23.876302}}, + {.next = &nodes2[30], .payload = {.id = 0, .data = (double)-69.040635}}, + {.next = &nodes2[56], .payload = {.id = 2, .data = (double)93.741873}}, + {.next = &nodes2[14], .payload = {.id = 17, .data = (double)-76.022677}}, + {.next = &nodes2[44], .payload = {.id = 27, .data = (double)43.23836}}, + {.next = &nodes2[13], .payload = {.id = 40, .data = (double)-46.959917}}, + {.next = &nodes2[24], .payload = {.id = 5, .data = (double)49.595112}}, + {.next = &nodes2[38], .payload = {.id = 3, .data = (double)15.836058}}, + {.next = &nodes2[7], .payload = {.id = 54, .data = (double)32.677743}}, + {.next = &nodes2[47], .payload = {.id = 58, .data = (double)-78.592804}}, + {.next = &nodes2[58], .payload = {.id = 57, .data = (double)-76.914266}}, + {.next = &nodes2[52], .payload = {.id = 16, .data = (double)-52.959221}}, + {.next = &nodes2[62], .payload = {.id = 31, .data = (double)-40.000584}}, + {.next = &nodes2[63], .payload = {.id = 32, .data = (double)-36.764561}}, + {.next = &nodes2[36], .payload = {.id = 33, .data = (double)50.372898}}, +}; + +node_t nodes3[] = { + {.next = &nodes3[35], .payload = {.id = 52, .data = (double)10.882496}}, + {.next = &nodes3[28], .payload = {.id = 48, .data = (double)1.424501}}, + {.next = &nodes3[22], .payload = {.id = 23, .data = (double)96.710115}}, + {.next = &nodes3[7], .payload = {.id = 36, .data = (double)61.302174}}, + {.next = &nodes3[61], .payload = {.id = 27, .data = (double)57.285636}}, + {.next = &nodes3[49], .payload = {.id = 17, .data = (double)68.732233}}, + {.next = &nodes3[45], .payload = {.id = 38, .data = (double)88.052624}}, + {.next = &nodes3[6], .payload = {.id = 37, .data = (double)37.371429}}, + {.next = &nodes3[23], .payload = {.id = 34, .data = (double)-12.788497}}, + {.next = &nodes3[53], .payload = {.id = 46, .data = (double)-75.074937}}, + {.next = NULL, .payload = {.id = 63, .data = (double)57.151765}}, + {.next = &nodes3[5], .payload = {.id = 16, .data = (double)35.903624}}, + {.next = &nodes3[38], .payload = {.id = 8, .data = (double)-55.415291}}, + {.next = &nodes3[39], .payload = {.id = 11, .data = (double)-44.279388}}, + {.next = &nodes3[31], .payload = {.id = 25, .data = (double)19.314251}}, + {.next = &nodes3[30], .payload = {.id = 59, .data = (double)-18.784966}}, + {.next = &nodes3[24], .payload = {.id = 44, .data = (double)24.631082}}, + {.next = &nodes3[15], .payload = {.id = 58, .data = (double)13.821051}}, + {.next = &nodes3[33], .payload = {.id = 3, .data = (double)-60.085434}}, + {.next = &nodes3[37], .payload = {.id = 0, .data = (double)-23.491655}}, + {.next = &nodes3[8], .payload = {.id = 33, .data = (double)-91.122693}}, + {.next = &nodes3[12], .payload = {.id = 7, .data = (double)74.264607}}, + {.next = &nodes3[14], .payload = {.id = 24, .data = (double)-92.348561}}, + {.next = &nodes3[3], .payload = {.id = 35, .data = (double)3.98407}}, + {.next = &nodes3[9], .payload = {.id = 45, .data = (double)32.677495}}, + {.next = &nodes3[57], .payload = {.id = 31, .data = (double)79.900947}}, + {.next = &nodes3[2], .payload = {.id = 22, .data = (double)16.117947}}, + {.next = &nodes3[21], .payload = {.id = 6, .data = (double)64.107276}}, + {.next = &nodes3[55], .payload = {.id = 49, .data = (double)33.378581}}, + {.next = &nodes3[44], .payload = {.id = 20, .data = (double)75.407682}}, + {.next = &nodes3[60], .payload = {.id = 60, .data = (double)66.745034}}, + {.next = &nodes3[4], .payload = {.id = 26, .data = (double)-30.862578}}, + {.next = &nodes3[10], .payload = {.id = 62, .data = (double)-57.963463}}, + {.next = &nodes3[50], .payload = {.id = 4, .data = (double)83.69038}}, + {.next = &nodes3[48], .payload = {.id = 56, .data = (double)49.626912}}, + {.next = &nodes3[43], .payload = {.id = 53, .data = (double)-61.631981}}, + {.next = &nodes3[18], .payload = {.id = 2, .data = (double)-5.861996}}, + {.next = &nodes3[36], .payload = {.id = 1, .data = (double)-92.255078}}, + {.next = &nodes3[52], .payload = {.id = 9, .data = (double)32.006637}}, + {.next = &nodes3[58], .payload = {.id = 12, .data = (double)-86.115849}}, + {.next = &nodes3[42], .payload = {.id = 14, .data = (double)-29.770774}}, + {.next = &nodes3[29], .payload = {.id = 19, .data = (double)-94.479893}}, + {.next = &nodes3[11], .payload = {.id = 15, .data = (double)1.881135}}, + {.next = &nodes3[54], .payload = {.id = 54, .data = (double)32.985887}}, + {.next = &nodes3[26], .payload = {.id = 21, .data = (double)-47.756961}}, + {.next = &nodes3[46], .payload = {.id = 39, .data = (double)47.407539}}, + {.next = &nodes3[63], .payload = {.id = 40, .data = (double)-60.592974}}, + {.next = &nodes3[0], .payload = {.id = 51, .data = (double)39.441683}}, + {.next = &nodes3[17], .payload = {.id = 57, .data = (double)-65.194531}}, + {.next = &nodes3[41], .payload = {.id = 18, .data = (double)-33.770026}}, + {.next = &nodes3[27], .payload = {.id = 5, .data = (double)-30.068315}}, + {.next = &nodes3[59], .payload = {.id = 42, .data = (double)89.774897}}, + {.next = &nodes3[13], .payload = {.id = 10, .data = (double)-20.306804}}, + {.next = &nodes3[1], .payload = {.id = 47, .data = (double)80.009367}}, + {.next = &nodes3[34], .payload = {.id = 55, .data = (double)-24.170945}}, + {.next = &nodes3[47], .payload = {.id = 50, .data = (double)-34.763419}}, + {.next = &nodes3[25], .payload = {.id = 30, .data = (double)-76.870843}}, + {.next = &nodes3[20], .payload = {.id = 32, .data = (double)-61.984245}}, + {.next = &nodes3[40], .payload = {.id = 13, .data = (double)54.665327}}, + {.next = &nodes3[16], .payload = {.id = 43, .data = (double)84.154171}}, + {.next = &nodes3[32], .payload = {.id = 61, .data = (double)-39.22501}}, + {.next = &nodes3[62], .payload = {.id = 28, .data = (double)-12.721223}}, + {.next = &nodes3[56], .payload = {.id = 29, .data = (double)96.84717}}, + {.next = &nodes3[51], .payload = {.id = 41, .data = (double)-13.74052}}, +}; + +node_t nodes4[] = { + {.next = &nodes4[8], .payload = {.id = 36, .data = (double)70.68959}}, + {.next = &nodes4[11], .payload = {.id = 61, .data = (double)-24.179227}}, + {.next = &nodes4[16], .payload = {.id = 44, .data = (double)-12.832805}}, + {.next = &nodes4[56], .payload = {.id = 58, .data = (double)-72.860103}}, + {.next = &nodes4[45], .payload = {.id = 51, .data = (double)-74.474441}}, + {.next = &nodes4[0], .payload = {.id = 35, .data = (double)50.695025}}, + {.next = &nodes4[34], .payload = {.id = 6, .data = (double)-50.552052}}, + {.next = &nodes4[52], .payload = {.id = 46, .data = (double)-32.774091}}, + {.next = &nodes4[21], .payload = {.id = 37, .data = (double)90.686068}}, + {.next = &nodes4[51], .payload = {.id = 33, .data = (double)-98.820783}}, + {.next = &nodes4[29], .payload = {.id = 10, .data = (double)25.349687}}, + {.next = &nodes4[61], .payload = {.id = 62, .data = (double)-57.667943}}, + {.next = &nodes4[47], .payload = {.id = 40, .data = (double)9.226462}}, + {.next = &nodes4[17], .payload = {.id = 20, .data = (double)41.283828}}, + {.next = &nodes4[9], .payload = {.id = 32, .data = (double)-23.923794}}, + {.next = &nodes4[14], .payload = {.id = 31, .data = (double)53.118915}}, + {.next = &nodes4[7], .payload = {.id = 45, .data = (double)-94.195036}}, + {.next = &nodes4[49], .payload = {.id = 21, .data = (double)-87.15423}}, + {.next = &nodes4[53], .payload = {.id = 0, .data = (double)66.113834}}, + {.next = &nodes4[27], .payload = {.id = 18, .data = (double)-53.747704}}, + {.next = &nodes4[58], .payload = {.id = 25, .data = (double)-58.633122}}, + {.next = &nodes4[39], .payload = {.id = 38, .data = (double)-16.195743}}, + {.next = &nodes4[32], .payload = {.id = 28, .data = (double)16.815883}}, + {.next = &nodes4[4], .payload = {.id = 50, .data = (double)-6.52197}}, + {.next = &nodes4[23], .payload = {.id = 49, .data = (double)-66.991054}}, + {.next = &nodes4[30], .payload = {.id = 23, .data = (double)8.522228}}, + {.next = &nodes4[22], .payload = {.id = 27, .data = (double)80.967696}}, + {.next = &nodes4[13], .payload = {.id = 19, .data = (double)38.789962}}, + {.next = &nodes4[43], .payload = {.id = 55, .data = (double)12.878397}}, + {.next = &nodes4[41], .payload = {.id = 11, .data = (double)-45.080511}}, + {.next = &nodes4[20], .payload = {.id = 24, .data = (double)-16.845153}}, + {.next = &nodes4[3], .payload = {.id = 57, .data = (double)28.54993}}, + {.next = &nodes4[54], .payload = {.id = 29, .data = (double)39.104597}}, + {.next = &nodes4[48], .payload = {.id = 13, .data = (double)-42.85437}}, + {.next = &nodes4[36], .payload = {.id = 7, .data = (double)27.532287}}, + {.next = &nodes4[28], .payload = {.id = 54, .data = (double)-21.195949}}, + {.next = &nodes4[38], .payload = {.id = 8, .data = (double)53.162737}}, + {.next = &nodes4[40], .payload = {.id = 42, .data = (double)-55.892261}}, + {.next = &nodes4[10], .payload = {.id = 9, .data = (double)4.259963}}, + {.next = &nodes4[12], .payload = {.id = 39, .data = (double)49.503134}}, + {.next = &nodes4[2], .payload = {.id = 43, .data = (double)-56.115673}}, + {.next = &nodes4[33], .payload = {.id = 12, .data = (double)-84.503329}}, + {.next = &nodes4[57], .payload = {.id = 15, .data = (double)-36.058086}}, + {.next = &nodes4[31], .payload = {.id = 56, .data = (double)-94.579591}}, + {.next = &nodes4[50], .payload = {.id = 2, .data = (double)79.441621}}, + {.next = &nodes4[59], .payload = {.id = 52, .data = (double)24.451392}}, + {.next = &nodes4[55], .payload = {.id = 4, .data = (double)-5.065113}}, + {.next = &nodes4[37], .payload = {.id = 41, .data = (double)20.650518}}, + {.next = &nodes4[42], .payload = {.id = 14, .data = (double)-45.656979}}, + {.next = &nodes4[25], .payload = {.id = 22, .data = (double)-18.480126}}, + {.next = &nodes4[46], .payload = {.id = 3, .data = (double)48.731088}}, + {.next = &nodes4[5], .payload = {.id = 34, .data = (double)-29.648239}}, + {.next = &nodes4[63], .payload = {.id = 47, .data = (double)35.828377}}, + {.next = &nodes4[44], .payload = {.id = 1, .data = (double)9.57439}}, + {.next = &nodes4[15], .payload = {.id = 30, .data = (double)71.346406}}, + {.next = &nodes4[6], .payload = {.id = 5, .data = (double)-48.16169}}, + {.next = &nodes4[60], .payload = {.id = 59, .data = (double)-7.660311}}, + {.next = &nodes4[62], .payload = {.id = 16, .data = (double)8.030445}}, + {.next = &nodes4[26], .payload = {.id = 26, .data = (double)-15.971296}}, + {.next = &nodes4[35], .payload = {.id = 53, .data = (double)-94.60671}}, + {.next = &nodes4[1], .payload = {.id = 60, .data = (double)-89.943073}}, + {.next = NULL, .payload = {.id = 63, .data = (double)-34.630839}}, + {.next = &nodes4[19], .payload = {.id = 17, .data = (double)-72.325188}}, + {.next = &nodes4[24], .payload = {.id = 48, .data = (double)-19.136666}}, +}; + +node_t nodes5[] = { + {.next = &nodes5[6], .payload = {.id = 40, .data = (double)89.612516}}, + {.next = &nodes5[22], .payload = {.id = 28, .data = (double)22.066341}}, + {.next = &nodes5[29], .payload = {.id = 26, .data = (double)-51.227312}}, + {.next = &nodes5[52], .payload = {.id = 16, .data = (double)61.639844}}, + {.next = &nodes5[0], .payload = {.id = 39, .data = (double)-97.969777}}, + {.next = &nodes5[18], .payload = {.id = 4, .data = (double)-31.753765}}, + {.next = &nodes5[20], .payload = {.id = 41, .data = (double)-82.877408}}, + {.next = &nodes5[43], .payload = {.id = 50, .data = (double)-55.68072}}, + {.next = &nodes5[2], .payload = {.id = 25, .data = (double)76.326237}}, + {.next = &nodes5[49], .payload = {.id = 58, .data = (double)-33.841741}}, + {.next = &nodes5[36], .payload = {.id = 7, .data = (double)-78.892226}}, + {.next = &nodes5[51], .payload = {.id = 45, .data = (double)38.121868}}, + {.next = &nodes5[25], .payload = {.id = 53, .data = (double)16.311117}}, + {.next = &nodes5[44], .payload = {.id = 55, .data = (double)6.184386}}, + {.next = &nodes5[31], .payload = {.id = 35, .data = (double)-31.932231}}, + {.next = &nodes5[21], .payload = {.id = 21, .data = (double)-46.320892}}, + {.next = &nodes5[24], .payload = {.id = 31, .data = (double)70.190567}}, + {.next = &nodes5[34], .payload = {.id = 1, .data = (double)-14.324397}}, + {.next = &nodes5[45], .payload = {.id = 5, .data = (double)69.915125}}, + {.next = &nodes5[57], .payload = {.id = 10, .data = (double)65.741462}}, + {.next = &nodes5[32], .payload = {.id = 42, .data = (double)44.014933}}, + {.next = &nodes5[41], .payload = {.id = 22, .data = (double)70.342632}}, + {.next = &nodes5[53], .payload = {.id = 29, .data = (double)-24.202139}}, + {.next = &nodes5[19], .payload = {.id = 9, .data = (double)27.117021}}, + {.next = &nodes5[48], .payload = {.id = 32, .data = (double)-63.632029}}, + {.next = &nodes5[13], .payload = {.id = 54, .data = (double)-5.347902}}, + {.next = &nodes5[7], .payload = {.id = 49, .data = (double)-81.38933}}, + {.next = NULL, .payload = {.id = 63, .data = (double)-61.483141}}, + {.next = &nodes5[8], .payload = {.id = 24, .data = (double)-82.66742}}, + {.next = &nodes5[1], .payload = {.id = 27, .data = (double)-7.058307}}, + {.next = &nodes5[15], .payload = {.id = 20, .data = (double)46.205243}}, + {.next = &nodes5[50], .payload = {.id = 36, .data = (double)76.063996}}, + {.next = &nodes5[58], .payload = {.id = 43, .data = (double)-2.284431}}, + {.next = &nodes5[5], .payload = {.id = 3, .data = (double)1.192158}}, + {.next = &nodes5[33], .payload = {.id = 2, .data = (double)-25.885825}}, + {.next = &nodes5[12], .payload = {.id = 52, .data = (double)-38.758794}}, + {.next = &nodes5[23], .payload = {.id = 8, .data = (double)92.157513}}, + {.next = &nodes5[54], .payload = {.id = 61, .data = (double)-49.719265}}, + {.next = &nodes5[17], .payload = {.id = 0, .data = (double)-30.559247}}, + {.next = &nodes5[30], .payload = {.id = 19, .data = (double)-12.885101}}, + {.next = &nodes5[9], .payload = {.id = 57, .data = (double)49.187087}}, + {.next = &nodes5[28], .payload = {.id = 23, .data = (double)66.146204}}, + {.next = &nodes5[63], .payload = {.id = 14, .data = (double)93.094746}}, + {.next = &nodes5[35], .payload = {.id = 51, .data = (double)38.357431}}, + {.next = &nodes5[40], .payload = {.id = 56, .data = (double)-14.899237}}, + {.next = &nodes5[10], .payload = {.id = 6, .data = (double)64.466184}}, + {.next = &nodes5[39], .payload = {.id = 18, .data = (double)-3.300499}}, + {.next = &nodes5[4], .payload = {.id = 38, .data = (double)-44.746285}}, + {.next = &nodes5[61], .payload = {.id = 33, .data = (double)-57.57603}}, + {.next = &nodes5[60], .payload = {.id = 59, .data = (double)40.570988}}, + {.next = &nodes5[47], .payload = {.id = 37, .data = (double)40.23675}}, + {.next = &nodes5[62], .payload = {.id = 46, .data = (double)29.18058}}, + {.next = &nodes5[46], .payload = {.id = 17, .data = (double)7.634581}}, + {.next = &nodes5[16], .payload = {.id = 30, .data = (double)-94.26}}, + {.next = &nodes5[27], .payload = {.id = 62, .data = (double)-75.868823}}, + {.next = &nodes5[42], .payload = {.id = 13, .data = (double)46.759061}}, + {.next = &nodes5[55], .payload = {.id = 12, .data = (double)-12.902571}}, + {.next = &nodes5[56], .payload = {.id = 11, .data = (double)41.461729}}, + {.next = &nodes5[11], .payload = {.id = 44, .data = (double)51.632931}}, + {.next = &nodes5[26], .payload = {.id = 48, .data = (double)58.586574}}, + {.next = &nodes5[37], .payload = {.id = 60, .data = (double)-45.816715}}, + {.next = &nodes5[14], .payload = {.id = 34, .data = (double)59.566471}}, + {.next = &nodes5[59], .payload = {.id = 47, .data = (double)-1.835733}}, + {.next = &nodes5[3], .payload = {.id = 15, .data = (double)-45.983521}}, +}; + +node_t nodes6[] = { + {.next = &nodes6[44], .payload = {.id = 19, .data = (double)10.398449}}, + {.next = &nodes6[16], .payload = {.id = 53, .data = (double)77.884578}}, + {.next = &nodes6[41], .payload = {.id = 9, .data = (double)-14.234033}}, + {.next = &nodes6[62], .payload = {.id = 47, .data = (double)-39.181762}}, + {.next = &nodes6[58], .payload = {.id = 32, .data = (double)17.957918}}, + {.next = &nodes6[27], .payload = {.id = 23, .data = (double)-6.017504}}, + {.next = &nodes6[12], .payload = {.id = 38, .data = (double)-46.873506}}, + {.next = &nodes6[35], .payload = {.id = 34, .data = (double)-60.436157}}, + {.next = &nodes6[61], .payload = {.id = 61, .data = (double)-95.850909}}, + {.next = &nodes6[63], .payload = {.id = 4, .data = (double)55.138708}}, + {.next = &nodes6[29], .payload = {.id = 56, .data = (double)-94.827022}}, + {.next = &nodes6[1], .payload = {.id = 52, .data = (double)19.607332}}, + {.next = &nodes6[51], .payload = {.id = 39, .data = (double)-71.552743}}, + {.next = &nodes6[30], .payload = {.id = 7, .data = (double)-40.529373}}, + {.next = &nodes6[48], .payload = {.id = 58, .data = (double)34.859673}}, + {.next = &nodes6[25], .payload = {.id = 15, .data = (double)25.103006}}, + {.next = &nodes6[22], .payload = {.id = 54, .data = (double)46.906785}}, + {.next = &nodes6[53], .payload = {.id = 36, .data = (double)-55.03811}}, + {.next = &nodes6[31], .payload = {.id = 43, .data = (double)64.84806}}, + {.next = &nodes6[34], .payload = {.id = 1, .data = (double)-16.765196}}, + {.next = &nodes6[21], .payload = {.id = 13, .data = (double)-80.153285}}, + {.next = &nodes6[15], .payload = {.id = 14, .data = (double)52.547421}}, + {.next = &nodes6[10], .payload = {.id = 55, .data = (double)20.742728}}, + {.next = &nodes6[11], .payload = {.id = 51, .data = (double)-12.448227}}, + {.next = &nodes6[19], .payload = {.id = 0, .data = (double)11.614607}}, + {.next = &nodes6[55], .payload = {.id = 16, .data = (double)-47.070775}}, + {.next = &nodes6[20], .payload = {.id = 12, .data = (double)92.021755}}, + {.next = &nodes6[36], .payload = {.id = 24, .data = (double)-93.472029}}, + {.next = &nodes6[9], .payload = {.id = 3, .data = (double)23.68367}}, + {.next = &nodes6[14], .payload = {.id = 57, .data = (double)-54.215117}}, + {.next = &nodes6[2], .payload = {.id = 8, .data = (double)17.705028}}, + {.next = &nodes6[40], .payload = {.id = 44, .data = (double)84.238506}}, + {.next = &nodes6[38], .payload = {.id = 49, .data = (double)-45.550761}}, + {.next = &nodes6[59], .payload = {.id = 29, .data = (double)-53.315239}}, + {.next = &nodes6[28], .payload = {.id = 2, .data = (double)19.225369}}, + {.next = &nodes6[17], .payload = {.id = 35, .data = (double)-77.04474}}, + {.next = &nodes6[46], .payload = {.id = 25, .data = (double)-42.379022}}, + {.next = &nodes6[0], .payload = {.id = 18, .data = (double)-52.026964}}, + {.next = &nodes6[23], .payload = {.id = 50, .data = (double)7.996313}}, + {.next = &nodes6[3], .payload = {.id = 46, .data = (double)-6.260406}}, + {.next = &nodes6[39], .payload = {.id = 45, .data = (double)-12.16931}}, + {.next = &nodes6[60], .payload = {.id = 10, .data = (double)13.725894}}, + {.next = &nodes6[13], .payload = {.id = 6, .data = (double)81.700876}}, + {.next = &nodes6[18], .payload = {.id = 42, .data = (double)19.008807}}, + {.next = &nodes6[45], .payload = {.id = 20, .data = (double)-68.693477}}, + {.next = &nodes6[47], .payload = {.id = 21, .data = (double)-18.296485}}, + {.next = &nodes6[52], .payload = {.id = 26, .data = (double)-43.456325}}, + {.next = &nodes6[5], .payload = {.id = 22, .data = (double)37.874227}}, + {.next = &nodes6[54], .payload = {.id = 59, .data = (double)72.103375}}, + {.next = NULL, .payload = {.id = 63, .data = (double)64.284249}}, + {.next = &nodes6[4], .payload = {.id = 31, .data = (double)58.249549}}, + {.next = &nodes6[57], .payload = {.id = 40, .data = (double)-88.072392}}, + {.next = &nodes6[56], .payload = {.id = 27, .data = (double)71.921346}}, + {.next = &nodes6[6], .payload = {.id = 37, .data = (double)-70.20212}}, + {.next = &nodes6[8], .payload = {.id = 60, .data = (double)17.424586}}, + {.next = &nodes6[37], .payload = {.id = 17, .data = (double)-83.762507}}, + {.next = &nodes6[33], .payload = {.id = 28, .data = (double)-85.764048}}, + {.next = &nodes6[43], .payload = {.id = 41, .data = (double)58.525713}}, + {.next = &nodes6[7], .payload = {.id = 33, .data = (double)60.781136}}, + {.next = &nodes6[50], .payload = {.id = 30, .data = (double)-47.089075}}, + {.next = &nodes6[26], .payload = {.id = 11, .data = (double)-87.953939}}, + {.next = &nodes6[49], .payload = {.id = 62, .data = (double)52.952076}}, + {.next = &nodes6[32], .payload = {.id = 48, .data = (double)-19.498296}}, + {.next = &nodes6[42], .payload = {.id = 5, .data = (double)-23.924395}}, +}; + +node_t nodes7[] = { + {.next = &nodes7[12], .payload = {.id = 48, .data = (double)82.686034}}, + {.next = &nodes7[61], .payload = {.id = 29, .data = (double)45.210197}}, + {.next = &nodes7[22], .payload = {.id = 22, .data = (double)-86.037984}}, + {.next = &nodes7[0], .payload = {.id = 47, .data = (double)-5.40475}}, + {.next = &nodes7[24], .payload = {.id = 8, .data = (double)29.541938}}, + {.next = &nodes7[16], .payload = {.id = 36, .data = (double)-33.512009}}, + {.next = &nodes7[39], .payload = {.id = 17, .data = (double)-71.071606}}, + {.next = &nodes7[57], .payload = {.id = 38, .data = (double)-24.557989}}, + {.next = &nodes7[3], .payload = {.id = 46, .data = (double)-36.364735}}, + {.next = &nodes7[62], .payload = {.id = 3, .data = (double)-18.401863}}, + {.next = &nodes7[21], .payload = {.id = 12, .data = (double)41.082326}}, + {.next = &nodes7[42], .payload = {.id = 56, .data = (double)93.070718}}, + {.next = &nodes7[60], .payload = {.id = 49, .data = (double)-23.753771}}, + {.next = &nodes7[36], .payload = {.id = 26, .data = (double)57.543481}}, + {.next = &nodes7[17], .payload = {.id = 51, .data = (double)58.478732}}, + {.next = &nodes7[51], .payload = {.id = 42, .data = (double)-52.238891}}, + {.next = &nodes7[7], .payload = {.id = 37, .data = (double)52.574536}}, + {.next = &nodes7[37], .payload = {.id = 52, .data = (double)30.4038}}, + {.next = &nodes7[44], .payload = {.id = 59, .data = (double)69.007885}}, + {.next = &nodes7[4], .payload = {.id = 7, .data = (double)89.412148}}, + {.next = &nodes7[26], .payload = {.id = 54, .data = (double)92.964888}}, + {.next = &nodes7[38], .payload = {.id = 13, .data = (double)-16.901931}}, + {.next = &nodes7[49], .payload = {.id = 23, .data = (double)54.535027}}, + {.next = &nodes7[10], .payload = {.id = 11, .data = (double)-41.627688}}, + {.next = &nodes7[32], .payload = {.id = 9, .data = (double)-69.205775}}, + {.next = &nodes7[41], .payload = {.id = 61, .data = (double)82.088336}}, + {.next = &nodes7[11], .payload = {.id = 55, .data = (double)-74.750746}}, + {.next = &nodes7[30], .payload = {.id = 32, .data = (double)31.988151}}, + {.next = &nodes7[43], .payload = {.id = 1, .data = (double)-37.849972}}, + {.next = &nodes7[28], .payload = {.id = 0, .data = (double)41.956565}}, + {.next = &nodes7[50], .payload = {.id = 33, .data = (double)73.052119}}, + {.next = NULL, .payload = {.id = 63, .data = (double)-71.168917}}, + {.next = &nodes7[23], .payload = {.id = 10, .data = (double)86.530612}}, + {.next = &nodes7[1], .payload = {.id = 28, .data = (double)-99.486948}}, + {.next = &nodes7[5], .payload = {.id = 35, .data = (double)-3.131723}}, + {.next = &nodes7[19], .payload = {.id = 6, .data = (double)-77.307776}}, + {.next = &nodes7[33], .payload = {.id = 27, .data = (double)-46.565467}}, + {.next = &nodes7[20], .payload = {.id = 53, .data = (double)-69.578936}}, + {.next = &nodes7[40], .payload = {.id = 14, .data = (double)-3.500085}}, + {.next = &nodes7[63], .payload = {.id = 18, .data = (double)-61.877926}}, + {.next = &nodes7[59], .payload = {.id = 15, .data = (double)-5.556044}}, + {.next = &nodes7[31], .payload = {.id = 62, .data = (double)-96.93048}}, + {.next = &nodes7[52], .payload = {.id = 57, .data = (double)-33.601059}}, + {.next = &nodes7[9], .payload = {.id = 2, .data = (double)-97.265107}}, + {.next = &nodes7[25], .payload = {.id = 60, .data = (double)-80.05766}}, + {.next = &nodes7[27], .payload = {.id = 31, .data = (double)15.984677}}, + {.next = &nodes7[8], .payload = {.id = 45, .data = (double)-17.844981}}, + {.next = &nodes7[54], .payload = {.id = 40, .data = (double)73.920337}}, + {.next = &nodes7[58], .payload = {.id = 20, .data = (double)49.258509}}, + {.next = &nodes7[55], .payload = {.id = 24, .data = (double)70.882476}}, + {.next = &nodes7[34], .payload = {.id = 34, .data = (double)-10.690521}}, + {.next = &nodes7[56], .payload = {.id = 43, .data = (double)-23.40583}}, + {.next = &nodes7[18], .payload = {.id = 58, .data = (double)-79.92708}}, + {.next = &nodes7[35], .payload = {.id = 5, .data = (double)68.281136}}, + {.next = &nodes7[15], .payload = {.id = 41, .data = (double)96.154926}}, + {.next = &nodes7[13], .payload = {.id = 25, .data = (double)-32.024951}}, + {.next = &nodes7[46], .payload = {.id = 44, .data = (double)71.202595}}, + {.next = &nodes7[47], .payload = {.id = 39, .data = (double)86.570451}}, + {.next = &nodes7[2], .payload = {.id = 21, .data = (double)-72.698331}}, + {.next = &nodes7[6], .payload = {.id = 16, .data = (double)-8.642705}}, + {.next = &nodes7[14], .payload = {.id = 50, .data = (double)97.6828}}, + {.next = &nodes7[45], .payload = {.id = 30, .data = (double)67.495185}}, + {.next = &nodes7[53], .payload = {.id = 4, .data = (double)-55.059868}}, + {.next = &nodes7[48], .payload = {.id = 19, .data = (double)19.87552}}, +}; + +node_t* head[8] = { + &nodes0[12], + &nodes1[20], + &nodes2[50], + &nodes3[19], + &nodes4[18], + &nodes5[38], + &nodes6[24], + &nodes7[29], +}; + diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/data/layer.h b/software/tests/multi_producer_single_consumer_double_linked_list/data/layer.h new file mode 100644 index 0000000..c954d1d --- /dev/null +++ b/software/tests/multi_producer_single_consumer_double_linked_list/data/layer.h @@ -0,0 +1,160 @@ +// Copyright 2020 ETH Zurich and University of Bologna. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +typedef enum { FP64 = 8, FP32 = 4, FP16 = 2, FP8 = 1 } precision_t; + +/** + * @struct gemm_layer_struct + * @brief This structure contains all parameters necessary for GEMM. + * @var gemm_layer_struct::M + * Dimension of matrix product MxK * KxN + * @var gemm_layer_struct::M_p + * M divided by number of compute cores + * @var gemm_layer_struct::N + * Dimension of matrix product MxK * KxN + * @var gemm_layer_struct::K + * Dimension of matrix product MxK * KxN + * @var gemm_layer_struct::TA + * Transpose matrix A + * @var gemm_layer_struct::TB + * Transpose matrix B + * @var gemm_layer_struct::TILE_M + * Tile factor across M dimension + * @var gemm_layer_struct::TILE_N + * Tile factor across N dimension + * @var gemm_layer_struct::TILE_K + * Tile factor across K dimension + * @var gemm_layer_struct::A + * Pointer to matrix A + * @var gemm_layer_struct::B + * Pointer to matrix B + * @var gemm_layer_struct::C + * Pointer to matrix C + * @var gemm_layer_struct::ALPHA + * constant factor: A * B + ALPHA * C + * @var gemm_layer_struct::dtype + * Precision of GEMM + * @var gemm_layer_struct::expand + * Use expanding DOTP instructions + */ +typedef struct gemm_layer_struct { + uint32_t M; + uint32_t M_p; + uint32_t N; + uint32_t K; + + uint32_t TA; + uint32_t TB; + + uint32_t TILE_M; + uint32_t TILE_N; + uint32_t TILE_K; + + double *A; + double *B; + double *C; + + uint32_t ALPHA; + + precision_t dtype; + uint32_t expand; +} gemm_layer; + +/** + * @struct conv_layer_struct + * @brief This structure contains all parameters necessary for Convolutional + * layers + * @var conv_layer_struct::CO + * Number of output channels + * @var conv_layer_struct::CI + * Number of input channels + * @var conv_layer_struct::IH + * Height of input feature map + * @var conv_layer_struct::IW + * Width of input feature map + * @var conv_layer_struct::OH + * Height of output feature map + * @var conv_layer_struct::OW + * Width of output feature map + * @var conv_layer_struct::FH + * Height of filter + * @var conv_layer_struct::FW + * Width of filter + * @var conv_layer_struct::pad + * Padding on all sides + * @var conv_layer_struct::ifmap + * Pointer to input feature map + * @var conv_layer_struct::weights + * Pointer to weights + * @var conv_layer_struct::ofmap + * Pointer to output feature map + * @var conv_layer_struct::TILE_CI + * Tiling factor of input channel + * @var conv_layer_struct::cluster2cluster + * Flag for enabling cluster 2 cluster communication + * @var conv_layer_struct::im2col + * Flag for enabling im2col + GEMM + * @var conv_layer_struct::gamma + * Pointer to gamma for BatchNorm + * @var conv_layer_struct::beta + * Pointer to beta for BatchNorm + * @var gemm_layer_struct::dtype + * Precision of Convolution layer + */ +typedef struct conv_layer_struct { + // CONV2D + uint32_t CO; + uint32_t CI; + uint32_t IH; + uint32_t IW; + uint32_t OH; + uint32_t OW; + uint32_t FH; + uint32_t FW; + uint32_t pad; + + double *ifmap; + double *weights; + double *ofmap; + + uint32_t TILE_CI; + uint32_t cluster2cluster; + uint32_t im2col; + + // BATCHNORM + double *gamma; + double *beta; + + precision_t dtype; +} conv_layer; + +/** + * @struct dotp_layer_struct + * @brief This structure contains all parameters necessary for DOTP + * layers + * @var dotp_layer_struct::M + * Length of the vectors + * @var gemm_layer_struct::dtype + * Precision of Convolution layer + */ +typedef struct dotp_layer_struct { + // DOTP + uint32_t M; + + precision_t dtype; +} dotp_layer; + +typedef struct payload_t { + int id; + double data; +} payload_t; + +typedef struct node_t { + struct node_t *next; + payload_t payload; +} node_t; diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/debug.c b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/debug.c new file mode 100644 index 0000000..30aeb57 --- /dev/null +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/debug.c @@ -0,0 +1,33 @@ +#include +#include +#include "printf.h" +#include "debug.h" + +/* Global spinlock aligned to 8 bytes to ensure correctness */ +static volatile int debug_lock __attribute__((aligned(8))) = 0; + +/* Spinlock acquire/release helpers */ +static inline void debug_lock_acquire(volatile int *lock) { + while (__sync_lock_test_and_set(lock, 1)) { } +} + +static inline void debug_lock_release(volatile int *lock) { + asm volatile ( + "amoswap.w zero, zero, %0" + : "+A" (*lock) + ); + } + + +void debug_print_lock_init(void) { + debug_lock = 0; // Optional: usually zero by default +} + +/* Thread-safe debug print using global spinlock */ +void debug_printf_locked(const char *fmt, ...) { + debug_lock_acquire(&debug_lock); + + printf(fmt); + + debug_lock_release(&debug_lock); +} diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/debug.h b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/debug.h new file mode 100644 index 0000000..0f48eb7 --- /dev/null +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/debug.h @@ -0,0 +1,21 @@ +#ifndef DEBUG_H +#define DEBUG_H + +#include +#include "printf.h" + +/* Enable or disable debug printing */ +#define DEBUG_PRINT_ENABLED 1 + +/* Raw printf protected by global spinlock */ +void debug_print_lock_init(void); +void debug_printf_locked(const char *fmt, ...); + +/* Simple macro wrapper */ +#if DEBUG_PRINT_ENABLED + #define debug_printf(...) debug_printf_locked(__VA_ARGS__) +#else + #define debug_printf(...) ((void)0) +#endif + +#endif // DEBUG_H diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.c b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.c new file mode 100644 index 0000000..62f551d --- /dev/null +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.c @@ -0,0 +1,80 @@ +#ifndef LLIST_C +#define LLIST_C + +#include "llist.h" +#include +#include +#include +#include +#include +#include "printf.h" +#include "debug.h" + +void list_init(LinkedList *list) { + list->head = NULL; + list->tail = NULL; + /* Set the list lock to 0 (unlocked) */ + list->lock = 0; +} + +void list_push_back(LinkedList *list, Node *node) { + /* Acquire the list lock to ensure exclusive access while modifying the list */ + spin_lock(&list->lock); + debug_printf("[core_id %u][list_push_back] spin_lock\n", snrt_cluster_core_idx()); + node->next = NULL; + node->prev = list->tail; + if (list->tail != NULL) { + list->tail->next = node; + } else { + /* If the list is empty, set the head to the new node */ + list->head = node; + } + list->tail = node; + debug_printf("[core_id %u][list_push_back] spin_unlock\n", snrt_cluster_core_idx()); + spin_unlock(&list->lock); +} + +Node *list_pop_front(LinkedList *list) { + Node *node = NULL; + spin_lock(&list->lock); + debug_printf("[core_id %u][list_pop_front] spin_lock\n", snrt_cluster_core_idx()); + if (list->head != NULL) { + node = list->head; + list->head = node->next; + if (list->head != NULL) { + list->head->prev = NULL; + } else { + /* List becomes empty, so tail is also NULL */ + list->tail = NULL; + } + node->next = NULL; + node->prev = NULL; + } + debug_printf("[core_id %u][list_pop_front] spin_unlock\n", snrt_cluster_core_idx()); + spin_unlock(&list->lock); + return node; +} + +void list_remove(LinkedList *list, Node *node) { + spin_lock(&list->lock); + debug_printf("[core_id %u][list_remove] spin_lock\n", snrt_cluster_core_idx()); + if (node->prev != NULL) { + node->prev->next = node->next; + } else { + /* If removing the head */ + list->head = node->next; + } + if (node->next != NULL) { + node->next->prev = node->prev; + } else { + /* If removing the tail */ + list->tail = node->prev; + } + node->prev = NULL; + node->next = NULL; + debug_printf("[core_id %u][list_remove] spin_unlock\n", snrt_cluster_core_idx()); + spin_unlock(&list->lock); +} + + +#endif diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.h b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.h new file mode 100644 index 0000000..1353087 --- /dev/null +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.h @@ -0,0 +1,68 @@ +#ifndef LLIST_H +#define LLIST_H + +#include + +/* --- Simple spinlock implementation --- */ +/* We use a volatile int as a spinlock. Zero means unlocked. */ +typedef volatile int spinlock_t __attribute__((aligned(8))); + +static inline void spin_lock(spinlock_t *lock) { + while (__sync_lock_test_and_set(lock, 1)) { } +} + +static inline void spin_unlock(volatile int *lock) { + asm volatile ( + "amoswap.w zero, zero, %0" + : "+A" (*lock) + ); +} + + +/* Node structure representing a packet or data element. + The node structure is stored at the beginning of a fixed‐size page; + the remainder of the page may be used as payload. +*/ +typedef struct Node { + struct Node *prev; + struct Node *next; + void *data; /* Pointer to the payload data */ + size_t data_size; /* Size of the payload in bytes */ + spinlock_t lock; /* Per‑node lock (0: unlocked, 1: locked) */ +} Node; + +/* Doubly‑linked list structure for storing Node pointers. + All operations require a pointer to an instance of LinkedList. +*/ +typedef struct { + Node *head; + Node *tail; + spinlock_t lock; /* Global lock protecting the list structure */ +} LinkedList; + +/* + list_init() initializes the given LinkedList instance. + It sets the head and tail pointers to NULL and the lock to 0. +*/ +void list_init(LinkedList *list); + +/* + list_push_back() appends a given Node to the end of the list. + It is safe for concurrent use by multiple producers. +*/ +void list_push_back(LinkedList *list, Node *node); + +/* + list_pop_front() removes and returns the node from the front of the list. + This function should be used by a single consumer. + If the list is empty, it returns NULL. +*/ +Node *list_pop_front(LinkedList *list); + +/* + list_remove() removes a specific Node from anywhere in the list. + This function adjusts the pointers of neighboring nodes appropriately. +*/ +void list_remove(LinkedList *list, Node *node); + +#endif /* LLIST_H */ diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.c b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.c new file mode 100644 index 0000000..7622ddc --- /dev/null +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.c @@ -0,0 +1,90 @@ +#ifndef MM_C +#define MM_C + +#include "mm.h" +#include +#include +#include +#include +#include "printf.h" +#include "debug.h" + +/* Simple spinlock functions using GCC built‑ins */ +static inline void mm_lock_acquire(volatile int *lock) { + while (__sync_lock_test_and_set(lock, 1)) { } +} + +static inline void mm_lock_release(volatile int *lock) { + asm volatile ( + "amoswap.w zero, zero, %0" + : "+A" (*lock) + ); +} + + +/* mm_init: Only core 0 initializes the mm_context_t; others do nothing. */ +void mm_init(mm_context_t *ctx) { + ctx->buffer = (uint8_t *)snrt_l1alloc(BUFFER_SIZE); + if (!ctx->buffer) { + fprintf(stderr, "mm_init: Failed to allocate %d bytes from L1\n", BUFFER_SIZE); + /* In a baremetal system you might want to halt or trigger an error */ + } + ctx->alloc_offset = 0; + ctx->free_list = NULL; + ctx->lock = 0; +} + +/* mm_alloc: Returns a fresh page from the pool if available; otherwise, recycles from free_list. */ +void *mm_alloc(mm_context_t *ctx) { + void *page = NULL; + mm_lock_acquire(&ctx->lock); + debug_printf("[core_id %u][mm_alloc] mm_lock_acquire\n", snrt_cluster_core_idx()); + if (ctx->alloc_offset + PAGE_SIZE <= BUFFER_SIZE) { + page = ctx->buffer + ctx->alloc_offset; + ctx->alloc_offset += PAGE_SIZE; + } else { + if (ctx->free_list != NULL) { + page = (void *)ctx->free_list; + ctx->free_list = ctx->free_list->next; + } else { + page = NULL; /* Out of memory */ + } + } + + debug_printf("[core_id %u][mm_alloc] mm_lock_release\n", snrt_cluster_core_idx()); + mm_lock_release(&ctx->lock); + return page; +} + +/* mm_free: Recycles the page by pushing it onto the free list. */ +void mm_free(mm_context_t *ctx, void *p) { + if (!p) + return; + + mm_lock_acquire(&ctx->lock); + debug_printf("[core_id %u][mm_free] mm_lock_release\n", snrt_cluster_core_idx()); + MM_FreePage *fp = (MM_FreePage *)p; + fp->next = ctx->free_list; + ctx->free_list = fp; + debug_printf("[core_id %u][mm_free] mm_lock_release\n", snrt_cluster_core_idx()); + mm_lock_release(&ctx->lock); +} + +/* mm_memset: Custom implementation that fills dest with the specified value. */ +void *mm_memset(void *dest, int value, size_t count) { + unsigned char *ptr = (unsigned char *)dest; + while(count--) { + *ptr++ = (unsigned char)value; + } + return dest; +} + +/* mm_cleanup: Reset the memory management state. */ +void mm_cleanup(mm_context_t *ctx) { + ctx->alloc_offset = 0; + ctx->free_list = NULL; +} + + +#endif + diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.h b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.h new file mode 100644 index 0000000..f6f7b2c --- /dev/null +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.h @@ -0,0 +1,49 @@ +#ifndef MM_H +#define MM_H + +#include +#include + +#define PAGE_SIZE (1024) /* Fixed size of each memory page in bytes */ +#define BUFFER_SIZE (1024 * 1024) /* 1MB memory pool size */ + +/* Type for free list entries */ +typedef struct MM_FreePage { + struct MM_FreePage *next; +} MM_FreePage; + +/* Memory management context. All state is stored here. */ +typedef struct { + uint8_t *buffer; /* Pointer to the memory pool allocated from L1 */ + size_t alloc_offset; /* Current allocation offset */ + MM_FreePage *free_list; /* Free list of recycled pages */ + volatile int lock; /* Spinlock for mutual exclusion */ +} mm_context_t __attribute__((aligned(8))); + +/* + mm_init() initializes the memory management context. +*/ +void mm_init(mm_context_t *ctx); + +/* Allocate one page (PAGE_SIZE bytes) from the memory pool. + Returns a pointer to the allocated page or NULL if out-of-memory. +*/ +void *mm_alloc(mm_context_t *ctx); + +/* Free a previously allocated page. + The page is added to the free list for later reuse. +*/ +void mm_free(mm_context_t *ctx, void *p); + +/* + A simple custom memset implementation that fills count bytes in dest + with the given value. +*/ +void *mm_memset(void *dest, int value, size_t count); + +/* Reset the mm_context_t state. + In a baremetal system, this might simply reset the allocation pointer and free list. +*/ +void mm_cleanup(mm_context_t *ctx); + +#endif diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.c b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.c new file mode 100644 index 0000000..6ff00b9 --- /dev/null +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.c @@ -0,0 +1,84 @@ +#ifndef RLC_C +#define RLC_C + +#include "rlc.h" +#include "mm.h" +#include "llist.c" +#include +#include +#include +#include +#include +#include "printf.h" +#include "debug.h" + +/* + Each allocation is a fixed-size page (PAGE_SIZE bytes). + The Node structure is placed at the beginning of the page and the remaining + space is used for payload. Thus, available payload size is: +*/ +#define PACKET_SIZE (PAGE_SIZE - sizeof(Node)) + +/* A simple busy-loop delay function. Adjust iterations as needed. */ +static void delay(volatile int iterations) { + for (; iterations > 0; iterations--); +} + +/* Consumer behavior (runs on core 0) */ +static void consumer(rlc_context_t *ctx, const unsigned int core_id) { + while (1) { + Node *node = list_pop_front(&ctx->list); + if (node != 0) { + printf("Consumer (core %u): processing node %p with data size %zu\n", + core_id, (void *)node, node->data_size); + delay(100); /* Simulate processing delay */ + mm_free(ctx->mm_ctx, node); + } else { + delay(10); /* Wait briefly if list is empty */ + } + } +} + +/* Producer behavior (runs on cores other than 0) */ +static void producer(rlc_context_t *ctx, const unsigned int core_id) { + ctx->mm_ctx->lock = 0; + while (1) { + Node *node = (Node *)mm_alloc(ctx->mm_ctx); + if (!node) { + printf("Producer (core %u): Out of memory\n", core_id); + delay(200); /* Delay before retrying */ + continue; + } + /* Initialize the node header */ + node->lock = 0; + node->prev = 0; + node->next = 0; + /* Set the payload pointer immediately after the Node structure */ + node->data = (void *)((uint8_t *)node + sizeof(Node)); + node->data_size = PACKET_SIZE; + /* Zero-initialize the payload using our custom mm_memset */ + mm_memset(node->data, 0, PACKET_SIZE); + /* Append the node to the shared linked list */ + list_push_back(&ctx->list, node); + printf("Producer (core %u): added node %p\n", core_id, (void *)node); + delay(200); /* Delay between node productions */ + } +} + +/* cluster_entry() dispatches behavior based on core_id */ +void cluster_entry(rlc_context_t *ctx, const unsigned int core_id) { + if (core_id == 0) { + consumer(ctx, core_id); + } else { + producer(ctx, core_id); + } +} + + +void rlc_start(rlc_context_t *ctx, const unsigned int core_id) { + /* Enter per-core processing based on core_id */ + cluster_entry(ctx, core_id); +} + + +#endif diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.h b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.h new file mode 100644 index 0000000..45113a3 --- /dev/null +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.h @@ -0,0 +1,29 @@ +#ifndef RLC_H +#define RLC_H + +#include "mm.h" +#include "llist.h" + +/* rlc_context_t holds the RLC kernel state: + - 'list': the linked list used to store packet nodes. + - 'mm_ctx': a pointer to the memory management context. +*/ +typedef struct { + LinkedList list; + mm_context_t *mm_ctx; +} rlc_context_t; + +/* + rlc_start() initializes shared RLC resources and starts the RLC kernel + for the current core. The core ID, obtained in main(), is passed here. +*/ +void rlc_start(rlc_context_t *ctx, const unsigned int core_id); + +/* + cluster_entry() is the per-core entry function for the RLC kernel. + Depending on the core ID (passed as a parameter), it calls consumer() if core_id is 0, + or producer() otherwise. +*/ +void cluster_entry(rlc_context_t *ctx, const unsigned int core_id); + +#endif diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/main.c b/software/tests/multi_producer_single_consumer_double_linked_list/main.c new file mode 100644 index 0000000..b7928a4 --- /dev/null +++ b/software/tests/multi_producer_single_consumer_double_linked_list/main.c @@ -0,0 +1,35 @@ +#include "kernel/debug.c" +#include "kernel/mm.c" +#include "kernel/rlc.c" +#include +#include +#include +#include +#include "printf.h" + +int main(void) { + /* Retrieve the core index only once in main */ + const unsigned int core_id = snrt_cluster_core_idx(); + + mm_context_t mm_ctx; + rlc_context_t rlc_ctx; + + if (core_id == 0) { + /* Initalize the thread saft printf */ + debug_print_lock_init(); + /* Initialize memory management context */ + mm_init(&mm_ctx); + /* Set up the RLC context to use the memory management context */ + rlc_ctx.mm_ctx = &mm_ctx; + + /* Initialize the linked list */ + list_init(&rlc_ctx.list); + } + + // Wait for all cores to finish + snrt_cluster_hw_barrier(); + + rlc_start(&rlc_ctx, core_id); + + return 0; +} From e2cfe5b6140c4cf299ed376bc8439891d612ffa8 Mon Sep 17 00:00:00 2001 From: Zexin Fu Date: Fri, 25 Apr 2025 04:24:57 +0200 Subject: [PATCH 07/17] [SW] Fix the spin lock issue, move the critical resource to global variable, now can kernel can run without getting stuck --- .../kernel/llist.c | 18 ++++--- .../kernel/llist.h | 2 + .../kernel/mm.c | 50 ++++++++++--------- .../kernel/mm.h | 15 ++++-- .../kernel/rlc.c | 23 ++++----- .../kernel/rlc.h | 6 ++- .../main.c | 7 +-- 7 files changed, 70 insertions(+), 51 deletions(-) diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.c b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.c index 62f551d..c42a3ef 100644 --- a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.c +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.c @@ -19,7 +19,8 @@ void list_init(LinkedList *list) { void list_push_back(LinkedList *list, Node *node) { /* Acquire the list lock to ensure exclusive access while modifying the list */ - spin_lock(&list->lock); + // spin_lock(&list->lock); + spin_lock(&llist_lock); debug_printf("[core_id %u][list_push_back] spin_lock\n", snrt_cluster_core_idx()); node->next = NULL; node->prev = list->tail; @@ -31,12 +32,14 @@ void list_push_back(LinkedList *list, Node *node) { } list->tail = node; debug_printf("[core_id %u][list_push_back] spin_unlock\n", snrt_cluster_core_idx()); - spin_unlock(&list->lock); + // spin_unlock(&list->lock); + spin_unlock(&llist_lock); } Node *list_pop_front(LinkedList *list) { Node *node = NULL; - spin_lock(&list->lock); + // spin_lock(&list->lock); + spin_lock(&llist_lock); debug_printf("[core_id %u][list_pop_front] spin_lock\n", snrt_cluster_core_idx()); if (list->head != NULL) { node = list->head; @@ -51,12 +54,14 @@ Node *list_pop_front(LinkedList *list) { node->prev = NULL; } debug_printf("[core_id %u][list_pop_front] spin_unlock\n", snrt_cluster_core_idx()); - spin_unlock(&list->lock); + // spin_unlock(&list->lock); + spin_unlock(&llist_lock); return node; } void list_remove(LinkedList *list, Node *node) { - spin_lock(&list->lock); + // spin_lock(&list->lock); + spin_lock(&llist_lock); debug_printf("[core_id %u][list_remove] spin_lock\n", snrt_cluster_core_idx()); if (node->prev != NULL) { node->prev->next = node->next; @@ -73,7 +78,8 @@ void list_remove(LinkedList *list, Node *node) { node->prev = NULL; node->next = NULL; debug_printf("[core_id %u][list_remove] spin_unlock\n", snrt_cluster_core_idx()); - spin_unlock(&list->lock); + // spin_unlock(&list->lock); + spin_unlock(&llist_lock); } diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.h b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.h index 1353087..caa173c 100644 --- a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.h +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.h @@ -7,6 +7,8 @@ /* We use a volatile int as a spinlock. Zero means unlocked. */ typedef volatile int spinlock_t __attribute__((aligned(8))); +spinlock_t llist_lock; + static inline void spin_lock(spinlock_t *lock) { while (__sync_lock_test_and_set(lock, 1)) { } } diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.c b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.c index 7622ddc..83996fb 100644 --- a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.c +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.c @@ -23,51 +23,55 @@ static inline void mm_lock_release(volatile int *lock) { /* mm_init: Only core 0 initializes the mm_context_t; others do nothing. */ -void mm_init(mm_context_t *ctx) { - ctx->buffer = (uint8_t *)snrt_l1alloc(BUFFER_SIZE); - if (!ctx->buffer) { +void mm_init() { + mm_ctx.buffer = (uint8_t *)snrt_l1alloc(BUFFER_SIZE); + if (!mm_ctx.buffer) { fprintf(stderr, "mm_init: Failed to allocate %d bytes from L1\n", BUFFER_SIZE); /* In a baremetal system you might want to halt or trigger an error */ } - ctx->alloc_offset = 0; - ctx->free_list = NULL; - ctx->lock = 0; + mm_ctx.alloc_offset = 0; + mm_ctx.free_list = NULL; + mm_ctx.lock = 0; } /* mm_alloc: Returns a fresh page from the pool if available; otherwise, recycles from free_list. */ -void *mm_alloc(mm_context_t *ctx) { +void *mm_alloc() { void *page = NULL; - mm_lock_acquire(&ctx->lock); + // mm_lock_acquire(&ctx->lock); + mm_lock_acquire(&mm_lock); debug_printf("[core_id %u][mm_alloc] mm_lock_acquire\n", snrt_cluster_core_idx()); - if (ctx->alloc_offset + PAGE_SIZE <= BUFFER_SIZE) { - page = ctx->buffer + ctx->alloc_offset; - ctx->alloc_offset += PAGE_SIZE; + if (mm_ctx.alloc_offset + PAGE_SIZE <= BUFFER_SIZE) { + page = mm_ctx.buffer + mm_ctx.alloc_offset; + mm_ctx.alloc_offset += PAGE_SIZE; } else { - if (ctx->free_list != NULL) { - page = (void *)ctx->free_list; - ctx->free_list = ctx->free_list->next; + if (mm_ctx.free_list != NULL) { + page = (void *)mm_ctx.free_list; + mm_ctx.free_list = mm_ctx.free_list->next; } else { page = NULL; /* Out of memory */ } } debug_printf("[core_id %u][mm_alloc] mm_lock_release\n", snrt_cluster_core_idx()); - mm_lock_release(&ctx->lock); + // mm_lock_release(&ctx->lock); + mm_lock_release(&mm_lock); return page; } /* mm_free: Recycles the page by pushing it onto the free list. */ -void mm_free(mm_context_t *ctx, void *p) { +void mm_free(void *p) { if (!p) return; - mm_lock_acquire(&ctx->lock); + // mm_lock_acquire(&ctx->lock); + mm_lock_acquire(&mm_lock); debug_printf("[core_id %u][mm_free] mm_lock_release\n", snrt_cluster_core_idx()); MM_FreePage *fp = (MM_FreePage *)p; - fp->next = ctx->free_list; - ctx->free_list = fp; + fp->next = mm_ctx.free_list; + mm_ctx.free_list = fp; debug_printf("[core_id %u][mm_free] mm_lock_release\n", snrt_cluster_core_idx()); - mm_lock_release(&ctx->lock); + // mm_lock_release(&ctx->lock); + mm_lock_release(&mm_lock); } /* mm_memset: Custom implementation that fills dest with the specified value. */ @@ -80,9 +84,9 @@ void *mm_memset(void *dest, int value, size_t count) { } /* mm_cleanup: Reset the memory management state. */ -void mm_cleanup(mm_context_t *ctx) { - ctx->alloc_offset = 0; - ctx->free_list = NULL; +void mm_cleanup() { + mm_ctx.alloc_offset = 0; + mm_ctx.free_list = NULL; } diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.h b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.h index f6f7b2c..618baf1 100644 --- a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.h +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/mm.h @@ -3,10 +3,13 @@ #include #include +#include "llist.h" #define PAGE_SIZE (1024) /* Fixed size of each memory page in bytes */ #define BUFFER_SIZE (1024 * 1024) /* 1MB memory pool size */ +spinlock_t mm_lock; + /* Type for free list entries */ typedef struct MM_FreePage { struct MM_FreePage *next; @@ -17,23 +20,25 @@ typedef struct { uint8_t *buffer; /* Pointer to the memory pool allocated from L1 */ size_t alloc_offset; /* Current allocation offset */ MM_FreePage *free_list; /* Free list of recycled pages */ - volatile int lock; /* Spinlock for mutual exclusion */ + spinlock_t lock; /* Spinlock for mutual exclusion */ } mm_context_t __attribute__((aligned(8))); +mm_context_t mm_ctx; + /* mm_init() initializes the memory management context. */ -void mm_init(mm_context_t *ctx); +void mm_init(); /* Allocate one page (PAGE_SIZE bytes) from the memory pool. Returns a pointer to the allocated page or NULL if out-of-memory. */ -void *mm_alloc(mm_context_t *ctx); +void *mm_alloc(); /* Free a previously allocated page. The page is added to the free list for later reuse. */ -void mm_free(mm_context_t *ctx, void *p); +void mm_free(void *p); /* A simple custom memset implementation that fills count bytes in dest @@ -44,6 +49,6 @@ void *mm_memset(void *dest, int value, size_t count); /* Reset the mm_context_t state. In a baremetal system, this might simply reset the allocation pointer and free list. */ -void mm_cleanup(mm_context_t *ctx); +void mm_cleanup(); #endif diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.c b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.c index 6ff00b9..51a78ae 100644 --- a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.c +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.c @@ -25,14 +25,14 @@ static void delay(volatile int iterations) { } /* Consumer behavior (runs on core 0) */ -static void consumer(rlc_context_t *ctx, const unsigned int core_id) { +static void consumer(const unsigned int core_id) { while (1) { - Node *node = list_pop_front(&ctx->list); + Node *node = list_pop_front(&rlc_ctx.list); if (node != 0) { printf("Consumer (core %u): processing node %p with data size %zu\n", core_id, (void *)node, node->data_size); delay(100); /* Simulate processing delay */ - mm_free(ctx->mm_ctx, node); + mm_free(node); } else { delay(10); /* Wait briefly if list is empty */ } @@ -40,10 +40,9 @@ static void consumer(rlc_context_t *ctx, const unsigned int core_id) { } /* Producer behavior (runs on cores other than 0) */ -static void producer(rlc_context_t *ctx, const unsigned int core_id) { - ctx->mm_ctx->lock = 0; +static void producer(const unsigned int core_id) { while (1) { - Node *node = (Node *)mm_alloc(ctx->mm_ctx); + Node *node = (Node *)mm_alloc(rlc_ctx.mm_ctx); if (!node) { printf("Producer (core %u): Out of memory\n", core_id); delay(200); /* Delay before retrying */ @@ -59,25 +58,25 @@ static void producer(rlc_context_t *ctx, const unsigned int core_id) { /* Zero-initialize the payload using our custom mm_memset */ mm_memset(node->data, 0, PACKET_SIZE); /* Append the node to the shared linked list */ - list_push_back(&ctx->list, node); + list_push_back(&rlc_ctx.list, node); printf("Producer (core %u): added node %p\n", core_id, (void *)node); delay(200); /* Delay between node productions */ } } /* cluster_entry() dispatches behavior based on core_id */ -void cluster_entry(rlc_context_t *ctx, const unsigned int core_id) { +void cluster_entry(const unsigned int core_id) { if (core_id == 0) { - consumer(ctx, core_id); + consumer(core_id); } else { - producer(ctx, core_id); + producer(core_id); } } -void rlc_start(rlc_context_t *ctx, const unsigned int core_id) { +void rlc_start(const unsigned int core_id) { /* Enter per-core processing based on core_id */ - cluster_entry(ctx, core_id); + cluster_entry(core_id); } diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.h b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.h index 45113a3..a1cd765 100644 --- a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.h +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.h @@ -13,17 +13,19 @@ typedef struct { mm_context_t *mm_ctx; } rlc_context_t; +rlc_context_t rlc_ctx; + /* rlc_start() initializes shared RLC resources and starts the RLC kernel for the current core. The core ID, obtained in main(), is passed here. */ -void rlc_start(rlc_context_t *ctx, const unsigned int core_id); +void rlc_start(const unsigned int core_id); /* cluster_entry() is the per-core entry function for the RLC kernel. Depending on the core ID (passed as a parameter), it calls consumer() if core_id is 0, or producer() otherwise. */ -void cluster_entry(rlc_context_t *ctx, const unsigned int core_id); +void cluster_entry(const unsigned int core_id); #endif diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/main.c b/software/tests/multi_producer_single_consumer_double_linked_list/main.c index b7928a4..6eca764 100644 --- a/software/tests/multi_producer_single_consumer_double_linked_list/main.c +++ b/software/tests/multi_producer_single_consumer_double_linked_list/main.c @@ -11,8 +11,6 @@ int main(void) { /* Retrieve the core index only once in main */ const unsigned int core_id = snrt_cluster_core_idx(); - mm_context_t mm_ctx; - rlc_context_t rlc_ctx; if (core_id == 0) { /* Initalize the thread saft printf */ @@ -24,12 +22,15 @@ int main(void) { /* Initialize the linked list */ list_init(&rlc_ctx.list); + + mm_lock = 0; + llist_lock = 0; } // Wait for all cores to finish snrt_cluster_hw_barrier(); - rlc_start(&rlc_ctx, core_id); + rlc_start(core_id); return 0; } From 344173c348c99b5b9a73b6e7c06fef16555e91a3 Mon Sep 17 00:00:00 2001 From: Zexin Fu Date: Fri, 25 Apr 2025 04:38:40 +0200 Subject: [PATCH 08/17] [SW] Directly access the global varibles. --- .../kernel/llist.c | 33 ++++++++++--------- .../kernel/rlc.c | 6 ++-- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.c b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.c index c42a3ef..c449a00 100644 --- a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.c +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/llist.c @@ -2,6 +2,7 @@ #define LLIST_C #include "llist.h" +#include "rlc.h" #include #include #include @@ -11,10 +12,10 @@ #include "debug.h" void list_init(LinkedList *list) { - list->head = NULL; - list->tail = NULL; + rlc_ctx.list.head = NULL; + rlc_ctx.list.tail = NULL; /* Set the list lock to 0 (unlocked) */ - list->lock = 0; + rlc_ctx.list.lock = 0; } void list_push_back(LinkedList *list, Node *node) { @@ -23,14 +24,14 @@ void list_push_back(LinkedList *list, Node *node) { spin_lock(&llist_lock); debug_printf("[core_id %u][list_push_back] spin_lock\n", snrt_cluster_core_idx()); node->next = NULL; - node->prev = list->tail; - if (list->tail != NULL) { - list->tail->next = node; + node->prev = rlc_ctx.list.tail; + if (rlc_ctx.list.tail != NULL) { + rlc_ctx.list.tail->next = node; } else { /* If the list is empty, set the head to the new node */ - list->head = node; + rlc_ctx.list.head = node; } - list->tail = node; + rlc_ctx.list.tail = node; debug_printf("[core_id %u][list_push_back] spin_unlock\n", snrt_cluster_core_idx()); // spin_unlock(&list->lock); spin_unlock(&llist_lock); @@ -41,14 +42,14 @@ Node *list_pop_front(LinkedList *list) { // spin_lock(&list->lock); spin_lock(&llist_lock); debug_printf("[core_id %u][list_pop_front] spin_lock\n", snrt_cluster_core_idx()); - if (list->head != NULL) { - node = list->head; - list->head = node->next; - if (list->head != NULL) { - list->head->prev = NULL; + if (rlc_ctx.list.head != NULL) { + node = rlc_ctx.list.head; + rlc_ctx.list.head = node->next; + if (rlc_ctx.list.head != NULL) { + rlc_ctx.list.head->prev = NULL; } else { /* List becomes empty, so tail is also NULL */ - list->tail = NULL; + rlc_ctx.list.tail = NULL; } node->next = NULL; node->prev = NULL; @@ -67,13 +68,13 @@ void list_remove(LinkedList *list, Node *node) { node->prev->next = node->next; } else { /* If removing the head */ - list->head = node->next; + rlc_ctx.list.head = node->next; } if (node->next != NULL) { node->next->prev = node->prev; } else { /* If removing the tail */ - list->tail = node->prev; + rlc_ctx.list.tail = node->prev; } node->prev = NULL; node->next = NULL; diff --git a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.c b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.c index 51a78ae..a340dac 100644 --- a/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.c +++ b/software/tests/multi_producer_single_consumer_double_linked_list/kernel/rlc.c @@ -29,7 +29,7 @@ static void consumer(const unsigned int core_id) { while (1) { Node *node = list_pop_front(&rlc_ctx.list); if (node != 0) { - printf("Consumer (core %u): processing node %p with data size %zu\n", + debug_printf_locked("Consumer (core %u): processing node %p with data size %zu\n", core_id, (void *)node, node->data_size); delay(100); /* Simulate processing delay */ mm_free(node); @@ -44,7 +44,7 @@ static void producer(const unsigned int core_id) { while (1) { Node *node = (Node *)mm_alloc(rlc_ctx.mm_ctx); if (!node) { - printf("Producer (core %u): Out of memory\n", core_id); + debug_printf_locked("Producer (core %u): Out of memory\n", core_id); delay(200); /* Delay before retrying */ continue; } @@ -59,7 +59,7 @@ static void producer(const unsigned int core_id) { mm_memset(node->data, 0, PACKET_SIZE); /* Append the node to the shared linked list */ list_push_back(&rlc_ctx.list, node); - printf("Producer (core %u): added node %p\n", core_id, (void *)node); + debug_printf_locked("Producer (core %u): added node %p\n", core_id, (void *)node); delay(200); /* Delay between node productions */ } } From 127a6a26a14949a44ea6e1d00014027853990711 Mon Sep 17 00:00:00 2001 From: Diyou Shen Date: Thu, 15 May 2025 09:23:55 +0200 Subject: [PATCH 09/17] [SRC] Update to latest main, remove unused signals. --- hardware/deps/spatz | 2 +- hardware/src/cachepool_cluster_simple.sv | 32 ++++-------------------- 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/hardware/deps/spatz b/hardware/deps/spatz index 1a8b23e..c746414 160000 --- a/hardware/deps/spatz +++ b/hardware/deps/spatz @@ -1 +1 @@ -Subproject commit 1a8b23e52468c132f2a47abccb4502326803ad76 +Subproject commit c7464146cb51aa778fc93353ef233a8e79325466 diff --git a/hardware/src/cachepool_cluster_simple.sv b/hardware/src/cachepool_cluster_simple.sv index 274186a..ff963d5 100644 --- a/hardware/src/cachepool_cluster_simple.sv +++ b/hardware/src/cachepool_cluster_simple.sv @@ -464,8 +464,8 @@ module cachepool_cluster_simple spm_req_t [NrTCDMPortsCores-1:0] spm_req; spm_rsp_t [NrTCDMPortsCores-1:0] spm_rsp; - tcdm_req_t [NrTCDMPortsCores-1:0] unmerge_req, strb_hdl_req; - tcdm_rsp_t [NrTCDMPortsCores-1:0] unmerge_rsp, strb_hdl_rsp; + tcdm_req_t [NrTCDMPortsCores-1:0] unmerge_req; + tcdm_rsp_t [NrTCDMPortsCores-1:0] unmerge_rsp; tcdm_req_t [NrTCDMPortsPerCore-1:0][NumL1CacheCtrl-1:0] cache_req, cache_xbar_req, cache_amo_req; tcdm_rsp_t [NrTCDMPortsPerCore-1:0][NumL1CacheCtrl-1:0] cache_rsp, cache_xbar_rsp, cache_amo_rsp; @@ -498,32 +498,10 @@ module cachepool_cluster_simple data_t [NumL1CacheCtrl-1:0][NumDataBankPerCtrl-1:0] l1_data_bank_rdata; logic [NumL1CacheCtrl-1:0][NumDataBankPerCtrl-1:0] l1_data_bank_gnt; - logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_req; - logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_we; - tcdm_bank_addr_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_addr; - data_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_wdata; - strb_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_be; - data_t [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_rdata; - logic [L1NumWrapper-1:0][L1BankPerWP-1:0] l1_cache_wp_gnt; - - // Used to bridge `l1_data_bank*` and `l1_cache_wp*` signals - logic [L1NumDataBank-1:0] l1_data_bank_req_flat; - logic [L1NumDataBank-1:0] l1_data_bank_we_flat; - tcdm_bank_addr_t [L1NumDataBank-1:0] l1_data_bank_addr_flat; - data_t [L1NumDataBank-1:0] l1_data_bank_wdata_flat; - logic [L1NumDataBank-1:0] l1_data_bank_be_flat; - data_t [L1NumDataBank-1:0] l1_data_bank_rdata_flat; - logic [L1NumDataBank-1:0] l1_data_bank_gnt_flat; - - // Requests/Response to/from outside DRAM from cache controllers - axi_mst_dma_req_t [NumL1CacheCtrl-1:0] wide_dcache_mst_req; - axi_mst_dma_resp_t [NumL1CacheCtrl-1:0] wide_dcache_mst_rsp; - logic l1d_insn_valid; logic [NumL1CacheCtrl-1:0] l1d_insn_ready; logic [1:0] l1d_insn; tcdm_bank_addr_t cfg_spm_size; - tcdm_addr_t spm_size; logic l1d_busy; // High if a port access an illegal SPM region (mapped to cache) @@ -832,7 +810,7 @@ module cachepool_cluster_simple end end - logic [NrTCDMPortsCores-1:0] unmerge_pready, strb_hdl_pready; + logic [NrTCDMPortsCores-1:0] unmerge_pready; logic [NrTCDMPortsPerCore-1:0][NumL1CacheCtrl-1:0] cache_pready, cache_xbar_pready, cache_amo_pready; // split the requests for spm or cache from core side @@ -1184,7 +1162,6 @@ module cachepool_cluster_simple .TCDMAddrWidth (SPMAddrWidth ) ) i_spatz_cc ( .clk_i (clk_i ), - .clk_d2_i (clk_i ), .rst_ni (rst_ni ), .testmode_i (1'b0 ), .hart_id_i (hart_id ), @@ -1464,7 +1441,8 @@ module cachepool_cluster_simple .l1d_spm_size_o (cfg_spm_size ), .l1d_insn_o (l1d_insn ), .l1d_insn_valid_o (l1d_insn_valid ), - .l1d_insn_ready_i (&l1d_insn_ready ), + // TODO: Here we only check controller 0 + .l1d_insn_ready_i (l1d_insn_ready[0] ), .l1d_busy_o (l1d_busy ) ); From 09cbdfdfa1689ea3b81621a308707b78b7e6e643 Mon Sep 17 00:00:00 2001 From: Diyou Shen Date: Thu, 15 May 2025 11:15:29 +0200 Subject: [PATCH 10/17] [Runtime] Update Runtime and Opcode. --- Makefile | 65 +- hardware/deps/spatz | 2 +- software/CMakeLists.txt | 28 + software/cmake/SnitchUtilities.cmake | 74 + software/cmake/toolchain-llvm.cmake | 46 + software/snRuntime/.gitignore | 1 + software/snRuntime/CMakeLists.txt | 139 + software/snRuntime/README.md | 48 + software/snRuntime/include/debug.h | 38 + software/snRuntime/include/dm.h | 74 + software/snRuntime/include/encoding_out.h | 1 + software/snRuntime/include/eu.h | 85 + software/snRuntime/include/interface.h | 157 + software/snRuntime/include/kmp.h | 31 + software/snRuntime/include/l1cache.h | 23 + software/snRuntime/include/omp.h | 157 + software/snRuntime/include/perf_cnt.h | 81 + software/snRuntime/include/snrt.h | 294 ++ .../include/spatz_cluster_peripheral.h | 255 + software/snRuntime/include/team.h | 45 + software/snRuntime/link/common.ld.in | 129 + software/snRuntime/src/alloc.c | 86 + software/snRuntime/src/barrier.c | 76 + software/snRuntime/src/dm.c | 350 ++ software/snRuntime/src/dma.c | 153 + software/snRuntime/src/interrupt.c | 170 + software/snRuntime/src/l1cache.c | 95 + software/snRuntime/src/memcpy.c | 23 + software/snRuntime/src/omp/eu.c | 313 ++ software/snRuntime/src/omp/kmp.c | 512 ++ software/snRuntime/src/omp/omp.c | 148 + software/snRuntime/src/perf_cnt.c | 33 + .../snRuntime/src/platforms/shared/start.c | 90 + .../src/platforms/shared/start_snitch.S | 49 + .../src/platforms/standalone/putchar.c | 41 + .../src/platforms/standalone/start_snitch.S | 39 + software/snRuntime/src/printf.c | 19 + software/snRuntime/src/start.S | 321 ++ software/snRuntime/src/team.c | 91 + software/snRuntime/tests/atomics.c | 200 + software/snRuntime/tests/barrier.c | 27 + software/snRuntime/tests/data.h | 2468 ++++++++++ software/snRuntime/tests/dma_simple.c | 42 + software/snRuntime/tests/fence_i.c | 25 + software/snRuntime/tests/interrupt-local.c | 119 + software/snRuntime/tests/printf_simple.c | 16 + software/snRuntime/tests/simple.c | 5 + software/snRuntime/tests/tls.c | 14 + software/snRuntime/tests/varargs_1.c | 25 + software/snRuntime/tests/varargs_2.c | 35 + software/snRuntime/vendor/printf.c | 914 ++++ software/snRuntime/vendor/printf.h | 117 + .../snRuntime/vendor/riscv-opcodes/encoding.h | 4172 +++++++++++++++++ software/toolchain/llvm-project.version | 1 + .../toolchain/riscv-gnu-toolchain.version | 1 + software/toolchain/riscv-isa-sim.version | 1 + software/toolchain/riscv-opcodes.version | 1 + software/toolchain/verilator.version | 1 + 58 files changed, 12543 insertions(+), 23 deletions(-) create mode 100644 software/CMakeLists.txt create mode 100644 software/cmake/SnitchUtilities.cmake create mode 100644 software/cmake/toolchain-llvm.cmake create mode 100644 software/snRuntime/.gitignore create mode 100644 software/snRuntime/CMakeLists.txt create mode 100644 software/snRuntime/README.md create mode 100644 software/snRuntime/include/debug.h create mode 100644 software/snRuntime/include/dm.h create mode 120000 software/snRuntime/include/encoding_out.h create mode 100644 software/snRuntime/include/eu.h create mode 100644 software/snRuntime/include/interface.h create mode 100644 software/snRuntime/include/kmp.h create mode 100644 software/snRuntime/include/l1cache.h create mode 100644 software/snRuntime/include/omp.h create mode 100644 software/snRuntime/include/perf_cnt.h create mode 100644 software/snRuntime/include/snrt.h create mode 100644 software/snRuntime/include/spatz_cluster_peripheral.h create mode 100644 software/snRuntime/include/team.h create mode 100644 software/snRuntime/link/common.ld.in create mode 100644 software/snRuntime/src/alloc.c create mode 100644 software/snRuntime/src/barrier.c create mode 100644 software/snRuntime/src/dm.c create mode 100644 software/snRuntime/src/dma.c create mode 100644 software/snRuntime/src/interrupt.c create mode 100644 software/snRuntime/src/l1cache.c create mode 100644 software/snRuntime/src/memcpy.c create mode 100644 software/snRuntime/src/omp/eu.c create mode 100644 software/snRuntime/src/omp/kmp.c create mode 100644 software/snRuntime/src/omp/omp.c create mode 100644 software/snRuntime/src/perf_cnt.c create mode 100644 software/snRuntime/src/platforms/shared/start.c create mode 100644 software/snRuntime/src/platforms/shared/start_snitch.S create mode 100644 software/snRuntime/src/platforms/standalone/putchar.c create mode 100644 software/snRuntime/src/platforms/standalone/start_snitch.S create mode 100644 software/snRuntime/src/printf.c create mode 100644 software/snRuntime/src/start.S create mode 100644 software/snRuntime/src/team.c create mode 100644 software/snRuntime/tests/atomics.c create mode 100644 software/snRuntime/tests/barrier.c create mode 100644 software/snRuntime/tests/data.h create mode 100644 software/snRuntime/tests/dma_simple.c create mode 100644 software/snRuntime/tests/fence_i.c create mode 100644 software/snRuntime/tests/interrupt-local.c create mode 100644 software/snRuntime/tests/printf_simple.c create mode 100644 software/snRuntime/tests/simple.c create mode 100644 software/snRuntime/tests/tls.c create mode 100644 software/snRuntime/tests/varargs_1.c create mode 100644 software/snRuntime/tests/varargs_2.c create mode 100644 software/snRuntime/vendor/printf.c create mode 100644 software/snRuntime/vendor/printf.h create mode 100644 software/snRuntime/vendor/riscv-opcodes/encoding.h create mode 100644 software/toolchain/llvm-project.version create mode 100644 software/toolchain/riscv-gnu-toolchain.version create mode 100644 software/toolchain/riscv-isa-sim.version create mode 100644 software/toolchain/riscv-opcodes.version create mode 100644 software/toolchain/verilator.version diff --git a/Makefile b/Makefile index 8e84e90..1bad5f1 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,11 @@ CACHEPOOL_DIR := $(shell git rev-parse --show-toplevel 2>/dev/null || echo $$CAC # Directories INSTALL_PREFIX ?= install -SOFTWARE_DIR ?= software +SOFTWARE_DIR ?= ${CACHEPOOL_DIR}/software +TOOLCHAIN_DIR ?= ${SOFTWARE_DIR}/toolchain +SPATZ_DIR ?= $(CACHEPOOL_DIR)/hardware/deps/spatz + + INSTALL_DIR ?= ${ROOT_DIR}/${INSTALL_PREFIX} GCC_INSTALL_DIR ?= ${INSTALL_DIR}/riscv-gcc ISA_SIM_INSTALL_DIR ?= ${INSTALL_DIR}/riscv-isa-sim @@ -24,7 +28,6 @@ HALIDE_INSTALL_DIR ?= ${INSTALL_DIR}/halide BENDER_INSTALL_DIR ?= ${INSTALL_DIR}/bender VERILATOR_INSTALL_DIR ?= ${INSTALL_DIR}/verilator RISCV_TESTS_DIR ?= ${ROOT_DIR}/${SOFTWARE_DIR}/riscv-tests -SPATZ_DIR ?= $(CACHEPOOL_DIR)/hardware/deps/spatz # Tools COMPILER ?= llvm @@ -43,7 +46,7 @@ BENDER_VERSION = 0.28.1 # Initialize, setup the toolchain for Spatz init: - git submodule update --init --recursive + git submodule update --init --recursive --jobs=8 ln -sf /usr/scratch2/calanda/diyou/flamingo/spatz-mx/spatz/install $(SPATZ_DIR)/install # Bender @@ -69,9 +72,7 @@ rm-spatz: # Build bootrom and spatz .PHONY: generate -generate: - rm -rf $(SPATZ_DIR)/sw/toolchain/riscv-opcodes - make -C $(SPATZ_DIR) update_opcodes; +generate: update_opcodes make -C $(SPATZ_DIR)/hw/system/spatz_cluster generate; @@ -96,29 +97,49 @@ USE_PRINT ?= 1 ENABLE_CACHEPOOL_TESTS ?= 1 +############# +# Opcodes # +############# + +.PHONY: update_opcodes +update_opcodes: clean-opcodes ${TOOLCHAIN_DIR}/riscv-opcodes ${TOOLCHAIN_DIR}/riscv-opcodes/encoding.h ${SPATZ_DIR}/hw/ip/snitch/src/riscv_instr.sv + +clean-opcodes: + rm -rf ${TOOLCHAIN_DIR}/riscv-opcodes + +${TOOLCHAIN_DIR}/riscv-opcodes: ${TOOLCHAIN_DIR}/riscv-opcodes.version + mkdir -p ${TOOLCHAIN_DIR} + cd ${TOOLCHAIN_DIR} && git clone https://github.com/mp-17/riscv-opcodes.git + cd ${TOOLCHAIN_DIR}/riscv-opcodes && \ + git checkout `cat ../riscv-opcodes.version` && \ + git submodule update --init --recursive --jobs=8 . + +${SPATZ_DIR}hw/ip/snitch/src/riscv_instr.sv: ${TOOLCHAIN_DIR}/riscv-opcodes + MY_OPCODES=$(OPCODES) make -C ${TOOLCHAIN_DIR}/riscv-opcodes inst.sverilog + mv ${TOOLCHAIN_DIR}/riscv-opcodes/inst.sverilog $@ + +${TOOLCHAIN_DIR}/riscv-opcodes/encoding.h: + MY_OPCODES=$(OPCODES) make -C ${TOOLCHAIN_DIR}/riscv-opcodes all + cp ${TOOLCHAIN_DIR}/riscv-opcodes/encoding_out.h $@ + + + ############ # Modelsim # ############ # Currently highjack the simulation flow from spatz .PHONY: sw sw: - make -BC $(SPATZ_DIR)/hw/system/spatz_cluster sw DEFS="-t cachepool" \ - USE_CACHE=$(USE_CACHE) ENABLE_PRINT=$(USE_PRINT) \ - ENABLE_CACHEPOOL_TESTS=$(ENABLE_CACHEPOOL_TESTS) CACHEPOOL_DIR=$(CACHEPOOL_DIR) - rm -rf ${ROOT_DIR}/${SOFTWARE_DIR}/build - mkdir -p ${ROOT_DIR}/${SOFTWARE_DIR}/build - cp -r $(SPATZ_DIR)/hw/system/spatz_cluster/sw/build ${ROOT_DIR}/${SOFTWARE_DIR}/ + make -BC ${SPATZ_DIR}/hw/system/spatz_cluster sw DEFS="-t cachepool" \ + USE_CACHE=${USE_CACHE} ENABLE_PRINT=${USE_PRINT} RUNTIME_DIR=${CACHEPOOL_DIR}/software \ + ENABLE_CACHEPOOL_TESTS=${ENABLE_CACHEPOOL_TESTS} CACHEPOOL_DIR=${CACHEPOOL_DIR} BUILD_DIR=${CACHEPOOL_DIR}/software .PHONY: vsim vsim: - make -BC $(SPATZ_DIR)/hw/system/spatz_cluster sw.vsim DEFS="-t cachepool" \ - USE_CACHE=$(USE_CACHE) ENABLE_PRINT=$(USE_PRINT) \ - ENABLE_CACHEPOOL_TESTS=$(ENABLE_CACHEPOOL_TESTS) CACHEPOOL_DIR=$(CACHEPOOL_DIR) - rm -rf bin - mkdir -p bin - cp -r $(SPATZ_DIR)/hw/system/spatz_cluster/bin/* bin/ - rm -rf ${ROOT_DIR}/${SOFTWARE_DIR}/build - mkdir -p ${ROOT_DIR}/${SOFTWARE_DIR}/build - cp -r $(SPATZ_DIR)/hw/system/spatz_cluster/sw/build ${ROOT_DIR}/${SOFTWARE_DIR}/ - + make -BC ${SPATZ_DIR}/hw/system/spatz_cluster sw.vsim DEFS="-t cachepool" \ + USE_CACHE=${USE_CACHE} ENABLE_PRINT=${USE_PRINT} RUNTIME_DIR=${CACHEPOOL_DIR}/software BIN_DIR=${CACHEPOOL_DIR} \ + ENABLE_CACHEPOOL_TESTS=${ENABLE_CACHEPOOL_TESTS} CACHEPOOL_DIR=${CACHEPOOL_DIR} BUILD_DIR=${CACHEPOOL_DIR}/software +# rm -rf bin +# mkdir -p bin +# cp -r ${SPATZ_DIR}/hw/system/spatz_cluster/bin/* bin/ diff --git a/hardware/deps/spatz b/hardware/deps/spatz index c746414..49b310b 160000 --- a/hardware/deps/spatz +++ b/hardware/deps/spatz @@ -1 +1 @@ -Subproject commit c7464146cb51aa778fc93353ef233a8e79325466 +Subproject commit 49b310b4f9dc92fa4136bda4045768b4b487a035 diff --git a/software/CMakeLists.txt b/software/CMakeLists.txt new file mode 100644 index 0000000..cdff98b --- /dev/null +++ b/software/CMakeLists.txt @@ -0,0 +1,28 @@ +# Copyright 2020 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.13) + +# set(SNITCH_SOFTWARE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../sw) +set(SNITCH_SOFTWARE_DIR ${RUNTIME_DIR}) +set(SPATZ_SOFTWARE_DIR ${SPATZ_SW_DIR}) + +list(APPEND CMAKE_MODULE_PATH ${SNITCH_SOFTWARE_DIR}/cmake) +set(CMAKE_TOOLCHAIN_FILE toolchain-llvm) +set(SNITCH_RUNTIME snRuntime-cluster CACHE STRING "") +# set(SNITCH_SIMULATOR ${CMAKE_CURRENT_SOURCE_DIR}/../bin/spatz_cluster.vlt CACHE PATH "") + +project(snitch_cluster LANGUAGES C ASM) +include(SnitchUtilities) + +enable_testing() +add_subdirectory(${SNITCH_SOFTWARE_DIR}/snRuntime snRuntime) +add_subdirectory(${SPATZ_SOFTWARE_DIR}/riscvTests riscvTests) +add_subdirectory(${SPATZ_SOFTWARE_DIR}/spatzBenchmarks spatzBenchmarks) + +option(ENABLE_CACHEPOOL_TESTS "Enable CachePool tests for spatz" OFF) +if (ENABLE_CACHEPOOL_TESTS) + message(STATUS "Adding CachePool tests") + add_subdirectory(${CACHEPOOL_DIR}/software/tests CachePoolTests) +endif() diff --git a/software/cmake/SnitchUtilities.cmake b/software/cmake/SnitchUtilities.cmake new file mode 100644 index 0000000..ec96cf4 --- /dev/null +++ b/software/cmake/SnitchUtilities.cmake @@ -0,0 +1,74 @@ +# Copyright 2020 ETH Zurich and University of Bologna. +# Solderpad Hardware License, Version 0.51, see LICENSE for details. +# SPDX-License-Identifier: SHL-0.51 + +set(SNITCH_RUNTIME "snRuntime-cluster" CACHE STRING "Target name of the snRuntime flavor to link against") +set(SNITCH_SIMULATOR "" CACHE PATH "Command to run a binary in an RTL simulation") +set(SIMULATOR_TIMEOUT "1800" CACHE STRING "Timeout when running tests on RTL simulation") +set(SPIKE_DASM "spike-dasm" CACHE PATH "Path to the spike-dasm for generating traces") +set(LLVM_PATH "/home/spatz" CACH PATH "Path to the LLVM RISCV installation") +set(GCC_PATH "/home/spatz" CACHE PATH "Path to the GCC RISCV installation") +set(RUNTIME_TRACE OFF CACHE BOOL "Enable runtime trace output") +set(SNITCH_TEST_PREFIX "") +if (SNITCH_SIMULATOR) + message(STATUS "Using RTL simulator: ${SNITCH_SIMULATOR}") +endif() +message(STATUS "Using runtime: ${SNITCH_RUNTIME}") + +# Toolchain to use +set(CMAKE_TOOLCHAIN_FILE toolchain-llvm CACHE STRING "Toolchain to use") + +# Select to build the tests +set(BUILD_TESTS OFF CACHE BOOL "Build test executables") + +macro(add_snitch_library name) + add_library(${ARGV}) + add_custom_command( + TARGET ${name} + POST_BUILD + COMMAND ${CMAKE_OBJDUMP} -dhS $ > $.s) +endmacro() + +macro(add_snitch_executable name) + add_executable(${ARGV}) + target_link_libraries(${name} ${SNITCH_RUNTIME}) + target_link_options(${name} PRIVATE "SHELL:-T ${LINKER_SCRIPT}") + add_custom_command( + TARGET ${name} + POST_BUILD + COMMAND ${CMAKE_OBJDUMP} -dhS $ > $.s) + # Run target for RTL simulator + if (SNITCH_SIMULATOR AND SNITCH_RUNTIME STREQUAL "snRuntime-cluster") + add_custom_target(run-rtl-${name} + COMMAND ${SNITCH_SIMULATOR} $ + COMMAND for f in logs/trace_hart_*.dasm\; do ${SPIKE_DASM} < $$f | ${PYTHON} ${SNRUNTIME_SRC_DIR}/../../util/gen_trace.py > $$\(echo $$f | sed 's/\\.dasm/\\.txt/'\)\; done + DEPENDS $) + endif() +endmacro() + +macro(add_snitch_test_executable name) + if (BUILD_TESTS) + add_snitch_executable(test-${SNITCH_TEST_PREFIX}${name} ${ARGN}) + endif() +endmacro() + +macro(add_snitch_raw_test_rtl test_name target_name) + add_test(NAME ${SNITCH_TEST_PREFIX}rtl-${test_name} COMMAND ${SNITCH_SIMULATOR} $) + set_property(TEST ${SNITCH_TEST_PREFIX}rtl-${test_name} + PROPERTY LABELS ${SNITCH_TEST_PREFIX}) + set_tests_properties(${SNITCH_TEST_PREFIX}rtl-${test_name} PROPERTIES TIMEOUT ${SIMULATOR_TIMEOUT}) + set_tests_properties(${SNITCH_TEST_PREFIX}rtl-${test_name} PROPERTIES PASS_REGULAR_EXPRESSION "SUCCESS;PASS") + set_tests_properties(${SNITCH_TEST_PREFIX}rtl-${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "FAILURE") +endmacro() + +macro(add_snitch_test_rtl name) + add_snitch_raw_test_rtl(${SNITCH_TEST_PREFIX}rtl-${name} test-${SNITCH_TEST_PREFIX}${name}) +endmacro() + +macro(add_snitch_test name) + if (BUILD_TESTS) + message(STATUS "Adding test: ${name}") + add_snitch_test_executable(${ARGV}) + add_snitch_test_rtl(${name}) + endif() +endmacro() diff --git a/software/cmake/toolchain-llvm.cmake b/software/cmake/toolchain-llvm.cmake new file mode 100644 index 0000000..55c3075 --- /dev/null +++ b/software/cmake/toolchain-llvm.cmake @@ -0,0 +1,46 @@ +# Copyright 2020 ETH Zurich and University of Bologna. +# Solderpad Hardware License, Version 0.51, see LICENSE for details. +# SPDX-License-Identifier: SHL-0.51 + +# Look for the precompiled binaries +set(CMAKE_C_COMPILER ${LLVM_PATH}/bin/clang) +set(CMAKE_CXX_COMPILER ${LLVM_PATH}/bin/clang++) +set(CMAKE_OBJCOPY ${LLVM_PATH}/bin/llvm-objcopy) +set(CMAKE_OBJDUMP ${LLVM_PATH}/bin/llvm-objdump --mcpu=snitch --mattr=a --mattr=v --mattr=m --mattr=zfh) +set(CMAKE_AR ${LLVM_PATH}/bin/llvm-ar) +set(CMAKE_STRIP ${LLVM_PATH}/bin/llvm-strip) +set(CMAKE_RANLIB ${LLVM_PATH}/bin/llvm-ranlib) + +## +## Compile options +## +add_compile_options(-mcpu=snitch -mcmodel=small -ffast-math -fno-builtin-printf -fno-common -falign-loops=16) +add_compile_options(-ffunction-sections) +add_compile_options(-Wextra) +add_compile_options(-static) +add_compile_options(-mllvm -misched-topdown) +# For smallfloat we need experimental extensions enabled (Zfh) +add_compile_options(-menable-experimental-extensions) +# LLD doesn't support relaxation for RISC-V yet +add_compile_options(-mno-relax) +# Set the ISA and ABI +add_compile_options(-march=rv32imafdvzfh_xdma_xfquarter -mabi=ilp32d) +# Set the GCC path +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --gcc-toolchain=${GCC_PATH}") + +## +## Link options +## +add_link_options(-mcpu=snitch -static -mcmodel=small -fuse-ld=lld) +add_link_options(-nostartfiles) +add_link_options(-march=rv32imafdvzfh_xdma -mabi=ilp32d) +add_link_options(-ffast-math -fno-common -fno-builtin-printf) + +link_libraries(-lm) +link_libraries(-lgcc) + +# LLD defaults to -z relro which we don't want in a static ELF +add_link_options(-Wl,-z,norelro) +add_link_options(-Wl,--gc-sections) +add_link_options(-Wl,--no-relax) +#add_link_options(-Wl,--verbose) diff --git a/software/snRuntime/.gitignore b/software/snRuntime/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/software/snRuntime/.gitignore @@ -0,0 +1 @@ +/build diff --git a/software/snRuntime/CMakeLists.txt b/software/snRuntime/CMakeLists.txt new file mode 100644 index 0000000..770d955 --- /dev/null +++ b/software/snRuntime/CMakeLists.txt @@ -0,0 +1,139 @@ +# Copyright 2020 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.13) + +# Allow snRuntime to be built as a standalone library. +if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + # Read SnitchUtilities + list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) + include(SnitchUtilities) + # Create snRuntime project + project(snRuntime LANGUAGES C ASM) +else() + # Export package information to includer. + set(SNRUNTIME_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE) + set(SNRUNTIME_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE) + set(SNRUNTIME_INCLUDE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/vendor + ${CMAKE_CURRENT_SOURCE_DIR}/../toolchain/riscv-opcodes + PARENT_SCOPE) +endif() + +add_compile_options(-O3 -g -ffunction-sections) + +# Default memory regions +if(SNITCH_RUNTIME STREQUAL "snRuntime-cluster") + set(MEM_DRAM_ORIGIN "0x80000000" CACHE STRING "Base address of external memory") + set(MEM_DRAM_SIZE "0x80000000" CACHE STRING "Size of external memory") + set(L2_ORIGIN "0x51800000" CACHE STRING "Base address of L2 memory") + set(L2_SIZE "0x800000" CACHE STRING "Size of L2 memory") + set(UNCACHED_REGION_ORIGIN "0x52000000" CACHE STRING "Base address of UNCACHED_REGION memory") + set(UNCACHED_REGION_SIZE "0x800000" CACHE STRING "Size of UNCACHED_REGION memory") +else() + set(MEM_DRAM_ORIGIN "0x80000000" CACHE STRING "Base address of external memory") + set(MEM_DRAM_SIZE "256M" CACHE STRING "Size of external memory") +endif() +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/link/common.ld.in common.ld @ONLY) +set(LINKER_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/common.ld CACHE PATH "") + +# provide linker script +# set(LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/link/common.ld" CACHE PATH "") +message(STATUS "Using common linker script: ${LINKER_SCRIPT}") + +# OpenMP +set(OMPSTATIC_NUMTHREADS "0" CACHE STRING "If set to a non-zero value the OpenMP runtime is optimized to the number of cores") + +if(RUNTIME_TRACE) + # Enable runtime tracing + add_compile_definitions(__SNRT_USE_TRACE) +endif() + +include_directories( + include + vendor + ../toolchain/riscv-opcodes +) + +# Common sources +set(sources + src/barrier.c + src/dma.c + src/memcpy.c + src/printf.c + src/team.c + src/alloc.c + src/interrupt.c + src/perf_cnt.c + src/l1cache.c +) + +# platform specific sources +set(standalone_snitch_sources + src/platforms/standalone/start_snitch.S + src/platforms/standalone/putchar.c +) + +# Sources only compatible with the LLVM toolchain +if (CMAKE_C_COMPILER_ID STREQUAL "Clang") + set(sources + ${sources} + # OpenMP support + src/omp/omp.c + src/omp/kmp.c + src/omp/eu.c + src/dm.c + ) + # Check if static OpenMP runtime is requested + if(OMPSTATIC_NUMTHREADS GREATER 0) + message(STATUS "Using ${OMPSTATIC_NUMTHREADS} threads for optimized OpenMP runtime") + add_compile_definitions(OMPSTATIC_NUMTHREADS=${OMPSTATIC_NUMTHREADS}) + else() + message(STATUS "Generic OpenMP runtime") + endif() +endif() + +if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + # Build all runtimes + + # Generic Runtime (requiring bootloader/OS) + add_snitch_library(snRuntime src/start.S ${sources}) + + # Bare Runtimes (with startup code) + add_snitch_library(snRuntime-cluster src/platforms/shared/start.c ${standalone_snitch_sources} ${sources}) + + +else() + # snRuntime is added externally, only build required runtime + if(SNITCH_RUNTIME STREQUAL "snRuntime") + # Generic Runtime (requiring bootloader/OS) + add_snitch_library(snRuntime src/platforms/shared/start.c src/start.S ${sources}) + # Bare Runtimes (with startup code) + elseif(SNITCH_RUNTIME STREQUAL "snRuntime-cluster") + add_snitch_library(snRuntime-cluster src/platforms/shared/start.c ${standalone_snitch_sources} ${sources}) + else() + message(FATAL_ERROR "Requested runtime not implemented: ${SNITCH_RUNTIME}") + endif() +endif() + +# Tests +enable_testing() +set(SNITCH_TEST_PREFIX snRuntime-) + +# General snRuntime tests +add_snitch_test(tls tests/tls.c) +add_snitch_test(simple tests/simple.c) +add_snitch_test(varargs_1 tests/varargs_1.c) +add_snitch_test(varargs_2 tests/varargs_2.c) +add_snitch_test(barrier tests/barrier.c) +add_snitch_test(fence_i tests/fence_i.c) +add_snitch_test(interrupt-local tests/interrupt-local.c) +add_snitch_test(printf_simple tests/printf_simple.c) + +# RTL only tests +if(SNITCH_RUNTIME STREQUAL "snRuntime-cluster") + add_snitch_test(dma_simple tests/dma_simple.c) + add_snitch_test(atomics tests/atomics.c) +endif() diff --git a/software/snRuntime/README.md b/software/snRuntime/README.md new file mode 100644 index 0000000..d19e74e --- /dev/null +++ b/software/snRuntime/README.md @@ -0,0 +1,48 @@ +# Snitch Runtime Library + +This library implements a minimal runtime for Snitch systems, which is responsible for the following: + +- Detecting the hardware configuration (cores, clusters, ISA extensions, TCDM) +- Passing a descriptor struct to the executable +- Synchronization across cores and clusters +- Team-based multithreading and work splitting + +## General Runtime + +The general runtime (`libsnRuntime`) relies on a bootloader or operating system to load the executable. This usually requires virtual memory to map the segments to the correct addresses. The general runtime does not provide any startup code in this scenario, but is more like a regular library providing some useful API. + +## Bare Runtime + +The bare runtimes (`libsnRuntime-`) assumes that the executable it is being linked into will run in a bare-metal fashion with no convenient bootloader or virtual memory setup. For this scenario, the runtime provides the `_start` symbol and implements a basic crt0. + +## Usage + +The runtime library can be compiled as follows: + + mkdir build + cd build + cmake .. + make + +The tests can be executed as follows: + + make test + +Interesting CMake options that can be set via `-D