URL
https://opencores.org/ocsvn/spacewire_light/spacewire_light/trunk
Subversion Repositories spacewire_light
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 2 to Rev 3
- ↔ Reverse comparison
Rev 2 → Rev 3
/spacewire_light/trunk/bench/vhdl/streamtest_tb.vhd
28,6 → 28,7
component streamtest is |
generic ( |
sysfreq: real; |
txclkfreq: real; |
tickdiv: integer range 12 to 24 := 20; |
rximpl: spw_implementation_type := impl_generic; |
rxchunk: integer range 1 to 4 := 1; |
84,6 → 85,7
streamtest_inst: streamtest |
generic map ( |
sysfreq => sys_clock_freq, |
txclkfreq => sys_clock_freq, |
tickdiv => 16, |
rximpl => impl_generic, |
rxchunk => 1, |
/spacewire_light/trunk/rtl/vhdl/spwstream.vhd
11,7 → 11,7
-- |
-- The SpaceWire standard requires that each transceiver use an initial |
-- signalling rate of 10 Mbit/s. This implies that the system clock frequency |
-- must be a multiple of 10 MHz. See the datasheet for further details on |
-- must be a multiple of 10 MHz. See the manual for further details on |
-- bitrates and clocking. |
-- |
|
26,9 → 26,14
-- System clock frequency in Hz. |
-- This must be set to the frequency of "clk". It is used to setup |
-- counters for reset timing, disconnect timeout and to transmit |
-- at 10 Mbit/s during the handshake. |
-- at 10 Mbit/s during the link handshake. |
sysfreq: real; |
|
-- Transmit clock frequency in Hz (only if tximpl = impl_fast). |
-- This must be set to the frequency of "txclk". It is used to |
-- transmit at 10 Mbit/s during the link handshake. |
txclkfreq: real := 0.0; |
|
-- Selection of a receiver front-end implementation. |
rximpl: spw_implementation_type := impl_generic; |
|
67,12 → 72,13
-- Without autostart or linkstart, the link remains in state Ready. |
linkstart: in std_logic; |
|
-- Do not start link (overrides linkstart and autostart) and/or disconnect |
-- if the link is in state Run. |
-- Do not start link (overrides linkstart and autostart) and/or |
-- disconnect a running link. |
linkdis: in std_logic; |
|
-- Scaling factor minus 1, used to scale the system clock into the transmission |
-- signalling rate. The system clock is divided by (unsigned(divcnt) + 1). |
-- Scaling factor minus 1, used to scale the transmit base clock into |
-- the transmission bit rate. The system clock (for impl_generic) or |
-- the txclk (for impl_fast) is divided by (unsigned(txdivcnt) + 1). |
-- Changing this signal will immediately change the transmission rate. |
-- During link setup, the transmission rate is always 10 Mbit/s. |
txdivcnt: in std_logic_vector(7 downto 0); |
193,8 → 199,12
constant disconnect_time: integer := integer(sysfreq * 850.0e-9); |
|
-- Initial tx clock scaler (10 Mbit). |
type impl_to_real_type is array(spw_implementation_type) of real; |
constant tximpl_to_txclk_freq: impl_to_real_type := |
(impl_generic => sysfreq, impl_fast => txclkfreq); |
constant effective_txclk_freq: real := tximpl_to_txclk_freq(tximpl); |
constant default_divcnt: std_logic_vector(7 downto 0) := |
std_logic_vector(to_unsigned(integer(sysfreq / 10.0e6 - 1.0), 8)); |
std_logic_vector(to_unsigned(integer(effective_txclk_freq / 10.0e6 - 1.0), 8)); |
|
-- Registers. |
type regs_type is record |
/spacewire_light/trunk/rtl/vhdl/spwxmit_fast.vhd
122,7 → 122,7
-- no problem there. |
-- |
-- This is different when the data stream includes 4-bit tokens. |
-- See the datasheet for an analysis of that case. |
-- See the manual for further comments. |
-- |
-- Implementation guidelines |
-- ------------------------- |
200,6 → 200,7
type token_type is record |
tick: std_ulogic; -- send time code |
fct: std_ulogic; -- send FCT |
fctpiggy: std_ulogic; -- send FCT and N-char |
flag: std_ulogic; -- send EOP or EEP |
char: std_logic_vector(7 downto 0); -- character or time code |
end record; |
220,6 → 221,7
b_token: token_type; |
-- stage C |
c_update: std_ulogic; |
c_busy: std_ulogic; |
c_esc: std_ulogic; |
c_fct: std_ulogic; |
c_bits: std_logic_vector(8 downto 0); |
277,6 → 279,12
end record; |
|
-- Initial state of system clock domain |
constant token_reset: token_type := ( |
tick => '0', |
fct => '0', |
fctpiggy => '0', |
flag => '0', |
char => (others => '0') ); |
constant regs_reset: regs_type := ( |
txenreg => '0', |
txdivreg => (others => '0'), |
285,8 → 293,8
txdivsafe => '0', |
sysflip0 => '0', |
sysflip1 => '0', |
token0 => ( tick => '0', fct => '0', flag => '0', char => (others => '0') ), |
token1 => ( tick => '0', fct => '0', flag => '0', char => (others => '0') ), |
token0 => token_reset, |
token1 => token_reset, |
tokmux => '0', |
txflip0 => "00", |
txflip1 => "00", |
336,7 → 344,7
vtx := rtx; |
v_needtoken := '0'; |
v_havetoken := '0'; |
v_token := ( tick => '0', fct => '0', flag => '0', char => (others => '0') ); |
v_token := token_reset; |
|
-- ---- FAST CLOCK DOMAIN ---- |
|
349,9 → 357,9
-- Stage B: Multiplex tokens from system clock domain. |
-- Update stage B three bit periods after updating stage C |
-- (i.e. in time for the next update of stage C). |
-- Do not update stage B if the last token from stage C was ESC; |
-- stage C already knows what token to put after the ESC. |
vtx.b_update := rtx.txclken and rtx.e_count(0) and (not rtx.c_esc); |
-- Do not update stage B if stage C is indicating that it needs to |
-- send a second token to complete its task. |
vtx.b_update := rtx.txclken and rtx.e_count(0) and (not rtx.c_busy); |
if rtx.b_mux = '0' then |
vtx.b_txflip := rtx.txflip0; |
else |
380,11 → 388,26
-- Stage C: Prepare to transmit EOP, EEP or a data character. |
vtx.c_update := rtx.txclken and rtx.e_count(3); |
if rtx.c_update = '1' then |
-- NULL is broken into two tokens: ESC + FCT |
-- time codes are broken into two tokens: ESC + char |
|
-- NULL is broken into two tokens: ESC + FCT. |
-- Time-codes are broken into two tokens: ESC + char. |
|
-- Enable c_esc on the first pass of a NULL or a time-code. |
vtx.c_esc := (rtx.b_token.tick or (not rtx.b_valid)) and |
(not rtx.c_esc); |
vtx.c_fct := rtx.b_token.fct or (not rtx.b_valid); |
|
-- Enable c_fct on the first pass of an FCT and on |
-- the second pass of a NULL (also the first pass, but c_esc |
-- is stronger than c_fct). |
vtx.c_fct := (rtx.b_token.fct and (not rtx.c_busy)) or |
(not rtx.b_valid); |
|
-- Enable c_busy on the first pass of a NULL or a time-code |
-- or a piggy-backed FCT. This will tell stage B that we are |
-- not done yet. |
vtx.c_busy := (rtx.b_token.tick or (not rtx.b_valid) or |
rtx.b_token.fctpiggy) and (not rtx.c_busy); |
|
if rtx.b_token.flag = '1' then |
if rtx.b_token.char(0) = '0' then |
-- prepare to send EOP |
493,6 → 516,7
vtx.b_mux := '0'; |
vtx.b_valid := '0'; |
vtx.c_update := '0'; |
vtx.c_busy := '1'; |
vtx.c_esc := '1'; -- need to send 2nd part of NULL |
vtx.c_fct := '1'; |
vtx.d_bits := "000000111"; -- ESC = P111 |
584,6 → 608,7
-- prepare to send time code |
v_token.tick := '1'; |
v_token.fct := '0'; |
v_token.fctpiggy := '0'; |
v_token.flag := '0'; |
v_token.char := r.pend_time; |
v_havetoken := '1'; |
590,25 → 615,27
if v_needtoken = '1' then |
v.pend_tick := '0'; |
end if; |
elsif r.allow_fct = '1' and (xmiti.fct_in = '1' or r.pend_fct = '1') then |
-- prepare to send FCT |
v_token.tick := '0'; |
v_token.fct := '1'; |
v_token.flag := '0'; |
v_havetoken := '1'; |
if v_needtoken = '1' then |
v.pend_fct := '0'; |
v.sent_fct := '1'; |
else |
if r.allow_fct = '1' and (xmiti.fct_in = '1' or r.pend_fct = '1') then |
-- prepare to send FCT |
v_token.fct := '1'; |
v_havetoken := '1'; |
if v_needtoken = '1' then |
v.pend_fct := '0'; |
v.sent_fct := '1'; |
end if; |
end if; |
elsif r.allow_char = '1' and r.pend_char = '1' then |
-- prepare to send N-Char |
v_token.tick := '0'; |
v_token.fct := '0'; |
v_token.flag := r.pend_data(8); |
v_token.char := r.pend_data(7 downto 0); |
v_havetoken := '1'; |
if v_needtoken = '1' then |
v.pend_char := '0'; |
if r.allow_char = '1' and r.pend_char = '1' then |
-- prepare to send N-Char |
-- Note: it is possible to send an FCT and an N-Char |
-- together by enabling the fctpiggy flag. |
v_token.fctpiggy := v_token.fct; |
v_token.flag := r.pend_data(8); |
v_token.char := r.pend_data(7 downto 0); |
v_havetoken := '1'; |
if v_needtoken = '1' then |
v.pend_char := '0'; |
end if; |
end if; |
end if; |
|
/spacewire_light/trunk/rtl/vhdl/spwpkg.vhd
232,6 → 232,7
component spwstream is |
generic ( |
sysfreq: real; -- clk freq in Hz |
txclkfreq: real := 0.0; -- txclk freq in Hz |
rximpl: spw_implementation_type := impl_generic; |
rxchunk: integer range 1 to 4 := 1; -- max bits per clk |
tximpl: spw_implementation_type := impl_generic; |
/spacewire_light/trunk/rtl/vhdl/streamtest.vhd
31,6 → 31,9
-- System clock frequency in Hz. |
sysfreq: real; |
|
-- txclk frequency in Hz (if tximpl = impl_fast). |
txclkfreq: real; |
|
-- 2-log of division factor from system clock freq to timecode freq. |
tickdiv: integer range 12 to 24 := 20; |
|
209,6 → 212,7
spwstream_inst: spwstream |
generic map ( |
sysfreq => sysfreq, |
txclkfreq => txclkfreq, |
rximpl => rximpl, |
rxchunk => rxchunk, |
tximpl => tximpl, |
/spacewire_light/trunk/doc/timing_diagram.py
0,0 → 1,224
#!/usr/bin/env python |
# timing_diagram.py, Joris van Rantwijk, Jul 2010. |
|
""" |
Generate timing diagrams for SpaceWire Light manual. |
""" |
|
from pyx import * |
|
riseWidth = 0.15 |
clockWidth = 1.0 |
lowLevel = 0 |
highLevel = 0.5 |
midLevel = 0.25 |
|
def drawGrid(x, y1, y2, tstart, nclk): |
|
for i in xrange(nclk): |
x0 = x + clockWidth * (tstart + i) |
c.stroke(path.line(x0, y1, x0, y2), [ style.linewidth.Thin, color.gray(0.5) ]) |
|
def drawSignal(x, y, events): |
|
for i in xrange(len(events)-1): |
(t, v) = events[i] |
(tnext, vnext) = events[i+1] |
|
firstevt = (i == 0) |
lastevt = (i == len(events) - 2) |
|
x0 = x + clockWidth * t |
x1 = x + clockWidth * t + 0.5 * riseWidth |
x2 = x + clockWidth * tnext - 0.5 * riseWidth |
x3 = x + clockWidth * tnext |
|
# fill |
if v.lower() == 'x': |
p = path.path(path.moveto(x1, y + lowLevel)) |
if not firstevt: |
p.append(path.lineto(x0, y + midLevel)) |
p.append(path.lineto(x1, y + highLevel)) |
p.append(path.lineto(x2, y + highLevel)) |
if not lastevt: |
p.append(path.lineto(x3, y + midLevel)) |
p.append(path.lineto(x2, y + lowLevel)) |
p.append(path.lineto(x1, y + lowLevel)) |
c.fill(p, [ color.gray(0.5) ]) |
|
lineStyle = [ ] |
if v.lower() != 'x': |
lineStyle.append(style.linewidth.Thick) |
|
# draw low part of signal |
if v.lower() in '0vx': |
p = path.path() |
if firstevt: |
p.append(path.moveto(x1, y + lowLevel)) |
else: |
p.append(path.moveto(x0, y + midLevel)) |
p.append(path.lineto(x1, y + lowLevel)) |
p.append(path.lineto(x2, y + lowLevel)) |
if not lastevt: |
p.append(path.lineto(x3, y + midLevel)) |
c.stroke(p, lineStyle) |
|
# draw high part of signal |
if v.lower() in '1vx': |
p = path.path() |
if firstevt: |
p.append(path.moveto(x1, y + highLevel)) |
else: |
p.append(path.moveto(x0, y + midLevel)) |
p.append(path.lineto(x1, y + highLevel)) |
p.append(path.lineto(x2, y + highLevel)) |
if not lastevt: |
p.append(path.lineto(x3, y + midLevel)) |
c.stroke(p, lineStyle) |
|
# draw center part of signal |
if v.lower() == 'z': |
p = path.path() |
if firstevt: |
p.append(path.moveto(x1, y + midLevel)) |
else: |
p.append(path.moveto(x0, y + midLevel)) |
if lastevt: |
p.append(path.lineto(x2, y + midLevel)) |
else: |
p.append(path.lineto(x3, y + midLevel)) |
c.stroke(p, lineStyle) |
|
|
th = 0.3 # an appearance of "hold time" in diagram |
xstart = 1.2 |
|
text.set(mode='latex') |
|
#### Read timing |
|
c = canvas.canvas() |
|
drawGrid(xstart, 0.9, 5.5, 1, 9) |
|
c.text(0, 5, '\\textsf{\\textbf{CLK}}') |
drawSignal(xstart, 5, |
[ (0.5+i/2.0, str(i%2)) for i in range(20) ]) |
|
c.text(0, 4, '\\textsf{\\textbf{RXVALID}}') |
drawSignal(xstart, 4, |
[ (0.5, '0'), (2+th, '1'), (7+th, '0'), (10, '') ]) |
|
c.text(0, 3, '\\textsf{\\textbf{RXFLAG}}') |
drawSignal(xstart, 3, |
[ (0.5, 'x'), (2+th, 'v'), (4+th, 'v'), (6+th, 'v'), (7+th, 'x'), (10, '') ]) |
|
c.text(0, 2, '\\textsf{\\textbf{RXDATA}}') |
drawSignal(xstart, 2, |
[ (0.5, 'x'), (2+th, 'v'), (4+th, 'v'), (6+th, 'v'), (7+th, 'x'), (10, '') ]) |
|
c.text(0, 1, '\\textsf{\\textbf{RXREAD}}') |
drawSignal(xstart, 1, |
[ (0.5, '0'), (3+th, '1'), (4+th, '0'), (5+th, '1'), (8+th, '0'), (10, '') ]) |
|
c.stroke(path.line(xstart+4*clockWidth, 0.4, xstart+4*clockWidth, 0.8), [ deco.arrow() ]) |
c.stroke(path.line(xstart+6*clockWidth, 0.4, xstart+6*clockWidth, 0.8), [ deco.arrow() ]) |
c.stroke(path.line(xstart+7*clockWidth, 0.4, xstart+7*clockWidth, 0.8), [ deco.arrow() ]) |
|
c.writeEPSfile('timing_read.eps') |
|
#### Write timing |
|
c = canvas.canvas() |
|
drawGrid(xstart, 0.9, 5.5, 1, 9) |
|
c.text(0, 5, '\\textsf{\\textbf{CLK}}') |
drawSignal(xstart, 5, |
[ (0.5+i/2.0, str(i%2)) for i in range(20) ]) |
|
c.text(0, 4, '\\textsf{\\textbf{TXRDY}}') |
drawSignal(xstart, 4, |
[ (0.5, '1'), (5+th, '0'), (6+th, '1'), (9+th, '0'), (10, '') ]) |
|
c.text(0, 3, '\\textsf{\\textbf{TXWRITE}}') |
drawSignal(xstart, 3, |
[ (0.5, '0'), (2+th, '1'), (3+th, '0'), (4+th, '1'), (8+th, '0'), (10, '') ]) |
|
c.text(0, 2, '\\textsf{\\textbf{TXFLAG}}') |
drawSignal(xstart, 2, |
[ (0.5, 'x'), (2+th, 'v'), (3+th, 'x'), (4+th, 'v'), (5+th, 'v'), |
(7+th, 'v'), (8+th, 'x'), (10, '') ]) |
|
c.text(0, 1, '\\textsf{\\textbf{TXDATA}}') |
drawSignal(xstart, 1, |
[ (0.5, 'x'), (2+th, 'v'), (3+th, 'x'), (4+th, 'v'), (5+th, 'v'), |
(7+th, 'v'), (8+th, 'x'), (10, '') ]) |
|
c.stroke(path.line(xstart+3*clockWidth, 0.4, xstart+3*clockWidth, 0.8), [ deco.arrow() ]) |
c.stroke(path.line(xstart+5*clockWidth, 0.4, xstart+5*clockWidth, 0.8), [ deco.arrow() ]) |
c.stroke(path.line(xstart+7*clockWidth, 0.4, xstart+7*clockWidth, 0.8), [ deco.arrow() ]) |
c.stroke(path.line(xstart+8*clockWidth, 0.4, xstart+8*clockWidth, 0.8), [ deco.arrow() ]) |
|
c.writeEPSfile('timing_write.eps') |
|
#### Time codes |
|
c = canvas.canvas() |
|
xstart = 1.4 |
|
drawGrid(xstart, 0, 6.5, 1, 9) |
|
c.text(0, 6, '\\textsf{\\textbf{CLK}}') |
drawSignal(xstart, 6, |
[ (0.5+i/2.0, str(i%2)) for i in range(20) ]) |
|
c.text(0, 5, '\\textsf{\\textbf{TICK\_OUT}}') |
drawSignal(xstart, 5, |
[ (0.5, '0'), (2+th, '1'), (3+th, '0'), (5+th, '1'), (6+th, '0'), (10, '') ]) |
|
c.text(0, 4, '\\textsf{\\textbf{CTRL\_OUT}}') |
drawSignal(xstart, 4, [ (0.5, 'x'), (2+th, 'v'), (5+th, 'v'), (10, '') ]) |
|
c.text(0, 3, '\\textsf{\\textbf{TIME\_OUT}}') |
drawSignal(xstart, 3, [ (0.5, 'x'), (2+th, 'v'), (5+th, 'v'), (10, '') ]) |
|
c.text(0, 2, '\\textsf{\\textbf{TICK\_IN}}') |
drawSignal(xstart, 2, [ (0.5, '0'), (7+th, '1'), (8+th, '0'), (10, '') ]) |
|
c.text(0, 1, '\\textsf{\\textbf{CTRL\_IN}}') |
drawSignal(xstart, 1, [ (0.5, 'x'), (7+th, 'v'), (8+th, 'x'), (10, '') ]) |
|
c.text(0, 0, '\\textsf{\\textbf{TIME\_IN}}') |
drawSignal(xstart, 0, [ (0.5, 'x'), (7+th, 'v'), (8+th, 'x'), (10, '') ]) |
|
c.writeEPSfile('timing_timecode.eps') |
|
#### Link status |
|
c = canvas.canvas() |
|
clockWidth = 0.8 |
xstart = 1.6 |
|
c.text(0, 5, '\\textsf{\\textbf{LINKSTART}}') |
drawSignal(xstart, 5, [ (1, '0'), (2, '1'), (10, '0'), (19, '') ]) |
|
c.text(0, 4, '\\textsf{\\textbf{STARTED}}') |
drawSignal(xstart, 4, [ (1, '0'), (4, '1'), (6, '0'), (19, '') ]) |
|
c.text(0, 3, '\\textsf{\\textbf{CONNECTING}}') |
drawSignal(xstart, 3, [ (1, '0'), (6, '1'), (8, '0'), (19, '') ]) |
|
c.text(0, 2, '\\textsf{\\textbf{RUNNING}}') |
drawSignal(xstart, 2, [ (1, '0'), (8, '1'), (16, '0'), (19, '') ]) |
|
c.text(0, 1, '\\textsf{\\textbf{ERRPAR}}') |
drawSignal(xstart, 1, [ (1, '0'), (15.5, '1'), (16.5, '0'), (19, '') ]) |
|
c.stroke(path.line(xstart+6*clockWidth, 4.8, xstart+6*clockWidth, 2.6), [ style.linewidth.Thin ]) |
c.stroke(path.line(xstart+8*clockWidth, 3.8, xstart+8*clockWidth, 1.6), [ style.linewidth.Thin ]) |
|
c.writeEPSfile('timing_link.eps') |
|
/spacewire_light/trunk/doc/Manual.odt
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
spacewire_light/trunk/doc/Manual.odt
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: spacewire_light/trunk/doc/Manual.pdf
===================================================================
--- spacewire_light/trunk/doc/Manual.pdf (nonexistent)
+++ spacewire_light/trunk/doc/Manual.pdf (revision 3)
@@ -0,0 +1,2964 @@
+%PDF-1.4
+%äüöß
+2 0 obj
+<>
+stream
+xœí\K㸾÷¯Ðy{Y¤DQ€a »mÉm’rä”ì2 v.û÷S¾$’’==ÝÀ@è¶lóQ¬úêIÊjÝïO¿uªS{Ý
+Ó°:×ÃÞu_éþúS÷ù¯¯ÿ|zy{ÒFïm7ý~ìÞþÑý|\÷öë烥•Qýq5ð«F~uÙg“zæWùæE½ªÓñooz:¿=}ZÎųŒz@jx.ÝŽs±;OghhͳáL±&S‰ÉA"žñzÅ×éøö¯:%€«¶“C-(91Ia"„‡ž‰@¤H]x¥ò6ˆDƒ>îìL‹lÓ—+&ܵH³Ÿ:ëÆÐÄ^>jNñÒ
+.ZãÒµ:©³º(ØLi ¶#ßéå<ûAÁdýl`šÍö{3Ÿ
+Îà ‡,^#Þ9q‚Q
+xwà»gü)Â{&ìñ‚ßõHÇB!¶†W¤äÛšÙªéAüe4üýË“BÌü>#õÏxRÝðë/¶½Üþ»ûKÁ»Á">DŽØV"åóq×Ü.G”–òâÛˆ&(–#¿3,_è¹ýéÈíÌ!{CKÖ2»±A³¢¨_°{]Ø#Ò]>Ó,Z´„È2DÅøª‰h’GÀU‡ì\ï½Ð¨ÃM/-¬Òò*XPt¡„E‡i]E„‚%̳AG,G*´*D7øw¨åü!8^ê¶ÝÌAü÷…‰?8‹²à-<{
+v[HµÕ¸JÞÝåüÈ×ûQWÑ*êÐ%ÙyزiEë+Qt^ rpBk܈ê1˜©Žtw!|´ëvÃõ]_ÖñX«‰ÇºAé‹+>v¢€wÙ C‚£‘A˜, Ø6Ø´]ÚU†¼·?âõ‚Ô#k€ê'4+j;V†TÙ
+p–X휼ið†âUú/€kCÌLûm?`6¿îlÙ¾¢UÔyá~tØmÞá²î…Ë.ŸCàvÂB‡7‚GsŒAá×ãÖy›8ÎQkZ¥¦Þ€¶ ŒÙw_%æÞà¹÷õ8}7”kÈ\±·vD8@Þráe·kÐZAâ·<ÑÍ#N‰Ñ2ªäü¹œÚÄ£FoPøîrÿ×ýWBHÃ
+âúXiÍ·’NâŠnœN[Æ:bŠ9ZS‰F›o`ïZ3Ý]¼ëº ?% Vñƒvb¬à§
+~ŠnŸº?Bˆë ØÑ/Æ¡€3ÞR¾éäË‚Í ÐáBk„Ü[\½ßJ•°ÑÃ
+Ê4,÷«a6PVtãŒx8Ž³$Ø£ÆCÈAÈ0EZ§Ú÷i#ʾFëD]wÝ êu5[UÓ²¨·ÉV‹.©fŒ ñFÈŠkóè9³}cÚ~ƒÏ£êêÄwÏ#^íW06®ÒLn¹ó¡‡uP–]ئ1óâ‰Ó¡bܸ"¢§ö.-á®:öÝeü‘®ÇÂc
+^Ï«xtvYT¯x,º`$÷‚äõýzÔ*ê|›%¤æ·ˆ×)HaZÐëƒ8ï¦CßfDgp¹5‚î
+‹Ç¿¾7òJ m o\67p7¨;Å
+´6³Ô™¿ùC!“hî¨éê,÷ÔG¸Æ
+jªÐ¢óyí\ÃX³,Ù·ªÁe·üX#ÎÑ3§ƒ·Î²Œ˜þ6cD*Wç»»äézìò°@³ÄÚ8Xîl087
+Äe·Ùyï‚-—éÒîÙG§
+rh
+îx5¹©Ôʆ˜%Þº‰r
+Tž©~o\=Š×1VB1¶º³kÀÄóª=[,´ò˜‘BÌeŠ^#^Ô èîHïèxîêYU=õeUð…`
+§eùO§ã}¾¶,ùøì(¡)§`SC7Dœ>YwúrÔC©
+wW‹Ã°Ø|Úe…#8yUÐÇìxa¶+]+,‰V¸[WT¤q©úÀÍÓಓC6(^¶ùãd—àãq匑@+¯øÆÒ¶ràÚMö@$Z 'ƒäœÎ‚{Žs™É@fU´‹,n†š
+±W‚¦}–]PæL‘åúX1ðŠY!ñ¤é ž+žçÈ
+-ËWÙ Ô¶:òäv(K;gæ„`Q°b‹:ö‚¡bQ ¨'Á¨
+;ÍŒÁ«à-`¢Ü$\ãgtñ‹Ük!‘¬ƒ°î\Ôrs'>Ó¾¢2`š¾ÄÊïTŸºfÒÚ˜ßTŸt®Ä7Êò
+—ÜYĈmÁ Ÿèé‚[¨–Ñž¥‰±ô¯1Ÿ£ç–½iÙõÉ\O:U4o™ÿ‰žò¹~ôÉ`ZX.ÅËôÜ>y;Ü4
+(W™ç ¡[T{´gÐäU‹ö+üÈ =ŒÉóNíÊ{0}Uòdn½ÑÈ<2 f1Œ;ºL§Þ=v²üÉq?Pv0?zF¶FØ0Ï_\ækxSÅæÖÞá6~¹aà îÉd$[‡Ü@zפ3S·žg“ó+†¶R
+¶Eœ?ae†êUdùuðbm“0ÉJ´zÄ8¶Êº²÷º¨ayq<^0ˆÀÌ®‘îH÷e|MÈš;›efuîß㑧ŒäæÅ—x6éç‹.8{tV§ÜykßðÚl§lŽhÿãA,´‘\PÜfs΂öV