From c389382c893542560b1cdc4ae647f09172911a03 Mon Sep 17 00:00:00 2001 From: AngelaGonzalezMarino <135128652+AngelaGonzalezMarino@users.noreply.github.com> Date: Thu, 21 Nov 2024 23:36:18 +0100 Subject: [PATCH 1/3] Altera opt 2 (#2602) The second optimization for Altera FPGA is to move the BHT to LUTRAM. Same as before, the reason why the optimization previously done for Xilinx is not working, is that in that case asynchronous RAM primitives are used, and Altera does not support asynchronous RAM. Therefore, this optimization consists in using synchronous RAM for the BHT. The main changes to the existing code are: New RAM module to infer synchronous RAM in altera with 2 independent read ports and one write port (SyncThreePortRam.sv) Changes in the frontend.sv file: modify input to vpc_i port of BHT, by advancing the address to read, in order to compensate for the delay of synchronous RAM. Changes in the bht.sv file: This case is more complex because of the logic operations that need to be performed inside the BHT. First, the pc pointed by bht_update_i is read from the memory, modified according to the saturation counter and valid bit, and finally written again in the memory. The prediction output is given based on the vpc_i. With asynchronous memory, the new data written via update_i is available one clock cycle after writing it. So, if vpc_i tries to read the address that was previously written by update_i, everything is fine. However, in the case of synchronous memory there are three clock cycles of latency (one for reading the pc content (read port 1), another one for writing it, and another one for reading in the other port (read port 0)). For this reason, there is the need to adapt the design to these new latency constraints: First, there is the need for a delay on the address write of the synchronous RAM, to wait for the previous pc read and store the right modified data. Once this is solved, similarly to the FIFO case, there is the need for an auxiliary buffer that will store the data written in the FIFO, allowing to have it available 2 clock cycles after the update_i was valid. This is because after having the correct data, the RAM takes 2 clock cycles until data can be available in the output (one clock cycle for writing and one for reading). Finally, there is a multiplexer in the output that permits to deliver the correct prediction providing the data from the update logic (1 cycle of delay), the auxiliary register (2 cycles of delay), or the RAM (3 or more cycles of delay), depending on the delay since the update_i was valid (i.e. written to the memory). --- core/frontend/bht.sv | 211 +++++++++++++----- core/frontend/frontend.sv | 5 +- .../fpga-support/rtl/SyncThreePortRam.sv | 65 ++++++ 3 files changed, 221 insertions(+), 60 deletions(-) create mode 100644 vendor/pulp-platform/fpga-support/rtl/SyncThreePortRam.sv diff --git a/core/frontend/bht.sv b/core/frontend/bht.sv index baff335c73..e95c536770 100644 --- a/core/frontend/bht.sv +++ b/core/frontend/bht.sv @@ -1,5 +1,6 @@ // Copyright 2018 - 2019 ETH Zurich and University of Bologna. -// Copyright 2023 - Thales for additionnal conribution. +// Copyright 2023 - Thales for additionnal contribution. +// Copyright 2024 - PlanV Technologies for additionnal contribution. // Copyright and related rights are licensed under the Solderpad Hardware // 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 @@ -15,6 +16,8 @@ // Date: 09.06.2018 // FPGA optimization: Sebastien Jacq, Thales // Date: 2023-01-30 +// FPGA optimization for Altera: Angela Gonzalez, PlanV Technolgies +// Date: 2024-10-16 // branch history table - 2 bit saturation counter @@ -47,8 +50,6 @@ module bht #( localparam ROW_INDEX_BITS = CVA6Cfg.RVC == 1'b1 ? $clog2(CVA6Cfg.INSTR_PER_FETCH) : 1; // number of bits we should use for prediction localparam PREDICTION_BITS = $clog2(NR_ROWS) + OFFSET + ROW_ADDR_BITS; - // we are not interested in all bits of the address - unread i_unread (.d_i(|vpc_i)); struct packed { logic valid; @@ -58,7 +59,7 @@ module bht #( bht_q[NR_ROWS-1:0][CVA6Cfg.INSTR_PER_FETCH-1:0]; logic [$clog2(NR_ROWS)-1:0] index, update_pc; - logic [ROW_INDEX_BITS-1:0] update_row_index; + logic [ROW_INDEX_BITS-1:0] update_row_index, update_row_index_q, check_update_row_index; assign index = vpc_i[PREDICTION_BITS-1:ROW_ADDR_BITS+OFFSET]; assign update_pc = bht_update_i.pc[PREDICTION_BITS-1:ROW_ADDR_BITS+OFFSET]; @@ -127,17 +128,23 @@ module bht #( // number of bits par word in the bram localparam BRAM_WORD_BITS = $bits(ariane_pkg::bht_t); - logic [ ROW_INDEX_BITS-1:0] row_index; - logic [ CVA6Cfg.INSTR_PER_FETCH-1:0] bht_ram_we; - logic [CVA6Cfg.INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] bht_ram_read_address_0; - logic [CVA6Cfg.INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] bht_ram_read_address_1; - logic [CVA6Cfg.INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] bht_ram_write_address; - logic [ CVA6Cfg.INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] bht_ram_wdata; - logic [ CVA6Cfg.INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] bht_ram_rdata_0; - logic [ CVA6Cfg.INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] bht_ram_rdata_1; - - ariane_pkg::bht_t [ CVA6Cfg.INSTR_PER_FETCH-1:0] bht; - ariane_pkg::bht_t [ CVA6Cfg.INSTR_PER_FETCH-1:0] bht_updated; + logic [ROW_INDEX_BITS-1:0] row_index, row_index_q, check_row_index; + logic [CVA6Cfg.INSTR_PER_FETCH-1:0] bht_ram_we, bht_ram_we_q; + logic [CVA6Cfg.INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] bht_ram_read_address_0; + logic [CVA6Cfg.INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] bht_ram_read_address_1; + logic [CVA6Cfg.INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] + bht_ram_write_address, bht_ram_write_address_q; + logic [CVA6Cfg.INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] bht_ram_wdata, bht_ram_wdata_q; + logic [CVA6Cfg.INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] bht_ram_rdata_0; + logic [CVA6Cfg.INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] bht_ram_rdata_1; + + ariane_pkg::bht_t [CVA6Cfg.INSTR_PER_FETCH-1:0] bht; + ariane_pkg::bht_t [CVA6Cfg.INSTR_PER_FETCH-1:0] bht_updated; + + logic [CVA6Cfg.INSTR_PER_FETCH-1:0][1:0] bht_updated_valid; + logic [CVA6Cfg.INSTR_PER_FETCH-1:0][1:0][CVA6Cfg.VLEN-1:0] bht_updated_pc; + logic bht_update_taken, check_bht_update_taken; + logic [CVA6Cfg.VLEN-1:0] vpc_q; if (CVA6Cfg.RVC) begin : gen_row_index assign row_index = vpc_i[ROW_ADDR_BITS+OFFSET-1:OFFSET]; @@ -157,64 +164,150 @@ module bht #( bht_updated = '0; bht = '0; - for (int i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin - bht_ram_read_address_0[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)] = index; - bht_prediction_o[i].valid = bht_ram_rdata_0[i*BRAM_WORD_BITS+2]; - bht_prediction_o[i].taken = bht_ram_rdata_0[i*BRAM_WORD_BITS+1]; - end - + //Write to RAM if (bht_update_i.valid && !debug_mode_i) begin for (int i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin if (update_row_index == i) begin - bht_ram_read_address_1[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)] = update_pc; - bht[i].saturation_counter = bht_ram_rdata_1[i*BRAM_WORD_BITS+:2]; - - if (bht[i].saturation_counter == 2'b11) begin - // we can safely decrease it - if (!bht_update_i.taken) - bht_updated[i].saturation_counter = bht[i].saturation_counter - 1; - else bht_updated[i].saturation_counter = 2'b11; - // then check if it saturated in the negative regime e.g.: branch not taken - end else if (bht[i].saturation_counter == 2'b00) begin - // we can safely increase it - if (bht_update_i.taken) - bht_updated[i].saturation_counter = bht[i].saturation_counter + 1; - else bht_updated[i].saturation_counter = 2'b00; - end else begin // otherwise we are not in any boundaries and can decrease or increase it - if (bht_update_i.taken) - bht_updated[i].saturation_counter = bht[i].saturation_counter + 1; - else bht_updated[i].saturation_counter = bht[i].saturation_counter - 1; - end - bht_updated[i].valid = 1'b1; bht_ram_we[i] = 1'b1; bht_ram_write_address[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)] = update_pc; - //bht_ram_wdata[(i+1)*BRAM_WORD_BITS-1] = 1'b1; //valid - bht_ram_wdata[i*BRAM_WORD_BITS+:BRAM_WORD_BITS] = { - bht_updated[i].valid, bht_updated[i].saturation_counter - }; + end + end + end + + for (int i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin + + //When synchronous RAM is used, addresses are needed as soon as available + if (CVA6Cfg.FpgaAlteraEn) + bht_ram_read_address_0[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)] = index; + if (CVA6Cfg.FpgaAlteraEn) + bht_ram_read_address_1[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)] = update_pc; + + if (check_update_row_index == i) begin + //When asynchronous RAM is used, the address can be updated on the cycle when data is read + if (!CVA6Cfg.FpgaAlteraEn) + bht_ram_read_address_1[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)] = update_pc; + bht[i].saturation_counter = bht_ram_rdata_1[i*BRAM_WORD_BITS+:2]; + + if (bht[i].saturation_counter == 2'b11) begin + // we can safely decrease it + if (!check_bht_update_taken) + bht_updated[i].saturation_counter = bht[i].saturation_counter - 1; + else bht_updated[i].saturation_counter = 2'b11; + // then check if it saturated in the negative regime e.g.: branch not taken + end else if (bht[i].saturation_counter == 2'b00) begin + // we can safely increase it + if (check_bht_update_taken) + bht_updated[i].saturation_counter = bht[i].saturation_counter + 1; + else bht_updated[i].saturation_counter = 2'b00; + end else begin // otherwise we are not in any boundaries and can decrease or increase it + if (check_bht_update_taken) + bht_updated[i].saturation_counter = bht[i].saturation_counter + 1; + else bht_updated[i].saturation_counter = bht[i].saturation_counter - 1; + end + //The data written in the RAM will have the valid bit from current input (async RAM) or the one from one clock cycle before (sync RAM) + bht_ram_wdata[i*BRAM_WORD_BITS+:BRAM_WORD_BITS] = CVA6Cfg.FpgaAlteraEn ? {bht_updated_valid[i][0], bht_updated[i].saturation_counter} : + {bht_updated[i].valid, bht_updated[i].saturation_counter}; + end + + + if (!rst_ni) begin + //initialize output + bht_prediction_o[i] = '0; + end else begin + //When asynchronous RAM is used, addresses can be calculated on the same cycle as data is read + if (!CVA6Cfg.FpgaAlteraEn) + bht_ram_read_address_0[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)] = index; + //When synchronous RAM is used and data is read right after writing, we need some buffering + // This is one cycle of buffering + if (CVA6Cfg.FpgaAlteraEn && bht_updated_valid[i][0] && vpc_q == bht_updated_pc[i][0]) begin + bht_prediction_o[i].valid = bht_ram_wdata[i*BRAM_WORD_BITS+2]; + bht_prediction_o[i].taken = bht_ram_wdata[i*BRAM_WORD_BITS+1]; + //This is two cycles of buffering + end else if (CVA6Cfg.FpgaAlteraEn && bht_updated_valid[i][1] && vpc_q == bht_updated_pc[i][1]) begin + bht_prediction_o[i].valid = bht_ram_wdata_q[i*BRAM_WORD_BITS+2]; + bht_prediction_o[i].taken = bht_ram_wdata_q[i*BRAM_WORD_BITS+1]; + //In any other case we can safely read from the RAM as data is available + end else begin + bht_prediction_o[i].valid = bht_ram_rdata_0[i*BRAM_WORD_BITS+2]; + bht_prediction_o[i].taken = bht_ram_rdata_0[i*BRAM_WORD_BITS+1]; end end end end for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_bht_ram - AsyncThreePortRam #( - .ADDR_WIDTH($clog2(NR_ROWS)), - .DATA_DEPTH(NR_ROWS), - .DATA_WIDTH(BRAM_WORD_BITS) - ) i_bht_ram ( - .Clk_CI (clk_i), - .WrEn_SI (bht_ram_we[i]), - .WrAddr_DI (bht_ram_write_address[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)]), - .WrData_DI (bht_ram_wdata[i*BRAM_WORD_BITS+:BRAM_WORD_BITS]), - .RdAddr_DI_0(bht_ram_read_address_0[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)]), - .RdAddr_DI_1(bht_ram_read_address_1[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)]), - .RdData_DO_0(bht_ram_rdata_0[i*BRAM_WORD_BITS+:BRAM_WORD_BITS]), - .RdData_DO_1(bht_ram_rdata_1[i*BRAM_WORD_BITS+:BRAM_WORD_BITS]) - ); + if (CVA6Cfg.FpgaAlteraEn) begin + SyncThreePortRam #( + .ADDR_WIDTH($clog2(NR_ROWS)), + .DATA_DEPTH(NR_ROWS), + .DATA_WIDTH(BRAM_WORD_BITS) + ) i_bht_ram ( + .Clk_CI (clk_i), + .WrEn_SI (bht_ram_we_q[i]), + .WrAddr_DI (bht_ram_write_address_q[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)]), + .WrData_DI (bht_ram_wdata[i*BRAM_WORD_BITS+:BRAM_WORD_BITS]), + .RdAddr_DI_0(bht_ram_read_address_0[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)]), + .RdAddr_DI_1(bht_ram_read_address_1[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)]), + .RdData_DO_0(bht_ram_rdata_0[i*BRAM_WORD_BITS+:BRAM_WORD_BITS]), + .RdData_DO_1(bht_ram_rdata_1[i*BRAM_WORD_BITS+:BRAM_WORD_BITS]) + ); + + end else begin + AsyncThreePortRam #( + .ADDR_WIDTH($clog2(NR_ROWS)), + .DATA_DEPTH(NR_ROWS), + .DATA_WIDTH(BRAM_WORD_BITS) + ) i_bht_ram ( + .Clk_CI (clk_i), + .WrEn_SI (bht_ram_we[i]), + .WrAddr_DI (bht_ram_write_address[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)]), + .WrData_DI (bht_ram_wdata[i*BRAM_WORD_BITS+:BRAM_WORD_BITS]), + .RdAddr_DI_0(bht_ram_read_address_0[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)]), + .RdAddr_DI_1(bht_ram_read_address_1[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)]), + .RdData_DO_0(bht_ram_rdata_0[i*BRAM_WORD_BITS+:BRAM_WORD_BITS]), + .RdData_DO_1(bht_ram_rdata_1[i*BRAM_WORD_BITS+:BRAM_WORD_BITS]) + ); + end + end + + // Extra buffering signals needed when synchronous RAM is used + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (CVA6Cfg.FpgaAlteraEn) begin + if (!rst_ni) begin + bht_updated_valid <= '0; + bht_update_taken <= '0; + bht_ram_wdata_q <= '0; + row_index_q <= '0; + bht_ram_we_q <= '0; + bht_ram_write_address_q <= '0; + update_row_index_q <= '0; + end else begin + for (int i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin + bht_updated_valid[i][1] <= bht_updated_valid[i][0]; + bht_updated_valid[i][0] <= bht_updated[i].valid; + bht_updated_pc[i][1] <= bht_updated_pc[i][0]; + bht_updated_pc[i][0] <= bht_update_i.pc; + + end + vpc_q <= vpc_i; + bht_update_taken <= bht_update_i.taken; + bht_ram_wdata_q <= bht_ram_wdata; + bht_ram_we_q <= bht_ram_we; + bht_ram_write_address_q <= bht_ram_write_address; + update_row_index_q <= update_row_index; + + row_index_q <= row_index; + end + end end + // Assignment of indexes checked to generate data written in the RAM. When synchronous RAM is used these signals need to be delayed + assign check_update_row_index = CVA6Cfg.FpgaAlteraEn ? update_row_index_q : update_row_index; + assign check_bht_update_taken = CVA6Cfg.FpgaAlteraEn ? bht_update_taken : bht_update_i.taken; + assign check_row_index = CVA6Cfg.FpgaAlteraEn ? row_index_q : row_index; + end endmodule diff --git a/core/frontend/frontend.sv b/core/frontend/frontend.sv index e59da0ee36..3117e27654 100644 --- a/core/frontend/frontend.sv +++ b/core/frontend/frontend.sv @@ -140,6 +140,7 @@ module frontend btb_prediction_t [CVA6Cfg.INSTR_PER_FETCH-1:0] btb_prediction_shifted; ras_t ras_predict; logic [ CVA6Cfg.VLEN-1:0] vpc_btb; + logic [ CVA6Cfg.VLEN-1:0] vpc_bht; // branch-predict update logic is_mispredict; @@ -484,7 +485,9 @@ module frontend //For FPGA, BTB is implemented in read synchronous BRAM //while for ASIC, BTB is implemented in D flip-flop //and can be read at the same cycle. + //Same for BHT assign vpc_btb = (CVA6Cfg.FpgaEn) ? icache_dreq_i.vaddr : icache_vaddr_q; + assign vpc_bht = (CVA6Cfg.FpgaEn && CVA6Cfg.FpgaAlteraEn && icache_dreq_i.valid) ? icache_dreq_i.vaddr : icache_vaddr_q; if (CVA6Cfg.BTBEntries == 0) begin assign btb_prediction = '0; @@ -517,7 +520,7 @@ module frontend .rst_ni, .flush_bp_i (flush_bp_i), .debug_mode_i, - .vpc_i (icache_vaddr_q), + .vpc_i (vpc_bht), .bht_update_i (bht_update), .bht_prediction_o(bht_prediction) ); diff --git a/vendor/pulp-platform/fpga-support/rtl/SyncThreePortRam.sv b/vendor/pulp-platform/fpga-support/rtl/SyncThreePortRam.sv new file mode 100644 index 0000000000..2b65c9ec80 --- /dev/null +++ b/vendor/pulp-platform/fpga-support/rtl/SyncThreePortRam.sv @@ -0,0 +1,65 @@ +// Copyright 2024 PlanV Technologies +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses +// +// Inferable, Asynchronous Three-Ports RAM, there are a write port and two read ports +// +// +// This module is designed to work with both Xilinx, Microchip and Altera FPGA tools by following the respective +// guidelines: +// - Xilinx UG901 Vivado Design Suite User Guide: Synthesis +// - Inferring Microchip PolarFire RAM Blocks +// - Altera Quartus II Handbook Volume 1: Design and Synthesis (p. 768) +// +// Current Maintainers:: Angela Gonzalez - PlanV Technologies + + +module SyncThreePortRam +#( + parameter ADDR_WIDTH = 10, + parameter DATA_DEPTH = 1024, // usually 2**ADDR_WIDTH, but can be lower + parameter DATA_WIDTH = 32 +)( + input logic Clk_CI, + + // Write port + input logic WrEn_SI, + input logic [ADDR_WIDTH-1:0] WrAddr_DI, + input logic [DATA_WIDTH-1:0] WrData_DI, + + // Read ports + input logic [ADDR_WIDTH-1:0] RdAddr_DI_0, + input logic [ADDR_WIDTH-1:0] RdAddr_DI_1, + + output logic [DATA_WIDTH-1:0] RdData_DO_0, + output logic [DATA_WIDTH-1:0] RdData_DO_1 +); + +logic [DATA_WIDTH-1:0] mem [DATA_DEPTH-1:0]= '{default:0}; + + // WRITE + always_ff @(posedge Clk_CI) + begin + if (WrEn_SI) begin + mem[WrAddr_DI] <= WrData_DI; + end + + RdData_DO_0 = mem[RdAddr_DI_0]; + RdData_DO_1 = mem[RdAddr_DI_1]; + + end + + //////////////////////////// + // assertions + //////////////////////////// + + // pragma translate_off + assert property + (@(posedge Clk_CI) (longint'(2)**longint'(ADDR_WIDTH) >= longint'(DATA_DEPTH))) + else $error("depth out of bounds"); + // pragma translate_on + +endmodule From 7eb33df0acf17e2a1162d7d56a1047d78afa63e4 Mon Sep 17 00:00:00 2001 From: Jalali <110232072+AyoubJalali@users.noreply.github.com> Date: Thu, 21 Nov 2024 22:59:42 +0000 Subject: [PATCH 2/3] Interrupt agent : Modify README also clean interrupt_pkg (#2571) --- .../verif-spec/media/interrupt_uvm_agent.png | Bin 0 -> 69573 bytes .../verification_specifications.adoc | 69 ++++++++++++++++++ verif/env/uvme/uvma_interrupt/README.md | 17 +---- .../uvme/uvma_interrupt/uvma_interrupt_pkg.sv | 2 - 4 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 docs/04_cv32a65x/tristan/verif-spec/media/interrupt_uvm_agent.png diff --git a/docs/04_cv32a65x/tristan/verif-spec/media/interrupt_uvm_agent.png b/docs/04_cv32a65x/tristan/verif-spec/media/interrupt_uvm_agent.png new file mode 100644 index 0000000000000000000000000000000000000000..03cb21e2ec744a9034fca0cafd00bb93662e1d6e GIT binary patch literal 69573 zcmZ^~1z6PG);=r<(hSl)gmj8XDGV?Y(%m5nN;gOjB@9TnG)RY_2qKLlN=PFmT|;;0 zxA8gWJkL4*_v4z2Ym{HCz4Bi7UOP-pMUDWM8u!MH8w8K#A8FjUfl+RGjl}(B{p(W^+p1kg*Y}1*|;*iJiPJ^ySj-+ zbmKpt0DqF>L;ROxheMQPQVi)Bm&x5`{mrzes4MI%EOdq&e}BvvTS64?nWPOq)4Ca; zM*Mye+11r$ia1%!m5bgz@o_knRoyz+%gK9~Ku za@V)*3h3O1b4XAo@SvBTF?P+iA|c*h6&1hLf+5)cH~#*-ijV}iA|X%-uYK&&&`*Ns ziP8!!N!R~e1~(}xDrO|hHlH$%`ptZ;{iN^dBE8@iPK5l`$(^j;>1IDa1mf~M_-7q~HfmgUYeK&T>mQG}fgvq9WAwX|xIH)= zzPGn`v^Cv}+WXw;N``FN+$PqWgfyS;b^-Z#d3k$&{!F*q2!e*p$PvN+Rx%pV6Z8e- zI}~s4&!619yb?agLrC1Cv#u}xhG_>yb=2ARrmC$C@H0jj1j`V@p1fZIe*DF*fG#dTM^jZ zyHYg_Um@@p;*>GQ=!}MPU9z)Be|2i;QJs7 z*#t&g>+4Mq{fFP85n-bR41bDsqbZp|G9J+3+t^{uAc>6saY=wYi9fVlnL+Kr5cpH< z<$e4weqe=vE4YOP?bxiy7c0n+CP3hLwlK@>-Sp>3i7do$+f}At!=mrF-p&He&7k;( z47|$OwC0k+4cg8s$sG%LxOI&~Z`$zrCB*$=5Vn4ED~lHbRD;$NBd3wSMY2s|>@1WpG1<<4Knz88O^>ohZVn_(H;uIa z8t;vEzCSkUFm1E2QOQuRrV;n6tShqcR5YN(l(w>by|vNdvLtiw$jnO~=UTu3oW1iypeV3S#epgd(%rTwVyS3pY^pxpk9=imc0VI8`h%2o6qMjqa_llc| zr$z-kuQ?d|TD}MW=0ygc?9eLWU=WsThk{WidGavj3~Z8|VB(O+jDYMfx+t z9ty{Gbw9WqqPu*4@qW{h;>YX(Jaw$gSW8Z5Vn;{Z&YXasM~w)`X}~MoY~2k*jDE#I zIqwzpd(12HZ3(~o*|BG0zdO&fwf9{+{$%ZP&)s>+-%H9p=SFh9`B%QihOCctl<7my zzNa`zdLU+siq_J?quWwH74A2 z6=Yl~kw)xo+)$jQ+dJ$q!HR52%(qt;oN99--I-_I-R(m8)#MrG+Kmm>H=Q+_4mvLAv8&RvlI<@&6f7^s@9P;s z`JHx?mC(xF)qddAsfUHolRaLh{^My3fj|NqZR{b)T{P3PS)j%|Q?gx_Q?l@ED8dc1 zU>C1PEU!LABfd!?kJv5em!dTbj|y)L=evYoZJ!R+Rig0}T!d81-|JMwH@3rYCOcSS z>ROF^uUz>KOn?W0FAkHlyf{CqPISMSczMFkwqG_MtzEn9lROiVc&LM?-xEjYABG1L zuTSU9^QZ(cE+k!i|IU{aAlgGl-TAAkiMQ*aoux|eP-_n{N7x332^Jk*TPd3wn{vkY zk4%rUzg|TOZSiYOs8%jM%!hZn>6Sk!G2D&euvpREDL`D79xF^Gq@HUx(xWzhbeyjon)w_B?@F;M0w;6KeD3-u z*jjR%10+j}e2XDUNzh5-#k-3^ETub@dDU+?;A%~rVULdnol>UC+VL%<7+Z=v#VWa@ zpYaO!&L_H=r%bJYFjG{h3=~lE!TfiP-;M#1`0Z0r&bve)96#`|ILXzgcHGXm<>w~t zAO=Msx&qY9y6KaB0`B-oxJ2id=P^XLIVS=e-<4P+uuJ&3FoJNB|C9WL^8%;Rx%7k= ztTm?*SF<+FBHt8M!F5e#-z`**d6{a}40R_L{NSi>d=&bK0p=3Ui8G zJ$Cl}SB2lux31%*c*5su=1%k+Snitdj>+rqNivD1XQz>eq>(%}AlrDc5Ap~EfOm(k z$x}?$md4hoE-vM(c5Y~0>NRu(;k280JPO7oP`)6&UR#v8;O5iS-?}NCr|d!h#$=>H zE&2^tj_(KqPG?zW+98H=1qEP%T5Km`L(!M&$Fn0eV@%7tu*}d3rGn;iIOgC|mEvKM zaDr1ps)m~G{>pE073FRh3E1h6L`>OB>+$e5lR@LsTU9-B)1?lv#_Tt%MrEAxzTOu+ z^m|_)EVr}Mw5MRIF<{9jT;Z`BSzPSdZK1;MLFcqBv`DlDx&VtTl z)F@WfiRi>(N$%>nX+mZ3GQc4s8B(Ma@x!pFMV?1&?$bou&``~$^bkoa`M-^Z=75uK zN2gztv-+*$&{pWdy?Y-&e}2=8N={C0ExkcWg-v>A<|WM5avg>SNLN zSj3-+#tW{m-*fr0L3+l zkA2okydGYxJ9|GSV{pDFEh}4 z8L6=Ka1xcp)`P@=cLt?zYWkWm4Zd`ut?d${Mls-BOJlCgsrXn^md#t&-HG;j58SZX ziH7HfGaaY=%>`p;r#Ax0Yu>g?aX2;FxWShX&~MIu?OZG~y+Yk=YH|hsRM+d*u=TKJ zj`q$6h(2@UHF)Ix26ee`E3Misq zflt`{Htp$$8DElSzbA9`)81)mYO^~&7inUenl8bqs>7N^z>YjopgT7Soy3=K73nozQv zNR-tgs3me_3!|pq7eqC01AhiMiC+yyD|si=h&B=T?b}?nOhO)qAq+mcY|{wa;wd=6?ERliZ}~Z1ZSJCv|(|G62V3F<3hBWLbX9#wb}YhwuZbNE;Noxi*saw}MEJ1u)YNB&*(X)$N`n=*RKL8t zh$)<}Y#Dx0V(#p#nlkM|RGTr9oWSx8NKhO&k%ZTotrY*^GHgLj0J_FX5SgrB{<)T$ zpLS5>wcH0Y&P35{0omu(h4eL*!0{3c z$;Tefe5eZz-2}J1kndf=r0S-}oRLtFd3+lx8e^C^Pu7~dUYkA^G1ABVH0Pjkw%C^6 zSyJK3L)e8WvH#l48Ix0fHUVvMXYOVlkk&JAzgak?)>h^%*L+ua*5WjdMVp-k#Ws9# zbe8L1keBot@;<%wYS!S7OkWw;2KT+c#Hr!K5<-||qS%f)8?us1lp-xqBbOiBF0sW4 z8v#r!imoZ}uRJcPj?)5p=Zbd5B-;`OWi>=PD0hRteU_C$7rVDQ`jz*4O1gio>rsj% zac^PR8+5bJ4(}LR>HZ-yI*PvJm%CU>}Z}9P+ zA?9H?D%s!|-CZX9#yQbj8e{b2vu4k24pYuD3PNA6j=6|HDy3B-sbmXs!-2%yFk)(Xb5>R=< zxX@Q~@5!B8=nPM!W@`P44m)gbS^Y(6c*xv9SgzoWQt_Z$?7_oVDBJ^pIsCJ5Jnqv; z(f(D9vWWblumM>d4V()#woJJDn)O!YE`=6XqbM2;tG$fdswgJ5>NwFPtK5jOYl z_%QM1%bKmPVN`Yey!N*_iIa!E*`Aulae{HQaTvsh?SAM{=lr4%MMY7&%qWv|0^I9I z%&4O8vUM$1KvVxh5yz1&DGS?xZ(&pU^y1@KN=iywTbqwWb3?;=ucn6Q$5gOzXGE-c z%zhlFyj#2)9{BHXtaG+-8rIdY;CG-Gxf#gvar0OKaJ+6VL)k@`AwdtH$!r2O<}=-Z?K{$ksQpo?F#7GC)>FiwgG*cM71#Il{EJ0g(RFJR;J5GX7yuwqqneUjX&) z%*-56&}im(b{6@<_f)%qq9BAOkZ<#LGsxM@!Kbd^HB-PBy+j~z_G{PNrU_6xo!y@F z*5lldhB~wI2^9dZIzIU#v<-JyiV6iWNo4;&%Thv!h&E&Mm{aY!n00+P6c=ZfFj9A& zL-KUYhJ|_a!kjC~Hmz7>0o6!^{=YsVsp#x68B#*R_WR@5`p=&~=jNVDWSN?n5cZvf zX9@>l#hmJ6<1HROeYSdRISli&-G*P$;+X>}W=#J_iax}s+uCON5YZ+Nx49|WcoWzC z1?1wR;~YO!Zac^cEijO7=zCg;aIf>jxhz8{LLS0A>0Bl*c^Ra&LBxLM%yixd+f)5N zpRR`xIhvUTVZjf7P);@>2CTPOw@ivyo<3n00Bq|v!NRijK^kS0l5!|ZUjgY`$JFd1dxB&%oaHMW0dzE)Fo)O{48Xq{=;?TxG{Lg8?T`L>xT~sHeuVXk}BG< zg4q6&VIc2|rz06jufzN}(!clO{o3&4fT{ASH2jCgrTWzdmGjpS8xqA6x!U0Tk@&`* zh^{E;;dJI*{Q2OJsA~7yUa+#zHbwU~j`R25;+0&lZ72WV3U8@Fi1-{$mGVs5B(kWk z9!+PaG+s%DjE}`qHP_5|;5cc+e9C#PD8DaLxKwJUEwUdo=8QU*HIDX*1Ve8*m%Ppc z$WcM*24Z>kA%4y^JJaHT;j@f%fzT%%y(7z{0i=~)8r41gT%mi<2XQR!_kK+L;;T0` zcu%7tECvqysWRbm5*z<+jsOySjX_&T{@1tsr_ZlbEAaotU&M8LeLL1Undc=4k<+#b zjmy}N^tnq&vJW0Rt$Ua;dlyo!-=jVft?=hBz|#s1k(K%!abMGUi_H| zxJZ?B+ur9N@7=o>9v*(;gYfjM^(Z6@Z~r0p5#cc=F3!nX^S-L&{jcZWzi;tuhk{@1 zHvZ-zMql{xFZ2cY1YIdZ`u)6RDY_`A#l+aQmdKOXziM3e15*Nn2;9|#O^n4dqVht3 zVWgu+J+Vwt&RpD7Gh1@WIboR(xda@5e$Ht>G&(jY8> zsw_S~f?8gU^*&R5SRJ%v2Y%1LfJJY>`ZjTrt8b0%4BzfFAB2?h73gF(RIMO?U0>E| z6R9(G3izh8j=g#d!Ut1gm7t$@{*aiGjgP)~osoW<6P{dGH-99C&m7WK*@|Q1YaO4L zfs(yhao^2nnWc(|gKw$%=egrQDaXcL+&ad8j;>!|)#({jK!uFb_daQ{6dNqM?(*rj2cnP_TEE_xufzH>sSHk{2|~=wLs$=iX@H8Y95^WI z+i$&WaC@fDyKh1G#MXkoUp0HznXj+M-U@Wd&+0D&V(*I;D zIxKNClas;GUE+qmgmlfBCsExH$)IEx{KPC*Z|U~IyfkzHDP_bdXi)^pw@#}pQ79>B z4`P?hvGJ}k7=l5~7S=e%o!Sr#!V6@CJRHT3p=_^O5I^Xqir# z7kx`M&4+3TnlL8(DpDfjeCp(t8#0$)DG|o?pk!S}XYVlp69XhN_;Jvis28#GdjCBrv|^;M3C2TYtXgwtFYZV=KaBzIliNy-K}Mxbdx%S@kOLoK_jh{ zju1Y))^3-rcdH=3=jF7G9_VVlE2>>MzjQ3~7L;GEqdoxENqlFBaOJyZ?HIUXbidVF zVJqduv}b-v$c#K$9)03$%swaZL+~1t;u6oLv6n@^3ZOcGH4cr+VDDcnc8)v(*W*NL z-6J9WsvvnexZSFCOY~nrPd+;Wv5ZQD7mJsLt{V&W9@7H5fUMo8?E>7{IhYeUfHyF) z(CW+`2ZDNRESAHSit}ZTktt_n^4f9XOh<5m)Gj;@Y9&FAG@5q1>z1f2t8&mDOS;C4 z_S-MpxVRRCp)#y2De(YzsQRsAh?&yjbF18`S3f%=p%Q!R4}4UYfGKD2`3lN+-N*Q> zKGDGPs*R}PJ3&;#n?EOu&DjK5l7J0py~8$H}gg(H0pNI_u;kfgfU?*7zu z`2lZDDPc{Bp!L0;=OCO6$RuczJ0D_y-dCU((hK2wx&x9ZFPpl`Ilt3VXZK&3a*VbW zfbUGtL%OuYMC+6soPoTohs|g0{k#Kgbr!LCP9V)#kdW5`<9+Z}#ruWA6qB)18aZ`^ z<&iaj=tVlDrFVAIi;lPX*6zUPYQZ&O?2*BX+aO=P{?k`f{wQ1C{aIOWUYc!NkQ2?tBcWCDz-<>*S{ZvC1wVO{7u+th|Tnchw?u!|2ud_JB_JP)HZOZflTpH|4q4WA;_>twGR-)J z&%S9s$n>zr`oZ{dAhL@e-&vFcR#3}h8B3QT#z>?o-*DS^u@#M$hkz|X;KyJ+*-SY z-`ZT_)RaSvIxjAD>nB4+$13mbIw&oEv%%4@NIQ;y3ll5C~=HJ}S^E(ITd<0pfv0ITt z-m%4}@6u_zM9*##MnI`UK9nSpN@o`(Tiwr(3a(p)kYF*asL6V;T+4ym-QK)jJjO8T`nYQ+Hl4~Twn7DUU$*!x}hR;y^gCx{KlYu{s>S_SEUW|i);I} zD*?QG_-c43-L|dqp>DD*UGL7570j?ZNodB`=#mcBB`A-Or*JpGi(bKZ{*@@$%C7_{ z-&~GL^B)ka3pM>GT7he3V2kg$S8JXbWg0?{XXHX@1DG<|<3f#<`v)N`K~U|G=f9CR z`-f}fz5M$DL_bAAE&G?KW(v2|miqG7G2>8>Z4H9C_Vq|b-)T+xeO}G*2;PJx+^sDO zPhZ*1ek%^rX6xx}>3#&QRr5YC!KN-bDWg`CMz^+{^3DEg<>&(Zv9SxJms~<2x&k4I z#b2m@n$_j64ZMeU)SkldC!Q&W=V{Czktgj&zb2(M<9h1!0wO>V2i@hI2FW^xKK~~} zH0{P)Vc~Wf!pG7|SqmM}>9K3xaRd8sVdBzL74w*jkx70<rVIy(OLvD|81K%zj*L+A@`f<1KO0E1k!XHRQQmsI((aJIpP) z8DUBIhiC%jv6}~;?}Okt=VwQd?LTB*KrR@7Tywr~GRgh=Ur2i8ITI>ZvsT|)MpHbT zwQU>TX?_*pUgsCBwFlLM>O)93W&SrnnJWKfyR$8;UKk+%SeS%?)dHSqI z)c~=hzt-$KAU#*}V66VZ*xAV51$Z;9YBZ~WFt1UDd^9Sgu!%DBG>|s#@@Vs%$@dcV z1%7%yjg=bol%oCKG6t>EZ`u>HrF?03af_crNo_F87n6IFG#%hnKHT>)!Lz^7) z3v!OGyq4ZE|M*?`U);sv9L7`PXMk8Dau2u@q>}C0%V+ofG^e9^|Ccam#Cl#TcGj{^ z>J>fQb~$h?LPKXzlSbd2F8hdsYw#B^OYrxv`eF*LmlTrc^q84wnZ?uPwO~D!b5>yO z4vUk>S~|8Ay0+;}sVAzvp+U98!w@=2m#J4KYEr7^IV(#5!8V_n1nur?q3E(%03YB4 zsLRA!(m%W~;4ve7BqrTG&$olQ>Ij66fWzOr3p89(oHPnS(Lcn0WlYM^0lHJ!<~O;6 z2cR^)o3BM}e~s2_psZp;QP3%c&mal2bHEgcrGHBEb-u| z0*jyc=8wUIJ*1~IS7pi2Ry zh@NzU(nAimAI?2X)+*=Qu1_s(|MI-_{HW`vGN=jsH(xNy*q4%WyuYKJyU(2htPX2* z%)fWEp*gHtQ%zUd9GQ zTnlg`n^dbDfoq+JFiWaj%j^D?BqO(tNSdYb55{{+)YfXzSZ~J4}-tCWy}*2oab} zYqF-4wKucUmMQCwhy+Et_&Z<~#(%ykrV#&AeizA;igtlLFKS+xST2u_#ooowb$j?? zobwwEV2|IV1qCw0Z0V_K(wqRX!h_}M{X4JD#nRhmT={4Bft_JmQ!Q3iC9C@F@Om7* z!%u)aaVtET)^RKBQ1r&tJ~U@AOw-|QDe9iszLN?KB!a`t18HrEV_^EceiwbTe^~h^ z$K$RpM>Xl&gL}GSSZtj#ORg@DryUqo#VbC!BK5SCki&o`Al(TLAsoc*{l(Jk^|TxC zRd&xK1b1ue%X z`@|$6bd$eg#QMb4WZ4p)bp0Wv>_vy|OCB>${o$mZ0Rkgmg)nJBtw!#eG$7VpD$Lm> z=T)On-)jYAy>VyG;2ET~8qr>AW}iev26Gi9Ie_m~pPJb%$;xm~-MzbkT)4=(ISje* zi%7tqMLIJD|M8bmwmwl2DHT08_LH?|6zw?33gzF?YJsU1`|wu&x5c3qY~G;3%zm29pHQqPY zk5^kBy~2g9zj;GAMx1q#yOqs)-iKDTD--}tdV&by1w7o>M>9s#A~rd&47CB?3aG5k zZ7XrLQxh5POhY{l6Mx2w7|uQtH2_fo6(#DaTijy0V)7&OcsA+TMrJ$XFoeM1prm_( zp^?Ltgid?D`4e!RhuV`j-R_h0@1%nZw}yUgr@jWF>+*OaT#rP%meFj`)|K5O1hx z&eErRg`9X->Q(YHz7zri?XmLMhwJ+_2(qKmS1gWwW17>um;#U zI$;-zU6hKSzo2B=@wTR>z(ScG6IX_X!LQQj@-#>EIv>4?ZmDg$YrsQlukLEy?^DUQi7IA-J_cxigLeknoOsSGoh-ggVlwLdjLPNQ3EUr_4 zgbI19ye404VA!0CmrKy&0m18$odg!S64|bZN*qNB2dz295OT*)Liw%^d2bT$q*Y+bI0{ZC#;|?rsL5mKM$1t0Fc~GF%*0p)V55L&(3yYf(Gr5K8wf@GyLgB zicVzerm`vB#nUL%o>7cV$iBvFkU1N4$=%(}uX*aWqT$}c915#fZWoSV4`;Ui==I$z zoCxT^`I}3Lhx)JuOr{fIIg8960yNTx|*5P7h^qeH7oB z2H^+%_7Oh=ZuBl@i+eB1Sk_LT;o-ri4x z4vg6W@FNh9bE@my45)Kw20%8r;3=MZ6M_gv{9+U?JTiPE_9ArJVF#2~uq!oXqRGjo zrE;S$jv4Qv2KWjSHkRnw&dl#lEJIijHO{w{ewmEY>dW01s7j-(;AA<6^1u zS`0A@vt!ACyE!IjnhEN0y-wTHK?n!6aaT#%dVjxJ#-O)(L?_dGOj_TFhWr>PX9#x~ z2l5R(wq?*dPe$N1bXVSjc2MAgfio;+_?xT)PJ0&jfBKFuOfl4NMt{d$js$gc8F;ue z+~>btcD`Z0rV7JflxC_}=~v_cefU0;w@%Y*z4S~QG4CrWP!LNR`})9EfMF+WpfNT- z7OJ)9RatX&2pIV=S3&bNB-puoU1i%&Qpj+^$hPrV%9QTy`#h!s8%^?yN>_C{V|vT* zO5&UjsxdE%X_eGix)KdQ2pPk)Kjl9-( z>etg+OM-nGeAbYzybmN&C$*9jZjmiJ+db#5dH)FB#l!t!gd@oMv(R0HLqP8mz*Y&u zEY25z%?9iV)ki>)fE|UHNk93QG~^CrG3s(dkj3?MeMhPBz?BWhD%m^94SG22q4vJ! z4^DaP@`ySylTOJJ(`m?*wvuz}&yI`Pf)^eYD9|2z8EgjA-+S?5^7EjEAY zSOCsE$%6svm0ZTzH%>X-`gqfoZl!Pou3N5xM6^pB!Nsa&wrlU(`uE`G?6k(EFka-# z3_xn*e|h5oF5OG%?QO-M@b~U&5Cq za-mF&wIE+^Y#*)=5wv}fRY&JUSV=KeM3EpBEBE1Ap$)pJ)n=EyPc(aH+Ry*hD{V<(Niajur4cs+ds z&KVfhiqTbL!WXwO+aW7TFCDkN-js_h;-u9COP-m9jo>fhbG}Bf|A_tzNHN}kX)S3S zOIgA${`5o7|Je^oa^T=cmK!P5?N+|dr4T!1Qy6peKNWKm`}lvcqRA%{ z^W|rtgJFCvG4vJS-^X}e9>|;nQ}Xk^RLJ4=I8qBPShW9=r#u;kq(62G{>Bx{s{zQ# z`6N&lSSQFe6Id9FIi_Z0q=vo)-P)# z&5qZNP0y`AQ*hgC|J>ls_P_{{-HM@VnjZSqpT%P$#~ALjy8q<3oUd9UOQna8p0?rA zT2a`j-w=6+4Zl+(X9fEB(S@3)spyq{yKr3EuEF4UX@?@+KwCS7TF-gWMySY!y*GtMC+d3#G=i9jAq8ES_F{a@?6=5KfK(`G6>)G#nw@vWAi1~Fkv@?Ek z;e2kVe;v#+luKD~yf^hYmD~g9x?TegHkl=SMk5~f33aKQzhBv(LH%n@X|-N@-T852 zKl20;diwE2p>4BBAqZ|sfd9RJn$^Ds!wYHOpE`T_@uCr4(?CEUYpL9C2&)pIVg2EZ zg;mi!=1%3%#b5o1_$!zd@x6RQ6%My;#6wti|M)dEaGVoF`T?xhv3GcZmP9?_&Dqxuf!n zUT|yNvszHg!RQQOieP8;m+Mg>c8hzg@q8f<+aPJ^#cQ)LqQQ+Wld zT+O&1bncV+!b<_ED-LG;zo+7z;U0dfNsznrY2Q6>`<-;6rn9-2XA`ORL3 zVL{3Yjp<|8_;jBH`d>%oR(ReCR;8eIT2Nn?zvFTKiywcSDT@nUP*vL$8H_xSX$XHX zK*QM)!_aYt0|cdwpLdjcO%<&1P4&c@GQ?HrHGF>Yjh0+gRI1juxjVLkdZ(sdMbS#| zu+|C6vV9Heid}PtGN?ib`&qz0>9(1OmcI7sEMz*GnWm|s^#?Qcn8rUENxyqqLap1=ivv!t5pAyu%dQtCz{xp~n z0oDS;Rd2bZqobdLS*BpLaoAkI4&0f?VCJ;vQd9UjY6GHCQOvEeQ%9wr!h{@ZsB@85 zNaZySF;j~(Qa<4vjOosYatd@PdpwS>xn5|b;yA^NwgWfV#CXD7y2X7Ct5>1Ad+qqZ zhKFJ)A^1$jL!{h1bvobXDihZY?B#&5uE+Aka=*#~#~L7_q^{K*Nh%ggnDF}qeXfVU zwB72QVbWg#!NK?rNi2oxE2iH~R49;(vGH$6Hji$Kqub%tk13Z?_Bc?|iN9?w5ZoYt z$UD!jTNMZ8B(rSO;FVW+G3XYXrpU6C2p{LtCA11xh9%gI_PmnERQy+v0v%JriPogf%GER%;{coJVPbk#dUvxnS>LI=Z8G+!1;ZCv^ zZslXNSLXF|VCjh^+P>9_@A=+u$;|hB6;qQd=_%_*f_L8g%6I#49G$J$>2$`lZ9C*d z@Y`bNdfU&nP09+{Wgslt!sF|BJ5vF}tPju&-Orjn3{ZYp0-`S0%j1iI91q-9QoGbF z?UipJ^pae-#17a3T8@GL=Qmub)#1{Ka(LUio=UlGAvG5Ek59?lAZ{P4=aJ5C>RZyL z&l1+Mv`h(&Wc{HE)a+QvH_rRKtb-dtTuc$SybGDyHM&oI&i|Rs(tJ}C4Y2$k*4yJK z)6eGsgrjl|?q>(jbo{XG6agLGgSk{^%;;1PXJ3vVBY3S&zMC}n1qFzo5Frd}u;!-x3uD7i2p7PnZdkZ-hMag_m z(tuzK$8RL?WltGT;+nq8bGe~RetDeVfL_J6} zc>#dE!egr9O0D)Mi)S*VeEA}JV2GU30tN;GlWdbhq9hrtF$9=jN+?|SUXW@F@cpfj zPgVp4Vi~E);|zA(!S<}6$Hq9t^^o5p3AudkD8?uxeDd~OkU#35mXxlZ-E2wIPguG>&Y_?(EsMXeEK644~*53KMJDD1h;!dk)kPrvy*zAVbrJS0gfc? z_|qpvqQ=^1$AJU04`%6Y)nu_?++!!CbSGK<&tMJS8>!b*rzcPnfqj6l`bZ+MHOT)_ zKp&;Fv~>xu;N**^bg;W@{~n!1T8P%X)%3fb<=gwrzy*Z!14GJx&Gj)jVhFU>z^pg( zEm~Vxpr@~9k(XjCOlg(G;Ly-c!I#pJ%{mYQI{G--F5pHYy^MdP;@fu|3sARsXxv}0 zGK=_JK}4fagJlTTN0CLqJhF@O&(eWA*n?2MfHlHHuE%eKO!;W&8%5T8@ne7evUxd+ zv{#9>q!9qnKZZ^XADl7FW(URfjTC@mA`FhRYxM+JNQVcOQLNWK#NAm-A{7J%r73^T zhm-+;sh|k-R;f=dh7MTKBD*fFU#vF21#+m=L$T0d+#8R{8c$NesZU$l2CswiYg#NZ zvv0USONP7L&-$M5L!|;Cms}?Dtv7EzMb%bwRM$3j*F|+Tf}%|J;d2*5fQDnh} zKX9GJK|7u;K}l(a5`yG>JNo|l`%p)_SG+0E@pepYbX8E|JMi(Pt_N&yRg^V+nFGni zX1#%WGd9G*b-T4CtMKlPEntSmXT>ssP-}UGIyA&?Lg~!EX94syCd{_*5tL0U46+y? z9e(bs*_}Is3A&q&^%=g;54#1!KeM8pH@pe9v2n`&@a!5PW?I8{j_KQ0dl(y6mrjMs zC54ae9F%p3?-a3~F-~TEzn`d9_q}f;(8v$ql`Vtmw-Z_%-u+uJEe%dryS#%NRHWL2 zTUB{E9KKFV5y@dYysi8Rvu~!TOCIUW@sDo2v$A=kUtqknBS+r z{o$=zLPSK%3Yi!YEmp8IaOI@uuR}~E8L}~`A5`f4VvRPTB(%Jgr$OkI4|1IzFa|K3 z%yNZozSe7~WZhBs8e&lp!Wt9-B&NKF-iLPhaj6+)l}yi42d>aa%}zs>x&Okezko}r z{0M-=j!IF?cwS1a{Gnvp@t>Yi-ttXs?SJs=+3L+Zs91QCe(ZcKhO?;>@T3=uzsD0a zZWZCD#4%c-c-dbNKBc^ciE6@L2MQ7re%)%yk$?fPAKm@ao7uPxGOWc5KN0eY9Hn5j zmw1c{r$rnr5)=D1Kb}4May<(CMgqja8{!!o1-|`B!FT?V0Sq9M_To^aBxLxLfOBB9 zw2fXP*BjC6YS~u8JRf~tTou!N+;cY|E6FXR*jXh|9wZaZV*nnl0Rb~^GWYa&K2tCL zG_??@tlftXv+0lVJSU z6P46dtCXNhoscdsr6Gl+4-YCuR~SXbmlu6QRTMOK9f*lZ76`CjeC%^d;EGRgma!OA z-$Q3Ew0mJ`L=_wdJW1B2GgLju9}^9sQY=Haj(gn^cJvf3w_jnP&m#pl4jnJlvXb}u z1&o{Hco`$34ArH0?{%^&+_&POjTEZ9xrV7}Q)yzbQ08$zV(WBpeoyR9VP2l{NI@m4 zY`ofvRg=R%OPTC>w#h~=Nl~Hv;&b95uZBf6bpNRpQMEWW5Wo3_- zOOvX%nm)LO?nfp?1(s#kU zi#1SV%CD$*JbyjqHCE);M(8U2)9xQy4-;6O#nn4^^Mlu@*AAj-^{%oWo zDszka4gS7lOv4?Jq0cjZ!u7z0lB1fz?xK2?vWC=7>Ss2Y74qOR}j3$t9=v9G7SZ)A3W?VwTFL;#D=w zRV`0kybX{M`mFQz#XA*D^Ap@G!PpjBYM{Y=yFs0Gq-zk<&Def(xL5Z{cI_=6?am;8HqJ|OQ8Zbwa6-b*nTOqmpQr{@0S^^~> zx>W-yFHX3~-QIJ3{@edT%b}?fXu-5UT{#^%aTc6uUk`;-;Md|5Gwa4vKj&0e@Fk~T zYbIl%8VfgSf6I{fIGq?(=9=?O>y{<1f-L`i!9krmj@Wgl5NDAI%-c(1o$N~9BNs7* zXjsLeZ4X!rSnf(hP4JN|NQ(G*uIJ5lcG4mZcgT-(9?g~t0N6e#VNQs?i8GW*Q&u8Q zqH630#l3wFpu%#g3vV0;UqI-onP*P!OVC)gTw@;>1!S3I_9(`!5NAKjhJ7fqR~$hd z`5Vbc`oQqpOEB?I`FT%(n3o<6i4YMG+qmw2+i2*Su21>+|C4FM#tpd4ndl**YZmir z@?)n+NRKVN2Vk{oPa-xkA%HcGv~m&X0M=YkR#)vy@gy zxHqxPz9f+9)~X|;K9EoVd>_wxp2Ld$%3pG%#aw$M1(vZ%@I{Xw<9hzuLahF+A&l5@ z0l5{)q8^gwg8qqe zV?MectY`EZoc}q^1E!zuAP-O#$D)rHmPA3RZ;WTOmI(wT3Nex@2m_7C@milJw)kjL zEl3Q5y7G#KA8+SNATDqP8NjK#dL}*E;|HRLtXMwf2C}q)p$P8PpZH&-S|Av!y`}-Q zr?Zj?ELg{8A5^kJX(Z8aAHWBb6AhtY&tPJoY-9MHLhZ=D#ag}+gSqctP(p`pXt-c# z>GYF!X^wOsfX`h5&)|jEa}hDEaXE)C^1rc@Q0B;u`fG!~iNWE;P*uG1 z*iS9W66uQ4M`o&epoPD59wqcMtmI!j_uDFHlez~AU(Q!!Gm;$ZI}3`aGd7>lz%pzhOy!T8*-T_%1e~>+z3EA8{iboyx!JF`a1v@ zA6(~GZxY5??i^(;I3oYxGCwF)=hR5Uor^D-=I2)@U!|(Uri_JGC*E%e6D%2+Tj~~& zTzKsnlSYzwWTs-2vD}9fi~e)G)+yMN(wpHs!Dm_JxR4&3Lk=SA>q~yT0DIJ2o4MhO zy>>plU4w<+y_g-xevS@gDsn(bl3p;}MMG1|D0QQWj}!R(k#Y%^E1H-UFGB>x4FeC}@& ztyfiZK7A3Bk!1T$i0EEoIGcT@w|jyZkH`4;xRZi79*B7eyHbY4n*VRL)t16iy+^V| zmu9cjWfgVnvwuH$0Kh6o35y~gr?Q8ih#i@Vn#{Fj-PMU4@=zm9^m?1t>me)~3b`v9 zo7&P7eEoms(6p~pgDfK`0}+*UY@hBwzT<}b-lIa@)z4Kq9=fpqh-=<11*=@gG+>FnPmVKd!BoNOEWS$@?JSHd_NB zI-JruscOMTEIVW>T?&TZD*?4DKc(_AdA8sOx6GQ4G@&W8O0y4wG5SX=cqo z<)=3qWS+;S^sxaQb(vZeKz~Qx)-eh8CZ%1+CF{EpeAVOFw#|7g;FJvI@Cgu)))yRAEX=EFE#(pl|Pc@->2 zWZ7!u|<`hj~;I9Uiy z_OQ}`+@A`)NMCl(2PCSTUsasExg`Op63O$Ux`TyBxLD`xu~I!Fs5DdVcNdEfe6y)p zvN2MNgj<$m-uEmO-ADDpIgOl0LS2T{QjU?hA-#i%y4 z89au7qEPiUSBPk01;QYNmtAm1&!q%$BNX+ieSRJN-jY;T+LAK56oj@moOXy-;3iU2 z>;FcZTIar)Vf$;&KylcqhI2AVxnWR{8sr5c#Nr+qDl30^!>un$Q?gOX*82*$hK{|3 zgZ&slFX9Dt#UtEyMCWxc%0{x0ZTC68Q^>z&S!yTL6goD&*Yq1{pmLR%<2v;OOAuPx z-(}CM2(<4QyB~Aw#gIelytOwWFG_WqxZ>2~`ki<1lwcX{Ips#CyN}d^{hwnA=j&k+ z=r6slH03dL)*jzhjq5PkW&y=!v<5HkH0HTMxaIJQ0Zp_O^*{I#-kFwMYh6=Y3^xCU)R`Bty!lY%QT#6 zW`6wiy|mQxh7IxehE;hy9L9k6O8;s70OG$zciWBNnwh93wdBO zu>|Xo`pg6cJ{>~Z3&wi{m*}*P^^y^UH=yQJ1o@gOkuo#~7I~lJ0VI6U{%4)G*;8p2 z3$vT$uE<{h-uzt6wP(P#D0=&_dl0Ksh1(#)gNDtE z6O&ybp29}VhBch2032QC!e|5<83O&c!$MQ;;^cxg{WN1q{2TwCf70ZWZnN(2!rC?v z)bz(P)CBDbu&r~1)4T9O?j2$0oxgC##rWn|Y{?EI`t>xve+bxCtt;Iz zxEEWw(5Dzlk>H21Lkaic|G)uW3hy+lkq1H^%_) z=JX@tjf8|RZ)W+;#=cr)!+=Fv(C8q-$52sbc)xixWi#~cBs{KC_n7=4l0FHbIjE)^ebo3!uuC)kNqUGxHN8fvM#N099N>` zOs0j#u5k)#@VTs5dI=||CMLcxGU{JH0+s$cL^2uJu;9S8GrW%3?FV)pmJAsK+yKN) zwfPO6N4mCS?}$zuUBYue%C+qOMbd=-GrebR7_`w!A1Mgq4253ZiG7lRbmX|QJug5< zYhu!Ja@~(lPusqqa`^Naq%$3Sr6A_TWJ?6LTY&p`q#*F`7J}CZ(OkJ_NLJNw=vS}c z8_!Ohr!B5Tk>KBRrAo7;=}7@^)}?t$Xk2%@DW(1dj3X0AUk3dPnRT#5(xrHop7!^I zWq0gi9mvToiR?yZr<)i>^RIFRE<6gUPp9Y)A<8a12pkKYC2^(t~>#&|8I8Q-w29K(N`7>JlOK%gtQVs zAybs^(m00vC>Q`9oms;%3gdqei;>w|-6AFm!r>|zeOd-We30yfbic(4%HnZ(V=PE6 z5UU;s*&9)5BZGh>rR|wsI$(<&wvooeg5Ui>5{#P%KMC^*XmwV79BFI97N&%U5ob7JYm4FK*g90VnE*MFNHKIbF+pKJ8BBjN>EO=Mu zr8>qadhLSPs7VaXbKM7ecTvGokXZxd3^Ivc1NSMwF2A?ALDCt(H4EKJQ)Z*CuciQ~ zv!A*XT?@QfAP%Yt5rG3H2>gII2>ZzUI?oJ~|Dnyk^X8JzD|dSpHsQ_k^AC6x4ujw4 zRKY(JyKR8lAd@GFG%K{l_ut~c=D2sr82Pghd!DXt3+0s@5LzlAYPV5G-jED7(f!>6 z0(!RK*bl(Z_xzJCyZPN%zzj*at~gq4)F3zCwB?yfRETY$S{+==_15@6-XP8M6KUWQW5#@`UiiQmBBNQnQ&C+dw9s&rU8{kaZpg{ zOr?@A)!Y4jmD%hTNV((`C+!$m4Zh+Gtf${1>PE!o*QgkOL-&`A8OuQP;Eh{`;m~-W zFalkaV--qeTY+^|wyg7Tgt8NsW4bWt~>v6iRsmtNRKln@DNt+i3TuKt>i+0 zWAq`%WegDhfp%Owq%QNse1|w3nUb6h^n2o0XDLc8A0?Cp*1R3*A6;7lE`MB zgUUptdfe#Mz$}B!{B#jG6TZMpLU*s!S_ayYWH=Lf>0*{dINyp=YG)*i82X=La4Gme2TM(SP$DK%7J`Q5uJNyP&l!e!NYnGIAs-rf6jWpi{Z&JV-%nN|ZE3t= z)EKV&8Q-F~umV4Uayc;&kVobp7C}kqbzy(b&T2{G3}!1bwVIy>DbVjW;8JHT_f@M2?TC-RrMh5Pezd zJp(_#vwy9(gWQt&-T(k3$H$uW*dJ;bGKfT6v+Vz`A{?jJ&L2K9EO`Mt*G$g@&s>Zk zIt;rD$P0n^R(&EQPJQIuNwVp95)N%cx>!EPh$_AT6@Z2**z`cLl#e1{;-9kzQR!D; zfySDidHn$`zs&t?ivV5~s)H(tU|z75S@C0U-$}p!yv9Nc!lDrmza$KB z)=?}&QYa6(OfW#{7%brKG0RjYuL+Rp!J?6tKAem?jdp>BGlB2`s_3dm!OM4mgWCPr zeX-@`?L;}L!s?248NhF zzC}~|3Z?3f5scR_N_ zPV~ZxK<)4)bE>N*@=84mNvXsNC}n)8jBn}{ z15O@GTIwh>Dqx0<)F-2m0W>pDIV4jfcESvMK63>4AvJY?K#yEnCQD?4^Y8fdnqbG* zRI$iPNk z2Hst_H@4*g$ERX5|Gr#&9~ zJ-n)@WCKnJ&&-7v%U}wChs+a=<#UN4;IYl)0EfgO%&H^su9g2)Fxi)62U;F799bW2 zhgVp0&%%Qck!L!Yz?<_m`GT>WRmbO^Zg8~B5-b|8_Zk$xdblQ!@8j<$i$WRCC9^*P z>Wa$Uq<@Su>%jt`&B6yA9TaIoW;+|K^(q!Va7}vPlH=23tW&V+>Y>fS9hAt%AZZ7Z za>f~Z%AcRcR*US$dNNj5nTY0es2R(Pl9A)!1J6^v$RrY4n;3;pQ_>jMj$(-Tu{SrX0cx^HHndHUSBHxd?8fK5CFQ;h zpx6|L0aOPz_foI1Ku+2&#+q$p3NEQlIq>{ zuO=zzx-i?&T&2peLkmYZ6#2GH04-^2z5Sv?meSCm#OFO}9abI-%hcj3Q>Ko()Pcf# z?p!vXr^jmLRW=~OzGNYV7nA#&P*JSUwCMj!y;f*0c@M$g zrl)*0rGNCK1#HvI^1(VtUIW;sT)yI<4(tc^*}nC$NX4zU0XZ4oK81QJ_f*O(%ZhZI zo${_DlfhxK2{Za)Vvjp^C_3tzEk>K<`2^uBwR@Q0S|Ke03UJ3NPD%rRKUK7@8JMrr zPF5cSNMS8Tn!oLwPqtw|6~F$V??KJ}BIXcOtLAur3eZcT8b*SVKKCNP;;(ED@kgL>W_2= zmx=w5y+g!t*Z)Rr`h0zC(_CIr?e=`OCf1l`3XFRh{nk)`SwvPb|EoK7VG&t}kf%_$ zAe}@Ca!%?-(E#43Yg*sFcS)*5RF>qi*j|BMXmrHL;cSt4xZ-YLJf5xV)a0sH z?#B&Ids4vH_GwUvnE8Ydb!hTP=(nY2#V}O~-Ig!6V=;ee86nbS)^_FB=d+QSo!CIb{*!>|uCesE zi-+#*{ZomDz*Paz+w)dIuKGi9q&ZuCy|{MGdF#y(XIVv7bMpAtG2$0XMPu2C+PX_} zoHjnj9FfR}leX^k4OBmH^Lux0tGj7|efkd=ZejD^ib?gg-MK#6be^B?AE{aPy;)WJ z-BBDrN-CV3O^qc2&T|jluiL^mkZ0(<1dDbst8c-S{}aAbp_y@Ex!%0MLVUe}kzUL)Ua0P%s*3XpXNxh7A5;MX(4<8!% zgOYHdqE{L}G1mro@kIJVH$89$A)NumgJoK%7!r*8d+90sPvsxdd48aLf&+TGIT(=+sL>n``tum=(7fat`+}2A;?u^|Vl7t1Hp|mlogJ<83JX z(BDd;pwn>hV;(rlZm~<*hCK9#TrxJcns|I>Y>vvRcjBn@rFeBu-+!`q`5iP(D4l1xlY3*I`CHxyS8 zrJLKr=qUoY%smzU1##Y@O|Une#3q3m@6TPp-e&uSi^hXZQ@CgNf0eau6boS>z{2<_ zBaa}uSZ{0AhG!BI;^-hDRlE}~5XMUkYF_Vc&PSgq%VzAuk{Ff%9*rDw9nI9u0N7^`Nh$hwv|MST_Q9E0?+K{z^ce(wSePf_2sDj?oTsrLJI6NQ5Drkm z>TvhZ*I1_@0HylbyWEIzzVTU+SNR~QrF{iNOW?@SHC3jHI2?|9+5NfOp~t1F71Yhq zv-AK&B>@=`UXy)51hTKwb##5Q#$I52L-T(GR!&SrFiZJ4w#Y%-(AJnwynP)qc2NC$ zIZHht3VM^;l{U4L)zyllURKyAOlk{{riPA&0hlb<_uQiqT^{sF=2=l98qzyN4*zv^9K9rloT;zqdZJyD#^1a$9qYqP(v^Iyx+w06 zHz}>7S&1l-`n;`5o6a=CXNf$W=E!^t{Lj%`T#AHDB`L&(W8Sjh8uX}!*OBE^3`Fd3 z=RNqM2UCl~0h=k4F&G9Q@QD=61gewN_r5c@@vEL(U$(Zbhgqrsk2uc>*-az zR+Fjf-o98u&uou%(YkxfD7<4c`DxSV_-o9oYS&>3;3Bx6%s3XP^lh$yH`#33HQh=$ zpTaaEe7mf{X6`OGjHU94Jb8(9#&0}T?o5)*3{r}5Q98{;eIbEo7GiKQN1HaD$Wgr6 zmHmk(Z7INk#6ZIbB@Z0%$9!TMH$&1ElH=<;r9@*5z^0BDU-5-6p-C|i-9c-fBQ~wg zEUGE1D)wr~KVvIpy1Q%oH2{Pa{>M6DMbmqBf7Fw&qb<|Al1<8aNJSm|Gd$m@zh@TL zg>lxAwjg>a^dPCPK6T{0dzN=dk$gqsMZo*jaTdb zd@Msb=C%GjMU8g!xJL3&=Tz>ZsC-achAyZwr)P7My7LD|<)-XgkRz(ktX@w0G~<9z z^!qhW=u?DNNKfXfKOn;?$Qu5e^;(yXoii5G*ho4*|2s7m)T*GGuf3TA{cOHjYPCMe z28&6Cb#?ufes|V)w>4;FaPYpQ6@w(mdEhST6T4LTp|CB3&zscO*BOv z`B@MDsMXNVAH6l37C+ozb(=Yp=TtcUSh3H8LP~!fz!`aZy*LYWIUT<#gpzWzbBT`i zF}f#6;P7xLADX8g%lW(xROKpWheA|d5QiDkV8I#b#X*+=OJI5T&ke&W%-HyM;rP0p zo&NPz{Fg4M`*qa?v9}BZ4hHn*XK&KEsk!ycOj(Xjx|>@>8)2hlG6OXhJl#)DTJ3D! z5g8bCXwIY*P53s-yshr*V;%K3o<=a7xJMzfogKwtWb&Tjh4eZyxp7U0orpsY4oM%o z$Oi4gyw!5wrzCu9+2h(D+}B_a3xa|{3RU;-;{SoSXM+9<$CjFV^6R-@aVg8w>}apX z7C=Qb4hV5)H%2$%&9}4T>B*nqE0Zniz0HBsJa)v@&}7V91$1L#ljOau3^42;0-ify zA&o?q`A^SZp!!7xHL!>5f_yia9y_pUF#qekpVE|1ec}0ez*7u8yFPDIQUs-lIf&r% zmmtf{>)Lrst@7pytd*+8e%r(#;V(ioGZ1NkcSX$YY{AIw-pktCLP(B|;(rJX$A#%% zi5@NZGDKB%aaZy)2slPe(GU7wO!M7J?ac{{TzalC|7&jU-c?XkoFUOy=<_CBLeIPY zl}O6^&X2Ct(JI#*oGmvN&pFmsf0=fGA|=1_-e5*S6J9Id9JIw*BR~w#k^&VoF@yBg zZ`i??FHNUMZGiDg-R3hQdJc}>cs+~$j$W1u4^1}cx+C$Z+CUBh!0Weti$qi)t{k#h z5kGf>!GMc=7fsyYIJcdfXtoC%ek))eKje$hl>;a>`7NLN_%2!#GE}j{OojvrR{>Hv zZg0AxZ=WOdoq}$RJ-8KVy&D2(!v8pT_T|#klcG$Jd5d8f6lQ=qkp+CmhHv!|i=3{s z_nw--8yEZFp9E zdaUa3YV`DUS)K{;lU~1!7h!i&mo$TSJA~#^soE8ouPuaS^zYw@J?WjE(^HL$^Yl{o zIv-b-#{XoKJ)9&|_4HJ*mSS1zC-fTIRKA6(jFdUIfj80rPje$t#AP(5{5(U?L9}4 zcq_{rh0hg41j!Knr$oiv5Qe8Gd%f4YJhAfHYQo3mCG=9KZN}>a<9I9RXxa=FPE(7B z3ehO=3=0hxlfB)#=`r!;b>Et_RaYt~)yEkA=!ZyhNtrL36x`Mi8GkN-e&kD}D}6Ok zHi^K*{6~nl$`PRC9Q!iNT}r)WXcn@F3`>+Y%sj0KO!*wTUYTg{BWNH_uM z2%&w4M*+?*fZxx&nHY@0Q%CGiHH(tYPEmf;R9X)-qdLEer%fgO>f_^*j&FQjvH=5%NEY0egJ-r0vL*!ufg{*MC6eFBQmSmo9e%oY!;lAs7vD%6tw)Uc z!#{l<0u>~Z)1s%-M7=D`mO+eB!Q4jy5R(g^@NFeLfQFf;sS}H1A+f!PN;fgU_H*F% zwZ6EffY3=>?ZTVs``h^Ku&aG@C6HLpq)boZzMV=@LT`?!n9DahHnjp}s`slF78Y)$ ziAxaOnGhMqRZRTv^=7O8VV|cnH9HfWoP2W)4ZA_Onh!0c$#~zryGIrL-okd$s-{ch zlbTvT_roiMnXszr`P|>2KVP;d2QcsM^$#wr`wCT6ohg+;-|xrxOL}?XwI!rB4h`6U zDlM^2Yff0>u5`FIuhFVGC5?G9XxhJkFy~LdiRP&sm^Tq|HJ3jvhz0j?@M(kJOnZ@@ z)r2}7+?2x?78@JS(75iP231n@>hyAR*J|N#f0Oa2z%j%2`dGR5gLF@|f%lNi62_vq9eMIe=>-5M3nCTVBbN={aag7nJS=kQO1FDZHY zHPuoKb1q%2;q9wIb#+)<;=K`Kbh?7Q!|l7N2_mo=LH_qVY(rb#-`}S17SY>?mp=1- zyX{~&>+W^gZgc&s3^Ho~uef16NDM|VB7IH{g`~OvfK?6R@}9Z5=fCSajmyg~Q$5&aEr>C22>LO`nG%%zn)o$!Fs-O0)Ea ze^RrcvZ{(8dc4+Kx$cYb z^zSXUTP6k5X*CwF%LE@i+I}M*T#4N-b+bgqB_$z1tNUeo{PU{AJD$;b@enR+VHdBN zaP{=mHa@)6R4H*KGMey<%n2#QoJhiwQ+~WQ^Rx}m`@vjKDk(#Z*r?fvE{Cgz1{AtA z4UGP<5`pWO53`S#quzX=tJ8Bgzq^d1*wIq0Yi zC>YPU{gLk#{xE6vY_UWR6V~qPP|~^NYk$MS98B*jKO7iP&`ZjMf0+_?X2jjv5{=q_ z$VI1nI!@N))OkR<{`P+TiYl%2d%A(byrDs2YdL24yzW4aHdB!I%bL&TR20;rax8hn ze0tbhwqXu_1vs=B&!X;Y%?<}yjy@J4kGUsVVz(jYdp$eceJ?9{gOe$$k6%U$8fV2p zQYZ14lJO99rYjo)H!9|Pzs>Uq&S)f^(?G9H+Y<2yhFM9L@v+$TE*?HQnhXOYav-ZR zU(8)X@xR$9U;*Ld7S}uPDBUD~)IVs^RgPn*e-@I^d3lx3hbR8Xg`X|ey_@vdg35IV z?!lyxNheG2tZj#d!~%roYiJG;Z)Td!5vot#j-*l%;Q+^rN|0^SV#SqI#nF5s6f7cx zI6T)R=H$mTo@eL7V|G%k>U%aMuQoVwr`2a;mtae<*fZuLbilFf5_0N0n4mpHMT&r5ON1)2N58T}qSql~ zulE`*#N`UjBR6CZo#-3iP{mQ>q;>Lra);=VJNaEjLW~+>7lb~U{nFYOijocr&Quvx z8zPR2BwR^1m-2MebxiAs(8gC5{#1ao#!itTYW(`JLtE#=gi@r z)SWKdw(@|{rmwdqyK0p!GoNAo#TC^=q-ER3qO!9WA3sQ6{Jc#2D6*KjKVA{`=CYF@N8&#>`522dk4$g{OvGo#7XbF~hoQ8YT>&pYY?v>GSixFlUJ- zk)*(m{POEq-YHcF>4#t52+>l64XxpLG+Nl%E#qD0bh*K%Mm4epa|8@UXzog@jWRJ9 z=8>RCV~pHELuyY{28TEqS?MeDRLddg(H7wi!#f{A!FZfd!=BQoZ}tr%2K$YeNN__9 z*VlQ6`i+W;_gF}JFzNQ%cXk>&gjF;oe5jkZs7$4M$Hu}I+epva#;R6zj*j9%9eUi$ zo)E9osBp(m`0q{nzdqj9)2 zLPb7X5GU-FjXG?4#i?GFZZDyhJH;&h7{2SUe8K2B)!HnB($+%w#MvLIm%yADu>uP) z1?Blwqnb_;m1?gPN+sBa9jwt+ySUa#&cEzS$vfy|;Q2dDZ=!~^gubofV1IhYTb##O zm(l_!95%$}{iU!lZ2J5(p?}tOv%J{Mag8C^OzNf(?pgD9G`s3RJ^BG=6egSPb6F$Y z6EqjmJm!L#Ky`z)khjv5;K42zqk-wTkQ@TkeYphkf0WaIv;-8+>3igAS1qkuoYkrzdaW1FW!EGY_>Yj!mG2lsYZzL+6D*v@5tr% z6*sI>cX#Oo-M|lyFlNIj*CXhq?fHVbJ%;&L?xiac}rdB;$vJ z@v+wDPY=p57FIhEWCONWvJ8|7Y7`zSUYkZ*edIq)H&g|qBb$CN{$V$Oo^2cUI+P~P z|EpD5{J=p)(){gxe$i+OPHi8Ado=vs2p|&74Ti}uSRf6mZ$sC$Z7LqqJ+$xiX$}9m z($q_4+lIpwtz}S9i-=!3Ndz)keZrGb@{_^y4}`-1{3xk5 zg)l@j`kDP&?ZNF?4U{O3X-VFzY$5zf$oWob7!i9FIkhk;{G@Q-vyE=(`>f=aGr?nF z(KpVWleD3&=9m~n8EF2c;$%W%*&%C=b&7Ml+7Z@s+xWUR7=D8~Fd64>^iE=OR#lp% zyBwfO*2br)#dlXrq{O$^f!FPb3P|2Fw}b(ye8JU&Pugbv>xVOMoP+hOaA9prFa`)2 zdt@lRqx;{58tkpWuKTC%ZSRH>#vYkh5l&3ZX89U8VacO{<+_6w)ImU<`qQ>zmi9^h z+xEZrj@;YE@1bVo$1?dTdcg!O1upfbuJ-NiC!5crP|&cn{96_mN|c}lI&KO5QZPaJ zDE@SGuo$c#c4M&o=y|y7M>bo(7rTrvJ#VAAPLDj1sv)7g8!-?!|IKMI;2!+!65wSBqoP>8@CksKx<9+n6qV+kRu%f1IL zV6HNL{iM9h;D;L${eJxY32kO?MH<_2Tl|f|<>U{e+u`xv zR8s)`85ydA;loA@kb`F$tc+ePrHx`cLu1kDn;PwjoVck77Ai)8Oh(2pU?;-A6uMl{ zg}D%YNw7*Fe&W`R6yz}9LJ!1WtAB2JoqHE~OG_LFhysv(<%?x11EZo5S91D}y@@DO zOM7BGSrk+*qHf++L`9BX;fSk3d;)>)>N%aM%PqfY-MkcO2Q#Kubl-}Fs;n--^dgxyn4h4Wn`ws_m2UDGdJ|X= z|Gme0Dx1^FfZ_wRj(N-DL`=P{(^e+V&x7u}9ij0zlPJicE!BZa!cdNlQ+wl5^*=#3Ia=U{lMm)lJ!VnW=qe-~rQM zDn4JBnGvsDr=)lsqDvY?1B2`Rr!L#qy^!KorUZv*Z*_t~mWV$Yg2)aV66HIecJS=1 zV4heg>27S%>4y!+>^ZdiwH=tq1{rEm7LTejAVqrB_tnu|l_Gzwd;r;3&M{&bBn0qg zXbs$rSMLe3W%x-|$2iTtnGa{jXRLZnHbCE*I4;CE)JG=U|K9h$RTqv&KMCXMIKI#* zGsqbbK}43M57d?ghn|An&qd_Ek|=vClF#mlGx4DDRQp#>n77Msxo%h} zYW#eZl|k+gF|zF|_XP{h_Uh+i%yMkN#TVD8u$?F{}_Cn-MiOYLCF0c8E2RG z$JtCd-VZNPiDB8#x2q9zw_%U3{WD{v%eoJ4N2d5*SV*Aga_$RdG`Be~za(_25?W^qFuq#I7cQ)}nGVwx*p?=-E2zrM1a;&$7~ z7`eyU4*q^$3pdu^_NROugf-{cHCRC38(T!6f)5{<69(ssxarnqJ}?QzXf(Q!DDdUc zELAniZs_-$$gjcEsk=YdE-!p^!EwO2{+RY)H$AcLc;M@i;?eW^GlH3B9q^!efe-XL zN|783xw5j{u8~r6hFpX#jt#sVCl^hjE8QK$?g;fAeox#W+mW)IS1{3HzVV4y((JB1A4u=qsI#ZKR# zOKV?^#nB^bsAY4^iDp5@;Eb5MnF-^RR>%*`F|Y%Ow@@m9L?0XVe8^7!Ao;Fz_d@lL zceAHO+=hLR?Kx+^)sdNdV1&P$@pk^5N75ObRX#=8aA`sz)k-#Ph!LQy2#rcrw7%MI zY%?wAeQC=v^S#h=>`!*zTasMUu>r$gVQ`O{Mw|8B83g9^be(L}ufj>^q<*PnN%^Qd z%uBE^HLPW_31Gp%F7YCu;(9AK_Lz;GH{DtJWeTGySSN@kka5c&QDUO zmZGvaDBBmW{Bj7X6fkkNsPwGPgtlN7u3Z(=0tFK%kXO4DO}Sr{jSU}^7Ldip9fW^z zR0$WBdkB+xkNx9&pz-tZSkvLi7{k6_S^(%e9@){P@%D5N)Q)W6b#|_#%*|YV2+mr` zTOm1hOp-sSR8keqeKi-V@saS^%|E`-kli|SrG4gZbn;@`0;?&C?(#+UOE_f>#17tyaOQ&6Et&@eQ^4Fh!* zMzH>ILOAE~@q?$d<{@Eyf{(rmo#6M*h`q2Y{g(F(?JEu1#G{ohYX05XwT2b*$vo~{ zA+g_(w78CY5P|U37XaV<;eOT8QBvt>@+z*P$Ux7S*+iq5!=$F>nZaU)t@)ep5;4zL zbc)1|gP~!MmK?&r8*~-y2RMC)V(DODVEv=uc75s(drzG~8K*bk@g0c$=)cnZ9%kk% zbJ5cba#p0j8a0*RnG3`A)%c>u%oU-uP4C&z%8h*lyN;ZVG*G+c z2^+D@o(VuUR)mQI(9|aVLO`P#p=G8{ng2Odqbd8EXyNyq0M)fBZN9|*wcZr}THMpt zzv6FSJ9lO>|GDT~VEKI`Ft+iD_J<8uaiEKuheb?q$K==KlfF0Paea>86$z%g-}2*P z2#0)onrS<==`~>0JV57I-$EE7DhM_~5fNmXuxp;KNWR#se?ko4uX~>mIIj$$nSqMd zJ9EX{rLR?gytX{a2+B6_d7b!q?{Bh%*D1-t6H%{I9s5N~?^GwJD9EZKb20lhnTm44 z6P5!Q`(SGGK6jDtJ03^#L)lj0Y`o7UY5VP>E>H&>)M6C z$7=(h^qh~pSK}N;X@f=zv(1?(%Pa zA{ic2WAf|thB^JRq8CW^@suk!7%SAPen4iDIL94VE&DLWPkxI;HO1RMu1`={xbSq> z9;m&klVa#`_J+^p{rky!G-Xd1zJ;)Agp61B2W!`TSKEEY(V+752e{GWdAR=2Wg%?LlkbjI!~G>&cIZlaj+; ze`9o9+qef)%IgVff8Saq*%*U6FT&nLH}1DtH|!yRHyxIJ3aHDY8u092f$GO=n3P1&;6v!j#i339~9mew;t z*ju6yTAW<{+}+{VKfWvqb4_K8oo(RzD319}uduI1inWQr89lbpy2#j3pb1&@?`Cs3 z#kQ1xh(K2)g3ajm9&^?%4`!yf%Kq%OZKQ~w@Pup(8G|cYP+^2*6r=m23LqzlXZ$8L-szDv6 zCwv?1D0g9X=UMA#WYP}b)*hRm^_>pGGN-xM%XXRq|AxI3=P}>bG`Z$*K487vx6fHH z72dek>5T!k(R{t=a=RDP3K=xUH<>d(YD_tdlLP>PnV_h6j>-5%v&HrxxgTB3Cqid} zhitma2`(gN(MRwU`u=V7*H^GmMQh9T{UD|vIum)1kC}>JKxYe#0>HJ?Fx%6Nd1A-< z{Rgn|D7ji|nybhJt)HkwfRUL_5kAJn553y9p>?V+TPT((d)>#|G8O-BI+KUPHQ!iG z^Y_&BmoZztwu9g6Zxf6UPH3dVFW1kH7Na!*b@GyGa>D0B%5$w9S1$*03FwtXlu26y zSNcIBZs`1@ejZC_l@lUu44>fq{PmAy&RT6dvLqWvnjI-j`ax#TUjtT`vFGkfDyy1s zlHC4DZI;f}U}EdItxU-3;hYf*BR|uujnuD7IrVHoI&b^+p@?zGXXWQHJvU7tgy47l zV|9z&+nlLdv)8~7fAB9QLmMsNs3|58o9UqxTnf-N4fJt9o`gM=fMP& zW9g=FB7$N&a)9o`)a!E$aQ!i^(=qc=KU{=;3|Bb+v!XTRRgHs)gruaTxcL1L`7)zA zv?3G?4gf!inxi^bqJ{|{+w1-zuOH=!oX?%J4dMc)?>QsODC)@8>U#E%5);+5kVr5? ze$;Jto6Mt_-bk9SxG^UEzR$bZf1kGNW(5oJWCGzHbKQhCiTeYWdlH3X zWrZ0p#drWCl2x(!j$(Eh)=e1-DvZ?h$Nl*yIr?lztAE0P9bMmU|8bTa{b^`wS>X_e zMIceBc>8m>;1d{Wvpq$-05;K{$04Hg*%8b+cjhh>@&xw-53f8x>e!<4XJQe}(C_by znb;Q-UEi~LBKX#Z3#F`-ZWs`h54;|CMaH)dp4BF(gMua|?{p!)B42ezgX17UG z*L5du)&=H2^IhpI#i34pa>I1C?6_Q&H7UJyY5M+i(;vj2fwCCiJ+bq% z!JcL}jiv?Yj(u84e92Gg*OzH=)soY;o*CcP20y>}flEE`cv2)Fw@~vp)*@Yu^7*YtaYG`S9rRE3`tj-HFZ1lA6qoXoz>D zKjd>u#G${zQ%%4UL~_Z9-TCJ%bYJ*E_^Q|_Pg6*5+=57oLEliy&-i>ElZJ*O@DMpc z>p$I^KmQzevas1IAEwJ>;RF7yZkXT3##>BO!Jej*&ld3bkaoVExjOq07&c+>2l!n^ zd2}sS2?nh0T zQJVI}eDZCISR7?**5cCtwuz4rHsrf_YYoR8AJt7tzH!X&6Z}BWCK}^!tH%JsPmfA ziS1+*%+t2DYG@xll1fd<5)9>j5#QPnpZ6DMBkdrmV8>q72V8uN&f%57guyJm`d=!C6jU}4h@$IUJ} zd2PdizrolmA$%fIk^MI3MD8cz{w?@Sk^6=x)wTC0OUT*ol{bF24?%^x2beI}Ji~=1 ztg79u)b_tU1%7`QaNJ_{c1A%t(F=Ml5NyU2!W-0yiS&dV)%aFHUL;%KwN-@J4|c2) zD|^ddv_FPZYbRSgWEa`F)g8M6qXOPY*2~Z5bxh_I7opYvV)8bx#Z> zhz;EeXnz5C$n->3I;(}B_4uP3Cv8`kVRaGX9MBG7$sRW;RtJQ^4%A@hyt?3#=Mq$B z$@_z~*C#vA9FwD$)jLh*yT)Fs_CD)j^`3RlrY!2~Cj?3aj6M4^|E%J9s?!3W&VH`` z+v{shjp&2X;zvucagVmSlr(Tyd*YQ5p$uFWMxJF~z%mw}L?d7iH>n_@R@Uobs`IKf zzAMRzpwtUfvX%r;iv4w}@+w!TB!bC4wwb!J2Q61uYttY-0xtk{PWn;(%d5g5o#FeE z*AKV;tgZ&ZbvbgskAJpx;Nw$RO@!ZF%*(2^kA{SZ7T9me4nf|nZVFZbcSg+eJzc|k zi7OjP=+J_Ab9Ww2{KM7eX%lmk=R zsJh%fNf_^nPua=uR)7I=fgV&_4xu_Fb#9Kq1xA4LhwJaKtT6}28%h2UQ;y{H=6=c( z(rK;f{dPR0gVC#fDCLK|221$U8Ad%bXTnZwrc@E|->K=%5>C51#&YaY5UG84b})t9 zz}rjgqY?sZM=b){EKr@B;|*&~)fr~qM;#aZ)B|I-L5kRKgDF1()1p2RoB-#AuGXlE zB^!MpyOlh3(4ie}4u@4=&`>E4V> z>y&#GXq>!!!~;8v+u!Z6TKLL+#_kI(&eCB3yZE@#s*eF~mNb}>F)j1*4l?|JJ&p4! z{iYNmkmjC8bmefzl(?X1LXrRqx%1awicJ{=s3=HZ?K~JMYwQ&Id?mZCr$@|>mnz((5dGy_By4Q+uuijD8&XQiS^d6 zylsgEa>GXMq}=GEi$;0xoG#T$r>5TwO1p=;Zy8v1$)03C7OT6v0>25(t^!93aMk#@ zffa0)lr72MECKkDv@NGhm~BvID5K_3vc~)I%08;N_!;3$|LK_asAV_m+mXpP!0=hs zDL`G-*>t>`)`#y}*7{c5>;^nNqo~;9C6&`1=LMPv|K=D8( zZpYtogjdBK`Hxas?=LUVZx#iIoa)#BxXA7};|SX=d4%Ic41ALXYQQTiwg3E-S(Ae8 z9-+h+d?;kCcKGv#INU7y56UzE+vL)gk80}-x(Z1(rV`pj&A$?C9wP)i?$?u^v72Jm z?g{6(z_0QnH@S}$=?RBcSH)K@yX`jR!pThcS9T<7b9tMvqDHqmPlnc|kq+(*iGw%` zDhl8Pq%g%+(Jr`4x%GQ|GmH(lsY}t@!eD+mF!#@T^II2~57awGG02ARk8)QVd}ciG zMm@DDA<|L}zxZ?+Gz{#%=Hfi`Y&SZ6UHB?1;Y=n7{?le!uDTbt9ZRS*u>b$D^_F2# zgBxWbR$T&bPWTFj(|u@OLr+LEdqi_N_Tg64x9&l-}AlK`Ht88 z*dTk)6Kkz!#eJ_0en5?n!RQWYVP2h0>91dN-AOZYw{xf!y{Yv!aBNc8)+`i>U`+27 z-*){dZ1QrLL^2~E)WzEIsGD_8-XSM7aY(D$w4`C#cxVkVUO?$4v9LqN8 zc^O#DLEI$6`+%JwIi;hq@Y8M7$h7=_N~fQ}zqGUnSz5g^W5x4o+)zpCN^p{LiY4OD zSz1b5pFe3GO{@2ar1P!mD|-pTfEJ&JEnL`_F7}%i+#dB6KO21Zj7yiaw9cFNWedTd zJUes@PnfLN^7dN&6Enf;(73cvX_KwDIk3_W>R)A}2j{QXCy0FifCnPqD!S=_M|xL( zbeSoPWkH-bpWehCfcDmntpj#h!yre47JIY&_J`0TKknd*>csP`cvq{S|UkhTr;L&VZ9 zQ~VXt#@Iws9jK@h{)+O=7r#cE3%eX`2|O86ubHl-yS+)hge!fE{De(a8Y61RaAB3Z z9DRSV&FVE=*#|=KB`~_T(ZOb6$87g<4;FZ{UVK|p7R~pSPdb`z6OJn2kIBKKIy8us zj02Dohgh;LI?qaKXx_Y%EZoEkBcG^y4aLwG@g8xW)$AMBxbD!aOAkms`I$0xb5tYv zT=e3YiK;QlakMGIz>s- z4t{iE*zT1#93AbP?exH&!Y_Obem{!OVq)!3*AAoPA`;b|JhXjvB=gLEcj7bb%4W*N z_iCu&<}eai-4b*JKyj(5Kjndys60)fTvUhZ{#~|>b zWGud$XCQvYwEvf*QtlrC3G){5<+7=QkS1!pdPeKK?G^E;Njc!VCI{++mv7+R zM@M8zzkNJagc=N(2!!^@=(hX@XNz!|n!Rz+@D!4e&S@6zxgw!~D#4Ag;{PeeMxzY~ ze874J2cdn>&yOFrPiWKpY;ZuSG@zHcN7(oxa(l9~W^MN9;-gtW^-*gC2IYj`@*qVW z#HF`B{p;CUx^oj^hRfOCe}~RtRIJvy|M!%ecwdp_D4P$5HAprMoq}&%6Wq%WP8Gq#1ZnGs_ceX=}%WhH1wN^Rq7d@Uk==Cfixb+0o8&W?cIZ8bX`o0Kq zDT5AS@68mdCSP0sj%r;Wv-QvAb-|vi-$PnEZ5Ye;*=x%-{%pYhs(5(jUiO>?g|s!M z+qb8dPg6ueC=)<4_|8&06i%c!e3- zui;!@j?le0`+F9WNmKZ$JrA=V|A56G&X(hq6@GFoij_NKKC<;}vc?9rv+Q2g6s*=q z$iXA>-xtVD{yiT*0u2z=pX6=Ge?7b}t5!H&tnFRIC#K|?pgF>#=ha29V^R2w+3S_>C;3k` z6}ruNO4m{m$8EwFpZw4hY@)kF?VZXege|M#+kMYBA5aWv0WUU&2@g?3!DI9WXiecJ z!TVH<3PXi4$nOi32IGm$k+YOisg##bFOq4P@BqH%zpEsv6xektoceMYs{!>kJMS0y zfNgeQB7D!~VA0Ip6xKlUx7-fk44H!@6Lqv-b94$f|7>33$fwWFKOqhfhPJ59m1~|c z$E8U}hqv*J@Y{=*#KPLO1B}ZjHOm(dd+-aNWp^Zm$hpW!D5Yhh`rSthk~{=jUQK7M zJn&+lB|Z%$)4j9I`UgbfDl56a_V;57Lz9*X{Hh6fY&nS=O0Xp+-`6HSVHwuSw`~g> z8ygc76AJWhE8X$3u{H{*C?sIjUF`-{*Wp}^#wTMfmH$L>-|cZkU)Qfk;SA2zmzz#2 zy`M5B@cEKZ8Qmpa_A`x?_AhGuKHbpe9WMEebmDB5p0C1n3wuD8pl2KH5R~yj{<9&iC^8LR;X%=a@q7GLj0FiJER^PewhF8x}}#z{p-iDURuMRk80 z;BcY-(;*)L{Avd`is$Gq44{GAp3RGq_{TT6< z-~qv6rn^HGKX%c`Uo+f6952C1FB_Dz}-LhH~5q95j9FgbiJKRXY_L?J-(6&xNWm# zi50?28(HwK2AHJ3!PEP|5!{p>8K51;gM&Y6pC|;LpU7Kd&vC}qW+ONTtc7^^zspd6 zAxDW|KS!9aIzW!O74J@1b)83-3)uh-a#)-D_lTuLc#5AdxaCo35CYsj0~Y%(d`ocT z4Hf4vJYIGZl*{onPVs-WX)erRX*g zY6spW7l!*S@Eg5iR}?9L9ztK04t~-s|-T+{Fl4HU4L;q-}a(Gaa_<=9%TdwSrBFvcxkCo*?xUna{4gk={KGOf0c{;Pf?+*%bf@eiAA%$bg*` zdKF|GM;#SICE)9L`g}8FM8M+fy9Ym|s_XUG50;k|L8;lvd#7oq>z(h7e zWl?+2^46!eU*DC~JWPQO+mn5rlvi2Jn4M2x6GoTTL%qVdqH_BN%z*9vL=GwKFyU;B zV*(&k^dP{qhezZAKbb4O`pD2R9V%sLR{v(?hj-U91*ucZFY+pV8AV;}i93goH2KA? zj8Y=RgO}v*{C3X*3pVJk_dkhv-JDT0{MF)Vx6Z!xJqQC(w7w_QWFXoYQ%1Vp_Y0M} zi3ff|;s*gqN&sr>h0F+CVS+6qtI-E%mRadWynkkTh2yx;0`S~_BHgwTl@oaj`i>L#t z)RF-5_3c>u@deF=^47q@CozAr+MR-ls$7e*h~n`>>XmOh^H z8s46m@>zGqF7IHCuePfK#Z>C^1zsjv4RWx+#9*O#Brk^e~k_9^MZhfBUusIH8!-QHp5yu?^nJZO3Fc9^N;1N_*WQfEl7z zmnD`2 zAEGN~5q_fT?4ji!cJ1&LC#94o+gHJ6pJimmq7Xi2;b5_`wW%{wUD3^|=$l(mA`Kvp zyrGidGE2$Wgss?$HAUagG+dSagn4Af5D_#eYFYD+y~f<5MJn8h7%IFRhTA+~pk6Q0 z`{|zNlQH&~Z#tWlZ|u1J^!)zctwFjh>ZpzRbE;_RG)=g5C2=f6IrnkbjFjT_ey zcDn#|lL6l33H?^&2(B63gn!zTwFbJoofV*A>hdIgvpM?qT507`i&X*V0NX39DrKO*2{kpp2^QoDZE9 z4TXRnoY3TD46B#s*mKBZ5SH_w-|S58Nqpcz^HHz@Vh>QAwk&BA_`F81fwO1%v(1+D zH4;ja5>nHzK{CoDno9yavvB}cltjh=$0mR|HBvR7sPPYCSy<@)<=#MJwEK--2fuR(h?Q`|9>z(i6- z=6GHZNRDm}*?DFhPVRr#f>%nrt^-|$I)H7eX4B*TbU&6p5= zFz}bIa)8z|Y97mwBZynX2ek;TO>*#!^+4<^d<^RJR#>61cWPr-`xQ2 z>?bjbXbvwpMDa|3^REdu^IPf$W*j>BR_dq^RNVmnTL>9Lvwx}p3gS`S!f4P)nmep8 zzJ&a1)W1n@Bm~;niwCxzsJy=Z*mKY4EcK@fq`t0fp0w%a7F|uA5}(f!|6ML%!mO3M zEO9rF#le`_4}g*_pX5#my74quN2^t2!`l-%KjSj8}FxfZYg9whvR*2RMY`GYk|Mg6u)~P+N zsJ=mx*1(wbY>yH7VW2sa-hI_dwdmmq;3=h?8fqMceuorhhz)eoV*vx%^HUcX$a5k< zmI-^rZ6G~p^aq2l9=WhFt<#$uc77$}RcSzNuTxO(c~7FAO{^nS>J0c-V2P*x5hHpVivxIb7{W)7KlQ{qUoHh?yfFgw-OUqDetb2599}iw(5^ zbPOB;uo%PNq*%bdSlsO`QZQWbE~AECf>EEy9vpZ5CG+vjFy+nN?k=LKtO7~+Lxw`S z6Qn)b=b-3;&=@b$@Y*^Kta2dv-yx|;mG=MQGmj5lg;1c{^~|u{_O)~_ z{v1W`(eLvg%5dkFD+hv$w^`O7b?8r7b;SHY;`ON|FC2*!PhSc=?$>YB<(|9o6!w46 zbJc!b6eO7p0sxgEB3zJ{)_sg@jH@d3#$2OxBeq*OJhI3XR=mG^RXec$fR@rX;B0E| zlg>zDwQx%-w=FNa)I+_I@WkB+WQiW1wP0LEbx_YKaj@k#ct`VB(dFH{Y;iXpAXj@y z(mJfwJlzcRxz*IIOyY8kXKSeTYngp&$#*xhJC#=XZi`EzBGtr`F>>{|=yQLwW6mH6 zM51}E)O)LDPm{8bhpLaqWiB^hYi1HoH3vAV&Bpzs>j8dCQNUVoqnm5fw1q6iVGXzL zL1Jq$00IISw!efVg*4z`ce_7i#zYGW`o;UN;0r< z4@aKZ=!I^LF^cEOmlnA^Wymp?9SX}8P4foHopVRP^nwpPA}<3>VD$JIV!(8)faxML ztV7@cowF`Wx%g-U2l?gkCwv0k7HN4ep%@t${|>6hMAJCdeF z$Cqk2Tpkp^mnSv_-*=bZ{ZC9d5C2W7Ixj+rsR7{PG#ztD15oNHUgQ9i0-lUPfZ!G@ zZ+?D#K7_$mEK<%!3A>yxb|GMk6KhXTpXbtGX(89ZyXHR1#qdky1BPy2=0BDhGnV!4 ziaKb|+Wf)1GGrLIrWlCkUYDjecFq%1y~Y#VqdtE@MJoz>&vdml!NhmpAzD5h8JKsG zR+Wh4&z?JW&gf`uR*L3#Kw$%;3u-0cOME@K-o()U#|yXLR2lf}b*3Zj0@awtymATh zYvHqwcr7Gick8Cj81xe-jV5F8VmWNL-VYlH&$6#|M;*0`)^#NMEiiGnoUw`ubDA7w z@YPF&;-lhWsD+)sXDRaB(LUCENbW50lEnN@@-t&?7nfAwG!r?VQ-ya8a9{EvN% znh0}N#<>NSNAeZQy_W+o9@u-nVfAd$|I@cH=|I*DY+iG7oR$4TgXJM-#AyBy#)F^K z|1p){J8@8V;rFe|HI}Uejdss3@`y}15q{a5^^0#4l=sdr7`-axm=9Uwnha-N95enp z&lACuocF^T<~4_fTdp7zW1b@?OcieC%!mvg+IdzZN5u|x^ltREY`j2q}8heuT${rOj4h1C%K(x4H zO;y*i@xBS6fp<_+5>7SRDFglYS*`m~d)uMR``NcFO5VnCT9fKT26Dd8>$}5yZUB6x z1YlbZfNd%7hYUIrgQG*6?#nSo2Hr9?(L~5jOlq92bYRzP~p_Q$1R)eHNZe z(MV_m&CYC;uJ`os%~sz9=Kf6d+gXD8V}=j@l+(%pC+TlLRzuQ00ckd;W-Gjvuh1^(fcpJnx+CACU6EA>wycmy%WyfQ10EOd#?p`T8hK z;l@yo3J=iPtWi2iTLnZSewpD@E){?AS_?Xk%*2mvLldG-l}+Te#>Eeaz)mwpHRDS3UvgdLBmDG9J;y&1x!JdPSGAivqZv zx?1H%cYbA3p}iyTp<$|~LB8P=JdPWvK^Fc~(3vFmJ3kKQ`tchb{*UY34~?w&+wbEQ z6jXfDGwfznVaTn2O{?QocK%(euWY6#B1O67nssdlw(Gl@r0R{Zpu32C0wTD!M2~TTj=#sGvey+h76RkOt+nh!n0C=|b{a9JBaH zrv7zlQK37aPyAoG0A3Tc445P}GSKXRvzoUk5uw6}4EZgsBEQH_i~i??gd%8JNFb$y z84TE&py**}tzG1o?N2NZTX5gedLs_9VAz0@^tl-gQ)qbe9$T^bL05#nNabgFGr*bI za&B7sZ3H`=;HZUNn@K=#nQCvAByO%EV7KLZw>wN+w=L<{2e*h$s=q%>!J4mKZV&Qd zSHF~RZ_>-JuV5{wu|{*3{Zq3DuE}I0=iBqqbg17Jh1u+1GR}1}d#r0CEgEa_P6%z@ zo{iA2PayaD1x+D~6e21{m$_=Q#MmlWE!r!TWY0FPw^1h=VWb^gi$7kd8clqr1~c3`z}i8GQ?%jZ1zYo=1&V?XLpp@x&GKhDgS zgSp}{!30Z1$r7W7`$0S%$*K9X8Dxo^qWe-Uprw$6%1_8aINU%{#&uD4VE{^)5(${J0^5pw(-vlhY2>;%>1mSb{PaaS6 zJlXBG-x}032@Jk=t(l*v>H7?g0Cl?EnYpUl7w)6cpQZ!so_{T>n$|bjdLiHgZt0z- zq=aS2%`ahNxX9A67%|zcD41P$M}Huv{SJAgk3#=EUNS83{LS2!+0{e$RR;OJuY?+Q z_bkIGgS%4F*djoKcxZ8J%N<+!e%L|0=R}=ma2K1_v21N2@vuol0?R8Z>9>CDiT5V@u^3HuT6|ynp-|&2qn8cz zO@95Tsi_^SP!S8W=JLvKx1*do-wy< z2-F@9!?!tJOZ~O(7joaIDEp%K-#QlpTS79h*$N>d6MR2$k35Gf*dcITtH4h#=G0hU z)U8doHzPQ%^X!$;z2rKm>UP*-CXrPA7$lDrcw0 zhgjWUsmirCg?{>+7wapkrMnoAd=`ml0WUXInu0l?0ZEg7& z*%jU*qg^I8qba-f(^5MN3 zEBlv1jmRD=c=5D1iRc(?3iF%Y(T-SV^Pjrwb?gJ)&{{03&qbcna$tbuJ$;5g;~h{` z#UqsEwd`c*l{qL@+AI@J)&)rXwQk1Ca03+QVMu&Y;C`E&HL)w}6HL4}5;vW#gkW=D zu0%QVhcIV7&YvbUMh~4ofDV4Yl~v|M?_^V(zlx{h;4CarF5JYB=#j+^5=Rbhzw<}t zAlQ!6gj9bY4;Z?E2*7qlVPoW#+0o4*lGv94&vj4eX~!w;g248x{Z;AAIr<}L_YvLE zgbA{fSb>Q?_&9}<)G~MR`iLiI8jZr+flWB@Gu{@NvF|J&reX}9v;~mC*WQ4TfhH;? z@@k=#9T~nxpe*vZD6rZ~qnJvXE=X4*X9QBn7g$%JPHq3v-El<1*vxRwc3B>qbp&>VoyB9`h@45@8h_d;2P#iKla0Z7k>8)aESt#dv3gFX@((^KUyW2=0P~-yR%lzF4P-zv;^wY#iy>2eA@t{M@d!Gf;q_01g(3#X%C!l7V)XjAacx3l z*HK$|%EAQQ;?+OPN6-g4&5E&YJ(1%lne>kDhnRX*Rwoyl{5$!JT)5|luodB&BkG)q z2iX`N+@)CbIQ~&XmpB;$ zAW6eJD*xXV0Sw}QWMUv1@lMV4%>-psoY%EE9%D4NFwm{x4b0;}0rrRt1=CU-*#c~e zxnb{S=2yuVRv@r8t)-$AwXhI41uk0{-cz4;v_N7y$UgTH7X4}4|B#&>*q(tN)zye_hX`!RZOe~;cViTkQQ;{`bew8k=xZrEjmXgbCZdv=X?-VIB^tEuy4Nj zgwTdFW~AV#HrcLp1+Vwj+Aixkv`}3PT@E#AEENOrj~xT|z&M!_pw!IG_-86Sl^ch3 z>9=j?sd;#%frdPe0gOqUzjdS@v{_qoGQ|3#ANBMYOQ%0dxFU0_W{yrp=^RsjaZB^E zk*cWr4XKG_Hkq~qf;B?DY&*8A-Z#Me(Uh@4zQI(+&+O-@f!_wkQ8tQGfoM_@Mrv3N zqItwljK9(S2>OfMzy-CXGY)k?Hp5j)=)>%sD1fv;F>pqzO@>3iekFO(2FQ!#v)^Ny zK8yN3Z2N*uw3^UUS3x2ytPV2oTs@t9_|Sdb)4BrPspdEDz>9i{pwA`RS2PMwLmxM7 zB_D5*da8=r$ixvQ~;pRUmD(gSAa+ABw2d!`!SUE6$X4u)KvjsNKeVRwMRWPndCeBvTA2E z_Innatlh8ZqJJ|VEeg3zPJkR$%IH=+G)oL4E6_(_py$>5b_!nKa?KU3LMUssS>|>^ zx1T`e2dd%XS(_q(QHQO>`U=*LXDSSu?W&$i)=j}}o?-12_pMr#cE)T`wTXp+(Nd#c zm{+gvpi?g6CnoE>^&>u-%T=E1?J>Sw9lz)+d!#%n*+;F1&Si4RiC^c)7a2XYaQ=+O z)pMnb2ATBx%KZSF>>kSR#r7{?;fd-`L~}TS%h(|+xIkcjCJy!0!SGz%HVD{QozCq7 zpT#Chk`7gTmc_gI7##mZ4{0}7%C$})!q3H z@l@P8DO=hMD}Nwc%L)%$Awwpy%u_cZZzRBCv)AdOlyVwaqIhm-wvPyZwG?AUeLgil zt`Z|hJrzL*#tAUB@oeFZZ3_f=UD|g6_YS<_bfcSfs_;=4#QzE~IY+0w-J(A}qfJm( zF_pa7>2v*&>Sg1zdCdMQ>EOrPi|D~h)$Q5yo-TpsVogw{=hfc|`{eKmTe-KlCzJ~) zwFOpXlv5c#E3;FG{-e6O_4UfBshHv^V}w3f|GxVmySw90YvE93S1{4Dhgvd*64TY{ z@aw1<$H+_bNaI1S*fXV^8H|Zfki;Szhj_>^GiAYZQ8Jx&j`#|GokfU)6%|iB*;bsV zidg+VCMcY28E%Xpgaj)5-8EUsV&&8_EH|}$hpeWf^LD|tRZbHM!>dd6=qKzR?C}_@ zoN_?i{g%3htJhbD@4*C7EIo6)EI^)##@hGZIc*SvD+8qQo*|}Hd$Fn=;E9gC_uDWo~sxq>3+403mhSouPF(47E?^&wc z0G`N$w#J>#KC^Ry=B^9uIe{;JU2;)BG6}Q=@`fiW6S^)QtxC!Lc(m3fHqSb!HrH?FF<(X=-- zMeiMo+P~3`{t_JS+Dh~j=%gX=?uth!RhyOKXqc}DiRXy`6Mg%asE&&X0u~uKn@UbQ zIi7^N?cP&L_xqG(ZYchzW=29kJnwf<@S+EONMa{?&fp_MKBLbhk>;d*PK&p1+eqJaTyTHh|r~u4f8NFG+Kt-pe65g`A zvbMk9k_$}rOjGPKZ2_gntG(+B7cr-~j7obayvIU-CMzWI&b$DbCzSYIwAKJm5qaB} zC8oaOYN@z_(R*zR#S-~6dLM;9l7?P(IBtiPKhe^v+4}<`cm&2piM3JqcQyiVOj!y! z@+qJ#>6>MyLb7h}ZxC7(%>%~>rNLxYo@_%ytzs+pZItJLpHR>CD0ed5b$_l&UC(p^ zR|=0>*B6iF0K;}ik=`w-V>dzqo2B^E_g!!zCAUHb$0V+?(F#CPX}=!fx~1l69-2Zs zNK5{`$-xizgec*=L#HK*GgtF73%&l(ANaNX68|WpLNb6i8i=)fUCZ$U*-cn@ceAy2 z;JqwoY=0Il=+u{7uWvN>SnIwoolx|&8Z8C%Qz(4>yCa31x=qc;pQ)?>NysO&E}S`a zg(CzD$Y1p*jH9`6u#?)kQ$UVf;(21|B_ zSB?twK#a4<^|S%#n7*dTKVbrxufKOOH+Q$K5;JMyQ)XCQya^s!FX;^~?|SNg8l$kt zR63r{UTQ1TLMJ)lceT&YLYF;+wFQ1-#4O`7M}MLBz^31n_H(lFWBco_^{QT;j{yDE zD_3=iCj^O)^xkc%cSF05Qqn|%qNC`6@B$qC&J$(bT=uyNiR|B$RMq=4Z@fI0XginA zIz3>1e$IdokN-ScE1xswhk=Uay>*x13AHFlkGLnw#9)80y_4p3_8E6X44()xV z%|A6dT727QtbrTN+}x^NYR)Rb^+;Qnh0K7k`HO1ax=ukrQj;i4X#^&zIwNRn=Dj@{ z7w1cZiDFCh?ydzVy(nH7)HYOH*r9q!`MHJOb~u#5%CxE{q`=Y{_g2UPswD`BQ12y- z=7uBe-={BvrU9k$WVA%jBAC|FQ^KR3Xk7brItQ#^2HNm`3nab`d`&&<6qZVXQ;v3=8=kk)p}%@owFP-t7YLYTMhUQ4$74 zrTggg?g7^A6R~H@QY02i4{ZjebW}0knXmQ1lyfj-&KWxIh_?4Hkka^*pS^ESWRlxh zKT=+%!CzaY?DL5)tgDPZCM$sC%jV=**+v8&!_3?GB_a3_&PIf|OS<2edbPBo{xzL7?Xia9&D8dsN$}}!=Ib|Wgt|CJ z^X-Mm2HIDaY$F1u9Ck7OaIZZuI2fb<6n{}OqIqwD`sS8+LgDAre3JQZH{bJJPks@e4=IQ@FNzI;wDt&u>dt`m`S0*-&_ilqX&xc6$KVh1G@@k}`s_EO& zSD#ydUHkysm^HwINowT?=d(50R#c65|4MOb^V&|}5E6vFiW}61UY+g)2L}%h4jvpF zF!==9eZ!_X?^J%Fd&zxfd=Xk~foZjpR#V{>TPK&_qOTpm8Q7vsB@Z(f3OG(x_%UX7 zR#!DQ1|2qw(af>WWbxh;cm1Gly&~|3Ab&{c(l#}4nNS+SLnj+ENU%`ZH5jWiH*hUW z^(T^En$ypE@mGc|7-+1S5H&;!{m`=7a51bsR4CY0@Jd zDeF&G{-1Z20;aff%JSp=9<)Rmig#B!{pMHBSt*J+%6<3y_+g&Ky4d_uD&yVyKGgEs z_7MZ?JNhbB{E9<03AC&g+x8GvRIB)rUNUa8LPhNAq?I2UbNzd1DK?TaVu*m0MpL7- zdWgWHXMg{t;*C|Z0-fc-Z^Z1wWa&e#Vq0O_knco1WohUKSNw7vYh5W3j#fKhb=)tT z2?fMOh%Te_Sg4LKGAy~(6QlRdQ~5p69sIJ zcm@eB!{~>P^^^{3S_(AB1j&72qCWG<71^QFMH`tiq5RXlCPn42xTG}=3!J+Aq|o^M zvZGbYRiQZjqaD?;X41uP3He`?61S)zlx5;kuGY7iMI2MrE-+35m`b&-1#P+Talr$- zcZCVGN>2B!s{KO-Nl)n>EF55b?0byTn0C8nW*Ets{wxEnOZa2akf3e1$3yEr*0Y#L z`9n!;P8KUnmr+RyYKc~ z`6I5<0eGSWK{og6erJ@*LAXKPTDO|vob_FsIsl-ph-?DMzq zq5nxGOa@z5*$yredlkPWz$VehU((IbYv!r&IHMEOmt~RC;H{y1>x+7enn@=h@P}$V z9@P7d6EtCPcv~+^^`!D?6c;5RT6i}Y~vD^G+YxWXOOB?fx%pVgW zj|G!0d0^sg>=Mdcex95MeuLYYQ?k#iYAz>SUiaD0Z)plSSxqzX?SRZHjQ*%>aHAdV zApCBDwo>EIXPV%E8w{*DD^u4d_q5Z;YenpZ!dqe5CiVa_sU~ z{k6`7-x;d1@2vI0bE;<6uh%1pr&@{!LQM-Xzy4UW?P2ao{hWR*_a*gisj?+%>B)uQ zl31c9D+f4tIybjx__T=KS@Ee`*5t_6N(8{kXJfqlLo5tWE8$t zyZ-X@Gro+5opA%d-<7;?8U=~x)3m;N?Ap3#90Fr(oRcEEPaqURx>G|-ejyZR>1{l% z9QjRcxeyLu%%pAqvmAxtpF2K8;eY!XmA}d3j_;kf^u33K@j#5pd#CXFu=udwE7?1s z=xXhXL2u9JmJWfc$ZP$A3|h#@Dk(2dxZ3K19cv>>Wl!p4v^wt4^G1$MoZ^mYPc7t-?hcaMWrH&8M^{KvY1)ifo8`y84G&zL z2q?6P>)B*iui|ma#N;orOIFZ!A5w;qmdqQ|B4V zF!bfk85Fc&@_Yjd16SdIJRt^!|vcBP_t(hyx zTyJgZFP`0q1af80U%xoC2uGrxB^o;I)KvVBp%ruyj2am`SH|@CR!cmtW}Jfiey5$k z!uU3Y48a$<(>@&bAX%CY3M~UYWFmVog_d1aK7JHV+~8CDQ1|DLj8AKvW~p{4%U+WNgYJu-QW zNsZTxrWVk=)t)cn^gP|DMtzhqYas;apRbAo&ziL`35|0fz~l)t|_IoHIF+T6pI8%|&B|IgF1bPwrk7~J>MO~S(S9UL8XOaiQlux<%Evcf1uxg3I|#T4)p(no z?lvWv?J7+)a~;J7Or_^1yodExLStO6wu3xwgBxG6Y;I5U)@2!%+A;GBq_BHA7{IGb zv>s4k2BZQDC~|v};@MzaT>dZ*6SL$`es2tEmV-qo*xRBdNPlm3Z>RB;<#RY%0EfivjRdwYLK!ver}Oy$4^| ze;uD}YuEy&@hDKrc=^BX)k0fa{iE>DR*SX9%5UNv-rR%xAH&NB7S8=oY># z4w(C12RDjcRd|zkU(wH1)??Y#qaf+exWMZjCrGXdpocJ`rvXOp8MYOe|%qXWhSuB4W2PVHDO zWaF9ca=;9Sf2Wu(?b*^ry-`yWod;3d{J?nW)EhYlJ$<3jgIR(u;pg;JW6s0UR2H{1 zdpI9~X8$$v*Yht&Mw!`AFhfL;e}AG_?VVEHgHprH7xK88{vL#OA8-KZEdi`>6sxI}bvibgh5lp^$cM!i%hHPK%yFh80f zfftWCh+iE7=E(ct@0%y2>oV&yJeV}+UCJ-KF2DTLon^U`n=j+r_l6!vls$j0{iwlA z4EAc+zc@_5Nsulm2osZ7&`GfD`itvqmQ#b*?@G6li8?C-q0uUjwn6%lR+)+&7KWY# zT2AlqHgJXU$Z|JH#vO!0RtG{6WrIx>RlSC*f8ZAD!t+bUOu$<&H#EXOkptv2FrcDp z24`r2F2RVcM+6u^cyG1Hi?X>%lvA6P;T|(`D?XjMW~l#*7cV?K2!P8iME(2$nsqVc zx3Ci}rmhjZ!(NcM+_oy>zLlzDqcYXa5o*UJhdde{9!BsVSRi$Ji%;inlN`R?+mZ}c zGcQeA7WIB^MhbVu_Fg;EL(O(8=U3ktWW4t?*f;bQS84Dy$vFkRB zjG9;1QL2Gj6OCF>?a{4kwf$7SE_gg@FhsA|_>$YSRAUr;{k^5ff8g-*v@4mOH{t|u zwu2*0!3j=4T6Bo}@aDjDAvq!!lbRYI<<>`C94zguzE1OYoU}nUyD$@%C|hrFR~H|Z zvM!ZUluNfjNjH~Kyjcy)lq<7TU=IVXs;_T++4GLLr;eTw_DLFCSl2lE+PxSgm$loQ z&JH6leLP9Y2WYdm--s{qj^L*DSeDolcMf@y5dSE!w`k#|ZI0Cmq~!(G5pTPbp}QAt zEv4+|K54kfXtL7tE^OFf8fCJK5+G_cGuAZADT-w)%Jq%kNXpB3$$$|_SlZ8D8f%D4 z&l(dmvXR87XeyUkktaKp!Pex+SDRew1)gu=E>=T;jJAq~Jll6W6B$QVoAhr`2n8W9 z-DV%p%nJEZCl42D?~`Ts#hbLW=p=nJ(m+-W%HB^%$C(2`@!s$E6JTB9#-(yd$kBM` zza=bXsR#)^vv3ybIgpJ^hIcTWxXD%1m($Yy4iHsMk1J7A8wAS1TVecLX(h}){_?dh z?AHr>9)oQ{BY&SrR%=1RR)b8HyG@&e5NrvM{T~ z8msnb!7!0WZUPOijKS@90dthbOV^Hux5a{Sv_V0{m?b{7c;F0o?JFjK%5C(|cX7Fu zyX=Q({}lyrtt5}-Cg&NNC*|_Z*xqrFEV=qpnIZY!n3rsafq_)KN}yrc(_;2AjzPW` zs~YI~W)v=&th{}sX(#87o5(v~u)D)CMs3-qA|3#lMoy8gV}@0C#2Z8QQr zV=$@JbOvouqlxg7sT`cP=c^^@E%j@&0%wHbkcP2lxu%&bTN`5&@)NjplhV2}o&I{@ z1x^3zk+*J___=I25{d=&e&7AEJ``X%+Jx9&y|{!>bF)DcOAlu(?BbE+pPFrtvkQA2zoztfWfxWt50r2< zm5iAD+2q_fPEf|_mDei%bM`Vrb zR)hLZ_!dkKYDm)hHj2p!1&*vQH4ojw8{mdRF1+a2#wA$DywHK?S{ybmHBYoeUsU{jJxcP!SC=d*3^j^P%B%p@5s=C4YDxvT4aRB5`X znXtq<`b>2Nxp<4BDW`~ZsiCj}EbXTo#*MKS)n|9Rp?{e|zb-S_P5=Lt_Z4nYb#1>e z4mf}?LpMVTibyxo-QBIUl%RBjLr9A>N~ef~B8`9o(y2&GBOxIn!dU~)`@PS1uJa!p zF4)&Fd+)XGb?0y0_u6|6iwt}};ruf=21ZDZX1e9Kpd#^XiHe)8H>8o#+Be%A5{b|d zyNtnA0Pjz$tx99hbP=cXT`j?Gyz-;22B2P}7Ic44HcKz{N#gIa)+8H)K1b?H4lTho zmCTtPi7ek{tFK-VH_a?G97w=NF$lo+RAp;uq(Q#y- zy5DMczgPzONDrdjsf=;Do4&d?+Kw5u3!>9uUARH&%`4s7bix@zRpekIJ95zBrDl%# z@5cLeFl=mygvSoh2>-pMC_^mB85#f81ihQ(deGS@(u;SFJd=hAfIguJ|$lUgL_-a1<>^QYPLP9(etu%;VobE#?D^AoreGHg(cCJ7Y z@06i3-`rI@1@|4~+Ot4t$hoh`^x@pfJQ@iMZzGC)c|?RmkMxH8c?CCGyd3C%@0B=T zPu%e$lSKa0Ct52ixJ^Vl5vnV|U8xnj0;M4921@Z^*7euf$2U19_177ypid;;yLnkU z$r5W2dIv5T?2{{WeR9BE8ZS%24p=7*d)xoOgf*ZAy|nZ>v`d|{AFpp ziv{1fd9z=BVP?Nr3R%q$5syg)@j79MKjV9>ZDZwua@2}-?qZg#?_T*mxtCjgb9C9w zHYQU=9G?Xrs>|=fL+)=1(wem1a+vv)?<7cLmRe+z>fk0PKxYQN`&)FMS^&AP(QH3- z3zGScX0D0f+0XO0oyAhuPkrSARy@*GWj^v;xEy=B?6Qywa{DnSUHeKXh70>EKU~Aa zHqI(?=U71N5Xw8S)SEP^{vJyFKp8~3)aPA~eNOb!zuEMBK8#Y(y-tk#1Kz#3xNrTV z5Z1y1I8zON1qHkYTe4>SYFdSuO;|ZCSUKl>Bpdu(f9C{%{rfzW=;kJ3MqnZJ$4%h( z_*(Tf)Dmb5w3u%6uIcQy+^|nwk&>%D&L4|JIhOGGJDiwhaJ>!r^rnn8nTK~_^NbfW zgB)iYA0pobk`V6aN2aYZwmb^(+~R4I55w3BpclnE-|78)mRoNFX(GRcxh6Ass_AM! zzQIYJYRbk|k*KI)`@kr^m?|l$P9aH|D87s+p8hzgZJ~3qBdQAr6+^(n2B&%cd1r7g z<38i5TTLfTtHec{)JZN>?&AVu67ktz>G_fk`y`QDMt)-B35hl-iW+1j6C|moLu+?8 z@n6f=WP2&b$|7LY5Y>Rlek@Fj@z(pZd0YEr&L#*-QbI~vLds@(9!G%s!B?N}hGD$# zY7vSxbyqKR={(g=EQ8i_=tF8oQRBdIQG^aZ6wKHv{G@N@P-E<&Wn^lgX~@wpk&?;5-Q47CO@zysj`M%@dG#IqVL!*u*Wp?W)>=J*Z z8}8lq*q<1SePGuPbPM6HO7HOZQ^8~ExJt7i@58BZUir=P;HcK&`s;xxI?^ywFB} z@PAKCJpKJ?HdVUH;ybqm4{|j%6b^FR$I1k2?GICx`C{eDPNn5yRRaZD=RM5>Q}`}O zLg6@yd+N%2>MP3ZH6CAht1E7m7Je@zD-xg1SXEXX$r&|igKK)r!ezuL=Uz@U-WtE-@SZ)#N**#eG@)*~%b*&pm&2U-l39%k_gsBe5P z)5>r%X+H-Ve*)}=IG&`@i_CC;uN*W!K6SHsA$oXv#axV$&oR$y$n+U-mS#llLD(Ti z>mAP=kHSo*x^^cmtEp9;w{LZ_Q_U^($k$Wsxh6fxI zOUBK~-jR_P+V{)b$85R2b-C?yC~ydhE)yc$*E9oZk zIy)o{3Ga|Yn-87#PYF!~HS0_>Yi23jYo{kJHhEiuUevq0t~J<&dslCZZPm^Ct<(FD zT6)^m0w?w2_ePW0OP}|Y$LNxeO{tt}PY&$wZl8_va0PV_U5|{;1g_C8MTI2~5MZ#O z9Yr<661$ybyon1)g<245mU5D%^4*T!c(CWFG+SD7#nPI#i{)NyH&pTRyfzYE{xFhU9aId6W+_@GDT(oQ0(lO* zKEHi!s^_UKxMna`Dnti*6D9ZN{Gl>P$g3`-plMXih3Yq{7J?av+ac@?h={6K2T47gs1%Ekw{g~bbOcl)6Wq6*_hu!DN zR$O8{KTQaBVzYI7y`p^yzJT9KQ%Aa_rjV29HzJGIrw9!knK#W%A$0AX zn|x*40OW#SAsd)LmMGpUco#?H{9j&>*Rp#B?^#0$o61icK$T;i3qJ{%Im8%$*VQ$B zsjbPMEyTROj#Zq}b?E4vJkWfra!iQ7ZkgRrlOS0#E%wg>0nA&eEr7iK_e)+ua!V6T zvxx2Qk;(yY6~{G8#9mss39y3-^!RSGxap~lav1~rs%*~B8#6}p->0;wSYAyuJQ=e0 zOf?h5>#W_PIo+iU2!=1-yqq4dEw@3w*~$h#>o~X@;H_k2`ZC?(vCwC-%(7VFJX6jZ zBDH#kK_U-X%FHsg?zcs~>bIgdl=;*&TAM%m&wP1i$;b-}4%UEi1+uu8${tZ&pNw{@ zkT|-I)){#}BfXIl&74$4jiTbr)H^eBD{yd3$#Hq1r~woyiFV&m{^`O<5Z~{B8)pxPiHs zm2s1=4fXwOT$A8~{@M55u@j0_+_H z!CYkrM)B;owoJKtP@(Khf#!tLe%Z)Kze3!L&d;ksZ{US5j*ri71+d-ID=Fd7vKU)` z^PI{UUtaXCA_D9#j1lrdrOmQ-Q^kaTN~Nodd~Z*~?!i>fIO?7MH%c3==1+%}SO+H* zVJA7j-_&CfHU&Lxdw5{wC|}n;76@$4_A8C_ z$8tN!_1m{vWGhWb9cDm<&*= zjlXxDqobgpprxfnB7?vjszeWxMb3W3H-GC3_(9XEPM-O+|XEKvxIvFK(LMBy+-d!65(gIk$W|G6^ zTm z5b|T)(Bif}H?&n4YWoV_*Z|(Yw{a4a{|X-P6`9LMhPjPcNI#LeLCD1nL7RmebKBNg z`X4Ylqq&shH4os#X<~z+zle7Akpu(;K)IdX{{lpVwy%dgujTD2)l*1jCyM)OedKii zH=BTB@vQ4xDaY7v`H`ZpM4#IWXP72t8K)#Y`GgdBrFvz07{v2W&fhe><7MO#VdObY znS7GB4|ns3tZFc8j0M6>@8dT!GYbm~i>JHyao?enJzjR_!}WmUrJm%ds3?VaI(&Tm znP$I9>(|+>Lb#aFGiA#wNF4wY`m5v>e}~WXc94@mcbkGtkMd8-b1bTUM?}T~gq{7~ zzR{vza^XrQAt&>;zXhtu7?X@*Wtdt zzLgfOm7@lvx9<>@-sM$E$tV)aF;07A3cNuJV?vg;+a04POC`(;ZogZ;E}3!TP#4JO z!37m#8?A|~f5ah0p8G77EE!hc5iV>qILxED;sia>B`1EbkDhdB44+(o>+rF0qt??# z-u5k@hDAx$+JWBW8;hOwbxJBKDzH;aT3Xv5j?T*D&W%>P03l)FljC1MP;eyJBX+jo zae01zerajxyLZ3)(s@}maw@=2n*?H)HiVc}{dr1CdjHDE$VgsZUQ<&O2Nqc#{5^@` z-rinxOw6Hg^S6h0+1W+i7sGcP<(00uBgF(%A!u)(GgADlXRuXr691c6Ei5by47}(rB-^~8j!sTaj*jXt#m%&|toW$(ZjbAqjGcG9epIep$dj(h zs-7hjaO$b1rsnMY`v0cvG^X?~O5$&qy63r+Q(9GJePv~3OG`^`ZtjN<-(23$)w}06 zHeQuA&;>Ddb?bA4wo(>UY_kJ!=UIGwd~7T}9DW3T4i2Up9&er=ZW_EXclNrd`GJHT z$4Q!)n5d|z=;-JK1O({mrHnhyRI)McqrQ{c=$9WJtdBl^{1{Ni!NK9|?A%gL$r6GA z3&wy!V=+LQ=*VJ=aUXSYUT(H_7B<1PVD7GOmoSZDnDDHpk=H^!Q{{2zoPRr)@c8lN9HtpFp%$G!K z8ygKi`zxR^Q4tZagMy)%S+k6h`oRK$jSrwoM<;p4h1JZ*z#vtFUBT)~ob3!~asJ+< z0FyIt^gM5OASE30J=&hx-rfe!30J;<@8#yUyU>AJ>M2B^5|pfO&Rd-)Y;;6L;h;LW z0iirRJb+?8K0YBKAug_=_#pau9SGnJXrd92_I@r9EU=sy8bauKhOTv#BP0QKY7kI(myuR{Xqch`pVfgupw zxZ!^^<2C2MuLdON>5esw8tx(m67uxJI7u9Y-+c8?^p`}tAPI|inQI*{IlspaNDOT; zRG-pG1pagr`t&=_peGHws-JsW*BV{BH%i_|~Quv=aq4SVnBut1V4tSw^-n*}W zY`(j;)_vc4S#~>0{7hHR;r(|YU!R@X=Id}eG2es8gO$K4h+OEEYCK1)M%ShvuqbdG zI=NoU-DyBc`Axmy;-32j@dvTsKa8yNuf-o&GkOu6hXzZ)fZB@C!~tG_C57L?)Wp-1 z>(C0Ql7WGNg~eQVH!R>?nna&u`u{jI;Jr@~z>|Fko{SsS7#S99kJBfQj3y(afn#9q zHBEzsiS6y}z*YtZ)QiM_f=!h@R@H-oF4or8j*o?21VLZPX@Xa)07VW4)Y@&xc%Eb0 zLv%6GK`b2OfT1#ch_Q{9Q4;x7AFmy}(gPE*dkshu9|=ToG?yho}HB36G+Nkvn9bnb2$eG%ph&UX+Us8 zO9?wkV&gKhzq;yE$^oW}i@t6MRgWzlb49!{2h<7BF4+c$)@Mr`H=z5ZXS?jvN|Oqba%m<&#X|mnRk7NABn1WV?i)XUhX21rDv5#t zT=d}I3J1}czX}+@B{DHF{r&qFAmQz`HOq~TxVX5hmNzetv&mo4oh+^FxA&1P}*k z2L#aLl1C($a;D$C0ZIUNZu2rjK=rVjaV)Q#T@psN7!5VG-|l=n@ck|T0!&RQA1(~0 zZn-!+|NRa8=AZ3G;3c2M#>U3SOSoU)6=Yx8kgPN)H!mIX$Y*hp&jOc=MZG?e{EXrNC&#Hb6y)V;2(G6~ zcize4G{&$2<`Ue7P6WJc4}nX8+BC(%&0x$+Q{#g4^>l!+OzW5^MHWhCd!l7|cdkJh`2*hkl8%D1MszQ14B zalCo+W>w4B%h<4LFmzc^PSPyEM^?MYAfG-QZR0|l97qY}!I2Vyeg2Qu70O5JiQKz- z3*NmGSkY0F!9stg;MS8rrDcwl;&-%C-@khYqS^lW-#<$nZKJMkd~$O1R%h!u(_3IJb#;fIVyOWVM$*v*o*i?OrD7Mp zMaKY8D~75edvTp+eOD>=C#5>2ETh}LXyKX9o-eAHtZ>e9xh`aoGl~ZWwxb3)kJln1 z<5xLMd4qmECAXNWo?qS~FVeHYvm+nq80J$mj@@8V@0ipeVHET8Le136h`Aj9H)1H*dX*}TX5MAOFs>Rf{vr^Tk-smfH0XH%#B3|!2y%nz}b)d`(%}mV>)78+#`|k*Z%6=+m{cIKr0#- z6XaP=(C}y%6CtwSq<)HnV6xAmmM$5Uw-MdNg^P-(M`Qr2vOCy{=nG+-KWFd(gRt;- z*gxyaL~}Oim;4dD$Aqk@mNZ61j$byo2DEC;AnA7w&Nl{9n*NdQWUWkL!iy4`K43h( z2p;@_^=k^R-<`Jt0!qs;oB%fLq1|CW$ddai@UQpp-v=(XqoV^jVW4vW;ZaahQc_b> zBatt&vN}5)niQh5&~zgfp=tLnc6WE%+S>m9IcfwG5no>blP51xzbeus`dp&Z#A9NG zdwHz_uRRLfBawh{umFcfjs|E1i*5Tqdh`hBHX7jGzaKw+@#)hifKJ84#ntIdP`^TU zhVy07UI0dixks@kr6>i|$@RRl0$=4H^-=Q#S&BGFANh01#MB*Dw5_dSG>2%OZ9Ojiew29jvW5 z>SBLUDNLb#A6MxQE>EU^0dih_wAuayJ#O^SMIi@*Qnt)Lo5E$#`52#9^f*w6I>ss2 ze76?ErMXbYj`jl>uqxmPs)Og5V9*GR11rs{{7XP{ z)dfZfIvp<_b`2>>uZX@EN;m%Rd%3__9!q*$U=Sdb@Ew#;pndK?zrmoMUciRH1WT5I zcVqO|#lPeWU=5l(V7Uk)6|6^ufMB3$kM;HH>&v4xh)Zn0*)h&hU>oZW@QMq=OYDul z4Jk3PZ?(j}RaK$0hH!r>d8Ksl52q zy)@3tv2U3t%*f;0)mxjMLlJy-puA6X-)nF_I>mu7ahTh$PF#>P0l(MDAAC0f-ZN9k z4Za5VRv0ra^gl&wZ!2KT0lPT~0R+90?|_J;Is^pgZm+NHvirQHEyt1yTPwunh`TYNff^p}(f4EhuZ(o!h@ zg&UJ(OEZw#cx8BNDzSyckYdrJGzTqEmLS4=5cWvTvBrz=+B^AMS?YFPgRk`G+WMc8 z0J4IJ>Ae_FHg_5{#Q|FI1l%fS3iCuD7%y9kpg7s5SU^$)L>?9vuyl9_+{&(n_mM6S zie9q`Ynw(V^xuDnPoVIC?A#objtLC`-$R!BD>)KQ6U>fO#ZjYY3#w;1?z8g(YzGU^ zsBf?a2M3{}5sFp%JQT>-ER`dc$m;dO#@vT;C189&jZZE$F4eAtk0x>IkSK%$NJ<>B@^ zI0pm|G-m9alzkMm@cpM*6U!)(eV}dl5s58hX{1|S|o z*9Yt>?d}f;vJ+Z+iH{38jHqg?ZH$fOS(?ArM`-4#wt~keqEz1)Mb&-)E%tp$YGMyP za_1bwz(rB!F7q-u|E{ckrfiMf)AZ2i3=kG#5I@5}2~sQ%D1 z^7Kd67<}o|n6+p1f4)vz7cMB>Yn9$F*8FapN@s$HgTbB5P#cdUBr~XCSZq`btZ&Ft zWFg*Xi=CV>WBQinEUTS%-^)sWiS14H82{8_?Z!G|0gW#syNQn+o{nwR?Luk<}lYfZ? z<^20@$csg)gcn*pcS4LrPY#O#O|Ro7DT+sLnZkTbRys&fu8-tmdv{dYRoJx5k-{>ztN5w3DI-K!ceySl2d!GP zrqz!|tk!@N^(0Z*OUM;V7hA}=>;K$WL7}k1cU|E&g+1;lCr{h*z|F~lpClL<@Hn?`MIeD8F?~4%jdZgiQ~5!srMcd< zm;IuxX}xGaV&J6MMt6kRC{e(VT<`FXK5!e|%}n$cYd;sMU6EEP&*JI1STDz)O^n^4 zh=8e}0l>Ekx85CS_j_`uDn*5K5F;QuEXD!XgtNcq1GW28{ ztj@|}1LOWo^^S+#=0!(YM$X+EsOOT)AbkoJLeAU^dk}ta1|z#0V`7QH_3_6FHsXtQ znFiyeu5^7hCS6zH<#>HY$bNl&Rm-->UxN?{VsleU9*z2$zTHA!yl*VM^&skrBWWx` z!|3#7&VX{U9k;89`L#9tFORZ}AW=G46hOAOqu+%paCWO(x|l&*f`ym`JdbW9ebaTp zF%3(EKypFB8f(e55xUZ^_?$vYeU3FY3wDbolPj3=OvjOof5C;v{A-=$)hhdb#}S_Ic21ADeZ@cue+TK!b!gC9gi#rx*! z2W;%p1%x^mI)Xl{`#tM?a8BI3ht27U`Ce=W$Ry;=Zh4Cr{j>fg?-KMNCq6bkBNX}~ z;-Qjj#PnvEC)B4CAEgm610c19sp{P?t(QZRRQ>D*VbZcDqjaxUXGPgFm|kD2nDYF> zWK@jc=%h(X%Kh!hWVVn$#x={$SK~N~dGB7f1APCEe%6MGIVlG{tKo7Lct%ZS)%Jt; zr9!5hY9NW47k()-z1STH9!AS*jCPTKvwyM5;~y1GHM#R4H9gRMpGzlFoy;vgozfiv zqlFZ((+A0XzHJDBSOWmZ_KpnI+QI;$yx}z)k=_S|9_354cF7NG5!*%&o^_v{9^4$r z`pk65qmxz#1MZ6ZdQ0D^L)Lqm9gX7U1n#?Ua+u?Qm63Hl+f`>6Nk`7U`=S4Nlc|P` z=qOpdpsdFa(uq~%Rbx+x*1MH6hRFb1+}CmGia$(0E+O>vnZu5P9C~WaG4&xnC7896 z3outLSw3~IIUI7uxFo-Jzau4eeH9-a!o6TgHykd`y?Nu%DJjW5w1Q2a?gspZdZR3w zWMpPVygz?qX5|R?V-$`#Ib2uE6248U&;L=O)C%(Bp*8O<6j;>ocYVwq(=YM|9Y?Ml zHo4nW>d1|^ak|d{fT9nfbOi;3@p_}hz?g@9s*5p89Y6eG8rRwbi*E(_alpH z98vJn+OzYKj}Fa!D@6)Qvh;BN;K#k5NS~O!J;(G))rM7bE6b z5z0bOF97t%+R6QRlln4C1TteAy8||i)bVB)}sL;;6{KsM9N--gFL#C*vCb*~B+D;4hX3{imEWlQ_UgWOT zqixk?${Km1;=@PqVUi3KPC89?DQ1(LPgLYoN32_BeCG9A^ayNdccJ?E(-2WN@O%X* z^>zqPxp9eh1AaOIewxc*eTo4(5cR-{`HlIa?TXq0?c8YAM}S?@2o zfj(l{FXZ{CRl<|=&5fmFtmOBVui8`|wJLO=Wq3LUA%NUl@3JTNaVdMG|-j zd7O2NPOO>{8`g)^rvLa_sgSDIh0fc3YLK0HV`BIFrVinb21CjIz&fQel@6wH6L zPZFZ*JEwk{J-{9Qfj4@qPq+-cU(XsxLZ4bVTYYwpWG&)zzlM%Io%x|0{%*;3ng)d} zsoY_c0%wCCwn2sJ{g#i3UzHw|eO@Ud&KaE%9dnYEq=(`p47@nQm)f@^0t?&$-cY2X zayd;yyq$Oj0(F-gyfxrr!I znUIWfg-G1`yC;iKwt54FhGi?6L6w&5tU^g0@XH^Qy{9*Tve?2lWp0br*LSb$x>j{! z3oCDt58WWSc@$k}K;^p7MB&qXGpdQ4w+6AWQ6HYZs!cE&RSqT`j08-K`9?nW&3zCf z_Y6A`lCj`*W^1oO`u>hhyk-w@^21d8)Tr$aqaf@kqvCbr$}e)v*DdY$>5R!4=@FsO z?k$<~r>}gtaKN(@m)T={!2s1@f4{d+59t)r$6z50{2bx7wsLD+++fn`^gJ}q9vE=l zDYl5>GHF874?p9UU9F^8$0UG{ZT1`+p1wvSxqfzo5(|JvvR9+Nl^6bg|E&=$EVPyZ zGY40OG2K}Pp?e!P;g#42^_~eP*@6|}FEwPI6$}B)Ke|C3xp7lXNlUd@2_#{i<5*Pg z6Wq*Luiyz$VpVhySRqw02^R=aaA`76mTd+8tKK@4u~ih{Vj`_hQdA%ECbVfE8_W6D zM2dxp*Op~oIz<)0fuu{OWvZMnIN~+FloV`rHTd|@{`xw75K7qM1r?e{z@XU}>koV8 zUQu7WCMj79LWA7*1Gls5g!FUfeZvAC%)PW!)whW$v`2GqZ<4Hh20)D#kEd15!5`S4 z$iagg#R2PdHC_#h($6N{XW1|0 zu0p@UojItfED6@5Gh^m`bs3hmM0c6Ne+`+bX5) zf=sj23BDmPSU3;nNlQpLX}iY-YE8^TG%{M3ArWR8KNuVpqRSO4nbbzVKJE z$kQ9nP5fcpr>B=XV9is+X|uBH=XiC-hzd!kdU})ZI2F$L)>T472}nab#INg-N%%UC zYu2Pw(wb|4;?D(h-Y+jczcFSa)I1(jGmlqf?EmpAdSjb%sd=vybCyI7FLz7s0fUE# zS(`CWV!dN*_$`v=R@H2^io&KP(gjD(AK>isL} zN00CaO|`pTGX&4U=E2ivFc<$z40slYHCPL5Od(kX3-3J3?e>$bhhOFquUcqhMpPtn zZ-Cl0EJNIXe^9B<9K-#eH0f0)GZK`>HnZa^|L0oe zdGKWqu2U#Kk9;#AKxz~v`R|^t`a@`=nNubV=CJ?GK3?(_EPgq#8XC&C{+|~A`2f2G zhQ}~Y!*yAh|6fdz2TZYF)4D9`{JXhu5}+yxjsz4}RmOiYOX~lTZoOo%G?-CaDe_-` wc9}~47Y!k=(CS6yt9#>LY`bicL2mxyy793hwrK;HG=d)`Id$1eY0J?610)t01ONa4 literal 0 HcmV?d00001 diff --git a/docs/04_cv32a65x/tristan/verif-spec/verification_specifications.adoc b/docs/04_cv32a65x/tristan/verif-spec/verification_specifications.adoc index 23efda5cd3..b7b59b27e1 100644 --- a/docs/04_cv32a65x/tristan/verif-spec/verification_specifications.adoc +++ b/docs/04_cv32a65x/tristan/verif-spec/verification_specifications.adoc @@ -492,6 +492,75 @@ image:./media/axiagentmerge.png[./media/axiagentmerge,width=602,height=285] At the time of writing this document, the merge of the two agents is not yet completed. It remains to publish on GitHub the agent and to integrate it with CVA6. +*_[.underline]#Interrupt Agent#_* + +This document describes the interrupt agent that plays as a interrupt controler for the CV32A65X, the agent is based on the following protocol: +https://github.com/openhwgroup/cva6/blob/master/verif/docs/Protocols/interrupt-verification.adoc + +[.underline]#Agent Architecture:# + +image:./media/interrupt_uvm_agent.png[./media/image5,width=618,height=366] + +[.underline]#Agent components:# + +The Interrupt agent provides following components: + +* uvma_interrupt_agent_c: UVM Agent. + +* uvma_interrupt_mon_c: Agent monitor, collects and broadcast transactions to the coverage model each time the interrupt interface changes. + +* uvma_interrupt_base_seq_c: Base sequence, instantiate agent configuration & context, and connect it with the sequencer configuration & context. + +* uvma_interrupt_seq_c: Generates interrupt requests & clear them based on the clear protocol decribe in link above. + +* uvma_interrupt_seq_item_c: Have main items of an interrupt transaction, `+interrupt_vector,+`interrupt_channel_mask and interrupt delays. + +* uvma_interrupt_sqr_c: Sequencer, receives requests from the sequence and send it to the driver. + +* uvma_interrupt_drv_c: drive the vif with the requests received from sequencer. + +* uvma_interrupt_cntxt_c: Agent context, instantiate VIF uma_interrupt_intf and memory uvml_mem. VIF and Memory are accessible in all components through context. + +* uvma_interrupt_cfg_c: Agent configuration, all available configuration fields are described in Configuration Fields. + +[.underline]#Supported features:# + +features are: + +* Asynchronous request: the agent support Asynchronously interrupts requests. + +* No channel Dependency: there’s no dependency between the interrupt channels, every one is managed independently. + +* Channel delay: provide delay after setting the interrupt request, also after clear it. + +* Randomize channel: full randomization of setting interrupt request. + +* Timeout: the agent is triggering a `+UVM_FATAL+` after a number of clock cycle if it failed to clear the interrupt request. + +[.underline]#Agent configuration Fields:# + +* is_active: Switch the agent mode to active. The agent support only UVM_ACTIVE mode (can’t be in passive mode). + +* trn_log_enabled: Enabling interrupt transaction logger when 1. + +* enable_interrupt: Enabling sending interrupt request when 1. + +* interrupt_plusarg_valid: Enabling interrupts from commande line request when 1. + +* num_irq_supported: Represent the number of interrupt channels supported. + +* irq_addr: Represent the memory address used by the interrupt clear mechanism. + +* enable_clear_irq: Enabling the interrupt clear mechanism when 1. + +* irq_timeout: Represent the number of clock cyle before the agent trigger a `+UVM_FATAL+` timeout. + +[.underline]#Sequences:# + +This agent provides only one sequence: + +* Set/Clear sequence: this sequence set interrupt request also clear it based on a protocol. + ==== UVCs No UVC used in this project diff --git a/verif/env/uvme/uvma_interrupt/README.md b/verif/env/uvme/uvma_interrupt/README.md index 2994761f7d..37edcd36ab 100644 --- a/verif/env/uvme/uvma_interrupt/README.md +++ b/verif/env/uvme/uvma_interrupt/README.md @@ -1,16 +1,3 @@ -Description of the interrupt agent. +*Interrupt Agent documentation:* -- The interrupt agent supports mainly 3 modes: - 1 - The agent sends one interrupt request, then we deassert it. - 2 - The agent sends several interrupt requests at the same time, with the same size, then we deassert the interrupt requests. - 3 - The agent sends randomized interrupt requests. - -- The interrupt agent has 2 type of delays in `uvma_interrupt_seq_item.sv`: - 1 - `irq_delay` is related to the delay between two interrupt request. - 2 - `irq_time` is related to the time the interrupt request could take. - -- The interrupt agent sends requests asynchronously. - -- To enable interrupt requests you should add the option `"+enable_interrupt"`. - -- There is no mechanism to clear the interrupt requests (on going). +You can see the UVM interrupt agent documentation in : https://gitlab-tss.gemalto.com/riscv/ohg-pr/cva6/-/blob/master/docs/04_cv32a65x/tristan/verif-spec/verification_specifications.adoc diff --git a/verif/env/uvme/uvma_interrupt/uvma_interrupt_pkg.sv b/verif/env/uvme/uvma_interrupt/uvma_interrupt_pkg.sv index dbe12ed238..0a08d68af4 100644 --- a/verif/env/uvme/uvma_interrupt/uvma_interrupt_pkg.sv +++ b/verif/env/uvme/uvma_interrupt/uvma_interrupt_pkg.sv @@ -29,8 +29,6 @@ package uvma_interrupt_pkg; import uvml_hrtbt_pkg::*; import uvml_trn_pkg ::*; import uvml_logs_pkg ::*; - import uvma_isacov_pkg ::*; - import uvma_rvfi_pkg ::*; parameter XLEN = 32; parameter int MAX_ADDR_WIDTH = `UVMA_AXI_ADDR_MAX_WIDTH ; // subjective maximum From f800707738d8a33b741fe2fa033298b6c929cae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Sintzoff?= <61976467+ASintzoff@users.noreply.github.com> Date: Fri, 22 Nov 2024 15:12:57 +0100 Subject: [PATCH 3/3] docs: update URL in CSR access DV plan (fix #2625) (#2627) CSR are no more described in CV32A6_Control_Status_Registers.html --- verif/docs/VerifPlans/csr_access/VP_IP000.yml | 6 ++-- verif/docs/VerifPlans/csr_access/VP_IP001.yml | 6 ++-- verif/docs/VerifPlans/csr_access/VP_IP002.yml | 6 ++-- verif/docs/VerifPlans/csr_access/VP_IP003.yml | 6 ++-- verif/docs/VerifPlans/csr_access/VP_IP004.yml | 6 ++-- .../csr_access/dvplan_csr-access.md | 30 +++++++++---------- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/verif/docs/VerifPlans/csr_access/VP_IP000.yml b/verif/docs/VerifPlans/csr_access/VP_IP000.yml index 664f24fee5..a62965d9d2 100644 --- a/verif/docs/VerifPlans/csr_access/VP_IP000.yml +++ b/verif/docs/VerifPlans/csr_access/VP_IP000.yml @@ -17,7 +17,7 @@ subfeatures: !!omap description: Upon reset, RISC-V CVA6 Machine mode RW CSRs must initialize to their respective POR value. reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' @@ -68,7 +68,7 @@ subfeatures: !!omap random values like 0xa5a5a5a5, 0x5a5a5a5a, 0xffa1ae40.. and read using the CSR instructions defined in the instruction set architecture (ISA). reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' @@ -94,7 +94,7 @@ subfeatures: !!omap description: Accessing RISC-V CVA6 Machine Mode CSRs in different privilege modes (User, Supervisor and Machine modes). reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' diff --git a/verif/docs/VerifPlans/csr_access/VP_IP001.yml b/verif/docs/VerifPlans/csr_access/VP_IP001.yml index 4e72a8156c..8b16419697 100644 --- a/verif/docs/VerifPlans/csr_access/VP_IP001.yml +++ b/verif/docs/VerifPlans/csr_access/VP_IP001.yml @@ -16,7 +16,7 @@ subfeatures: !!omap description: Upon reset,RISC-V CVA6 Machine RO(read only) CSR must initialize to their respective POR value. reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' @@ -42,7 +42,7 @@ subfeatures: !!omap random values like 0xa5a5a5a5, 0x5a5a5a5a, 0xffa1ae40.. and confirm whether write into RO CSRs is possible or not. reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' @@ -68,7 +68,7 @@ subfeatures: !!omap description: Accessing RISC-V Machine read only CSRs in different privilege modes (User, Supervisor and Machine modes). reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' diff --git a/verif/docs/VerifPlans/csr_access/VP_IP002.yml b/verif/docs/VerifPlans/csr_access/VP_IP002.yml index c615ae16e4..51ed9fa8d0 100644 --- a/verif/docs/VerifPlans/csr_access/VP_IP002.yml +++ b/verif/docs/VerifPlans/csr_access/VP_IP002.yml @@ -17,7 +17,7 @@ subfeatures: !!omap description: Upon reset, RISC-V CVA6 Supervisor mode RW CSRs must initialize to their respective POR value. reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' @@ -67,7 +67,7 @@ subfeatures: !!omap writing random values like 0xa5a5a5a5, 0x5a5a5a5a, 0xffa1ae40.. and read using the CSR instructions defined in the instruction set architecture (ISA). reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' @@ -93,7 +93,7 @@ subfeatures: !!omap description: Accessing RISC-V CVA6 Supervisor Mode CSRs in different privilege modes (User,Supervisor and Machine modes). reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' diff --git a/verif/docs/VerifPlans/csr_access/VP_IP003.yml b/verif/docs/VerifPlans/csr_access/VP_IP003.yml index 3267c6030f..3099b330be 100644 --- a/verif/docs/VerifPlans/csr_access/VP_IP003.yml +++ b/verif/docs/VerifPlans/csr_access/VP_IP003.yml @@ -16,7 +16,7 @@ subfeatures: !!omap description: Upon reset, RISC-V CVA6 User mode counter CSRs must initialize to their respective POR value. reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' @@ -51,7 +51,7 @@ subfeatures: !!omap two continuous reads and checking whether the value in the second read is greater than the value in the first read." reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' @@ -80,7 +80,7 @@ subfeatures: !!omap description: Accessing RISC-V CVA6 user Mode counter CSR in different privilege modes (User, Supervisor and Machine modes). reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' diff --git a/verif/docs/VerifPlans/csr_access/VP_IP004.yml b/verif/docs/VerifPlans/csr_access/VP_IP004.yml index 8c7d5b8871..2250afd03e 100644 --- a/verif/docs/VerifPlans/csr_access/VP_IP004.yml +++ b/verif/docs/VerifPlans/csr_access/VP_IP004.yml @@ -16,7 +16,7 @@ subfeatures: !!omap description: Upon reset, RISC-V CVA6 Machine mode counter CSRs must initialize to their respective POR value. reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' @@ -52,7 +52,7 @@ subfeatures: !!omap tested by performing two continuous reads and checking whether the value in the second read is greater than the value in the first read." reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' @@ -81,7 +81,7 @@ subfeatures: !!omap description: Accessing RISC-V CVA6 user Machine mode counter CSRs in different privilege modes (User, Supervisor and Machine modes). reqt_doc: - https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CV32A6_Control_Status_Registers.html + https://docs.openhwgroup.org/projects/cva6-user-manual/01_cva6_user/CSR_CV32A60X.html ref_mode: page ref_page: '' ref_section: '' diff --git a/verif/docs/VerifPlans/csr_access/dvplan_csr-access.md b/verif/docs/VerifPlans/csr_access/dvplan_csr-access.md index 60e8d9e63c..861c79e614 100644 --- a/verif/docs/VerifPlans/csr_access/dvplan_csr-access.md +++ b/verif/docs/VerifPlans/csr_access/dvplan_csr-access.md @@ -89,7 +89,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#item-000 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -153,7 +153,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id2 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -188,7 +188,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id3 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -223,7 +223,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id5 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -254,7 +254,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id6 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -287,7 +287,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id7 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -322,7 +322,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id9 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -384,7 +384,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id13 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -417,7 +417,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id15 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -451,7 +451,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id17 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -483,7 +483,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id18 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -524,7 +524,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id20 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -588,7 +588,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id23 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -620,7 +620,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id25 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description** @@ -662,7 +662,7 @@ Module: CSR ACCESS VERIFICATION[](#module-csr-access-verification "Permalink ##### Item: 000[](#id27 "Permalink to this headline") -* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CV32A6\_Control\_Status\_Registers.html +* **Requirement location:** https://docs.openhwgroup.org/projects/cva6-user-manual/01\_cva6\_user/CSR\_CV32A60X.html * **Feature Description**