From 9fc95b8769215ef8cfd4151549f08805771ebfb1 Mon Sep 17 00:00:00 2001 From: Alex Mykyta Date: Wed, 10 Dec 2025 23:17:33 -0800 Subject: [PATCH] Refactor readback mux implementation. Improves performance (#155) and eliminates illegal streaming operator usage (#165) --- docs/architecture.rst | 9 +- docs/dev_notes/Alpha-Beta Versioning | 10 - docs/dev_notes/template-layers/5-readback-mux | 115 ++++-- docs/diagrams/diagrams.odg | Bin 19782 -> 18292 bytes docs/diagrams/readback.png | Bin 90728 -> 0 bytes docs/diagrams/rt-readback-fanin.drawio | 242 +++++++++++ docs/diagrams/rt-readback-fanin.png | Bin 0 -> 62372 bytes pyproject.toml | 2 +- src/peakrdl_regblock/addr_decode.py | 5 +- src/peakrdl_regblock/exporter.py | 21 +- src/peakrdl_regblock/module_tmpl.sv | 65 +-- src/peakrdl_regblock/readback/__init__.py | 73 +--- src/peakrdl_regblock/readback/generators.py | 381 ------------------ src/peakrdl_regblock/readback/readback.py | 101 +++++ .../readback/readback_mux_generator.py | 361 +++++++++++++++++ .../readback/templates/empty_readback.sv | 7 + .../readback/templates/readback.sv | 94 ----- .../readback/templates/readback_no_rt.sv | 17 + .../readback/templates/readback_with_rt.sv | 82 ++++ tests/README.md | 10 +- tests/test_only_external_blocks/__init__.py | 0 tests/test_only_external_blocks/regblock.rdl | 11 + .../test_only_external_blocks/tb_template.sv | 115 ++++++ tests/test_only_external_blocks/testcase.py | 29 ++ 24 files changed, 1116 insertions(+), 634 deletions(-) delete mode 100644 docs/dev_notes/Alpha-Beta Versioning delete mode 100644 docs/diagrams/readback.png create mode 100644 docs/diagrams/rt-readback-fanin.drawio create mode 100644 docs/diagrams/rt-readback-fanin.png delete mode 100644 src/peakrdl_regblock/readback/generators.py create mode 100644 src/peakrdl_regblock/readback/readback.py create mode 100644 src/peakrdl_regblock/readback/readback_mux_generator.py create mode 100644 src/peakrdl_regblock/readback/templates/empty_readback.sv delete mode 100644 src/peakrdl_regblock/readback/templates/readback.sv create mode 100644 src/peakrdl_regblock/readback/templates/readback_no_rt.sv create mode 100644 src/peakrdl_regblock/readback/templates/readback_with_rt.sv create mode 100644 tests/test_only_external_blocks/__init__.py create mode 100644 tests/test_only_external_blocks/regblock.rdl create mode 100644 tests/test_only_external_blocks/tb_template.sv create mode 100644 tests/test_only_external_blocks/testcase.py diff --git a/docs/architecture.rst b/docs/architecture.rst index daa88f8..4a0b74c 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -38,18 +38,15 @@ This section also assigns any hardware interface outputs. Readback -------- -The readback layer aggregates and reduces all readable registers into a single -read response. During a read operation, the same address decode strobes are used -to select the active register that is being accessed. -This allows for a simple OR-reduction operation to be used to compute the read -data response. +The readback layer aggregates and MUXes all readable registers into a single +read response. For designs with a large number of software-readable registers, an optional fanin re-timing stage can be enabled. This stage is automatically inserted at a balanced point in the read-data reduction so that fanin and logic-levels are optimally reduced. -.. figure:: diagrams/readback.png +.. figure:: diagrams/rt-readback-fanin.png :width: 65% :align: center diff --git a/docs/dev_notes/Alpha-Beta Versioning b/docs/dev_notes/Alpha-Beta Versioning deleted file mode 100644 index c8a089d..0000000 --- a/docs/dev_notes/Alpha-Beta Versioning +++ /dev/null @@ -1,10 +0,0 @@ -Holy smokes this is complicated - -Keep this exporter in Alpha/Beta for a while -Add some text in the readme or somewhere: - - No guarantees of correctness! This is always true with open source software, - but even more here! - Be sure to do your own validation before using this in production. - - Alpha means the implementation may change drastically! - Unlike official sem-ver, I am not making any guarantees on compatibility - - I need your help! Validating, finding edge cases, etc... diff --git a/docs/dev_notes/template-layers/5-readback-mux b/docs/dev_notes/template-layers/5-readback-mux index fa53102..7e9702c 100644 --- a/docs/dev_notes/template-layers/5-readback-mux +++ b/docs/dev_notes/template-layers/5-readback-mux @@ -1,35 +1,84 @@ -------------------------------------------------------------------------------- Readback mux layer -------------------------------------------------------------------------------- +Use a large always_comb block + many if statements that select the read data +based on the cpuif address. +Loops are handled the same way as address decode. -Implementation: - - Big always_comb block - - Initialize default rd_data value - - Lotsa if statements that operate on reg strb to assign rd_data - - Merges all fields together into reg - - pulls value from storage element struct, or input struct - - Provision for optional flop stage? +Other options that were considered: + - Flat case statement + con: Difficult to represent arrays. Essentially requires unrolling + con: complicates retiming strategies + con: Representing a range (required for externals) is cumbersome. Possible with stacked casez wildcards. + - AND field data with strobe, then massive OR reduce + This was the strategy prior to v1.3, but turned out to infer more overhead + than originally anticipated + - Assigning data to a flat register array, then directly indexing via address + con: Would work fine, but scales poorly for sparse regblocks. + Namely, simulators would likely allocate memory for the entire array + - Assign to a flat array that is packed sequentially, then directly indexing using a derived packed index + Concern that for sparse regfiles, the translation of addr --> packed index + becomes a nontrivial logic function -Mux Strategy: - Flat case statement: - -- Cant parameterize - + better performance? +Pros: + - Scales well for arrays since loops can be used + - Externals work well, as address ranges can be compared + - Synthesis results show more efficient logic inference - Flat 1-hot array then OR reduce: - - Create a bus-wide flat array - eg: 32-bits x N readable registers - - Assign each element: - the readback value of each register - ... masked by the register's access strobe - - I could also stuff an extra bit into the array that denotes the read is valid - A missed read will OR reduce down to a 0 - - Finally, OR reduce all the elements in the array down to a flat 32-bit bus - - Retiming the large OR fanin can be done by chopping up the array into stages - for 2 stages, sqrt(N) gives each stage's fanin size. Round to favor - more fanin on 2nd stage - 3 stages uses cube-root. etc... - - This has the benefit of re-using the address decode logic. - synth can choose to replicate logic if fanout is bad +Example: + logic [7:0] out; + always_comb begin + out = '0; + for(int i=0; i<64; i++) begin + if(i == addr) out = data[i]; + end + end + + +How to implement retiming: + Ideally this would partition the design into several equal sub-regions, but + with loop structures, this is pretty difficult.. + What if instead, it is partitioned into equal address ranges? + + First stage compares the lower-half of the address bits. + Values are assigned to the appropriate output "bin" + + logic [7:0] out[8]; + always_comb begin + for(int i=0; i<8; i++) out[i] = '0; + + for(int i=0; i<64; i++) begin + automatic bit [5:0] this_addr = i; + + if(this_addr[2:0] == addr[2:0]) out[this_addr[5:3]] = data[i]; + end + end + + (not showing retiming ff for `out` and `addr`) + The second stage muxes down the resulting bins using the high address bits. + If the user up-sizes the address bits, need to check the upper bits to prevent aliasing + Assuming min address bit range is [5:0], but it was padded up to [8:0], do the following: + + logic [7:0] rd_data; + always_comb begin + if(addr[8:6] != '0) begin + // Invalid read range + rd_data = '0; + end else begin + rd_data = out[addr[5:3]]; + end + end + +Retiming with external blocks + One minor downside is the above scheme does not work well for external blocks + that span a range of addresses. Depending on the range, it may span multiple + retiming bins which complicates how this would be assigned cleanly. + This would be complicated even further with arrays of externals since the + span of bins could change depending on the iteration. + + Since externals can already be retimed, and large fanin of external blocks + is likely less of a concern, implement these as a separate readback mux on + the side that does not get retimed at all. WARNING: @@ -42,8 +91,14 @@ WARNING: Forwards response strobe back up to cpu interface layer -TODO: - Dont forget about alias registers here -TODO: - Does the endinness the user sets matter anywhere? +Variables: + From decode: + decoded_addr + decoded_req + decoded_req_is_wr + + Response: + readback_done + readback_err + readback_data diff --git a/docs/diagrams/diagrams.odg b/docs/diagrams/diagrams.odg index 5b42eb6c76134be390521086f32cee3d6a577d49..dd6fab76bf3ab20a59777b14fe9cf0e282989986 100644 GIT binary patch delta 16346 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 UA3hQQ0PW+U`xuR{BL86jAAml=MF0Q* delta 17788 zcmZ5`18^om*X|qJwyjMzww;Z=v2A0Ljcspi+t!8~XJc<{JGuLR|NZJ#-L9JMgVt0} z_tWQ`xr+t+l?jHdBnJVB2?D`_Ku|Q=>IujSkpC$S*#2)xnshD(pU?~YUpCKTE3UCcFSsYZOr`a z#Oj@}+!x;K0y+{?qU%p*GjDgtZ?!~Rw7vVsQ*d5B){~|w7DN9YA9y!0-7-j4G_Y9PHr&oriI;L-@q~|hLaax(Lfz5TWu3^qhkQbVBNyspeVs5OtTePsgMpjx+ z+90}jZVcNqK7H;dg}E`8wyw`FnDxV4WqMLEX^nBX0q9FZ!!47L+UP#)h1~Vy2+Th^ z4m}lQ?I)s1?ZJE+8-CrJFGAR;Bxc*ONF$t>b4umeW>HkHVBdWq265gPCk}HomW}*5 zBfs8M>g>;VHygJqALB~KSgVi!LwLd|cgv#Jfi-#PqPSo^N7YF5w`F{t>J)9KPC&}% zfic$>2GF=DD*m!Jq;K>~MoxEhKtKG)vTe2l7lMvXoB}t`LQt{5-VAdU5*B;??47gv z>k`%4LBt(P1DCh%4BIe$VuZP7H8Ju`+cX{m`Meek0c1}Yd#1lSwalO5sG0j^h+atC zb}qUNzd~KpGf2*qL|lO;%uqY;5>!v&ojHQLD4G)9_K(0X?ps08V$av7eAcl!?`E;pRH4|3rn-mF#EyNQKfd#HOvgNR?tf{8qhtC! z?=)&(p zD?nZX6h-MG)m#TdW{_52ilzrvX%@Cj!VNB@qu96_Z37p7DGHrd+f3t**ZHjWWVIJCUz4Q}hlF4Z@-{mpV*cklkouYl*l}ynK#-6QK4#%)+fI7-S*X!C=_VndN zZVEX+ftG%5cZGAi74Qn}$HVQEShUSW2wYQYKau@r%ZxTnSjF$3`jObc9Q2#~42KOG z;ebo-T19<3;v`b5OUG^||3G~lETr%8(~|w9hU^($isTheue<>YZDu(B-?YH%}-L=!%B4VbVueqz=TYkomnN8RUgijbza}~Xb$|Vh7j-w9; zpMu-R^;+~rUp{?1;xjQw9i+ZD0Rd(i1cp1jcfH82Ps~gv>mww0xR86oT^!w#^Qf{v z@E!;|cE0<{gL??NvxvQ+0DXnZc+op1yWw#&Xd$XniQK|MS$qZ66udXXBiujY%K5?` z`}!ZtAtY`yAntEjn+85-9MQQO6h+XZiFk;8<-aS3t74D{qZEd>Fh5{~YXjk9pngx- zY(>wmcuuuy?XhbVsvpR@DhsisZZG0cg|TSMscpVLuOUsbCAe9DgHTWii(_&+s3Z{M zTLP#PbYXbG)o8mb?1dWnC^rQ55&p*o_!$yN(2wzhZR8hP*G5}o=vHLf83N;VkxrI8 zVE7D==ZCVN?MohLvVdPw0vzMjg3ox|&i=OS84y!k&;q+d_=AVwlIG3wNCT&rXjk$h z*n7I5McD9pm^Vf$Q$wH=>Sv4Pn5qukcPy8Cd;$d;alR5N?(QHnudy2UnUo25ys?Rl zsOjHD@G9u6S~j%GA!w9owmg;aKh}%j%o3ALhcl1tH0ytx^kC^a&H`Mv6LSh=lZp$4 zBW^fUR0esWgFP{=oVIk9I5|sSeCef~*wM`O5~~V0$Q{{X{%R@j#MS^896aAX0*dV< zHi)7}-D_~a_YcdhUynAj5AMv?=JUsRJ!H#)jFb(E4e|w};hD$T?xszlB-%Oye&C*k zr_Ef}=Ayi~?Yzm}yaQs!VnKd3_&h&;Xdo4w_SCq=;45f$y&gNtBRZJfJ>)3cR7^RY zuDW#yIqTgoTu?nnc)Wq;~~+KnX&P1$|KT%-s>0@BukFZ<{*DB#&H$;Fv)g& z)2s>U*pUcVKshyutVgSEW&;2I$Q?);6E#NMLtNpLiix8{1n38bao1)}>mtw}N;Hve zcA3ocW?I*sWp(9?&6Zh9%}qBA>rD&64+thykqgAPYQ8)%YHdjeOX`S?VQlw^^@J2H zX5UWFWOZhJ@b5s}$7?RI1aIMLeDu?@QO1Rf0->zjOaKbHOE9j8DD2PqG->~|M;6qC zB&x41qsUl6i!vm=h{m~4fJryp$0bf^;P{o5iLW;R;>N~O4^GiUHX z)R8(ly8waco@T`K{_~YrvA?%FXK;b$N$H`5_>tSoaUUQ=AfEKeB4wvmiIKJBafOda z+qdkvs!cX{gP9+TTA`Fnx>|gbJjYy#LR+CFj`&BdB`rak7HhPayo6Nda#(F0hsi27xrHKm*f=_EMNYp{(QJKh&uCQv)xYQAmt_-DwE0=Lsxz`mAD4s%eR*T1~AgoqpW|8^H}=G_xHY68C6T-CcU8ODZCaU10uM=Ypn? zSa1y2<@#NP*s)exv8!s~_iGKKn_rNj;+vGHl?Hs2db1rOq9-)$>TF)@#5qKc^)5zj zdls_yP8r<`Sh!s8q%xUqaDTRF$N<(Y+nMBs4i~jEk7Lr}UKZ)prE#8pGQXK7mF+ zpRbO&)2R-H#say;J&*3gj+58uqD5Jl4w9mb8op}h1M08)hp_3P-?{*+5WW6;+45j>5pZR7d=<{JUcLCmXlwrCM;*k7HaF^5*sIsus{8wU+%G235)Af-y~*P z-`+#e5m%9&%B1zt<93w!3;K~GQBQIsJC{sQKJo;fSR^$M=2g%0!v$65-^>{H#rDJ#d71G@K^t8QE(D1O z{y8i9$&^a%Y$L`6H(W5nR?7UW^v-8t12+Zyb8u`g3+Z}*&Pn6wA%;SZn3bFP2?(IJ zOQZ>vK>9EpePc8!h&%jwsR-L~Wg()d63?QK5>9IQ5bD=f!aEzagiD+uMtgf_Ctj`k zGEIKsQ4TB0FZ)u%aR~TsgCFdF z$Jk-SVQlxA%6MQFGpF4zdn!ACpC3&-rXxOBU%#hHAFZuyO4^JwSEY{W`c54;T3|)f zf3!d@$Ni=3^NsfB?XFxMCO?c~x09v8OFzv+`-29hX8lNeA;vB&i4FYr!osS2Y z6Mt?mBi=G@JE577_67NoOd3$h!28!n=hsinm#4B}Qw5oubsiFp83y*kI+Up|bt6aI zgEP1SQI+0;@vC@0O7*TRkBG;ryR?o9V*idO2PKT4NVtm0G&AK6=rfrhEBd)|nXdVy zwk9echIF?+BCwyJ^}59Lp5b<q~XxUZ6FY2S?L-IX9r zu!${qehe9CP<_k=CZ@e@z(>vJEirsmuP4L8@%CDJ8%6yRB9U&i#h=xyLE2se%x~xQ zWYi+XL=&pL7qQY>k2NTQ!SBPep)rY~K0L?g(VC;}r6zAq)cSED7b?$5hQw^?IU?=g z_ii_Z6)(NtRyusbD9ORV=4sPzWFdk;J?bFP|JqNmu(1EJpOO~HNP%5WOux(8Wuw&$ zcV0%^#Em}NqjU!ySVKe^&m=o2Ow+LxQ^eO(AG=XbImCR<3)jprP>bu-;=eT8-22wz zbR5Qko#^PEH7|(mLh_}tU2J)mlZ#{RIcwdanWX2cl*V|kV$g1DSbm>M13q&UWhQ&< zE8SRb_YxTnC05-r!N!gTL-c@+#td*nPs(Abwo*ESm+Zm2l3UcL`0 zd-2dM>Kn2)-MJ`mg%iLbwasd6KLv}FxVFJnG=xKAmR9 z53cTc{sQ|WPK4(sSEF1Fes&|Rq%_;lZToDa)&*&8+TC;+_;{^Er8~4{xxPY&Zf1F{ zKNGwWH{yy;KzW@YTd_lyuc?7U?vYSruGxC@GZzoVC_#vpzu4Eeuc(IMf>UkJbT7o} z#oXL|qc{`vS8>|*s=jOgiT|F%ZH)(G&_SOzPp~y?S|80}@LIL8{xd4qBO#4uvY+6L z(0PZ{zo9@7K;<^}i5=!X;(;-jr6NUlZvMjDWSVmXyLD6iaq<|#*q)Vvr@XtPsrB^L%B64hQZ4R)*IUooOmO!D!HQCjd$(c15>Y< zA&>bNZ8f9@y4u`tv0U8y4hr%lKSLGkJw1Y?V@VGF2pMkiudk$j7cQfTzJ)7^53IxZ zF#?g62r%c-VnVNv^-XS&yJ5$WC1jM+ z!sQRo4XO-2M(;xZ3Z`r=&jRyV%FC0_%dbnLnOHdpEhV~J_y?djC><8G_olz%ENjLv zFNF{^b8-HwlqW$gwBDbfPC6`c7M&_+@S_k81~`?r8)~GS?B8-IlPD;wyjO8)3)HWMO}t#?c2eRq8Seo)F<`H3Sd0gJvDi( zUwcjR^@WI7eCEj7fHDwYI}@VYJj#)3RgI9qpmTkGZ~umgxPS=ZV0{;diS7Tkg6=p2 z4;0t19I-&Pi-Y6viyPrSl{&wV3ZJ>%QYHkW@#JP)e^HK6vg0FQ0|4k??L^q>PLN)RLC0ho+xR1V=t^M1h3h zh8g=k5)B#0IcLekjII3zFc?|ju*=Wird{QKe_W+KO zF$>gk8Q~%`RUmd|P27yKj&79orEQoT{Z~-E^h~+A|o6hCp-fv*u2h&o}5)bTUK%!nfIe2&kZ8SMVc++{e z(_UkYE3&CRj#fF$UQu;F+OYnpADANSX$JY&li0Nb;=T*p3)x{9xTXHwlWNJVl^-Ey zGt+7IHS;l+!Tjmg{Tpx^A3Lo3#uz^&7~eclGCvSIda)x{^Bf*(F67^ZKDqvw?;UGi zPT69%4j!;`&)(@T!MrT>0*`kOzVNvWHdUt>t)kK2I-j^_xsWur3SLilfwz23*3v+H zewL=di)yI)*f zw$(XzqG{(fh9Pr<>{w{-z41IW$oCRv81Ds`Dbza`vE7ZjjJgcQ?B!(zqG6cIVbmDAQRsxy=9! zF52BOz7yMa`C-5=LQ-smUR;h6Fp>>4wP<p;xGxcaW`bq^Wm+6A|j2PJrgCi#T3r};%@1dD>AB|&L&piBi&t`ev~8C0l+RHF&1)`qV64%eU$-=z-< zb;iI^Z(^6ciK`7!nl{5fd335)~aC8WkTH^D`nQAv!)ZCLug1J|{LlDKRN7DLFYg zH9aFMH7hGCB&i@gr8qLZH0Eb@PHtX&Ze31Zc1~SDQbAK{Nn0jR(OJ+GRMH+=+8JKn z9Z^_VP*qh`S5wv4)YRG8nO)PDTQ`v3FjUksR?;?6)-hGpGgsXoT|XRG|0}+EJh5#m zwPQNHVC2Ko4HlPY zpEc6sc)0rbl+)<5SnM}ve6l?>vrhC=VVhP{=R$|LO<0!IeuH+@NJjMdmkm8SA*T3e zlIy~Y#qig|t+MpkrO31P7}Q#s6FkR=u2gS6#PI%la5H%{d#xi$-ldFP&^3@qMsS>r z`muW6QWj$TIJbUji8zA+Mqj`?&@ z1#zWZzoDG`aDct7_bI;UL$fl_R2B1*cA&vV(be`@@x2}`0$u! z(#uKHhf5zwAQhmvOS70{JyPUko{JOTltBjwn3=# z25*QowgU|{qZhApmW=`_~QznTFC zItj{`DDi-d+8!VNiB9LaaRjB8cd>v)xOgv?SIB9nv}c<4GiZ0E2Mc~3t|TsU@MJi! zgURD@{i>g!a8P9o$QVZ$&!|OqJ>W!biQcZ;EnKv13RiVs9kZoPdpXHQDmECckC92( z9itakJfL|M>M8j+a&zo00A19wI1Jc3?Fv%TwJo5F4j=U+>!1sX2ALs_N(OxTeLUj~ z982+h3`js~Rq6$pux_~vObKi~$PD+6)ai|Qe4lpPIIW@J#O5lF-M_l~PSnRp0_N{_ zbPn~l@UKY{>{S_Y{~cAtmS&qqKQx)n1{0804Vh_1(O0|4OcQ_rX3fwC0NgEme`|J% z&xUvpt1WT~^x#_z9A_Q;6@Qz7nXkYqeFI&B!GrywL@1-J)ZK}iE)G0!rU+Q#;{E$? zi7EO-Atp0CY{xz^5%R)Nw7P#ucqxHFmgR$5Y`lnR+_&3WEF#<{Q23Wzx`v@7rY%`TflTdeOvY7AoyKtNnF;(>2mG)%F5{vO z>M1vhyiZY(&XSZ^!5LPm6P9#5URA;Oy!|)hFhZL>979?26LVia5Uee45q*M39j3UYbkTan9w*I!oY5nuLY3 z{TP96D*{PjfH=wl`F^If;vQfEi6nAr5U~4WLL%VE z;iJn|Y$k_W2b{|gaul!5)k29ACj>;m2>usQtAeF(iL4JAhy*pRtwLMOALqF0KER^6 zjP(T6lH8N^Nk)Loz1M{0fGP_q+bq1{e`iSF(#87A$!XZo-CO^F?6!C-1Q@3*r1Tb0 zV+QyEjOfC|i&?Q4V?yHKzRwppIerf{e8nJ^iX8}@T%$8H)NKT^fYO>4WW#S!$G+Y# zZ)z9&^PK?8H~0@3HE@GYpHml)_odt|uO&U0;Z?<7e<5&a_GgsohQmNy`k>1L-kw!h zL&?eR4A&l(?V0?b+TMrp(^_KwC!ltsWIGNa^9M}_9Aw)y8ma%9HANrtJmF74u5@X{ zgOpKt$D?yGA%7X)YXhDq=N6VcCD5K04P=`#_%fh@JeOk7)RiI*atY(96T-GRDZdml zW{w8cZZzMAXaaAg(;M$^6VtuUmiiVmrmZ1*eMlJFSrHUG=u*xTVa-?)0WW_(N*;(F zFC6R$C*iIZ$;J%ez&>nG|K$36olZ<|KA&xnV|FbIurJUMKlgq4_2^XwxycQdGnqa- zsR29$5ieztfDPo{A~j7^2-hITD?%8oy`0HScV7)uvIsoh#KF(?Swx$VkRyG^0DF5z z@YfGe={+p7WtVzjs%)d0Vf3Xr{*l@zwsYt1`5U3Gbxl-EsX7kMwe9ryCS7<$nP^eN zZp|!t63(zCJ)=?eK-VSP6H5}r=^p?Y^#O3RcP|+2WGkZvf|@b!m#C7z*7ejuKv z<942;tuh?c^A9yL;T=UWZ`>49*_Yn0ek$}(3AyA>>;h$h2w=!r5kq}ypN7UQfVD7V z=E0=BNx|c_Ng+v*3Wd+##VKF?A`Z2o2;`?3h6`Di4LaDhB7OWpGaTx{j)M4&gvZCq(EST%3M&5O z1t+zXr0QPzR}0C(QyPpti>bSd3|taCIfYnX{>{hh5fhk#8xlF|v(|?6)pFHxHEVXP%_5cV zZsX%titg^x0iSO~7>xjSx>6R z0182{SC3UXi&k7}ic=ww#lk5rUqTKRT`4veN7{!J4bpBvxS7d;Ujvf_wwYIvm9!zh zP(N0LgSgnhG5yXOQ|_VaO5c6u43C!-FIj6+vGek{9DTRk&cG|EguPdPX69sc|FntM zO8{l8m}M`QzTt|PcZe-6B+-19Jf(?=r}LTZEq^b`%G#AckKJUPGl+Y$`l) zlqA4paqCP~>r#PBg!B%Yhp_3%Y4eh`TyFla0$*>nKc&9n(zjrWnHaZ@-C4fG8l5#C zkPB09ea+PykHb9K_c0iNQl$Ue@yxeK4(97{aeVQ{H+U_=Unw1643RpE=lYSOrD_YP z%AMsrq^3S-?O~j+m7sz}UUy2oKaW2>J!yHug=x)-fyDwpCrqctRJebpGa#+t4bgeP zI_>u%t5sQd6su%^)m_44AprYc5ozIAQ+b2mmO6aaM-?3z;dG!R8U;nmM#|7Pjl%r5 zHwrS{+S)ck!0Gb+{;{Q%-J#P&N>TUh3ncA;k39Bs3Pd4HY>XbEfLk65e@UV&*h^NX z&jqgKNiP8CD$X0404`b45Gxmk%$-3TDXR4qXiVi+lXL9~UMsMDXUOQtXky7%+krJj zWe#k*Y9}%(+^FGFvaoeC0ac(sP_l;x*b8hSpvK(kB9`CZ5SSIG;!owPY%X zkINJIyL1>gs-Hdih--pVMtCZfR4Aybfc(Np<}7LD9y7czFW0~pOn||(E*;nMd#brZ z7yqCcGLr#^G$|tEP!~g>8lu-;AdWH56+syHHiku@aX$TR55-*&y}8&=>;nA8uDu=V z8Emton9UyEg3C^ulWTEtL*G9-&kP~n%Qz2U#kQ%v+;R{NXpjkT+Mm?o&gP*|91|FF z(G~^<`1#U_pDaHUg4??=BoS-rkr=roXBwa^trVK5@IOtrxvBwSNZK{TFV?=oHOJpI zW}oc` z5RX_jB?bf$^UkE;z`@bn)FhE>G>j%(T>^4}X5<1lWfGR#-kov4WQQ`ywSkYN2c@k} zOLBl*s&&DmkhCH|mhk%c8@hGLmq>`fPZQ?Pk^IUC(4PqM&50Z2Fif2qN5SS2V@;d{vREm{otJYa3ziHYipD6Ess`e>ot7%~84FasOE2BpQh17C~- zZlH{1kb^Qg`_D!&j{ptbmY?xAFU4?TY_j_3zkM8=+YX1HPZ&W=;Hp|Lmi45DoZ}0Sw8%yRkaa zcK7`?nsC5sD@5B4G9Y*Y;n;QZiIc5&AvUD*;?9IfyAzLJ}J$>OM%l~mjuxn#sz(&y7Fpu;Mix`Qeb_XeFUrDYfTaHxb+D#AdO zBFKb|TKGFE=c{$1YD_g1^2G_D0XYQl1vc=y^KaV|s!%Y*Kr8sx;g0h?M1WKgC=yFC z75K(2pHI@=RWTG+vCrzM|>ug}gyBAB69MIK2Gwe0V+;kTbdX5hi? zyRl<*?H@W!G)s9Tn~s`CeGa;OUcGNF9|`LO(QMnAY5xOYH*6)7H%G+wSgZ?OQemdX zfU|GB__zgt#%FL=GEHs-3sr!oXA3xq)%L15$lPhIUL3kimmKGB>{O)zT+<#K_;Qr* zSi6~SOM%mcqh2pDH>XKpDS{oTa12GjK59)Jg7Kj|9h`5-bj-Pu0>pr<;WMll$2g|! zU!#c0$caEXMr>4BTUe!e*lmUye){y&mM8bshF(R0afO5S6PYgH;IyfVv|y;+lcK}_ zcf)$$_22Zb9atBcq{8Q`U?<{MjjNv+D~x@;?Jj01!mvt(u#V?sd~2J#hxqyjEE-lf z1B`~98^u+oHnIH$HVepg=2qKt3jP03lN`KC+oMiuu*8rA+!t&O%y#;LKLeVV8SU$d zXU8636ML%EZ4DDB;Rp7JWd;^|*p?&4F@61AwZi74(X68J(JQQtvk zO(;#|d>QsrGOE`DcR~Vd+?Dk^MtjM2h-Iei(1i8PqZR)JjJ%1xW1zBGI$gAq5N{w6 zWSJhMqpue~i0XT?+ml<81k0RLLgLC$&888Mr>t6c$Rf=uu}Wj0U}9XO%2n4!*r>LC zE4WB|7|XmyLn{26ys!7oj>yFp&B<_-Tpz5QUKU@9w^fcDf|KY|eBL1IRH!E#S2f2PI!}oWg=MG(b_A`Y8;9`B9|_R@ z*9`&9X#dvb!d7zzwMm`7R;X=1{rdaNll0UXoci`2GgziEQNmiT^+gEs|Na^=`s+iQu`BwA z;M3}rs_l_vTrtGk9~+TYv&unaH4jSHi-I2MoIQP3P5Ur^DY0T4R?KYiM}DgEV&HcX z?hJ@k7Cuo)` z$)cm7i|>WCLaIj7k&*RtPmC+7~Aj#c|P87 zT@ZeS#J%@oUN6&==7(PCqJts!@a*}aK080DTs#-h__?_h}k^T+IeB}x1!M8I+E zp0xAFWhrUXX`qKdQTkY?c?Ch|S6svMoQ;0hTD#>h@QjHnPCDq#l#A*dp}GA+@BaSi z7B|#iy`=ez$DupahWT-$!=t00*l=GS-Y5J={G8tU?vWoENW&SXc(iiPiCZ2kd;MPm zmozW8-Zxq|&G&Ssvd^_kyIo+tCIG(Rqa?9HlzzSS6R*wp6FS5=kJDxkSLAE;{@Yd? z+Q?tLA3iD3tSA>B{%$uY9yxez{Tu!3eEoWs8$0>Oeit`A=HawmQLxc0&^{hZZs6-U zvt2?3+Qc5;oH7e9AiMMy*NP;zo}LoDdLKNN*(od`&HS%4kh^X_{) zAF0!rHmd4Yn>9p*kEm1rPims;8_bJxiU1?r(=v|pj_bE~xf}ir#>6mZ{n*&c-9uIn zkDM^*tDNo~JxY}=zRi6M%-nM-M;lA1Q{eS_Q0jDSCCf6FlpUo#`Q2nW4`Y1QBQ}Sm zq}z_+)R+Icvn?LBvY z&1N$G>RX{5_VOaNfD61oU5h!j9#;@8#!%JyJ}$4I{_2)P38g`_&Oxf#JHSf2s@*=3 zuJkB3z?jCbYD6ITyLCk{@9eo&@7~|(u(uztcd*;bTKrgfnQbr$@HmnDhUh?9WuCJi zJ@)K2@G~Rs-p&%ueHw^lP>6WF(LD?pibV9e!VjM6S=c`c#Rd|`aOOQIn)SKn@A@T9 z1?J|>JLuneXAXRPZogn!S&l2vtU8X!gx}_@$G>hq8xv15;j1csFW#e6d2ht={(Up) zE#F^tX1?z6c{ja2a=BVA%ZvQ0%5B42p(d+zW-vc!SnAdkf#*fr8~YWuA&aVsMvwqt zZ-vr`7i$${bp=kdMrf8~Sx6K}q!eaJeEDHt$6AipDqS~CVF7W;^=q*uIBt1RNA9Jc zBn0v%n4S4-aZKmn&g7IB--`q1Y;O_NYs8U0_2=K`i(2AM5>J;y`-J}2eazsCgXYz1 zgr2k%kF`!(dKrh{l@SNO%M8GI{T!oVj=%*c?@x?JE8u~$qArF?R`;-SZ?W`?0Conl ztZ+h03F?5u2|adDrYenM9M>)Ok5Cm92JH6LD&bY zyPL8`YGuyWM&BvlLep{=9Z^q~nM8rW1mt@};wvtklYgVl-F~@N8NY`lGEiIH|_ECET_8(m%i`GyCJ&?W~7KhpZ)y8Q_?# z2RtE(|HVKl&$6e(;tpw(*;e#7OQf}srZyg7*dSDXODfUK<9i*fA(BlO(V0&qSxJ#% zkpJP4Co@ff^Wr5_Bvp(V!x&SYbCAe+AxO3;1~^tsPH|XKK4-r(Jg`i6!z}FTNGyZ z?ll|gcGS0ZQN(zccASA2H!RAHw2SP$2fq)?2BGp+2u~b)U#9M>ZI9fy4+f)FaN9n&6AaTuI#7#X>T3 z66!oJaV-LOgsk%;rg&X%NB{mnvk9m|7r@mAnIbU<;HDkJer4H5ERPH3VICo7?3Yu9 zf~#Qn0o`Tsm4hhqb0%iX%+9_DFG|OV0``&ljP79>;6ly6x2@E>hV~e^Lr&_3oz5PW zU%!v5rTZQd6HbU1c=3mjEjmhk9;kl}fGx$Xq0eh2#3F#pG5b}TSuS>OpO#ey!4lw= zVf?+0VQgVrTOGTTp+8}cGOZ9VD<)^UyXt%Pu~7;fzoF;t=p{NkJbcBQIlDFGUm(r- zWc{Af>jb2eOzU433V!7B`~5dWo?JYRL$BdLyo+Q*J%Q%5jaUvc8D4{m8gm%VSms+Wq{^Wa}(>#0lo1!>-q8FC* z(Dg*8+d*&(0y`hgkrQhe!$`$O1VBZ&fe@i!yyO%?nqySWC*x4vJ5j?9~-WS?ffBY!Q$)r&R-9sz)SB`|~Mk1 z_&)8J{DyjJMIVmP^P9p@lR?}ysf&q&F_ukZjWL_T-5e7?a<`6G_|Ge*$VgeZ*Rf{n zo)2RWA2y5|V-_B8w%VmjvfF2AhSi!6i}l*s*^Z&0qmJ1ekv(DkZw-yneM6ESmW#`* z4lfy{%e{atfsad?bP_$Aq_1Mx=+M{69d7RVUtsfRd=$a;{VSG^?QE_SMjV3WX6?r% z@JZuSGe8+q8uiPN*3&|;AeEmX-_u)jBrzEv5u5*f>W~7L&;7(S1cdJc(0a=(jJJ2w zD#i&@QhMW_=I)9tuD~9)#TYBz36JSZ$#9R*?DGAL`ULe6K<>)cVfI&cZ4ZU z470(-VMzEhq{4pE(ko|X-=?7x`pfFNA28IY1qgPj;?gkwb>nYlj3BFhhU19W_wDDa zr8U!LtmRISkBuCpI&u3>6U-Y%^M(Y*+3VKTjqy@D3wjfP0f4(JRv{W^)H36nuf;F- z;nMd+4D2XtjEYoQC%B819|?m&LX?AY^N!D@qwjo=htj){Tf7bEe;UwR8qnc0)%J^M zE$JB@(P_bx5q`2mq9Klq!7knqeeDz2bhrYb-ownknT#v7ib_UUbP_CGLsTJ0B14ga zDKBA?TK$AK1!O>d0TuN0k!1@}Fk6=pFK~%`LD7=z8Mp=!pRuofmWa{fse<=g-<%YV z23}T7Q@r^BU^U~hatqwP*&ZJ(9L;zFR*MJ?ZM=0;rXX$*Wtm^82HCeap>50LS2cw_ zN1Vp!Y{2WtBSHIq4ZYp>!%pj_*(2@6w;E}>Grfj7V0Y`e5U1_B@=+STS3x3){l#*O z?+qc&9nJ$72&3jWKagA3S9?^+T}tKAzvXF=(wk3P#mYd@11VpSe*G4x6JlT3#tG~kv4(#x`<;_+a# z@iUUnaK*P*n%Q*Bn1CS1v>zsOyQb%{z|Tf>rdZ2pxmDvsz3B)`NG?T5B2__XPLXLaJUXG27rl!aD)uMf%$7^k zU#(NGhwUd{Or+Ruc?`AF$#n=IQUc=d1xvV{oX)e1!i*46-AM+iSjI#`D7i_N4rBlHf0^aa0VhI(_$R_4OXAC*C+Dwnp3 zaFw_GvrjI2ih-#^%K&Kt{hEr2B8=oH9C)1Lezz`$yI#vqxml0DzkrG^bMpY&L>ICSNAL$ zU0rG*bJp3x2+s_}OY+SVAw*TzdO~^}`YPFrTkzJr{Hs{G4iXc;LfoDJ?H-j53;hV= zi^G-CF93c*ekR&}lsxFC#=4 zQGO%E-F57Y)Ib$h3_85#7aLRV1$g$XP_;C?MI({Zo$PO7poZ^G@ou0Q?SCKx18U~b5VLG2}rRE=%iZa}~!!r#@a`YM(bGjqm@j8pF z@a4nIdMUO~`yf}-jK9FR_snfPBRsB|2zwKJy;JT=1k-Q>$54qMwr~}*T=mc|Kj;>Y z6_-19PD`7l7#CzPTGHfMa8WXh;5Xyf*(O1u<;{HPD10ack|c$gFbIJa_UC*N8cF4^ z#1+0j4hiw^EL1NCga6bu3Ca~AR5q7NXL>u%s-< zR4U)bkVeo)(NE#3sFQ*(DsfAspqA6mAS$TlA)i2DiII_zhl@`Jpd$wT&6CDs55%+l z@hUx*{`A$JheQ~#3KEkB6(dcTK`5atp;cCH%^u0@evZ#|?&AqDCGez}cIk(x; z@~j$t-VNS+6LIIDHRo@{=3*>G^T1;8!6HRfY>3e^<*fp$x^U$wImuuP`&PI!2K3-P$;~*3WlCH{bMk!-qZdGnmS~ z!IP)|IlMKW<;w zKw!~bIWTVj6D_ZyfuQOPnxRu!onOPf5F-xIT0#0p2v+~q8Ml|ub^O;u9R`d0t{WAN z{(ma|Z~Lk|Q^6~@J{~5wEZdrQ;DK(FyPcw4KLH9pu5g4U^J<>b>8;udW*2s*j zE>Cpr+>cv0-j%g%0eV!7#uLoWV4baG41G zQ)r+EXP}r1GP9FZQNltb*Va>*UTZjZ_fnfc?)SW4h1zT z2GsS|a#gG7l`U%hA6m^+8g>!tx)t;Qab?RwgjA!3uFm&ZxXOY-qSEJMjh7u zCB{vS>hzvvq)O7S$p`iDY!qk{^rNng!g3X)5UcvFW>ltAhw}tAWG>9PT4;D0;s-CP zFaIG*u!RgIOtsK5Tr>YFh zRpdckE?UnesOo8QEo<>jBGFt7~3{>Mk*7r7KJx;AMX?H#JfufWtW8FID1wJTSVJhU;^bhnfZh75OMAX3gS*R zkm|qVW44@>OZ67Y5IV?Y0nn(hW-{$w+TaLPB6U8H$xQcjwd0YD2`jO1{n<7w866Zk z8Ig)klvZef#qknP3E`pPG=oU_rpn=Ymy6*gGdHWq9~Um9j3aoG$S$V0n@4-=3C)i2 z@s^T^6Zo{Q?stk}&wOu#nSb{Wo{Lfswb6DBL%3@Cr8!`1?u}pp%Vqy81L$Dc*=jYY zS=v&#l9Z&few|zQLPJ+>uiS%5y(gp>2;XL;Uc8qhj6b)<917J>ZFxG$4CAs%u3E0L zbHq4A6u-&(lGi67xl7hxig3`K8GgR}8Lbvj@Q8*u^?YBz(3xwKK*K*Q^6QK-FdIDSmf5{=EPQH|r-IbV}2&I|8+ z5&uS&jHS0|cxELjE8)VTF4O<%@`zrF5tRz*ii{gDm>Y==6xj23{DLUEZm1H^_2hn_ zS3gr6XS)#-ajjnoBGf;U{xOVmDN@`qC&y^2H_KoQGoM8b(3hv&QPNir?QBv`5Ywr8 zt>8GGc(P*oIi)|QXH`NLr!dQDf)X{v9QIC|mucT*n=1|^;aAEQpjo!0^jCI4f+~O&E;#WEv(_}T;&1p?&nAVpQYRK#so5G+c5{+d4 z&+_%F&AVQ-Z7nb43ts%iHJ6eR10}!%Ev6zrz7Pw{9ELqEA!;)M5*$bwrr+LrX8?*Yh)g5Jz-bE&&f-K z^rOxy{-4q_Z%Ujo+r$@Fd6NaE^ayE8$>x~I=~~!-GdSLhlizg7vf8wBwN5(S`=wVf z-fX;io&D^Y@TM>?uZvBg3%picQGES1sz*fkx2EBtZo{DKGLIewqRB(z9qI<epX6ytC(0cIVX0hPXxH-JMgHH_TJ{)cZl} zi;1#}QRm|BdH(5%wf^d!VeLGxzdp6z6?NNMJ@(tz)RP8Fw@+Ve4NMTFCB4&j*u6BY z4ieOPbJ5h()pPnuPu)w7r>|(q?>aYYmFuJ^PpgHOtd4*04(ND0A$(iPzPJVJu0L`( zW{^?;bA#&1UHcQ+jejufa26M3)C~;PI0p5-1w#W+N;RlKFbe< zCUqJ#Ips{ZSaeNs)qkfWd{YmlGOks>_36ClvATv8)Ant2$*WVH62!RmEw}fRtGoBh z6o!@;m#5`kqxGuXc$xO=~N{vVIas`s}9>qPAOW+r{T=-mg^ z?;FnQ+f;qaUU+k}U-ff=Pt(ddE*@)U zmYRIURfiXJ$OwEJ-DF-jZ3U1B@+Jh}{yHQe&p&yhn-o|PVm|@{1JEBxfKhDnd<`ib zn6F?{G|1CAz;jNJz!#m#g6`1MNVMIhGG6O3F!;KLIO=-(x#{O7=4Ga(7MJK%?#iC2d(O<9 zz2}}ff844=RVrOw(B0qq-u24!{8k5imJvmI{q8jc0zncN6Z!&yzz{C5uOXYJ(sbV#VX<$zqS0SGL$p@P&|Fua0>5E4M~5G7Vz@rOR@Fc@jR_I z_e1y9=`yYD%}u+zk}yJE`{#?Psj1KreM7^vkH%lh23|r&37y%~Yd?JqS5|rZhi;v` zi*=TrP;8Ng;k$mF0#7TN(~a`##Rs{mOx{#Kyzme-EuZ`mJDJ`QD;^gg-L|RPA8FV| zLl=J#E&kNj{ZYcu@4hwe64dx{8fNNp}L(_h0(D9qPg-_2#U>$(oX~Dr&xIXsfYa2a(`?8F8vU-hO zBxsG^^c@#QyT zBnzLPgJ?E{ZAgVb5L;%MwO*rt5D*CM(To20=Ee>)zFgy&TI%_bZfv`F@T|gCD+u?FGagH^R=fBJ0Ygnv0>l+lG#tdz}Nu z_h0MhQT8{^23YzV$t5dvw@Pc(DEvH3fRmpq38E&9;!Z0 zamZ}xn%pTnuIm&Z7jC%tSC!2LM}4}y-u`(JNTr=@e%K`PL+-N|Zcxc#^}+MUZ3~S( z_Y~s@zX)!_#UNbl($v}Jwf4M?1sJO2Hd&Gq%$ITV=L%*9#vi_Id_=llm#KAr-9dw+ zqpyT}*t^*MzV6Z)4T1R#LuY#vHP=Ny&V*DH7S1;nzPiD6RNgwFpvAjnmDmbdObv2T zl$e-Urq!lXF@yR+BwYgmvJ#eVKlUa}G*UoPWP)$q80mW+s2|cF9>JDZTw5K z;g_(brBpIpj0t3d>iH7+df8Oe@hgUzeJRQat!pWZ;-#6ZRGiAZ*<9ZN6dsGtmG3i} zc&7m)x}i%C9Spn-`?Wzcb;TQXn}hGz&!d0F3rG^G*unMY(xl~!(tJ@3r89{Z5;!O} zOPo5G;q2Ld9a@HwUR>(rmOf`zH>lehAtOPzcu`RkyG@EGdZw_D;voG(vtZNWo6Hq# zAo23Zpk0OB+4lKkeN()0yhmN{$p;dpdIFWz=Ka2yt7=TQQ69?Qk~#qaE#4^+doN__ zJJ39zD!#9F%+0CN(Ule!QdOHmK^{;ibg*h4-^f}dm^AaBwk_~IIWiLOGTRr&l+8=2 zqQJ+h{n7O{iNCFx8F#SnFIv&klysl;G%rcXQ*$SoD6XW8r~}$$PL_r5GQ(x9Z3~Pic$wX)9vGMgZfVb9a*753ysh=Jfe`E0y z0s8o>`So}6>BZYT?xAGjFHz@I+;JFmU?R#sND4Gj$q47S$R z&@eDCj#uhBi$MKC6yE8fp<%W3U$+)?62^xgx9#@9H9gy}yg3WoBw@OqE;L|@4T{_D zWmcCGAcl67vO2CEF2D-Mn9`{{wOwF2ubQtI%p%z?EHuScNhl0(@R%G4(|4eVko7$F zcOv}0z_q}JSkPFQxX_)b%+CHQ8{7DP>TTQ%8;8pN;L5&9{R6m;gT+f~>&K*dLu9y@ zY4vx-$eqLO;+EKfS53cu{p#=U=izP1%*-6`wPH(-j*gCujD+sam&>|qh97O~2_t;I z+*e{@sm;zN`5R`4;uO6!cm&Vf9PdSOH;6=bCy(aP+J?XQZib`(`u00I^~C|bZn?W# zHu+5U(1-JjTHgB9=w#>fsges$#``gyA1J&2T479Y_MN96lv(PH7aX$taN_?(CuvQhLqn>>a@5%p!% zA~G^oBGU)|`yCqM)A>uNg@uI{XPs*svIwzkfxz_i_Z#FN=;{VS|f1XSHzeOi^LtXpWY!%27 zv=Ht6zOvtb6ZG77FBSX9Gt=^9{7nuw)@lvobh$K8*vMHP zK5?L*=KZx=zwJ{n|B^=bH6`b?i=R5xjg%g?e8q`FIjb67H}k`G&oR9+O>7dhaZo^j z-2+yDkn_ckoPmLXv-4e!WL!Q93oC1{JdI}a%=EOwa5B5M7Bd9m$txtwh`^~jZhN~m zal^LEt$6M*xSE-ZX+61U9yAHPRDjeAx z;o&DUQE!uI^f;DhR*vYT=7R=S3+yTtp^&d~2S^(H9a|;D#hq?WGAb%g;~8~FOLHDC z%4mG6s%&(1b#-*s3gq)5qoN9yrE`=kbcBtJ@brAgQF+9_ejB0eyO*}?2_g5W!OT5Wgdd7(qR=*1}=A#EwC&P7- zwsNJGS)6sQIP=8qL9~O7T+LBsCS5!fc~kw<#|@uqVvz!*BwNusQM4a7dREX4D~WZb z3P&W0l;;qeDY_{UGNKG$E3ef-(?sUi)pi(NGlglSqP?3_l~U&ypU^T>Ma_m#9LfXD z6CC)ARg@U_adR2Z{94cak_IH(zOOJ?!nr%tY~e8=)z2@aHvhJx5BiC-mZTgvi9+dw zN}pTj5f++WyuDaQ)X}MDPlJLI_T$Ho61BR$-Q9-z`rp5Qr)&ISrJ%9B#arbL<>bt!#!^EUs-5=eL_;7|#M;*|O7e=JGmV@4Cr!_#%YhbJVx; zv{;=|=5)WOUYG89WrYBLeQ7sJxTk#;8yg#i5rjo6&@ol1Kd?jI{`2S0oBMmqg?g*| zt3!Vj!k*6tuyqv`4Ys>qq@<)Qdso0z!S_;?5rNlO-eMqErmd58e(bq9$76b=+j^w@ zb%O=w*lNbq!5u6U>_C72SWy;9R(YXmexWIA(wf4Y^W)?ca+s|qOK0+9+1!x3Rzi((a2~zQEFJ%-m&r>?j#^7|PP=93*U3N;28hU>{l##0Fc-!#{b&Zfj~AQ#xvU@W?3|o#ySlo>qsTHe@WGy5POn-jCNR2N9&c_otRWtVmCCq8 zi)iC=I`i@&QzRioPhL^Mz40^&M=Vhl+|yYinzh!?A^_ zsmtvdX=HV&dIOW?5?8e(42*!JBtqXEh!!JkXvmGcAe})3Rn$VPa^6Zb%0k-~R{#@T zin<#s14#=!d3rA0G|%E!!S4A$=P^rIN8N<_-dEr4K4I^a|M6aY>3(s0zI`}f2d-jz zbab@4TUbKk^UXy6Lg65+64jbQP*DpDB{Vd+KYg;BDpoOygS}hc8cNEjL-Sny z_Pd*A0q61X2=%&l$v%mf(`M+4aq5)AEWA}+V8D-}Yv-a`hnbIBHsPb((>F=+-3)Gq z?QZmaMDFbimXGcZUNWCpSw)3}ghWK>KvJBX1QjiYz|WkLf?{K9YdD^9eSf-aa&l74 z9IObKBaEiOOr356F8LcnF>_tEUclk(TW6kiJw6>~FPmbYOzHG_0~h_h#}{w6%p1e? zgdU^^J3_+W5D;JwJ@y>iWADHwNXcaIWd>JOG0$yQ65X^!bLil9K(8A*19J6k_=0%b?nA4dJ@EJ#K91akR^`n6)tqTKQaN=4H$U|=z_D0x`VL6RN+39_zA2VjH>cT-@w4} zLc{ptBEIqc&5e<12 zC|-cQu*VB0%!zor)eheeqM`5GQ4a(C0tEe$!EIw;VA$E;&jJ&iwpeD9_8-OD8;Olo zUElFAA(fyfwzqm}f-nIwF%=$lqOPc!Jk#v>yuG&vsG*Ol^RL}C(?5-iGS>^wFNtW$ zMaO97N<({4FfpB-uJ>|qa0CZGJ|OtM{`T#guyA*9aPZyTo#}KbQ5nMDcL)1cNlB@y zs!DJW8gha3*i~Fh?;C(hL?o)qB=PRmL*r|ynOaxNgxUXv*pR;-8Gw16b#*IBw&ZkH zTNx9eq*s_38j_c^G=aJt_4&UO8zvA%@6@MQ4EHZ}Q-f}Tu3>GzV8^EH+U(KoBX|*f z*)u>6t%dE^F$=HtJJ74KjpqbA5vB&{lkx(sl8QQqmfD$G zG1oYhe^MtIhB8JNMUs{t8cJgQ5CS&---!Wof|STuRKrET$`)C+cGPT2d?G>XfM8R} z`WfTa-5}IDsWvt^-(?H?945y2@$1IO_M(|AHskO6+#JV|Y(IQU*(jvfCU7Wohf|ab zCz z%MA&axj-JHG>i?>imtAu_F*wQXmX8(ZRCedP@<&FLBfg zv(HG(ZCEaM!!k~o4+Exs^z+}>FH)33x*zL&I%4q~|GbMJymNkNKNmA@#2>dkrIreQ zg^V1+zVZFjjOp5!Yu!9<&M7#^>u_EyW8>Z4Fv7ap+Ow0B2bRBC4z&1J_S6*>6>um7 zW=2NZIywTWp{{QPoh-!a(1tgKLuo?ck6lG4t=iq|46DugaRYw~;zA=qxIf-KKOTE#YU0q#5!sKkDPwa)z)3IPV48)TNDJR}ne{&6Wth~P)vx1N0N|`Y;0~Cj--Y>@ap$t^yhi*GsTm%ANp)`69jW;@E5`>E#vp4*JCj72{dDZjrN+Af zB682paB-5sx~NcI_v<)OXWxG^yRI(0N{1mOC7tMbe!6ZuI>z{@)Acj;!ts%cfgv2L z%GJ#ce9(o7iLc_Pn*(uwi`31@DrkQ!ms{P=x1@E~QSf_7(01Pn>*p4!?#D$cyk?3R-hvLjFyF&W?#O}rX?b(aJ{wG&{$NdGC=ygDL4RH{jTor=M#A% zh$lgMD!Q@{R{W8w_TJ;uQiEOrxC|kG34C?Gf#G4$0VCM-z8NnU(|& z7k|s@30HIdbpzAmRUNdX_rc_C&QCY`Nu@N0pQiLRq|1nOogFfNT=3{`JCB4*zDx@^ z(4oS5LcTH>$Z=fJ>-}tZxi<+?+5XNBn7mI;Pct-R+8W#+IcgY3#k(gbFE{$4#2f{_ zeC6Z&1$vGq)yOmfIk|{C(gdle>tzoc@MCRlu~2^sdYBE=y}GBInKqB-o745_VwEcU zLshWJq1-TSL!+Xil9F%_sX$4ET*hA_ozFD%%x}MQar+&Bf&dR6#+^{nCy;wCT#@xj zI?hriB}GLFGSM}Ais;bUU z;`1)1O4KI&Dl5-CEq;1=wU3O*g2q{}0UN0j#>vUax>3=E9D{ne2oFrY3%GaIm1>;2-Z^J5$lpg1|Rq_(}*FHMGU5YW=o>j=E#5YX3sUNcwASerDTqKv(n$H)Dvh zy}Ol)Mw+KIu5F%ck^};8I}2S*`#kl|S_=C8@%OMOH3J*Ej#PSqC6sY160UzS7@~|0 zyx0*8JuSch^4;+8u!xArKPH_?Q!%~_7K5QgQYtErS859tx^S0f+G1j_(7r?rPHZa> zd4yC^hS$fYq~L>A@ZGz)sVTpVK`E<~mG<=XbW+J!M;DiYfr0CJgq;NA@!UVdX3!8m z!coJ)%nsSP==sWmBFnR(+6!LG-Q~;iiUsCkfl@VJTgUuQO|4$R?Uj|457<@lwrlUi ztRBBI;B=&NyVP1Na?sP$GyU^-O;f%*_09uC51Z(RvYmd=-Zg$hOC z(&H9%pufK`tM8%tq8~YrwvUl~=5;@vOfI+d+&Ad}BRH1y9ol5iT4TufHN=l;Vwc1h zY_Ge^eK2b5UbQj;W3(WA4vY#0y1M)Bx9-`QnZ%Tow+FLTKqs`I&<8?a%TNftBUHdEIRl z^E6G&ma$u0${UBGc#3-Gvbwz${J>w~_DMQxT>)Z07#Vjra$)j=f`eV39@zbu=E-R- zk=~J$lY_gIjf#Qs@eN~8U|87kFE1Ee7PFZKo9zH}^6)oOBxpc%2{-e9C@Uyn=bINs zJ!38@D(YN670l$tgp7u?|5RaTXCH{A#q~jY3=aOL-=Tm>=7Xh9qFcd+=M~|bLpJ$s zP7Dqs5b7cW4DNNZPPb<{EiEl|bq>9=pLW~9B)_n@SYV#rY+>;F@T;^m5(>&l8U`OO zfjd|OU{Zqhd6J!);^yaX&k_x@n5%}rRZ(wq$Dg%TQJL+Jp{}W}1|b6$i}QODfoo4s zPfbmYTRkos#B&KzWYEOa^d8)W_h$K=dQ1T`a|@mif(>sNgcKANGc`I;!jr#QSjdz} z$jA)$^%ZQ7U}9prJ=`z`2<`Rq4%%!FJ2^XFP0uwlfegQ~u~A+95#$1;vbk*oaWS!a zyM0A%?Q~z?Zazz(YdD)S=wNyAdA<#SO35!PvjmyH6CImQJw7UG+<&+nsuH|h600RK zl88u8d3m|!&>=`co+Kr}>*A%)0w21x6xkS*LL`B~%rA0sPN1(T)o6Nne2hpVI}@Ox zrTwe?9L!WK+3(tw6&Ai$VaE#c<=2LIw!RIHC#9#Cwd96cDbv^1euIuae!iIyAD^#; zFO$S#-t`j|Mp5bbeS#m0zW^VfXK}Ha2yXi*6Mo8WL`Y85*``Z zKQgimvK3mxPoXuiG(bARe*2dF`}!#qBwY!x0VmAj;^H7@efaPJ2*uT=x3fT#v9q%) zIDCnK^*#c6(fQ5X+#DD^fgr{os`849;CO$(C_n$_K`gyi>%{bQnMTtU_!G4{3;YcU zFrF*Dse;_V26Y2P#qsg(^7r$FlSk)blY@(sliWPB;jom1gpR(xa2<(HWF%Uo-A^GM zMMXtZQ)(EP*W+W9)YPE&784aEXJw6(BKy$3|9F25CSb35RA|WPOGX3;A~SPUL_`Fr zvC)+BK;*SaHhII1tG{;$J?QJUl#r1j53?k|h!%&=gB2N6rnh zY@T}qsL$x+GNY65(jb0Gw249n2c@cYu>7oBfXIm5+}vz`ycCjwsH4_kO&Zx4-us6N z9&!@r4PKM3+Lpfk;q+j6{YXj%;^+m_0NH{0rs~&n_wX>Xxa!}#GEXpGQe9mQBmwpM z?_Mn9jnUB)AfVi+m?$vHba+u1Q9k+B=3E-o$xDeC0xEOS1TRZdQhWa_JuQk(N-VQZ^9!?E@v zCP--{x<+6n7W9pqU$`%S$OKp^bdVw;3m7w|>$0!<%vw{)zwvSIjA@|KdV_SmuSFk7&bqE0*)!bV=iRu>^`BO z$d;x45Gn#vO)5V;)}5ZpYDU z#fFCi3C`(kBOobheznv858Z3Xi4tIi_+*{r(luVDtZi=Quo#W!kHuK6_oVQ8Xv)h+ zNs;;c`GM_>W1OXd0nxqz*9F;utBzLy9)Sg^hDwEwZ%d0CXokjWYil*jwfQZ3XP_W_ zmi&Wz*yguOOjQo8s&CHja$DXbADTdLT&vGhL94iY6b#WgiHiUh&k{1MEs=n&$fYpV&74;Jkec0*0XP z2awkm=_%>y(~^_9*c6~3caZ;??s1ywEuPAxXz`uGUXEbv-Y(b+tenC!%+o-zk!-NN z-${{-UF&?9^ycjy9+ok$uC2{f6TjXXOz7y#T*HVL{ZVXX)f@FjB{JiAua|dY(_=RHQPxaMsKQtvjW2#K4Ryv)e~+wdzCj z3rt~^-Tl^XPlAshKYqrwXEVma3c_d95n@FE11^!*AQ(f8 z5x+=7JT(QV4dh^%52?nRz8tOjbWu{AoXRQJGJ5A;}-;cmXM&Lr!TuN z_z1iopdKGeGKyW={p#xr@aeF?;uBD|v%5^6gn{h9fI<)(kN_`fQQALeY|j;D7?43) zwxI0lQr7q<_*sZv3j?dmZ6a-)5Y7w4H3MPVbGmh- zixw#zZfC*qwf^mzh7th}jfU2`mp!!(>Ji*SEVSzGCsw$y{+(BAKV@ABY%aF2{cgQf z>NL7q^-0@k4X1u5IjV)9w<|5)g@FDpwZN2_QFmwoSRnU9Unw1 zwYN3LK2##H$}BrgDld3QQkczV;Fh4?W;paZjZM=lkRXPpcpu)MpZtKWu$)H2f!FA+ zk?BA3WSIXWD!9^iM4Q_ednM_h*TY+HU$ros*jA;07PO8RvY2@k^J&$IWKtuHV-}Yx z?0!>SeH#~lWpVQ1;Wx*z8d8?xO(W%lBigHf4J3KC!I(R~aqB4t)ggvj>5FLe!0+ET zx3_;&{YshV(HqC+@?<>TL!)KY_@reagYX2_pqh1oe399S5d;N4Sf((#|=>#ldqpoc1)0F}5b1en=>UJYAnHn$dA_B}WWdpdg*_ zjf@BbL-VWk3!gRRL_0oeFs}9_J~Yy_KIpOs3_jKrCIoM;ZQfRR`vUS95=MEnIK@5* z9oeBO#gZC2Z{Tjv8S50ip{`(O{()NllU1!|^kRk(4^%6m0nab1^Y7~n*?Wa1*4U;x z|3w!rD_T8kGqX*%S6Xi~Jg_s*O06m|YqPgFcTFwzM*q(eaCRMn@V$n%w)VAPWRnt5 z#dp`)@MKg~Rl(e#qT;k8BQ4XU`|*%q>|(tu0G*$of5INL9X>uU{t?Rr|Asj|QiS4} zhx_B?C^eZ%K5)pQ#|p|o{E6h9(aPI`+wU$TQnjO4!Uo6ZpH`f|Snmy~)r}o@9Y_Yj z^JEjcbNBNV?`xdv&f>3p=baA8nVOosWrw|8yrqxpAwXisvzih;u1*_m{=^a*s;D|H z`WRX3KD)zrK)2?Z~)2>(A)P!nJOD+PsmU#mb9v_eCxwvk4kTeFrHg&T}F z(#7FoT+q97arXjecYj*~O=QDm=DmX3twe`*gHxj>W~_qHADy~P-;t)``Ya+MR7SO_ zhE6D;Gmy37H20cEoFGWeP+=(g! zs1lCtzB6bM4N1zjiNJ&cF&V{8RgbBmu&@xgA_WDzpz|c;b*IU6ygl0lbDMDxQ3Q2V z2k3It)aHRjFC$Z`H9$xKG|UNDjqYM#uY72VnETs*A|eXa5kP(|`=y44A<7%}F%ilR zjr13=${#zvw38f~R%EfLy`sYW3 z11(b>fuEc;7Tf~*a6%rB(}iFDhxz#wL7FG>V`i1Bd+qDHJYQjR<(>ffE{`TEtc;hr zO<3{HZEX%m%HPEtFSZoO?SE3db3RPcJ(!kDQcL zj!+0%#n#qVN^0Cqymi6EdC7A1^8rw}4Uy*Ky;G~&TQK_A}i z?BbW1>h^}38ymk>T}*&@%KRBmLbk8Y-8~yBIJIhZDc(Ac?-Z7%-Y9IE$0~Z+EYIo8 zyY%(v`x-G}?c?)p#?`uMLdBe6L)aFcZ0kv8qlTqSvV zPqXXOLNx2j-}WwlIBsYps6TH?uA`*zYnU|S<2gE9F5OP3RL%v;;ER{`l+&qJ{G6K? zqH1xw+cF*7VQ<`%Z^Sto=CUt6y=v&uB(z@Z6cFgpl{GM{4BvIteQap@tyO0Jk@Ln! z-bUq;p7K$J&jem7-FEG0( z2%8>s_lwO==z_a2f(1?rD3)mPH_(8{cJ{)2?{7EsOkY@C3ST$ zDS=hSM%1sL0TxF1+$ddP9-T(xN8>S)>LQ>N!u($VZaF)kYT++C-O<9+e~sF!xSAT7 zCzATeQ!lSu{Xd8;1cV@9SDu`ogJe^xRu>u3Y1;ObfB@=0as92Sy^5l9j$h4 zZ7qDomxOjh&1iZiprb>;M0c**ct=s-^0@68%y98@?LD2HQOU_t{xIiY?1gCr>>J|0 z7SwTH|5HJ|)r}x|DcGks0H@pF-2VVRuqgs9;j|(3_wR0A_qo@yX(6~5`uT2xHCmmu100Ja5N^2Z`%G)`eHR@XCQ3*&|%q!FOMgGR99eTu`qHnSV^)viDfj zVa2%>dJ+C+;!<)aZ&A4L=B6M-imY|0bwWH_H#}}xyywK`-)SzAruWYtcNYLR0f>SI z85tSSrNIUiYAQVjdRmwdm4kzWrR6br>U|ghKD$Rp8Hk98sHg&$wn*D-wvlW8S}wNK z{9LX#pQWWkoHfYN(t#RCL`xfDF9-2#!}#BTzP{}TcNCUp6qYWU1u7ZuUn;3_a*a97 zBHCQFnan?%2QX8mv@#(2iBspsVvHw2Q#LLs#kDj%VwYizK|}$yqqMXXtRScy<>lW2nFZ8;5487ps1ag=gM(e4w{ZAbvk8D< zIW-kKhlPgL=>FIU*yljd;Qk5^QpxTosUw}DWZQ(fE@PL?MARZvT1G+?x9ot=FBqsH z#KEOnQk;l#XC@#R=;9Xf4AKnEg2{zzLU^E{ryl{V*!cMP(vtgPqumFQV7{hI`xnqe z6ck2%k)%M00d~OV<|fEEGLn*6{sVUeJg#CbCJzV5Pi{$V!3G*;rgx^+P2XOn^yhI-4iT1`u5?royC&rw6q zautZt28!&cL%)gA!n3mh&26cbPm z0c_Z4vmIJr&(^3wN=Eht7jWbG7$(Y>nqYDWL$cS=9gxm}uH2^ZGe0U); zlC;*)aOXBS3Myde#c%~$Ad8np(qT-&HM(AW-L60+>M1KD0;@n~kjo`NC+0QMae>y| z-rf!pF_6B2kjK}QY!4hQUteDd35nz7w&&&Nr@V}eh@_;TqZg8WeSH&tiHUP7mfRE+ zzvt(ha&ut?8*)1Vv<2Vm`0)K1@)CkW{Ff4oi4hhRy*`&{FfdXc98Gtdb>-zaaX+3q zxj0>1rvIq^aC`Jlv$3&7I}gas!ml|J7QU#fKlFs)PRNM@r<#?SISBY4hljaB!omfA zHc$XCviFb%)Kg#vKAdA-sasi9l$4m8m{45~fO9E6{{CgEH6{$EIPc-%;ej3s1jO9j zT%&0~9)9q)nxUYiJUuzV@j-%ONEeG%6B_ddicem4HduAU08d~Hu(?0f$HXX%q!D0Z zDrjmh0slFS6dVUaniGZrN;;@Cz@y4)c>(ZAATk2U3rPkFW@u!jthP2bC}N+pZgc>WdsK!ZWx~K{Q0mK2mD2#oiCPugGssg1YAK; z@6#R<3W|DTd8Kn6D9;}|J39nD#ec>4486_%7&g4&-d@9WgndjBO<-1hASZ|G;}DAg z4&MIcIB<#XzoQ(4GBGoQSc~xU^!)Wc*u&#&13uE0UZYXSMek3huxJxW(PQ;W41aNCfAT#(VqivZtc1Lv z0Wd1ybU%Pa6dM$H2by+&Wc+tN0hoZD5N+YE0=9}B#slHq$*Q2ME7unf3k!?hUJx15 zQc~gAY*uSsyvu+mKxAqRQu$9RBR9goX^}lo3-1aJvZKzs9efI8;HP0GZYVPfYe=Sq z{!p+u1!)CpZZOqONf8dMV41t%x(UloEe%27cc#En10JxXqy)f=z?vZxlaT1|>w5%& z1DGKYuN$>om$gnXmva_>+eL=*_`yvQ3ApXp8Z{v+!)`=w1Rd=?WW7X;F3bFL%~dgUdrq+^@yq+I!}r!KX;61 zaXn$p2rtv=a8zAPiBvPOJf@u)*WyKP=uN6mqGaiv%OQ_bR(f%2f=6KFQx87DIa5uy z8I$1)t`TcYK_L9|k_2`4SrL_M zJxcq*g-Lsa?i0%@oxx~A4kLvRgz;|^TI~Y9IUx-z?bWf=ti*FF`us!Vn`k0N`xmDN z*4`7&tkb#`_up z1q-+k5dA@VLS$q(Snv=Wve96be=e~_Lw%%uD|bCezXeA%epm22ZKP>7l};!8T3Yfn zRUC=)zdMK+6{aU!C5;eA=(^z7zUqDx9IUVXbSj;4@iY~ZXYRa5&8{TF#)c+|U*%&4~G!j;P-a5%(;#-!~f#Rl)!xa{tJI^SM-PY0d zb7f^TUJzNyyM>I-j@N#!O4kjN4!MdkUkbtetO}Y8o z+gsqT3$rMR|LL?N_Lu;@baY%C@L!)Yg@ZsrzgO%#@jFNWhY*mS?13BxaO|nMIbaF$ zzkd@>h&4k0;>8O`CnvZz7Kk6kKW8er^s2G8wpb(H>TM0(tya;;D!I3kteWs^YEsGx zpLCCBve1lAy#0dDi)>9*Ky97;^YG5SVI#5meP;}=d{SlSLitaUkQ(n7ILo_>mpRG8iHal0(7IYq6{+h zuJBx|T@NWssLT`x^G)L(L9g}sQ~bAg{nUG6@wwDw3(8Si*u8NcG~^KtZHk|wD%6{~ zc&|hm{|&)RvCKbRX1;2yl^dD;TC2rb=fopB-5#L+ymgh($=^<1%2U)?Zu9+WzdHH%^dR=~@&dTdlZ(s}5pPXuS1~Y@doh5hHzE3+4G%3h0*BjQKvnhK(FPI(Q^EuO zU$L8;kBC8?>mFiU(c?tQ|9+N{K%yMa8k!9;fyr@WdOy0c(K_H}wQ-xO({q94ZBzXX z1iyk#WF-<5?MxuCCtPGlc2Q+&SI)P$3&odfIyePK=wA^PbOa4NO9yhJo4w z3{+spR7Xj;iJ1xh2nZ18=ZBh8Kuq<9LmAr&|JzC}G}wR=OU+3^O@04x%Y23)LW0K0 z6Cp(0lFeqbg?L7ai#y-!bRJ8iQVGuWfW{I-6CPp1rRb6mL=>gOZW zWu{_d9e47hrdCEKHgR0UULN~Ds(W;K&U7-+vFb_+i-GO7H}4nkG7ivB<9q`MBk{gY z`(TD?xY4ZE=X}lMUJkKj))nyn@c|8??ai!E%-}T#TYOpgmhXtErws7c<@2Ng7=WK1 z?3=M5Tdqa+;pK(6h=>6oD8SJRzPa7qT~OusE(&Ey3_rA)iRDvKQ8@z$7}V0gr)L-) ziB@T1I=~5*uU~QH=6`NRAVzyv*$gM7=gYI*>p)^9+W;Py^)6&ye zT(tX1ZxBU8d!ukZDYg{Jh1p%hRpR7~vCTd#Vkz%H{rIhQ!3uMPhE#XQa{H250|v?< zGB0rcJeHT2Jthkkz`26XUFqk)Gl3r%SQ}$Ji9iQw4jNb&fNOxMt)rs@*l!*heqLVR z@O%LieaKH@N93VCivcwBY;MgjU(jU!%0wFAP!M+uKs(xljaH8N>HXhsRoH~ojeNSg z3r8meBPW3ilWvr+)OL`LsA(eIa`HRE?WSInr%-nF30|fDufXRc3nA8}%72u;e2rYJ z*tu$Crl@|kFWDxLux=C)(S7`Q!Q~qs{>J)MMP=nXMx7UP!k6BFW-<{J7l)q|_%+(o z-d>?UfTgCUmVLOrZTRimpUwalvM)IA-sw=d6@mFdN?e?Oj2Epc9|7D%pD(Wv5R$-9 zHZy}5=E49O{c9C3GlWF2Uc|62sB7N&!uap%P>}r}^Pkjni9gFikGURWeXt9~FO^;P zw-4Wty(3&GU{swtKbn8@Egs)A-pJfMhXwR^+eb&OZuft)JHXnktgLJi?$JrmD2a)G z%uP*92-V>*OsJ@-5rVo8Cb5YoD!b<9YJb48*iwXFwLL%m#TCJk8lX$xo-FEsmnsT@Vc<8JaHD!{Ue z-VSXSXJgYLlJQ|dpabUg9h63XQ4s<%vPdW?wPLX{7#iN-JAy-x6JujPG8PuTgAHaB z2lEsi7$~8u3q~#S5^5uc)$jEnVC4kIz;b{l?pd!o&Bv#UB@jr##7@*49Eo?C;mb2P zfq=dSDhW{p!Z68?Zvi~ISeWi(xeKw<8g5aRwK>mDlFy}Sp_{4SFs&Du;gxoo3(?p-v!iR{KzbGj^ zpCdu>DebTuJVxX`a}N!;C{kCN^P5o7!A~+q3usetW&mKouV24@tf7T`W>we4Dq!j}53qYJbNlPjbU2CvAAMu5 z$%|-LnholcT|=9GE&nJv2q{1#f$s~zwvGpJmvJ885#C8uQ(>{#xXPHE=ANIQ4|WZJ z{(O9WGc*RY)tc;S&y-HUOa#^h%z5_B`Q=*Rc;^97X#ge%hB82j@Lw^Xt$-)Muna__ z2s1cV9q7)^?;$GnjCb>kACAmh4p}_xw-R&4xJr&I(bp_6(O)VZUn=@033x7>8X2+K zAK+NKYBbvJ0{#)m4L|LLQ|iGtO0>9KGepA^adUBv(izqR%uo(U0>6d?MMhq|_z@B^ z1o~sfXyg+2FqN->LIFY=n2AA}e}#xxTv#YT(CmC^0tiNcTmDUiF1!FSSO6ai2XTLp zmQqE>#ojMqM|6Xb8?K8D8~Xoapz!XmzxKt z3^&%-1?vbH20;@J24uPC7d&ovT_YpBe7FKXitFm?04ti7rp3nx@v}C6eKrf!(=CA4 z%je19ryoKyyaLJ(xZ6NfF?+)@feFik42#%sCw(=0$YEHQrTmId3pBjTsW;$Ho=P@G z0L1Nfa{^^7mG}|9vGPgv)2C117=s10m#1sv`v|eq)6++$H?6q8ivY#nR#S7?XtzH$ zJ{}=Tz~#uG+k?2_FyGs|ecVt*f@1*Q7zkNJgiUZjdO^ekcoRU>dU`~v5pKySD0V+kRH;4F{9&Y%V8iVoy^7vXd@;j>-CQ1~j@r!uvBd1v=lHsCc`>xliDG zDNI}dzJ`EB!&gV(i3RQul$!%-R3ErNaBu`<1ATpcAh5#J(Y~X>G6e@aOG_;b4dVc9 zn30SI061>Dy@^0fYS;|$)lGlj79>2NCh*U^fwcL$UW5e%?Dj?e?uEg}PXUPD2oRjo zi}qr`1_lyX;2hwWcft1)jh4Wr8)0^PTKu>p7fewb1|le5-6SfQodLd_m6Zh&5)D1lnQ6&Ox{U8eI}&sszT7R~m1 zeS7Oy7eM=m5pY+Qm$SKC(VXdn<4qt$1q7fU&b*1BfB<(0&XsAXs{@ef|6%T}1FG7$ z^>0K%LO@E84k_vG6afM0?go*RP7whSX+@BhmTmzlQ2_y^B&E9%>3ql9`<#1npL5T> z@9%wo|L=`!tvTm+j`57=`3$rRrhWo=PQia19v(i(k*Ay-YFVU~btlt+h=dx_+G)IY z_+wgrV8IHrJchxfjMFjbpeC8e9LPt3$(FnHw*<$7;3^L9pum{(hVYaJ^w1ibBP7s4*3MHVH%i)U&;Bx zG8vlJDy+=(9+St2s_%* zEbt}RTOU70t}2wI+Aufp86ks{u)%$82<}Qaq+_yk-oAbP@+InA719L44a=^`)LZgK z5maB$*T6Li7p4lGl$10zC8fq;{LZ&JJZuXXI00O0Z*TA7{KN?oE<0G^j$%-pg0Wxf zyj|7tTSjrQKRi8yg~%BiU=5bkgZtCbaTDUB1O5H^2PBy^cvrw+35QE&TfxniDR`h& zlDHRu&e5^83jG(%UVBTfWEB;qBqqLtnFjqnO`stBVDP#P?NmmhfDhVY3gj(#3gIUP z#Rar~xN5SpvLJ3sp36lUH?x0hYs)Gv-CAE~WoH*Z{Eoa$aP8W)RSuRNGDTc22;~sd z!(64e7tc;kP7XRMCosT6MEQ^u9IQTh_4W0&o~yENv>=D1l3;0WuK(Vv94yG8p=e4i zSC+$Is!=V~F#D1c4xZDKt!6l1ZjV8T8;(zSGcZF4dHXWLTuQic+;rZk!4V{xDD*Iw z`xCS&W=OTk+`a_=@KgR__2d~pyk0Qu8KgO z7D4=}7lnmufX%Ueb-srQA`-Yypf-tnBPb{cZ$HL+DNOJ+%|4*a2QI%urbrd_uJ}#P zjtDRxf|l`5hEw8EBWUPBpX^woqNB@#bEfS%pQ;Oua2`MgkkF1909jsQd!n^@O=FV3LqbL&Jv0SVSv&Lt$(I}LL%3CQSRa;Z|%1t?W$4T`5VwQ+QwuCtWv@8!ML7Hzk6(R-pOLM!B zh@))Kdha7a1C-8ccRo6sjV6ibZB{hlEz{&UE>7FpXRv-ov%`ASj8aSxk>*5^7#n+y zm>8m4I{*yG&B*8-=X(x9Sbe<@(%s8}9Dm^R6m@;i(O{Zs?)>&CXFzOPai8GOYn|G; zZ%3rYb;sMTW8y@c`)$I1oDQdPLQ-n5D(>r0*!npumWq5`=01Gq zN!AfPe39ZS8S?8OJiGeMw5xB^vmRCl`sXRRFnj3KR*_0Xl_^@kpLJH<;QaW;I4xg5 zLH>-t-c5`ydM4f*;pQX%(&vfPM&Te&jD?koGjyB95Q=RWfQ&(Pv?lWz*_0YkaxvWg zhW{&)T-2?#XNm3m<|J`%H08@|aNh7*?>M=L!+%4RM+SiMd-S4QsYWvrs z@eHOSQYhOPYUn!TbhP`4;B;P1F$PWqqTy&DM{1H{vsQD=x%Yo3V6J2HzV9?MpXav- zeoG;KH7mM{`N*OB<`NSpsQ=pLiG&m?K30@nrHHd~7mzA$ZoHv8nY(bjLPZCpj23}q zoS=3@Xnr7Szc{4sNZArC$-6Q@u*AZ9VM!6cgm`}8CB7Dli74CsHg4rqn(r>}3G(9V zY1_j`CXKW{aJqMzw@#P6xEirHRhM|5O)Zh7pWgk(3VdBP#12^Z2-H zj48f{tKMp4q0N<-^gqTu?;52N((;>)b}-~mYixMF({%^k($h>%o{7zXLEk`c-)ZL8 zuEwQe681}h0|lvC{|&<@>Tmi-9(0>t=x*aONUAO?{WqaNB9Dsld3uY5CI2coBiwEs zX-P>11qWZQ-q_rPH_UTKF(kJqj@=(ze|ZS93%t-7jOA3;QF>R-(99meaiM#U_F-W0 zeFlpO5Jio##U2TS_I);OiQ zghyt@SAWHBDhchnsOY;iYIKOfAjhGhE%!D6zcHYv-Xh_?N#d`stC1`7SJVGqZ0_Ic z7zw~9A%VtWbSZBDM^i#7Dt91PSwmf28V47;Arc4@qzhaM4J)^3e+K3SqffZDwcObg zGOzDZ2Wo>;R9SiB)vX?=7@$~2+zPm=QF?-+=e}+kejaUq%KEz}u&{=uAmPa5?$VnE zl4|a*(TTM(I8Y|#)tL*E;4*g^#`>Ch(J&IQ4lEq&wWO*j^#hG80fjrdV8D zh@11TBn6c@_#m(;o zAPT7gNZ9`4`OoBq1OZt2OBeUt12dV9rAu1 zF|?RGHD2tw-`?Hc9zv&sQBe1QZ*GGYZSbKBe%XBe+f{AsT$v?>wXh16k4+9lU9^IV zUBpLA5q8CgOY>-S?L6gQjrCW#gd4>#-GP`<+>>iZl>G8qCQWgix{hfjIw4j>YE>h} zwllxjZ*AJj%ir!!;A8Z};Lx>So3|_waxjdv&ZW=uc*_<`d#zuL`TjW{@qx3axgR)%d`KyKN~REbbx(9zO@ z86GuNg9H>ykW|tkgc7@>von(|l)f&RQ2sM`HNHcI1}X5d(uH8-cV0hfcP_s%4Bn}| z#mbt^znmw4b(G94AOMh!Hr3oD!NBuVL_@@m`6#{b?=gFTsj2-Fb|A3O;%~46#fQJk z&`KOrSO$f6OD-u^oT!gBk>cURAEER9$WEHoVI8&8Dii-u-(a&BWg(oe~ghyDTVV0%F0 zcK{zGYMWp>X!|lfJ^fxR*zNqwN=n#SSXL3NgOQz|KV#$Kq%)VB)1bA+&dq(ZPeMZv z_ENTaL_4My)<_p<2rUMv9q_zJGA=V)oBe}^T_s&o-{4TL-y%|-bugzKaz#Bt6J=jK zkdh$4_smRdwOduo^X&asExfWsb~H)%lAB%r^{%QL{d7Xti`oZ#d{)!N0+c^;M-k;3 zb3A3lKpw=vz)PWA5XJy&C47?q!An~Tra+@fp`Qm8z(JG1d{C`-g`TgEJ#QjcIr&3dTY-awgakB4Zfln^ZtW6Qa*n9g zp9GhlTHtTgI*(BpQRHC!`1s7m?m9um6oKWB)GDUyKe?C%ee*vGPYS+eGcnH>al&3v zw*GN6yz}*QWPn+zPbJr9Z}xHCZ%H>tI+YtU$}K+&QsxeQnLX*mu#nl?7(GssO4;jD07xLak95||2|wK_Tjpa2gX$RAv|dU_rl9OTt( zY-}L(%wqIMj(`CCVCpPw|E5Bg=I-%1$?4D(I-!JYi@+P>eloq)v2$p15z(S7gNq<6%xUBb>?ld?Ihg}PQa_Mp9x z^2&30`9Lo*@y3^C9}_XYFt87i8M)Cj7k+U4GYfF~tuLXuxp`Dn6frR|XtK7$dlT@e z!U%g2Ac-(!0)Y(MYL*s`clsb2vxuamqgs2UjAreZZpI_Qf5 zV++bxhOg}>*3)d|I<{otGn}ahiWk2U&W$9lcZs#J%-3tlhlS}^u90<+u->|*SSoJI zg;`h+R85acX5*aVVH1aqZTTfDp6=0$w+~?VJJ@2S66bv%wF~}F*|+; zbxg;ylSt0RfzegC%*Wyi+E za3W}bg_kccfZZP(8(WY(>fYC0F|X}MW1vnjJhK7|0K{w4Bm&cpZ^o6!M3e9KHlRrg zEEfqBqW?7=!nX1DUj_ytx26M;8w$gqx!m8H3S91`p`f4uh8ro5H6SKE;Wz_5tE#dR z2nn~Fx*_1sXRm$#{%W>Dd@uV|?5AJ~2O-?m#f7Fh!FITxT}&)>OjS)ysxWkC#}!bs zV^(#DQ1Zb+*mKn7seg2lK38P?YZs|XQoriYnm1{?$v?Ms88*3)4ch`jUsA5K_e#MS zL+=^FQ@1q-gP)A}q<4_zr=_JG92`_qR)#4R2!suwh0aeO49G?x?KU8uiLEL+cJ`>D z2RNXc$nW}r&KAl&WVSWg2nze{9DJY?bo`HagbF^SN200$%?*-y6-+U6U*HW2UajSM zaYu0X5)%+)rM(09m`oh8I{jI<1xjcRC{Fh+AYhkIh(}C}0D;_3hWioZcV{CS66sJw zcsg}$92Gk8$18bu{XTa-`e=>3q>CY&ELq#L|7Gw5gS&g&ji&P{AQ3~zXlRtKPY_<- z@B|BMR(^iR1_ zjZI!E-w76cDpfN1BC2_1$UDQyvIC~bK@RZmC4&IIdC2)YykVz2SvcGEzr^$0T{Gr3SP1c zYAL)Uzi1GUC_vT(wio5Qy?FU-7!+r>e*RqZV6-A=ytfo`0#E#Eyum-PrwDT3ydW(# zHD@9p()JPz6=>4y%!~;*2Z3wR`_0P$6p{JEw}pj@4DkgPH8K2SvO%p00AEN?pE{%9 zIq3p&I*CnHU?f!_tLnvk$C4&5?Syc(PqNfP+?{@x_YI$sOK@ORk6=Rp?g95!ILPE0TZT~&%<;aGFfcL# zrGbc$P_-FUS2s^jIm)0;uhtlTl(3e|oJ@cf7y?#^-%}gYjDc{Dm^r*1sX(wn$)7;* z3m(izNmY^(Z5EZ-6GeEy4jfMs{qivT&sqJ2BYFqiay^I!{~ho zfs^`rVQec(bPSB}b0hDE4|(EdfNk>Y*DpKVDClG$s@K6t?&0xH0+mFZ+S;t+d-OMo zZQSO>w2Na6itr@gb^1D4d-5L}ub!1>7~LSDhf@QFoiHju^tr?R_7H&?9v+5i4o$2) z%p@ioJUPaQf+S>9uU-Gdr2zUgSo<>(Z_^W(9=L-ru3m+?kfyh{(1sMedO(1NpaM9R z5%$pCX{Y~=-dHJ)^ALn`4|n(PLqiOBq1#i)u1}@SiTfp^i~;=;TFE9ufq&dbVSODR ze+QTsxH3uE4xgS81vW|3Yk~lr3c*tmkz}QFNLm4~JSJM8V=V-uyv148Gc2LzOS=v& zF4e7+0QxWbyY0cUf5J&h)DAh@H^?0R8p0sH?igA^_y)&~;a};IK1uu-r!+P;OS`*n z2ubAdXXZU)V@e^GX7K#NwfEebq`=Smf;92=H(nG~bt8`!9Iq}Os8a$)r z={-&p0EoErQ&L3*mz^G^jqE=IPf{p-e0HLCa!N@+_a%sU0-*F++Xd5Na8ZP^PtNaT(;ukmp70}MMWLc+Rd}-N&tJZ zOdSiQxpp96v`)8Y+NKgN!x?@IL8okRjbmTE8ac&&5fAtNJWn^op48RVLA=}>@B~yd zJTi8UjwPT=N-Q8tPAyYgS8Ed*I)2kBPs)jW5<9^ABU)s1mHA4g>C>0pO1iEOwTA9h z&UuR}VzYTKd{$??#PHInOqEMe>o!TV{I?-na{Hdb@t;el*rkU4UP2D(n4Z3vw69ER z)P}_Lo>B04R!>NCosJig@GOMk=zpij4vk$gctvtg)xu!Dbc^=tRu_wcE`wBNpFCmP zy@N08-|t3Y<6w#r*gibU$eZWZ@I^Ohlbt1xsX?0P?dubAo<{0l_Ua=(l!4Z!$}Z&` z9}0GGqvzCku8;J^i%>z$ah;f0+-H|5d3GxBV#7;62J{34F#4F7P#uZ3d_Zn9ZZ$#a zN&K##_R5*OQ^&<~lJA;VPC`S7&?p(xGd~F)xw`7V?60T_V1a!Qf4#q=Evh!J6AiUG z7=6QIjc_yG=3|u@_P(&j-T7g$c(Ou)n#OO*>vlDEGdsc2%)7=S3L4#`+!Wb}PfcICk_b;>~e_!x!sST5{ z335xi%)c^-1{3~o4WhykvJSYSIg6X#eW9%F3~wLIr@!yhS6fi#M>%SfmY!+=i@R}XRm;OKAOcp@3~A|)lIaRRgA92h^G zJUkl12m;G5D$A@vGy(!cL2gZ;i6F)|gZw)Wt12p>Yb!nd2Hp(YgO(Mv9T86ZAy%+q z08kFWNBfp4c?rSUE~KAx-Iu#ZlzwPI_A1h5Yx5f(2P6o^koG}iQ?`;%u|Fi8Bz((4Ifub6jm=G~k)h}<; z?(G|U!I%_sEL#Dj^iJWbPoF&lw~ZP|yZZV*gZXNWV|bFX?R8{OdknVOxHvm2rHSfk zYZEKzJY4LS3Yf(!M#=!&ubJLIZkSjNV9<4(q~cNfoAnm6f4|-$v+z&rEf@`2RXBxw zk}8DN_u`lL?1v~SHBUaIcxpQ-G5VX#9}CoeBgerMciGdU2u%&HG~oz9$%u}z1kDbN zO+itv9~u?qab&ph!2ha(tS2Y7QgD3t=Riy@n0si=u!OL|eqaEnbID|$3Vc0^yvkz? zoUl3QxC1;oIKI7enak($`SOCfgM)IO1*!hAdbfGZRO*GR-Fjb4+cg{i-Fqh(Jq8wY z%eFau{(~HLSO|OQAy%%T@pG#e#v3JUKi4u*{*LW=;Dq*{h;s;s=rl}`2k$_h=U_s! z!xKh^CuJCcfq~!yxo@DNqN1z&4zQ&a!7wWv9vV6qMm~lfsFpe3gjNN(V7lPc0m3Id zawn>t+lw=|;x1`MYYafr$ghW)<; z0(Hr@*3dJyHg;(vk&R69qsYP^c+xqyomg?;G!@S|nE3r)LPDXKfC{2jwY~yv)A=2= zEA&QcPVPEjkffkETVuRV??n@Y8}0*!f^3}F06^01ShZWlpng@QR(X|>psk^yp`&9` zW_n4f=q{*EZ1lxA=ZP)=#4_XW!$8WH5o0X-&y1tBP4^3q#=d;+8KR6x{K#-+uCp{v zB49N4mZEQ@yPnQ~eMjQfga(`EK~aB0Z!Z20?e}~6Z706=KMU1q(FEe0=y7Cx(kmV| z+H~YR{&w4giwG+a-M4ZN*I0$mi^l%Ad*Xxe0w+VL^&h}Eg|J-tRp ztg6}!b_Z~y$lPxNgF66#_N3^2Dc<0L@H0GY0=%}>+SbV?e_uO0W&(ov>T16FmoUU( z`bVFs_xO?Yzf;dp#&KW&OU~$lU3j_ZtpjrYCMV~eH`VJC8ArdeQ4?3E7HlT`^%N}Q zU9Ng0w?4{d*ZbDsB=f|~qsZ({W@gZsd>$N9fJfoy{Tj$}s&y^U`#rO!_w@KSpmAY>kApV$5ZXn^7R>;|u*#l9@$TIi-uIqc#-JrY z2@0>9D&g9gZXF||$Wuo!J^;o%6{I&r=9n|_E3~3v1o{Lo+1@U11=4ce^ixryOGq^_ z)E;Iu9YC94p33e2pi&m8XtlkMS?{&<@m%D`+pEjbMjI`px!~#{d~p3#Vi{R|MwoODjs6I{&=1LZ$tmEv=ZTFla zl9LyXQ<|_NI2^SKwTl6xhFHU(GbjS%%uIgxwbAqD&`0qq+QIo{1g{qqItz zXYgQI0XZ!s1m65jIXS4_r|@t>`2*%p`5Ks@S(q;0-?^b=LyS555 zk=R$Swx;%=tpw97UFqiT$^ZZqeSglPhH`sQdM80&CJxwU&`3@^BY-u!_3v4uEaO`` zNasG#4}oD6FrVOolApXG;7C43`?c`gcq#kVj?o%Y*Mi0 zA22vay;QBja2tP6%6i3yOfvfW;2=3zH3bEA6%`|dMflHbA3Vr5x&-z}Mp|0#4%CtH zaSe+huwQ}~63tOx6FCSV>u>V%u3x)0Gdn9yQ5k|#3K{*QlM_&_T15@O4arNwb&HYF z21tm(Wtk=;z4aiMgNBn zv!IW_u>n==<$8D60Tc|3)s646Ak}}b^ipi;==9fSIi<9#7Tk`isxh#dB32$q%Us;t;HTBLwPnJ> z>Y5$|@Om>J374X=ahiw3RixfOp-bCBKoSGF7~**2ODh8CA3y{~SjQcpwhe@%)L$2J zKnj81vmhc4Zg^0X5)%alDfBfvmIPqw100|8HXt%Zh~h)VuB+<>mVO%H9#&uj{_Zoq zMUE3TPeN~s2)!D0eS@D#rh#V~tcXCMczW!X3Mr3V;|(vci?lx1(}dUCw=Z9I_V;r? z_ne;kff{F7+np@1^-U-3)vJTu6%7&-T%=_lgviql>poCW;Z~z>%`j4AglnVF_~~k> zt3eB3Fn@D`;)l9khm5)$wv`8lCZ^=$MexxAme0b{QWJzXV`KOMZx9evx-NW?FsuZ8 z%ZZ9>g!xut>>qRvYSN{|E0VXCUV~PIRUO>-<#UOnKv?=2L!qrl# zW|w4vWePV%0{odB39#uP^X>(@6(S>@R#RICHAlRD4Ghj)n0$bJ7?5pa3vLBvWdN=Y z2F)850A-2O($f=CQbrAegEaMx?04wcGYv38xm(zUguEf@3O`%ND>#w>`v8Z#?eKRj zIA{Yw9S@RJ1&crfF;WXv5W-D*=Qqgc>gp=wLBM;qzW!h=xMODM%a{AmZMgXo*u!6f zffbnh;9rJsE=n2gC??MZnrhBXHhOiK#c0dOT%LIA1Fq+$-vjz+)0a61Ay|%N1QqXFA=vY@17b3-dYzUn@BWIN+fkj;M1egeuTxF}@Sa=Ac51?#gs zxM8t3^qVZKtd#HG1&HbxsJLJ|;pO9lhc`lWq%H3o><&0`fi!krULLL`Fo(<#Fat4J zGS|W8T4_1$2=cFB>xF$7h-`9Uvg81+eju*VCsyo*u{OX2gLZozLkWH@I8Cbz94{la zNd87Mt*fu66m)(Bz3@yO3NmZH>k6EUfy*Att&}o z4PJhOG~0cBeL!v9^&>?=G8Kdy;?Ky@Hxv6ya0Gx=ssL_!FCU*xn5f9qML8j)<$76I zIn=U^4&>inT-bb-9|`iU+pU!^5bOX32z)`X6T{&SM@;bXM*{esxbQtQs5rT~)yd#e zBMex`L4a$fV_<-E1kC7gsKnRj=bs>;E@lw9{wIrrTc)#=Q}5O`>RkcaS#PiE>ho>H z*y-ob)|vVfUwGn4i~5D9d=7@I-WY&em66)oy;S_7JIEl#r{u=m#oJ1(`BmOmql%AB zOszM){hS7}n^&uYo6O)X$Pd>Mpnr%M!LOYim~lJ+vwlg*oraXnn9lk0##|yK&O`Wn zg?wA{2@d6Nc~URlCd!s5O;}PKSG;_lS$aYcOcUhs(D8Wir?eXV4G)PhZ7nULICr$B z{B(!O_Xyenw8K>zNi0r?7$oGM9KTjRW7>eR}wu_?4F4LYa5) z5Iw)roRCo(-%|3}E8(UmD}teFGrfi59_h6nYW%3gE@z% z0GTGL?*Q}QKL?6l08q64-Q?!rMXqC%u1@|Wm-QcbNqc)gV*ryO(?CH0Cap8;>q-t= z@7az z{r_q8@WF(vPvB7J&j$<7i^J1gzwHJb5}VcQcob;6S~{yPCrKuEp^M#ol{6+Ya)TXz z=}{G`Fm~taQSk#bQgr~a%-N0GUB5xQ&vxs`L8$W1SJ9iaxxM{z+7qqi%w3GD*CJjdWJTP# z8H@M7W`tgBviFZ`?6Y6DU+|=uqVMWIT^~*#z0yfkBBw35<>Q(o<{(Q|rGmK=r)zG$ zWonZx97Ir3c3SxI)hi7$xAEj^kVBy;!d}ocg?yXJ=a{3zL)ERYtMF6@>vz9--yUm_ zd&5cfltUm!!uYxT@pB6Mg*E>8A(_Vu+PfneH>?BL_IFcLcUTTz4ab?(%zR!EDZLSK z;)D^xCgPUGM=PxT_JBAb3;=fSDM`2fsMr62op2&+s@9m-85l^t;Phe>ZwFFMn~_F-T}z^UYNkR zRIg(V59Ald&OAa}dpsabk{=1)LLe;XK_Vg$W~=v4AjkmKSboA~q(g%Y5fn;6SYP~LsOSiIk?L9^b`d$ zFX`e&zY{f~y^z@*>Z>v!?KkW8IXx^7567s6ECKAvxDRF~q*JlpNIejXaoQI`cb*C3 z=dL`%5Ez;tw)(k1)umv$S*q1z$$FjRTQt>q(v#aL+ljN24yhV!)XYVnEaz6KtNi2}p{pda~{ zy7%@ubW8Vd07e24LxR_s; z!oBdMr!v;EVJ7%6%iu>f9Jy|R+cX6xge=WZHs%o$6&WV#Jp9E&vZex3a zFGIJvVRSA!oxlt0+jK`P+$#z!hvas5G+Ve4gN#mfTqRGh4vis%AwdCw z5*AWe0QM^Uy<~*pc`q^4Dh*OW53FEi17zbMcd|LWgZ`z`X6nu_3`|V8zvVi_O&~qv z{v#34P2kuu6BR)+x@Txdb1Wm0tBqRql!a)Bp#TK}JSGiQbT zf4-YJVBBa#?csAH0l!1$+#1nlKl-B{CRBpPBvHeMx3~XbZL{XmXSukmt|VFU1?X2$ zK0LsL$pyU;%;jOe28yQzlfNn4Oi_`M)ipIx-U)0p1?}cSZWeA2`QVTcSwlne4c9Rm z2@{|pK#I$PDQham|LM9}Rm5t+?~@O3RAm}nL7G!x_{jEb}%XP?dGv}Y9X~LS7SZ%9mRwb zw}p(c9648Z-RQi%-9ZW8)7MX}$Zsh%8sn)@n|AD(H1VGIk`Cs49&Ziu)Y(c^NxfNE zygV2?e;<484N*jXqjGltc%D-eLu6W3p?FTj%x1U6(ha9{`}I8Go8n774M%=e%({)V9j0n>VS*p7IsrJ%B+3a4mX{=cmBa^Qyzfy3;{qDCH2^Jdw z$GMV#5#nV+0@T!7F?5A|vLH7)J8viP*o-kr%g8|QcLPjQUOzb`ScJDhT%fn3xoT;n zzDOlS8dvV-?hgAwxnA(hgLPx5w^tI;eM~(~Gbct9x$7CY{W4JL%^C5%hOELY-k@aN zpR60^()+%TpEtx4FVKoJpxWTR)NLn|t6osVc3+C5Y3zJ1a-lyt`mT>-{kv0b@1_6I zhUi}vSO!Fy-2S7*}sq4&yl9P&jrigkAE;Qu0u7C|oz`XO}Ta0sy*zU%Gjxf;&l=FZau zi(JzMT|UImf;8Dd2M?-Z0&96~tpp73gCunV>qzcTk%i({_7F9(#VYx3syu))9 z6H_0wuPN=2k3ZqugXK1W`q{OQ1a2m(f1{qo|D9gZnmhmH6%DRyC<7#fzdwZ=Oc$oI z0qz600?5M|h0H|^_fovTs|9?WhYx?v&YEYB0sRL?_ptfoVE=ymB`DS89J*igVNKkH zQUxN;RH9ywGEW2O8oIuIE%|0Iv+oD-f4o%l%Se*Az0dRx6_Q;I_}z~wnnn}Om)Oo4 z0@xFLL$x~G3!`3H)mje=#Bk|qYbO}*$#MS2j!-mbPZtuy`@GBU#WKTS3WA+R;8S}5 z&^!wZL@pXIqRcETpkM3j>cS!<8k5O-cYA2GVRPe$54&-Gv2poVvo#63Bm78tw$GC}}?!XV~oX=upMnkp)Gfr1tz3RVy)TmcF8%of#L*F*?# z>suK%`HgmT?%aDdgud|axqasO8{Cm5n!1uqidx|A*`CVCS-9&D-y?-AQ3kwSu z*W^#E1~z>JQ5BXA!#d)$F$*ZIvmyJOmL?8h8Mi`!WWM2tq_-+Fq?a8aBn{(&oPf^u zc27`aep@C44T>A@yg9Ms^K*}br@jVG4L#|pb=C#EDr*hvPu>}Py50KSw^3_c~-T8@bs72km7|g4{VwOy*N8HEiH<$1|V3ICAT#-t8#M} zzePxWum%00A11IQ^YLy#f}yAXI69iNe`Uu4%+M720?f!r*iN8$!%vEk1nzHq3@zO< znWw%e!5$6&W`kxi!&w(3O+tQJw66Q9Fi%?Up$!vuo>-la3`1%86boJ%b#FZ znFQ|5vo)~k!dsbxojm~RoH$V*-_@AkyqGPU%P=;8o`&R$F=9VVdeK|P7(+ltFheR? ze?&Hb7H-1oii$Ud1y&b7;0928Z%u$$QuhN^gP~ziQKiF&1fwKq$9=FC3!XKE(J+l2 z8xzyj&5e9Ma|&K*x%@D^S*7;wOGGBtbwF$Dm)0Q?u8iC#)VV&eV%eV7VUq%;UO0bMvF z!xWDn1&O4D+WPE~Vd^5cufjG~cehydmcwh_A2#2Sr@)p(MoJ1ky54V9TVeu;2k$y! z9XHT)L`8o9IU0{27B_dFcr z95Ri*rmF*!&>UergFzE8b%2p3l96n0XEzE<;;I|LpD3{oSye4C{eX?c0iTs+RmgDO zrV2o5unYM6030@HeJb7ePt+4huHn1#GGt{3wUidNJaOncNJwfdRN7K6f7mHpnW~dk zy~^MxT>aQbiC+6h^w<(rlGjq__!n&kd5LPHMfZn)y1ZvdwKf%bgXQ>YoV<3izB@p7uorNGFH=+^BO~V@Jfno)wxGa{ zY6ubqu)DznaPu&gdG+$;*{)GQz&UWBp&iA^D=33S4vetKy_g8~)%Y*12iA6UX7jvP z59aRG_+WluB{9GGkNVwUpL%u$7BLH2-m@!n*H=bwL|PPkyNjHsq|dx8#O27_(3o*l zk(%G>;{Q_5s90{XSW;ua6dIUJWRZK?D^>XVNh>G!+38C1?s-xC+~^ll0|K#yv@@?Y z;eWFuJQA@_#X=i~CV<#gkOxc4;6ALK^%W$9duR`CDR_RNfr5z|1oaNxNdZX;a}pp; z!w}hRtN&>|RDaMMz^wrfMFy;ppN`HTt<>-Og&zft?&jA92ISH~*IG_S-^;SGTQ-YK zPSyV_CgjqA89(o-bg~EXlXr^AV>b-%g#yj#qQqoFE=QY)J<^`{vv|Y>CSh%*PTtNR)W+p1$*TbLY zp9x=pfH}6kJ`4T4`^A3bd|8vjn>qQS?d|O}iP(@3EASLnTKB{OR#eP)UzOC&9WEv8 zZo75`1#a0Y`%5x$z+!-vcREuGv$HpZT(dzZ0XO1pCSZ&}fRZoK(+vIcKVOGlTKGJ8 zVeyQsjrVVo*HM3;y#AQ{`@)^`bIGns8ExYguWGvX2MoJ@Ix%ZgKg1sjG97;WZsShk zfpbsr+ok2ZD(afB^@hqZdLaJRIWS;iQW)>j0DvU~S?C$|r$SWlX8jH`fq7M52`aV% zC?FGlwXbL4edf9OW99G=w9MG%*Wg`(v709pLgW}SHXL?=dyz|&3KXx_ikvFaT=ujY{U0rf!1M_s|3NR4xJW7;&6na6dR zLcE0&$am5XfV`NktsJ4N%fn?PhLgkVc-Kzf6r7N`sppd7fo%nNNCC5JYxb6ww;ee2 zDo~E%5w7(0M@kGA$3+LfZGq-w#g65mR_req#Z2N9GhFbh@W`=kB=Y%?bqi|>*x z9Q1cnIbOgg6u#|GEw88u^BJc{+BhxS7N(}oFvA3DV|LHSk3jI<9zX_f7UDgbc?etl zBAz`<19Te5RZ(5dCb)W1^XO48&j{~(WyOB7LzlU%F8Xw(z*aFaNlOKPBH|h*Z*rvzD9vHeo zo8(4MLu2OPpxlU_Ut4`MW33^nz3J8ATomk99W) zxPbKnL^;}S$fKsrSFl%pfW%wI#JjC$A;(0}Ik7gC;|WDhgT&z%35LD^th|Z7?`p4G zl#9F)Jh*61#H2n?C@7YR4e|WTXtA(~!*vo%v8|@7*Fs0jLorq{s^K&TzQp#nGk~ph zbcWO3|LhZ*59Y2ee=y38_%^4OkPQQ{yws$h>%)ifadALM^VxF)Q`19Oux_ZT>I~it zgrB2W0^<74G19WKpZfY-z&^?;7+2D(*L@rst8yDDn8xGC|9_0wd{32IS^m?g4RW*> zD{Gf_F}%Ok--Deg0Kb1=YTDA>eR`7DmmYY26ee6MOhrZIkfx4=lsY{-3m-Xaa%cjs zmx8qaiD8(iVuCqTWbl@T?hP6l|NZsxlrcL(aCgFtzp|oYwJqnPDfNG_G2QKq?5mk` zL0^W--ea0Icx1tV(IN7R?bB}!QobhyR8<^E$jI8z^^le!$+p>>DFY`n#2xP{DM1eO zw2kOlM1)gjM^8`WvuDB&7nO{RD0U9P909rXciFi8_VlKc=&$@pb*LZj6L(;NK<#!tK6)v@xDOjxF3m3(XdoK^Yue@Zp~lIV9r~5Rg-6)vvOJ*a@6oIls&dvJYR3juTol*jnadFcLN#a_S^%8q!3Vr*jKJLp)z{9?hBcWrNX_g<=S$OA%a0Sdo1 zK5H}1BA(i8%kYg+QXla-OG$H{poc|I-Y92`Tl-o`y|cyJ9RURj`eZQILD4Mt=7-^< z09fP-LkIP7Xxrh+ED!OV-iAdnTXs)9XiO8qU79_KO?c#11tLgL!{Qwo84IXSVA>CT zAvkYjC}Bpvf3cAS48}AwdkvMI) zy+n7qo_i2Y(Zl)~M$y~g<#bL|zK@H<0=+k+B`wU&(Pk2fu3s0(fNk~R;dby?%8!7& zOR^OKTBVI{jM8lyGMOloqnFSOn*PT(saa4i2J1J}`hs0g?rz{CMZ z6J^E+pB$(JJaX`Nj0;Lj!PbR@jf;3KF*73;YqvN&zD*0?5iBr}c&2rdd+;EbOWOG*5W{-VatN{D$s?PFGU=?Y{F2WLUtB zJ3c-h4ZdkfU}!R`q_Lh$_}U=jXdSfwOyb&Sdr_p<&mK#B(>|O@+RI^7b|@x})j|IS z;aK)}{9-~`D-M16G0(fJPF+o3cO(|~@A=3OZch7AMlW@ziX8YYb$2&T`F`Cx{o21( zc)KS}OoWye*+>kpL;geRhYamYjw4{%eAJE{;0R>KVEyYvfCGhR85$4MGRY0oE;x+f zt?CBWFfOk0%sx)xpv+V}c>$$VVWO1#cFvFC49|p+qdG9G>tSgGSf%UZsPW{Rdx5b0 z{44O|!n&<#AbgaYlj8tyYPj=Y3lqp6V1fdZ6^u}2m@PCfIS`}lTy}0l-`uz5HyQ#w zD7?pFDjq#T64X#hM0)l3M$n^MCSa%o<1L^o$MmT$M?<_D5?Wj@7F0-7Qtuet~63JKN0=Gb4bA*K)$Ip~xN6n6O-TL}8Xi&?FY)2=@oMA7M5$EhY| zhIo*4pn$D#zoq2E+aj5aO4`_+A~XO6_~76R>!q15O(Y}DzR zYA6liSgflfO=14h)de(#6DY61UA+YNL%jq5_}^+3f*x%9aFGrL`A88)5kWo3A#lHC zI#zNL<{@N6XnP?l?A-J_F9;Uc-x#Y8panEBHEOR9C>hWS!_~2kIKB!u4)s|U+*!@R zo-O(i+S{{Ian99HQ!B5k8tm%}qLISuxMKbJIVoJq3{`FI(3*rTPEJlkP|)w(S!@f# zoxY9!RT}K0)ARGU4Tf>^%in?ojn3Z%$oj8ezy7vH9>vJ45eXitew|0?(wLVUidY4~ zs#L{|3MC5;PShn)K@{XnV#P_$lP5HQHQ1q~(a z21!x}U;S1qr(OU7`wZ>y?)UT@<~Hsk=2uuI1@E>^)aY2;s^tv+-h-EfVF9C zs|O&k00HFL)2Cq99T^+z?{H?U(!;xgB5kk^7;b3PZ3`b^v%~)(g9(Q4WtNo$z<*m> zSxtbVT3ihM(>xpq@FuX0SS5ftA`nrb2`Psmt-CwCUF39dfBS35LD+nn!~G*8PfOw) zp(BCn2bnSl9#1&1;M9;@yx8Ev4cgh9Xn>0lW)wh* zAMO_ZxTt77^eS14FX^#!fNiBuUIC}ig#(TS?nbzqts<%Bl>`26-Kr(NnPD3eLTMAL z`f%y3E2JSn0lrQ|lv#|-&20t=3(P@!RNkjeP3I87C^2cC?Cax#8O~t5CJgS+N3pOl zF&`;|IaX6${f4eWGwN88@d}e*qqkzpm|<0$&wMHU-cLF+$>Mlo>Z?1 z2_-UxS4d8w!c7*4>RuExRxBG#2-itYj?M}+ZlBxygtic;XtZT+?}i4G0rda1Qmy4eJ`whbSwY zB1T$z4`ga9E^;=ETe!E#o-0=Mqzc|JnRuT_-e~tJxRm)| zztHt`GS*F#_@>8k;k)&I;?ohmvB`ELibx_xPK&2}Vp_tcJ+h=cAE!S%N3Qf`&DxwS zzFf^sxgz4lB>a(vYtW`XHz&R_YZM>DW4VSJ?@D&Ms!Rpkti4+O1mMN!cpCw&50p5z zT`RYASv?^1(_+d7Dw4zhL)u%1RlU9YqJVTsm!wEatB7<+C?JR+Eg&f^jYzjh3DO{- z2-4ls-Q6i6NF$y1o$Ghbv(G;J?zqog&-!n%V9sxhG2TydCa3b7$!S)66WJKi-H`WZ zV3%XTu3~TO-rLlESJiN!T3^*MI^Eyi^y0b5eTS`Qm%l{pa4DL;^31QP-2NhQ@KeB0 z;;GWd@X>(QZmBN>VBh!rPC%g7LR+P#SkHQgrCIl)Mjd;K+UkD0-~;yZi7`Ey?#YY? z?bjoQCQo$9ogF_gGB~j$K9zl?v;D^}ed+EgTcCwDdAjKQ-E*@AEOq1KS7#G~?ATm% z7+36~$1m=t$l6tn^QyDFV2Y$;v=>o*nqSSM+$)XFAM&x)KumY`qQCPmWw^Y>liVey zRr5HvvuX~~(_>LD>z)Hr+CcTnEthwB!&a?+g1RDWLTb%TovwLRQ+Mzwm~MLG;=;bV zFx1`CLk(+iIa!DPb8sn=03Ow#8r^4~!3P&Tj+zt~ zJk2gKQ}4!VJ!eAj)jhq|bKG^P;*S;)dV5>n*^;A!O$)I zuj^;EKMq?a$5?fXUN4;GVLx=M+s1$Lo^GdjYGY)!_@&_Xx)!ahPI8ZGiw9-MM%|FN zC6|h>6;1HWr|MZzb(j1uB46o=Ke1I6HZt$#pD9ec-RsoN-smNxsrVK){+#AG_1Cwo z!a}JcjHIaM_bl9hMc<8O*2qvwfSqrNn|vCXK4c3xLHh1Zu-a2zWKK?NVzPsN01|Y( zqoRnXatRfrrO{MU+v0}tfx?FFnU1PH;Fy86w34ou0Mk`x=NnMtA&w#zr`&4+4a16Y z_X5M;mF=+BsZTup9vk!Jc$kP-gSJX~c&}3$4K3rbTAF(Q98uv%mEupjOUVM!WziE# zZHL@kVXvMV{!pGMQti)R{xZYq_<$tiB)*7(L!{Yedf9YRtRa{q;+)NbEazJ(s_5ci zBDoC~Mcp<^X%LfUu&bVc>SaHjZo#9XaZ2}kRl$f}f8#{ff~s2gncL%Av>|8_?$h$z zk2voISFe<;rpn|WkLa0b{c`_nDwSY#LaRGuwsQlQD|rJS4`xclhpYawZ3 zdJ8;}a1wbA=cVV*HA~G1t>&gA=_9=Tt6!IfG^#^X!JAC66Q~Z1}QGw^b6Fp@N z2t5RQ&aX!M(&~2p6gh<)nl4pne3|}WO!d$`Eg>eQDmkP2@y>YF7h~thj_&^Rs9TM1 z-`X#->Pj!uhP5;`hOzv7I$vVq80;I8^Rte_MhSZA5tl-m`?up&_ISUnKEdF0Mf*uY z-wz+ZkOE=%%q1AodI zK=~RReBc}lI1n&>&Bkv+2zwwz9S*Mzfe`)X1237}5`uB|t`4}*Db5_#+taf>Umu?K z(F7oH!b2TR-85$M)T$1KK;|b;P(a?)YL5 zWa{wxDxvMLpQxs|uT=E8e(hmnXb#&O7*+auLT96BZ#gyG*>7Wev6qs#YC5Uguy~bo zE5vN$jX=~ZYtzLIEbhD!2$w?X6cbjWLeZRn|*}Sh`8T}DuVU?vd)zv;VoyebWu46z61lkuW5b(e#g8UmGAvut0 zQs^@2PL{qQE_@m1Nj{xcR=NY%50H`ugisUoD5;#8N&`>la-YSyxITKjtYzSMjC41J z)>5391%p=JIyY~lLBHA|#UVP@o#{$5Ps1e5wK{Bpn_&3)>27IemApezVnP1PT#tH; z2D$lcb2*AgIul=2?aNTVM!Ulp7H{dtohF%|La#HEP8b&#pBE*DKHG^)-3|Ymlatq% zTlDk2C|sQ7qcMKIlTQOLj7#75go!xtaIpWVOz2?Gw){CgIr*+tfmZ8`YLK;o)c$#c z^4VgIs5Cu6!%stWe>iY5-tvwDosgK_au5&%klq;-go&NbK+usYvDKR(@b-4~(=2My z_byN}EjKwnPOfPZ_#IC1U#Er_Q8;z!)-zT+d1#dG_H^15553;lf9!Tyf&Y?gtZ$n{ zX735{T8GUmVOK?-h_nwjJx}^_Sq#tOvwnUpKTty(9_d`V7Qw%)e8hkLlbb~&Q^ftk zJBxdGzKx;IQ$txg=9F-A?jZMs6SYK9UtbCeb6nc0?04ee0DoDQ{Eabm7G;CBff{L|(Uk!i{^`(exY;M+CP4knH z#mv*K1USO9^5!=ZE+bnd_tB(2^bVE)%I;&2qnLkuk{)QI_J98lA)1SIlZL3e zArTy!eif$pnIi@oF}WH(2mFyw@Ab{SlclO}5Vw%Ixwx(1gQISvTRBxBe0@>0yW3GY zta;1wTTOu_Qeuea$IPl-gI8DRUzqqXVsYs8K8#fqS=R-ZQE*wwi!e}sUs8K*r1kaV ztf(pQR_i*=GkW0Qhwlvika?OV0f~vXtR9IWy-s3-F)9!&@IuaEk8hV%R6rXO@RZQW zUK2sfOBDxjt6PZ|M<#<#oUybk!vE zsA7~;qJ8cllMmhXm{SnzW$bugWOY^^!`-&tiRXW>Ji1m6DsVrg+`?^h_GsQE8osl; zoW9|K?sWXUP)=*7Wc$ZGZ-v{=`Nfv}$JJq$ktucQ0v5A>qvKB8@Onz#qxAYmzHJF> zk~6KTbUMB4N)VaM-QmIRh)3&+x5{SCGif&v#doq_WY(aYh^n1nI_>Cs^Kd1WBk6ts z2x!lbE|oZYUgU)Z#P8oII^Yv^77b9MV3;fdFzYWEE)^5`wT1FQ-o#Bk$7m zrS2xxcYqauwE&%$X3=YZP}D=W%hU%CQ10xbqk(U@xR{S9xD?(-0Iwd)%9a!rU0xj$ zVEQq$ad14w28?oz9mHA>9Z#u%8;Xu5p-AE>Of@c9`)*k|UY9m)>hgOUU9S*t`?O4h zOS5M8meZmxzvJ?Q2T{BlWMr!zj`n;C%6|pEtq#ho33nksoI`b(9QtW_hUPX;Q1`og zmLP9x>sGTqg`?puxuQ!#xirL_Wn@2y!m?GzSOCuV1$zZnQjo2k9>h z14CLyhJV_fS^}qJKvr$9tbn)`y$eW-1rk#m z8?ggEnVZdhz}9fsKg?VW+L`iLlN?)je`4i=-}vJxKEtcTB-MyR)b*8zI<@A{E<$^o zLgNJuR5gz0ACP}@hMIX-Y{;MojUHn20Yc}QoE&tIqptvyusu~4Le+@vEpCp?Arr~_HG|{o>gt=e+z(YZt>DRMgwTyvg zOrAa|WkS>;SvYKaSd;({C2;ediwh(@*qEsvlG|$IK1=No*@Go~95kv#Xo)XWfza&KFKt_fuz>7 zULSF@2t+n9Ik_*44Hch1k9tx61@$s~96Z3&IELXd& z$1Q`uCIgiwuQTrk56mdMHlUn%wDIo%Nt=)`OV8v&ClMA5Vy5S0C!c8;fM?l&r5Dt` z3*~klD&x4cFuwt?3{pmjU2p{s8wl&cm-i*JpdPrO0AoDc;C>KpnnZ_Daecj*3Oag_ zukVsg*h>`^J9sH!iBPe>Pw$o320$?688k6SCipm6lBHD(u(1nY$XUL8axbM{Jd#kJ z^&l#x{%g-kms`cB2QQ}!M0R*8FAjUKWxBRoy3R9?P`}7^xt|q%_l=Z&{Pf9uV|%xT zdCyIjk(ZySH*5YL^rjaxGuKgeF>h2@MfZ;pJ9os)9^Y=4svU0rA3%+G&T!VA9vnpO zduoP5NwMov>+jzRloe0(NjR{(U-QiTc;5bMfiwhu{_>t4h0-$d0A7T?_~L|@6`C@A zv}?o!B;gPVnP?#F0X+KZOWj?hN_EIy1UnEBcTM&Nc})-3xRvDg~<@x{cF&F6a#xD zZWah9Y+x|I)k2`z%dt8x=5x3fKpBGM5#nLFp~Z2W2Iz`|!$U~W9?m5C)f#ZBL7rNmJY%zvND&+&@(%+ITFF>7hm zNWY{*gZgNAwD&qm_{&~pX-tdYtJnDfRhb3dDuivGjvwRenwEC4D`=Do9INxQLal-UTZvD9%u^A*l!mK9Q}LnwqEoDm4{_ z_6(THA<=GA(4g=x#2dl-20R?sYWG1J4?DR-IA-d$DX!}=yop!i8@(%HS2JR+l)>fu?%yGVLec+IgfN8j_UPzXWC!Pu=`DNz-`O0z8h&{m@owiP z-;TFhN`F3#n#qW(?nqmT8QBxeUZPb^A|WMnVm-Wh1 zq}qwXk!1d^CDX7xU{ULmJ}Z&h_i4W9Ks4l2Rnm8dn=om!GTohY)DM!uDx76YgmL-Y~!}hlxfWTyyE>B^+?BI%2{`Mkqa%G$c~&yc(T8#d#=vc zAr)+Mejr9Az5tPjl!%56^3HnQtx6bOZvL_b-z%41-NlB}LaA5((sv$@3m1@M6JkS6 zJL>hhHV!J^>%#K#?=iIwc`QFrwe*;NxPq*c92__pLMaFA?)?d) zO!!>+M`y*gB4}OuRW2S!JiVl!L+>bTJiy_~Z7rx7R(t=0KC-F~4md?g!ZQkDBAu)p zO-g~T*M>KKCXJuwyb`1HmUwJ4PrGCxn2AlqRkweTe6_Li;s1u&D)qVj$i#)o0*d?E zY@E>_j=?R0(#Lgm((Cxi$7ogD5CJq>pj1>+0**ikhO-0y6>e~BWTdw`PRAMu9CEp9 z7WZ5rstsaR*j{|67mERtW>Z;-3_5(HcU8&$1+lF(Sm8l}zir<0%W2GYG`6-rb3Urn zn?dAcA4m13KRz>{G@*L8aXB^W*I3-Y*ly5qhiLUYb*aDqC@=G~`?e(8*^7#&bDxQL zb*;#%s_x%KKgl6h|1uV#@tB0uNl<8dO)lJjP?Lbl3)BW|NY^87!obB_fxLijIRp`r z_@It9E)yg-yHS$p67SwUfjln}><%f|)guLTzo5fL&f;wVM~I(#`xI!BIEDnI4XfIqLK1o+Su&b=MJ{(}&H>P065#N-2FF z+~*ZK8fYxc`u5BGc1~9DA@t2|klu4$=tq%cjF9^VHVdR~wC0*jZKMF^fv6rfe51=0Yr79`(S;0q>ukUvz4h!&?ZL`#Jv`Y;7 z6c6f@@}b#!pI7E7xWjv;O-UEbcR9#t|ZE4CWSeR)w)@E5CIMOE5}SiKC( z$*EY2tMf9kfgH0J#riG)n*y*Y%*$}&aT9FZh!b@Dv*6#3!r}lvC;dXNf)5`*mR3|C zUZa2^#U3dGK)$bCpJ;2}+SP_b1q{fjoO;U214H{F!bBQUEq0Kbhc`34v9SSwC`2uV z6^5_gv~_Y?g(#t@4*Cc}q(A%{LjMV(G*2q@s@?ANd+Faj@0v|AEA570o#!28&gC3x z^T$svJ1+mmG`Vy#Wna|j)dq$3XppA`+!@OLNxYn>9Nhl8V?>HKWbZz?XixY2LdoOR z1v}(#yjt^Z)u+s3uPaMA5B+T8!qkH!--PlxohK!8Jjk>UJ^FiH*xui711Kdp%0L+b zYF*Fxuy`jplRn07_>OBX4P_jVD+N0IhCAME3eTQxyL&E>eq)PEOf+Quso6mIJu`D2 zLi}K_K};#uphAr#fdD2rOnc8$^~UFdn&`ViyiYkcCMqA&z=z&5{I6a~nyE>X-#-kQ zJ5jG19t#=#H;@&!BYFnUe~DQshx;Y!yX!0Mzm8pIyqh^2tygS2MDe<{WOMphtc*vg zOpwZ?>*fXJ&yW4d;fuujPPv3l?cvFKIYUD#N=lGGEe^K}%y)1wEp@!)gb803djwU> zS5{800|XfWhQq`Rc~dn|+Fe%XtY$p-Pf%4W9Gp zO1_lyFWw9)+I>{|di+#c5BwR^94*%q;M_%8v#2=-fXQrWq+1$2BzK!ovC>*^P`-%db3LY7HG&`Tf^*u724eK-Mh0dG#KIScU3U4u_0lh7j7+x{owfz5Z2bv zfbwD(DWN(VCp(b`*?&F_as@OsDXD9H0iVRRn&LpMX1ldrX0x{bWbU-Qk=)YP&Ervw z{213ofUZldB8{tJFLc-Y`&Y?tV*m6Sno{0necX`OK?-tBYRjQL8ACzb8Im< zC`cSTARs_$35(xy!WMWuP%Oe>9(MP7=d37Z#r?0laGYn94NHQoM+ld)EXd9Vy~#L? z+1^XY{rGRmxb&Goh#yca15aL4s&V3>dg;}UrbOdkbV9{Y$`Q109ivKLVxrdCLV}AA zk5oEXS76Ko30H%-z@tZy@MjNk2zgmb;Q93n^sG+=nus#tDGc;^xw$|Mic?MGZsB=A z?yG^PpvOl?Ujua<%y}T&y5V9A8Uq|`D4YS51ynXnk#caK8eEX;(cTwA@71RuOca1O z;v>!fJ8b9B(c7UTE91uxFxjF^1i_$~& zX7=Hdz(E()1SkH*DIEDhQT`heJOlA*e7cz>=?M}5Vt5IfLGUCKsE!aH2-A}P@BU2z>6Q* z`es}TJd%wm%K|WCgAW|;8|2d6X4`3$T4)d#f(hdz#OpTHzb*o!{@4|lAQs$&&@=&F zkk)}T7*9f)pkobrA^}EX#ueB`aj>usFU!2Wy+IKOGwO|#=8xgwbUr#n6kUIq;Ox4< ziGhaZT`@2*v9`GQ7646Xn^OHGii-|(IAM0*!#rosDMua4;Y;;#au2fPk}%;e}d zZukPfm6o;$8HO-mHN?Oah0rvzvp-c*vcW_Z2hAxR08&gWEb1>_+(RXmps#No8MzMw zXSmSt;Nbe7KPbNbcLa9|5-IP%@muLo_cFr0>|u>md7txy}>AEZeej_1;8@hDm%2pG$u&F)h`i8)VfQ(fd}aH zGeBXWZ-2ng?{Tn37_R_ph%?w7ZHI1r+GYUlZGL`OC?4|^Vv)lHHCl&KP;fA^Gh|6B z`sO^%%*cR2ihiq- zAuJ(TYp^a5up?xN^AN)a=g3)jX)w$?-XOtkgd2p2aoM*87dos55l{rEPU-`{5z-{# zG6A9i9$mDH`2hs1kIPN%i?b&%#mFWYKg za!7g1wkrTmWo3>A1`PWIl{w(spQ7w-S+oU?R&IL$)ReGslt#lUs0e=rw8`-Q0>^}s z4Y=YX*xX7F;A6vuh#15nCy)L4Q>2oAcynzCPLXhudZJ57CG|uKZYiZ!2$>ed#(!E| zhcCi9#o+}JqVOJoL)?Ou1C%@hoSK@NBuomLCwgkiUKbeI9(QyMcwlU7u;2bUSLa_V49bYvt8fwD?r+l2-I+@6n&;iQUq z%kjluEO!!@mN}qUI)I%G5?JB9Yh{%OFp8}f2yx9ee8lO$;)AyND-Nt`aQ{oyE>M9E z;Na-_26t-ckZnOXhFcH1-sP5%W#9t=DGEo;EI2%0oR+|94w$&4zZL692icZG7DBVIF`ZlQR{wAb|E{) zba4{|gD`A>-1YvgxNEw9)5#9{^r9#v3G9Ka7M{D*6^R$VN2qNf-rmSoy7erOQv5H0 zCcHXG@MOzfBaLrfY;O;OZ+W`3tDi0N}pjGK7dH+TA}v$wEI?5@XC9E_@dW{1dQ_k~%V(0MTqR>Ybhu zv9V%qM;v^P^pL^%@}(2VYs^9rmlX~1ZR>t5E*5!Sdk_U5U=*}2?QN2P#uXMXFSf{& zSSYy~-1KX&W4v?6j|7H|0k!?R(7yoDx(K;bK(XZ!Ak^mqdxh2231q9!K*h3%gZOrO z|EOE3{9~-h^x??s%mzZmD@a-e7zN%T32hQo6v|VC$W|O3=@0f8&=??BB@+~^hKv(X zL945(3VUA7Oiv353sYM?C%`mXz5!BS6iTG5U=T-dfaHo8hIW=`Ng8$UAF#l~ncbxyeZN;wM!~Vq*?G`$2MS>p~|kl=7jcZ{OJ5eS&{9>w0GLT$7l19@jYPaGJl% zbR$^EsC(Nja*1Isd?KqYmR!mQU$=w(-Emo+Z4oBS=*_hO*-IfiLJqr#_^!Tbh@)tHsi38_x2Fg*p)CV{eQa|LjFjb=cPb8~Z z(5l3UruFRA{KyEjx;RMg=*G`c%Yn+m~->< ztvg^ph!8{KO!PN4dfoDA+T6Zen}&N~jHhHJo)MF4^;>ZWfA)9NxnC??yiWJY4S#q> zy%lBX*wotp+HxS0t&<$xZ!2SRNy?VZ+21QQDz% z!vO5Chg2u4Z?2d4LSu^#<@b8!-+Je$Y|AV&2?cd(pktJL*%eW1;h7g5Fk||RMc2>EZ0dUFJ2aoAgOjh=xoS$$#GGQv zkKd}x8n$BfP`p-D`i!q(PndEi^F4jh22}yYyc%nmJM~Vz@rC7lt;%dPu>r=JvMDCs~Boh%N^&BsNf#LEl!uQY`J0#)Jh{Sh+-VqEBA9O4qzBbEv+~`(j09 zWRyKORX259$NVN%jQpFgnNz$Q8*feRE4qIS{j5vbPw*nX_g0%J=-l~cYwtAf>r$oY z;~hbzvzNN^O$!qfnx3^`&pPgJFNwLJzgKd~y9Ls^e&@aM)$0nkkhckW!^KvUzv*=9 z)fP?q$7dOW|1*GmR$b7mSNcrl$X~84f(|_keWjRVOw+ic^zwy=-LF>N)rTc>8M6n8 zjH}BlJgUAYh zGjvB;oEOO~H4EBluz|q%xf6^HlLMSs9(QeTZv&FQ_6JURUr`;T7S@@2;+tiEPC5S@ zTK$F)mm_>8ef?w^Ks=T7?13Cp8!QbOHqFlby=T;2T2D7wmbA{)9{r4NQ%Nf{{E;HB zC|afc$DH-)-aSKJjdua_<(>V-o?gV7^v5s8I9@(^gY~}Y>qG82BA)lNXl8`+#YBJW zY_rb3h*iI`zpZUUyAt~pqp+%@H&oF`q5W%gtOb_{*7z@}kH5Bk=oLqMt0cAqaqY*H zPL01aLC9;rkV?Oy>7pjx-SMo_XrF{o#u*c6c0QoJJ1hjLl)l2Z$8|UJH2VZ+mQR*NgCWfbz7GArwjU z0kmNvpj&W0IZH~SaLR_mQJN6FiysGI?`FXT+l8lL#&K`f@*W(^^OINsZ&VlZo|a%E3h84d%#)&*DEE&)gU5-bTSc)|=IM ztgX}>e_$tsqsJX0L_|yI*f)P-8Btgp=^GM~yuJChUPs^ahXYa~&cgr;Tzra0&j-IG zQ%8O4xi9?vVmL7Tv4T2io49&EAYc7y8O?lfhm24dy8L4XC;X~x^PH@CLH#n{r{FLsb{j#lyVr=C;g& z{DFlO1X)65*}y1FfHJpA9o)agCa^R+2tlg~rPYbe7I92Y&BGxUOZISf` zK7|DIgDBBVYrWsZ9vN95I+*j#i8nWm%5*-twft_Q!v+r|*>h-hhWj5J8Y%+*%%N5^ zY7GIN`RC6;F$A8G`?uJXn4=)EiZ_~;5yW1lEAKHVI3Q2p+vcxdh(aWXLpZ5C$K;&k z*mR-kUP&D4Ysc6w)-JU|X0a<{8K0XhR&}3eIb=NU*T!CAip|>J@z}e~&u6IXNA-y^ z`{-GOjU*Fo$T|a3w%e3_t!WOmrG}Hhb^7IF^PA6x|FY}^X`nY^b-b4l6sDE3&d#?! zt%}NI(c){8+@{!m znnvqZPJf5{2gt6g_E8_T@dX)6fg;qrNz48+l)z@un zab}^-uLWN*$$Wp%HL+#yR6LT@_n_xe&DPcyMl;YShlSxY>7nN}^!9EkFx7Oi zhmtW7rQqQD@dn{;mH{0KO4&`;j}GM_7P0dMxsy@Q zrzGIWhrq1J$QA$=x;i_dpV$#RkDg>90xrVuPYBomF~iYi!UQN0J$MJ2%x|Q5TtcHy*8Xrwnb+;U?yN!jxaG~DDH?#5MPF30( z^P{%R!Shqv+GsaB8?M+1YQ;c5R+c%|Dtd+M+ly~+ufBDCzgUCcHm@KOsW$r9Xkj@~ zz`{TL`kfN-n{PHj)&Yh=HuZwz7cx3fzxGeU*1(Y}t3N{97NU%wiH>Bd`pqV&x$>}oK* zKYMW_2mp3D30UlOnP3Wr+>Z&48uD}YflgE3Hx#y^t1pqaMfmr ze2tetg+B*7v{*pfyOJ~Ujq4Or5@8#H!I3zLEvDP*V(wbc(rt%uNd4H1pwQI3j=*A25hDt`W#p<0NBR!5&%L(i_(cdMAd#&zFCwsv-tYTv4SmnTGehg zIbyfxC3SuESW;h2-)dL*XT@*xEzO3MRj4PAWG@uW=@M}EapFnfaJsp@Z4ICaBk!yR z#~5&k5W@g__rfA1FF^mW>){`@k(HI@W%^)kXbKD`4^Wp#EFSlwtp~$kTA*7)CXo2RVhlics9*u&28@-&3(!QTg_flF?w#O( z6Oh>sOs(zhjBrg?(h8Cv-v)!Q)nqZC9r~;|>JVq_Q~jO+=!w+s!V*mi-0qp)ACG?3 zl+#s5IKIbQzg_;X>u7Jh;OY#Z9+Yr+?)t-!oiV8ZB21j>9%$8vZ z5R`DF149G|)u1a6C?4F$M|)-9sc$eeD4M9>JZFgNlpA>j<%0`0_@lC3LJ-UR({2Sj zi)u1GBZHKXkXMInVw(|@S<<<~-o64;b!`>})~M zlS9ah@)#}cmB>aO#O5rF?gJ|X?~;#mAgZ?kD_ulrC?trup$ieo!)1hK==k_k2!!+1 zB82()2LiOb@B)D)G(XMG>cTW&#p#X`(h9q__=^|BQj}PbB7l^lZ$FE@81{E11!s=_=^)A4W|A+?T+Q}hLgJHnLQ8KsoR+ZK7y_{3- z?u{bD$KRsybS@rJUDj~W8{Mbp;DEX$BO9Ck)>i-Wm@7p56fh@nrywf~Ub-8J0{0Jr zKcHj-+r5cChT4-mL%`O0H6nQF2k1Cbn#!*5#3E+@hH79JjFi3kailI>tjj)0>#)5t zn|rNGx;=L6JjAtm|EKG3`uS%?2V z{|1PJowprK9vhgLpz~X#;%h_HAs9v=%Haj$24OUWdR|_tsj8x9-$tMeRAzl9gytza zLWFNiU5*xC9Hoo(E3y3Jmq(vCiI}4+(U~WpVAk`PcgTUK2n9T!85U)cTG2 zkyD>xl{`2;-O~elb?=w7eqqFOId)(YU^RtQ38{OJG2uFtMqm*~QM6n>m9+J;9jEd^kEQD>=4}gtPhDJ7SqUkwAzvz6CI)pr zW?U(@o%+$2SagOH4IgLOIabsE7l0#O>xoS)#o`mYE)1fY{Jjr*x_QL^1Kclwn}cNF zC2s_T>2G;eX`u%K}|zrtM+ed)T0;w zAJwQ%PCAk9|0YMh67h`M2%-DQ_{+2>LF=+71EuC9C z7=AC<6{u~pY9F>pw!X_evi?V6{s$G=vp$R7QRcS|8ORK45RmLo0#Se%W$6$}2b;1l z3XcZldHmd*oSC_RARYiK#J&RWGd@fu3#%(28#lI}K6w(npA!f-nh@nFf5?gGoN?Ls zj~e4Vhne9r;jl`<_#Z)+d}Oj!$xIdUc}J>$_{ik0?AZR8lfE3_8nEChlfvrGC>?yU z6?b@8SyDB0eXx>_s?zfO*#QWEc4YAqT=kE4<+X{PsQ&Ie=#z z*s+4R1P1sFlCv86r65yKzAtRHcXgee>taydITr>LWI!Fy`=i`IvF5+?dPn9x43~Up z&_`XDPa{LqdW@~zc`&s9*MsVyaleBzAxw#jot2d-8~f+GqZlva=ue+F1)V?sFD)vL z!fFN7Zw+huR)(8eT^n?o<@%4jmxcEtf@hU?#3o*rLRxiWx4w9d1X{<7BRG95Qza&ZAtVSAU z{1b>n^g{IAGs5#jJL&%$a_c!mN<+)e$%&K%Es2dYJ|5nsFKq~f9UZv;2KrSoNdTg5 z?9L9>!K;dd265+CW0;grL0VnS%npg@Y9#Nb=-&HBD3M*ne)^OkHDcS zJ$732v=0^0s3KVYI zpS-2uGwvPLGc>y{LHqxXpcy!j`JtyW-^C!WpK~ig0=AZ#n))&ix=797fC2vk{UO1?X7gD$Mb!5=<^dELzi(=ty1<3i{GAr4N+!h-%cppj?b2yuSZFfgCtB@7gF zgB_<%r83BgpFDZfKa~t6{J(|2s^k8hx4Z36g21C)4Ld_CT@3W$jDjCu zYd7x}bz2Ku{fKH`u-mwsGvzULQ|gYxwoJeH19wik62qG`xFJv3^O=i3uxsx)IhDWS zjS56(HkYKIXXD~(Q|5APpu|<7uM+VG+mDqBq+)?otNcS+GpLVX3PMO0jBRXoVA4SG zRvt#Xb5ao91nMdfuE<4eYoQj}6Z%61s&^oOAG+n1@xY0ur{5+fei2?KNzX_%;*Rp) zU|Ii8tD2W@5nA?-RyF-j&3__Qt=93RSj}O3n^YO+zU7qH*hMFz6^eG8;-F8-tQghs zpJ-L_Sfua_Bl;*x)o^(bm81xbzilz?a=*Tzp%5G#^Ygh_q4&KT>WtyETuV|tTMsST z@lVcxyMstO=oE&Cz~Hk@d2A>{Ff}khHt7b%2b>DgmnCFwWle(%7mG{hr{kje{Qkw? z_NHdWrDvvAg^}AH>i+>HdmZ*a*Q4r&wPviCad|wtNUF%(PWoCcncORp-8b>;i*hjK zSHtuN_#x{qpDE(USPd)sCp%T_1<7kY@a*9{@Ef|Hva_oJu(KVy-ddQlU4+d;&H(jJ zSzu}hXgA=<1{P0{*g(&@9cYJMIiaUKiD`l#;*Fl;(653cUKD5>A9%__6AKeIybcQ| zARmNKhg}mSzNe|AiH9^Y$d5|IAC)MQW{hqM^t5j~H-+7sxaG8!Cao~=OS207tShQA z=yU%tw{GA0$Jiq$fZS@W`Tk24s)Go{e+ee-B74ekFWLV#JVA}4vG7yY(7?RPd=V$? zS`4+!m69L577{^0MvrKXcK9qFAOy0tPtnnLh=Rc^1;+$1es3({?73WUV1ri|Bz`cy zE?C3^S`HPw$4$2QDxbRzt0VofzAOT~7# z^V>*=ZV{&jzbF>vjcfN?!gwa{l`^CscJhjb&h;NJWXwdl*;lo!nhD-{{Af?66V1RQ z%&*-pXS1*NZi$=Q$!X8Gdz7eTb!_s~{I2KuYBDN)hE;wB)W0!T5Rm=5Lf5}0AUp#h zEV$Q7NiP`?r3LQiAfv7+gxR2UMLggkym+7&Ml-<_$b-oZRKsEdnD~K-@{RrdJ0ObD zlay=%@C3Hmi1?2Sw{UQ0Ab%4KI}J)oT3YYC=5L@%-W&MdE18;Dy!h%oASGov+2+>! zM*hm*v4&MfTTM0-{?3ylk>eu@ZTgxTah}-8?RGu)=Ll_Tmv)$>0vOmyykY7PQE`%~F!x8Rmp4tjx zuDD15HibbQpGHvi)vK^HD2;gz&fjUsv#SLOlbk53q|`uh@7dk|({=pEh2Z~i9W(e` zVAx6rr$KBfQV-eg-DW0B2wU-J58FA$1PpEMgEuZFK#SI9W{C8;Zj<1UkOHkT>?dDI zsi>YF?s*2oxw8N=GsBhOF^2$-lW+x9_}i;+)P%fN?@4%)s3TyqqB8h4#i7!x#*KHb zn$&f5K0f1pB@rST?d4eQ(7XlYqv=9VDW6&TnL~^72C8bPim(1|38TN@}*R z_<%9|@g%R#mpfTC$ds=_R!whlCU(y5vF+GhY#l#lXrA>jZx)@SDB)oR@E&qkN z*e{@6g8@@BQ6ePkEJ=&21YEnrRcE~my692p1oyAE!fLrSAB$E1%|E*6= zmArG5WMtIgda}D1fH%+b3mp}qXhhQ$iAXbr&`LPjqN1B&J}U&;&DXqy03JLx;9|iH z2ywS`xN4Ufxw#6jUeUTT0tN;l#j+W861v7j6g101;B0f7uBfm5swDo{1V#TN)Yhb7k@7^I~zM1 z(YK*necyUU04&The1HwfTJwO>AOK=pL5B>+y_u;gK{hrl;acc3guB$>8Mlqh_wgU2 zF%~4NfVlOBue9&rGx$w_bV>@7L5Wu7CUUobIco=|EEJU&X@WLUN>AwK&6~Swfbzl2 zaW7I1-lHGzGywjhpG9U=iO8$mrvXIS)buyZFt~HId13*NZ(GgRiO|y{xq_-2(A-f7 zuS?It=A(*xXhU0hY-Vlkak6XR?k<9X(N2KV@VW@LuIR`}-uw4aQ5vk;K;#L--p$w@ zKU^GyC6fn~!ys4yvE;!)X{C4r*n+`91rKRtARv3d)gfX{)JctYEA3W3fOa>OaePY+v0XJ=!B;DVvSK{&|rLY%KOF6xjoLg@Oc!B_#jITRd- z7KkzjB>;K>0{YRtjugYCO9d%~zL!=J$d8qkl_BfHic~C4%v1DJ<^l96m`!pZRhB_s zH|4W=Y zSE~s#vaYT>Qfw2AIHXDw5fj6rng}XV$C~nTep^8EB+Y;lf*evrIw+4`8z?U$B|)HE z{gfxVp#>!Wa5W(R8{@4O4BhI`+@np7IwXR~$t4G_4z9Ub&I#7-$P-v&ATQW9F-$>c zrwdj}MB@~PhS!Jk=V6~d5mjb=%|meqQ8YM0PU0oOrVsDX;AnGWBXTb3$#Y@1quifA zb(NI3Sy%%9pfM06piFUK8nJ>%9}X;FIsi6I571jgjISrMdXV0+sgcph*q9Tf&d0{m zy(=T=@PxAt->ya~qE8Xf;?fm|uygn!Bqn%NFzPuViwr_HY>EBLxiFXO5s>D=P1|QX zHmL95IRRi*@2KT0YMEuLh&;*I$&N0%L7)Wb#5H2>^A- zd4IPg3;1-f4VM(ws?_((9fZKe0P=%KFAzh#(d&2X06#*eJmq**Tlr5e9i+OGS#i#% zX(sxo|RQhW}L->Z^Y=VgW=KqJdw~niF-M7AJDM3+6Bm|L8 zk&qTaN>GvRMnF)cJ48f~4go2V?(S{@Y3UB>ZUo-nbf2^LKF>aDt!JO-ect!ay+1CU z^Pcy8-PbjKV|+(rBQOgP=3Q%)e=(_Y<>Qe8RK*PH4UYii00wS&cE4n!8^U=j=z)_H ze}%N89?TM8EA?P}5PZfq*48j=Kp-GQV)n_Rv6Bv`7TFJa;&?;&6Zm(kjhV4s#n#SM z9m}VGmTM8vlp|9GS)~7tk0^G8XtVOmPHX2^ryzfM}>tg(i z6_EwoQrw#fzCH7DE{TMk?SMF82X( zXwR+~1Ji&V#=5$sQU9Xm_UW?!AK6DePKjI2_qIX2zx(`ERc{@S{3&JRiz@$Y?GKh( zA8<6nt$3)}Mnq*>IC(#vz1>Wwes_G}A)!F}_Ii2V@H-2`3z@NMcf&~@l1P&n{?}YJ z6%HJHj{P4lX)A23D=!>X(=7j?H0_vSy%p`JVaHTQQ=-wv*)EUFm;M(N)SzHFGc%@V z2_u8%2yt<9DliN*G)zIFw-N}mXvn}nF;Ay({ypYt{r5PMf`33yZe}AQW^RKuu3%J?U8gL$v4w9In2eNn&Xy%mvQ1`dj(2e(rp7*pUq1F1`T zaN9RdGh(j0M|U;YYR&#%gP876{vSY0>&;l7sTR2ngNrG9Oct$T#5X|wS?g+AfYTE| z3#$w#4x@f=*R2VSbf6Sm?bl2K4SYua@#D+S66){qv>OyacLD_cL?DSqB6SJhqX+XJ z+|gVA;EuNT+0gxeZ}QA8SKAdk{5rTxV*V;@Et_FW;F;rOupRy;ScpuJ%9f$I}EJzuX= zCf1~_CAfLh|2B70QW8Hvvu?7!?YX`LHSompk*ij3#0_b%`W?GGam=UtXRQ+i$C1ck(dT7H{80Ij~qgOPH*-`D9#)xxZ`~XRv6mbDepR)-gVQ zr*Msxz~R`z?c1sQ-0Wh5uB1(|&7VO=CA-AWZCTd#)C)eXjuMX7Zp+T6;FI=Vz0@do zN7%9{FaJ%CNn1Diei4VgBtmqxCg1dF^mvSW_j2`q%6W7$c88D; zrOzz|M}oXsG{UorWVXD2iyZ14@K@weuYQgBj7;N@%-5movI`_m!{}=R8qtKPzXp9X z<;^6SsXq|$$Hu<2{@NO_x5P}n?S!Gca$@1~_3)RV0p~G;H;5*wo6@yO? z9vl-NVnb9F0yW>jLIs=XV9FFgV#9u+R|yTi>VIR@ylnE%M$PY`2&1OpJo^Rtzl8&R zedtWj?DsyTOOBT8LY{B?QA1;r9uHaUB!}n>C7hAeV^#H?j-4@*ff_x;X2do7kW0C9 zrDP={a3tRc@0~a;q4G6V@$hUretz}bPwiqd+DW255GcVvDRPg@fZpHV(J&S^whK6f zt7Ah1{Cj)*a)mJkIwZ@XcE-Wpo}Qi__p`0!1r#Nq#9x1Wc{1_uj?L%pw_!=Ut+@hw zdH`UY8JCU$L-c{n&?Com2Ts}6e(X0pF#Qfry$6o#^`xziL|(DS29rY7ZCCR*O;tg|F-zo{aG}9pd9; zv~dc1PQ=6!*3yFP+#PhZp7_a|klBu2<;0~X<`oyS0H;xZM(EhXuuf-ak`3QDC-mym zU^!m4i^>0tLzsLq7AtY`xxyt@{wVwlBXvw!#^b!g&_OGyjo{B@ZaT=sNUYci%&e@F z`wS4?0!s?a6krnuhC^yHsDI6Q0*NTFR6wlyq3B-PPdJ9adCMd-0Slrfp4Z(IMU}Bo z@({DN_s7==2w*&TTxjt1N}Gfagq?6Qr@e?8da5_H=McyD;+vwJ7; z*Ty-H`IMEFi1_b6K`Y5chGs`G3i#o``v`Rh=)ANrYCGP@814b_`>Bk zZiJMS7t{5q&^WDDW;FeZmjN4;zB)}fyox`1sW}u8C^T3KjVcPOHA^!)Jj6~ zwbp!_ceO^x6eBr(1E2Q3Ofvo4(M98EMQenygYp%BWSe-hy*%3j>;6HCa5zU>rDd;F zUPYB{z<~J6%c>j}EdkMohYGBzwT3}^<2vj${UOt|DN@tz;zMV+Ya5SsgNr7OyZRb? z+ivTqkzDUw)EWwA>FZa%Zk+8DM{vz8*TW$~KB1hQGhp~B$+9`|5NoZrY9Zaf%J8?$ zSQ}1xXdf~QzKW`StNKsgOGqy=va;e~VX49~7{uB-w;QAuItB(@2}lIu!G~+cc{CRp|X#$uAOGv^*Uqx_AX|-#dgP}!3fCvXiMo*8LCCyXB(Gw13Wx2$E zMq_v*_GdJPbMc0`hn;gfM-6u5{64tgGJ)HAWlE#+ zj5LbFSWCJxCWu3DnAyrnouAb2r#6w}_uG2a+Vkg2eG>OA^1YQ-OEJn>f6e8X|HEx* z!D=;Es7yZL^BAZ{yl)9V0glG`qxV^4Ff!)XcpEgE>EeKn{X-ytIn)Ibk| zU?g?OXt~osKQmOaB-D?K2VIo~W973TXs}jp2T2XKRp}H=aI;BCVQETTk=*=upq^6f ze+czFaGj!2D<0!{SI@rE!X2b{N)z;;`=vMO^kPFmvD}N|jncZAZg>fR00g#=wWXyp z+jX^34i2C{0Ody{BsNwPp-fuUgR_yM%F73r76!+Xq96u}lY)m4%ZsnFs=AP zi-EGt52VUq(;UYa!>O~+52k82xV;G?<#H;o5yXvrm{T5#?&ljG)Hu#B@ZF2Cw`Zn_ zL=rZZFBf@)>te#%*6r^14YIVjrt^NGq}=0b)~ zH-jcy;`nIda@&>~m++X$i0npyyhG%iWi1^x>BfP=>RR55$_;@*s>B5zZa>$9gDcCDhEI0ALP)d;vuaMpH$_38+WkL9!xefZd7nd$T}D z_16lmFn*a<0QNv?s!#P+&`i^l;VkfKZJCiyds%%m9cwdHpe&gP#44Yvr4ewlGIqb$ z%kDO%LE{$}LA>U>vttEugBwyO0O&dbUb8$X<-=JZZ;_FZz>U;s)~y3cbC2K7I_~IV zRbo~RlIJhcP>`hj)E+9`}VCoXA(&L;&oN`Sq&- zqDuz|nVf0U+x7;A_yaJOYWx0OtH|Uj=wuca8z5(buMGqkQd8hi!dDwP{Sf7bb@ZJE zT}-U8J~Nr=HUR@PnFE%5T%1ZBcBO!L0Vd#mE)?MXBPg6{X-hepmG2U$F~0`BefQ4w z?4&r5|1K27k&yuogo%l1XmIdyMqUk29t)x35VWT!lc2Z5e$JotF6c<4&vG=%QEGyq zx1;kDhu3p)(21Y1b8_DJ%2;8wIVng+76TnlxA3DreF8B6ETotD&0y9Ba{3H@YNO&A8zjo>cptLy1{e~rO*Hqcp6nd zX$ONlv>e$4Ahbh6<`)>3mr%F0-C}0OWuS^p@p=gQw1|j^wKdnh0T=i}5CZ^wLUOQ) zB<8&3Z#5p7HygN~!+=8tFPF;aS@5rxz_J1}&?g6nhd$gmoKFNC_vpbPF2*4U#y+p7 z;s8s3Wd#$x6bmQ?g33UE5t0MvL1zF!cL?p4Di$tSbW{{PO_wXh%{4SNQBhFdKcp@* zF*GuQg9UtZP6DI@at6@h^71dwd&10x999P*`>p9%eqkf0xovwGf5TuE>zYK*Y&t+P zN>#~^C+`xW*DmY6H2P2dP0(vO4JIYTs^4CHS`;uaHa^_m7G?ba56wGnoSnle`|Vj6 zxs!Z2eQj$?k=7^#nSJQ_5fJ!%LlwVn<`p1Apsy*4`{k&JBAQ1JUeXvmpx^sAxlSIO zY})RW(xsPbS-*Of2R?h6HcF%{tRrFQ$b=FBcvFMK4wGTRIvQ$jsN+sgOhk6D3!3Qw zsk}$?8QgAHe8W&`;g#=OE1(9u?3>=;e8?GV^(RFTLFVUgv$CE?DneErr)z}yL0705 z9d!Uvw~+HUt-YUI3vU;V2yi+?a_k= zgHIR3`%xgp+0PNMdc#VTrB&^y<3n@n%8j@G?=eFIGmX@xtnxO$_w)FDi~e+EL?4qi zRq|9wU4HzQy6u$TP5f<&i0E6&ce3sL&KPHItTVNuQ0V_RYTSK-oX#XNU2Ky~5=q!# zA}ZAe2A+ek?dAm)4JI4%EcB)4sH4e!Y40H{6 z6d&+jOXBWF<-Ay)Uo$Cr=t&+&OU2~{zO~d;I(n+YMk>??qN4SXM3D%;_1@1=7VBM&Dl~Q6M(wWcc0mt z{gY0o5op|1(%`b1B+VNcKmMhDU!SsqqhHznrq)c!+;Xv8DdDvh>-~hy=a+Hleikp9 zhVo8hcV5{`#OMJa5xCFoImoVn91q6%UL_7|7!1=GkwX~}9W(Pd(1ZHDVJ-)^Je)Dy zb5#L<22Z8DPs7YB_`hMG3Jy)g9&Et?&%~R*2ls7Cv%&+MDk561D%0I1 z%-3$2rRNErw@n|6lh$lOY1d{I*UWCf9z}QTO17ofEf3>%%pfnUp|In&tNhG3vAW8T zi^a=vtyIyo%@dRiPk9((D@#RcVPOLRojz40H+auyw{f#rRpyp=t@{pAYqn8AZ1UQKqig+S-~b)4~M%sJpe54&E8k$SHU*^1=bT@Sh4< z-cV$HX5d6me1*ADR?M80hKSAbSu7uvv+Z6Hxdo12ay5WJ1;FRPDtk`Q_nT-YD-v4heX(0rL%j%+5GL zvX%|&1z2eiUd6{;P3=Zr^tgr}ue80tRLraTm#S57b5lo$FU=5kX5}T7?Y-&fe|A_d zSoJ^EIw(F3+nirnCBA#(HFY$Tk&U{|A0&@GbX%_6NUW;5NxA^)<;sNq*=3j=!#fe2 zP-un*ucwy#QxA&}<^ebW!OaJ0g{P8}x{FXeux!K*-RSn)Q*lO9>?AKot z_J3t%1>X}4OE(pfkKkLO*~HiVMIBATKSz}_%}gr~PAti@G_qoOn*C=(@AL#uRoU-E z>rjcg1pbHaWoOs*zoAZ9*#8vNfZVVRbP^PshQkcG!nfp71Zb{b^K|MxMYG!`C(oht z8<8nOM(Q9WAn5ClgYO>7@T3$@UI=V7u>8QB2+iN778WTMfr)j^&B>XWr`^IAfM;kp zXMtE9ipT`G?WDl4n2n=+8u2q;n23Uc)b75S*GKEaO1;)q71pURTOpxWkrQ8D;_wFJ zvHZDyhA~aT3%qTxMMaF z?BW1%)z#i!4z4jcPa)*EwJq2YUAumCd<>*~*kz08=1odb(lam||2n=)c8ob zf<6nq+;Bt(D-y|vOW+S7U0VSxKH?ayi@uM6jxPT2;jem8I9CkN1EKLJfUMvEhGaPd zPheXi;-Cb=5}clZcc!VKLBy)To3NRX+xG3-?@Hc$*mr-SMgn}H-G6v0(Z(BWDa8k| z{>P?Dn-;rs9)h^>qwJDcf5V?T7dACCi14g?4Ik#mry3gOU|@mTV@X}!JEw5(ieuLW z;6ASHfVTmF+VKPsb@e>v!|b{Z+Gmn=9fI`WnmY&Qb6qKPzk031dEh5KEHYzLQ`+k4 zPS0r#AZ9^>G+LyJX|2FLZZ_4^A6m8h(u-{vN~(2_`AvJsW!5fG3*m0M3*zW`(jtMf-VlQP&~hP6~w!07W0^b!=OODp6EV1_{Ych}Tab zIl#3!W&t?nU&u51XJ^P%S8x|W>45|a43ey@tu-obSw^iY5X2^svFe_1s(~vE@}&t9 zw@n18srA^+iBNEGIuQM}kMiI?0l(YHiDTY2fSo{vgS&?A$lbNl9eS2M5}HBu`1Q*f z3^}*bmTH4InElH}XFGg8um(q!}6fn!Wi>*ghBnn$bH*H`M76bcO(COfb zF+(3F#2OP>H!5vb5!}lOVWirIt}a0;X;5k70i~RV{1O%uFq}cYtO|lj$T8H&z9@vMCGLt_^OZKV@*v_ z^2!ZogG&XFoCrf=928b#GJ1-*A{?Zk54mZJ1K(0dCnzlJEwhOj&e6#U{9NuRa6f@2 zaYC389~A`-p%4BwXSCCIu=5>Z*%8wzyaIX(pn{zMAl-vGt?7<$4R^xw@-he>(0D^KyAW{+b*o0APx=Yy0Y+aDT8LW*fOHX^CCtnxWV>9$NOZ`bDW8>q-!4C2 z^eJv0KX}qW9z{h|<={niJ-BlHx~z;0KQ!O@_&k!4fn82AfE^_z;Uv}Z}zN!qT~qw)uwyq@9rnuh@v8{QMC$qA}^t# znNQV_JJ7SS#ee!Fi8I6RN5q1{33gxL&%)g4gLD7~XbcSv51`)$#BY6iGc`9@(73q| z*g{iIPEVnt`Lh2*c!x7W@)TvcGkya$cJuR1t*t&l%sigDI8V*Zbpwm;d?LI)w^ZPA zEoD5=F*JBC%n<28TGVo)e;^%6V7g#U%!A1kjfzN-VGcmwX zNN)`JB3MM>qNa=pY`TN_mye&HhOdVs%svZP9Wb*7 zVfz9LRA5eqHlpB@b2q=Nj0F00krlzh4T=`+6-=;*4)*kvy`IAW>mw!_A;MM33L8Oi zwt>s0*M*$P`ih3@O|FFiv>hMFQd1Jjpi%3 z6qsm+ut>lhk&~0tolJ!Ka~eAb2XyWkfzuSekV*S04d{d@C+!ASP)Ac$B`|7rAKa_v z78W2BU}S(l4n#cY0qP|hqys$wcbxI&5|~kt5Yn6&asmBg&@{`ofC&js!|IeRxU?Xd zomU8Np~2e`@=^eJ70W%qho|KsHca%m^nf(Gi~@4AIMFZyQ@P~{Q=8v($0SU|J$(+1 z9<5zn6Ss!#3sL`jXdKGslxh=*qtIVO)?6(;Z0G@E~ ztk0S4@9nwEpi+K=&;f=5EaRm4e{(!$Y$BRKkSG9K?h4L9cq-v81s^|23SVn_wQ7-3 zArd4_KtxxB+wskt!r)+dLIY2DDI&we(KYVDphbrXL@pXa#Hai(TuyW?Y>n*t!B}r^ z^y{E8(BA$HEi?Rf9g^Qy*|A{3!DIl86SUAPi|lGuSigXCYu#O!qpkYh-hAy2A2GOV zDG?6FK4oWygltcV8Az&OgIEhLfd~lV!DWMRJb`ahSs5?feK03QxFv&ve^O^aEund3cLjj268ZD|tyGjjaGXK6tzQ{=--Cic}#6(8zB`U$BS{FI7t0 z4Q*NdsYcu6oN@t0?S(dKaIlO{!I~bb&pzw@P}SZD3{s3I#NKc#KU9`t>*?)<>^q!h zE8%J2;0XTsG5avB3?$QA{Xbr=S9iY4oti5ISx+WbX$K~{<~KP}4yhE5~bOL#y^sipywcvS~vQiX91 zokNX$cmWP_T>3`s_~0E2RiWb z@3rIOXTEXKmg0M*S@zD~>?F=zrIPFb_!GIDM8@k2LSVlE&UaCyO^&P;QSCSqJErf_1#9=Y^g z6ifF_(N`5T;hIHH?+NY_3BUHuPbw#oIg9b%#S%3d3ZbM;*?gL;g7oKF>e=$#t!iPT zv}yY!56id%Vb*?oQuW&FQ&rcA%NQ3d9%>bMeeySa#eRx4r67*GyN>!Xg%gv(N;m)V z#JBUv5+~%2Dob|OUT(Wt6K9)UJ*&MGLj0PP@v+=*+fI-Ao~nioFXzq{$f$4W8^3U( zw6oz-`dsIK>&M>nW%ql;u6f``Sl(&3)1Mt<|sKrj(bHGW1yC<-yhmF~<|T3TX$vs+~14aMEF# zdc6y~rt$C4HShbBIw#5aI%D)6&ibSCJL$CvDUlJe;k!Jjn|?Lys&8l$%%yz(k>~e!X04Rzu9IuG z%kycBRb1IW)*5+)DqqG}dDz$b;}1pT)x>93gWevdtW{zCa+ODlk4l%-bx?=Wx=6Z* zf0ff8CrqVV9iXe1MsLxa_I~{Hx+r6n08`)?1)~6YCgXu4qW=N*Ws-2r?}DAm(Yg%e zx5Vy*s;bT~BXA`?2}Xr^v61$F>wR)_K|StBPRmqO5v>%-EgzsDV26^rO(ya5n^QJ%d)XBcZ|n2(3(xJzV}o9dx4LcN z9>uMx@f1|L$8XN&c3o^<=A7eFPc&1~q3%dHe6_#>IQBG+0Z28UnnE;ZYm zg4pt@cZwX7ZFhdDsE+jyJ?Ko~ykPeE3yY=1rGff;I**?a_6fr54>kyrb(L@kOnDr0 zvXcRuA9(p(&f$bz;1^LIv^WbWrEng|ba}L0-Jrx-UG%FeUXMRdz{)RWF4PYjTiQ3{ zL2g_%_^6T%Xe(RzU(=g0}-4KxM$a?R1-Xc9Sk-oXxzgcIQ)OGBR zaK|~aoPo! zj{xpH&Ejo|#_KMYnTCZ&BsYYGB=5hT{S>QYI2T@sclTnh=zjgKH1pfKYPqVfbSqWSy>ez{(0x1ivr9hu zFU-#voh(cJZ#KK@qXAfwIyf@^Fg27Xz%K^J=hoohk9~Gktd2h}cOU#bXSwE5ZE7nb zC*i(kH)Le=GojL=zRznT)A-v2e$a*larv^CgmqJWUTAwa8Hf4W%_6dpyCQGjz6JU2 z*LDX?t-*`=x7^3yy_k)SyRC`|n1e>WI;Q(D#cOG5(xE4Bgkg9zyDpUE!Un|z*)YaC zDd|*~ylxP~T<<@4n(B|4Pj9;3d?&jsRd-I{wZ9rsQ+L1r*+mH5-)87ByrL4@PR6B*L^VL%E-fjOj{6f);>~o0*o$@j# zq3aQUUDA#^tO1##A0h1i0{RzsZxQgn!=a~BR8%_Sm;LbvomM8xW?V~1hr5?t)S!L@ zw(^j2DJ~}D4FQiwRWc$diO{qsSRy?uD^I~90?tIyRhF%g>?M_x`k`if;e&%+j1 zb%&(wNi)ylZQ~!I9B2L|OKB`FiuGJJJ4bGTV!{>yU9OuQSU+CKQ@T;DbnKPBe!odc z^gP(m6|Is-kjYgBK$vm2w#URcaF|p!p5*PFI`hn!sMs5HrYO>t`qD=oZ%mjmO`I`d z4qJkoAj zewzpP)iRR`bA%rXJzz5JTs}zN7J}*scs5`F2AjwcOxzI%Y?%B(TBXRcWU}@`2%Ck0 z!8eD1vF_O82PzBJw*+MHWM5O%(CLOjb>f@@ zmTqA;W&r`t4eK8mWXl^&WOa*rDhb&f8_)NuX(|;SfHPvuzPtZ$*J+x~^6vgWtjLK5PoA2VLF@&qomhkqh%!wC{HXw|l- z`&m*!yEGhg{=9{1vqqe*er0Er?-_CNJ%i>lQhw9PDf#lx=MkcPZ@lV{E#BuCZzKQn1t-=gA`JAx@*x`ozr8)eX4TcW)TX8>Go84FYbLDzB$0pF zl#O)$L2D|| z!2+WdAnKGr^QfKOh5RAG2O!zSJcHn|n7#cGqJpj{zRoEbiVDU`@i9~CSxHTQc)@`_ zk#U|MloBSTthAh*mM416?#9VicM*aE8J8g#%RcAzrVBhxo}LbsN)N8oQ_nMZCg8+4 zKjpT+(Rma{_Q4`V-}y#${ARsOIo;u+m2X$Cwd8xN*^ePO4SQ?^6m)tNk*&lvt2)2B z2Ck_pK7NQHSL0i#baa$^$Q3Mc@@~n9_ubLr=z4dXKi}@N(TTVI%k@UVV`HQ3DgqY; zJ#X$@T|J{dd=$yu_u7x8NUio>o6QX6Pi}*0!kJbbN4)!FWs411WS^^qrCcs*(wI~^ zPII}gkhWmTMidWklubT1#ugWbp#a+BZoo;AeB*S6`wA#Ka7f+T+5(!=BlRJCkWt*z zQ6$*GGxLcBm-ZqR_*t;cgD3R`%Y7k!eliA0sCdXkL;6L3Bm(J4M5u(9hDIO6BsW`V zCCLJaC4`rO0gIQ0=*v?3cPN|P#{V{DGpNgZE`)o;@rQv~?fzvu$=iLj*svYl-P;@J z?{A!Yv2dUdSOpMNVE9{7T-*iyF6!V&D}hNJ2xjN`HYB*5eC$rnIy~K(m7m0iqztQ;C(%C3WAe8yh>0=e>z(XTkwNaAv#^3tjI= z;%npwQWTeN3~RVtvPXyUC0t(cv_Y79RF%sJcE`|b1NM;1czAaRe8K016o7b-Obd_p z-3JCaa;Nl%FAolpqXmRg*-Cb7Gm?16n069*?L8Q!HL?2SEt;R%hh$oQ|F z@89FBJOW4%o$v7sEG+vwJ1EL#kfeb%ceuMz>J`P$rI&@*N-qyup5HtiSQH7KyV#~B_}bHxQKbj=l@CByUWyaqjST!<*~~f z(F(}9x?Y^0!7T}|$~v1~$=cwI3{zKEp(_gN>Nx)Buhig31_a87%7dWL1tDsB8Br*N zoK2u&qKh85d_<(A?M+Psr6dcBDk%lNgzpgWrO* zAYoXffg$rH&8hyNf5|Dwt;18hx5n}tzg$y;8~%pgTtIi4WkvsXBC!NiZiE*Xq|8vs zuh7sG{pl0TWU^~VK^lX++JzQwu;jylMqt`@!t5b$6R^NNFmnd6txXKp|5tIOdY9q+ z)yEH00q|^t%EyZav;r^e_1js|ysz~@5(KC>NP>u#K?;hEm6g%M$V(U)2zMsLP>^Uz zNl0*`E5tuW%UHTio_7y3pF48iUp{%)7sTwK?W{A)Ia!TACX z3n!;j_!;XJ2HD_l{zdOz07Q|J65A=_YiO2~_RP~aE?kT9OG+YSH*O~KaB=;{H9p9-z{W5GDlGpU61cz8aJ{=A-9MU_m|7)&1rr-qsl8?+SZ81y0$dUc zAWux+%2V}X%cexKvw>>|Q4z50!l-7&@x9AisN=@}QMVy&YRX6uNJ~v!0PTyle9yI! zEQyA{fnd8r1RfHA;eM>b-GnC=po&GIwU@!*%&}#R>tT(WM+Muzy2>8O2R;_{digNJ zh=Ke$y>_+ZJs{@4FZ4p;afiP8n;14t?2yxk^{3A0X(@~`V18!5+?VX7%>F11x6n(8B!bkv#tH z5uD$I(MFkZ|3tIYJ^20YPziVAb=@W+dWW37{&ct{Es|W%EQFFm>F0?MrNEzPo4oqY zZ(qUo1Du^v(a{C@AJOPoZr#d<+YnG1+(3yb1Wh`| zhK3VW4%f;uVg7I-0H$rUn_J+boq5X-FIVTp*j?g(2~+=H?2*4ZS$i(hRKPOueDP%a zeial)_HUKqOxCi}>Y(MB`zyZSUt@b`9yU;5W&4^-@v5=6g<09%K$KBN3@70~DRYd0H4mQ1&P?>i9MSTV`s^&l0?(*2jZp!aX@g#J0b^V!X7<}0{@qAl0JDJ4sY z-sKg$9;2KQV@16-ow#(xr|C)ja&&~;_W&cA+rx=to;|pTjn(1dCG=@cjN&g)6ArK~ zU3#fzC`fjzbOT@@JPk0!wgnrzP97Wsu+SQEE3q&!fvJGx1rEYr$U}%PZsL&w*i!m3 z=bJ~FN8|F@_7v?4TCEzfvf&S1{X3uDaV|EFtuS**XMgBDDleW>F}+}az*4QDur}i>E^Oab@(SlZtmzl)ZtwKaq2b~^dQAK= z(rWYtaqY?yw+oK>^o?TDIno$mVp_^Qe#P%KI;%?8Tn&W(!Zm857t7y9|LEB>0){Hr zvuN2n_|K&GU_JuV#jg(8)p$kj-3Zkm> zg+aTdnht=X{&t*!|Hi}&u7(@>pRzrl2aP2wIWgLh;@oyCziv~E&16EnbT4u=@$JI1 z(WP|T&J)M+k@0n_4C~z7)T%qvO|s)kShMF7Vy}0(y-3!tEogQx48M-P>JSyW-g(BI z^5F*J&|0QK?}79MmP{Hh>4XqBNhUQKf=ToV-brX75sg) zv>q!kS^EKg#a5cUf&zf}Jo;U-t|cyRXwcLGy9P;l2vAA?ua!97zePk%Hqw8PJ5?$+ zeEy(C{@%=GpMnU2)Aq6m)|j@-_+pQhUsm<9i%*T2jxYh7N-eKUD?m;X)5-6^9< zhi(JA3mjvL+iVXyQARrObn4dSs|oqQ~bEgW%dKC4KjVj12@-4i%(DXGvO@yY zlmv(0%fgeHOyo;;M=$sB4=5@v!xOWU{9?w6X4b7gB;N?BHz4|;`laL6*U!yM=rqy9 z!eK!f>z7H;SZ>5t*k6QEzv1P zS}S!9qIxWJ{{t?J24UK zQ__1brHNfpv4VSlFz;eKIkZ^1Tq!a=r-gdiGW~^yC;h7&U$R4vIPHXy!=t0;AA*MZ zl$fe+J`+>$x}C-*rJYt4kw4^F@^X70-(@E}cf71MtQbBlhPuhj?4^M#Fp(j|7lh+F zUG+GPq%w+3OTi%Lc5PD{$iPkXCBpXS;pG4E>6m9D1de(i4x zRM5d59nHYKzkW8x`@!Vdbl7#_15M_5ofXn04y={_V_^Z;L;mw49PQ?^p#htmLOOg? z#awQepXArCQ&7}^8x7oHkk=9i$JUR9=TWfC`_bLEUZNV4Mna;B@6=af^~Q*$%UTl9 zeXY?HTzmG*mSX&k&CEavEf4MfJGmS44l`|uhGr=?sv}aG&eR{|s>`diFD_G_Y?e70 zgxtzhjMu_2118p}!-&3__O^&xI*&4o(B~#yUV_Tld=zZcNM0B#F8cz|6!$){5UVirF))>`_ra6O=l_Zy2acb zkX0S_9N;p)y*`A)Nh7KG=wViN_Rp>uy7wBzugg4O!l>}2QV8;NAp03=;vpf;XS6@M zo-)$F|JgfPFwJbeinYl>b6KA5UUtfHY|Nsv4$+~l5z*ryY3UE>6;*e+#sbvyEj5~J zk%(73L4t<<0B+NPHu%{_MpPkC^Mg>TuA@Un;8vPONjMUci0C~&BSmT3hQdqu=Uwat zrDo}$c>>P?fOxZcz^sqt&{)hDRs*-w^-`c8%0_d&04EHf1jB8_4J!emX8-jGfb~ER zX{)%Ih60lfqrwq5R2uT2yGLi|v@kOs&pTHx|0EUUnH1!2mE}r7jkVont7RI&^*To# zi{vI^bQh73cn75f5aaa0C51ZH-fVRqRpq_A;5H$YFRQ4~dz)IJ3x+eWu@vN>AZ3VX zepK~8nNwoksx98z`NjHU=;kGrfjQSQm$fHH{H~3?W|4b}tWL;V@sFMkyuJ#Gjp*2Wj;2S#3jW^ z!ptY$yoZzXvPjeL3GM)HR8&-m&_cb}C3q!+wFM-ZUf6l7RN5p{=I>81@v3) zSCTz`RiP^)3fIBn6k$V%^u$l`Q76=TAMul!zVGam#q&|{pi@&-6?8inV9HFH-xI$0 zwF?$wPb}`3YPevdym;tHBC*QklwB}aXm4*H%%gVa{75M*L{FdgYn>Fgr6*Ag`k5;r z3H?UGf!B6z7?hf(e(24qCtgEB8jwB0AxSU*?+zU2#QyxsirU>v41)0YyuV7*)DQnCDEh)R{YXeirX)?w?v!Zt&5eyo zEv^gS!SlS6O9&>vIDR`kRKr0jKnXqrMBek~<3%q*5wAY!bl+A2chftVijV=zZP%uX z{rnl)9&T^!vi5)#65JgiXm^w_28DnD7yfn3Np1KiM)5ds&im0GaRLJtBrEuRRfnEs zKqD@cM#IF#?*c4@ZE$DmvC|>BN8`gERtGa=(>1Vi!+07X;!hP7!(U1X!%)8*LWr={ z^tgPdeUJ@b zGJM5|X%b4HvOEp54=68p5D{^Qt*JTAsk~~wp17J?H0V-#L`ctZ^@x6z4u5E?`0xzs z%%N=^8pa_|N#<2U{2z6&QAaGGd@YhJ+-E&4DA*!h7>ObW8w14G|#*6Q(CV{J4*! zIGZ~G3K;Q`kQi|}a1!os9sh#E1oXv&+6qHS2$@xbas!(uPdBioDpyrQRS;wg z!H5YD^Ru%-6eN*wkxrB#S@>nD9rtfLexOo=kabvUGMH>)V<*702_EYab6an0G`M~! z@NZOol1;Hk2wvF49eVlj?&<-t6kZax8{?!j_uwufeXokNfM|jTfB)jt3Efrhm~8lB z5J-h*A|qoo?P-!xS2Uz@p=_Cyj0`px$_~Zw_Irc)?}}9({!oOKDcj={I?|KEw>~~G zpFZhaQFFhK#DRm9VDwZ$p&z(=h^GVnN+A*wwESJ2SzbQg<%S1S)ZUAZ~k;4*PQ_zTn-73JNedG&nMni6HcJ?-H z96xV)Blr6#wVg;vw1q`Q%w9B@qr|jZG`U+n}6r|JytCFo!93;7tjtxC0#6m^NxCXcG0M@Ug z4m0ELDmJq=cQkca*#tT6OK-h7dwX%iGG>|V*H8eDa?bpRFG@wFYA2s8r>%q>ohbQw z1>PxD>R!8JJB@Q^B>OSpl|>{GxLc7-g|)1=z6ynUPA*=5uX5X~%V?`iKusWU@y__< z{lt#YrMszu*-WpM{7$DudK7Y~R0%(~o2*UGZ9bVXL=n;ShC8H~{Ac^g>;4^1A_mK0 zvx5-t&`V>{t4tic>6?_F@kfiSG}{WTKTxI3lgT`)EUutrFZx0rR$#e-JGsB-*oFG%dH_6kUQEcdTe(kd&^doH^1=9$F$ zO~iBWc>3_o6h`ljQP5%P$chd5S@M*+78vhm)COt>o&-sxahr^|6pi&wwU#Ooix*gm zHrljMc7IoA*>`xPeN66&-%AvCHMqk!Ioa-RxAPm@p&#!0#57+fn^PBpK15?YR#QEs z;C{V0fZX*QyJ+rhw|SqXPaa9h!Z)A8s_16#ms%xvraLD}+rvJ1I7D78tcsK^>0{o) zWu)aaI4wC#%@K6ozQy3x_^kKEKtsjUr;%E@%?U{@Q?i>#-w?mK={?59S9RW8+uou^ z{iI{(C&BqU!KUQICv25HMjL~&(FqQ@2dCOv7W%35_9CjPQa9Dp{09z=7s~=BPS%_@ zyjycOHz_pvXC55Y8aFssm_FZ{S2mgtkiw(5sOma@eQ$Rx@>3doyx%`WNK=k~Or@9(9W!iwZp6t)IDaxR=_aiT++*SW=7 za0>=#W+~rM;C_@|>>t?-sJQ&}M=de0hVpaNcB8`P<{r|gF~%o8uDvBohJ!(;CkN|8 z3=L(p^hOh&nxQ$J97b2F(k@^7`Qa{+Skl?oDdR()h*K-e&C!pyw6s!)pt2a|V%xv_@%d&?I{NAnd5%u>$s5PV&cAjm{aNm`8OGLx38r`jBw;a2bapx@dv7?rKS)cs%Ld;|$uaxrn z$ro)*3`QiJX;!}2kW&aPHkVqEm8XiN|st~Z)%cDp8;xS9w3e5Z;!q~=E?7E&G@ zD2>g3bn7QiMtpa($isqW=aH?m1G#LZQZTaXpAit!GdEM&AR6 z3tdh>49*DgTnlvmoDTKTB8A}{EnaM5;q$@O=M^yqJajv8Qw~9_c<#83ITO)DYLu15 zFCQuH7=Cy)LkT^EU+?qKbBUl8mRDCV2L>8Pq_o-?D8j|YoCDY$E{(@GM-}o-S>@`0kX>qdayetu?{=Y)Cxx}9;-ZVC$cJpXf zVy@F6lJgK(+loIew}&SneW1lqc{-$?WnXdl_GXRos$6FL92b$uW5f=iI9hthH8%Xg zcR$vRYW}0zH*r6_?#b}3H@OkdQ^uVN3UuB%JBcB#Hj$)lp?mf)lydnFKLdv#4>kwa zDxu)9;+<^jYCbmJ zBbl7Kpp}N^egpaUD*4Q1b$=aHyHV?|D(2 zP_bCPg4Q_QkVWeE7th$(zAOlQun#+(5R^qNG-|%|{fpb^HGiEb^-^Wys$Y!EtBw1s zmd7PsZg11qoRlrxI>@~nzUp6kiFK)LwzYLZGsu91gmkf1Wzuhz=h}`QQO+Hd0VLQO zJ*f=df5)Qz<21|c(<^^Ft+?f+@+JcF9hwmptV5R{^#AP^8mnzSP|bfkBJND+`Aa3Dx;0-;4g1jT^#PB2vI zHFQD|5fG^fy%{>v2?RpO%en8oc{6wBe!u(Mp4n^9n%QOje{0X|1$(gEF?9#I6`yav zB?oI_Z3(kHrkB|swM3jgOIs}dGintiqYs#q<>T>+SkUZ8K{6FAc;uuy+t6!6N?Mn# z1Aaf)7`>FcNx`1S+r7iw%fTzijo)A9wZVTy2bYfBJ_$B|!=G=Tc!?gh{mc#W%>E8E z!x2|)<(uj{?6ixcxl@M0#l6zOVB`A|b+5niqhL!xS(owKgty6?@T z*>EuVNCo@(>VPRJfgS98eZ#f!?%_HgM%lBday=SwrP_&Y+qRlhmQg;n_b%qJUbSt8Qx3k^hNZ*bVr z2qe}=J!YPZkx$v;3Y8h{zcebUqM%!`6Qr4=KPEMh+cM+dIRu*N%Z#-Oa2jvs@eR%K z4%PDjl}G{BtD(8t=`>YkdN$En*)Zk>^qwN0WK?n#r#Y)@sq+$NV6R+NM;5jKdxgs6 z9p#3hfCmfZbWxhg-xtomb;&j=8?TtCjG_N|$UhdNJ;7Ct@WB!oG+YsPrt>&RfOzW}}a%G1Ti94vy66sPM!CSk12gl|EJeq(?^3TcIpUnv#t()_= z_WUoK0x0V?mHR84|0I16#FI=U*Adp^9)_f+P)oc~QuX-~9K~j!m~PYlje%=Tk~`oy zHPJ(tijQ*OK8gLKwQt;&`CDrr7y*pEdr2U^_pxR9A!Dk(kSX>WyeNyFtx@ulcDb`> z{gL=W$4bc2v9gbfFmuTphGXj1IV#K*3U@ZM!MQ@txjqaQ{<6mr>YPm~QrC7cPwPrI zUi5}~-CKWXVQeAy;jPQP2&K=*=s5<*@-s$`<=bhAi5z6|GK5xgp{F(IRB~>IP;OSUY?|kC`DrMj&ZEfNx zT*2qRxu|$UhtH93pB9*$bMWx|Bz=dtuuly`t#La-N3@-oa(;u!;5)tTx}$t_#( zJ_2$gi$B0Sa@{U42Pb=c`VCRwq-{i;cMN(C=)!}&w7RlV>CZ&gS#NEONh`ClnvVc8 zg2_kJ38KBM-1pZ#J^#Skgbn5O{ZRy};U;{{S|*!%?Fp=K;9rqLgFGD~mj!xdDwrA( zStOZB$BRr) zk!}}GnMCTtVuU3ffLb+!%`-rQ;6Nn_Wo=oN!zEi`ra^}6d~H3Ge{ChYeWZ**mhew; z2KaGe7-DYW+0H;)n=23;y<*bWK=uM-$op1+rRp>zrfiidAkaa4+=?Mb0;L~1-%=I& zrai_XN!ZWf1$(gCsjD!-NYg!MgZoT#2AOK6zOyycU|U4jO--PEw)F?}P2H>*=> z2RP`s47w=e@0-POkXC-H00Hm=g%-OS_@(rW{t4cVx81@r%D3;H>o%ccVxz(h!d^b`f{Z(BH{^*P39@8V}<{CUmJe z2t+DQ$(bVh;u!s$Rq$^gu?~L`z!GHGSP1K{6K`hf$;wxEuame5U6-fo4}mrOa)R{y z12#FlnN=<_(J#cvq-{u<`F7dc-SDM9TP}dTYJ~XpM~}C%_a{G@W~{a`$%T-w1FU6K zLmB3MmTL)Nk5Ns*>*eU?n4i3Z2n1po5 z+ey5k*ooc9U03RB3O-N^Z;4Ue7(ph`+gS(O1pP9bpAdV3E7_|JeMb=L49~CCSD&LK zIE;gbLrO-ZpC&!32TlNf~rbwW{5s2i+W&m1qZ*LDD5#!OgAHVZcJv zlyC}a+~*!k&^gM!s=X?Xp*9|O)JYH8VP!njs41T{kCkS=yTKk5VWY*tHA^rGl>HeC z{WF@EpF!TTdBw~>;*ntyt){`B$1Y}Y!=p3}Ay6RTg`XRf-9X`31-LO$)Jo*x1ax(_ z0&2mmJEw{ss*|r;7i-|blMR|&h0hzaFd=AYS0HbP1ZR`iLCFJQBz5^q@KNT8Vpp!B zMQzDn_odDDL*L~N1nPY*(ubzLlc$9ETvj_7PT5h^VzTD^Krg6A8y0@zSHKtScol>+ zK`4(7+tly6^P%`hl(M?Dg@TIZCrZ)grZu0mAUr-zWmR}(u;{8) z8eP6E*b%6M#lgF2Md)JIlH<9Gla`ZadnD@o>gcb_7nT=w-z!meN^YRIa)!s#d))Y6 z9&2$KTd^@t7Rmo6gc{Px&j`ci?oi;lSd&_}aQ$)2DJgKu9j3IoJ6`p6r!PM%R+kTk zVgDFDKpF{X{C>`i6`eZ}YEUH%k)A8|$h|Xl!PN+R^)05H3ArT%EY!X#!VJ-83Gt*G zI9&vNXgA0ZI&2hfI+!qLi?AfnSQKXlXtJ8r()tPJz71U!Ae7!PdS zyO6HlOTTup2HH0Z6VeZ#&K(V#_0xekvNj9#gQE3C>Y7{$o}A-~ld4oMk|~y%DIb;r zOL)$(qc-CEIy2I_r{Q@D8=^cvub@lp6co_RAx1Vuwz@ofprR~xAIL4v@R8wgw_~lX zF--FQ?xfJXjtFkG&}Uh4sflkB*GBXCJ*ot~gmoBYZx^);cO?cxa>A*Q&&`&$IH3yKP#yuG4c@5=3ZdMmY-CT3-J zx_y88D_ltf2sm(vFux#`ZKB(B5~fQ+R#>_=tJZ(dX|A}7K5_Vx=s7$7Nw<}GUO(M; z(36B20R%ZGP^*Z$?YGW}M-G{qlf@Y8Igc;Dwt|lXwpUOOf2?`S82aXTu#NM5b5sjZ z=Q-}r;Ud#T$@36O<{%$|Lqx+n0TZ!zn1Yf+M_k|f)@9$vycn*zI(p5TImM#Q^{)*7 zjk2K-ku3dCIVo6;<@EZuhd18<&c#enN;9)f%zdA)?vRvVJK`LZ%?{)d$*A&Hj;zNw zrFJ8ChmCdx;2UKK(yybO+~B$#R$MJ1i?*i{d1%Fq!4|n-PZxSzB)uNzF;;3s#Czp< z)JUSo3)IzjGG`jV!qeAx{dU&fW2=%0gXI@C94^4$*Qn~V?0fmN{l76}RFfT94GWaz zTAePITBCFd!Er42VG65pJ&&ubnAoxQ+hYQ9;pm>zs}26dS)SXRKic@y#y=jEK;hTs zV0aXLy0`q3PuVrLT>IxM(N%Ed|6^C-qD}_hYbI%_GtuZ9jcnN=00x=8IC-9tJBo<% zu;kFA>xJyL`b{kEd82J_-F^R(DN5aB0cVyVJGzNN6#chi)FU@kUM(tFw$-CfLO?N7Spzh?O( zRm2M1*8atD;*C+ojuAE}GHhVVJVyOE6j2+pfJxQmL}lc}L!*8g<`d=a=|VBBT7}hz zORgEEZ4|c6WFdi2(Yzic-AbxH%khz zmA%$HsBj%o{WVxi03Y+&g?HcPe04Q6$_~FfY8-4AK=ny1C3#4)0#rTq+h_}Xh&6M% z8u>}cDPql&OA*Z(lL+Lh-}zCDEETh3DJW01TMv>e%0Cp?G!kf6FhjNa6pu0@|5~j& z_@utC%FiO2b$M5omesO040ys7j^J_UQkUQwc>d&NSdBmu8ig%zzaghU=52??r}KGq zAlxv_cT8%(vCqOb=A4RvTJZy?{ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/diagrams/rt-readback-fanin.png b/docs/diagrams/rt-readback-fanin.png new file mode 100644 index 0000000000000000000000000000000000000000..e05530bbd995a766dd889d8548d8a7abe163ebaa GIT binary patch literal 62372 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%0DYm$dFxNaSNRkz#@9sy4T?SN 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 ?|bh+|F+I_Z>jL2=vjFeyD}83UewPD4!rE! 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%0AUQbw4R_{O8G@FTn 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.7" dependencies = [ - "systemrdl-compiler ~= 1.31", + "systemrdl-compiler ~= 1.32", "Jinja2 >= 2.11", ] diff --git a/src/peakrdl_regblock/addr_decode.py b/src/peakrdl_regblock/addr_decode.py index 7617a44..7f79613 100644 --- a/src/peakrdl_regblock/addr_decode.py +++ b/src/peakrdl_regblock/addr_decode.py @@ -133,8 +133,9 @@ class DecodeLogicGenerator(RDLForLoopGenerator): self._array_stride_stack = [] # type: List[int] def _add_addressablenode_decoding_flags(self, node: 'AddressableNode') -> None: - addr_str = self._get_address_str(node) - addr_decoding_str = f"cpuif_req_masked & (cpuif_addr >= {addr_str}) & (cpuif_addr <= {addr_str} + {SVInt(node.size - 1, self.addr_decode.exp.ds.addr_width)})" + addr_lo = self._get_address_str(node) + addr_hi = f"{addr_lo} + {SVInt(node.size - 1, self.addr_decode.exp.ds.addr_width)}" + addr_decoding_str = f"cpuif_req_masked & (cpuif_addr >= {addr_lo}) & (cpuif_addr <= {addr_hi})" rhs = addr_decoding_str rhs_valid_addr = addr_decoding_str if isinstance(node, MemNode): diff --git a/src/peakrdl_regblock/exporter.py b/src/peakrdl_regblock/exporter.py index ba4d2d6..c6e068e 100644 --- a/src/peakrdl_regblock/exporter.py +++ b/src/peakrdl_regblock/exporter.py @@ -165,12 +165,6 @@ class RegblockExporter: # Validate that there are no unsupported constructs DesignValidator(self).do_validate() - # Compute readback implementation early. - # Readback has the capability to disable retiming if the fanin is tiny. - # This affects the rest of the design's implementation, and must be known - # before any other templates are rendered - readback_implementation = self.readback.get_implementation() - # Build Jinja template context context = { "cpuif": self.cpuif, @@ -184,7 +178,7 @@ class RegblockExporter: "default_resetsignal_name": self.dereferencer.default_resetsignal_name, "address_decode": self.address_decode, "field_logic": self.field_logic, - "readback_implementation": readback_implementation, + "readback_implementation": self.readback.get_implementation(), "ext_write_acks": ext_write_acks, "ext_read_acks": ext_read_acks, "parity": parity, @@ -319,6 +313,10 @@ class DesignState: ) self.cpuif_data_width = 32 + # Also, to avoid silly edge cases, disable read fanin retiming since + # it has little benefit anyways + self.retime_read_fanin = False + #------------------------ # Min address width encloses the total size AND at least 1 useful address bit self.addr_width = max(clog2(self.top_node.size), clog2(self.cpuif_data_width//8) + 1) @@ -328,6 +326,15 @@ class DesignState: msg.fatal(f"User-specified address width shall be greater than or equal to {self.addr_width}.") self.addr_width = user_addr_width + if self.retime_read_fanin: + # Check if address width is sufficient to even bother with read fanin retiming + data_width_bytes = self.cpuif_data_width // 8 + unused_low_addr_bits = clog2(data_width_bytes) + relevant_addr_width = self.addr_width - unused_low_addr_bits + if relevant_addr_width < 2: + # Unable to partition the address space. Disable retiming + self.retime_read_fanin = False + @property def min_read_latency(self) -> int: n = 0 diff --git a/src/peakrdl_regblock/module_tmpl.sv b/src/peakrdl_regblock/module_tmpl.sv index 1c15395..5ec9666 100644 --- a/src/peakrdl_regblock/module_tmpl.sv +++ b/src/peakrdl_regblock/module_tmpl.sv @@ -30,24 +30,7 @@ module {{ds.module_name}} logic cpuif_req_masked; {%- if ds.has_external_addressable %} - logic external_req; logic external_pending; - logic external_wr_ack; - logic external_rd_ack; - always_ff {{get_always_ff_event(cpuif.reset)}} begin - if({{get_resetsignal(cpuif.reset)}}) begin - external_pending <= '0; - end else begin - if(external_req & ~external_wr_ack & ~external_rd_ack) external_pending <= '1; - else if(external_wr_ack | external_rd_ack) external_pending <= '0; - `ifndef SYNTHESIS - assert_bad_ext_wr_ack: assert(!external_wr_ack || (external_pending | external_req)) - else $error("An external wr_ack strobe was asserted when no external request was active"); - assert_bad_ext_rd_ack: assert(!external_rd_ack || (external_pending | external_req)) - else $error("An external rd_ack strobe was asserted when no external request was active"); - `endif - end - end {%- endif %} {% if ds.min_read_latency == ds.min_write_latency %} // Read & write latencies are balanced. Stalls not required @@ -109,11 +92,9 @@ module {{ds.module_name}} decoded_reg_strb_t decoded_reg_strb; logic decoded_err; {%- if ds.has_external_addressable %} - logic decoded_strb_is_external; + logic decoded_req_is_external; {% endif %} -{%- if ds.has_external_block %} logic [{{cpuif.addr_width-1}}:0] decoded_addr; -{% endif %} logic decoded_req; logic decoded_req_is_wr; logic [{{cpuif.data_width-1}}:0] decoded_wr_data; @@ -147,15 +128,31 @@ module {{ds.module_name}} decoded_err = '0; {%- endif %} {%- if ds.has_external_addressable %} - decoded_strb_is_external = is_external; - external_req = is_external; + decoded_req_is_external = is_external; {%- endif %} end +{%- if ds.has_external_addressable %} + logic external_wr_ack; + logic external_rd_ack; + always_ff {{get_always_ff_event(cpuif.reset)}} begin + if({{get_resetsignal(cpuif.reset)}}) begin + external_pending <= '0; + end else begin + if(decoded_req_is_external & ~external_wr_ack & ~external_rd_ack) external_pending <= '1; + else if(external_wr_ack | external_rd_ack) external_pending <= '0; + `ifndef SYNTHESIS + assert_bad_ext_wr_ack: assert(!external_wr_ack || (external_pending | decoded_req_is_external)) + else $error("An external wr_ack strobe was asserted when no external request was active"); + assert_bad_ext_rd_ack: assert(!external_rd_ack || (external_pending | decoded_req_is_external)) + else $error("An external rd_ack strobe was asserted when no external request was active"); + `endif + end + end +{%- endif %} + // Pass down signals to next stage -{%- if ds.has_external_block %} assign decoded_addr = cpuif_addr; -{% endif %} assign decoded_req = cpuif_req_masked; assign decoded_req_is_wr = cpuif_req_is_wr; assign decoded_wr_data = cpuif_wr_data; @@ -223,7 +220,7 @@ module {{ds.module_name}} {{ext_write_acks.get_implementation()|indent(8)}} external_wr_ack = wr_ack; end - assign cpuif_wr_ack = external_wr_ack | (decoded_req & decoded_req_is_wr & ~decoded_strb_is_external); + assign cpuif_wr_ack = external_wr_ack | (decoded_req & decoded_req_is_wr & ~decoded_req_is_external); {%- else %} assign cpuif_wr_ack = decoded_req & decoded_req_is_wr; {%- endif %} @@ -262,10 +259,26 @@ module {{ds.module_name}} {%- endif %} {%- endif %} + logic [{{cpuif.addr_width-1}}:0] rd_mux_addr; +{%- if ds.has_external_addressable %} + logic [{{cpuif.addr_width-1}}:0] pending_rd_addr; + // Hold read mux address to guarantee it is stable throughout any external accesses + always_ff {{get_always_ff_event(cpuif.reset)}} begin + if({{get_resetsignal(cpuif.reset)}}) begin + pending_rd_addr <= '0; + end else begin + if(decoded_req) pending_rd_addr <= decoded_addr; + end + end + assign rd_mux_addr = decoded_req ? decoded_addr : pending_rd_addr; +{%- else %} + assign rd_mux_addr = decoded_addr; +{%- endif %} + logic readback_err; logic readback_done; logic [{{cpuif.data_width-1}}:0] readback_data; -{{readback_implementation|indent}} + {{readback_implementation|indent}} {% if ds.retime_read_response %} always_ff {{get_always_ff_event(cpuif.reset)}} begin if({{get_resetsignal(cpuif.reset)}}) begin diff --git a/src/peakrdl_regblock/readback/__init__.py b/src/peakrdl_regblock/readback/__init__.py index dafb1e0..9e3117a 100644 --- a/src/peakrdl_regblock/readback/__init__.py +++ b/src/peakrdl_regblock/readback/__init__.py @@ -1,72 +1 @@ -from typing import TYPE_CHECKING -import math - -from .generators import ReadbackAssignmentGenerator - -if TYPE_CHECKING: - from ..exporter import RegblockExporter, DesignState - from systemrdl.node import AddrmapNode - -class Readback: - def __init__(self, exp:'RegblockExporter'): - self.exp = exp - - @property - def ds(self) -> 'DesignState': - return self.exp.ds - - @property - def top_node(self) -> 'AddrmapNode': - return self.exp.ds.top_node - - def get_implementation(self) -> str: - gen = ReadbackAssignmentGenerator(self.exp) - array_assignments = gen.get_content(self.top_node) - array_size = gen.current_offset - - # Enabling the fanin stage doesnt make sense if readback fanin is - # small. This also avoids pesky corner cases - if array_size < 4: - self.ds.retime_read_fanin = False - - context = { - "array_assignments" : array_assignments, - "array_size" : array_size, - 'get_always_ff_event': self.exp.dereferencer.get_always_ff_event, - 'get_resetsignal': self.exp.dereferencer.get_resetsignal, - "cpuif": self.exp.cpuif, - "ds": self.ds, - } - - if self.ds.retime_read_fanin: - # If adding a fanin pipeline stage, goal is to try to - # split the fanin path in the middle so that fanin into the stage - # and the following are roughly balanced. - fanin_target = math.sqrt(array_size) - - # Size of fanin group to consume per fanin element - fanin_stride = math.floor(fanin_target) - - # Number of array elements to reduce to. - # Round up to an extra element in case there is some residual - fanin_array_size = math.ceil(array_size / fanin_stride) - - # leftovers are handled in an extra array element - fanin_residual_stride = array_size % fanin_stride - - if fanin_residual_stride != 0: - # If there is a partial fanin element, reduce the number of - # loops performed in the bulk fanin stage - fanin_loop_iter = fanin_array_size - 1 - else: - fanin_loop_iter = fanin_array_size - - context['fanin_stride'] = fanin_stride - context['fanin_array_size'] = fanin_array_size - context['fanin_residual_stride'] = fanin_residual_stride - context['fanin_loop_iter'] = fanin_loop_iter - - template = self.exp.jj_env.get_template( - "readback/templates/readback.sv" - ) - return template.render(context) +from .readback import Readback diff --git a/src/peakrdl_regblock/readback/generators.py b/src/peakrdl_regblock/readback/generators.py deleted file mode 100644 index 87f2969..0000000 --- a/src/peakrdl_regblock/readback/generators.py +++ /dev/null @@ -1,381 +0,0 @@ -from typing import TYPE_CHECKING, List - -from systemrdl.node import RegNode, AddressableNode -from systemrdl.walker import WalkerAction - -from ..forloop_generator import RDLForLoopGenerator, LoopBody - -from ..utils import do_bitswap, do_slice - -if TYPE_CHECKING: - from ..exporter import RegblockExporter - -class ReadbackLoopBody(LoopBody): - def __init__(self, dim: int, iterator: str, i_type: str) -> None: - super().__init__(dim, iterator, i_type) - self.n_regs = 0 - - def __str__(self) -> str: - # replace $i#sz token when stringifying - s = super().__str__() - token = f"${self.iterator}sz" - s = s.replace(token, str(self.n_regs)) - return s - -class ReadbackAssignmentGenerator(RDLForLoopGenerator): - i_type = "genvar" - loop_body_cls = ReadbackLoopBody - - def __init__(self, exp:'RegblockExporter') -> None: - super().__init__() - self.exp = exp - - # The readback array collects all possible readback values into a flat - # array. The array width is equal to the CPUIF bus width. Each entry in - # the array represents an aligned read access. - self.current_offset = 0 - self.start_offset_stack = [] # type: List[int] - self.dim_stack = [] # type: List[int] - - @property - def current_offset_str(self) -> str: - """ - Derive a string that represents the current offset being assigned. - This consists of: - - The current integer offset - - multiplied index of any enclosing loop - - The integer offset from "current_offset" is static and is monotonically - incremented as more register assignments are processed. - - The component of the offset from loops is added by multiplying the current - loop index by the loop size. - Since the loop's size is not known at this time, it is emitted as a - placeholder token like: $i0sz, $i1sz, $i2sz, etc - These tokens can be replaced once the loop body has been completed and the - size of its contents is known. - """ - offset_parts = [] - for i in range(self._loop_level): - offset_parts.append(f"i{i} * $i{i}sz") - offset_parts.append(str(self.current_offset)) - return " + ".join(offset_parts) - - def push_loop(self, dim: int) -> None: - super().push_loop(dim) - self.start_offset_stack.append(self.current_offset) - self.dim_stack.append(dim) - - def pop_loop(self) -> None: - start_offset = self.start_offset_stack.pop() - dim = self.dim_stack.pop() - - # Number of registers enclosed in this loop - n_regs = self.current_offset - start_offset - self.current_loop.n_regs = n_regs # type: ignore - - super().pop_loop() - - # Advance current scope's offset to account for loop's contents - self.current_offset = start_offset + n_regs * dim - - - def enter_AddressableComponent(self, node: 'AddressableNode') -> WalkerAction: - super().enter_AddressableComponent(node) - - if node.external and not isinstance(node, RegNode): - # External block - strb = self.exp.hwif.get_external_rd_ack(node) - data = self.exp.hwif.get_external_rd_data(node) - self.add_content(f"assign readback_array[{self.current_offset_str}] = {strb} ? {data} : '0;") - self.current_offset += 1 - return WalkerAction.SkipDescendants - - return WalkerAction.Continue - - def enter_Reg(self, node: RegNode) -> WalkerAction: - if not node.has_sw_readable: - return WalkerAction.SkipDescendants - - if node.external: - self.process_external_reg(node) - return WalkerAction.SkipDescendants - - accesswidth = node.get_property('accesswidth') - regwidth = node.get_property('regwidth') - rbuf = node.get_property('buffer_reads') - if rbuf: - trigger = node.get_property('rbuffer_trigger') - is_own_trigger = (isinstance(trigger, RegNode) and trigger == node) - if is_own_trigger: - if accesswidth < regwidth: - self.process_buffered_reg_with_bypass(node, regwidth, accesswidth) - else: - # bypass cancels out. Behaves like a normal reg - self.process_reg(node) - else: - self.process_buffered_reg(node, regwidth, accesswidth) - elif accesswidth < regwidth: - self.process_wide_reg(node, accesswidth) - else: - self.process_reg(node) - - return WalkerAction.SkipDescendants - - def process_external_reg(self, node: RegNode) -> None: - strb = self.exp.hwif.get_external_rd_ack(node) - data = self.exp.hwif.get_external_rd_data(node) - regwidth = node.get_property('regwidth') - if regwidth < self.exp.cpuif.data_width: - self.add_content(f"assign readback_array[{self.current_offset_str}][{self.exp.cpuif.data_width-1}:{regwidth}] = '0;") - self.add_content(f"assign readback_array[{self.current_offset_str}][{regwidth-1}:0] = {strb} ? {data} : '0;") - else: - self.add_content(f"assign readback_array[{self.current_offset_str}] = {strb} ? {data} : '0;") - - self.current_offset += 1 - - def process_reg(self, node: RegNode) -> None: - current_bit = 0 - rd_strb = f"({self.exp.dereferencer.get_access_strobe(node)} && !decoded_req_is_wr)" - # Fields are sorted by ascending low bit - for field in node.fields(): - if not field.is_sw_readable: - continue - - # insert reserved assignment before this field if needed - if field.low != current_bit: - self.add_content(f"assign readback_array[{self.current_offset_str}][{field.low-1}:{current_bit}] = '0;") - - value = self.exp.dereferencer.get_value(field) - if field.msb < field.lsb: - # Field gets bitswapped since it is in [low:high] orientation - value = do_bitswap(value) - - self.add_content(f"assign readback_array[{self.current_offset_str}][{field.high}:{field.low}] = {rd_strb} ? {value} : '0;") - - current_bit = field.high + 1 - - # Insert final reserved assignment if needed - bus_width = self.exp.cpuif.data_width - if current_bit < bus_width: - self.add_content(f"assign readback_array[{self.current_offset_str}][{bus_width-1}:{current_bit}] = '0;") - - self.current_offset += 1 - - - def process_buffered_reg(self, node: RegNode, regwidth: int, accesswidth: int) -> None: - rbuf = self.exp.read_buffering.get_rbuf_data(node) - - if accesswidth < regwidth: - # Is wide reg - n_subwords = regwidth // accesswidth - astrb = self.exp.dereferencer.get_access_strobe(node, reduce_substrobes=False) - for i in range(n_subwords): - rd_strb = f"({astrb}[{i}] && !decoded_req_is_wr)" - bslice = f"[{(i + 1) * accesswidth - 1}:{i*accesswidth}]" - self.add_content(f"assign readback_array[{self.current_offset_str}] = {rd_strb} ? {rbuf}{bslice} : '0;") - self.current_offset += 1 - - else: - # Is regular reg - rd_strb = f"({self.exp.dereferencer.get_access_strobe(node)} && !decoded_req_is_wr)" - self.add_content(f"assign readback_array[{self.current_offset_str}][{regwidth-1}:0] = {rd_strb} ? {rbuf} : '0;") - - bus_width = self.exp.cpuif.data_width - if regwidth < bus_width: - self.add_content(f"assign readback_array[{self.current_offset_str}][{bus_width-1}:{regwidth}] = '0;") - - self.current_offset += 1 - - - def process_buffered_reg_with_bypass(self, node: RegNode, regwidth: int, accesswidth: int) -> None: - """ - Special case for a buffered register when the register is its own trigger. - First sub-word shall bypass the read buffer and assign directly. - Subsequent subwords assign from the buffer. - Caller guarantees this is a wide reg - """ - astrb = self.exp.dereferencer.get_access_strobe(node, reduce_substrobes=False) - - # Generate assignments for first sub-word - bidx = 0 - rd_strb = f"({astrb}[0] && !decoded_req_is_wr)" - for field in node.fields(): - if not field.is_sw_readable: - continue - - if field.low >= accesswidth: - # field is not in this subword. - break - - if bidx < field.low: - # insert padding before - self.add_content(f"assign readback_array[{self.current_offset_str}][{field.low - 1}:{bidx}] = '0;") - - if field.high >= accesswidth: - # field gets truncated - r_low = field.low - r_high = accesswidth - 1 - f_low = 0 - f_high = accesswidth - 1 - field.low - - if field.msb < field.lsb: - # Field gets bitswapped since it is in [low:high] orientation - # Mirror the low/high indexes - f_low = field.width - 1 - f_low - f_high = field.width - 1 - f_high - f_low, f_high = f_high, f_low - value = do_bitswap(do_slice(self.exp.dereferencer.get_value(field), f_high, f_low)) - else: - value = do_slice(self.exp.dereferencer.get_value(field), f_high, f_low) - - self.add_content(f"assign readback_array[{self.current_offset_str}][{r_high}:{r_low}] = {rd_strb} ? {value} : '0;") - bidx = accesswidth - else: - # field fits in subword - value = self.exp.dereferencer.get_value(field) - if field.msb < field.lsb: - # Field gets bitswapped since it is in [low:high] orientation - value = do_bitswap(value) - self.add_content(f"assign readback_array[{self.current_offset_str}][{field.high}:{field.low}] = {rd_strb} ? {value} : '0;") - bidx = field.high + 1 - - # pad up remainder of subword - if bidx < accesswidth: - self.add_content(f"assign readback_array[{self.current_offset_str}][{accesswidth-1}:{bidx}] = '0;") - self.current_offset += 1 - - # Assign remainder of subwords from read buffer - n_subwords = regwidth // accesswidth - rbuf = self.exp.read_buffering.get_rbuf_data(node) - for i in range(1, n_subwords): - rd_strb = f"({astrb}[{i}] && !decoded_req_is_wr)" - bslice = f"[{(i + 1) * accesswidth - 1}:{i*accesswidth}]" - self.add_content(f"assign readback_array[{self.current_offset_str}] = {rd_strb} ? {rbuf}{bslice} : '0;") - self.current_offset += 1 - - def process_wide_reg(self, node: RegNode, accesswidth: int) -> None: - bus_width = self.exp.cpuif.data_width - - subword_idx = 0 - current_bit = 0 # Bit-offset within the wide register - access_strb = self.exp.dereferencer.get_access_strobe(node, reduce_substrobes=False) - # Fields are sorted by ascending low bit - for field in node.fields(): - if not field.is_sw_readable: - continue - - # insert zero assignment before this field if needed - if field.low >= accesswidth*(subword_idx+1): - # field does not start in this subword - if current_bit > accesswidth * subword_idx: - # current subword had content. Assign remainder - low = current_bit % accesswidth - high = bus_width - 1 - self.add_content(f"assign readback_array[{self.current_offset_str}][{high}:{low}] = '0;") - self.current_offset += 1 - - # Advance to subword that contains the start of the field - subword_idx = field.low // accesswidth - current_bit = accesswidth * subword_idx - - if current_bit != field.low: - # assign zero up to start of this field - low = current_bit % accesswidth - high = (field.low % accesswidth) - 1 - self.add_content(f"assign readback_array[{self.current_offset_str}][{high}:{low}] = '0;") - current_bit = field.low - - - # Assign field - # loop until the entire field's assignments have been generated - field_pos = field.low - while current_bit <= field.high: - # Assign the field - rd_strb = f"({access_strb}[{subword_idx}] && !decoded_req_is_wr)" - if (field_pos == field.low) and (field.high < accesswidth*(subword_idx+1)): - # entire field fits into this subword - low = field.low - accesswidth * subword_idx - high = field.high - accesswidth * subword_idx - - value = self.exp.dereferencer.get_value(field) - if field.msb < field.lsb: - # Field gets bitswapped since it is in [low:high] orientation - value = do_bitswap(value) - - self.add_content(f"assign readback_array[{self.current_offset_str}][{high}:{low}] = {rd_strb} ? {value} : '0;") - - current_bit = field.high + 1 - - if current_bit == accesswidth*(subword_idx+1): - # Field ends at the subword boundary - subword_idx += 1 - self.current_offset += 1 - elif field.high >= accesswidth*(subword_idx+1): - # only a subset of the field can fit into this subword - # high end gets truncated - - # assignment slice - r_low = field_pos - accesswidth * subword_idx - r_high = accesswidth - 1 - - # field slice - f_low = field_pos - field.low - f_high = accesswidth * (subword_idx + 1) - 1 - field.low - - if field.msb < field.lsb: - # Field gets bitswapped since it is in [low:high] orientation - # Mirror the low/high indexes - f_low = field.width - 1 - f_low - f_high = field.width - 1 - f_high - f_low, f_high = f_high, f_low - - value = do_bitswap(do_slice(self.exp.dereferencer.get_value(field), f_high, f_low)) - else: - value = do_slice(self.exp.dereferencer.get_value(field), f_high, f_low) - - self.add_content(f"assign readback_array[{self.current_offset_str}][{r_high}:{r_low}] = {rd_strb} ? {value} : '0;") - - # advance to the next subword - subword_idx += 1 - current_bit = accesswidth * subword_idx - field_pos = current_bit - self.current_offset += 1 - else: - # only a subset of the field can fit into this subword - # finish field - - # assignment slice - r_low = field_pos - accesswidth * subword_idx - r_high = field.high - accesswidth * subword_idx - - # field slice - f_low = field_pos - field.low - f_high = field.high - field.low - - if field.msb < field.lsb: - # Field gets bitswapped since it is in [low:high] orientation - # Mirror the low/high indexes - f_low = field.width - 1 - f_low - f_high = field.width - 1 - f_high - f_low, f_high = f_high, f_low - - value = do_bitswap(do_slice(self.exp.dereferencer.get_value(field), f_high, f_low)) - else: - value = do_slice(self.exp.dereferencer.get_value(field), f_high, f_low) - - self.add_content(f"assign readback_array[{self.current_offset_str}][{r_high}:{r_low}] = {rd_strb} ? {value} : '0;") - - current_bit = field.high + 1 - if current_bit == accesswidth*(subword_idx+1): - # Field ends at the subword boundary - subword_idx += 1 - self.current_offset += 1 - - # insert zero assignment after the last field if needed - if current_bit > accesswidth * subword_idx: - # current subword had content. Assign remainder - low = current_bit % accesswidth - high = bus_width - 1 - self.add_content(f"assign readback_array[{self.current_offset_str}][{high}:{low}] = '0;") - self.current_offset += 1 diff --git a/src/peakrdl_regblock/readback/readback.py b/src/peakrdl_regblock/readback/readback.py new file mode 100644 index 0000000..b36ac0b --- /dev/null +++ b/src/peakrdl_regblock/readback/readback.py @@ -0,0 +1,101 @@ +from typing import TYPE_CHECKING + +from .readback_mux_generator import ReadbackMuxGenerator, RetimedReadbackMuxGenerator, RetimedExtBlockReadbackMuxGenerator +from ..utils import clog2 + +if TYPE_CHECKING: + from ..exporter import RegblockExporter, DesignState + +class Readback: + def __init__(self, exp:'RegblockExporter'): + self.exp = exp + + @property + def ds(self) -> 'DesignState': + return self.exp.ds + + def get_implementation(self) -> str: + if self.ds.retime_read_fanin: + return self.get_2stage_implementation() + else: + # No retiming + return self.get_1stage_implementation() + + + def get_empty_implementation(self) -> str: + """ + Readback implementation when there are no readable registers + """ + context = { + "ds": self.ds, + } + template = self.exp.jj_env.get_template( + "readback/templates/empty_readback.sv" + ) + return template.render(context) + + + def get_1stage_implementation(self) -> str: + """ + Implements readback without any retiming + """ + gen = ReadbackMuxGenerator(self.exp) + mux_impl = gen.get_content(self.ds.top_node) + + if not mux_impl: + # Design has no readable registers. + return self.get_empty_implementation() + + context = { + "readback_mux": mux_impl, + "cpuif": self.exp.cpuif, + "ds": self.ds, + } + template = self.exp.jj_env.get_template( + "readback/templates/readback_no_rt.sv" + ) + + return template.render(context) + + + def get_2stage_implementation(self) -> str: + """ + Implements readback that is retimed to 2 stages + """ + # Split the decode to happen in two stages, using low address bits first + # then high address bits. + # Split in the middle of the "relevant" address bits - the ones that + # actually contribute to addressing in the regblock + unused_low_addr_bits = clog2(self.exp.cpuif.data_width_bytes) + relevant_addr_width = self.ds.addr_width - unused_low_addr_bits + low_addr_width = (relevant_addr_width // 2) + unused_low_addr_bits + high_addr_width = self.ds.addr_width - low_addr_width + + mux_gen = RetimedReadbackMuxGenerator(self.exp) + mux_impl = mux_gen.get_content(self.ds.top_node) + + if not mux_impl: + # Design has no readable addresses. + return self.get_empty_implementation() + + if self.ds.has_external_block: + ext_mux_gen = RetimedExtBlockReadbackMuxGenerator(self.exp) + ext_mux_impl = ext_mux_gen.get_content(self.ds.top_node) + else: + ext_mux_impl = None + + context = { + "readback_mux": mux_impl, + "ext_block_readback_mux": ext_mux_impl, + "cpuif": self.exp.cpuif, + "ds": self.ds, + "low_addr_width": low_addr_width, + "high_addr_width": high_addr_width, + 'get_always_ff_event': self.exp.dereferencer.get_always_ff_event, + 'get_resetsignal': self.exp.dereferencer.get_resetsignal, + } + template = self.exp.jj_env.get_template( + "readback/templates/readback_with_rt.sv" + ) + + return template.render(context) diff --git a/src/peakrdl_regblock/readback/readback_mux_generator.py b/src/peakrdl_regblock/readback/readback_mux_generator.py new file mode 100644 index 0000000..34d7891 --- /dev/null +++ b/src/peakrdl_regblock/readback/readback_mux_generator.py @@ -0,0 +1,361 @@ +from typing import TYPE_CHECKING, List, Sequence, Optional + +from systemrdl.node import RegNode, AddressableNode, FieldNode +from systemrdl.walker import WalkerAction + +from ..forloop_generator import RDLForLoopGenerator +from ..utils import SVInt, do_bitswap, do_slice + +if TYPE_CHECKING: + from ..exporter import DesignState, RegblockExporter + +class ReadbackMuxGenerator(RDLForLoopGenerator): + def __init__(self, exp: 'RegblockExporter') -> None: + super().__init__() + + self.exp = exp + + # List of address strides for each dimension + self._array_stride_stack: List[int] = [] + + @property + def ds(self) -> 'DesignState': + return self.exp.ds + + + def enter_AddressableComponent(self, node: AddressableNode) -> Optional[WalkerAction]: + super().enter_AddressableComponent(node) + + if node.array_dimensions: + assert node.array_stride is not None + # Collect strides for each array dimension + current_stride = node.array_stride + strides = [] + for dim in reversed(node.array_dimensions): + strides.append(current_stride) + current_stride *= dim + strides.reverse() + self._array_stride_stack.extend(strides) + + if node.external and not isinstance(node, RegNode): + # Is an external block + self.process_external_block(node) + return WalkerAction.SkipDescendants + + return WalkerAction.Continue + + + def process_external_block(self, node: AddressableNode) -> None: + addr_lo = self._get_address_str(node) + addr_hi = f"{addr_lo} + {SVInt(node.size - 1, self.exp.ds.addr_width)}" + self.add_content(f"if((rd_mux_addr >= {addr_lo}) && (rd_mux_addr <= {addr_hi})) begin") + data = self.exp.hwif.get_external_rd_data(node) + self.add_content(f" readback_data_var = {data};") + self.add_content("end") + + + def enter_Reg(self, node: RegNode) -> WalkerAction: + fields = node.fields(sw_readable_only=True) + if not fields: + # Reg has no readable fields + return WalkerAction.SkipDescendants + + if node.external: + self.process_external_reg(node) + return WalkerAction.SkipDescendants + + accesswidth = node.get_property('accesswidth') + regwidth = node.get_property('regwidth') + rbuf = node.get_property('buffer_reads') + + if rbuf: + trigger = node.get_property('rbuffer_trigger') + is_own_trigger = (isinstance(trigger, RegNode) and trigger == node) + if is_own_trigger: + if accesswidth < regwidth: + self.process_wide_buffered_reg_with_bypass(node, fields, regwidth, accesswidth) + else: + # bypass cancels out. Behaves like a normal reg + self.process_reg(node, fields) + else: + self.process_buffered_reg(node, regwidth, accesswidth) + elif accesswidth < regwidth: + self.process_wide_reg(node, fields, regwidth, accesswidth) + else: + self.process_reg(node, fields) + + return WalkerAction.SkipDescendants + + + def _get_address_str(self, node: AddressableNode, subword_offset: int=0) -> str: + expr_width = self.ds.addr_width + a = str(SVInt( + node.raw_absolute_address - self.ds.top_node.raw_absolute_address + subword_offset, + expr_width + )) + for i, stride in enumerate(self._array_stride_stack): + a += f" + ({expr_width})'(i{i}) * {SVInt(stride, expr_width)}" + return a + + + def get_addr_compare_conditional(self, addr: str) -> str: + return f"rd_mux_addr == {addr}" + + def get_readback_data_var(self, addr: str) -> str: + return "readback_data_var" + + def process_external_reg(self, node: RegNode) -> None: + accesswidth = node.get_property('accesswidth') + regwidth = node.get_property('regwidth') + data = self.exp.hwif.get_external_rd_data(node) + + if regwidth > accesswidth: + # Is wide reg. + # The retiming scheme requires singular address comparisons rather than + # ranges. To support this, unroll the subwords + n_subwords = regwidth // accesswidth + subword_stride = accesswidth // 8 + for subword_idx in range(n_subwords): + addr = self._get_address_str(node, subword_offset=subword_idx*subword_stride) + conditional = self.get_addr_compare_conditional(addr) + var = self.get_readback_data_var(addr) + self.add_content(f"if({conditional}) begin") + self.add_content(f" {var} = {data};") + self.add_content("end") + else: + addr = self._get_address_str(node) + conditional = self.get_addr_compare_conditional(addr) + var = self.get_readback_data_var(addr) + self.add_content(f"if({conditional}) begin") + if regwidth < self.exp.cpuif.data_width: + self.add_content(f" {var}[{regwidth-1}:0] = {data};") + else: + self.add_content(f" {var} = {data};") + self.add_content("end") + + + def process_reg(self, node: RegNode, fields: Sequence[FieldNode]) -> None: + """ + Process a regular register + """ + addr = self._get_address_str(node) + conditional = self.get_addr_compare_conditional(addr) + var = self.get_readback_data_var(addr) + self.add_content(f"if({conditional}) begin") + + for field in fields: + value = self.exp.dereferencer.get_value(field) + if field.msb < field.lsb: + # Field gets bitswapped since it is in [low:high] orientation + value = do_bitswap(value) + + if field.width == 1: + self.add_content(f" {var}[{field.low}] = {value};") + else: + self.add_content(f" {var}[{field.high}:{field.low}] = {value};") + + self.add_content("end") + + + def process_buffered_reg(self, node: RegNode, regwidth: int, accesswidth: int) -> None: + """ + Process a register which is fully buffered + """ + rbuf = self.exp.read_buffering.get_rbuf_data(node) + + if accesswidth < regwidth: + # Is wide reg + n_subwords = regwidth // accesswidth + subword_stride = accesswidth // 8 + for subword_idx in range(n_subwords): + addr = self._get_address_str(node, subword_offset=subword_idx*subword_stride) + conditional = self.get_addr_compare_conditional(addr) + var = self.get_readback_data_var(addr) + bslice = f"[{(subword_idx + 1) * accesswidth - 1}:{subword_idx*accesswidth}]" + self.add_content(f"if({conditional}) begin") + self.add_content(f" {var} = {rbuf}{bslice};") + self.add_content("end") + else: + # Is regular reg + addr = self._get_address_str(node) + conditional = self.get_addr_compare_conditional(addr) + var = self.get_readback_data_var(addr) + self.add_content(f"if({conditional}) begin") + self.add_content(f" {var}[{regwidth-1}:0] = {rbuf};") + self.add_content("end") + + + def process_wide_buffered_reg_with_bypass(self, node: RegNode, fields: Sequence[FieldNode], regwidth: int, accesswidth: int) -> None: + """ + Special case for a wide buffered register where the register is its own + trigger. + + First sub-word shall bypass the read buffer and assign directly. + Subsequent subwords assign from the buffer. + """ + + # Generate assignments for first sub-word + subword_assignments = self.get_wide_reg_subword_assignments(node, fields, regwidth, accesswidth) + if subword_assignments[0]: + addr = self._get_address_str(node, subword_offset=0) + conditional = self.get_addr_compare_conditional(addr) + self.add_content(f"if({conditional}) begin") + for assignment in subword_assignments[0]: + self.add_content(" " + assignment) + self.add_content("end") + + # Assign remainder of subwords from read buffer + n_subwords = regwidth // accesswidth + subword_stride = accesswidth // 8 + rbuf = self.exp.read_buffering.get_rbuf_data(node) + for subword_idx in range(1, n_subwords): + addr = self._get_address_str(node, subword_offset=subword_idx*subword_stride) + bslice = f"[{(subword_idx + 1) * accesswidth - 1}:{subword_idx*accesswidth}]" + conditional = self.get_addr_compare_conditional(addr) + var = self.get_readback_data_var(addr) + self.add_content(f"if({conditional}) begin") + self.add_content(f" {var} = {rbuf}{bslice};") + self.add_content("end") + + + def get_wide_reg_subword_assignments(self, node: RegNode, fields: Sequence[FieldNode], regwidth: int, accesswidth: int) -> List[List[str]]: + """ + Get a list of assignments for each subword + + Returns a 2d array where the first dimension indicates the subword index. + The next dimension is the list of assignments + """ + n_subwords = regwidth // accesswidth + subword_stride = accesswidth // 8 + subword_assignments: List[List[str]] = [[] for _ in range(n_subwords)] + + # Fields are sorted by ascending low bit + for field in fields: + subword_idx = field.low // accesswidth + + if field.high < accesswidth * (subword_idx + 1): + # entire field fits into this subword + low = field.low - accesswidth * subword_idx + high = field.high - accesswidth * subword_idx + + value = self.exp.dereferencer.get_value(field) + if field.msb < field.lsb: + # Field gets bitswapped since it is in [low:high] orientation + value = do_bitswap(value) + + addr = self._get_address_str(node, subword_offset=subword_idx*subword_stride) + var = self.get_readback_data_var(addr) + subword_assignments[subword_idx].append(f"{var}[{high}:{low}] = {value};") + + else: + # Field spans multiple sub-words + # loop through subword indexes until the entire field has been assigned + while field.high >= accesswidth * subword_idx: + # Allowable field window for this subword + subword_low = accesswidth * subword_idx + subword_high = subword_low + accesswidth - 1 + + # field slice (relative to reg) + f_low = max(subword_low, field.low) + f_high = min(subword_high, field.high) + + # assignment slice + r_low = f_low - accesswidth * subword_idx + r_high = f_high - accesswidth * subword_idx + + # Adjust to be relative to field + f_low -= field.low + f_high -= field.low + + if field.msb < field.lsb: + # Field gets bitswapped since it is in [low:high] orientation + # Mirror the low/high indexes + f_low = field.width - 1 - f_low + f_high = field.width - 1 - f_high + f_low, f_high = f_high, f_low + + value = do_bitswap(do_slice(self.exp.dereferencer.get_value(field), f_high, f_low)) + else: + value = do_slice(self.exp.dereferencer.get_value(field), f_high, f_low) + + addr = self._get_address_str(node, subword_offset=subword_idx*subword_stride) + var = self.get_readback_data_var(addr) + subword_assignments[subword_idx].append(f"{var}[{r_high}:{r_low}] = {value};") + + # advance to the next subword + subword_idx += 1 + + return subword_assignments + + + def process_wide_reg(self, node: RegNode, fields: Sequence[FieldNode], regwidth: int, accesswidth: int) -> None: + """ + Process a register whose accesswidth < regwidth + """ + subword_assignments = self.get_wide_reg_subword_assignments(node, fields, regwidth, accesswidth) + + # Add generated content, wrapped in the address conditional + subword_stride = accesswidth // 8 + for subword_idx, assignments in enumerate(subword_assignments): + if not assignments: + continue + addr = self._get_address_str(node, subword_offset=subword_idx*subword_stride) + conditional = self.get_addr_compare_conditional(addr) + self.add_content(f"if({conditional}) begin") + for assignment in assignments: + self.add_content(" " + assignment) + self.add_content("end") + + + def exit_AddressableComponent(self, node: AddressableNode) -> None: + super().exit_AddressableComponent(node) + + if not node.array_dimensions: + return + + for _ in node.array_dimensions: + self._array_stride_stack.pop() + + +class RetimedReadbackMuxGenerator(ReadbackMuxGenerator): + """ + Alternate variant that is dedicated to building the 1st decode stage + """ + + def process_external_block(self, node: AddressableNode) -> None: + # Do nothing. External blocks are handled in a completely separate readback mux + pass + + def get_addr_compare_conditional(self, addr: str) -> str: + # In the pipelined variant, compare the low-bits of both sides + return f"ad_low(rd_mux_addr) == ad_low({addr})" + + def get_readback_data_var(self, addr: str) -> str: + # In the pipelined variant, assign to the bin indexed by the high bits of addr + return f"readback_data_var[ad_hi({addr})]" + + +class RetimedExtBlockReadbackMuxGenerator(ReadbackMuxGenerator): + """ + When retiming is enabled, external blocks are implemented as a separate + reaback mux that is not retimed using a partitioned address. + + This is because the address partitioning scheme used for individual register + addresses does not work cleanly for address ranges. (not possible to cleanly + map readback of a range to high-address data bins) + + Since the non-retimed mux generator already implements external ranges, + re-use it and suppress generation of register logic. + """ + + def enter_Reg(self, node: RegNode) -> WalkerAction: + return WalkerAction.SkipDescendants + + def process_external_block(self, node: AddressableNode) -> None: + addr_lo = self._get_address_str(node) + addr_hi = f"{addr_lo} + {SVInt(node.size - 1, self.exp.ds.addr_width)}" + self.add_content(f"if((rd_mux_addr >= {addr_lo}) && (rd_mux_addr <= {addr_hi})) begin") + data = self.exp.hwif.get_external_rd_data(node) + self.add_content(f" readback_data_var = {data};") + self.add_content(" is_external_block_var = 1'b1;") + self.add_content("end") diff --git a/src/peakrdl_regblock/readback/templates/empty_readback.sv b/src/peakrdl_regblock/readback/templates/empty_readback.sv new file mode 100644 index 0000000..f493b83 --- /dev/null +++ b/src/peakrdl_regblock/readback/templates/empty_readback.sv @@ -0,0 +1,7 @@ +assign readback_done = decoded_req & ~decoded_req_is_wr; +assign readback_data = '0; +{%- if ds.err_if_bad_addr or ds.err_if_bad_rw %} +assign readback_err = decoded_err; +{%- else %} +assign readback_err = '0; +{%- endif %} diff --git a/src/peakrdl_regblock/readback/templates/readback.sv b/src/peakrdl_regblock/readback/templates/readback.sv deleted file mode 100644 index 08ed492..0000000 --- a/src/peakrdl_regblock/readback/templates/readback.sv +++ /dev/null @@ -1,94 +0,0 @@ -{% if array_assignments is not none %} -// Assign readback values to a flattened array -logic [{{cpuif.data_width-1}}:0] readback_array[{{array_size}}]; -{{array_assignments}} - - -{%- if ds.retime_read_fanin %} - -// fanin stage -logic [{{cpuif.data_width-1}}:0] readback_array_c[{{fanin_array_size}}]; -for(genvar g=0; g<{{fanin_loop_iter}}; g++) begin - always_comb begin - automatic logic [{{cpuif.data_width-1}}:0] readback_data_var; - readback_data_var = '0; - for(int i=g*{{fanin_stride}}; i<((g+1)*{{fanin_stride}}); i++) readback_data_var |= readback_array[i]; - readback_array_c[g] = readback_data_var; - end -end -{%- if fanin_residual_stride == 1 %} -assign readback_array_c[{{fanin_array_size-1}}] = readback_array[{{array_size-1}}]; -{%- elif fanin_residual_stride > 1 %} -always_comb begin - automatic logic [{{cpuif.data_width-1}}:0] readback_data_var; - readback_data_var = '0; - for(int i={{(fanin_array_size-1) * fanin_stride}}; i<{{array_size}}; i++) readback_data_var |= readback_array[i]; - readback_array_c[{{fanin_array_size-1}}] = readback_data_var; -end -{%- endif %} - -logic [{{cpuif.data_width-1}}:0] readback_array_r[{{fanin_array_size}}]; -logic readback_done_r; -logic readback_err_r; -always_ff {{get_always_ff_event(cpuif.reset)}} begin - if({{get_resetsignal(cpuif.reset)}}) begin - for(int i=0; i<{{fanin_array_size}}; i++) readback_array_r[i] <= '0; - readback_done_r <= '0; - readback_err_r <= '0; - end else begin - readback_array_r <= readback_array_c; - readback_err_r <= decoded_err; - {%- if ds.has_external_addressable %} - readback_done_r <= decoded_req & ~decoded_req_is_wr & ~decoded_strb_is_external; - {%- else %} - readback_done_r <= decoded_req & ~decoded_req_is_wr; - {%- endif %} - end -end - -// Reduce the array -always_comb begin - automatic logic [{{cpuif.data_width-1}}:0] readback_data_var; - readback_done = readback_done_r; - {%- if ds.err_if_bad_addr or ds.err_if_bad_rw %} - readback_err = readback_err_r; - {%- else %} - readback_err = '0; - {%- endif %} - readback_data_var = '0; - for(int i=0; i<{{fanin_array_size}}; i++) readback_data_var |= readback_array_r[i]; - readback_data = readback_data_var; -end - -{%- else %} - -// Reduce the array -always_comb begin - automatic logic [{{cpuif.data_width-1}}:0] readback_data_var; - {%- if ds.has_external_addressable %} - readback_done = decoded_req & ~decoded_req_is_wr & ~decoded_strb_is_external; - {%- else %} - readback_done = decoded_req & ~decoded_req_is_wr; - {%- endif %} - {%- if ds.err_if_bad_addr or ds.err_if_bad_rw %} - readback_err = decoded_err; - {%- else %} - readback_err = '0; - {%- endif %} - readback_data_var = '0; - for(int i=0; i<{{array_size}}; i++) readback_data_var |= readback_array[i]; - readback_data = readback_data_var; -end -{%- endif %} - - - -{%- else %} -assign readback_done = decoded_req & ~decoded_req_is_wr; -assign readback_data = '0; -{%- if ds.err_if_bad_addr or ds.err_if_bad_rw %} -assign readback_err = decoded_err; -{%- else %} -assign readback_err = '0; -{%- endif %} -{% endif %} diff --git a/src/peakrdl_regblock/readback/templates/readback_no_rt.sv b/src/peakrdl_regblock/readback/templates/readback_no_rt.sv new file mode 100644 index 0000000..02d2cc2 --- /dev/null +++ b/src/peakrdl_regblock/readback/templates/readback_no_rt.sv @@ -0,0 +1,17 @@ +always_comb begin + automatic logic [{{cpuif.data_width-1}}:0] readback_data_var; + readback_data_var = '0; + {{readback_mux|indent}} + readback_data = readback_data_var; + + {%- if ds.has_external_addressable %} + readback_done = decoded_req & ~decoded_req_is_wr & ~decoded_req_is_external; + {%- else %} + readback_done = decoded_req & ~decoded_req_is_wr; + {%- endif %} + {%- if ds.err_if_bad_addr or ds.err_if_bad_rw %} + readback_err = decoded_err; + {%- else %} + readback_err = '0; + {%- endif %} +end diff --git a/src/peakrdl_regblock/readback/templates/readback_with_rt.sv b/src/peakrdl_regblock/readback/templates/readback_with_rt.sv new file mode 100644 index 0000000..28fe077 --- /dev/null +++ b/src/peakrdl_regblock/readback/templates/readback_with_rt.sv @@ -0,0 +1,82 @@ +function automatic bit [{{low_addr_width-1}}:0] ad_low(bit [{{ds.addr_width-1}}:0] addr); + return addr[{{low_addr_width-1}}:0]; +endfunction +function automatic bit [{{high_addr_width-1}}:0] ad_hi(bit [{{ds.addr_width-1}}:0] addr); + return addr[{{ds.addr_width-1}}:{{low_addr_width}}]; +endfunction + +// readback stage 1 +logic [{{cpuif.data_width-1}}:0] readback_data_rt_c[{{2 ** high_addr_width}}]; +always_comb begin + automatic logic [{{cpuif.data_width-1}}:0] readback_data_var[{{2 ** high_addr_width}}]; + for(int i=0; i<{{2 ** high_addr_width}}; i++) readback_data_var[i] = '0; + {{readback_mux|indent}} + readback_data_rt_c = readback_data_var; +end + +logic [{{cpuif.data_width-1}}:0] readback_data_rt[{{2 ** high_addr_width}}]; +logic readback_done_rt; +logic readback_err_rt; +logic [{{ds.addr_width-1}}:0] readback_addr_rt; +always_ff {{get_always_ff_event(cpuif.reset)}} begin + if({{get_resetsignal(cpuif.reset)}}) begin + for(int i=0; i<{{2 ** high_addr_width}}; i++) readback_data_rt[i] <= '0; + readback_done_rt <= '0; + readback_err_rt <= '0; + readback_addr_rt <= '0; + end else begin + readback_data_rt <= readback_data_rt_c; + readback_err_rt <= decoded_err; + {%- if ds.has_external_addressable %} + readback_done_rt <= decoded_req & ~decoded_req_is_wr & ~decoded_req_is_external; + {%- else %} + readback_done_rt <= decoded_req & ~decoded_req_is_wr; + {%- endif %} + readback_addr_rt <= rd_mux_addr; + end +end + +{% if ds.has_external_block %} +logic [{{cpuif.data_width-1}}:0] readback_ext_block_data_rt_c; +logic readback_is_ext_block_c; +always_comb begin + automatic logic [{{cpuif.data_width-1}}:0] readback_data_var; + automatic logic is_external_block_var; + readback_data_var = '0; + is_external_block_var = '0; + {{ext_block_readback_mux|indent}} + readback_ext_block_data_rt_c = readback_data_var; + readback_is_ext_block_c = is_external_block_var; +end + +logic [{{cpuif.data_width-1}}:0] readback_ext_block_data_rt; +logic readback_is_ext_block; +always_ff {{get_always_ff_event(cpuif.reset)}} begin + if({{get_resetsignal(cpuif.reset)}}) begin + readback_ext_block_data_rt <= '0; + readback_is_ext_block <= '0; + end else begin + readback_ext_block_data_rt <= readback_ext_block_data_rt_c; + readback_is_ext_block <= readback_is_ext_block_c; + end +end +{% endif %} + +// readback stage 2 +always_comb begin + {%- if ds.has_external_block %} + if(readback_is_ext_block) begin + readback_data = readback_ext_block_data_rt; + end else begin + readback_data = readback_data_rt[readback_addr_rt[{{ds.addr_width-1}}:{{low_addr_width}}]]; + end + {%- else %} + readback_data = readback_data_rt[readback_addr_rt[{{ds.addr_width-1}}:{{low_addr_width}}]]; + {%- endif %} + readback_done = readback_done_rt; + {%- if ds.err_if_bad_addr or ds.err_if_bad_rw %} + readback_err = readback_err_rt; + {%- else %} + readback_err = '0; + {%- endif %} +end diff --git a/tests/README.md b/tests/README.md index c20ca4e..58d32f5 100644 --- a/tests/README.md +++ b/tests/README.md @@ -6,10 +6,10 @@ Testcases require an installation of the Questa simulator, and for `vlog` & `vsim` commands to be visible via the PATH environment variable. -*Questa - Intel FPGA Starter Edition* can be downloaded for free from Intel: -* Go to https://www.intel.com/content/www/us/en/collections/products/fpga/software/downloads.html?edition=pro&q=questa&s=Relevancy -* Select latest version of Questa -* Download Questa files. +*Questa-Altera FPGA and Starter Edition* can be downloaded for free from Altera: +* Go to https://www.altera.com/downloads +* Select "Simulation Tools" +* Download Questa * Install * Be sure to choose "Starter Edition" for the free version. * Create an account on https://licensing.intel.com @@ -18,7 +18,7 @@ commands to be visible via the PATH environment variable. * Go to https://licensing.intel.com/psg/s/sales-signup-evaluationlicenses * Generate a free *Starter Edition* license file for Questa * Easiest to use a *fixed* license using your NIC ID (MAC address of your network card via `ifconfig`) -* Download the license file and point the `LM_LICENSE_FILE` environment variable to the folder which contains it. +* Download the license file and point the `LM_LICENSE_FILE` environment variable to the folder which contains it. In newer versions of Questa, use the `SALT_LICENSE_SERVER` environment variable instead. * (optional) Delete Intel libraries to save some disk space * Delete `/questa_fse/intel` * Edit `/questa_fse/modelsim.ini` and remove lines that reference the `intel` libraries diff --git a/tests/test_only_external_blocks/__init__.py b/tests/test_only_external_blocks/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_only_external_blocks/regblock.rdl b/tests/test_only_external_blocks/regblock.rdl new file mode 100644 index 0000000..be6e664 --- /dev/null +++ b/tests/test_only_external_blocks/regblock.rdl @@ -0,0 +1,11 @@ +addrmap top { + mem ext_mem #( + longint SIZE = 0x100 + ) { + memwidth = 32; + mementries = SIZE / 4; + }; + + external ext_mem #(.SIZE(0x10)) mem1 @ 0x0000; + external ext_mem #(.SIZE(0x90)) mem2 @ 0x0200; +}; diff --git a/tests/test_only_external_blocks/tb_template.sv b/tests/test_only_external_blocks/tb_template.sv new file mode 100644 index 0000000..bf8c2cb --- /dev/null +++ b/tests/test_only_external_blocks/tb_template.sv @@ -0,0 +1,115 @@ +{% extends "lib/tb_base.sv" %} + + + +{%- block dut_support %} + {% sv_line_anchor %} + + external_block #( + .ADDR_WIDTH($clog2('h10)) + ) mem1_inst ( + .clk(clk), + .rst(rst), + + .req(hwif_out.mem1.req), + .req_is_wr(hwif_out.mem1.req_is_wr), + .addr(hwif_out.mem1.addr), + .wr_data(hwif_out.mem1.wr_data), + .wr_biten(hwif_out.mem1.wr_biten), + .rd_ack(hwif_in.mem1.rd_ack), + .rd_data(hwif_in.mem1.rd_data), + .wr_ack(hwif_in.mem1.wr_ack) + ); + + external_block #( + .ADDR_WIDTH($clog2('h90)) + ) mem2_inst ( + .clk(clk), + .rst(rst), + + .req(hwif_out.mem2.req), + .req_is_wr(hwif_out.mem2.req_is_wr), + .addr(hwif_out.mem2.addr), + .wr_data(hwif_out.mem2.wr_data), + .wr_biten(hwif_out.mem2.wr_biten), + .rd_ack(hwif_in.mem2.rd_ack), + .rd_data(hwif_in.mem2.rd_data), + .wr_ack(hwif_in.mem2.wr_ack) + ); + +{%- endblock %} + + + +{% block seq %} + {% sv_line_anchor %} + ##1; + cb.rst <= '0; + ##1; + + //-------------------------------------------------------------------------- + // Simple read/write tests + //-------------------------------------------------------------------------- + // mem1 + repeat(32) begin + logic [31:0] x; + int unsigned addr; + x = $urandom(); + addr = 'h0; + addr += $urandom_range(('h10 / 4) - 1) * 4; + cpuif.write(addr, x); + cpuif.assert_read(addr, x); + end + + // mem2 + repeat(32) begin + logic [31:0] x; + int unsigned addr; + x = $urandom(); + addr = 'h200; + addr += $urandom_range(('h90 / 4) - 1) * 4; + cpuif.write(addr, x); + cpuif.assert_read(addr, x); + end + + //-------------------------------------------------------------------------- + // Pipelined access + //-------------------------------------------------------------------------- + // init array with unique known value + for(int i=0; i<('h10 / 4); i++) begin + cpuif.write('h0 + i*4, 'h1000 + i); + end + for(int i=0; i<('h90 / 4); i++) begin + cpuif.write('h200 + i*4, 'h3000 + i); + end + + // random pipelined read/writes + repeat(256) begin + fork + begin + int i; + logic [31:0] x; + int unsigned addr; + case($urandom_range(1)) + 0: begin + i = $urandom_range(('h10 / 4) - 1); + x = 'h1000 + i; + addr = 'h0 + i*4; + end + 1: begin + i = $urandom_range(('h90 / 4) - 1); + x = 'h3000 + i; + addr = 'h200 + i*4; + end + endcase + + case($urandom_range(1)) + 0: cpuif.write(addr, x); + 1: cpuif.assert_read(addr, x); + endcase + end + join_none + end + wait fork; + +{% endblock %} diff --git a/tests/test_only_external_blocks/testcase.py b/tests/test_only_external_blocks/testcase.py new file mode 100644 index 0000000..2486293 --- /dev/null +++ b/tests/test_only_external_blocks/testcase.py @@ -0,0 +1,29 @@ +from parameterized import parameterized_class + +from ..lib.cpuifs.apb4 import APB4 +from ..lib.cpuifs.axi4lite import AXI4Lite +from ..lib.cpuifs.passthrough import Passthrough +from ..lib.sim_testcase import SimTestCase +from ..lib.test_params import get_permutation_class_name, get_permutations + + +@parameterized_class(get_permutations({ + "cpuif": [ + APB4(), + Passthrough(), + ], + "retime_read_fanin": [True, False], + "retime_read_response": [True, False], + "retime_external": [True, False], +}), class_name_func=get_permutation_class_name) +class Test(SimTestCase): + extra_tb_files = [ + "../lib/external_reg.sv", + "../lib/external_block.sv", + ] + init_hwif_in = False + clocking_hwif_in = False + timeout_clk_cycles = 30000 + + def test_dut(self): + self.run_test()